admin: add support for displaying san in certs end point#4566
admin: add support for displaying san in certs end point#4566lizan merged 19 commits intoenvoyproxy:masterfrom
Conversation
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
ggreenway
left a comment
There was a problem hiding this comment.
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.
| namespace Ssl { | ||
|
|
||
| std::string Utility::getSerialNumberFromCertificate(X509& cert) { | ||
| const std::string Utility::getSerialNumberFromCertificate(X509& cert) { |
There was a problem hiding this comment.
revert: there's no reason to make something returned by-value const
| return ""; | ||
| } | ||
|
|
||
| const std::vector<std::string> Utility::getSubjectAltNames(X509& cert) { |
There was a problem hiding this comment.
I don't think this function is needed. There is already getDnsSansFromCertificate() and getUriSanFromCertificate(). You can just combine the results from those two.
There was a problem hiding this comment.
Are you referring to these functions?
envoy/source/common/ssl/ssl_socket.h
Line 72 in f936fc6
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.
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? |
|
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. |
|
@ramaraochavali yeah I would just switch it. It's pretty easy to do. |
Signed-off-by: Rama <rama.rao@salesforce.com>
|
@mattklein123 ok. Moved to protobuf/json implementation. Here is how it looks now. PTAL. |
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
|
LGTM on the format! We can always change it later since it's alpha. I will review today. Thank you! |
mattklein123
left a comment
There was a problem hiding this comment.
Very nice. 1 high level comment.
| /** | ||
| * @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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Ok. Will make that change
Signed-off-by: Rama <rama.rao@salesforce.com>
|
@mattklein123 changed the methods to return proto objects. PTAL. |
mattklein123
left a comment
There was a problem hiding this comment.
LGTM, small question/comment. @ggreenway can you take another pass and see if this works for you?
| CertificateDetailsPtr ContextImpl::getCaCertInformation() const { | ||
| if (ca_cert_ == nullptr) { | ||
| return ""; | ||
| return std::make_unique<envoy::admin::v2alpha::CertificateDetails>(); |
There was a problem hiding this comment.
Shouldn't this return nullptr to indicate no details?
| CertificateDetailsPtr ContextImpl::getCertChainInformation() const { | ||
| if (cert_chain_ == nullptr) { | ||
| return ""; | ||
| return std::make_unique<envoy::admin::v2alpha::CertificateDetails>(); |
| CertificateDetailsPtr ContextImpl::getCaCertInformation() const { | ||
| if (ca_cert_ == nullptr) { | ||
| return ""; | ||
| return std::make_unique<envoy::admin::v2alpha::CertificateDetails>(); |
There was a problem hiding this comment.
return nullptr in all these error cases
|
|
||
| envoy::admin::v2alpha::CertificateDetails* ca_certificate = certificate.mutable_ca_cert(); | ||
| MessageUtil::loadFromJson(context.getCaCertInformation(), *ca_certificate); | ||
| ca_certificate->MergeFrom(*context.getCaCertInformation()); |
There was a problem hiding this comment.
I think you can just assign, instead of doing MergeFrom, given that ca_certificate should be empty (eg we can replace instead of merge).
| 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()); |
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
|
@mattklein123 @ggreenway addressed the feedback. PTAL. |
|
Merge conflict :( |
| 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(); |
There was a problem hiding this comment.
Doesn't this need to check for nullptr now? Same below? Can you add a test that covers this?
There was a problem hiding this comment.
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>
| } | ||
|
|
||
| message SubjectAlternateName { | ||
| enum Type { |
There was a problem hiding this comment.
Prefer oneof here per https://github.com/envoyproxy/envoy/blob/master/api/STYLE.md
There was a problem hiding this comment.
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"
}
There was a problem hiding this comment.
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"
}
]
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
Should this just be expiration timestamp?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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>
|
@mattklein123 added test. PTAL. |
mattklein123
left a comment
There was a problem hiding this comment.
Thanks, LGTM. One additional small comment that I missed last time. Sorry about that.
| return subject_alt_names; | ||
| } | ||
|
|
||
| std::vector<std::string> Utility::getUriSubjectAltNames(X509& cert) { |
There was a problem hiding this comment.
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>
|
@mattklein123 no problem. Fixed. PTAL. |
| EXPECT_FALSE(ContextImpl::dNSNameMatch("lyft.com", "")); | ||
| } | ||
|
|
||
| TEST_F(SslContextImplTest, TestGetSubjectAlternateNamesWithDNS) { |
| } | ||
|
|
||
| TEST_F(SslContextImplTest, TestGetCertInformationWithSAN) { | ||
| std::string json = R"EOF( |
There was a problem hiding this comment.
This is v1 config format to be removed soon, can you use v2 format?
There was a problem hiding this comment.
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.
| 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); |
There was a problem hiding this comment.
Use MessageDifferencer instead of comparing JSON string.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
You should be able to do that with PARTIAL scope. https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.util.message_differencer#MessageDifferencer.Scope.details
| CertificateDetails ca_cert = 1; | ||
|
|
||
| // Details of Certificate Chain | ||
| CertificateDetails cert_chain = 2; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
ok. Do you mean for both cert chain and ca cert?
| 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); |
| } | ||
|
|
||
| TEST_F(SslContextImplTest, TestGetSubjectAlternateNamesWithUri) { | ||
| FILE* fp = fopen( |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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>
|
@lizan changed as suggested. PTAL. |
Signed-off-by: Rama <rama.rao@salesforce.com>
|
@mattklein123 rebased master to resolve the conflicts. Can you PTAL? |
mattklein123
left a comment
There was a problem hiding this comment.
LGTM, thank you! @lizan can you do the remainder of the review/merge?
|
@ramaraochavali can you merge master? |
Signed-off-by: Rama <rama.rao@salesforce.com>
5984913
|
@lizan merged master. PTAL |
…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>
Signed-off-by: Rama rama.rao@salesforce.com
Description: Adds support for displaying Subject Alternate Names as a comma separated list of string in
/certsadmin end pointRisk Level: Low
Testing: Automated
Docs Changes: Updated
Release Notes: Updated