mirror of https://github.com/k3s-io/k3s
Merge pull request #67576 from yue9944882/externalize-secret-serviceaccount-informer
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Externalize serviceaacount admission controller ref: #66680 this pull externalizes serviceaccount admission controller in which secret & serviceaccount informers will be completely replaced. /sig api-machinery **Release note**: ```release-note NONE ```pull/8/head
commit
687553a47a
|
@ -20,7 +20,6 @@ import (
|
|||
"k8s.io/api/core/v1"
|
||||
apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
// UserInfo returns a user.Info interface for the given namespace, service account name and UID
|
||||
|
@ -51,24 +50,3 @@ func IsServiceAccountToken(secret *v1.Secret, sa *v1.ServiceAccount) bool {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO: remove the duplicate code
|
||||
// InternalIsServiceAccountToken returns true if the secret is a valid api token for the service account
|
||||
func InternalIsServiceAccountToken(secret *api.Secret, sa *api.ServiceAccount) bool {
|
||||
if secret.Type != api.SecretTypeServiceAccountToken {
|
||||
return false
|
||||
}
|
||||
|
||||
name := secret.Annotations[api.ServiceAccountNameKey]
|
||||
uid := secret.Annotations[api.ServiceAccountUIDKey]
|
||||
if name != sa.Name {
|
||||
// Name must match
|
||||
return false
|
||||
}
|
||||
if len(uid) > 0 && uid != string(sa.UID) {
|
||||
// If UID is specified, it must match
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -16,19 +16,20 @@ go_library(
|
|||
deps = [
|
||||
"//pkg/api/pod:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/kubeapiserver/admission/util:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -38,16 +39,18 @@ go_test(
|
|||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/kubelet/types:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -23,19 +23,20 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
podutil "k8s.io/kubernetes/pkg/api/pod"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
)
|
||||
|
@ -74,16 +75,16 @@ type serviceAccount struct {
|
|||
// MountServiceAccountToken creates Volume and VolumeMounts for the first referenced ServiceAccountToken for the pod's service account
|
||||
MountServiceAccountToken bool
|
||||
|
||||
client internalclientset.Interface
|
||||
client kubernetes.Interface
|
||||
|
||||
serviceAccountLister corelisters.ServiceAccountLister
|
||||
secretLister corelisters.SecretLister
|
||||
serviceAccountLister corev1listers.ServiceAccountLister
|
||||
secretLister corev1listers.SecretLister
|
||||
}
|
||||
|
||||
var _ admission.MutationInterface = &serviceAccount{}
|
||||
var _ admission.ValidationInterface = &serviceAccount{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&serviceAccount{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&serviceAccount{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&serviceAccount{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&serviceAccount{})
|
||||
|
||||
// NewServiceAccount returns an admission.Interface implementation which limits admission of Pod CREATE requests based on the pod's ServiceAccount:
|
||||
// 1. If the pod does not specify a ServiceAccount, it sets the pod's ServiceAccount to "default"
|
||||
|
@ -103,15 +104,15 @@ func NewServiceAccount() *serviceAccount {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *serviceAccount) SetInternalKubeClientSet(cl internalclientset.Interface) {
|
||||
func (a *serviceAccount) SetExternalKubeClientSet(cl kubernetes.Interface) {
|
||||
a.client = cl
|
||||
}
|
||||
|
||||
func (a *serviceAccount) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
serviceAccountInformer := f.Core().InternalVersion().ServiceAccounts()
|
||||
func (a *serviceAccount) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
serviceAccountInformer := f.Core().V1().ServiceAccounts()
|
||||
a.serviceAccountLister = serviceAccountInformer.Lister()
|
||||
|
||||
secretInformer := f.Core().InternalVersion().Secrets()
|
||||
secretInformer := f.Core().V1().Secrets()
|
||||
a.secretLister = secretInformer.Lister()
|
||||
|
||||
a.SetReadyFunc(func() bool {
|
||||
|
@ -174,7 +175,9 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
|
|||
}
|
||||
if len(pod.Spec.ImagePullSecrets) == 0 {
|
||||
pod.Spec.ImagePullSecrets = make([]api.LocalObjectReference, len(serviceAccount.ImagePullSecrets))
|
||||
copy(pod.Spec.ImagePullSecrets, serviceAccount.ImagePullSecrets)
|
||||
for i := 0; i < len(serviceAccount.ImagePullSecrets); i++ {
|
||||
pod.Spec.ImagePullSecrets[i].Name = serviceAccount.ImagePullSecrets[i].Name
|
||||
}
|
||||
}
|
||||
|
||||
return s.Validate(a)
|
||||
|
@ -251,7 +254,7 @@ func shouldIgnore(a admission.Attributes) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func shouldAutomount(sa *api.ServiceAccount, pod *api.Pod) bool {
|
||||
func shouldAutomount(sa *corev1.ServiceAccount, pod *api.Pod) bool {
|
||||
// Pod's preference wins
|
||||
if pod.Spec.AutomountServiceAccountToken != nil {
|
||||
return *pod.Spec.AutomountServiceAccountToken
|
||||
|
@ -266,7 +269,7 @@ func shouldAutomount(sa *api.ServiceAccount, pod *api.Pod) bool {
|
|||
|
||||
// enforceMountableSecrets indicates whether mountable secrets should be enforced for a particular service account
|
||||
// A global setting of true will override any flag set on the individual service account
|
||||
func (s *serviceAccount) enforceMountableSecrets(serviceAccount *api.ServiceAccount) bool {
|
||||
func (s *serviceAccount) enforceMountableSecrets(serviceAccount *corev1.ServiceAccount) bool {
|
||||
if s.LimitSecretReferences {
|
||||
return true
|
||||
}
|
||||
|
@ -280,7 +283,7 @@ func (s *serviceAccount) enforceMountableSecrets(serviceAccount *api.ServiceAcco
|
|||
}
|
||||
|
||||
// getServiceAccount returns the ServiceAccount for the given namespace and name if it exists
|
||||
func (s *serviceAccount) getServiceAccount(namespace string, name string) (*api.ServiceAccount, error) {
|
||||
func (s *serviceAccount) getServiceAccount(namespace string, name string) (*corev1.ServiceAccount, error) {
|
||||
serviceAccount, err := s.serviceAccountLister.ServiceAccounts(namespace).Get(name)
|
||||
if err == nil {
|
||||
return serviceAccount, nil
|
||||
|
@ -313,7 +316,7 @@ func (s *serviceAccount) getServiceAccount(namespace string, name string) (*api.
|
|||
}
|
||||
|
||||
// getReferencedServiceAccountToken returns the name of the first referenced secret which is a ServiceAccountToken for the service account
|
||||
func (s *serviceAccount) getReferencedServiceAccountToken(serviceAccount *api.ServiceAccount) (string, error) {
|
||||
func (s *serviceAccount) getReferencedServiceAccountToken(serviceAccount *corev1.ServiceAccount) (string, error) {
|
||||
if len(serviceAccount.Secrets) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
@ -338,27 +341,27 @@ func (s *serviceAccount) getReferencedServiceAccountToken(serviceAccount *api.Se
|
|||
}
|
||||
|
||||
// getServiceAccountTokens returns all ServiceAccountToken secrets for the given ServiceAccount
|
||||
func (s *serviceAccount) getServiceAccountTokens(serviceAccount *api.ServiceAccount) ([]*api.Secret, error) {
|
||||
func (s *serviceAccount) getServiceAccountTokens(serviceAccount *corev1.ServiceAccount) ([]*corev1.Secret, error) {
|
||||
secrets, err := s.secretLister.Secrets(serviceAccount.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tokens := []*api.Secret{}
|
||||
tokens := []*corev1.Secret{}
|
||||
|
||||
for _, secret := range secrets {
|
||||
if secret.Type != api.SecretTypeServiceAccountToken {
|
||||
if secret.Type != corev1.SecretTypeServiceAccountToken {
|
||||
continue
|
||||
}
|
||||
|
||||
if serviceaccount.InternalIsServiceAccountToken(secret, serviceAccount) {
|
||||
if serviceaccount.IsServiceAccountToken(secret, serviceAccount) {
|
||||
tokens = append(tokens, secret)
|
||||
}
|
||||
}
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
func (s *serviceAccount) limitSecretReferences(serviceAccount *api.ServiceAccount, pod *api.Pod) error {
|
||||
func (s *serviceAccount) limitSecretReferences(serviceAccount *corev1.ServiceAccount, pod *api.Pod) error {
|
||||
// Ensure all secrets the pod references are allowed by the service account
|
||||
mountableSecrets := sets.NewString()
|
||||
for _, s := range serviceAccount.Secrets {
|
||||
|
@ -408,7 +411,7 @@ func (s *serviceAccount) limitSecretReferences(serviceAccount *api.ServiceAccoun
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *serviceAccount) mountServiceAccountToken(serviceAccount *api.ServiceAccount, pod *api.Pod) error {
|
||||
func (s *serviceAccount) mountServiceAccountToken(serviceAccount *corev1.ServiceAccount, pod *api.Pod) error {
|
||||
// Find the name of a referenced ServiceAccountToken secret we can mount
|
||||
serviceAccountToken, err := s.getReferencedServiceAccountToken(serviceAccount)
|
||||
if err != nil {
|
||||
|
|
|
@ -21,15 +21,18 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
kubelet "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
)
|
||||
|
@ -168,12 +171,12 @@ func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.MountServiceAccountToken = true
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
// Add the default service account for the ns into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
|
@ -196,12 +199,12 @@ func TestAssignsDefaultServiceAccountAndRejectsMissingAPIToken(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.MountServiceAccountToken = true
|
||||
admit.RequireAPIToken = true
|
||||
|
||||
// Add the default service account for the ns into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
|
@ -220,7 +223,7 @@ func TestFetchesUncachedServiceAccount(t *testing.T) {
|
|||
ns := "myns"
|
||||
|
||||
// Build a test client that the admission plugin can use to look up the service account missing from its cache
|
||||
client := fake.NewSimpleClientset(&api.ServiceAccount{
|
||||
client := fake.NewSimpleClientset(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
|
@ -229,7 +232,7 @@ func TestFetchesUncachedServiceAccount(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.client = client
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
|
@ -251,9 +254,9 @@ func TestDeniesInvalidServiceAccount(t *testing.T) {
|
|||
client := fake.NewSimpleClientset()
|
||||
|
||||
admit := NewServiceAccount()
|
||||
admit.SetInternalKubeClientSet(client)
|
||||
admit.SetExternalKubeClientSet(client)
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
|
||||
pod := &api.Pod{}
|
||||
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil)
|
||||
|
@ -283,32 +286,32 @@ func TestAutomountsAPIToken(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.MountServiceAccountToken = true
|
||||
admit.RequireAPIToken = true
|
||||
|
||||
// Add the default service account for the ns with a token into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: serviceAccountName,
|
||||
Namespace: ns,
|
||||
UID: types.UID(serviceAccountUID),
|
||||
},
|
||||
Secrets: []api.ObjectReference{
|
||||
Secrets: []corev1.ObjectReference{
|
||||
{Name: tokenName},
|
||||
},
|
||||
})
|
||||
// Add a token for the service account into the cache
|
||||
informerFactory.Core().InternalVersion().Secrets().Informer().GetStore().Add(&api.Secret{
|
||||
informerFactory.Core().V1().Secrets().Informer().GetStore().Add(&corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: tokenName,
|
||||
Namespace: ns,
|
||||
Annotations: map[string]string{
|
||||
api.ServiceAccountNameKey: serviceAccountName,
|
||||
api.ServiceAccountUIDKey: serviceAccountUID,
|
||||
corev1.ServiceAccountNameKey: serviceAccountName,
|
||||
corev1.ServiceAccountUIDKey: serviceAccountUID,
|
||||
},
|
||||
},
|
||||
Type: api.SecretTypeServiceAccountToken,
|
||||
Type: corev1.SecretTypeServiceAccountToken,
|
||||
Data: map[string][]byte{
|
||||
api.ServiceAccountTokenKey: []byte("token-data"),
|
||||
},
|
||||
|
@ -433,34 +436,34 @@ func TestRespectsExistingMount(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.MountServiceAccountToken = true
|
||||
admit.RequireAPIToken = true
|
||||
|
||||
// Add the default service account for the ns with a token into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: serviceAccountName,
|
||||
Namespace: ns,
|
||||
UID: types.UID(serviceAccountUID),
|
||||
},
|
||||
Secrets: []api.ObjectReference{
|
||||
Secrets: []corev1.ObjectReference{
|
||||
{Name: tokenName},
|
||||
},
|
||||
})
|
||||
// Add a token for the service account into the cache
|
||||
informerFactory.Core().InternalVersion().Secrets().Informer().GetStore().Add(&api.Secret{
|
||||
informerFactory.Core().V1().Secrets().Informer().GetStore().Add(&corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: tokenName,
|
||||
Namespace: ns,
|
||||
Annotations: map[string]string{
|
||||
api.ServiceAccountNameKey: serviceAccountName,
|
||||
api.ServiceAccountUIDKey: serviceAccountUID,
|
||||
corev1.ServiceAccountNameKey: serviceAccountName,
|
||||
corev1.ServiceAccountUIDKey: serviceAccountUID,
|
||||
},
|
||||
},
|
||||
Type: api.SecretTypeServiceAccountToken,
|
||||
Type: corev1.SecretTypeServiceAccountToken,
|
||||
Data: map[string][]byte{
|
||||
api.ServiceAccountTokenKey: []byte("token-data"),
|
||||
corev1.ServiceAccountTokenKey: []byte("token-data"),
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -531,17 +534,17 @@ func TestAllowsReferencedSecret(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.LimitSecretReferences = true
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
// Add the default service account for the ns with a secret reference into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
},
|
||||
Secrets: []api.ObjectReference{
|
||||
Secrets: []corev1.ObjectReference{
|
||||
{Name: "foo"},
|
||||
},
|
||||
})
|
||||
|
@ -612,12 +615,12 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.LimitSecretReferences = true
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
// Add the default service account for the ns into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
|
@ -690,12 +693,12 @@ func TestAllowUnreferencedSecretVolumesForPermissiveSAs(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.LimitSecretReferences = false
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
// Add the default service account for the ns into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
|
@ -722,17 +725,17 @@ func TestAllowsReferencedImagePullSecrets(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.LimitSecretReferences = true
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
// Add the default service account for the ns with a secret reference into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
},
|
||||
ImagePullSecrets: []api.LocalObjectReference{
|
||||
ImagePullSecrets: []corev1.LocalObjectReference{
|
||||
{Name: "foo"},
|
||||
},
|
||||
})
|
||||
|
@ -754,12 +757,12 @@ func TestRejectsUnreferencedImagePullSecrets(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.LimitSecretReferences = true
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
// Add the default service account for the ns into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
|
@ -783,17 +786,17 @@ func TestDoNotAddImagePullSecrets(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.LimitSecretReferences = true
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
// Add the default service account for the ns with a secret reference into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(&api.ServiceAccount{
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
},
|
||||
ImagePullSecrets: []api.LocalObjectReference{
|
||||
ImagePullSecrets: []corev1.LocalObjectReference{
|
||||
{Name: "foo"},
|
||||
{Name: "bar"},
|
||||
},
|
||||
|
@ -820,22 +823,22 @@ func TestAddImagePullSecrets(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.LimitSecretReferences = true
|
||||
admit.RequireAPIToken = false
|
||||
|
||||
sa := &api.ServiceAccount{
|
||||
sa := &corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
},
|
||||
ImagePullSecrets: []api.LocalObjectReference{
|
||||
ImagePullSecrets: []corev1.LocalObjectReference{
|
||||
{Name: "foo"},
|
||||
{Name: "bar"},
|
||||
},
|
||||
}
|
||||
// Add the default service account for the ns with a secret reference into the cache
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(sa)
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(sa)
|
||||
|
||||
pod := &api.Pod{}
|
||||
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil)
|
||||
|
@ -844,9 +847,7 @@ func TestAddImagePullSecrets(t *testing.T) {
|
|||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(pod.Spec.ImagePullSecrets) != 2 || !reflect.DeepEqual(sa.ImagePullSecrets, pod.Spec.ImagePullSecrets) {
|
||||
t.Errorf("expected %v, got %v", sa.ImagePullSecrets, pod.Spec.ImagePullSecrets)
|
||||
}
|
||||
assert.EqualValues(t, sa.ImagePullSecrets, pod.Spec.ImagePullSecrets, "expected %v, got %v", sa.ImagePullSecrets, pod.Spec.ImagePullSecrets)
|
||||
|
||||
pod.Spec.ImagePullSecrets[1] = api.LocalObjectReference{Name: "baz"}
|
||||
if reflect.DeepEqual(sa.ImagePullSecrets, pod.Spec.ImagePullSecrets) {
|
||||
|
@ -865,25 +866,25 @@ func TestMultipleReferencedSecrets(t *testing.T) {
|
|||
|
||||
admit := NewServiceAccount()
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
admit.SetInternalKubeInformerFactory(informerFactory)
|
||||
admit.SetExternalKubeInformerFactory(informerFactory)
|
||||
admit.MountServiceAccountToken = true
|
||||
admit.RequireAPIToken = true
|
||||
|
||||
sa := &api.ServiceAccount{
|
||||
sa := &corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: serviceAccountName,
|
||||
UID: types.UID(serviceAccountUID),
|
||||
Namespace: ns,
|
||||
},
|
||||
Secrets: []api.ObjectReference{
|
||||
Secrets: []corev1.ObjectReference{
|
||||
{Name: token1},
|
||||
{Name: token2},
|
||||
},
|
||||
}
|
||||
informerFactory.Core().InternalVersion().ServiceAccounts().Informer().GetStore().Add(sa)
|
||||
informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(sa)
|
||||
|
||||
// Add two tokens for the service account into the cache.
|
||||
informerFactory.Core().InternalVersion().Secrets().Informer().GetStore().Add(&api.Secret{
|
||||
informerFactory.Core().V1().Secrets().Informer().GetStore().Add(&corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: token2,
|
||||
Namespace: ns,
|
||||
|
@ -892,12 +893,12 @@ func TestMultipleReferencedSecrets(t *testing.T) {
|
|||
api.ServiceAccountUIDKey: serviceAccountUID,
|
||||
},
|
||||
},
|
||||
Type: api.SecretTypeServiceAccountToken,
|
||||
Type: corev1.SecretTypeServiceAccountToken,
|
||||
Data: map[string][]byte{
|
||||
api.ServiceAccountTokenKey: []byte("token-data"),
|
||||
},
|
||||
})
|
||||
informerFactory.Core().InternalVersion().Secrets().Informer().GetStore().Add(&api.Secret{
|
||||
informerFactory.Core().V1().Secrets().Informer().GetStore().Add(&corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: token1,
|
||||
Namespace: ns,
|
||||
|
@ -906,7 +907,7 @@ func TestMultipleReferencedSecrets(t *testing.T) {
|
|||
api.ServiceAccountUIDKey: serviceAccountUID,
|
||||
},
|
||||
},
|
||||
Type: api.SecretTypeServiceAccountToken,
|
||||
Type: corev1.SecretTypeServiceAccountToken,
|
||||
Data: map[string][]byte{
|
||||
api.ServiceAccountTokenKey: []byte("token-data"),
|
||||
},
|
||||
|
@ -934,14 +935,14 @@ func TestMultipleReferencedSecrets(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func newSecret(secretType api.SecretType, namespace, name, serviceAccountName, serviceAccountUID string) *api.Secret {
|
||||
return &api.Secret{
|
||||
func newSecret(secretType corev1.SecretType, namespace, name, serviceAccountName, serviceAccountUID string) *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
Annotations: map[string]string{
|
||||
api.ServiceAccountNameKey: serviceAccountName,
|
||||
api.ServiceAccountUIDKey: serviceAccountUID,
|
||||
corev1.ServiceAccountNameKey: serviceAccountName,
|
||||
corev1.ServiceAccountUIDKey: serviceAccountUID,
|
||||
},
|
||||
},
|
||||
Type: secretType,
|
||||
|
@ -951,12 +952,12 @@ func newSecret(secretType api.SecretType, namespace, name, serviceAccountName, s
|
|||
func TestGetServiceAccountTokens(t *testing.T) {
|
||||
admit := NewServiceAccount()
|
||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
|
||||
admit.secretLister = corelisters.NewSecretLister(indexer)
|
||||
admit.secretLister = corev1listers.NewSecretLister(indexer)
|
||||
|
||||
ns := "namespace"
|
||||
serviceAccountUID := "12345"
|
||||
|
||||
sa := &api.ServiceAccount{
|
||||
sa := &corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: DefaultServiceAccountName,
|
||||
Namespace: ns,
|
||||
|
@ -964,13 +965,13 @@ func TestGetServiceAccountTokens(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
nonSATokenSecret := newSecret(api.SecretTypeDockercfg, ns, "nonSATokenSecret", DefaultServiceAccountName, serviceAccountUID)
|
||||
nonSATokenSecret := newSecret(corev1.SecretTypeDockercfg, ns, "nonSATokenSecret", DefaultServiceAccountName, serviceAccountUID)
|
||||
indexer.Add(nonSATokenSecret)
|
||||
|
||||
differentSAToken := newSecret(api.SecretTypeServiceAccountToken, ns, "differentSAToken", "someOtherSA", "someOtherUID")
|
||||
differentSAToken := newSecret(corev1.SecretTypeServiceAccountToken, ns, "differentSAToken", "someOtherSA", "someOtherUID")
|
||||
indexer.Add(differentSAToken)
|
||||
|
||||
matchingSAToken := newSecret(api.SecretTypeServiceAccountToken, ns, "matchingSAToken", DefaultServiceAccountName, serviceAccountUID)
|
||||
matchingSAToken := newSecret(corev1.SecretTypeServiceAccountToken, ns, "matchingSAToken", DefaultServiceAccountName, serviceAccountUID)
|
||||
indexer.Add(matchingSAToken)
|
||||
|
||||
tokens, err := admit.getServiceAccountTokens(sa)
|
||||
|
|
|
@ -14,8 +14,6 @@ go_test(
|
|||
],
|
||||
tags = ["integration"],
|
||||
deps = [
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/controller/serviceaccount:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
|
|
|
@ -43,10 +43,9 @@ import (
|
|||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
internalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
|
@ -362,7 +361,7 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie
|
|||
// Root client
|
||||
// TODO: remove rootClient after we refactor pkg/admission to use the clientset.
|
||||
rootClientset := clientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken})
|
||||
internalRootClientset := internalclientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken})
|
||||
externalRootClientset := kubernetes.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken})
|
||||
// Set up two authenticators:
|
||||
// 1. A token authenticator that maps the rootToken to the "root" user
|
||||
// 2. A ServiceAccountToken authenticator that validates ServiceAccount tokens
|
||||
|
@ -417,9 +416,9 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie
|
|||
|
||||
// Set up admission plugin to auto-assign serviceaccounts to pods
|
||||
serviceAccountAdmission := serviceaccountadmission.NewServiceAccount()
|
||||
serviceAccountAdmission.SetInternalKubeClientSet(internalRootClientset)
|
||||
internalInformers := internalinformers.NewSharedInformerFactory(internalRootClientset, controller.NoResyncPeriodFunc())
|
||||
serviceAccountAdmission.SetInternalKubeInformerFactory(internalInformers)
|
||||
serviceAccountAdmission.SetExternalKubeClientSet(externalRootClientset)
|
||||
externalInformers := informers.NewSharedInformerFactory(externalRootClientset, controller.NoResyncPeriodFunc())
|
||||
serviceAccountAdmission.SetExternalKubeInformerFactory(externalInformers)
|
||||
informers := informers.NewSharedInformerFactory(rootClientset, controller.NoResyncPeriodFunc())
|
||||
|
||||
masterConfig := framework.NewMasterConfig()
|
||||
|
@ -457,7 +456,7 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie
|
|||
return rootClientset, clientConfig, stop, err
|
||||
}
|
||||
informers.Start(stopCh)
|
||||
internalInformers.Start(stopCh)
|
||||
externalInformers.Start(stopCh)
|
||||
go serviceAccountController.Run(5, stopCh)
|
||||
|
||||
return rootClientset, clientConfig, stop, nil
|
||||
|
|
Loading…
Reference in New Issue