Plumb subject field and add to authz flow. (#27615)

* Plumb subject field and add to authz flow.

* formatting

* Test on empty principal

* resolving comments

* resolving comment

* update subject check in test
pull/27848/head^2
Ashitha Santhosh 3 years ago committed by GitHub
parent 33aef08081
commit 1290364374
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      include/grpc/grpc_security_constants.h
  2. 9
      src/core/lib/security/authorization/evaluate_args.cc
  3. 2
      src/core/lib/security/authorization/evaluate_args.h
  4. 3
      src/core/lib/security/authorization/matchers.cc
  5. 4
      src/core/lib/security/authorization/sdk_server_authz_filter.cc
  6. 9
      src/core/lib/security/security_connector/ssl_utils.cc
  7. 31
      src/core/tsi/ssl_transport_security.cc
  8. 1
      src/core/tsi/ssl_transport_security.h
  9. 43
      test/core/security/authorization_matchers_test.cc
  10. 17
      test/core/security/evaluate_args_test.cc
  11. 297
      test/core/security/security_connector_test.cc
  12. 114
      test/core/tsi/ssl_transport_security_test.cc

@ -28,6 +28,7 @@ extern "C" {
#define GRPC_TLS_TRANSPORT_SECURITY_TYPE "tls"
#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
#define GRPC_X509_SUBJECT_PROPERTY_NAME "x509_subject"
#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
#define GRPC_X509_PEM_CERT_PROPERTY_NAME "x509_pem_cert"
// Please note that internally, we just faithfully pass whatever value we got by

@ -71,6 +71,8 @@ EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context,
dns_sans = GetAuthPropertyArray(auth_context, GRPC_PEER_DNS_PROPERTY_NAME);
common_name =
GetAuthPropertyValue(auth_context, GRPC_X509_CN_PROPERTY_NAME);
subject =
GetAuthPropertyValue(auth_context, GRPC_X509_SUBJECT_PROPERTY_NAME);
}
if (endpoint != nullptr) {
local_address = ParseEndpointUri(grpc_endpoint_get_local_address(endpoint));
@ -195,4 +197,11 @@ absl::string_view EvaluateArgs::GetCommonName() const {
return channel_args_->common_name;
}
absl::string_view EvaluateArgs::GetSubject() const {
if (channel_args_ == nullptr) {
return "";
}
return channel_args_->subject;
}
} // namespace grpc_core

@ -48,6 +48,7 @@ class EvaluateArgs {
std::vector<absl::string_view> uri_sans;
std::vector<absl::string_view> dns_sans;
absl::string_view common_name;
absl::string_view subject;
Address local_address;
Address peer_address;
};
@ -79,6 +80,7 @@ class EvaluateArgs {
std::vector<absl::string_view> GetUriSans() const;
std::vector<absl::string_view> GetDnsSans() const;
absl::string_view GetCommonName() const;
absl::string_view GetSubject() const;
private:
grpc_metadata_batch* metadata_;

@ -200,8 +200,7 @@ bool AuthenticatedAuthorizationMatcher::Matches(
}
}
}
// TODO(ashithasantosh): Check Subject field from certificate.
return false;
return matcher_.Match(args.GetSubject());
}
bool ReqServerNameAuthorizationMatcher::Matches(const EvaluateArgs&) const {

@ -96,11 +96,13 @@ bool SdkServerAuthzFilter::CallData::IsAuthorized(SdkServerAuthzFilter* chand) {
gpr_log(
GPR_DEBUG,
"checking request: url_path=%s, transport_security_type=%s, "
"uri_sans=[%s], dns_sans=[%s], local_address=%s:%d, peer_address=%s:%d",
"uri_sans=[%s], dns_sans=[%s], subject=%s, local_address=%s:%d, "
"peer_address=%s:%d",
std::string(args.GetPath()).c_str(),
std::string(args.GetTransportSecurityType()).c_str(),
absl::StrJoin(args.GetUriSans(), ",").c_str(),
absl::StrJoin(args.GetDnsSans(), ",").c_str(),
std::string(args.GetSubject()).c_str(),
std::string(args.GetLocalAddressString()).c_str(), args.GetLocalPort(),
std::string(args.GetPeerAddressString()).c_str(), args.GetPeerPort());
}

@ -277,7 +277,11 @@ grpc_core::RefCountedPtr<grpc_auth_context> grpc_ssl_peer_to_auth_context(
for (i = 0; i < peer->property_count; i++) {
const tsi_peer_property* prop = &peer->properties[i];
if (prop->name == nullptr) continue;
if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
if (strcmp(prop->name, TSI_X509_SUBJECT_PEER_PROPERTY) == 0) {
grpc_auth_context_add_property(ctx.get(), GRPC_X509_SUBJECT_PROPERTY_NAME,
prop->value.data, prop->value.length);
} else if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) ==
0) {
/* If there is no subject alt name, have the CN as the identity. */
if (peer_identity_property_name == nullptr) {
peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME;
@ -373,6 +377,9 @@ tsi_peer grpc_shallow_peer_from_ssl_auth_context(
if (strcmp(prop->name, GRPC_X509_SAN_PROPERTY_NAME) == 0) {
add_shallow_auth_property_to_peer(
&peer, prop, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY);
} else if (strcmp(prop->name, GRPC_X509_SUBJECT_PROPERTY_NAME) == 0) {
add_shallow_auth_property_to_peer(&peer, prop,
TSI_X509_SUBJECT_PEER_PROPERTY);
} else if (strcmp(prop->name, GRPC_X509_CN_PROPERTY_NAME) == 0) {
add_shallow_auth_property_to_peer(
&peer, prop, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);

@ -323,6 +323,30 @@ static tsi_result peer_property_from_x509_common_name(
return result;
}
/* Gets the subject of an X509 cert as a tsi_peer_property. */
static tsi_result peer_property_from_x509_subject(X509* cert,
tsi_peer_property* property) {
X509_NAME* subject_name = X509_get_subject_name(cert);
if (subject_name == nullptr) {
gpr_log(GPR_INFO, "Could not get subject name from certificate.");
return TSI_NOT_FOUND;
}
BIO* bio = BIO_new(BIO_s_mem());
X509_NAME_print_ex(bio, subject_name, 0, XN_FLAG_RFC2253);
char* contents;
long len = BIO_get_mem_data(bio, &contents);
if (len < 0) {
gpr_log(GPR_ERROR, "Could not get subject entry from certificate.");
BIO_free(bio);
return TSI_INTERNAL_ERROR;
}
tsi_result result = tsi_construct_string_peer_property(
TSI_X509_SUBJECT_PEER_PROPERTY, contents, static_cast<size_t>(len),
property);
BIO_free(bio);
return result;
}
/* Gets the X509 cert in PEM format as a tsi_peer_property. */
static tsi_result add_pem_certificate(X509* cert, tsi_peer_property* property) {
BIO* bio = BIO_new(BIO_s_mem());
@ -439,7 +463,7 @@ static tsi_result peer_from_x509(X509* cert, int include_certificate_type,
tsi_result result;
GPR_ASSERT(subject_alt_name_count >= 0);
property_count = (include_certificate_type ? static_cast<size_t>(1) : 0) +
2 /* common name, certificate */ +
3 /* subject, common name, certificate */ +
static_cast<size_t>(subject_alt_name_count);
for (int i = 0; i < subject_alt_name_count; i++) {
GENERAL_NAME* subject_alt_name =
@ -465,6 +489,11 @@ static tsi_result peer_from_x509(X509* cert, int include_certificate_type,
&peer->properties[current_insert_index++]);
if (result != TSI_OK) break;
}
result = peer_property_from_x509_subject(
cert, &peer->properties[current_insert_index++]);
if (result != TSI_OK) break;
result = peer_property_from_x509_common_name(
cert, &peer->properties[current_insert_index++]);
if (result != TSI_OK) break;

@ -35,6 +35,7 @@ extern "C" {
#define TSI_X509_CERTIFICATE_TYPE "X509"
/* This property is of type TSI_PEER_PROPERTY_STRING. */
#define TSI_X509_SUBJECT_PEER_PROPERTY "x509_subject"
#define TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY "x509_subject_common_name"
#define TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY \
"x509_subject_alternative_name"

@ -404,6 +404,49 @@ TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherFailedDnsSanMatches) {
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest,
AuthenticatedMatcherSuccessfulSubjectMatches) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_TLS_TRANSPORT_SECURITY_TYPE);
args_.AddPropertyToAuthContext(GRPC_X509_SUBJECT_PROPERTY_NAME,
"CN=abc,OU=Google");
EvaluateArgs args = args_.MakeEvaluateArgs();
// No match found in URI SANs and DNS SANs, finds match in Subject.
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"CN=abc,OU=Google",
/*case_sensitive=*/false)
.value());
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherFailedSubjectMatches) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE);
args_.AddPropertyToAuthContext(GRPC_X509_SUBJECT_PROPERTY_NAME,
"CN=abc,OU=Google");
EvaluateArgs args = args_.MakeEvaluateArgs();
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"CN=def,OU=Google",
/*case_sensitive=*/false)
.value());
EXPECT_FALSE(matcher.Matches(args));
}
TEST_F(
AuthorizationMatchersTest,
AuthenticatedMatcherWithoutClientCertMatchesSuccessfullyOnEmptyPrincipal) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_TLS_TRANSPORT_SECURITY_TYPE);
EvaluateArgs args = args_.MakeEvaluateArgs();
AuthenticatedAuthorizationMatcher matcher(
StringMatcher::Create(StringMatcher::Type::kExact,
/*matcher=*/"")
.value());
EXPECT_TRUE(matcher.Matches(args));
}
TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherFailedNothingMatches) {
args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE);

