github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/cli/opts/secret.go (about) 1 package opts 2 3 import ( 4 "encoding/csv" 5 "fmt" 6 "os" 7 "strconv" 8 "strings" 9 10 swarmtypes "github.com/docker/docker/api/types/swarm" 11 ) 12 13 // SecretOpt is a Value type for parsing secrets 14 type SecretOpt struct { 15 values []*swarmtypes.SecretReference 16 } 17 18 // Set a new secret value 19 func (o *SecretOpt) Set(value string) error { 20 csvReader := csv.NewReader(strings.NewReader(value)) 21 fields, err := csvReader.Read() 22 if err != nil { 23 return err 24 } 25 26 options := &swarmtypes.SecretReference{ 27 File: &swarmtypes.SecretReferenceFileTarget{ 28 UID: "0", 29 GID: "0", 30 Mode: 0444, 31 }, 32 } 33 34 // support a simple syntax of --secret foo 35 if len(fields) == 1 && !strings.Contains(fields[0], "=") { 36 options.File.Name = fields[0] 37 options.SecretName = fields[0] 38 o.values = append(o.values, options) 39 return nil 40 } 41 42 for _, field := range fields { 43 parts := strings.SplitN(field, "=", 2) 44 key := strings.ToLower(parts[0]) 45 46 if len(parts) != 2 { 47 return fmt.Errorf("invalid field '%s' must be a key=value pair", field) 48 } 49 50 value := parts[1] 51 switch key { 52 case "source", "src": 53 options.SecretName = value 54 case "target": 55 options.File.Name = value 56 case "uid": 57 options.File.UID = value 58 case "gid": 59 options.File.GID = value 60 case "mode": 61 m, err := strconv.ParseUint(value, 0, 32) 62 if err != nil { 63 return fmt.Errorf("invalid mode specified: %v", err) 64 } 65 66 options.File.Mode = os.FileMode(m) 67 default: 68 return fmt.Errorf("invalid field in secret request: %s", key) 69 } 70 } 71 72 if options.SecretName == "" { 73 return fmt.Errorf("source is required") 74 } 75 if options.File.Name == "" { 76 options.File.Name = options.SecretName 77 } 78 79 o.values = append(o.values, options) 80 return nil 81 } 82 83 // Type returns the type of this option 84 func (o *SecretOpt) Type() string { 85 return "secret" 86 } 87 88 // String returns a string repr of this option 89 func (o *SecretOpt) String() string { 90 secrets := []string{} 91 for _, secret := range o.values { 92 repr := fmt.Sprintf("%s -> %s", secret.SecretName, secret.File.Name) 93 secrets = append(secrets, repr) 94 } 95 return strings.Join(secrets, ", ") 96 } 97 98 // Value returns the secret requests 99 func (o *SecretOpt) Value() []*swarmtypes.SecretReference { 100 return o.values 101 }