github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/cli/external_ca.go (about) 1 package cli 2 3 import ( 4 "encoding/csv" 5 "errors" 6 "fmt" 7 "strings" 8 9 "github.com/docker/swarmkit/api" 10 ) 11 12 // ExternalCAOpt is a Value type for parsing external CA specifications. 13 type ExternalCAOpt struct { 14 values []*api.ExternalCA 15 } 16 17 // Set parses an external CA option. 18 func (m *ExternalCAOpt) Set(value string) error { 19 parsed, err := parseExternalCA(value) 20 if err != nil { 21 return err 22 } 23 24 m.values = append(m.values, parsed) 25 return nil 26 } 27 28 // Type returns the type of this option. 29 func (m *ExternalCAOpt) Type() string { 30 return "external-ca" 31 } 32 33 // String returns a string repr of this option. 34 func (m *ExternalCAOpt) String() string { 35 externalCAs := []string{} 36 for _, externalCA := range m.values { 37 repr := fmt.Sprintf("%s: %s", externalCA.Protocol, externalCA.URL) 38 externalCAs = append(externalCAs, repr) 39 } 40 return strings.Join(externalCAs, ", ") 41 } 42 43 // Value returns the external CAs 44 func (m *ExternalCAOpt) Value() []*api.ExternalCA { 45 return m.values 46 } 47 48 // parseExternalCA parses an external CA specification from the command line, 49 // such as protocol=cfssl,url=https://example.com. 50 func parseExternalCA(caSpec string) (*api.ExternalCA, error) { 51 csvReader := csv.NewReader(strings.NewReader(caSpec)) 52 fields, err := csvReader.Read() 53 if err != nil { 54 return nil, err 55 } 56 57 externalCA := api.ExternalCA{ 58 Options: make(map[string]string), 59 } 60 61 var ( 62 hasProtocol bool 63 hasURL bool 64 ) 65 66 for _, field := range fields { 67 parts := strings.SplitN(field, "=", 2) 68 69 if len(parts) != 2 { 70 return nil, fmt.Errorf("invalid field '%s' must be a key=value pair", field) 71 } 72 73 key, value := parts[0], parts[1] 74 75 switch strings.ToLower(key) { 76 case "protocol": 77 hasProtocol = true 78 if strings.ToLower(value) == "cfssl" { 79 externalCA.Protocol = api.ExternalCA_CAProtocolCFSSL 80 } else { 81 return nil, fmt.Errorf("unrecognized external CA protocol %s", value) 82 } 83 case "url": 84 hasURL = true 85 externalCA.URL = value 86 default: 87 externalCA.Options[key] = value 88 } 89 } 90 91 if !hasProtocol { 92 return nil, errors.New("the external-ca option needs a protocol= parameter") 93 } 94 if !hasURL { 95 return nil, errors.New("the external-ca option needs a url= parameter") 96 } 97 98 return &externalCA, nil 99 }