Add option to require API tokens to exist in admission

This commit is contained in:
Jordan Liggitt
2015-06-29 21:31:46 -04:00
parent 96828f203c
commit ecebac9395
4 changed files with 63 additions and 20 deletions

View File

@@ -57,6 +57,8 @@ type serviceAccount struct {
// LimitSecretReferences rejects pods that reference secrets their service accounts do not reference
LimitSecretReferences bool
// RequireAPIToken determines whether pod creation attempts are rejected if no API token exists for the pod's service account
RequireAPIToken bool
// MountServiceAccountToken creates Volume and VolumeMounts for the first referenced ServiceAccountToken for the pod's service account
MountServiceAccountToken bool
@@ -110,6 +112,8 @@ func NewServiceAccount(cl client.Interface) *serviceAccount {
LimitSecretReferences: false,
// Auto mount service account API token secrets
MountServiceAccountToken: true,
// Reject pod creation until a service account token is available
RequireAPIToken: true,
client: cl,
serviceAccounts: serviceAccountsIndexer,
@@ -172,7 +176,8 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
return admission.NewForbidden(a, fmt.Errorf("Error looking up service account %s/%s: %v", a.GetNamespace(), pod.Spec.ServiceAccountName, err))
}
if serviceAccount == nil {
return admission.NewForbidden(a, fmt.Errorf("Missing service account %s/%s: %v", a.GetNamespace(), pod.Spec.ServiceAccountName, err))
// TODO: convert to a ServerTimeout error (or other error that sends a Retry-After header)
return admission.NewForbidden(a, fmt.Errorf("service account %s/%s was not found, retry after the service account is created", a.GetNamespace(), pod.Spec.ServiceAccountName))
}
if s.LimitSecretReferences {
@@ -320,10 +325,15 @@ func (s *serviceAccount) mountServiceAccountToken(serviceAccount *api.ServiceAcc
// Find the name of a referenced ServiceAccountToken secret we can mount
serviceAccountToken, err := s.getReferencedServiceAccountToken(serviceAccount)
if err != nil {
fmt.Errorf("Error looking up service account token for %s/%s: %v", serviceAccount.Namespace, serviceAccount.Name, err)
return fmt.Errorf("Error looking up service account token for %s/%s: %v", serviceAccount.Namespace, serviceAccount.Name, err)
}
if len(serviceAccountToken) == 0 {
// We don't have an API token to mount, so return
if s.RequireAPIToken {
// If a token is required, this is considered an error
// TODO: convert to a ServerTimeout error (or other error that sends a Retry-After header)
return fmt.Errorf("no API token found for service account %s/%s, retry after the token is automatically created and added to the service account", serviceAccount.Namespace, serviceAccount.Name)
}
return nil
}

View File

@@ -128,6 +128,7 @@ func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) {
admit := NewServiceAccount(nil)
admit.MountServiceAccountToken = true
admit.RequireAPIToken = false
// Add the default service account for the ns into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
@@ -148,6 +149,29 @@ func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) {
}
}
func TestAssignsDefaultServiceAccountAndRejectsMissingAPIToken(t *testing.T) {
ns := "myns"
admit := NewServiceAccount(nil)
admit.MountServiceAccountToken = true
admit.RequireAPIToken = true
// Add the default service account for the ns into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
ObjectMeta: api.ObjectMeta{
Name: DefaultServiceAccountName,
Namespace: ns,
},
})
pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil)
err := admit.Admit(attrs)
if err == nil {
t.Errorf("Expected admission error for missing API token")
}
}
func TestFetchesUncachedServiceAccount(t *testing.T) {
ns := "myns"
@@ -160,6 +184,7 @@ func TestFetchesUncachedServiceAccount(t *testing.T) {
})
admit := NewServiceAccount(client)
admit.RequireAPIToken = false
pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil)
@@ -208,6 +233,7 @@ func TestAutomountsAPIToken(t *testing.T) {
admit := NewServiceAccount(nil)
admit.MountServiceAccountToken = true
admit.RequireAPIToken = true
// Add the default service account for the ns with a token into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
@@ -279,6 +305,7 @@ func TestRespectsExistingMount(t *testing.T) {
admit := NewServiceAccount(nil)
admit.MountServiceAccountToken = true
admit.RequireAPIToken = true
// Add the default service account for the ns with a token into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
@@ -345,6 +372,7 @@ func TestAllowsReferencedSecretVolumes(t *testing.T) {
admit := NewServiceAccount(nil)
admit.LimitSecretReferences = true
admit.RequireAPIToken = false
// Add the default service account for the ns with a secret reference into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
@@ -376,6 +404,7 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
admit := NewServiceAccount(nil)
admit.LimitSecretReferences = true
admit.RequireAPIToken = false
// Add the default service account for the ns into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
@@ -404,6 +433,7 @@ func TestAllowsReferencedImagePullSecrets(t *testing.T) {
admit := NewServiceAccount(nil)
admit.LimitSecretReferences = true
admit.RequireAPIToken = false
// Add the default service account for the ns with a secret reference into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
@@ -433,6 +463,7 @@ func TestRejectsUnreferencedImagePullSecrets(t *testing.T) {
admit := NewServiceAccount(nil)
admit.LimitSecretReferences = true
admit.RequireAPIToken = false
// Add the default service account for the ns into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
@@ -459,6 +490,7 @@ func TestDoNotAddImagePullSecrets(t *testing.T) {
admit := NewServiceAccount(nil)
admit.LimitSecretReferences = true
admit.RequireAPIToken = false
// Add the default service account for the ns with a secret reference into the cache
admit.serviceAccounts.Add(&api.ServiceAccount{
@@ -493,6 +525,7 @@ func TestAddImagePullSecrets(t *testing.T) {
admit := NewServiceAccount(nil)
admit.LimitSecretReferences = true
admit.RequireAPIToken = false
sa := &api.ServiceAccount{
ObjectMeta: api.ObjectMeta{