Skip to content
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

SDS v3 endpoints support SPIFFE validator #2435

Merged
merged 4 commits into from Aug 17, 2021

Conversation

MarcosDY
Copy link
Collaborator

@MarcosDY MarcosDY commented Aug 3, 2021

Update SDS v3 endpoints to use "SPIFFE Certificate Validator", it is used as default for Envoys from v1.18.0.
Add a new configurable to set default_all_bundles_name that i used to configure a validator config that contains Bundle together with all Federated Bundles.

Which issue this PR fixes
fixes #2420

Copy link
Member

@amartinezfayo amartinezfayo left a comment

Choose a reason for hiding this comment

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

Looking great! I have some small comments.

| -------------------------- | --------------------------------------------------------------------------------------- | -------------------- |
| `default_svid_name` | The TLS Certificate resource name to use for the default X509-SVID with Envoy SDS | default |
| `default_bundle_name` | The Validation Context resource name to use for the default X.509 bundle with Envoy SDS | ROOTCA |
| `default_all_bundle_sname` | The Validation Context resource name to use when fetching X.509 bundle together with federated bundles with Envoy SDS | ALL |
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
| `default_all_bundle_sname` | The Validation Context resource name to use when fetching X.509 bundle together with federated bundles with Envoy SDS | ALL |
| `default_all_bundles_name` | The Validation Context resource name to use when fetching X.509 bundle together with federated bundles with Envoy SDS | ALL |