@ -92,6 +92,7 @@ TEST_F(EvaluateArgsTest, EmptyAuthContext) {
EXPECT_TRUE(args.GetSpiffeId().empty());
EXPECT_TRUE(args.GetUriSans().empty());
EXPECT_TRUE(args.GetDnsSans().empty());
EXPECT_TRUE(args.GetSubject().empty());
EXPECT_TRUE(args.GetCommonName().empty());
}
@ -151,6 +152,22 @@ TEST_F(EvaluateArgsTest, GetCommonNameFailDuplicateProperty) {
EXPECT_TRUE(args.GetCommonName().empty());
}
TEST_F(EvaluateArgsTest, GetSubjectSuccessOneProperty) {
util_.AddPropertyToAuthContext(GRPC_X509_SUBJECT_PROPERTY_NAME,
"CN=abc,OU=Google");
EvaluateArgs args = util_.MakeEvaluateArgs();
EXPECT_EQ(args.GetSubject(), "CN=abc,OU=Google");
}
TEST_F(EvaluateArgsTest, GetSubjectFailDuplicateProperty) {
util_.AddPropertyToAuthContext(GRPC_X509_SUBJECT_PROPERTY_NAME,
"CN=abc,OU=Google");
util_.AddPropertyToAuthContext(GRPC_X509_SUBJECT_PROPERTY_NAME,
"CN=def,OU=Google");
EvaluateArgs args = util_.MakeEvaluateArgs();
EXPECT_TRUE(args.GetSubject().empty());
}
} // namespace grpc_core
int main(int argc, char** argv) {

@ -40,20 +40,6 @@
#define TSI_OPENSSL_ALPN_SUPPORT 1
#endif
static int check_transport_security_type(const grpc_auth_context* ctx) {
grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME);
const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
if (prop == nullptr) return 0;
if (strncmp(prop->value, GRPC_SSL_TRANSPORT_SECURITY_TYPE,
prop->value_length) != 0) {
return 0;
}
/* Check that we have only one property with this name. */
if (grpc_auth_property_iterator_next(&it) != nullptr) return 0;
return 1;
}
static int check_peer_property(const tsi_peer* peer,
const tsi_peer_property* expected) {
size_t i;
@ -106,124 +92,30 @@ static void test_check_security_level() {
GRPC_SECURITY_NONE) == true);
}
static void test_unauthenticated_ssl_peer(void) {
tsi_peer peer;
tsi_peer rpeer;
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_SECURITY_LEVEL_PEER_PROPERTY,
tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx.get()));
GPR_ASSERT(check_transport_security_type(ctx.get()));
rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
grpc_shallow_peer_destruct(&rpeer);
tsi_peer_destruct(&peer);
ctx.reset(DEBUG_LOCATION, "test");
}
static int check_identity(const grpc_auth_context* ctx,
static int check_property(const grpc_auth_context* ctx,
const char* expected_property_name,
const char** expected_identities,
size_t num_identities) {
grpc_auth_property_iterator it;
const grpc_auth_property* prop;
size_t i;
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
it = grpc_auth_context_peer_identity(ctx);
for (i = 0; i < num_identities; i++) {
prop = grpc_auth_property_iterator_next(&it);
if (prop == nullptr) {
gpr_log(GPR_ERROR, "Expected identity value %s not found.",
expected_identities[i]);
return 0;
}
if (strcmp(prop->name, expected_property_name) != 0) {
gpr_log(GPR_ERROR, "Expected peer identity property name %s and got %s.",
expected_property_name, prop->name);
return 0;
}
if (strncmp(prop->value, expected_identities[i], prop->value_length) != 0) {
gpr_log(GPR_ERROR, "Expected peer identity %s and got %s.",
expected_identities[i], prop->value);
return 0;
}
}
return 1;
}
static int check_x509_cn(const grpc_auth_context* ctx,
const char* expected_cn) {
grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
ctx, GRPC_X509_CN_PROPERTY_NAME);
const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
if (prop == nullptr) {
gpr_log(GPR_ERROR, "CN property not found.");
return 0;
}
if (strncmp(prop->value, expected_cn, prop->value_length) != 0) {
gpr_log(GPR_ERROR, "Expected CN %s and got %s", expected_cn, prop->value);
return 0;
}
if (grpc_auth_property_iterator_next(&it) != nullptr) {
gpr_log(GPR_ERROR, "Expected only one property for CN.");
return 0;
}
return 1;
}
static int check_x509_pem_cert(const grpc_auth_context* ctx,
const char* expected_pem_cert) {
grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME);
const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
if (prop == nullptr) {
gpr_log(GPR_ERROR, "Pem certificate property not found.");
return 0;
}
if (strncmp(prop->value, expected_pem_cert, prop->value_length) != 0) {
gpr_log(GPR_ERROR, "Expected pem cert %s and got %s", expected_pem_cert,
prop->value);
return 0;
}
if (grpc_auth_property_iterator_next(&it) != nullptr) {
gpr_log(GPR_ERROR, "Expected only one property for pem cert.");
return 0;
}
return 1;
}
static int check_x509_pem_cert_chain(const grpc_auth_context* ctx,
const char* expected_pem_cert_chain) {
grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
ctx, GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME);
const char* expected_property_value) {
grpc_auth_property_iterator it =
grpc_auth_context_find_properties_by_name(ctx, expected_property_name);
const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
if (prop == nullptr) {
gpr_log(GPR_ERROR, "Pem certificate chain property not found.");
gpr_log(GPR_ERROR, "Expected value %s not found.", expected_property_value);
return 0;
}
if (strncmp(prop->value, expected_pem_cert_chain, prop->value_length) != 0) {
gpr_log(GPR_ERROR, "Expected pem cert chain %s and got %s",
expected_pem_cert_chain, prop->value);
if (strncmp(prop->value, expected_property_value, prop->value_length) != 0) {
gpr_log(GPR_ERROR, "Expected value %s and got %s for property %s.",
expected_property_value, prop->value, expected_property_name);
return 0;
}
if (grpc_auth_property_iterator_next(&it) != nullptr) {
gpr_log(GPR_ERROR, "Expected only one property for pem cert chain.");
gpr_log(GPR_ERROR, "Expected only one property for %s.",
expected_property_name);
return 0;
}
return 1;
}
static int check_sans(
static int check_properties(
const grpc_auth_context* ctx, const char* expected_property_name,
const std::vector<std::string>& expected_property_values) {
grpc_auth_property_iterator it =
@ -235,9 +127,14 @@ static int check_sans(
property_value.c_str());
return 0;
}
if (strcmp(prop->name, expected_property_name) != 0) {
gpr_log(GPR_ERROR, "Expected peer property name %s and got %s.",
expected_property_name, prop->name);
return 0;
}
if (strncmp(prop->value, property_value.c_str(), prop->value_length) != 0) {
gpr_log(GPR_ERROR, "Expected peer %s and got %s.", property_value.c_str(),
prop->value);
gpr_log(GPR_ERROR, "Expected peer property value %s and got %s.",
property_value.c_str(), prop->value);
return 0;
}
}
@ -278,6 +175,33 @@ static int check_spiffe_id(const grpc_auth_context* ctx,
return 1;
}
static void test_unauthenticated_ssl_peer(void) {
tsi_peer peer;
tsi_peer rpeer;
GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_SECURITY_LEVEL_PEER_PROPERTY,
tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
&peer.properties[1]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx.get()));
GPR_ASSERT(check_property(ctx.get(),
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE));
rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
grpc_shallow_peer_destruct(&rpeer);
tsi_peer_destruct(&peer);
ctx.reset(DEBUG_LOCATION, "test");
}
static void test_cn_only_ssl_peer_to_auth_context(void) {
tsi_peer peer;
tsi_peer rpeer;
@ -306,11 +230,16 @@ static void test_cn_only_ssl_peer_to_auth_context(void) {
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
GPR_ASSERT(
check_identity(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1));
GPR_ASSERT(check_transport_security_type(ctx.get()));
GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
GPR_ASSERT(check_x509_pem_cert_chain(ctx.get(), expected_pem_cert_chain));
check_property(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, expected_cn));
GPR_ASSERT(check_property(ctx.get(),
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE));
GPR_ASSERT(
check_property(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, expected_cn));
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_PEM_CERT_PROPERTY_NAME,
expected_pem_cert));
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME,
expected_pem_cert_chain));
rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
@ -324,7 +253,7 @@ static void test_cn_and_one_san_ssl_peer_to_auth_context(void) {
tsi_peer peer;
tsi_peer rpeer;
const char* expected_cn = "cn1";
const char* expected_san = "san1";
const std::vector<std::string> expected_sans = {"san1"};
const char* expected_pem_cert = "pem_cert1";
const char* expected_pem_cert_chain = "pem_cert1_chain";
GPR_ASSERT(tsi_construct_peer(6, &peer) == TSI_OK);
@ -334,29 +263,37 @@ static void test_cn_and_one_san_ssl_peer_to_auth_context(void) {
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
&peer.properties[1]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, expected_san,
&peer.properties[2]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
&peer.properties[3]) == TSI_OK);
&peer.properties[2]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_SECURITY_LEVEL_PEER_PROPERTY,
tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
&peer.properties[4]) == TSI_OK);
&peer.properties[3]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_CHAIN_PROPERTY, expected_pem_cert_chain,
&peer.properties[5]) == TSI_OK);
&peer.properties[4]) == TSI_OK);
for (size_t i = 0; i < expected_sans.size(); i++) {
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
expected_sans[i].c_str(),
&peer.properties[5 + i]) == TSI_OK);
}
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
GPR_ASSERT(
check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME, &expected_san, 1));
GPR_ASSERT(check_transport_security_type(ctx.get()));
GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
GPR_ASSERT(check_x509_pem_cert_chain(ctx.get(), expected_pem_cert_chain));
check_properties(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME, expected_sans));
GPR_ASSERT(check_property(ctx.get(),
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE));
GPR_ASSERT(
check_property(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, expected_cn));
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_PEM_CERT_PROPERTY_NAME,
expected_pem_cert));
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME,
expected_pem_cert_chain));
rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
@ -370,12 +307,11 @@ static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) {
tsi_peer peer;
tsi_peer rpeer;
const char* expected_cn = "cn1";
const char* expected_sans[] = {"san1", "san2", "san3"};
const std::vector<std::string> expected_sans = {"san1", "san2", "san3"};
const char* expected_pem_cert = "pem_cert1";
const char* expected_pem_cert_chain = "pem_cert1_chain";
size_t i;
GPR_ASSERT(tsi_construct_peer(5 + GPR_ARRAY_SIZE(expected_sans), &peer) ==
TSI_OK);
GPR_ASSERT(tsi_construct_peer(5 + expected_sans.size(), &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
@ -392,21 +328,27 @@ static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) {
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_CHAIN_PROPERTY, expected_pem_cert_chain,
&peer.properties[4]) == TSI_OK);
for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) {
for (i = 0; i < expected_sans.size(); i++) {
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
expected_sans[i], &peer.properties[5 + i]) == TSI_OK);
expected_sans[i].c_str(),
&peer.properties[5 + i]) == TSI_OK);
}
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
GPR_ASSERT(check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME,
expected_sans, GPR_ARRAY_SIZE(expected_sans)));
GPR_ASSERT(check_transport_security_type(ctx.get()));
GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
GPR_ASSERT(check_x509_pem_cert_chain(ctx.get(), expected_pem_cert_chain));
GPR_ASSERT(
check_properties(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME, expected_sans));
GPR_ASSERT(check_property(ctx.get(),
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE));
GPR_ASSERT(
check_property(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, expected_cn));
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_PEM_CERT_PROPERTY_NAME,
expected_pem_cert));
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME,
expected_pem_cert_chain));
rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
@ -423,10 +365,9 @@ static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(
const char* expected_cn = "cn1";
const char* expected_pem_cert = "pem_cert1";
const char* expected_pem_cert_chain = "pem_cert1_chain";
const char* expected_sans[] = {"san1", "san2", "san3"};
const std::vector<std::string> expected_sans = {"san1", "san2", "san3"};
size_t i;
GPR_ASSERT(tsi_construct_peer(7 + GPR_ARRAY_SIZE(expected_sans), &peer) ==
TSI_OK);
GPR_ASSERT(tsi_construct_peer(7 + expected_sans.size(), &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
@ -447,21 +388,27 @@ static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_PEM_CERT_CHAIN_PROPERTY, expected_pem_cert_chain,
&peer.properties[6]) == TSI_OK);
for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) {
for (i = 0; i < expected_sans.size(); i++) {
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
expected_sans[i], &peer.properties[7 + i]) == TSI_OK);
expected_sans[i].c_str(),
&peer.properties[7 + i]) == TSI_OK);
}
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
GPR_ASSERT(check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME,
expected_sans, GPR_ARRAY_SIZE(expected_sans)));
GPR_ASSERT(check_transport_security_type(ctx.get()));
GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
GPR_ASSERT(check_x509_pem_cert_chain(ctx.get(), expected_pem_cert_chain));
GPR_ASSERT(
check_properties(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME, expected_sans));
GPR_ASSERT(check_property(ctx.get(),
GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_SSL_TRANSPORT_SECURITY_TYPE));
GPR_ASSERT(
check_property(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, expected_cn));
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_PEM_CERT_PROPERTY_NAME,
expected_pem_cert));
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME,
expected_pem_cert_chain));
rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
@ -483,7 +430,8 @@ static void test_dns_peer_to_auth_context(void) {
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(check_sans(ctx.get(), GRPC_PEER_DNS_PROPERTY_NAME, expected_dns));
GPR_ASSERT(
check_properties(ctx.get(), GRPC_PEER_DNS_PROPERTY_NAME, expected_dns));
tsi_peer_destruct(&peer);
ctx.reset(DEBUG_LOCATION, "test");
}
@ -500,7 +448,8 @@ static void test_uri_peer_to_auth_context(void) {
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(check_sans(ctx.get(), GRPC_PEER_URI_PROPERTY_NAME, expected_uri));
GPR_ASSERT(
check_properties(ctx.get(), GRPC_PEER_URI_PROPERTY_NAME, expected_uri));
tsi_peer_destruct(&peer);
ctx.reset(DEBUG_LOCATION, "test");
}
@ -517,8 +466,8 @@ static void test_email_peer_to_auth_context(void) {
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(
check_sans(ctx.get(), GRPC_PEER_EMAIL_PROPERTY_NAME, expected_emails));
GPR_ASSERT(check_properties(ctx.get(), GRPC_PEER_EMAIL_PROPERTY_NAME,
expected_emails));
tsi_peer_destruct(&peer);
ctx.reset(DEBUG_LOCATION, "test");
}
@ -536,7 +485,8 @@ static void test_ip_peer_to_auth_context(void) {
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(check_sans(ctx.get(), GRPC_PEER_IP_PROPERTY_NAME, expected_ips));
GPR_ASSERT(
check_properties(ctx.get(), GRPC_PEER_IP_PROPERTY_NAME, expected_ips));
tsi_peer_destruct(&peer);
ctx.reset(DEBUG_LOCATION, "test");
}
@ -622,6 +572,22 @@ static void test_spiffe_id_peer_to_auth_context(void) {
multiple_uri_ctx.reset(DEBUG_LOCATION, "test");
}
static void test_subject_to_auth_context(void) {
tsi_peer peer;
const char* expected_subject = "subject1";
GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_PEER_PROPERTY, expected_subject,
&peer.properties[0]) == TSI_OK);
grpc_core::RefCountedPtr<grpc_auth_context> ctx =
grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
GPR_ASSERT(ctx != nullptr);
GPR_ASSERT(check_property(ctx.get(), GRPC_X509_SUBJECT_PROPERTY_NAME,
expected_subject));
tsi_peer_destruct(&peer);
ctx.reset(DEBUG_LOCATION, "test");
}
static const char* roots_for_override_api = "roots for override api";
static grpc_ssl_roots_override_result override_roots_success(
@ -775,6 +741,7 @@ int main(int argc, char** argv) {
test_email_peer_to_auth_context();
test_ip_peer_to_auth_context();
test_spiffe_id_peer_to_auth_context();
test_subject_to_auth_context();
test_ipv6_address_san();
test_default_ssl_roots();
test_peer_alpn_check();

@ -270,35 +270,18 @@ static bool check_property(tsi_peer* peer, const char* property_name,
return false;
}
static bool check_subject_alt_name(tsi_peer* peer, const char* name) {
return check_property(peer, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
name);
}
static bool check_dns(tsi_peer* peer, const char* name) {
return check_property(peer, TSI_X509_DNS_PEER_PROPERTY, name);
}
static bool check_uri(tsi_peer* peer, const char* name) {
return check_property(peer, TSI_X509_URI_PEER_PROPERTY, name);
}
static bool check_email(tsi_peer* peer, const char* name) {
return check_property(peer, TSI_X509_EMAIL_PEER_PROPERTY, name);
}
static bool check_ip(tsi_peer* peer, const char* name) {
return check_property(peer, TSI_X509_IP_PEER_PROPERTY, name);
}
void check_server1_peer(tsi_peer* peer) {
const tsi_peer_property* property =
check_basic_authenticated_peer_and_get_common_name(peer);
const char* expected_match = "*.test.google.com";
GPR_ASSERT(memcmp(property->value.data, expected_match,
property->value.length) == 0);
GPR_ASSERT(check_subject_alt_name(peer, "*.test.google.fr") == 1);
GPR_ASSERT(check_subject_alt_name(peer, "waterzooi.test.google.be") == 1);
GPR_ASSERT(check_property(peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"*.test.google.fr") == 1);
GPR_ASSERT(check_property(peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"waterzooi.test.google.be") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.fr") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.fr") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "waterzooi.test.google.be") == 1);
@ -928,14 +911,21 @@ void ssl_tsi_test_extract_x509_subject_names() {
tsi_peer peer;
GPR_ASSERT(tsi_ssl_extract_x509_subject_names_from_pem_cert(cert, &peer) ==
TSI_OK);
// tsi_peer should include one common name, one certificate, one security
// level, ten SAN fields, two DNS SAN fields, three URI fields, two email
// addresses and two IP addresses.
size_t expected_property_count = 21;
// tsi_peer should include one subject, one common name, one certificate, one
// security level, ten SAN fields, two DNS SAN fields, three URI fields, two
// email addresses and two IP addresses.
size_t expected_property_count = 22;
GPR_ASSERT(peer.property_count == expected_property_count);
// Check subject
const char* expected_subject = "CN=xpigors,OU=Google,L=SF,ST=CA,C=US";
const tsi_peer_property* property =
tsi_peer_get_property_by_name(&peer, TSI_X509_SUBJECT_PEER_PROPERTY);
GPR_ASSERT(property != nullptr);
GPR_ASSERT(memcmp(property->value.data, expected_subject,
property->value.length) == 0);
// Check common name
const char* expected_cn = "xpigors";
const tsi_peer_property* property = tsi_peer_get_property_by_name(
property = tsi_peer_get_property_by_name(
&peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);
GPR_ASSERT(property != nullptr);
GPR_ASSERT(
@ -945,32 +935,58 @@ void ssl_tsi_test_extract_x509_subject_names() {
GPR_ASSERT(property != nullptr);
GPR_ASSERT(memcmp(property->value.data, cert, property->value.length) == 0);
// Check DNS
GPR_ASSERT(check_subject_alt_name(&peer, "foo.test.domain.com") == 1);
GPR_ASSERT(check_subject_alt_name(&peer, "bar.test.domain.com") == 1);
GPR_ASSERT(check_dns(&peer, "foo.test.domain.com") == 1);
GPR_ASSERT(check_dns(&peer, "bar.test.domain.com") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"foo.test.domain.com") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"bar.test.domain.com") == 1);
GPR_ASSERT(check_property(&peer, TSI_X509_DNS_PEER_PROPERTY,
"foo.test.domain.com") == 1);
GPR_ASSERT(check_property(&peer, TSI_X509_DNS_PEER_PROPERTY,
"bar.test.domain.com") == 1);
// Check URI
// Note that a valid SPIFFE certificate should only have one URI.
GPR_ASSERT(check_subject_alt_name(&peer, "spiffe://foo.com/bar/baz") == 1);
GPR_ASSERT(
check_subject_alt_name(&peer, "https://foo.test.domain.com/test") == 1);
GPR_ASSERT(
check_subject_alt_name(&peer, "https://bar.test.domain.com/test") == 1);
GPR_ASSERT(check_uri(&peer, "spiffe://foo.com/bar/baz") == 1);
GPR_ASSERT(check_uri(&peer, "https://foo.test.domain.com/test") == 1);
GPR_ASSERT(check_uri(&peer, "https://bar.test.domain.com/test") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"spiffe://foo.com/bar/baz") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"https://foo.test.domain.com/test") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"https://bar.test.domain.com/test") == 1);
GPR_ASSERT(check_property(&peer, TSI_X509_URI_PEER_PROPERTY,
"spiffe://foo.com/bar/baz") == 1);
GPR_ASSERT(check_property(&peer, TSI_X509_URI_PEER_PROPERTY,
"https://foo.test.domain.com/test") == 1);
GPR_ASSERT(check_property(&peer, TSI_X509_URI_PEER_PROPERTY,
"https://bar.test.domain.com/test") == 1);
// Check email address
GPR_ASSERT(check_subject_alt_name(&peer, "foo@test.domain.com") == 1);
GPR_ASSERT(check_subject_alt_name(&peer, "bar@test.domain.com") == 1);
GPR_ASSERT(check_email(&peer, "foo@test.domain.com") == 1);
GPR_ASSERT(check_email(&peer, "bar@test.domain.com") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"foo@test.domain.com") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"bar@test.domain.com") == 1);
GPR_ASSERT(check_property(&peer, TSI_X509_EMAIL_PEER_PROPERTY,
"foo@test.domain.com") == 1);
GPR_ASSERT(check_property(&peer, TSI_X509_EMAIL_PEER_PROPERTY,
"bar@test.domain.com") == 1);
// Check ip address
GPR_ASSERT(check_subject_alt_name(&peer, "192.168.7.1") == 1);
GPR_ASSERT(check_subject_alt_name(&peer, "13::17") == 1);
GPR_ASSERT(check_ip(&peer, "192.168.7.1") == 1);
GPR_ASSERT(check_ip(&peer, "13::17") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"192.168.7.1") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"13::17") == 1);
GPR_ASSERT(check_property(&peer, TSI_X509_IP_PEER_PROPERTY, "192.168.7.1") ==
1);
GPR_ASSERT(check_property(&peer, TSI_X509_IP_PEER_PROPERTY, "13::17") == 1);
// Check other fields
GPR_ASSERT(check_subject_alt_name(&peer, "other types of SAN") == 1);
GPR_ASSERT(check_property(&peer,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
"other types of SAN") == 1);
// Free memory
gpr_free(cert);
tsi_peer_destruct(&peer);

Loading…
Cancel
Save