WIP passing lifetime through to storage, unit tests are failing

Signed-off-by: Ryan Richard <rrichard@vmware.com>
This commit is contained in:
Margo Crawford 2020-12-10 12:15:40 -08:00 committed by Ryan Richard
parent c001bb876e
commit b0c354637d
9 changed files with 183 additions and 22 deletions

View File

@ -11,6 +11,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings" "strings"
"time"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -22,7 +23,8 @@ import (
//nolint:gosec // ignore lint warnings that these are credentials //nolint:gosec // ignore lint warnings that these are credentials
const ( const (
SecretLabelKey = "storage.pinniped.dev/type" SecretLabelKey = "storage.pinniped.dev/type"
SecretLifetimeAnnotationKey = "storage.pinniped.dev/garbage-collect-after"
secretNameFormat = "pinniped-storage-%s-%s" secretNameFormat = "pinniped-storage-%s-%s"
secretTypeFormat = "storage.pinniped.dev/%s" secretTypeFormat = "storage.pinniped.dev/%s"
@ -45,12 +47,14 @@ type Storage interface {
type JSON interface{} // document that we need valid JSON types type JSON interface{} // document that we need valid JSON types
func New(resource string, secrets corev1client.SecretInterface) Storage { func New(resource string, secrets corev1client.SecretInterface, clock func() time.Time, lifetime time.Duration) Storage {
return &secretsStorage{ return &secretsStorage{
resource: resource, resource: resource,
secretType: corev1.SecretType(fmt.Sprintf(secretTypeFormat, resource)), secretType: corev1.SecretType(fmt.Sprintf(secretTypeFormat, resource)),
secretVersion: []byte(secretVersion), secretVersion: []byte(secretVersion),
secrets: secrets, secrets: secrets,
clock: clock,
lifetime: lifetime,
} }
} }
@ -59,6 +63,8 @@ type secretsStorage struct {
secretType corev1.SecretType secretType corev1.SecretType
secretVersion []byte secretVersion []byte
secrets corev1client.SecretInterface secrets corev1client.SecretInterface
clock func() time.Time
lifetime time.Duration
} }
func (s *secretsStorage) Create(ctx context.Context, signature string, data JSON, additionalLabels map[string]string) (string, error) { func (s *secretsStorage) Create(ctx context.Context, signature string, data JSON, additionalLabels map[string]string) (string, error) {
@ -162,12 +168,16 @@ func (s *secretsStorage) toSecret(signature, resourceVersion string, data JSON,
for labelName, labelValue := range additionalLabels { for labelName, labelValue := range additionalLabels {
labels[labelName] = labelValue labels[labelName] = labelValue
} }
annotations := map[string]string{
SecretLifetimeAnnotationKey: s.clock().Add(s.lifetime).UTC().String(),
}
return &corev1.Secret{ return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: s.getName(signature), Name: s.getName(signature),
ResourceVersion: resourceVersion, ResourceVersion: resourceVersion,
Labels: labels, Labels: labels,
Annotations: annotations,
OwnerReferences: nil, OwnerReferences: nil,
}, },
Data: map[string][]byte{ Data: map[string][]byte{

View File

@ -8,6 +8,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"testing" "testing"
"time"
"github.com/ory/fosite/compose" "github.com/ory/fosite/compose"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -45,6 +46,9 @@ func TestStorage(t *testing.T) {
validateSecretName := validation.NameIsDNSSubdomain // matches k/k validateSecretName := validation.NameIsDNSSubdomain // matches k/k
var fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC)
var fakeDuration = time.Minute * 10
const ( const (
namespace = "test-ns" namespace = "test-ns"
authorizationCode1 = "81qE408EKL-e99gcXo3UnXBz9W05yGm92_hBmvXeadM.R5h38Bmw7yOaWNy0ypB3feh9toM-3T2zlwMXQyeE9B0" authorizationCode1 = "81qE408EKL-e99gcXo3UnXBz9W05yGm92_hBmvXeadM.R5h38Bmw7yOaWNy0ypB3feh9toM-3T2zlwMXQyeE9B0"
@ -119,6 +123,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "access-tokens", "storage.pinniped.dev/type": "access-tokens",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"create-and-get"}`), "pinniped-storage-data": []byte(`{"Data":"create-and-get"}`),
@ -137,6 +146,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "access-tokens", "storage.pinniped.dev/type": "access-tokens",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"create-and-get"}`), "pinniped-storage-data": []byte(`{"Data":"create-and-get"}`),
@ -179,6 +193,11 @@ func TestStorage(t *testing.T) {
"label1": "value1", "label1": "value1",
"label2": "value2", "label2": "value2",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"create-and-get"}`), "pinniped-storage-data": []byte(`{"Data":"create-and-get"}`),
@ -199,6 +218,11 @@ func TestStorage(t *testing.T) {
"label1": "value1", "label1": "value1",
"label2": "value2", "label2": "value2",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"create-and-get"}`), "pinniped-storage-data": []byte(`{"Data":"create-and-get"}`),
@ -221,6 +245,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "pandas-are-best", "storage.pinniped.dev/type": "pandas-are-best",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"snorlax"}`), "pinniped-storage-data": []byte(`{"Data":"snorlax"}`),
@ -256,6 +285,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "pandas-are-best", "storage.pinniped.dev/type": "pandas-are-best",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"snorlax"}`), "pinniped-storage-data": []byte(`{"Data":"snorlax"}`),
@ -278,6 +312,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "stores", "storage.pinniped.dev/type": "stores",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"pants"}`), "pinniped-storage-data": []byte(`{"Data":"pants"}`),
@ -327,6 +366,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "stores", "storage.pinniped.dev/type": "stores",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"shirts"}`), "pinniped-storage-data": []byte(`{"Data":"shirts"}`),
@ -345,6 +389,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "stores", "storage.pinniped.dev/type": "stores",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"shirts"}`), "pinniped-storage-data": []byte(`{"Data":"shirts"}`),
@ -367,6 +416,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "seals", "storage.pinniped.dev/type": "seals",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"sad-seal"}`), "pinniped-storage-data": []byte(`{"Data":"sad-seal"}`),
@ -402,6 +456,11 @@ func TestStorage(t *testing.T) {
"storage.pinniped.dev/type": "seals", "storage.pinniped.dev/type": "seals",
"additionalLabel": "matching-value", "additionalLabel": "matching-value",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"sad-seal"}`), "pinniped-storage-data": []byte(`{"Data":"sad-seal"}`),
@ -418,6 +477,11 @@ func TestStorage(t *testing.T) {
"storage.pinniped.dev/type": "seals", "storage.pinniped.dev/type": "seals",
"additionalLabel": "matching-value", "additionalLabel": "matching-value",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"happy-seal"}`), "pinniped-storage-data": []byte(`{"Data":"happy-seal"}`),
@ -434,6 +498,11 @@ func TestStorage(t *testing.T) {
"storage.pinniped.dev/type": "seals", // same type as above "storage.pinniped.dev/type": "seals", // same type as above
"additionalLabel": "non-matching-value", // different value for the same label "additionalLabel": "non-matching-value", // different value for the same label
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"sad-seal2"}`), "pinniped-storage-data": []byte(`{"Data":"sad-seal2"}`),
@ -450,6 +519,11 @@ func TestStorage(t *testing.T) {
"storage.pinniped.dev/type": "walruses", // different type from above "storage.pinniped.dev/type": "walruses", // different type from above
"additionalLabel": "matching-value", // same value for the same label as above "additionalLabel": "matching-value", // same value for the same label as above
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"sad-seal3"}`), "pinniped-storage-data": []byte(`{"Data":"sad-seal3"}`),
@ -479,6 +553,11 @@ func TestStorage(t *testing.T) {
"storage.pinniped.dev/type": "seals", // same type as above "storage.pinniped.dev/type": "seals", // same type as above
"additionalLabel": "non-matching-value", // different value for the same label "additionalLabel": "non-matching-value", // different value for the same label
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"sad-seal2"}`), "pinniped-storage-data": []byte(`{"Data":"sad-seal2"}`),
@ -496,6 +575,11 @@ func TestStorage(t *testing.T) {
"storage.pinniped.dev/type": "walruses", // different type from above "storage.pinniped.dev/type": "walruses", // different type from above
"additionalLabel": "matching-value", // same value for the same label as above "additionalLabel": "matching-value", // same value for the same label as above
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"sad-seal3"}`), "pinniped-storage-data": []byte(`{"Data":"sad-seal3"}`),
@ -519,6 +603,11 @@ func TestStorage(t *testing.T) {
"storage.pinniped.dev/type": "seals", "storage.pinniped.dev/type": "seals",
"additionalLabel": "matching-value", "additionalLabel": "matching-value",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"sad-seal"}`), "pinniped-storage-data": []byte(`{"Data":"sad-seal"}`),
@ -549,6 +638,11 @@ func TestStorage(t *testing.T) {
"storage.pinniped.dev/type": "seals", "storage.pinniped.dev/type": "seals",
"additionalLabel": "matching-value", "additionalLabel": "matching-value",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"sad-seal"}`), "pinniped-storage-data": []byte(`{"Data":"sad-seal"}`),
@ -602,6 +696,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "candies", "storage.pinniped.dev/type": "candies",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"twizzlers"}`), "pinniped-storage-data": []byte(`{"Data":"twizzlers"}`),
@ -637,6 +736,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "candies", "storage.pinniped.dev/type": "candies",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"twizzlers"}`), "pinniped-storage-data": []byte(`{"Data":"twizzlers"}`),
@ -659,6 +763,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "candies-are-bad", "storage.pinniped.dev/type": "candies-are-bad",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"twizzlers"}`), "pinniped-storage-data": []byte(`{"Data":"twizzlers"}`),
@ -694,6 +803,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "candies-are-bad", "storage.pinniped.dev/type": "candies-are-bad",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"twizzlers"}`), "pinniped-storage-data": []byte(`{"Data":"twizzlers"}`),
@ -716,6 +830,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "candies", "storage.pinniped.dev/type": "candies",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"twizzlers"}`), "pinniped-storage-data": []byte(`{"Data":"twizzlers"}`),
@ -751,6 +870,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "candies", "storage.pinniped.dev/type": "candies",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"Data":"twizzlers"}`), "pinniped-storage-data": []byte(`{"Data":"twizzlers"}`),
@ -773,6 +897,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "candies", "storage.pinniped.dev/type": "candies",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`}}bad data{{`), "pinniped-storage-data": []byte(`}}bad data{{`),
@ -807,6 +936,11 @@ func TestStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "candies", "storage.pinniped.dev/type": "candies",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`}}bad data{{`), "pinniped-storage-data": []byte(`}}bad data{{`),
@ -828,7 +962,7 @@ func TestStorage(t *testing.T) {
tt.mocks(t, client) tt.mocks(t, client)
} }
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(tt.resource, secrets) storage := New(tt.resource, secrets, func() time.Time { return fakeNow }, fakeDuration)
err := tt.run(t, storage) err := tt.run(t, storage)

