mirror of
https://github.com/outbackdingo/kubernetes.git
synced 2026-01-27 10:19:35 +00:00
KEP-740: promote ExternalJWTSigner feature to beta
This commit is contained in:
@@ -47,7 +47,7 @@ import (
|
||||
"k8s.io/component-base/metrics"
|
||||
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
v1alpha1testing "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/plugin/testing/v1alpha1"
|
||||
v1testing "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/plugin/testing/v1"
|
||||
netutils "k8s.io/utils/net"
|
||||
)
|
||||
|
||||
@@ -485,7 +485,7 @@ func TestCompleteForServiceAccount(t *testing.T) {
|
||||
if tc.externalSigner {
|
||||
// create and start mock signer.
|
||||
socketPath := utilnettesting.MakeSocketNameForTest(t, fmt.Sprintf("mock-external-jwt-signer-%d.sock", time.Now().Nanosecond()))
|
||||
mockSigner := v1alpha1testing.NewMockSigner(t, socketPath)
|
||||
mockSigner := v1testing.NewMockSigner(t, socketPath)
|
||||
defer mockSigner.CleanUp()
|
||||
|
||||
mockSigner.MaxTokenExpirationSeconds = tc.externalMaxExpirationSec
|
||||
|
||||
@@ -387,9 +387,7 @@ func TestValidateServiceAccountTokenSigningConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
if test.featureEnabled {
|
||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExternalServiceAccountTokenSigner, true)
|
||||
}
|
||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExternalServiceAccountTokenSigner, test.featureEnabled)
|
||||
errs := validateServiceAccountTokenSigningConfig(test.options)
|
||||
if !reflect.DeepEqual(errs, test.expectedErrors) {
|
||||
t.Errorf("Expected errors message: %v \n but got: %v", test.expectedErrors, errs)
|
||||
|
||||
@@ -1168,6 +1168,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
|
||||
|
||||
ExternalServiceAccountTokenSigner: {
|
||||
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
|
||||
{Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.Beta},
|
||||
},
|
||||
|
||||
genericfeatures.AggregatedDiscoveryRemoveBetaType: {
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
|
||||
"golang.org/x/sync/singleflight"
|
||||
|
||||
externaljwtv1alpha1 "k8s.io/externaljwt/apis/v1alpha1"
|
||||
externaljwtv1 "k8s.io/externaljwt/apis/v1"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
externaljwtmetrics "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/metrics"
|
||||
@@ -35,7 +35,7 @@ import (
|
||||
const fallbackRefreshDuration = 10 * time.Second
|
||||
|
||||
type keyCache struct {
|
||||
client externaljwtv1alpha1.ExternalJWTSignerClient
|
||||
client externaljwtv1.ExternalJWTSignerClient
|
||||
|
||||
syncGroup singleflight.Group
|
||||
listenersLock sync.Mutex
|
||||
@@ -45,7 +45,7 @@ type keyCache struct {
|
||||
}
|
||||
|
||||
// newKeyCache constructs an implementation of KeyCache.
|
||||
func newKeyCache(client externaljwtv1alpha1.ExternalJWTSignerClient) *keyCache {
|
||||
func newKeyCache(client externaljwtv1.ExternalJWTSignerClient) *keyCache {
|
||||
cache := &keyCache{
|
||||
client: client,
|
||||
}
|
||||
@@ -203,7 +203,7 @@ func (p *keyCache) broadcastUpdate() {
|
||||
// GetTokenVerificationKeys returns a map of supported external keyIDs to keys
|
||||
// the keys are PKIX-serialized. It calls external-jwt-signer with a timeout of keySyncTimeoutSec.
|
||||
func (p *keyCache) getTokenVerificationKeys(ctx context.Context) (*VerificationKeys, error) {
|
||||
req := &externaljwtv1alpha1.FetchKeysRequest{}
|
||||
req := &externaljwtv1.FetchKeysRequest{}
|
||||
resp, err := p.client.FetchKeys(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("while getting externally supported jwt signing keys: %w", err)
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
externaljwtv1alpha1 "k8s.io/externaljwt/apis/v1alpha1"
|
||||
externaljwtv1 "k8s.io/externaljwt/apis/v1"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
|
||||
utilnettesting "k8s.io/apimachinery/pkg/util/net/testing"
|
||||
@@ -48,7 +48,7 @@ func TestExternalPublicKeyGetter(t *testing.T) {
|
||||
wantVerificationKeys *VerificationKeys
|
||||
refreshHintSec int
|
||||
dataTimeStamp *timestamppb.Timestamp
|
||||
supportedKeysOverride []*externaljwtv1alpha1.Key
|
||||
supportedKeysOverride []*externaljwtv1.Key
|
||||
}{
|
||||
{
|
||||
desc: "single key in signer",
|
||||
@@ -157,7 +157,7 @@ func TestExternalPublicKeyGetter(t *testing.T) {
|
||||
excludeFromOidc: true,
|
||||
},
|
||||
},
|
||||
supportedKeysOverride: []*externaljwtv1alpha1.Key{
|
||||
supportedKeysOverride: []*externaljwtv1.Key{
|
||||
{
|
||||
KeyId: "kid",
|
||||
Key: nil,
|
||||
@@ -186,7 +186,7 @@ func TestExternalPublicKeyGetter(t *testing.T) {
|
||||
}
|
||||
backend.DataTimeStamp = tc.dataTimeStamp
|
||||
backend.SupportedKeysOverride = tc.supportedKeysOverride
|
||||
externaljwtv1alpha1.RegisterExternalJWTSignerServer(grpcServer, backend)
|
||||
externaljwtv1.RegisterExternalJWTSignerServer(grpcServer, backend)
|
||||
|
||||
defer grpcServer.Stop()
|
||||
go func() {
|
||||
@@ -268,7 +268,7 @@ func TestInitialFill(t *testing.T) {
|
||||
refreshHintSeconds: 10,
|
||||
DataTimeStamp: timestamppb.New(time.Time{}),
|
||||
}
|
||||
externaljwtv1alpha1.RegisterExternalJWTSignerServer(grpcServer, backend)
|
||||
externaljwtv1.RegisterExternalJWTSignerServer(grpcServer, backend)
|
||||
|
||||
defer grpcServer.Stop()
|
||||
go func() {
|
||||
@@ -333,7 +333,7 @@ func TestReflectChanges(t *testing.T) {
|
||||
refreshHintSeconds: 10,
|
||||
DataTimeStamp: timestamppb.New(time.Time{}),
|
||||
}
|
||||
externaljwtv1alpha1.RegisterExternalJWTSignerServer(grpcServer, backend)
|
||||
externaljwtv1.RegisterExternalJWTSignerServer(grpcServer, backend)
|
||||
|
||||
defer grpcServer.Stop()
|
||||
go func() {
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
jose "gopkg.in/go-jose/go-jose.v2"
|
||||
"gopkg.in/go-jose/go-jose.v2/jwt"
|
||||
|
||||
externaljwtv1alpha1 "k8s.io/externaljwt/apis/v1alpha1"
|
||||
externaljwtv1 "k8s.io/externaljwt/apis/v1"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
externaljwtmetrics "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/metrics"
|
||||
)
|
||||
@@ -85,14 +85,14 @@ func New(ctx context.Context, issuer, socketPath string, keySyncTimeout time.Dur
|
||||
// enables plugging in an external jwt signer.
|
||||
type Plugin struct {
|
||||
iss string
|
||||
client externaljwtv1alpha1.ExternalJWTSignerClient
|
||||
client externaljwtv1.ExternalJWTSignerClient
|
||||
keyCache *keyCache
|
||||
allowSigningWithNonOIDCKeys bool
|
||||
}
|
||||
|
||||
// newPlugin constructs an implementation of external JWT signer plugin.
|
||||
func newPlugin(iss string, conn *grpc.ClientConn, allowSigningWithNonOIDCKeys bool) *Plugin {
|
||||
client := externaljwtv1alpha1.NewExternalJWTSignerClient(conn)
|
||||
client := externaljwtv1.NewExternalJWTSignerClient(conn)
|
||||
plugin := &Plugin{
|
||||
iss: iss,
|
||||
client: client,
|
||||
@@ -118,7 +118,7 @@ func (p *Plugin) signAndAssembleJWT(ctx context.Context, claims *jwt.Claims, pri
|
||||
|
||||
payloadBase64 := base64.RawURLEncoding.EncodeToString(payload)
|
||||
|
||||
request := &externaljwtv1alpha1.SignJWTRequest{
|
||||
request := &externaljwtv1.SignJWTRequest{
|
||||
Claims: payloadBase64,
|
||||
}
|
||||
|
||||
@@ -140,12 +140,12 @@ func (p *Plugin) signAndAssembleJWT(ctx context.Context, claims *jwt.Claims, pri
|
||||
|
||||
// GetServiceMetadata returns metadata associated with externalJWTSigner
|
||||
// It Includes details like max token lifetime supported by externalJWTSigner, etc.
|
||||
func (p *Plugin) GetServiceMetadata(ctx context.Context) (*externaljwtv1alpha1.MetadataResponse, error) {
|
||||
req := &externaljwtv1alpha1.MetadataRequest{}
|
||||
func (p *Plugin) GetServiceMetadata(ctx context.Context) (*externaljwtv1.MetadataResponse, error) {
|
||||
req := &externaljwtv1.MetadataRequest{}
|
||||
return p.client.Metadata(ctx, req)
|
||||
}
|
||||
|
||||
func (p *Plugin) validateJWTHeader(ctx context.Context, response *externaljwtv1alpha1.SignJWTResponse) error {
|
||||
func (p *Plugin) validateJWTHeader(ctx context.Context, response *externaljwtv1.SignJWTResponse) error {
|
||||
jsonBytes, err := base64.RawURLEncoding.DecodeString(response.Header)
|
||||
if err != nil {
|
||||
return fmt.Errorf("while unwrapping header: %w", err)
|
||||
|
||||
@@ -39,7 +39,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
|
||||
utilnettesting "k8s.io/apimachinery/pkg/util/net/testing"
|
||||
externaljwtv1alpha1 "k8s.io/externaljwt/apis/v1alpha1"
|
||||
externaljwtv1 "k8s.io/externaljwt/apis/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -71,6 +71,7 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
iss string
|
||||
backendSetKeyID string
|
||||
backendSetAlgorithm string
|
||||
backendHeaderType string
|
||||
supportedKeys map[string]supportedKeyT
|
||||
allowSigningWithNonOIDCKeys bool
|
||||
|
||||
@@ -98,6 +99,7 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
},
|
||||
iss: "some-issuer",
|
||||
backendSetKeyID: "key-id-1",
|
||||
backendHeaderType: "JWT",
|
||||
backendSetAlgorithm: "RS256",
|
||||
supportedKeys: map[string]supportedKeyT{
|
||||
"key-id-1": {
|
||||
@@ -143,6 +145,7 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
},
|
||||
iss: "some-issuer",
|
||||
backendSetKeyID: "key-id-1",
|
||||
backendHeaderType: "JWT",
|
||||
backendSetAlgorithm: "RS256",
|
||||
supportedKeys: map[string]supportedKeyT{
|
||||
"key-id-1": {
|
||||
@@ -174,6 +177,7 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
},
|
||||
iss: "some-issuer",
|
||||
backendSetKeyID: "key-id-1",
|
||||
backendHeaderType: "JWT",
|
||||
backendSetAlgorithm: "RS256",
|
||||
supportedKeys: map[string]supportedKeyT{
|
||||
"key-id-1": {
|
||||
@@ -204,6 +208,7 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
desc: "empty key ID returned from signer",
|
||||
iss: "some-issuer",
|
||||
backendSetKeyID: "",
|
||||
backendHeaderType: "JWT",
|
||||
backendSetAlgorithm: "RS256",
|
||||
supportedKeys: map[string]supportedKeyT{
|
||||
"key-id-1": {
|
||||
@@ -217,6 +222,7 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
desc: "key id longer than 1024 bytes returned from signer",
|
||||
iss: "some-issuer",
|
||||
backendSetKeyID: string(make([]byte, 1025)),
|
||||
backendHeaderType: "JWT",
|
||||
backendSetAlgorithm: "RS256",
|
||||
supportedKeys: map[string]supportedKeyT{
|
||||
"key-id-1": {
|
||||
@@ -230,6 +236,7 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
desc: "unsupported alg returned from signer",
|
||||
iss: "some-issuer",
|
||||
backendSetKeyID: "key-id-1",
|
||||
backendHeaderType: "JWT",
|
||||
backendSetAlgorithm: "something-unsupported",
|
||||
supportedKeys: map[string]supportedKeyT{
|
||||
"key-id-1": {
|
||||
@@ -243,6 +250,7 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
desc: "empty alg returned from signer",
|
||||
iss: "some-issuer",
|
||||
backendSetKeyID: "key-id-1",
|
||||
backendHeaderType: "JWT",
|
||||
backendSetAlgorithm: "",
|
||||
supportedKeys: map[string]supportedKeyT{
|
||||
"key-id-1": {
|
||||
@@ -252,6 +260,20 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
},
|
||||
wantErr: fmt.Errorf("while validating header: bad signing algorithm \"\""),
|
||||
},
|
||||
{
|
||||
desc: "Invalid backend header type",
|
||||
iss: "some-issuer",
|
||||
backendSetKeyID: "key-id-1",
|
||||
backendHeaderType: "WHAT",
|
||||
backendSetAlgorithm: "RS256",
|
||||
supportedKeys: map[string]supportedKeyT{
|
||||
"key-id-1": {
|
||||
key: &rsaKey1.PublicKey,
|
||||
excludeFromOidc: true,
|
||||
},
|
||||
},
|
||||
wantErr: fmt.Errorf("while validating header: bad type"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
@@ -275,8 +297,9 @@ func TestExternalTokenGenerator(t *testing.T) {
|
||||
supportedKeys: tc.supportedKeys,
|
||||
refreshHintSeconds: 10,
|
||||
DataTimeStamp: timestamppb.New(time.Time{}),
|
||||
headerType: tc.backendHeaderType,
|
||||
}
|
||||
externaljwtv1alpha1.RegisterExternalJWTSignerServer(grpcServer, backend)
|
||||
externaljwtv1.RegisterExternalJWTSignerServer(grpcServer, backend)
|
||||
|
||||
go func() {
|
||||
if err := grpcServer.Serve(listener); err != nil {
|
||||
@@ -385,24 +408,25 @@ type supportedKeyT struct {
|
||||
}
|
||||
|
||||
type dummyExtrnalSigner struct {
|
||||
externaljwtv1alpha1.UnimplementedExternalJWTSignerServer
|
||||
externaljwtv1.UnimplementedExternalJWTSignerServer
|
||||
|
||||
// required for Sign()
|
||||
keyID string
|
||||
signingAlgorithm string
|
||||
signature string
|
||||
headerType string
|
||||
|
||||
// required for FetchKeys()
|
||||
keyLock sync.Mutex
|
||||
supportedKeys map[string]supportedKeyT
|
||||
refreshHintSeconds int
|
||||
DataTimeStamp *timestamppb.Timestamp
|
||||
SupportedKeysOverride []*externaljwtv1alpha1.Key
|
||||
SupportedKeysOverride []*externaljwtv1.Key
|
||||
}
|
||||
|
||||
func (des *dummyExtrnalSigner) Sign(ctx context.Context, r *externaljwtv1alpha1.SignJWTRequest) (*externaljwtv1alpha1.SignJWTResponse, error) {
|
||||
func (des *dummyExtrnalSigner) Sign(ctx context.Context, r *externaljwtv1.SignJWTRequest) (*externaljwtv1.SignJWTResponse, error) {
|
||||
header := &headerT{
|
||||
Type: "JWT",
|
||||
Type: des.headerType,
|
||||
Algorithm: des.signingAlgorithm,
|
||||
KeyID: des.keyID,
|
||||
}
|
||||
@@ -412,18 +436,18 @@ func (des *dummyExtrnalSigner) Sign(ctx context.Context, r *externaljwtv1alpha1.
|
||||
return nil, fmt.Errorf("failed to create header for JWT response")
|
||||
}
|
||||
|
||||
resp := &externaljwtv1alpha1.SignJWTResponse{
|
||||
resp := &externaljwtv1.SignJWTResponse{
|
||||
Header: base64.RawURLEncoding.EncodeToString(headerJSON),
|
||||
Signature: des.signature,
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (des *dummyExtrnalSigner) FetchKeys(ctx context.Context, r *externaljwtv1alpha1.FetchKeysRequest) (*externaljwtv1alpha1.FetchKeysResponse, error) {
|
||||
func (des *dummyExtrnalSigner) FetchKeys(ctx context.Context, r *externaljwtv1.FetchKeysRequest) (*externaljwtv1.FetchKeysResponse, error) {
|
||||
des.keyLock.Lock()
|
||||
defer des.keyLock.Unlock()
|
||||
|
||||
pbKeys := []*externaljwtv1alpha1.Key{}
|
||||
pbKeys := []*externaljwtv1.Key{}
|
||||
if des.SupportedKeysOverride != nil {
|
||||
pbKeys = des.SupportedKeysOverride
|
||||
} else {
|
||||
@@ -432,7 +456,7 @@ func (des *dummyExtrnalSigner) FetchKeys(ctx context.Context, r *externaljwtv1al
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("while marshaling key: %w", err)
|
||||
}
|
||||
pbKey := &externaljwtv1alpha1.Key{
|
||||
pbKey := &externaljwtv1.Key{
|
||||
KeyId: kid,
|
||||
Key: keyBytes,
|
||||
ExcludeFromOidcDiscovery: k.excludeFromOidc,
|
||||
@@ -441,7 +465,7 @@ func (des *dummyExtrnalSigner) FetchKeys(ctx context.Context, r *externaljwtv1al
|
||||
}
|
||||
}
|
||||
|
||||
return &externaljwtv1alpha1.FetchKeysResponse{
|
||||
return &externaljwtv1.FetchKeysResponse{
|
||||
Keys: pbKeys,
|
||||
DataTimestamp: des.DataTimeStamp,
|
||||
RefreshHintSeconds: int64(des.refreshHintSeconds),
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -35,7 +35,7 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"k8s.io/externaljwt/apis/v1alpha1"
|
||||
"k8s.io/externaljwt/apis/v1"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
@@ -80,7 +80,7 @@ func NewMockSigner(t *testing.T, socketPath string) *MockSigner {
|
||||
t.Fatalf("failed to load keys for mock signer: %v", err)
|
||||
}
|
||||
|
||||
v1alpha1.RegisterExternalJWTSignerServer(server, m)
|
||||
v1.RegisterExternalJWTSignerServer(server, m)
|
||||
if err := m.start(t); err != nil {
|
||||
t.Fatalf("failed to start Mock Signer with error: %v", err)
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func (m *MockSigner) WaitForSupportedKeysFetch() {
|
||||
m.supportedKeysFetched.Wait()
|
||||
}
|
||||
|
||||
func (m *MockSigner) Sign(ctx context.Context, req *v1alpha1.SignJWTRequest) (*v1alpha1.SignJWTResponse, error) {
|
||||
func (m *MockSigner) Sign(ctx context.Context, req *v1.SignJWTRequest) (*v1.SignJWTResponse, error) {
|
||||
|
||||
header := &struct {
|
||||
Algorithm string `json:"alg,omitempty"`
|
||||
@@ -135,24 +135,24 @@ func (m *MockSigner) Sign(ctx context.Context, req *v1alpha1.SignJWTRequest) (*v
|
||||
return nil, fmt.Errorf("unable to sign payload: %w", err)
|
||||
}
|
||||
|
||||
return &v1alpha1.SignJWTResponse{
|
||||
return &v1.SignJWTResponse{
|
||||
Header: base64Header,
|
||||
Signature: base64.RawURLEncoding.EncodeToString(signature),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockSigner) FetchKeys(ctx context.Context, req *v1alpha1.FetchKeysRequest) (*v1alpha1.FetchKeysResponse, error) {
|
||||
func (m *MockSigner) FetchKeys(ctx context.Context, req *v1.FetchKeysRequest) (*v1.FetchKeysResponse, error) {
|
||||
m.errorLock.RLocker().Lock()
|
||||
defer m.errorLock.RLocker().Unlock()
|
||||
if m.FetchError != nil {
|
||||
return nil, m.FetchError
|
||||
}
|
||||
|
||||
keys := []*v1alpha1.Key{}
|
||||
keys := []*v1.Key{}
|
||||
|
||||
m.supportedKeysLock.RLock()
|
||||
for id, k := range m.supportedKeys {
|
||||
keys = append(keys, &v1alpha1.Key{
|
||||
keys = append(keys, &v1.Key{
|
||||
KeyId: id,
|
||||
Key: k.Key,
|
||||
ExcludeFromOidcDiscovery: k.ExcludeFromOidcDiscovery,
|
||||
@@ -162,20 +162,20 @@ func (m *MockSigner) FetchKeys(ctx context.Context, req *v1alpha1.FetchKeysReque
|
||||
m.supportedKeysLock.RUnlock()
|
||||
|
||||
now := time.Now()
|
||||
return &v1alpha1.FetchKeysResponse{
|
||||
return &v1.FetchKeysResponse{
|
||||
RefreshHintSeconds: 5,
|
||||
DataTimestamp: ×tamppb.Timestamp{Seconds: now.Unix(), Nanos: int32(now.Nanosecond())},
|
||||
Keys: keys,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockSigner) Metadata(ctx context.Context, req *v1alpha1.MetadataRequest) (*v1alpha1.MetadataResponse, error) {
|
||||
func (m *MockSigner) Metadata(ctx context.Context, req *v1.MetadataRequest) (*v1.MetadataResponse, error) {
|
||||
m.errorLock.RLocker().Lock()
|
||||
defer m.errorLock.RLocker().Unlock()
|
||||
if m.MetadataError != nil {
|
||||
return nil, m.MetadataError
|
||||
}
|
||||
return &v1alpha1.MetadataResponse{
|
||||
return &v1.MetadataResponse{
|
||||
MaxTokenExpirationSeconds: m.MaxTokenExpirationSeconds,
|
||||
}, nil
|
||||
}
|
||||
@@ -251,7 +251,7 @@ func (m *MockSigner) waitForMockServerToStart() error {
|
||||
return fmt.Errorf("failed to start Mock signer: %w", ctx.Err())
|
||||
default:
|
||||
}
|
||||
if _, gRPCErr = m.FetchKeys(context.Background(), &v1alpha1.FetchKeysRequest{}); gRPCErr == nil {
|
||||
if _, gRPCErr = m.FetchKeys(context.Background(), &v1.FetchKeysRequest{}); gRPCErr == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
592
staging/src/k8s.io/externaljwt/apis/v1/api.pb.go
Normal file
592
staging/src/k8s.io/externaljwt/apis/v1/api.pb.go
Normal file
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: api.proto
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type SignJWTRequest struct {
|
||||
// URL-safe base64 wrapped payload to be signed.
|
||||
// Exactly as it appears in the second segment of the JWT
|
||||
Claims string `protobuf:"bytes,1,opt,name=claims,proto3" json:"claims,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SignJWTRequest) Reset() { *m = SignJWTRequest{} }
|
||||
func (m *SignJWTRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SignJWTRequest) ProtoMessage() {}
|
||||
func (*SignJWTRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_00212fb1f9d3bf1c, []int{0}
|
||||
}
|
||||
func (m *SignJWTRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SignJWTRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SignJWTRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SignJWTRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SignJWTRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SignJWTRequest.Merge(m, src)
|
||||
}
|
||||
func (m *SignJWTRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_SignJWTRequest.Size(m)
|
||||
}
|
||||
func (m *SignJWTRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SignJWTRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SignJWTRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *SignJWTRequest) GetClaims() string {
|
||||
if m != nil {
|
||||
return m.Claims
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type SignJWTResponse struct {
|
||||
// header must contain only alg, kid, typ claims.
|
||||
// typ must be “JWT”.
|
||||
// kid must be non-empty, <=1024 characters, and its corresponding public key should not be excluded from OIDC discovery.
|
||||
// alg must be one of the algorithms supported by kube-apiserver (currently RS256, ES256, ES384, ES512).
|
||||
// header cannot have any additional data that kube-apiserver does not recognize.
|
||||
// Already wrapped in URL-safe base64, exactly as it appears in the first segment of the JWT.
|
||||
Header string `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
|
||||
// The signature for the JWT.
|
||||
// Already wrapped in URL-safe base64, exactly as it appears in the final segment of the JWT.
|
||||
Signature string `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SignJWTResponse) Reset() { *m = SignJWTResponse{} }
|
||||
func (m *SignJWTResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SignJWTResponse) ProtoMessage() {}
|
||||
func (*SignJWTResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_00212fb1f9d3bf1c, []int{1}
|
||||
}
|
||||
func (m *SignJWTResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SignJWTResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SignJWTResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SignJWTResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SignJWTResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SignJWTResponse.Merge(m, src)
|
||||
}
|
||||
func (m *SignJWTResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_SignJWTResponse.Size(m)
|
||||
}
|
||||
func (m *SignJWTResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SignJWTResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SignJWTResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *SignJWTResponse) GetHeader() string {
|
||||
if m != nil {
|
||||
return m.Header
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SignJWTResponse) GetSignature() string {
|
||||
if m != nil {
|
||||
return m.Signature
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type FetchKeysRequest struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *FetchKeysRequest) Reset() { *m = FetchKeysRequest{} }
|
||||
func (m *FetchKeysRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*FetchKeysRequest) ProtoMessage() {}
|
||||
func (*FetchKeysRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_00212fb1f9d3bf1c, []int{2}
|
||||
}
|
||||
func (m *FetchKeysRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FetchKeysRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *FetchKeysRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_FetchKeysRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *FetchKeysRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_FetchKeysRequest.Merge(m, src)
|
||||
}
|
||||
func (m *FetchKeysRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_FetchKeysRequest.Size(m)
|
||||
}
|
||||
func (m *FetchKeysRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_FetchKeysRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_FetchKeysRequest proto.InternalMessageInfo
|
||||
|
||||
type FetchKeysResponse struct {
|
||||
Keys []*Key `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys,omitempty"`
|
||||
// The timestamp when this data was pulled from the authoritative source of
|
||||
// truth for verification keys.
|
||||
// kube-apiserver can export this from metrics, to enable end-to-end SLOs.
|
||||
DataTimestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=data_timestamp,json=dataTimestamp,proto3" json:"data_timestamp,omitempty"`
|
||||
// refresh interval for verification keys to pick changes if any.
|
||||
// any value <= 0 is considered a misconfiguration.
|
||||
RefreshHintSeconds int64 `protobuf:"varint,3,opt,name=refresh_hint_seconds,json=refreshHintSeconds,proto3" json:"refresh_hint_seconds,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *FetchKeysResponse) Reset() { *m = FetchKeysResponse{} }
|
||||
func (m *FetchKeysResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*FetchKeysResponse) ProtoMessage() {}
|
||||
func (*FetchKeysResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_00212fb1f9d3bf1c, []int{3}
|
||||
}
|
||||
func (m *FetchKeysResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FetchKeysResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *FetchKeysResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_FetchKeysResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *FetchKeysResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_FetchKeysResponse.Merge(m, src)
|
||||
}
|
||||
func (m *FetchKeysResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_FetchKeysResponse.Size(m)
|
||||
}
|
||||
func (m *FetchKeysResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_FetchKeysResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_FetchKeysResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *FetchKeysResponse) GetKeys() []*Key {
|
||||
if m != nil {
|
||||
return m.Keys
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *FetchKeysResponse) GetDataTimestamp() *timestamppb.Timestamp {
|
||||
if m != nil {
|
||||
return m.DataTimestamp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *FetchKeysResponse) GetRefreshHintSeconds() int64 {
|
||||
if m != nil {
|
||||
return m.RefreshHintSeconds
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
// A unique identifier for this key.
|
||||
// Length must be <=1024.
|
||||
KeyId string `protobuf:"bytes,1,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty"`
|
||||
// The public key, PKIX-serialized.
|
||||
// must be a public key supported by kube-apiserver (currently RSA 256 or ECDSA 256/384/521)
|
||||
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||
// Set only for keys that are not used to sign bound tokens.
|
||||
// eg: supported keys for legacy tokens.
|
||||
// If set, key is used for verification but excluded from OIDC discovery docs.
|
||||
// if set, external signer should not use this key to sign a JWT.
|
||||
ExcludeFromOidcDiscovery bool `protobuf:"varint,3,opt,name=exclude_from_oidc_discovery,json=excludeFromOidcDiscovery,proto3" json:"exclude_from_oidc_discovery,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Key) Reset() { *m = Key{} }
|
||||
func (m *Key) String() string { return proto.CompactTextString(m) }
|
||||
func (*Key) ProtoMessage() {}
|
||||
func (*Key) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_00212fb1f9d3bf1c, []int{4}
|
||||
}
|
||||
func (m *Key) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Key.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Key) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Key.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Key) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Key.Merge(m, src)
|
||||
}
|
||||
func (m *Key) XXX_Size() int {
|
||||
return xxx_messageInfo_Key.Size(m)
|
||||
}
|
||||
func (m *Key) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Key.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Key proto.InternalMessageInfo
|
||||
|
||||
func (m *Key) GetKeyId() string {
|
||||
if m != nil {
|
||||
return m.KeyId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Key) GetKey() []byte {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Key) GetExcludeFromOidcDiscovery() bool {
|
||||
if m != nil {
|
||||
return m.ExcludeFromOidcDiscovery
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type MetadataRequest struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *MetadataRequest) Reset() { *m = MetadataRequest{} }
|
||||
func (m *MetadataRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*MetadataRequest) ProtoMessage() {}
|
||||
func (*MetadataRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_00212fb1f9d3bf1c, []int{5}
|
||||
}
|
||||
func (m *MetadataRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_MetadataRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *MetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_MetadataRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *MetadataRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MetadataRequest.Merge(m, src)
|
||||
}
|
||||
func (m *MetadataRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_MetadataRequest.Size(m)
|
||||
}
|
||||
func (m *MetadataRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MetadataRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MetadataRequest proto.InternalMessageInfo
|
||||
|
||||
type MetadataResponse struct {
|
||||
// used by kube-apiserver for defaulting/validation of JWT lifetime while accounting for configuration flag values:
|
||||
// 1. `--service-account-max-token-expiration`
|
||||
// 2. `--service-account-extend-token-expiration`
|
||||
//
|
||||
// * If `--service-account-max-token-expiration` is greater than `max_token_expiration_seconds`, kube-apiserver treats that as misconfiguration and exits.
|
||||
// * If `--service-account-max-token-expiration` is not explicitly set, kube-apiserver defaults to `max_token_expiration_seconds`.
|
||||
// * If `--service-account-extend-token-expiration` is true, the extended expiration is `min(1 year, max_token_expiration_seconds)`.
|
||||
//
|
||||
// `max_token_expiration_seconds` must be at least 600s.
|
||||
MaxTokenExpirationSeconds int64 `protobuf:"varint,1,opt,name=max_token_expiration_seconds,json=maxTokenExpirationSeconds,proto3" json:"max_token_expiration_seconds,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *MetadataResponse) Reset() { *m = MetadataResponse{} }
|
||||
func (m *MetadataResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*MetadataResponse) ProtoMessage() {}
|
||||
func (*MetadataResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_00212fb1f9d3bf1c, []int{6}
|
||||
}
|
||||
func (m *MetadataResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_MetadataResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *MetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_MetadataResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *MetadataResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MetadataResponse.Merge(m, src)
|
||||
}
|
||||
func (m *MetadataResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_MetadataResponse.Size(m)
|
||||
}
|
||||
func (m *MetadataResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MetadataResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MetadataResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *MetadataResponse) GetMaxTokenExpirationSeconds() int64 {
|
||||
if m != nil {
|
||||
return m.MaxTokenExpirationSeconds
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*SignJWTRequest)(nil), "v1.SignJWTRequest")
|
||||
proto.RegisterType((*SignJWTResponse)(nil), "v1.SignJWTResponse")
|
||||
proto.RegisterType((*FetchKeysRequest)(nil), "v1.FetchKeysRequest")
|
||||
proto.RegisterType((*FetchKeysResponse)(nil), "v1.FetchKeysResponse")
|
||||
proto.RegisterType((*Key)(nil), "v1.Key")
|
||||
proto.RegisterType((*MetadataRequest)(nil), "v1.MetadataRequest")
|
||||
proto.RegisterType((*MetadataResponse)(nil), "v1.MetadataResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) }
|
||||
|
||||
var fileDescriptor_00212fb1f9d3bf1c = []byte{
|
||||
// 476 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x92, 0x51, 0x6f, 0xd3, 0x30,
|
||||
0x10, 0xc7, 0xc9, 0x32, 0xc6, 0x7a, 0x83, 0xad, 0x35, 0x1d, 0x2a, 0x59, 0x25, 0xa6, 0x3c, 0xf5,
|
||||
0x29, 0xa1, 0xe5, 0x01, 0x84, 0x84, 0x10, 0x88, 0x0d, 0x58, 0x85, 0x90, 0xd2, 0x4a, 0x93, 0x78,
|
||||
0x89, 0xbc, 0xe4, 0xda, 0x9a, 0x34, 0x71, 0xb0, 0xdd, 0x92, 0x7c, 0x20, 0x3e, 0x05, 0x5f, 0x0e,
|
||||
0x39, 0x71, 0x32, 0xda, 0x37, 0xfb, 0x7f, 0xff, 0xf3, 0xdd, 0xef, 0xce, 0xd0, 0xa1, 0x39, 0xf3,
|
||||
0x72, 0xc1, 0x15, 0x27, 0x07, 0xdb, 0xb1, 0xf3, 0x62, 0xc9, 0xf9, 0x72, 0x8d, 0x7e, 0xa5, 0xdc,
|
||||
0x6d, 0x16, 0xbe, 0x62, 0x29, 0x4a, 0x45, 0xd3, 0xbc, 0x36, 0xb9, 0x23, 0x38, 0x9d, 0xb1, 0x65,
|
||||
0x76, 0x73, 0x3b, 0x0f, 0xf0, 0xd7, 0x06, 0xa5, 0x22, 0xcf, 0xe0, 0x28, 0x5a, 0x53, 0x96, 0xca,
|
||||
0x81, 0x75, 0x69, 0x8d, 0x3a, 0x81, 0xb9, 0xb9, 0x9f, 0xe1, 0xac, 0x75, 0xca, 0x9c, 0x67, 0x12,
|
||||
0xb5, 0x75, 0x85, 0x34, 0x46, 0xd1, 0x58, 0xeb, 0x1b, 0x19, 0x42, 0x47, 0xb2, 0x65, 0x46, 0xd5,
|
||||
0x46, 0xe0, 0xe0, 0xa0, 0x0a, 0xdd, 0x0b, 0x2e, 0x81, 0xee, 0x35, 0xaa, 0x68, 0x35, 0xc5, 0x52,
|
||||
0x9a, 0xa2, 0xee, 0x1f, 0x0b, 0x7a, 0xff, 0x89, 0xe6, 0xfd, 0x0b, 0x38, 0x4c, 0xb0, 0xd4, 0x8d,
|
||||
0xd8, 0xa3, 0x93, 0xc9, 0x23, 0x6f, 0x3b, 0xf6, 0xa6, 0x58, 0x06, 0x95, 0x48, 0x3e, 0xc0, 0x69,
|
||||
0x4c, 0x15, 0x0d, 0x5b, 0xa2, 0xaa, 0xd2, 0xc9, 0xc4, 0xf1, 0x6a, 0x66, 0xaf, 0x61, 0xf6, 0xe6,
|
||||
0x8d, 0x23, 0x78, 0xa2, 0x33, 0xda, 0x2b, 0x79, 0x09, 0x7d, 0x81, 0x0b, 0x81, 0x72, 0x15, 0xae,
|
||||
0x58, 0xa6, 0x42, 0x89, 0x11, 0xcf, 0x62, 0x39, 0xb0, 0x2f, 0xad, 0x91, 0x1d, 0x10, 0x13, 0xfb,
|
||||
0xc2, 0x32, 0x35, 0xab, 0x23, 0x6e, 0x0a, 0xf6, 0x14, 0x4b, 0x72, 0x0e, 0x47, 0x09, 0x96, 0x21,
|
||||
0x8b, 0x0d, 0xf8, 0xc3, 0x04, 0xcb, 0xaf, 0x31, 0xe9, 0x82, 0x9d, 0x60, 0x59, 0xf5, 0xf1, 0x38,
|
||||
0xd0, 0x47, 0xf2, 0x0e, 0x2e, 0xb0, 0x88, 0xd6, 0x9b, 0x18, 0xc3, 0x85, 0xe0, 0x69, 0xc8, 0x59,
|
||||
0x1c, 0x85, 0x31, 0x93, 0x11, 0xdf, 0xa2, 0x28, 0xab, 0x42, 0xc7, 0xc1, 0xc0, 0x58, 0xae, 0x05,
|
||||
0x4f, 0xbf, 0xb3, 0x38, 0xfa, 0xd4, 0xc4, 0xdd, 0x1e, 0x9c, 0x7d, 0x43, 0x45, 0x75, 0xd7, 0xcd,
|
||||
0xa4, 0x66, 0xd0, 0xbd, 0x97, 0xcc, 0x9c, 0xde, 0xc3, 0x30, 0xa5, 0x45, 0xa8, 0x78, 0x82, 0x59,
|
||||
0x88, 0x45, 0xce, 0x04, 0x55, 0x8c, 0x67, 0x2d, 0x8f, 0x55, 0xf1, 0x3c, 0x4f, 0x69, 0x31, 0xd7,
|
||||
0x96, 0xab, 0xd6, 0x61, 0xb0, 0x26, 0x7f, 0x2d, 0xe8, 0x5d, 0x15, 0x0a, 0x45, 0x46, 0xd7, 0x37,
|
||||
0xb7, 0x73, 0xbd, 0x67, 0x14, 0x64, 0x0c, 0x87, 0xfa, 0x44, 0x88, 0x1e, 0xfc, 0xee, 0x2f, 0x71,
|
||||
0x9e, 0xee, 0x68, 0x75, 0x1f, 0xee, 0x03, 0xf2, 0x16, 0x3a, 0xed, 0x1a, 0x49, 0x5f, 0x7b, 0xf6,
|
||||
0x57, 0xed, 0x9c, 0xef, 0xa9, 0x6d, 0xee, 0x6b, 0x38, 0x6e, 0xc8, 0x48, 0xf5, 0xfc, 0x1e, 0xba,
|
||||
0xd3, 0xdf, 0x15, 0x9b, 0xc4, 0x8f, 0xc3, 0x1f, 0x4e, 0xf2, 0x46, 0x7a, 0x8c, 0xfb, 0x68, 0x18,
|
||||
0x7e, 0xfe, 0x56, 0x3e, 0xcd, 0x99, 0xf4, 0xb7, 0xe3, 0xbb, 0xa3, 0xea, 0x1f, 0xbc, 0xfa, 0x17,
|
||||
0x00, 0x00, 0xff, 0xff, 0xc2, 0x92, 0x25, 0x65, 0x1a, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// ExternalJWTSignerClient is the client API for ExternalJWTSigner service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type ExternalJWTSignerClient interface {
|
||||
// Sign takes a serialized JWT payload, and returns the serialized header and
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature. Signature can be generated by signing
|
||||
// `base64url(header) + "." + base64url(payload)` with signing key.
|
||||
//
|
||||
// The plugin MUST set a key id in the returned JWT header.
|
||||
Sign(ctx context.Context, in *SignJWTRequest, opts ...grpc.CallOption) (*SignJWTResponse, error)
|
||||
// FetchKeys returns the set of public keys that are trusted to sign
|
||||
// Kubernetes service account tokens. Kube-apiserver will call this RPC:
|
||||
//
|
||||
// * Every time it tries to validate a JWT from the service account issuer with an unknown key ID, and
|
||||
//
|
||||
// - Periodically, so it can serve reasonably-up-to-date keys from the OIDC
|
||||
// JWKs endpoint.
|
||||
FetchKeys(ctx context.Context, in *FetchKeysRequest, opts ...grpc.CallOption) (*FetchKeysResponse, error)
|
||||
// Metadata is meant to be called once on startup.
|
||||
// Enables sharing metadata with kube-apiserver (eg: the max token lifetime that signer supports)
|
||||
Metadata(ctx context.Context, in *MetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error)
|
||||
}
|
||||
|
||||
type externalJWTSignerClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewExternalJWTSignerClient(cc *grpc.ClientConn) ExternalJWTSignerClient {
|
||||
return &externalJWTSignerClient{cc}
|
||||
}
|
||||
|
||||
func (c *externalJWTSignerClient) Sign(ctx context.Context, in *SignJWTRequest, opts ...grpc.CallOption) (*SignJWTResponse, error) {
|
||||
out := new(SignJWTResponse)
|
||||
err := c.cc.Invoke(ctx, "/v1.ExternalJWTSigner/Sign", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *externalJWTSignerClient) FetchKeys(ctx context.Context, in *FetchKeysRequest, opts ...grpc.CallOption) (*FetchKeysResponse, error) {
|
||||
out := new(FetchKeysResponse)
|
||||
err := c.cc.Invoke(ctx, "/v1.ExternalJWTSigner/FetchKeys", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *externalJWTSignerClient) Metadata(ctx context.Context, in *MetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error) {
|
||||
out := new(MetadataResponse)
|
||||
err := c.cc.Invoke(ctx, "/v1.ExternalJWTSigner/Metadata", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ExternalJWTSignerServer is the server API for ExternalJWTSigner service.
|
||||
type ExternalJWTSignerServer interface {
|
||||
// Sign takes a serialized JWT payload, and returns the serialized header and
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature. Signature can be generated by signing
|
||||
// `base64url(header) + "." + base64url(payload)` with signing key.
|
||||
//
|
||||
// The plugin MUST set a key id in the returned JWT header.
|
||||
Sign(context.Context, *SignJWTRequest) (*SignJWTResponse, error)
|
||||
// FetchKeys returns the set of public keys that are trusted to sign
|
||||
// Kubernetes service account tokens. Kube-apiserver will call this RPC:
|
||||
//
|
||||
// * Every time it tries to validate a JWT from the service account issuer with an unknown key ID, and
|
||||
//
|
||||
// - Periodically, so it can serve reasonably-up-to-date keys from the OIDC
|
||||
// JWKs endpoint.
|
||||
FetchKeys(context.Context, *FetchKeysRequest) (*FetchKeysResponse, error)
|
||||
// Metadata is meant to be called once on startup.
|
||||
// Enables sharing metadata with kube-apiserver (eg: the max token lifetime that signer supports)
|
||||
Metadata(context.Context, *MetadataRequest) (*MetadataResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedExternalJWTSignerServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedExternalJWTSignerServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedExternalJWTSignerServer) Sign(ctx context.Context, req *SignJWTRequest) (*SignJWTResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Sign not implemented")
|
||||
}
|
||||
func (*UnimplementedExternalJWTSignerServer) FetchKeys(ctx context.Context, req *FetchKeysRequest) (*FetchKeysResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method FetchKeys not implemented")
|
||||
}
|
||||
func (*UnimplementedExternalJWTSignerServer) Metadata(ctx context.Context, req *MetadataRequest) (*MetadataResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Metadata not implemented")
|
||||
}
|
||||
|
||||
func RegisterExternalJWTSignerServer(s *grpc.Server, srv ExternalJWTSignerServer) {
|
||||
s.RegisterService(&_ExternalJWTSigner_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _ExternalJWTSigner_Sign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SignJWTRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ExternalJWTSignerServer).Sign(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/v1.ExternalJWTSigner/Sign",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ExternalJWTSignerServer).Sign(ctx, req.(*SignJWTRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ExternalJWTSigner_FetchKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(FetchKeysRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ExternalJWTSignerServer).FetchKeys(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/v1.ExternalJWTSigner/FetchKeys",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ExternalJWTSignerServer).FetchKeys(ctx, req.(*FetchKeysRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ExternalJWTSigner_Metadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(MetadataRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ExternalJWTSignerServer).Metadata(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/v1.ExternalJWTSigner/Metadata",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ExternalJWTSignerServer).Metadata(ctx, req.(*MetadataRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _ExternalJWTSigner_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "v1.ExternalJWTSigner",
|
||||
HandlerType: (*ExternalJWTSignerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Sign",
|
||||
Handler: _ExternalJWTSigner_Sign_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "FetchKeys",
|
||||
Handler: _ExternalJWTSigner_FetchKeys_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Metadata",
|
||||
Handler: _ExternalJWTSigner_Metadata_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api.proto",
|
||||
}
|
||||
114
staging/src/k8s.io/externaljwt/apis/v1/api.proto
Normal file
114
staging/src/k8s.io/externaljwt/apis/v1/api.proto
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// To regenerate api.pb.go run `hack/update-codegen.sh protobindings`
|
||||
syntax = "proto3";
|
||||
|
||||
package v1;
|
||||
|
||||
option go_package = "k8s.io/externaljwt/apis/v1";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
// This service is served by a process on a local Unix Domain Socket.
|
||||
service ExternalJWTSigner {
|
||||
// Sign takes a serialized JWT payload, and returns the serialized header and
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature. Signature can be generated by signing
|
||||
// `base64url(header) + "." + base64url(payload)` with signing key.
|
||||
//
|
||||
// The plugin MUST set a key id in the returned JWT header.
|
||||
rpc Sign(SignJWTRequest) returns (SignJWTResponse) {}
|
||||
|
||||
// FetchKeys returns the set of public keys that are trusted to sign
|
||||
// Kubernetes service account tokens. Kube-apiserver will call this RPC:
|
||||
//
|
||||
// * Every time it tries to validate a JWT from the service account issuer with an unknown key ID, and
|
||||
//
|
||||
// * Periodically, so it can serve reasonably-up-to-date keys from the OIDC
|
||||
// JWKs endpoint.
|
||||
rpc FetchKeys(FetchKeysRequest) returns (FetchKeysResponse) {}
|
||||
|
||||
// Metadata is meant to be called once on startup.
|
||||
// Enables sharing metadata with kube-apiserver (eg: the max token lifetime that signer supports)
|
||||
rpc Metadata(MetadataRequest) returns (MetadataResponse) {}
|
||||
}
|
||||
|
||||
message SignJWTRequest {
|
||||
// URL-safe base64 wrapped payload to be signed.
|
||||
// Exactly as it appears in the second segment of the JWT
|
||||
string claims = 1;
|
||||
}
|
||||
|
||||
message SignJWTResponse {
|
||||
// header must contain only alg, kid, typ claims.
|
||||
// typ must be “JWT”.
|
||||
// kid must be non-empty, <=1024 characters, and its corresponding public key should not be excluded from OIDC discovery.
|
||||
// alg must be one of the algorithms supported by kube-apiserver (currently RS256, ES256, ES384, ES512).
|
||||
// header cannot have any additional data that kube-apiserver does not recognize.
|
||||
// Already wrapped in URL-safe base64, exactly as it appears in the first segment of the JWT.
|
||||
string header = 1;
|
||||
|
||||
// The signature for the JWT.
|
||||
// Already wrapped in URL-safe base64, exactly as it appears in the final segment of the JWT.
|
||||
string signature = 2;
|
||||
}
|
||||
|
||||
message FetchKeysRequest {}
|
||||
|
||||
message FetchKeysResponse {
|
||||
repeated Key keys = 1;
|
||||
|
||||
// The timestamp when this data was pulled from the authoritative source of
|
||||
// truth for verification keys.
|
||||
// kube-apiserver can export this from metrics, to enable end-to-end SLOs.
|
||||
google.protobuf.Timestamp data_timestamp = 2;
|
||||
|
||||
// refresh interval for verification keys to pick changes if any.
|
||||
// any value <= 0 is considered a misconfiguration.
|
||||
int64 refresh_hint_seconds = 3;
|
||||
}
|
||||
|
||||
message Key {
|
||||
// A unique identifier for this key.
|
||||
// Length must be <=1024.
|
||||
string key_id = 1;
|
||||
|
||||
// The public key, PKIX-serialized.
|
||||
// must be a public key supported by kube-apiserver (currently RSA 256 or ECDSA 256/384/521)
|
||||
bytes key = 2;
|
||||
|
||||
// Set only for keys that are not used to sign bound tokens.
|
||||
// eg: supported keys for legacy tokens.
|
||||
// If set, key is used for verification but excluded from OIDC discovery docs.
|
||||
// if set, external signer should not use this key to sign a JWT.
|
||||
bool exclude_from_oidc_discovery = 3;
|
||||
}
|
||||
|
||||
message MetadataRequest {}
|
||||
|
||||
message MetadataResponse {
|
||||
// used by kube-apiserver for defaulting/validation of JWT lifetime while accounting for configuration flag values:
|
||||
// 1. `--service-account-max-token-expiration`
|
||||
// 2. `--service-account-extend-token-expiration`
|
||||
//
|
||||
// * If `--service-account-max-token-expiration` is greater than `max_token_expiration_seconds`, kube-apiserver treats that as misconfiguration and exits.
|
||||
// * If `--service-account-max-token-expiration` is not explicitly set, kube-apiserver defaults to `max_token_expiration_seconds`.
|
||||
// * If `--service-account-extend-token-expiration` is true, the extended expiration is `min(1 year, max_token_expiration_seconds)`.
|
||||
//
|
||||
// `max_token_expiration_seconds` must be at least 600s.
|
||||
int64 max_token_expiration_seconds = 1;
|
||||
}
|
||||
@@ -423,8 +423,9 @@ const _ = grpc.SupportPackageIsVersion4
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type ExternalJWTSignerClient interface {
|
||||
// Sign takes a serialized JWT payload, and returns the serialized header and
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature.
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature. Signature can be generated by signing
|
||||
// `base64url(header) + "." + base64url(payload)` with signing key.
|
||||
//
|
||||
// The plugin MUST set a key id in the returned JWT header.
|
||||
Sign(ctx context.Context, in *SignJWTRequest, opts ...grpc.CallOption) (*SignJWTResponse, error)
|
||||
@@ -479,8 +480,9 @@ func (c *externalJWTSignerClient) Metadata(ctx context.Context, in *MetadataRequ
|
||||
// ExternalJWTSignerServer is the server API for ExternalJWTSigner service.
|
||||
type ExternalJWTSignerServer interface {
|
||||
// Sign takes a serialized JWT payload, and returns the serialized header and
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature.
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature. Signature can be generated by signing
|
||||
// `base64url(header) + "." + base64url(payload)` with signing key.
|
||||
//
|
||||
// The plugin MUST set a key id in the returned JWT header.
|
||||
Sign(context.Context, *SignJWTRequest) (*SignJWTResponse, error)
|
||||
|
||||
@@ -26,8 +26,9 @@ import "google/protobuf/timestamp.proto";
|
||||
// This service is served by a process on a local Unix Domain Socket.
|
||||
service ExternalJWTSigner {
|
||||
// Sign takes a serialized JWT payload, and returns the serialized header and
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature.
|
||||
// signature. The caller can then assemble the JWT from the header, payload,
|
||||
// and signature. Signature can be generated by signing
|
||||
// `base64url(header) + "." + base64url(payload)` with signing key.
|
||||
//
|
||||
// The plugin MUST set a key id in the returned JWT header.
|
||||
rpc Sign(SignJWTRequest) returns (SignJWTResponse) {}
|
||||
|
||||
@@ -495,6 +495,10 @@
|
||||
lockToDefault: false
|
||||
preRelease: Alpha
|
||||
version: "1.32"
|
||||
- default: true
|
||||
lockToDefault: false
|
||||
preRelease: Beta
|
||||
version: "1.34"
|
||||
- name: GitRepoVolumeDriver
|
||||
versionedSpecs:
|
||||
- default: true
|
||||
|
||||
@@ -38,7 +38,7 @@ import (
|
||||
"k8s.io/component-base/metrics/testutil"
|
||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
v1alpha1testing "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/plugin/testing/v1alpha1"
|
||||
v1testing "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/plugin/testing/v1"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
"k8s.io/kubernetes/test/utils/ktesting"
|
||||
)
|
||||
@@ -64,11 +64,11 @@ func TestExternalJWTSigningAndAuth(t *testing.T) {
|
||||
// create and start mock signer.
|
||||
socketPath := utilnettesting.MakeSocketNameForTest(t, fmt.Sprintf("mock-external-jwt-signer-%d.sock", time.Now().Nanosecond()))
|
||||
t.Cleanup(func() { _ = os.Remove(socketPath) })
|
||||
mockSigner := v1alpha1testing.NewMockSigner(t, socketPath)
|
||||
mockSigner := v1testing.NewMockSigner(t, socketPath)
|
||||
defer mockSigner.CleanUp()
|
||||
|
||||
// Start Api server configured with external signer.
|
||||
client, _, tearDownFn := framework.StartTestServer(ctx, t, framework.TestServerSetup{
|
||||
client, clientConfig, tearDownFn := framework.StartTestServer(ctx, t, framework.TestServerSetup{
|
||||
ModifyServerRunOptions: func(opt *options.ServerRunOptions) {
|
||||
opt.ServiceAccountSigningEndpoint = socketPath
|
||||
opt.ServiceAccountSigningKeyFile = ""
|
||||
@@ -133,11 +133,11 @@ func TestExternalJWTSigningAndAuth(t *testing.T) {
|
||||
mockSigner.SigningKey = key1
|
||||
mockSigner.SigningKeyID = "updated-kid-1"
|
||||
|
||||
cpy := make(map[string]v1alpha1testing.KeyT)
|
||||
cpy := make(map[string]v1testing.KeyT)
|
||||
for key, value := range mockSigner.GetSupportedKeys() {
|
||||
cpy[key] = value
|
||||
}
|
||||
cpy["updated-kid-1"] = v1alpha1testing.KeyT{
|
||||
cpy["updated-kid-1"] = v1testing.KeyT{
|
||||
Key: pubKey1Bytes,
|
||||
ExcludeFromOidcDiscovery: true,
|
||||
}
|
||||
@@ -176,7 +176,7 @@ func TestExternalJWTSigningAndAuth(t *testing.T) {
|
||||
mockSigner.SigningKey = key1
|
||||
},
|
||||
preValidationSignerUpdate: func(_ *testing.T) {
|
||||
mockSigner.SetSupportedKeys(map[string]v1alpha1testing.KeyT{})
|
||||
mockSigner.SetSupportedKeys(map[string]v1testing.KeyT{})
|
||||
},
|
||||
shouldPassAuth: false,
|
||||
},
|
||||
@@ -187,11 +187,11 @@ func TestExternalJWTSigningAndAuth(t *testing.T) {
|
||||
},
|
||||
preValidationSignerUpdate: func(t *testing.T) {
|
||||
t.Helper()
|
||||
cpy := make(map[string]v1alpha1testing.KeyT)
|
||||
cpy := make(map[string]v1testing.KeyT)
|
||||
for key, value := range mockSigner.GetSupportedKeys() {
|
||||
cpy[key] = value
|
||||
}
|
||||
cpy["kid-1"] = v1alpha1testing.KeyT{Key: pubKey1Bytes}
|
||||
cpy["kid-1"] = v1testing.KeyT{Key: pubKey1Bytes}
|
||||
mockSigner.SetSupportedKeys(cpy)
|
||||
waitForDataTimestamp(t, client, time.Now())
|
||||
},
|
||||
@@ -245,6 +245,31 @@ func TestExternalJWTSigningAndAuth(t *testing.T) {
|
||||
} else if tokenReviewResult.Status.Authenticated && !tc.shouldPassAuth {
|
||||
t.Fatal("Expected Authentication to fail")
|
||||
}
|
||||
|
||||
// Perform SSAR
|
||||
if tc.shouldPassAuth {
|
||||
config := *clientConfig
|
||||
config.BearerToken = tokenRequest.Status.Token
|
||||
|
||||
newClient, err := kubernetes.NewForConfig(&config)
|
||||
if err != nil {
|
||||
t.Fatalf("While creating a new client using token: %v", err)
|
||||
}
|
||||
|
||||
ssr, err := newClient.AuthenticationV1().SelfSubjectReviews().Create(ctx, &authv1.SelfSubjectReview{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "SelfSubjectReview",
|
||||
APIVersion: "authentication.k8s.io/v1",
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to perform SelfSubjectAccessReview: %v", err)
|
||||
}
|
||||
|
||||
if ssr.Status.UserInfo.Username != "system:serviceaccount:ns-1:sa-1" {
|
||||
t.Fatalf("Unexpected username (%s) on SelfSubjectReview", ssr.Status.UserInfo.Username)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -292,7 +317,7 @@ func TestDelayedStartForSigner(t *testing.T) {
|
||||
t.Cleanup(func() { _ = os.Remove(socketPath) })
|
||||
go func() {
|
||||
time.Sleep(20 * time.Second)
|
||||
v1alpha1testing.NewMockSigner(t, socketPath)
|
||||
v1testing.NewMockSigner(t, socketPath)
|
||||
}()
|
||||
|
||||
// Start Api server configured with external signer.
|
||||
|
||||
Reference in New Issue
Block a user