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
Kubernetes Submit Queue 2018-08-22 19:19:07 -07:00 committed by GitHub
commit 687553a47a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 109 additions and 127 deletions

View File

@ -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
}

View File

@ -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",
],
)

View File

@ -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 {

View File

@ -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)

View File

@ -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",

View File

@ -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