@@ -273,6 +274,9 @@ resource name (e.g. `spiffe://example.org`). Alternatively, if the default name
`auth.CertificateValidationContext` containing the trusted CA certificates for the agent's trust domain is fetched.
The default name is configurable (see `default_bundle_name` under [SDS Configuration](#sds-configuration)).

Another option is to request for `ALL` that creates a [SPIFFE Certificate Validator](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.proto) that contains TrustDomain together with all Federated Bundles. This feature is supported from Envoy v1.18.0.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Another option is to request for `ALL` that creates a [SPIFFE Certificate Validator](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.proto) that contains TrustDomain together with all Federated Bundles. This feature is supported from Envoy v1.18.0.
Another option is to request for `ALL` that creates a [SPIFFE Certificate Validator](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.proto) that contains TrustDomain together with all Federated Bundles. This feature is supported starting with Envoy v1.18.0.

@@ -244,29 +247,79 @@ func (h *Handler) buildResponse(versionInfo string, req *discovery_v3.DiscoveryR
}
returnAllEntries := len(names) == 0

// Use RootCA as default, but replace for SPIFFE auth when envoy version is at least v1.18.0
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Use RootCA as default, but replace for SPIFFE auth when envoy version is at least v1.18.0
// Use RootCA as default, but replace with SPIFFE auth when Envoy version is at least v1.18.0


case names[h.c.DefaultAllBundlesName]:
if useRootCAValidator {
return nil, status.Error(codes.Internal, `unable to use "SPIFFE validator" on envoy below 1.17`)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return nil, status.Error(codes.Internal, `unable to use "SPIFFE validator" on envoy below 1.17`)
return nil, status.Error(codes.Internal, `unable to use "SPIFFE validator" on Envoy below 1.17`)

Copy link
Member

@azdagron azdagron left a comment

Choose a reason for hiding this comment

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

Thanks for putting this together @MarcosDY! I wonder if some of the "builder" stuff can be simplified.... I've left some comments to that effect.

Comment on lines 251 to 260
useRootCAValidator := true
if buildVersion := req.Node.GetUserAgentBuildVersion(); buildVersion != nil {
version := buildVersion.Version
useRootCAValidator = version.MajorNumber <= 1 && version.MinorNumber < 18
}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe put this in another function, maybe named supportsSPIFFEAuthExtension?

@@ -244,29 +247,79 @@ func (h *Handler) buildResponse(versionInfo string, req *discovery_v3.DiscoveryR
}
returnAllEntries := len(names) == 0

// Use RootCA as default, but replace for SPIFFE auth when envoy version is at least v1.18.0
useRootCAValidator := true
Copy link
Member

Choose a reason for hiding this comment

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

The builder interface doesn't seem very useful since we still check this boolean in most spots in order to set up the correct interface.

Perhaps, the builder interface looks like:

type validationContextBuilder interface {
    buildOne(resourceName, trustDomainID string) (*any.Any, error)
    buildAll(resourceName string, td string) (*any.Any, error)
}

Then that interface could be set once, up at top, once we determine if there is support for the SPIFFE Auth Extension. buildOne would be called in all cases except when the "ALL
name is requested, which would use buildAll. The buildAll method for the "root ca" builder would fail.

@azdagron azdagron added this to the 1.0.2 milestone Aug 17, 2021
Copy link
Member

@azdagron azdagron left a comment

Choose a reason for hiding this comment

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

Sorry for the additional back-and-forth on this, I noticed a few more things.

@@ -400,6 +402,10 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
ac.DataDir = c.Agent.DataDir
ac.DefaultSVIDName = c.Agent.SDS.DefaultSVIDName
ac.DefaultBundleName = c.Agent.SDS.DefaultBundleName
ac.DefaultAllBundlesName = c.Agent.SDS.DefaultAllBundlesName
if ac.DefaultAllBundlesName == ac.DefaultBundleName {
logger.Warn(`"default_bundle_name" and "default_all_bundles_name" has the same value, "default_bundle_name" will be used. In future versions this misconfiguration will cause agent to not start.`)
Copy link
Member

Choose a reason for hiding this comment

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

Small suggestion on rewording emphasizing that the "all" configurable will be ignored and an added call to action.

Suggested change
logger.Warn(`"default_bundle_name" and "default_all_bundles_name" has the same value, "default_bundle_name" will be used. In future versions this misconfiguration will cause agent to not start.`)
logger.Warn(`The "default_bundle_name" and "default_all_bundles_name" configurables have the same value. "default_all_bundles_name" will be ignored. Please configure distinct values or use the defaults. This will be a configuration error In a future release.`)

Comment on lines 53 to 56
# # default_all_bundles_name: The Validation Context resource name to use for when
# # fetching X.509 bundle togehter with federated bundles with Envoy SDS
# # default_all_bundles_name = "ALL"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# # default_all_bundles_name: The Validation Context resource name to use for when
# # fetching X.509 bundle togehter with federated bundles with Envoy SDS
# # default_all_bundles_name = "ALL"
# # default_all_bundles_name: The Validation Context resource name to use to fetch
# # all bundles (including federated bundles) with Envoy SDS. Cannot be used with
# # Envoy releases prior to 1.18.
# # default_all_bundles_name = "ALL"

| -------------------------- | --------------------------------------------------------------------------------------- | -------------------- |
| `default_svid_name` | The TLS Certificate resource name to use for the default X509-SVID with Envoy SDS | default |
| `default_bundle_name` | The Validation Context resource name to use for the default X.509 bundle with Envoy SDS | ROOTCA |
| `default_all_bundles_name` | The Validation Context resource name to use when fetching X.509 bundle together with federated bundles with Envoy SDS | ALL |
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
| `default_all_bundles_name` | The Validation Context resource name to use when fetching X.509 bundle together with federated bundles with Envoy SDS | ALL |
| `default_all_bundles_name` | The Validation Context resource name to use for all bundles (including federated) with Envoy SDS | ALL |

@@ -273,6 +274,9 @@ resource name (e.g. `spiffe://example.org`). Alternatively, if the default name
`auth.CertificateValidationContext` containing the trusted CA certificates for the agent's trust domain is fetched.
The default name is configurable (see `default_bundle_name` under [SDS Configuration](#sds-configuration)).

Another option is to request for `ALL` that creates a [SPIFFE Certificate Validator](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.proto) that contains TrustDomain together with all Federated Bundles. This feature is supported starting with Envoy v1.18.0.
The default name is configurable (see `default_all_bundles_name` under [SDS Configuration](#sds-configuration)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
The default name is configurable (see `default_all_bundles_name` under [SDS Configuration](#sds-configuration)
The default name is configurable (see `default_all_bundles_name` under [SDS Configuration](#sds-configuration).

@@ -273,6 +274,9 @@ resource name (e.g. `spiffe://example.org`). Alternatively, if the default name
`auth.CertificateValidationContext` containing the trusted CA certificates for the agent's trust domain is fetched.
The default name is configurable (see `default_bundle_name` under [SDS Configuration](#sds-configuration)).

Another option is to request for `ALL` that creates a [SPIFFE Certificate Validator](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.proto) that contains TrustDomain together with all Federated Bundles. This feature is supported starting with Envoy v1.18.0.
Copy link
Member

Choose a reason for hiding this comment

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

I think we should combine this and the previous paragraph, since it isn't exactly clear, at least with the current formatting, that this paragraph is still in reference to the validation context. My suggestion also has a little rewording:

[`auth.CertificateValidationContext`](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/auth/cert.proto#auth-certificatevalidationcontext)
resources containing trusted CA certificates can be fetched using the SPIFFE ID
of the desired trust domain as the resource name (e.g. `spiffe://example.org`).
In addition, two other special resource names are available. The first, which
defaults to "ROOTCA", provides the CA certificates for the trust domain the
agent belongs to. The second, which defaults to "ALL", returns the trusted CA
certificates for both the trust domain the agent belongs to as well as any
federated trust domains applicable to the Envoy workload.  The default names
for these resource names are configurable via the `default_bundle_name` and
`default_all_bundles_name`, respectively. The "ALL" resource name requires
support for the [SPIFFE Certificate Validator](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.proto)
extension, which is only available starting with Envoy 1.18.

Comment on lines 264 to 266
// Create validation context.
// - RootCA validator for v1.17 and below
// - SPIFFE validator from v1.18
Copy link
Member

Choose a reason for hiding this comment

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

This comment now seems out of place....

func (b *rootCABuilder) buildOne(resourceName, trustDomain string) (*any.Any, error) {
bundle, ok := b.bundles[trustDomain]
if !ok {
return nil, status.Errorf(codes.Internal, "no bundle found for trust domain: %q", trustDomain)
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this should be codes.Internal, it's easy for someone to make a request for a trust domain ID that they don't have access to. I'd recommend either codes.InvalidRequest or codes.NotFound.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I choose codes.NotFound

func newSpiffeBuilder(tdBundle *bundleutil.Bundle, federatedBundles map[spiffeid.TrustDomain]*bundleutil.Bundle) (validationContextBuilder, error) {
bundles := make(map[spiffeid.TrustDomain]*bundleutil.Bundle, len(federatedBundles)+1)

// Add td bundle if provided
Copy link
Member

Choose a reason for hiding this comment

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

FWIW, tdBundle should never be nil. I'm ok with the defensive code, but we should adjust the comment so folks don't think it can be nil in normal circumstances.

Suggested change
// Add td bundle if provided
// Only include tdBundle if it is not nil, which shouldn't ever be the case. This is purely defensive.


func newRootCABuilder(bundle *bundleutil.Bundle, federatedBundles map[spiffeid.TrustDomain]*bundleutil.Bundle) validationContextBuilder {
bundles := make(map[string]*bundleutil.Bundle, len(federatedBundles)+1)
// Add td bundle if provided
Copy link
Member

Choose a reason for hiding this comment

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

FWIW, tdBundle should never be nil. I'm ok with the defensive code, but we should adjust the comment so folks don't think it can be nil in normal circumstances.

Suggested change
// Add td bundle if provided
// Only include tdBundle if it is not nil, which shouldn't ever be the case. This is purely defensive.

func supportsSPIFFEAuthExtension(req *discovery_v3.DiscoveryRequest) bool {
if buildVersion := req.Node.GetUserAgentBuildVersion(); buildVersion != nil {
version := buildVersion.Version
return version.MajorNumber >= 1 && version.MinorNumber > 17
Copy link
Member

Choose a reason for hiding this comment

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

This check is potentially incorrect for Envoy 2.0 - 2.17 (which may or may not support the extension, but we can assume they do until we know better).

Suggested change
return version.MajorNumber >= 1 && version.MinorNumber > 17
return (version.MajorNumber == 1 && version.MinorNumber > 17) || version.MajorNumber > 1

azdagron
azdagron previously approved these changes Aug 17, 2021
Copy link
Member

@azdagron azdagron left a comment

Choose a reason for hiding this comment

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

\o/, awesome work, @MarcosDY !

Signed-off-by: Marcos Yacob <marcos.yacob@hpe.com>
Signed-off-by: Marcos Yacob <marcos.yacob@hpe.com>
Signed-off-by: Marcos Yacob <marcos.yacob@hpe.com>
@azdagron azdagron merged commit 8b905e9 into spiffe:main Aug 17, 2021
evan2645 pushed a commit to evan2645/spire that referenced this pull request Sep 2, 2021
Signed-off-by: Marcos Yacob <marcos.yacob@hpe.com>
evan2645 pushed a commit that referenced this pull request Sep 2, 2021
Signed-off-by: Marcos Yacob <marcos.yacob@hpe.com>
@MarcosDY MarcosDY deleted the support-auth-validator-on-sds branch August 2, 2022 15:40
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.

Support the new SPIFFE Auth validator in Envoy
3 participants