View File

@ -7,6 +7,7 @@ import (
"context" "context"
stderrors "errors" stderrors "errors"
"fmt" "fmt"
"time"
"github.com/ory/fosite" "github.com/ory/fosite"
"github.com/ory/fosite/handler/oauth2" "github.com/ory/fosite/handler/oauth2"
@ -40,8 +41,8 @@ type AuthorizeCodeSession struct {
Version string `json:"version"` Version string `json:"version"`
} }
func New(secrets corev1client.SecretInterface) oauth2.AuthorizeCodeStorage { func New(secrets corev1client.SecretInterface, clock func() time.Time, sessionStorageLifetime time.Duration) oauth2.AuthorizeCodeStorage {
return &authorizeCodeStorage{storage: crud.New(TypeLabelValue, secrets)} return &authorizeCodeStorage{storage: crud.New(TypeLabelValue, secrets, clock, sessionStorageLifetime)}
} }
func (a *authorizeCodeStorage) CreateAuthorizeCodeSession(ctx context.Context, signature string, requester fosite.Requester) error { func (a *authorizeCodeStorage) CreateAuthorizeCodeSession(ctx context.Context, signature string, requester fosite.Requester) error {

View File

@ -35,6 +35,9 @@ import (
const namespace = "test-ns" const namespace = "test-ns"
var fakeNow = time.Date(2030, time.January, 1, 0, 0, 0, 0, time.UTC)
var fakeDuration = time.Minute * 10
func TestAuthorizationCodeStorage(t *testing.T) { func TestAuthorizationCodeStorage(t *testing.T) {
ctx := context.Background() ctx := context.Background()
secretsGVR := schema.GroupVersionResource{ secretsGVR := schema.GroupVersionResource{
@ -51,6 +54,11 @@ func TestAuthorizationCodeStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "authcode", "storage.pinniped.dev/type": "authcode",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"active":true,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`), "pinniped-storage-data": []byte(`{"active":true,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
@ -67,6 +75,11 @@ func TestAuthorizationCodeStorage(t *testing.T) {
Labels: map[string]string{ Labels: map[string]string{
"storage.pinniped.dev/type": "authcode", "storage.pinniped.dev/type": "authcode",
}, },
Annotations: map[string]string{
"storage.pinniped.dev/garbage-collect-after": metav1.Time{
Time: fakeNow.Add(fakeDuration),
}.String(),
},
}, },
Data: map[string][]byte{ Data: map[string][]byte{
"pinniped-storage-data": []byte(`{"active":false,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`), "pinniped-storage-data": []byte(`{"active":false,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"requestedAudience":null,"grantedAudience":null},"version":"1"}`),
@ -78,7 +91,7 @@ func TestAuthorizationCodeStorage(t *testing.T) {
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
request := &fosite.Request{ request := &fosite.Request{
ID: "abcd-1", ID: "abcd-1",
@ -136,7 +149,7 @@ func TestGetNotFound(t *testing.T) {
ctx := context.Background() ctx := context.Background()
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
_, notFoundErr := storage.GetAuthorizeCodeSession(ctx, "non-existent-signature", nil) _, notFoundErr := storage.GetAuthorizeCodeSession(ctx, "non-existent-signature", nil)
require.EqualError(t, notFoundErr, "not_found") require.EqualError(t, notFoundErr, "not_found")
@ -147,7 +160,7 @@ func TestInvalidateWhenNotFound(t *testing.T) {
ctx := context.Background() ctx := context.Background()
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
notFoundErr := storage.InvalidateAuthorizeCodeSession(ctx, "non-existent-signature") notFoundErr := storage.InvalidateAuthorizeCodeSession(ctx, "non-existent-signature")
require.EqualError(t, notFoundErr, "not_found") require.EqualError(t, notFoundErr, "not_found")
@ -158,7 +171,7 @@ func TestInvalidateWhenConflictOnUpdateHappens(t *testing.T) {
ctx := context.Background() ctx := context.Background()
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
client.PrependReactor("update", "secrets", func(_ kubetesting.Action) (bool, runtime.Object, error) { client.PrependReactor("update", "secrets", func(_ kubetesting.Action) (bool, runtime.Object, error) {
return true, nil, apierrors.NewConflict(schema.GroupResource{ return true, nil, apierrors.NewConflict(schema.GroupResource{
@ -182,7 +195,7 @@ func TestWrongVersion(t *testing.T) {
ctx := context.Background() ctx := context.Background()
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
secret := &corev1.Secret{ secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -210,7 +223,7 @@ func TestNilSessionRequest(t *testing.T) {
ctx := context.Background() ctx := context.Background()
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
secret := &corev1.Secret{ secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -238,7 +251,7 @@ func TestCreateWithNilRequester(t *testing.T) {
ctx := context.Background() ctx := context.Background()
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
err := storage.CreateAuthorizeCodeSession(ctx, "signature-doesnt-matter", nil) err := storage.CreateAuthorizeCodeSession(ctx, "signature-doesnt-matter", nil)
require.EqualError(t, err, "requester must be of type fosite.Request") require.EqualError(t, err, "requester must be of type fosite.Request")
@ -248,7 +261,7 @@ func TestCreateWithWrongRequesterDataTypes(t *testing.T) {
ctx := context.Background() ctx := context.Background()
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
secrets := client.CoreV1().Secrets(namespace) secrets := client.CoreV1().Secrets(namespace)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
request := &fosite.Request{ request := &fosite.Request{
Session: nil, Session: nil,
@ -365,7 +378,7 @@ func TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession(t *testing.T) {
const name = "fuzz" // value is irrelevant const name = "fuzz" // value is irrelevant
ctx := context.Background() ctx := context.Background()
secrets := fake.NewSimpleClientset().CoreV1().Secrets(name) secrets := fake.NewSimpleClientset().CoreV1().Secrets(name)
storage := New(secrets) storage := New(secrets, func() time.Time { return fakeNow }, fakeDuration)
// issue a create using the fuzzed request to confirm that marshalling works // issue a create using the fuzzed request to confirm that marshalling works
err = storage.CreateAuthorizeCodeSession(ctx, name, validSession.Request) err = storage.CreateAuthorizeCodeSession(ctx, name, validSession.Request)

View File

@ -39,7 +39,7 @@ type session struct {
} }
func New(secrets corev1client.SecretInterface) pkce.PKCERequestStorage { func New(secrets corev1client.SecretInterface) pkce.PKCERequestStorage {
return &pkceStorage{storage: crud.New(TypeLabelValue, secrets)} return &pkceStorage{storage: crud.New(TypeLabelValue, secrets, nil, 0)}
} }
func (a *pkceStorage) CreatePKCERequestSession(ctx context.Context, signature string, requester fosite.Requester) error { func (a *pkceStorage) CreatePKCERequestSession(ctx context.Context, signature string, requester fosite.Requester) error {

View File

@ -457,11 +457,12 @@ func TestCallbackEndpoint(t *testing.T) {
// Configure fosite the same way that the production code would. // Configure fosite the same way that the production code would.
// Inject this into our test subject at the last second so we get a fresh storage for every test. // Inject this into our test subject at the last second so we get a fresh storage for every test.
oauthStore := oidc.NewKubeStorage(secrets) timeoutsConfiguration := oidc.DefaultOIDCTimeoutsConfiguration()
oauthStore := oidc.NewKubeStorage(secrets, timeoutsConfiguration)
hmacSecret := []byte("some secret - must have at least 32 bytes") hmacSecret := []byte("some secret - must have at least 32 bytes")
require.GreaterOrEqual(t, len(hmacSecret), 32, "fosite requires that hmac secrets have at least 32 bytes") require.GreaterOrEqual(t, len(hmacSecret), 32, "fosite requires that hmac secrets have at least 32 bytes")
jwksProviderIsUnused := jwks.NewDynamicJWKSProvider() jwksProviderIsUnused := jwks.NewDynamicJWKSProvider()
oauthHelper := oidc.FositeOauth2Helper(oauthStore, downstreamIssuer, hmacSecret, jwksProviderIsUnused, oidc.DefaultOIDCTimeoutsConfiguration()) oauthHelper := oidc.FositeOauth2Helper(oauthStore, downstreamIssuer, hmacSecret, jwksProviderIsUnused, timeoutsConfiguration)
idpListGetter := oidctestutil.NewIDPListGetter(&test.idp) idpListGetter := oidctestutil.NewIDPListGetter(&test.idp)
subject := NewHandler(idpListGetter, oauthHelper, happyStateCodec, happyCookieCodec, happyUpstreamRedirectURI) subject := NewHandler(idpListGetter, oauthHelper, happyStateCodec, happyCookieCodec, happyUpstreamRedirectURI)

View File

@ -31,9 +31,9 @@ type KubeStorage struct {
refreshTokenStorage refreshtoken.RevocationStorage refreshTokenStorage refreshtoken.RevocationStorage
} }
func NewKubeStorage(secrets corev1client.SecretInterface) *KubeStorage { func NewKubeStorage(secrets corev1client.SecretInterface, timeoutsConfiguration TimeoutsConfiguration) *KubeStorage {
return &KubeStorage{ return &KubeStorage{
authorizationCodeStorage: authorizationcode.New(secrets), authorizationCodeStorage: authorizationcode.New(secrets, time.Now, timeoutsConfiguration.AuthorizationCodeSessionStorageLifetime),
pkceStorage: pkce.New(secrets), pkceStorage: pkce.New(secrets),
oidcStorage: openidconnect.New(secrets), oidcStorage: openidconnect.New(secrets),
accessTokenStorage: accesstoken.New(secrets), accessTokenStorage: accesstoken.New(secrets),

View File

@ -77,12 +77,14 @@ func (m *Manager) SetProviders(oidcProviders ...*provider.OIDCProvider) {
fositeHMACSecretForThisProvider := []byte("some secret - must have at least 32 bytes") // TODO replace this secret fositeHMACSecretForThisProvider := []byte("some secret - must have at least 32 bytes") // TODO replace this secret
timeoutsConfiguration := oidc.DefaultOIDCTimeoutsConfiguration()
// Use NullStorage for the authorize endpoint because we do not actually want to store anything until // Use NullStorage for the authorize endpoint because we do not actually want to store anything until
// the upstream callback endpoint is called later. // the upstream callback endpoint is called later.
oauthHelperWithNullStorage := oidc.FositeOauth2Helper(oidc.NullStorage{}, issuer, fositeHMACSecretForThisProvider, nil, oidc.DefaultOIDCTimeoutsConfiguration()) oauthHelperWithNullStorage := oidc.FositeOauth2Helper(oidc.NullStorage{}, issuer, fositeHMACSecretForThisProvider, nil, timeoutsConfiguration)
// For all the other endpoints, make another oauth helper with exactly the same settings except use real storage. // For all the other endpoints, make another oauth helper with exactly the same settings except use real storage.
oauthHelperWithKubeStorage := oidc.FositeOauth2Helper(oidc.NewKubeStorage(m.secretsClient), issuer, fositeHMACSecretForThisProvider, m.dynamicJWKSProvider, oidc.DefaultOIDCTimeoutsConfiguration()) oauthHelperWithKubeStorage := oidc.FositeOauth2Helper(oidc.NewKubeStorage(m.secretsClient, timeoutsConfiguration), issuer, fositeHMACSecretForThisProvider, m.dynamicJWKSProvider, timeoutsConfiguration)
// TODO use different codecs for the state and the cookie, because: // TODO use different codecs for the state and the cookie, because:
// 1. we would like to state to have an embedded expiration date while the cookie does not need that // 1. we would like to state to have an embedded expiration date while the cookie does not need that

View File

@ -1155,7 +1155,7 @@ func exchangeAuthcodeForTokens(t *testing.T, test authcodeExchangeInputs) (
var oauthHelper fosite.OAuth2Provider var oauthHelper fosite.OAuth2Provider
oauthStore = oidc.NewKubeStorage(secrets) oauthStore = oidc.NewKubeStorage(secrets, oidc.DefaultOIDCTimeoutsConfiguration())
if test.makeOathHelper != nil { if test.makeOathHelper != nil {
oauthHelper, authCode, jwtSigningKey = test.makeOathHelper(t, authRequest, oauthStore) oauthHelper, authCode, jwtSigningKey = test.makeOathHelper(t, authRequest, oauthStore)
} else { } else {