2022-06-17 16:56:53 +00:00
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package oidcclientsecretstorage
import (
2022-09-08 15:41:48 +00:00
"context"
"errors"
2022-06-17 16:56:53 +00:00
"testing"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2022-09-08 15:41:48 +00:00
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
coretesting "k8s.io/client-go/testing"
2022-07-14 16:51:11 +00:00
"go.pinniped.dev/internal/testutil"
2022-06-17 16:56:53 +00:00
)
2022-09-08 15:41:48 +00:00
func TestGet ( t * testing . T ) {
tests := [ ] struct {
name string
uid types . UID
secret * corev1 . Secret
wantRV string
wantHashes [ ] string
wantErr string
} {
{
name : "happy path" ,
uid : types . UID ( "some-example-uid1" ) ,
secret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Namespace : "some-namespace" ,
UID : "" ,
ResourceVersion : "123" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` {
"hashes" : [ "foo" , "bar" ] ,
"version" : "1"
} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
} ,
wantRV : "123" ,
wantHashes : [ ] string { "foo" , "bar" } ,
} ,
{
name : "incorrect storage version: Data.pinniped-storage-version does not match crud storage version value" ,
uid : types . UID ( "some-example-uid1" ) ,
secret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Namespace : "some-namespace" ,
UID : "" ,
ResourceVersion : "123" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` {
"hashes" : [ "orcs" , "goblins" ] ,
"version" : "1"
} ` ) ,
"pinniped-storage-version" : [ ] byte ( "9999999999" ) ,
} ,
} ,
wantRV : "" ,
wantHashes : [ ] string ( nil ) ,
wantErr : "failed to get client secret for uid some-example-uid1: error during get for signature c29tZS1leGFtcGxlLXVpZDE: secret storage data has incorrect version" ,
} ,
{
name : "incorrect storage version: Data.pinniped-storage-data.version does not match package const oidcClientSecretStorageVersion" ,
uid : types . UID ( "some-example-uid1" ) ,
secret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Namespace : "some-namespace" ,
UID : "" ,
ResourceVersion : "123" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` {
"hashes" : [ "orcs" , "goblins" ] ,
"version" : "9999999999"
} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
} ,
wantRV : "" ,
wantHashes : [ ] string ( nil ) ,
wantErr : "OIDC client secret storage data has wrong version: OIDC client secret storage has version 9999999999 instead of 1" ,
} , {
name : "not found" ,
uid : types . UID ( "some-example-uid1" ) ,
secret : nil ,
wantRV : "" ,
wantHashes : nil ,
} ,
}
for _ , tt := range tests {
tt := tt
t . Run ( tt . name , func ( t * testing . T ) {
t . Parallel ( )
kubeClient := fake . NewSimpleClientset ( )
if tt . secret != nil {
require . NoError ( t , kubeClient . Tracker ( ) . Add ( tt . secret ) )
}
subject := New ( kubeClient . CoreV1 ( ) . Secrets ( "some-namespace" ) )
rv , secretHashes , err := subject . Get ( context . Background ( ) , tt . uid )
if tt . wantErr == "" {
require . NoError ( t , err )
} else {
require . EqualError ( t , err , tt . wantErr )
}
require . Equal ( t , tt . wantRV , rv )
require . Equal ( t , tt . wantHashes , secretHashes )
} )
}
}
func TestSet ( t * testing . T ) {
secretsGVR := schema . GroupVersionResource {
Group : "" ,
Version : "v1" ,
Resource : "secrets" ,
}
namespace := "some-namespace"
tests := [ ] struct {
name string
rv string
oidcClientName string
oidcClientUID types . UID
hashes [ ] string
seedSecret * corev1 . Secret
addReactors func ( * fake . Clientset )
wantErr string
wantActions [ ] coretesting . Action
} {
{
name : "happy path: new secret" ,
oidcClientName : "some-client" ,
oidcClientUID : types . UID ( "some-example-uid1" ) ,
hashes : [ ] string { "foo" } ,
seedSecret : nil ,
wantActions : [ ] coretesting . Action {
coretesting . NewCreateAction ( secretsGVR , namespace , & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
OwnerReferences : [ ] metav1 . OwnerReference { {
APIVersion : "config.supervisor.pinniped.dev/v1alpha1" ,
Kind : "OIDCClient" ,
Name : "some-client" ,
UID : "some-example-uid1" ,
} } ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["foo"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
} ) ,
} ,
} ,
{
name : "happy path: update existing secret and maintains existing owner reference" ,
rv : "9999" ,
oidcClientName : "some-client" ,
oidcClientUID : types . UID ( "some-example-uid1" ) ,
hashes : [ ] string { "foo" , "bar" } ,
seedSecret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Namespace : namespace ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
ResourceVersion : "9999" ,
OwnerReferences : [ ] metav1 . OwnerReference { {
APIVersion : "config.supervisor.pinniped.dev/v1alpha1" ,
Kind : "OIDCClient" ,
Name : "some-client" ,
UID : "some-example-uid1" ,
} } ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["foo"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
} ,
wantActions : [ ] coretesting . Action {
coretesting . NewGetAction ( secretsGVR , namespace , "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ) ,
coretesting . NewUpdateAction ( secretsGVR , namespace , & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
ResourceVersion : "9999" ,
OwnerReferences : [ ] metav1 . OwnerReference { {
APIVersion : "config.supervisor.pinniped.dev/v1alpha1" ,
Kind : "OIDCClient" ,
Name : "some-client" ,
UID : "some-example-uid1" ,
} } ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["foo","bar"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
} ) ,
} ,
} ,
{
name : "failed to create client secret" ,
oidcClientName : "some-client" ,
oidcClientUID : types . UID ( "some-example-uid1" ) ,
hashes : [ ] string { "foo" , "bar" } ,
addReactors : func ( clientSet * fake . Clientset ) {
clientSet . PrependReactor ( "create" , "secrets" , func ( action coretesting . Action ) ( bool , runtime . Object , error ) {
return true , nil , errors . New ( "some create error" )
} )
} ,
wantActions : [ ] coretesting . Action {
coretesting . NewCreateAction ( secretsGVR , namespace , & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
OwnerReferences : [ ] metav1 . OwnerReference { {
APIVersion : "config.supervisor.pinniped.dev/v1alpha1" ,
Kind : "OIDCClient" ,
Name : "some-client" ,
UID : "some-example-uid1" ,
} } ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["foo","bar"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
} ) ,
} ,
wantErr : "failed to create client secret for uid some-example-uid1: failed to create oidc-client-secret for signature c29tZS1leGFtcGxlLXVpZDE: some create error" ,
} ,
{
name : "failed to update" ,
rv : "23" ,
oidcClientName : "some-client" ,
oidcClientUID : types . UID ( "some-example-uid1" ) ,
hashes : [ ] string { "foo" , "bar" } ,
seedSecret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Namespace : namespace ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
ResourceVersion : "23" ,
OwnerReferences : [ ] metav1 . OwnerReference { {
APIVersion : "config.supervisor.pinniped.dev/v1alpha1" ,
Kind : "OIDCClient" ,
Name : "some-client" ,
UID : "some-example-uid1" ,
} } ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["foo"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
} ,
addReactors : func ( clientSet * fake . Clientset ) {
clientSet . PrependReactor ( "update" , "secrets" , func ( action coretesting . Action ) ( bool , runtime . Object , error ) {
2022-09-15 20:33:54 +00:00
return true , nil , errors . New ( "some update error maybe a conflict or something else" )
2022-09-08 15:41:48 +00:00
} )
} ,
wantActions : [ ] coretesting . Action {
coretesting . NewGetAction ( secretsGVR , namespace , "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ) ,
coretesting . NewUpdateAction ( secretsGVR , namespace , & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
ResourceVersion : "23" ,
OwnerReferences : [ ] metav1 . OwnerReference { {
APIVersion : "config.supervisor.pinniped.dev/v1alpha1" ,
Kind : "OIDCClient" ,
Name : "some-client" ,
UID : "some-example-uid1" ,
} } ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["foo","bar"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
} ) ,
} ,
2022-09-15 20:33:54 +00:00
wantErr : "failed to update client secret for uid some-example-uid1: failed to update oidc-client-secret for signature c29tZS1leGFtcGxlLXVpZDE at resource version 23: some update error maybe a conflict or something else" ,
2022-09-08 15:41:48 +00:00
} ,
}
for _ , tt := range tests {
tt := tt
t . Run ( tt . name , func ( t * testing . T ) {
t . Parallel ( )
kubeClient := fake . NewSimpleClientset ( )
if tt . seedSecret != nil {
require . NoError ( t , kubeClient . Tracker ( ) . Add ( tt . seedSecret ) )
}
if tt . addReactors != nil {
tt . addReactors ( kubeClient )
}
subject := New ( kubeClient . CoreV1 ( ) . Secrets ( "some-namespace" ) )
err := subject . Set (
context . Background ( ) ,
tt . rv ,
tt . oidcClientName ,
tt . oidcClientUID ,
tt . hashes ,
)
if tt . wantErr == "" {
require . NoError ( t , err )
} else {
require . EqualError ( t , err , tt . wantErr )
}
require . Equal ( t , tt . wantActions , kubeClient . Actions ( ) )
} )
}
}
func TestGetStorageSecret ( t * testing . T ) {
tests := [ ] struct {
name string
uid types . UID
secret * corev1 . Secret
wantSecret * corev1 . Secret
wantErr string
} {
{
name : "happy path" ,
uid : types . UID ( "some-example-uid1" ) ,
secret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Namespace : "some-namespace" ,
} ,
Data : map [ string ] [ ] byte {
"foo" : [ ] byte ( "bar" ) ,
} ,
} ,
wantSecret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
Namespace : "some-namespace" ,
} ,
Data : map [ string ] [ ] byte {
"foo" : [ ] byte ( "bar" ) ,
} ,
} ,
wantErr : "" ,
} ,
}
for _ , tt := range tests {
tt := tt
t . Run ( tt . name , func ( t * testing . T ) {
t . Parallel ( )
kubeClient := fake . NewSimpleClientset ( )
require . NoError ( t , kubeClient . Tracker ( ) . Add ( tt . secret ) )
subject := New ( kubeClient . CoreV1 ( ) . Secrets ( "some-namespace" ) )
secret , err := subject . GetStorageSecret ( context . Background ( ) , tt . uid )
require . Equal ( t , tt . wantSecret , secret )
if tt . wantErr == "" {
require . NoError ( t , err )
} else {
require . EqualError ( t , err , tt . wantErr )
}
} )
}
}
2022-06-17 16:56:53 +00:00
func TestGetName ( t * testing . T ) {
// Note that GetName() should not depend on the constructor params, to make it easier to use in various contexts.
2022-08-26 17:57:45 +00:00
subject := New ( nil )
2022-06-17 16:56:53 +00:00
require . Equal ( t ,
"pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqyq" ,
subject . GetName ( "some-example-uid1" ) )
require . Equal ( t ,
"pinniped-storage-oidc-client-secret-onxw2zjnmv4gc3lqnrss25ljmqza" ,
subject . GetName ( "some-example-uid2" ) )
}
func TestReadFromSecret ( t * testing . T ) {
tests := [ ] struct {
name string
secret * corev1 . Secret
2022-08-26 17:57:45 +00:00
wantHashes [ ] string
2022-06-17 16:56:53 +00:00
wantErr string
} {
{
name : "happy path" ,
secret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-pwu5zs7lekbhnln2w4" ,
ResourceVersion : "" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
} ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["first-hash","second-hash"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
} ,
2022-08-26 17:57:45 +00:00
wantHashes : [ ] string { "first-hash" , "second-hash" } ,
2022-06-17 16:56:53 +00:00
} ,
{
name : "wrong secret type" ,
secret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-pwu5zs7lekbhnln2w4" ,
ResourceVersion : "" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
} ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["first-hash","second-hash"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
Type : "storage.pinniped.dev/not-oidc-client-secret" ,
} ,
wantErr : "secret storage data has incorrect type: storage.pinniped.dev/not-oidc-client-secret must equal storage.pinniped.dev/oidc-client-secret" ,
} ,
{
name : "wrong stored StoredClientSecret version" ,
secret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-pwu5zs7lekbhnln2w4" ,
ResourceVersion : "" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
} ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["first-hash","second-hash"],"version":"wrong-version-here"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "1" ) ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
} ,
wantErr : "OIDC client secret storage data has wrong version: OIDC client secret storage has version wrong-version-here instead of 1" ,
} ,
{
name : "wrong storage version" ,
secret : & corev1 . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "pinniped-storage-oidc-client-secret-pwu5zs7lekbhnln2w4" ,
ResourceVersion : "" ,
Labels : map [ string ] string {
"storage.pinniped.dev/type" : "oidc-client-secret" ,
} ,
} ,
Data : map [ string ] [ ] byte {
"pinniped-storage-data" : [ ] byte ( ` { "hashes":["first-hash","second-hash"],"version":"1"} ` ) ,
"pinniped-storage-version" : [ ] byte ( "wrong-version-here" ) ,
} ,
Type : "storage.pinniped.dev/oidc-client-secret" ,
} ,
wantErr : "secret storage data has incorrect version" ,
} ,
2022-07-14 16:51:11 +00:00
{
name : "OIDCClientSecretStorageSecretForUID() test helper generates readable format, to ensure that test helpers are kept up to date" ,
secret : testutil . OIDCClientSecretStorageSecretForUID ( t ,
"some-namespace" , "some-uid" , [ ] string { "first-hash" , "second-hash" } ,
) ,
2022-08-26 17:57:45 +00:00
wantHashes : [ ] string { "first-hash" , "second-hash" } ,
2022-07-14 16:51:11 +00:00
} ,
{
name : "OIDCClientSecretStorageSecretWithoutName() test helper generates readable format, to ensure that test helpers are kept up to date" ,
secret : testutil . OIDCClientSecretStorageSecretWithoutName ( t ,
"some-namespace" , [ ] string { "first-hash" , "second-hash" } ,
) ,
2022-08-26 17:57:45 +00:00
wantHashes : [ ] string { "first-hash" , "second-hash" } ,
2022-07-14 16:51:11 +00:00
} ,
{
name : "OIDCClientSecretStorageSecretForUIDWithWrongVersion() test helper generates readable format, to ensure that test helpers are kept up to date" ,
secret : testutil . OIDCClientSecretStorageSecretForUIDWithWrongVersion ( t , "some-namespace" , "some-uid" ) ,
wantErr : "OIDC client secret storage data has wrong version: OIDC client secret storage has version wrong-version instead of 1" ,
} ,
2022-06-17 16:56:53 +00:00
}
for _ , tt := range tests {
tt := tt
t . Run ( tt . name , func ( t * testing . T ) {
t . Parallel ( )
2022-08-26 17:57:45 +00:00
hashes , err := ReadFromSecret ( tt . secret )
2022-06-17 16:56:53 +00:00
if tt . wantErr == "" {
require . NoError ( t , err )
2022-08-26 17:57:45 +00:00
require . Equal ( t , tt . wantHashes , hashes )
2022-06-17 16:56:53 +00:00
} else {
require . EqualError ( t , err , tt . wantErr )
2022-08-26 17:57:45 +00:00
require . Nil ( t , hashes )
2022-06-17 16:56:53 +00:00
}
} )
}
}