func (o *GetServiceAccountTokenOptions) Run() error { serviceAccount, err := o.SAClient.Get(o.SAName) if err != nil { return err } for _, reference := range serviceAccount.Secrets { secret, err := o.SecretsClient.Get(reference.Name) if err != nil { continue } if serviceaccounts.IsValidServiceAccountToken(serviceAccount, secret) { token, exists := secret.Data[kapi.ServiceAccountTokenKey] if !exists { return fmt.Errorf("service account token %q for service account %q did not contain token data", secret.Name, serviceAccount.Name) } fmt.Fprintf(o.Out, string(token)) if util.IsTerminalWriter(o.Out) { // pretty-print for a TTY fmt.Fprintf(o.Out, "\n") } return nil } } return fmt.Errorf("could not find a service account token for service account %q", serviceAccount.Name) }
func GetClientForServiceAccount(adminClient *kclientset.Clientset, clientConfig restclient.Config, namespace, name string) (*client.Client, *kclientset.Clientset, *restclient.Config, error) { _, err := adminClient.Core().Namespaces().Create(&kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: namespace}}) if err != nil && !kerrs.IsAlreadyExists(err) { return nil, nil, nil, err } sa, err := adminClient.Core().ServiceAccounts(namespace).Create(&kapi.ServiceAccount{ObjectMeta: kapi.ObjectMeta{Name: name}}) if kerrs.IsAlreadyExists(err) { sa, err = adminClient.Core().ServiceAccounts(namespace).Get(name) } if err != nil { return nil, nil, nil, err } token := "" err = wait.Poll(time.Second, 30*time.Second, func() (bool, error) { selector := fields.OneTermEqualSelector(kapi.SecretTypeField, string(kapi.SecretTypeServiceAccountToken)) secrets, err := adminClient.Core().Secrets(namespace).List(kapi.ListOptions{FieldSelector: selector}) if err != nil { return false, err } for _, secret := range secrets.Items { if serviceaccounts.IsValidServiceAccountToken(sa, &secret) { token = string(secret.Data[kapi.ServiceAccountTokenKey]) return true, nil } } return false, nil }) if err != nil { return nil, nil, nil, err } saClientConfig := clientcmd.AnonymousClientConfig(&clientConfig) saClientConfig.BearerToken = token kubeClient, err := kclient.New(&saClientConfig) if err != nil { return nil, nil, nil, err } kubeClientset := adapter.FromUnversionedClient(kubeClient) osClient, err := client.New(&saClientConfig) if err != nil { return nil, nil, nil, err } return osClient, kubeClientset, &saClientConfig, nil }
// waitForToken uses `cmd.Until` to wait for the service account controller to fulfill the token request func waitForToken(token *api.Secret, serviceAccount *api.ServiceAccount, timeout time.Duration, client unversioned.SecretsInterface) (*api.Secret, error) { // there is no provided rounding function, so we use Round(x) === Floor(x + 0.5) timeoutSeconds := int64(math.Floor(timeout.Seconds() + 0.5)) options := api.ListOptions{ FieldSelector: fields.SelectorFromSet(fields.Set(map[string]string{"metadata.name": token.Name})), Watch: true, ResourceVersion: token.ResourceVersion, TimeoutSeconds: &timeoutSeconds, } watcher, err := client.Watch(options) if err != nil { return nil, fmt.Errorf("could not begin watch for token: %v", err) } event, err := cmd.Until(timeout, watcher, func(event watch.Event) (bool, error) { if event.Type == watch.Error { return false, fmt.Errorf("encountered error while watching for token: %v", event.Object) } eventToken, ok := event.Object.(*api.Secret) if !ok { return false, nil } if eventToken.Name != token.Name { return false, nil } switch event.Type { case watch.Modified: if serviceaccounts.IsValidServiceAccountToken(serviceAccount, eventToken) { return true, nil } case watch.Deleted: return false, errors.New("token was deleted before fulfillment by service account token controller") case watch.Added: return false, errors.New("unxepected action: token was added after initial creation") } return false, nil }) if err != nil { return nil, err } return event.Object.(*api.Secret), nil }
func (o *CreateKubeconfigOptions) Run() error { serviceAccount, err := o.SAClient.Get(o.SAName) if err != nil { return err } for _, reference := range serviceAccount.Secrets { secret, err := o.SecretsClient.Get(reference.Name) if err != nil { continue } if serviceaccounts.IsValidServiceAccountToken(serviceAccount, secret) { token, exists := secret.Data[kapi.ServiceAccountTokenKey] if !exists { return fmt.Errorf("service account token %q for service account %q did not contain token data", secret.Name, serviceAccount.Name) } cfg := &o.RawConfig if err := clientcmdapi.MinifyConfig(cfg); err != nil { return fmt.Errorf("invalid configuration, unable to create new config file: %v", err) } ctx := cfg.Contexts[cfg.CurrentContext] ctx.Namespace = o.ContextNamespace // rename the current context cfg.CurrentContext = o.SAName cfg.Contexts = map[string]*clientcmdapi.Context{ cfg.CurrentContext: ctx, } // use the server name ctx.AuthInfo = o.SAName cfg.AuthInfos = map[string]*clientcmdapi.AuthInfo{ ctx.AuthInfo: { Token: string(token), }, } out, err := kclientcmd.Write(*cfg) if err != nil { return err } fmt.Fprintf(o.Out, string(out)) return nil } } return fmt.Errorf("could not find a service account token for service account %q", serviceAccount.Name) }