Skip to content

admin: add support for displaying san in certs end point#4566

Merged
lizan merged 19 commits intoenvoyproxy:masterfrom
ramaraochavali:fix/add_san_certs
Oct 10, 2018
Merged

admin: add support for displaying san in certs end point#4566
lizan merged 19 commits intoenvoyproxy:masterfrom
ramaraochavali:fix/add_san_certs

Conversation

@ramaraochavali
Copy link
Copy Markdown
Contributor

Signed-off-by: Rama rama.rao@salesforce.com
Description: Adds support for displaying Subject Alternate Names as a comma separated list of string in /certs admin end point
Risk Level: Low
Testing: Automated
Docs Changes: Updated
Release Notes: Updated

Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
Copy link
Copy Markdown
Member

@ggreenway ggreenway left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems reasonable, but I'm curious how this output is being used, and if anyone depends on the exact formatting of it. Anyone at lyft want to chime in? @mattklein123 @ccaraman @junr03 @danielhochman ?

Also, the output is formatted pretty strangely: It outputs repeated json objects (but without a json array [] outside), and the values contain free-form text of "key: value, key2: value2," format. Should we fix this to be proper json, with each key:value as a json key:value? Then adding new fields in the future shouldn't break anyone.

Comment thread source/common/ssl/utility.cc Outdated
namespace Ssl {

std::string Utility::getSerialNumberFromCertificate(X509& cert) {
const std::string Utility::getSerialNumberFromCertificate(X509& cert) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert: there's no reason to make something returned by-value const

Comment thread source/common/ssl/utility.cc Outdated
return "";
}

const std::vector<std::string> Utility::getSubjectAltNames(X509& cert) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this function is needed. There is already getDnsSansFromCertificate() and getUriSanFromCertificate(). You can just combine the results from those two.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you referring to these functions?

// TODO: Move helper functions to the `Ssl::Utility` namespace.

There is a TODO to move them to Utility. So I have added them in Utitlity now and will do a follow-up PR to use these functions there as well. WDYT? If you are referring to some thing else, please let me know. I will use them.

@mattklein123
Copy link
Copy Markdown
Member

This seems reasonable, but I'm curious how this output is being used, and if anyone depends on the exact formatting of it.

Right now this data is being just used for debugging. IMO we should take this opportunity to shift to a proto as we have done elsewhere. We can put this in the v1alpha namespace and then output JSON? Thoughts?

@ramaraochavali
Copy link
Copy Markdown
Contributor Author

I agree that this format is not scalable. I was thinking that moving to proto/json might require a broader discussion. But if every one thinks, moving to proto/json is right thing to do here, I can turn in this PR in to that.

@mattklein123
Copy link
Copy Markdown
Member

@ramaraochavali yeah I would just switch it. It's pretty easy to do.

Signed-off-by: Rama <rama.rao@salesforce.com>
@ramaraochavali
Copy link
Copy Markdown
Contributor Author

ramaraochavali commented Oct 3, 2018

@mattklein123 ok. Moved to protobuf/json implementation. Here is how it looks now. PTAL.

{
 "certificates": [
  {
   "ca_cert": {
    "path": "/git/envoy_files/certs/client-certs/ca.pem",
    "serial_number": "4114ea7c5d6cc0779e57c2b97c12a1940f2f9b7a",
    "subject_alt_names": [],
    "days_until_expiration": "2768"
   },
   "cert_chain": {
    "path": "/git/envoy_files/certs/client-certs/ca.pem",
    "serial_number": "5966c392",
    "subject_alt_names": [
     {
      "type": "DNS",
      "name": "localhost"
     }
    ],
    "days_until_expiration": "905"
   }
  },
  {
   "ca_cert": {
    "path": "/git/envoy_files/certs/client-certs/ca.pem",
    "serial_number": "4114ea7c5d6cc0779e57c2b97c12a1940f2f9b7a",
    "subject_alt_names": [],
    "days_until_expiration": "2768"
   },
   "cert_chain": {
    "path": "/git/envoy_files/certs/client-certs/ca.pem",
    "serial_number": "5966c392",
    "subject_alt_names": [
     {
      "type": "DNS",
      "name": "localhost"
     }
    ],
    "days_until_expiration": "905"
   }
  }
 ]
}

Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
@mattklein123
Copy link
Copy Markdown
Member

LGTM on the format! We can always change it later since it's alpha. I will review today. Thank you!

@mattklein123 mattklein123 self-assigned this Oct 3, 2018
Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice. 1 high level comment.

Comment thread include/envoy/ssl/context.h Outdated
/**
* @return a string of ca certificate path, certificate serial number and days until certificate
* expiration
* @return a JSON string representation of certificate conforming to proto admin.v2alpha.certs.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to have these functions return the proto objects? Then the admin code can actually merge the protos and do the JSON conversion? I think that would be more useful in the future for programmatic access of this information?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Will make that change

Signed-off-by: Rama <rama.rao@salesforce.com>
@ramaraochavali
Copy link
Copy Markdown
Contributor Author

@mattklein123 changed the methods to return proto objects. PTAL.

Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, small question/comment. @ggreenway can you take another pass and see if this works for you?

Comment thread source/common/ssl/context_impl.cc Outdated
CertificateDetailsPtr ContextImpl::getCaCertInformation() const {
if (ca_cert_ == nullptr) {
return "";
return std::make_unique<envoy::admin::v2alpha::CertificateDetails>();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this return nullptr to indicate no details?

Comment thread source/common/ssl/context_impl.cc Outdated
CertificateDetailsPtr ContextImpl::getCertChainInformation() const {
if (cert_chain_ == nullptr) {
return "";
return std::make_unique<envoy::admin::v2alpha::CertificateDetails>();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment?

Comment thread source/common/ssl/context_impl.cc Outdated
CertificateDetailsPtr ContextImpl::getCaCertInformation() const {
if (ca_cert_ == nullptr) {
return "";
return std::make_unique<envoy::admin::v2alpha::CertificateDetails>();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return nullptr in all these error cases

Comment thread source/server/http/admin.cc Outdated

envoy::admin::v2alpha::CertificateDetails* ca_certificate = certificate.mutable_ca_cert();
MessageUtil::loadFromJson(context.getCaCertInformation(), *ca_certificate);
ca_certificate->MergeFrom(*context.getCaCertInformation());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just assign, instead of doing MergeFrom, given that ca_certificate should be empty (eg we can replace instead of merge).

Comment thread source/server/http/admin.cc Outdated
ca_certificate->MergeFrom(*context.getCaCertInformation());
envoy::admin::v2alpha::CertificateDetails* cert_chain = certificate.mutable_cert_chain();
MessageUtil::loadFromJson(context.getCertChainInformation(), *cert_chain);
cert_chain->MergeFrom(*context.getCertChainInformation());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
@ramaraochavali
Copy link
Copy Markdown
Contributor Author

@mattklein123 @ggreenway addressed the feedback. PTAL.

ggreenway
ggreenway previously approved these changes Oct 5, 2018
Copy link
Copy Markdown
Member

@ggreenway ggreenway left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ggreenway
Copy link
Copy Markdown
Member

Merge conflict :(

Comment thread source/server/http/admin.cc Outdated
envoy::admin::v2alpha::Certificate& certificate = *certificates.add_certificates();
envoy::admin::v2alpha::CertificateDetails* ca_certificate = certificate.mutable_ca_cert();
ca_certificate->MergeFrom(*context.getCaCertInformation());
*ca_certificate = *context.getCaCertInformation();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this need to check for nullptr now? Same below? Can you add a test that covers this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought context will not be created if files does not exist or not valid. Any way it is good to handle that case. I will add a test.

Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
Comment thread api/envoy/admin/v2alpha/certs.proto Outdated
}

message SubjectAlternateName {
enum Type {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

@ramaraochavali ramaraochavali Oct 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I use oneof it would be converted to JSON as if I set empty value.

    "subject_alt_names": [
     {
      "name": "localhost",
      "DNS": ""
     }
    ],
    "days_until_expiration": "903"
   }

I think what we have as below is more readable. Are you suggesting some thing different here?

    "subject_alt_names": [
     {
      "name": "localhost",
      "type": "DNS"
     }
    ],
    "days_until_expiration": "903"
   }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I meant you should make this

message SubjectAlterativeName {
  oneof name {
    string dns = 1;
    string uri = 2;
  }
}

The JSON would be:

"subject_alt_names": [
     {
      "dns": "example.com"
     }
]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah.. I see. I will make that change

repeated SubjectAlternateName subject_alt_names = 3;

// Days until expiration of the Certificate.
uint64 days_until_expiration = 4;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this just be expiration timestamp?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

days_until_expiration looks at the chain also and computes the minimum of cert and chain. I think I will leave it like that for now as stats and others also use the same. If we can add another field to just dump expiration timestamp later?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reg expiration timestamp, just looked at it. There is no direct api now to get it. We will have to add one function , related tests etc. I will add it once this is merged in a follow-up PR.

Signed-off-by: Rama <rama.rao@salesforce.com>
@ramaraochavali
Copy link
Copy Markdown
Contributor Author

@mattklein123 added test. PTAL.

Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM. One additional small comment that I missed last time. Sorry about that.

Comment thread source/common/ssl/utility.cc Outdated
return subject_alt_names;
}

std::vector<std::string> Utility::getUriSubjectAltNames(X509& cert) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I just noticed this is basically the same function as the previous one. Can you padd the SAN type as a parameter instead?

Signed-off-by: Rama <rama.rao@salesforce.com>
@ramaraochavali
Copy link
Copy Markdown
Contributor Author

@mattklein123 no problem. Fixed. PTAL.

Comment thread test/common/ssl/context_impl_test.cc Outdated
EXPECT_FALSE(ContextImpl::dNSNameMatch("lyft.com", ""));
}

TEST_F(SslContextImplTest, TestGetSubjectAlternateNamesWithDNS) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move these tests to utility_test?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will move

}

TEST_F(SslContextImplTest, TestGetCertInformationWithSAN) {
std::string json = R"EOF(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is v1 config format to be removed soon, can you use v2 format?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can use for these two tests. But rest of the tests are still using v1 config in this same file. I prefer to leave these two also in v1 for now and cleanup all of them to v2 in a separate PR if that is Ok.

Comment thread test/common/ssl/context_impl_test.cc Outdated
std::string ca_cert_partial_output(TestEnvironment::substitute(ca_cert_json));
std::string cert_chain_partial_output(TestEnvironment::substitute(cert_chain_json));
EXPECT_TRUE(MessageUtil::getJsonStringFromMessage(*context->getCaCertInformation(), true, true)
.find(ca_cert_partial_output) != std::string::npos);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use MessageDifferencer instead of comparing JSON string.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to use MessageDifferencer and setup is becoming complicated because we need to ignore certain fields like days_until_expired etc as they change. So I left this with string comparison.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread api/envoy/admin/v2alpha/certs.proto Outdated
CertificateDetails ca_cert = 1;

// Details of Certificate Chain
CertificateDetails cert_chain = 2;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these be repeated? I know current /certs only print the 1st certificate in ca_cert and leaf certificate information in cert_chain for each TLS context, but we will need a full cert chain and CA cert?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. My goal was to replicate what we have in /certs with subject alt names added. Do you mind creating issue with what you are describing here so that we can add it once it is merged?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I know you're just replicate current behavior of /certs, so make this repeated, and it is fine to only have one when you fill it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. Do you mean for both cert chain and ca cert?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes both

Comment thread test/common/ssl/context_impl_test.cc Outdated
FILE* fp = fopen(
TestEnvironment::runfilesPath("test/common/ssl/test_data/san_uri_cert.pem").c_str(), "r");
EXPECT_NE(fp, nullptr);
X509* cert = PEM_read_X509(fp, nullptr, nullptr, nullptr);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bssl::UniquePtr

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Comment thread test/common/ssl/context_impl_test.cc Outdated
}

TEST_F(SslContextImplTest, TestGetSubjectAlternateNamesWithUri) {
FILE* fp = fopen(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use TestEnvironment::readFileToStringForTest read into a string then use BIO? See how context_impl reads certificate. Also factor out that function for these 3 tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. I will refactor to this to a function in utility test using the same approach because rest of the context_test_impl also uses the same to be consistent.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, filed #4635 to track them.

@lizan lizan mentioned this pull request Oct 8, 2018
4 tasks
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
@ramaraochavali
Copy link
Copy Markdown
Contributor Author

@lizan changed as suggested. PTAL.

Signed-off-by: Rama <rama.rao@salesforce.com>
@ramaraochavali
Copy link
Copy Markdown
Contributor Author

@mattklein123 rebased master to resolve the conflicts. Can you PTAL?

mattklein123
mattklein123 previously approved these changes Oct 9, 2018
Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you! @lizan can you do the remainder of the review/merge?

lizan
lizan previously approved these changes Oct 9, 2018
@lizan
Copy link
Copy Markdown
Member

lizan commented Oct 9, 2018

@ramaraochavali can you merge master?

Signed-off-by: Rama <rama.rao@salesforce.com>
@ramaraochavali ramaraochavali dismissed stale reviews from lizan and mattklein123 via 5984913 October 10, 2018 00:17
@ramaraochavali
Copy link
Copy Markdown
Contributor Author

@lizan merged master. PTAL

@lizan lizan merged commit 7403314 into envoyproxy:master Oct 10, 2018
@ramaraochavali ramaraochavali deleted the fix/add_san_certs branch October 10, 2018 04:25
aa-stripe pushed a commit to aa-stripe/envoy that referenced this pull request Oct 11, 2018
…4566)

*Description*: Adds support for displaying Subject Alternate Names as a comma separated list of string in `/certs` admin end point

*Risk Level*: Low
*Testing*: Automated
*Docs Changes*: Updated
*Release Notes*: Updated

Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Aaltan Ahmad <aa@stripe.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants