github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/cmd/swarmctl/service/flagparser/secret.go (about)

     1  package flagparser
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/docker/swarmkit/api"
     8  	"github.com/docker/swarmkit/cmd/swarmctl/common"
     9  	"github.com/spf13/cobra"
    10  )
    11  
    12  // expects secrets in the format SECRET_NAME:TARGET_NAME
    13  func parseSecretString(secretString string) (secretName, presentName string, err error) {
    14  	tokens := strings.Split(secretString, ":")
    15  
    16  	secretName = strings.TrimSpace(tokens[0])
    17  
    18  	if secretName == "" {
    19  		err = fmt.Errorf("invalid secret name provided")
    20  		return
    21  	}
    22  
    23  	if len(tokens) > 1 {
    24  		presentName = strings.TrimSpace(tokens[1])
    25  		if presentName == "" {
    26  			err = fmt.Errorf("invalid presentation name provided")
    27  			return
    28  		}
    29  	} else {
    30  		presentName = secretName
    31  	}
    32  	return
    33  }
    34  
    35  // ParseAddSecret validates secrets passed on the command line
    36  func ParseAddSecret(cmd *cobra.Command, spec *api.ServiceSpec, flagName string) error {
    37  	flags := cmd.Flags()
    38  
    39  	if flags.Changed(flagName) {
    40  		secrets, err := flags.GetStringSlice(flagName)
    41  		if err != nil {
    42  			return err
    43  		}
    44  
    45  		container := spec.Task.GetContainer()
    46  		if container == nil {
    47  			spec.Task.Runtime = &api.TaskSpec_Container{
    48  				Container: &api.ContainerSpec{},
    49  			}
    50  		}
    51  
    52  		lookupSecretNames := []string{}
    53  		var needSecrets []*api.SecretReference
    54  
    55  		for _, secret := range secrets {
    56  			n, p, err := parseSecretString(secret)
    57  			if err != nil {
    58  				return err
    59  			}
    60  
    61  			// TODO(diogo): defaults to File targets, but in the future will take different types
    62  			secretRef := &api.SecretReference{
    63  				SecretName: n,
    64  				Target: &api.SecretReference_File{
    65  					File: &api.FileTarget{
    66  						Name: p,
    67  						Mode: 0444,
    68  					},
    69  				},
    70  			}
    71  
    72  			lookupSecretNames = append(lookupSecretNames, n)
    73  			needSecrets = append(needSecrets, secretRef)
    74  		}
    75  
    76  		client, err := common.Dial(cmd)
    77  		if err != nil {
    78  			return err
    79  		}
    80  
    81  		r, err := client.ListSecrets(common.Context(cmd),
    82  			&api.ListSecretsRequest{Filters: &api.ListSecretsRequest_Filters{Names: lookupSecretNames}})
    83  		if err != nil {
    84  			return err
    85  		}
    86  
    87  		foundSecrets := make(map[string]*api.Secret)
    88  		for _, secret := range r.Secrets {
    89  			foundSecrets[secret.Spec.Annotations.Name] = secret
    90  		}
    91  
    92  		for _, secretRef := range needSecrets {
    93  			secret, ok := foundSecrets[secretRef.SecretName]
    94  			if !ok {
    95  				return fmt.Errorf("secret not found: %s", secretRef.SecretName)
    96  			}
    97  
    98  			secretRef.SecretID = secret.ID
    99  			container.Secrets = append(container.Secrets, secretRef)
   100  		}
   101  	}
   102  
   103  	return nil
   104  }
   105  
   106  // ParseRemoveSecret removes a set of secrets from the task spec's secret references
   107  func ParseRemoveSecret(cmd *cobra.Command, spec *api.ServiceSpec, flagName string) error {
   108  	flags := cmd.Flags()
   109  
   110  	if flags.Changed(flagName) {
   111  		secrets, err := flags.GetStringSlice(flagName)
   112  		if err != nil {
   113  			return err
   114  		}
   115  
   116  		container := spec.Task.GetContainer()
   117  		if container == nil {
   118  			return nil
   119  		}
   120  
   121  		wantToDelete := make(map[string]struct{})
   122  
   123  		for _, secret := range secrets {
   124  			n, _, err := parseSecretString(secret)
   125  			if err != nil {
   126  				return err
   127  			}
   128  
   129  			wantToDelete[n] = struct{}{}
   130  		}
   131  
   132  		secretRefs := []*api.SecretReference{}
   133  
   134  		for _, secretRef := range container.Secrets {
   135  			if _, ok := wantToDelete[secretRef.SecretName]; ok {
   136  				continue
   137  			}
   138  			secretRefs = append(secretRefs, secretRef)
   139  		}
   140  
   141  		container.Secrets = secretRefs
   142  	}
   143  	return nil
   144  }