1f1b6c884e
- Also reduce the minimum allowed TLS version to v1.2, because v1.3 is not yet supported by some common clients, e.g. the default MacOS curl command
102 lines
3.3 KiB
Go
102 lines
3.3 KiB
Go
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package integration
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gopkg.in/square/go-jose.v2"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
configv1alpha1 "go.pinniped.dev/generated/1.19/apis/config/v1alpha1"
|
|
"go.pinniped.dev/test/library"
|
|
)
|
|
|
|
func TestSupervisorOIDCKeys(t *testing.T) {
|
|
env := library.IntegrationEnv(t)
|
|
kubeClient := library.NewClientset(t)
|
|
pinnipedClient := library.NewPinnipedClientset(t)
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
|
defer cancel()
|
|
|
|
// Create our OPC under test.
|
|
opc := library.CreateTestOIDCProvider(ctx, t, "", "")
|
|
|
|
// Ensure a secret is created with the OPC's JWKS.
|
|
var updatedOPC *configv1alpha1.OIDCProviderConfig
|
|
var err error
|
|
assert.Eventually(t, func() bool {
|
|
updatedOPC, err = pinnipedClient.
|
|
ConfigV1alpha1().
|
|
OIDCProviderConfigs(env.SupervisorNamespace).
|
|
Get(ctx, opc.Name, metav1.GetOptions{})
|
|
return err == nil && updatedOPC.Status.JWKSSecret.Name != ""
|
|
}, time.Second*10, time.Millisecond*500)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, updatedOPC.Status.JWKSSecret.Name)
|
|
|
|
// Ensure the secret actually exists.
|
|
secret, err := kubeClient.
|
|
CoreV1().
|
|
Secrets(env.SupervisorNamespace).
|
|
Get(ctx, updatedOPC.Status.JWKSSecret.Name, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
|
|
// Ensure that the secret was labelled.
|
|
for k, v := range env.SupervisorCustomLabels {
|
|
require.Equalf(t, v, secret.Labels[k], "expected secret to have label `%s: %s`", k, v)
|
|
}
|
|
require.Equal(t, env.SupervisorAppName, secret.Labels["app"])
|
|
|
|
// Ensure the secret has an active key.
|
|
jwkData, ok := secret.Data["activeJWK"]
|
|
require.True(t, ok, "secret is missing active jwk")
|
|
|
|
// Ensure the secret's active key is valid.
|
|
var activeJWK jose.JSONWebKey
|
|
require.NoError(t, json.Unmarshal(jwkData, &activeJWK))
|
|
require.True(t, activeJWK.Valid(), "active jwk is invalid")
|
|
require.False(t, activeJWK.IsPublic(), "active jwk is public")
|
|
|
|
// Ensure the secret has a JWKS.
|
|
jwksData, ok := secret.Data["jwks"]
|
|
require.True(t, ok, "secret is missing jwks")
|
|
|
|
// Ensure the secret's JWKS is valid, public, and contains the singing key.
|
|
var jwks jose.JSONWebKeySet
|
|
require.NoError(t, json.Unmarshal(jwksData, &jwks))
|
|
foundActiveJWK := false
|
|
for _, jwk := range jwks.Keys {
|
|
require.Truef(t, jwk.Valid(), "jwk %s is invalid", jwk.KeyID)
|
|
require.Truef(t, jwk.IsPublic(), "jwk %s is not public", jwk.KeyID)
|
|
if jwk.KeyID == activeJWK.KeyID {
|
|
foundActiveJWK = true
|
|
}
|
|
}
|
|
require.True(t, foundActiveJWK, "could not find active JWK in JWKS: %s", jwks)
|
|
|
|
// Ensure upon deleting the secret, it is eventually brought back.
|
|
err = kubeClient.
|
|
CoreV1().
|
|
Secrets(env.SupervisorNamespace).
|
|
Delete(ctx, updatedOPC.Status.JWKSSecret.Name, metav1.DeleteOptions{})
|
|
require.NoError(t, err)
|
|
assert.Eventually(t, func() bool {
|
|
secret, err = kubeClient.
|
|
CoreV1().
|
|
Secrets(env.SupervisorNamespace).
|
|
Get(ctx, updatedOPC.Status.JWKSSecret.Name, metav1.GetOptions{})
|
|
return err == nil
|
|
}, time.Second*10, time.Millisecond*500)
|
|
require.NoError(t, err)
|
|
|
|
// Upon deleting the OPC, the secret is deleted (we test this behavior in our uninstall tests).
|
|
}
|