-
Notifications
You must be signed in to change notification settings - Fork 492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for San selectors in x509pop node attestor plugin #5775
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: snanjundaswamy <[email protected]>
ac2835f
to
a313ae5
Compare
@@ -48,6 +48,10 @@ func main() { | |||
KeyUsage: x509.KeyUsageDigitalSignature, | |||
NotAfter: neverExpires, | |||
Subject: pkix.Name{CommonName: "COMMONNAME"}, | |||
URIs: []*url.URL{ | |||
{Scheme: "x509pop", Host: "example.org", Path: "/datacenter:us-east-1"}, | |||
{Scheme: "x509pop", Host: "example.org", Path: "/environment:production"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just curious (naming things is hard), there a reason for /environment:production over say, /environment/production ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like :
is a reserved character for URLs so it might not be the best choice. It may work now, but the standard library could add more validation in the future. /name/value
seems like a reasonable choice to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although by https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 it seems to allowed in the path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too opinionated on ':', I simply chose the character for consistency with separators in selectors. Based on what I hear, '/' sounds like a natural fit. I will make this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since :
is allowed in URL paths, I would suggest we stick to it as the SAN selector delimiter since it's what we use everywhere else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution. Generally looks good to me, with some small comments. It would also be good if we had some tests for using the selectors in the path component, do you think that could be done?
@@ -36,6 +36,7 @@ type agentPathTemplateData struct { | |||
PluginName string | |||
TrustDomain string | |||
SVIDPathTrimmed string | |||
San map[string]string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something like this for the name, to be a bit clearer and to avoid confusion with other kinds of Sans
San map[string]string | |
URISanSelectors map[string]string |
if strings.Contains(unprefixedUriSan, ":") { | ||
lastIndex := strings.LastIndex(unprefixedUriSan, ":") | ||
uriSelectorKey := unprefixedUriSan[:lastIndex] | ||
uriSelectorValue := unprefixedUriSan[lastIndex+1:] | ||
uriSelectorMap[uriSelectorKey] = uriSelectorValue | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we also log something if it's not possible to extract a selector from the path? The x509pop scheme isn't likely to be used for anything else so the user might want to know that one of the URIs couldn't be used.
lastIndex := strings.LastIndex(unprefixedUriSan, ":") | ||
uriSelectorKey := unprefixedUriSan[:lastIndex] | ||
uriSelectorValue := unprefixedUriSan[lastIndex+1:] | ||
uriSelectorMap[uriSelectorKey] = uriSelectorValue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for using LastIndex
for splitting the string? Something like x509pop://example.org/datacenter:ny:1
would be split as datacenter:ny => 1
, but to me it makes more sense as datacenter => ny:1
(which could be done through SplitN
).
Definitely a bit of an uncommon edge case, but it would be good to figure out from the beginning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about this a little bit myself. In my experience, the Key is usually fully qualified as against the values.
Something like company.org.service.datacenter = us-east-1
. References on k8s annotations here.
Either way, this should be a simple change, lmk what you think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a convention in the project around how selectors are formatted - key:value
, where key
cannot contain a :
delimiter. See this helper method for reference:
spire/cmd/spire-server/util/util.go
Line 185 in 50976c3
parts := strings.SplitAfterN(str, ":", 2) |
We should be consistent with that convention here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rturner3 @sorindumitru
Ok makes sense now.
But what about the values? Should we also retain the '/' in the values coming from the URI San? This will help us eliminate ambiguity around the usage of ':' in values. Here's an example for reference
datacenter:company/foo/us-east-1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think we should keep the SAN value as-is.
@@ -44,6 +44,7 @@ A sample configuration: | |||
| Common Name | `x509pop:subject:cn:example.org` | The Subject's Common Name (see X.500 Distinguished Names) | | |||
| SHA1 Fingerprint | `x509pop:ca:fingerprint:0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33` | The SHA1 fingerprint as a hex string for each cert in the PoP chain, excluding the leaf. | | |||
| SerialNumber | `x509pop:serialnumber:0a1b2c3d4e5f` | The leaf certificate serial number as a lowercase hexadecimal string | | |||
| San | `x509pop:san.<key>:<value>` | The san selectors on the leaf selectors. The expected format of the uri san is `x509pop://<trust_domain>/<key>:<value>` string | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| San | `x509pop:san.<key>:<value>` | The san selectors on the leaf selectors. The expected format of the uri san is `x509pop://<trust_domain>/<key>:<value>` string | | |
| San | `x509pop:san:<key>:<value>` | The san selectors on the leaf selectors. The expected format of the uri san is `x509pop://<trust_domain>/<key>:<value>` string | |
Pull Request check list
Affected functionality
x509pop Node Attestor plugin now supports SAN based additional selectors. Each san is for the URI format x509pop:///key:value. Each of these SANs is exposed as a selector with x509pop:san::. These selectors can also be used as a part of agent template with {{ .San.}}
Description of change
The change contains feature augmentation on x509pop node attestor plugin along with tests. The certificates for testing were generated with test/fixture/nodeattestor/x509pop/generate.go
Which issue this PR fixes
fixes #5746