// TODO: when Secrets in kapi.ServiceAccount get changed to MountSecrets and represented by LocalObjectReferences, this can be // refactored to reuse the addition code better // addSecretsToServiceAccount adds secrets to the service account, either as pull secrets, mount secrets, or both. func (o AddSecretOptions) addSecretsToServiceAccount(serviceaccount *kapi.ServiceAccount) error { updated := false newSecrets, err := o.getSecrets() if err != nil { return err } newSecretNames := getSecretNames(newSecrets) if o.ForMount { currentSecrets := getMountSecretNames(serviceaccount) secretsToAdd := newSecretNames.Difference(currentSecrets) for _, secretName := range secretsToAdd.List() { serviceaccount.Secrets = append(serviceaccount.Secrets, kapi.ObjectReference{Name: secretName}) updated = true } } if o.ForPull { currentSecrets := getPullSecretNames(serviceaccount) secretsToAdd := newSecretNames.Difference(currentSecrets) for _, secretName := range secretsToAdd.List() { serviceaccount.ImagePullSecrets = append(serviceaccount.ImagePullSecrets, kapi.LocalObjectReference{Name: secretName}) updated = true } } if updated { _, err = o.ClientInterface.ServiceAccounts(o.Namespace).Update(serviceaccount) return err } return nil }
// removeSecretReferenceIfNeeded updates the given ServiceAccount to remove a reference to the given secretName if needed. // Returns whether an update was performed, and any error that occurred func (e *TokensController) removeSecretReferenceIfNeeded(serviceAccount *api.ServiceAccount, secretName string) (bool, error) { // See if the account even referenced the secret if !getSecretReferences(serviceAccount).Has(secretName) { return false, nil } // We don't want to update the cache's copy of the service account // so remove the secret from a freshly retrieved copy of the service account serviceAccounts := e.client.ServiceAccounts(serviceAccount.Namespace) serviceAccount, err := serviceAccounts.Get(serviceAccount.Name) if err != nil { return false, err } // Double-check to see if the account still references the secret if !getSecretReferences(serviceAccount).Has(secretName) { return false, nil } secrets := []api.ObjectReference{} for _, s := range serviceAccount.Secrets { if s.Name != secretName { secrets = append(secrets, s) } } serviceAccount.Secrets = secrets _, err = serviceAccounts.Update(serviceAccount) if err != nil { return false, err } return true, nil }
func (o AddSecretOptions) AddSecretsToSAMountableSecrets(serviceAccount *api.ServiceAccount) (*api.ServiceAccount, error) { secrets, err := o.getSecrets() if err != nil { return nil, err } if len(secrets) == 0 { return nil, errors.New("no secrets found") } currentSecrets := util.StringSet{} for _, secretRef := range serviceAccount.Secrets { currentSecrets.Insert(secretRef.Name) } for _, secret := range secrets { if currentSecrets.Has(secret.Name) { continue } serviceAccount.Secrets = append(serviceAccount.Secrets, api.ObjectReference{Name: secret.Name}) currentSecrets.Insert(secret.Name) } return o.ClientInterface.ServiceAccounts(o.Namespace).Update(serviceAccount) }
// createSecret creates a secret of type ServiceAccountToken for the given ServiceAccount func (e *TokensController) createSecret(serviceAccount *api.ServiceAccount) error { // Build the secret secret := &api.Secret{ ObjectMeta: api.ObjectMeta{ Name: secret.Strategy.GenerateName(fmt.Sprintf("%s-token-", serviceAccount.Name)), Namespace: serviceAccount.Namespace, Annotations: map[string]string{ api.ServiceAccountNameKey: serviceAccount.Name, api.ServiceAccountUIDKey: string(serviceAccount.UID), }, }, Type: api.SecretTypeServiceAccountToken, Data: map[string][]byte{}, } // Generate the token token, err := e.token.GenerateToken(*serviceAccount, *secret) if err != nil { return err } secret.Data[api.ServiceAccountTokenKey] = []byte(token) if e.rootCA != nil && len(e.rootCA) > 0 { secret.Data[api.ServiceAccountRootCAKey] = e.rootCA } // Save the secret if _, err := e.client.Secrets(serviceAccount.Namespace).Create(secret); err != nil { return err } // We don't want to update the cache's copy of the service account // so add the secret to a freshly retrieved copy of the service account serviceAccounts := e.client.ServiceAccounts(serviceAccount.Namespace) serviceAccount, err = serviceAccounts.Get(serviceAccount.Name) if err != nil { return err } serviceAccount.Secrets = append(serviceAccount.Secrets, api.ObjectReference{Name: secret.Name}) _, err = serviceAccounts.Update(serviceAccount) if err != nil { // we weren't able to use the token, try to clean it up. glog.V(2).Infof("Deleting secret %s/%s because reference couldn't be added (%v)", secret.Namespace, secret.Name, err) if err := e.client.Secrets(secret.Namespace).Delete(secret.Name); err != nil { glog.Error(err) // if we fail, just log it } } if apierrors.IsConflict(err) { // nothing to do. We got a conflict, that means that the service account was updated. We simply need to return because we'll get an update notification later return nil } return err }
func (o AddSecretOptions) AddSecretsToSAPullSecrets(serviceAccount *api.ServiceAccount) (*api.ServiceAccount, error) { secrets, err := o.getSecrets() if err != nil { return nil, err } currentSecrets := util.StringSet{} for _, secretRef := range serviceAccount.ImagePullSecrets { currentSecrets.Insert(secretRef.Name) } for _, secret := range secrets { if currentSecrets.Has(secret.Name) { continue } serviceAccount.ImagePullSecrets = append(serviceAccount.ImagePullSecrets, api.LocalObjectReference{Name: secret.Name}) currentSecrets.Insert(secret.Name) } return o.ClientInterface.ServiceAccounts(o.Namespace).Update(serviceAccount) }