Skip to content

Commit

Permalink
Backport of Improve XDS test coverage: JWT auth edition into release/…
Browse files Browse the repository at this point in the history
…1.16.x (#18196)

* backport of commit 613db16

* backport of commit 40e085a

---------

Co-authored-by: Ronald Ekambi <ronekambi@gmail.com>
Co-authored-by: DanStough <dan.stough@hashicorp.com>
  • Loading branch information
3 people authored Jul 19, 2023
1 parent f9482b6 commit 18db062
Show file tree
Hide file tree
Showing 5 changed files with 820 additions and 2 deletions.
162 changes: 160 additions & 2 deletions agent/xds/clusters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import (
"time"

envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
"github.com/hashicorp/consul/agent/xds/testcommon"

envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
testinf "github.com/mitchellh/go-testing-interface"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/wrapperspb"

"github.com/hashicorp/consul/agent/proxycfg"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/agent/xds/testcommon"
"github.com/hashicorp/consul/envoyextensions/xdscommon"
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/types"
Expand Down Expand Up @@ -219,6 +220,63 @@ func TestClustersFromSnapshot(t *testing.T) {
})
},
},
{
name: "connect-proxy-with-jwt-config-entry-with-local",
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{
{
CorrelationID: "jwt-provider",
Result: &structs.IndexedConfigEntries{
Kind: "jwt-provider",
Entries: []structs.ConfigEntry{
&structs.JWTProviderConfigEntry{
Name: "okta",
JSONWebKeySet: &structs.JSONWebKeySet{
Local: &structs.LocalJWKS{
JWKS: "xxx",
},
},
},
},
},
},
})
},
},
{
name: "connect-proxy-with-jwt-config-entry-with-remote-jwks",
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{
{
CorrelationID: "jwt-provider",
Result: &structs.IndexedConfigEntries{
Kind: "jwt-provider",
Entries: []structs.ConfigEntry{
&structs.JWTProviderConfigEntry{
Name: "okta",
JSONWebKeySet: &structs.JSONWebKeySet{
Remote: &structs.RemoteJWKS{
RequestTimeoutMs: 1000,
FetchAsynchronously: true,
URI: "https://test.test.com",
JWKSCluster: &structs.JWKSCluster{
DiscoveryType: structs.DiscoveryTypeStatic,
ConnectTimeout: time.Duration(5) * time.Second,
TLSCertificates: &structs.JWKSTLSCertificate{
TrustedCA: &structs.JWKSTLSCertTrustedCA{
Filename: "mycert.crt",
},
},
},
},
},
},
},
},
},
})
},
},
{
name: "custom-local-app",
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
Expand Down Expand Up @@ -1235,3 +1293,103 @@ func TestParseJWTRemoteURL(t *testing.T) {
func UID(input string) proxycfg.UpstreamID {
return proxycfg.UpstreamIDFromString(input)
}

func TestMakeJWTCertValidationContext(t *testing.T) {
tests := map[string]struct {
jwksCluster *structs.JWKSCluster
expected *envoy_tls_v3.CertificateValidationContext
}{
"when nil": {
jwksCluster: nil,
expected: &envoy_tls_v3.CertificateValidationContext{},
},
"when trustedCA with filename": {
jwksCluster: &structs.JWKSCluster{
TLSCertificates: &structs.JWKSTLSCertificate{
TrustedCA: &structs.JWKSTLSCertTrustedCA{
Filename: "file.crt",
},
},
},
expected: &envoy_tls_v3.CertificateValidationContext{
TrustedCa: &envoy_core_v3.DataSource{
Specifier: &envoy_core_v3.DataSource_Filename{
Filename: "file.crt",
},
},
},
},
"when trustedCA with environment variable": {
jwksCluster: &structs.JWKSCluster{
TLSCertificates: &structs.JWKSTLSCertificate{
TrustedCA: &structs.JWKSTLSCertTrustedCA{
EnvironmentVariable: "MY_ENV",
},
},
},
expected: &envoy_tls_v3.CertificateValidationContext{
TrustedCa: &envoy_core_v3.DataSource{
Specifier: &envoy_core_v3.DataSource_EnvironmentVariable{
EnvironmentVariable: "MY_ENV",
},
},
},
},
"when trustedCA with inline string": {
jwksCluster: &structs.JWKSCluster{
TLSCertificates: &structs.JWKSTLSCertificate{
TrustedCA: &structs.JWKSTLSCertTrustedCA{
InlineString: "<my ca cert>",
},
},
},
expected: &envoy_tls_v3.CertificateValidationContext{
TrustedCa: &envoy_core_v3.DataSource{
Specifier: &envoy_core_v3.DataSource_InlineString{
InlineString: "<my ca cert>",
},
},
},
},
"when trustedCA with inline bytes": {
jwksCluster: &structs.JWKSCluster{
TLSCertificates: &structs.JWKSTLSCertificate{
TrustedCA: &structs.JWKSTLSCertTrustedCA{
InlineBytes: []byte{1, 2, 3},
},
},
},
expected: &envoy_tls_v3.CertificateValidationContext{
TrustedCa: &envoy_core_v3.DataSource{
Specifier: &envoy_core_v3.DataSource_InlineBytes{
InlineBytes: []byte{1, 2, 3},
},
},
},
},
"when caCertificateProviderInstance": {
jwksCluster: &structs.JWKSCluster{
TLSCertificates: &structs.JWKSTLSCertificate{
CaCertificateProviderInstance: &structs.JWKSTLSCertProviderInstance{
InstanceName: "<my-instance-name>",
CertificateName: "<my-cert>.crt",
},
},
},
expected: &envoy_tls_v3.CertificateValidationContext{
CaCertificateProviderInstance: &envoy_tls_v3.CertificateProviderPluginInstance{
InstanceName: "<my-instance-name>",
CertificateName: "<my-cert>.crt",
},
},
},
}
for name, tt := range tests {
tt := tt
t.Run(name, func(t *testing.T) {
vc := makeJWTCertValidationContext(tt.jwksCluster)

require.Equal(t, tt.expected, vc)
})
}
}
59 changes: 59 additions & 0 deletions agent/xds/listeners_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,65 @@ func makeListenerDiscoChainTests(enterprise bool) []listenerTestCase {
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", enterprise, nil, nil)
},
},
{
name: "connect-proxy-with-jwt-config-entry-with-local",
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, func(ns *structs.NodeService) {
ns.Proxy.Config["protocol"] = "http"
},
[]proxycfg.UpdateEvent{
{
CorrelationID: "jwt-provider",
Result: &structs.IndexedConfigEntries{
Kind: "jwt-provider",
Entries: []structs.ConfigEntry{
&structs.JWTProviderConfigEntry{
Name: "okta",
JSONWebKeySet: &structs.JSONWebKeySet{
Local: &structs.LocalJWKS{
JWKS: "aGVsbG8gd29ybGQK",
},
},
Locations: []*structs.JWTLocation{
{
QueryParam: &structs.JWTLocationQueryParam{
Name: "token",
},
},
{
Cookie: &structs.JWTLocationCookie{
Name: "token",
},
},
},
},
},
},
},
{
CorrelationID: "intentions",
Result: structs.SimplifiedIntentions{
{
SourceName: "*",
DestinationName: "db",
Permissions: []*structs.IntentionPermission{
{
JWT: &structs.IntentionJWTRequirement{
Providers: []*structs.IntentionJWTProvider{
{
Name: "okta",
},
},
},
},
},
},
},
},
},
)
},
},
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
{
"versionInfo": "00000001",
"resources": [
{
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"type": "EDS",
"edsClusterConfig": {
"edsConfig": {
"ads": {

},
"resourceApiVersion": "V3"
}
},
"connectTimeout": "5s",
"circuitBreakers": {

},
"outlierDetection": {

},
"commonLbConfig": {
"healthyPanicThreshold": {

}
},
"transportSocket": {
"name": "tls",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
"commonTlsContext": {
"tlsParams": {

},
"tlsCertificates": [
{
"certificateChain": {
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
},
"privateKey": {
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
}
}
],
"validationContext": {
"trustedCa": {
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
},
"matchSubjectAltNames": [
{
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db"
}
]
}
},
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
}
}
},
{
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
"type": "EDS",
"edsClusterConfig": {
"edsConfig": {
"ads": {

},
"resourceApiVersion": "V3"
}
},
"connectTimeout": "5s",
"circuitBreakers": {

},
"outlierDetection": {

},
"transportSocket": {
"name": "tls",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
"commonTlsContext": {
"tlsParams": {

},
"tlsCertificates": [
{
"certificateChain": {
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
},
"privateKey": {
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
}
}
],
"validationContext": {
"trustedCa": {
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
},
"matchSubjectAltNames": [
{
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target"
},
{
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target"
}
]
}
},
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
}
}
},
{
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
"name": "local_app",
"type": "STATIC",
"connectTimeout": "5s",
"loadAssignment": {
"clusterName": "local_app",
"endpoints": [
{
"lbEndpoints": [
{
"endpoint": {
"address": {
"socketAddress": {
"address": "127.0.0.1",
"portValue": 8080
}
}
}
}
]
}
]
}
}
],
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
"nonce": "00000001"
}
Loading

0 comments on commit 18db062

Please sign in to comment.