... | ... |
@@ -802,6 +802,25 @@ Create a new secret based on a key file or on files within a directory |
802 | 802 |
==== |
803 | 803 |
|
804 | 804 |
|
805 |
+== oc secrets new-basicauth |
|
806 |
+Create a new secret for basic authentication |
|
807 |
+ |
|
808 |
+==== |
|
809 |
+ |
|
810 |
+[options="nowrap"] |
|
811 |
+---- |
|
812 |
+ // If your basic authentication method requires only username and password or token, add it by using: |
|
813 |
+ $ openshift cli secrets new-basicauth SECRET --username=USERNAME --password=PASSWORD |
|
814 |
+ |
|
815 |
+ // If your basic authentication method requires also CA certificate, add it by using: |
|
816 |
+ $ openshift cli secrets new-basicauth SECRET --username=USERNAME --password=PASSWORD --ca-cert=FILENAME |
|
817 |
+ |
|
818 |
+ // If you do already have a .gitconfig file needed for authentication, you can create a gitconfig secret by using: |
|
819 |
+ $ openshift cli secrets new SECRET path/to/.gitconfig |
|
820 |
+---- |
|
821 |
+==== |
|
822 |
+ |
|
823 |
+ |
|
805 | 824 |
== oc secrets new-dockercfg |
806 | 825 |
Create a new dockercfg secret |
807 | 826 |
|
... | ... |
@@ -810,10 +829,10 @@ Create a new dockercfg secret |
810 | 810 |
[options="nowrap"] |
811 | 811 |
---- |
812 | 812 |
// If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using: |
813 |
- $ openshift cli secrets new-dockercfg SECRET_NAME --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL |
|
813 |
+ $ openshift cli secrets new-dockercfg SECRET --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL |
|
814 | 814 |
|
815 | 815 |
// If you do already have a .dockercfg file, you can create a dockercfg secret by using: |
816 |
- $ openshift cli secrets new SECRET_NAME path/to/.dockercfg |
|
816 |
+ $ openshift cli secrets new SECRET path/to/.dockercfg |
|
817 | 817 |
|
818 | 818 |
// To add new secret to 'imagePullSecrets' for the node, or 'secrets' for builds, use: |
819 | 819 |
$ openshift cli edit SERVICE_ACCOUNT |
... | ... |
@@ -821,6 +840,25 @@ Create a new dockercfg secret |
821 | 821 |
==== |
822 | 822 |
|
823 | 823 |
|
824 |
+== oc secrets new-sshauth |
|
825 |
+Create a new secret for SSH authentication |
|
826 |
+ |
|
827 |
+==== |
|
828 |
+ |
|
829 |
+[options="nowrap"] |
|
830 |
+---- |
|
831 |
+ // If your SSH authentication method requires only private SSH key, add it by using: |
|
832 |
+ $ openshift cli secrets new-sshauth SECRET --ssh-privatekey=FILENAME |
|
833 |
+ |
|
834 |
+ // If your SSH authentication method requires also CA certificate, add it by using: |
|
835 |
+ $ openshift cli secrets new-sshauth SECRET --ssh-privatekey=FILENAME --ca-cert=FILENAME |
|
836 |
+ |
|
837 |
+ // If you do already have a .gitconfig file needed for authentication, you can create a gitconfig secret by using: |
|
838 |
+ $ openshift cli secrets new SECRET path/to/.gitconfig |
|
839 |
+---- |
|
840 |
+==== |
|
841 |
+ |
|
842 |
+ |
|
824 | 843 |
== oc start-build |
825 | 844 |
Starts a new build |
826 | 845 |
|
... | ... |
@@ -481,7 +481,24 @@ function cleanup_openshift { |
481 | 481 |
|
482 | 482 |
echo "[INFO] Cleanup complete" |
483 | 483 |
set -e |
484 |
-} |
|
484 |
+} |
|
485 |
+ |
|
486 |
+# create a .gitconfig for test-cmd secrets |
|
487 |
+function create_gitconfig { |
|
488 |
+ USERNAME=sample-user |
|
489 |
+ PASSWORD=password |
|
490 |
+ GITCONFIG_DIR=$(mktemp -d /tmp/test-gitconfig.XXXX) |
|
491 |
+ touch ${GITCONFIG_DIR}/.gitconfig |
|
492 |
+ git config --file ${GITCONFIG_DIR}/.gitconfig user.name ${USERNAME} |
|
493 |
+ git config --file ${GITCONFIG_DIR}/.gitconfig user.token ${PASSWORD} |
|
494 |
+ echo ${GITCONFIG_DIR}/.gitconfig |
|
495 |
+} |
|
496 |
+ |
|
497 |
+function create_valid_file { |
|
498 |
+ FILE_DIR=$(mktemp -d /tmp/test-file.XXXX) |
|
499 |
+ touch ${FILE_DIR}/${1} |
|
500 |
+ echo ${FILE_DIR}/${1} |
|
501 |
+} |
|
485 | 502 |
|
486 | 503 |
# install the router for the extended tests |
487 | 504 |
function install_router { |
... | ... |
@@ -129,7 +129,7 @@ func NewCommandCLI(name, fullName string, out io.Writer) *cobra.Command { |
129 | 129 |
cmd.NewCmdRun(fullName, f, in, out, errout), |
130 | 130 |
cmd.NewCmdAttach(fullName, f, in, out, errout), |
131 | 131 |
policy.NewCmdPolicy(policy.PolicyRecommendedName, fullName+" "+policy.PolicyRecommendedName, f, out), |
132 |
- secrets.NewCmdSecrets(secrets.SecretsRecommendedName, fullName+" "+secrets.SecretsRecommendedName, f, out, fullName+" edit"), |
|
132 |
+ secrets.NewCmdSecrets(secrets.SecretsRecommendedName, fullName+" "+secrets.SecretsRecommendedName, f, in, out, fullName+" edit"), |
|
133 | 133 |
}, |
134 | 134 |
}, |
135 | 135 |
{ |
136 | 136 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,215 @@ |
0 |
+package secrets |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "errors" |
|
4 |
+ "fmt" |
|
5 |
+ "io" |
|
6 |
+ "io/ioutil" |
|
7 |
+ |
|
8 |
+ "k8s.io/kubernetes/pkg/api" |
|
9 |
+ "k8s.io/kubernetes/pkg/client" |
|
10 |
+ kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
|
11 |
+ |
|
12 |
+ cmdutil "github.com/openshift/origin/pkg/cmd/util" |
|
13 |
+ |
|
14 |
+ "github.com/spf13/cobra" |
|
15 |
+) |
|
16 |
+ |
|
17 |
+const ( |
|
18 |
+ // CreateBasicAuthSecretRecommendedCommandName represents name of subcommand for `oc secrets` command |
|
19 |
+ CreateBasicAuthSecretRecommendedCommandName = "new-basicauth" |
|
20 |
+ |
|
21 |
+ createBasicAuthSecretLong = ` |
|
22 |
+Create a new basic authentication secret |
|
23 |
+ |
|
24 |
+Basic authenticate secrets are used to authenticate against SCM servers. |
|
25 |
+ |
|
26 |
+When creating applications, you may have a SCM server that requires basic authentication - username, password. |
|
27 |
+In order for the nodes to clone source code on your behalf, they have to have the credentials. You can provide |
|
28 |
+this information by creating a 'basicauth' secret and attaching it to your service account.` |
|
29 |
+ |
|
30 |
+ createBasicAuthSecretExample = ` // If your basic authentication method requires only username and password or token, add it by using: |
|
31 |
+ $ %[1]s SECRET --username=USERNAME --password=PASSWORD |
|
32 |
+ |
|
33 |
+ // If your basic authentication method requires also CA certificate, add it by using: |
|
34 |
+ $ %[1]s SECRET --username=USERNAME --password=PASSWORD --ca-cert=FILENAME |
|
35 |
+ |
|
36 |
+ // If you do already have a .gitconfig file needed for authentication, you can create a gitconfig secret by using: |
|
37 |
+ $ %[2]s SECRET path/to/.gitconfig` |
|
38 |
+) |
|
39 |
+ |
|
40 |
+// CreateBasicAuthSecretOptions holds the credential needed to authenticate against SCM servers. |
|
41 |
+type CreateBasicAuthSecretOptions struct { |
|
42 |
+ SecretName string |
|
43 |
+ Username string |
|
44 |
+ Password string |
|
45 |
+ CertificatePath string |
|
46 |
+ GitConfigPath string |
|
47 |
+ |
|
48 |
+ PromptForPassword bool |
|
49 |
+ |
|
50 |
+ Reader io.Reader |
|
51 |
+ Out io.Writer |
|
52 |
+ |
|
53 |
+ SecretsInterface client.SecretsInterface |
|
54 |
+} |
|
55 |
+ |
|
56 |
+// NewCmdCreateBasicAuthSecret implements the OpenShift cli secrets new-basicauth subcommand |
|
57 |
+func NewCmdCreateBasicAuthSecret(name, fullName string, f *kcmdutil.Factory, reader io.Reader, out io.Writer, newSecretFullName, ocEditFullName string) *cobra.Command { |
|
58 |
+ o := &CreateBasicAuthSecretOptions{ |
|
59 |
+ Out: out, |
|
60 |
+ Reader: reader, |
|
61 |
+ } |
|
62 |
+ |
|
63 |
+ cmd := &cobra.Command{ |
|
64 |
+ Use: fmt.Sprintf("%s SECRET_NAME --username=USERNAME --password=PASSWORD [--ca-cert=FILENAME --gitconfig=FILENAME]", name), |
|
65 |
+ Short: "Create a new secret for basic authentication", |
|
66 |
+ Long: createBasicAuthSecretLong, |
|
67 |
+ Example: fmt.Sprintf(createBasicAuthSecretExample, fullName, newSecretFullName, ocEditFullName), |
|
68 |
+ Run: func(c *cobra.Command, args []string) { |
|
69 |
+ if err := o.Complete(f, args); err != nil { |
|
70 |
+ kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error())) |
|
71 |
+ } |
|
72 |
+ |
|
73 |
+ if err := o.Validate(); err != nil { |
|
74 |
+ kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error())) |
|
75 |
+ } |
|
76 |
+ |
|
77 |
+ if len(kcmdutil.GetFlagString(c, "output")) != 0 { |
|
78 |
+ secret, err := o.NewBasicAuthSecret() |
|
79 |
+ kcmdutil.CheckErr(err) |
|
80 |
+ |
|
81 |
+ kcmdutil.CheckErr(f.PrintObject(c, secret, out)) |
|
82 |
+ return |
|
83 |
+ } |
|
84 |
+ |
|
85 |
+ if err := o.CreateBasicAuthSecret(); err != nil { |
|
86 |
+ kcmdutil.CheckErr(err) |
|
87 |
+ } |
|
88 |
+ }, |
|
89 |
+ } |
|
90 |
+ |
|
91 |
+ cmd.Flags().StringVar(&o.Username, "username", "", "Username for Git authentication") |
|
92 |
+ cmd.Flags().StringVar(&o.Password, "password", "", "Password or token for Git authentication") |
|
93 |
+ cmd.Flags().StringVar(&o.CertificatePath, "ca-cert", "", "Path to a certificate file") |
|
94 |
+ cmd.Flags().StringVar(&o.GitConfigPath, "gitconfig", "", "Path to a .gitconfig file") |
|
95 |
+ cmd.Flags().BoolVarP(&o.PromptForPassword, "prompt", "", false, "Prompt for password or token") |
|
96 |
+ |
|
97 |
+ // autocompletion hints |
|
98 |
+ cmd.MarkFlagFilename("ca-cert") |
|
99 |
+ cmd.MarkFlagFilename("gitconfig") |
|
100 |
+ |
|
101 |
+ kcmdutil.AddPrinterFlags(cmd) |
|
102 |
+ |
|
103 |
+ return cmd |
|
104 |
+} |
|
105 |
+ |
|
106 |
+// CreateBasicAuthSecret saves created Secret structure and prints the secret name to the output on success. |
|
107 |
+func (o *CreateBasicAuthSecretOptions) CreateBasicAuthSecret() error { |
|
108 |
+ secret, err := o.NewBasicAuthSecret() |
|
109 |
+ if err != nil { |
|
110 |
+ return err |
|
111 |
+ } |
|
112 |
+ |
|
113 |
+ if _, err := o.SecretsInterface.Create(secret); err != nil { |
|
114 |
+ return err |
|
115 |
+ } |
|
116 |
+ |
|
117 |
+ fmt.Fprintf(o.GetOut(), "secret/%s\n", secret.Name) |
|
118 |
+ return nil |
|
119 |
+} |
|
120 |
+ |
|
121 |
+// NewBasicAuthSecret builds up the Secret structure containing secret name, type and data structure |
|
122 |
+// containing desired credentials. |
|
123 |
+func (o *CreateBasicAuthSecretOptions) NewBasicAuthSecret() (*api.Secret, error) { |
|
124 |
+ secret := &api.Secret{} |
|
125 |
+ secret.Name = o.SecretName |
|
126 |
+ secret.Type = api.SecretTypeOpaque |
|
127 |
+ secret.Data = map[string][]byte{} |
|
128 |
+ |
|
129 |
+ if len(o.Username) != 0 { |
|
130 |
+ secret.Data[SourceUsername] = []byte(o.Username) |
|
131 |
+ } |
|
132 |
+ |
|
133 |
+ if len(o.Password) != 0 { |
|
134 |
+ secret.Data[SourcePassword] = []byte(o.Password) |
|
135 |
+ } |
|
136 |
+ |
|
137 |
+ if len(o.CertificatePath) != 0 { |
|
138 |
+ caContent, err := ioutil.ReadFile(o.CertificatePath) |
|
139 |
+ if err != nil { |
|
140 |
+ return nil, err |
|
141 |
+ } |
|
142 |
+ secret.Data[SourceCertificate] = caContent |
|
143 |
+ } |
|
144 |
+ |
|
145 |
+ if len(o.GitConfigPath) != 0 { |
|
146 |
+ gitConfig, err := ioutil.ReadFile(o.GitConfigPath) |
|
147 |
+ if err != nil { |
|
148 |
+ return nil, err |
|
149 |
+ } |
|
150 |
+ secret.Data[SourceGitConfig] = gitConfig |
|
151 |
+ } |
|
152 |
+ |
|
153 |
+ return secret, nil |
|
154 |
+} |
|
155 |
+ |
|
156 |
+// Complete fills CreateBasicAuthSecretOptions fields with data and checks for mutual exclusivity |
|
157 |
+// between flags from different option groups. |
|
158 |
+func (o *CreateBasicAuthSecretOptions) Complete(f *kcmdutil.Factory, args []string) error { |
|
159 |
+ if len(args) != 1 { |
|
160 |
+ return errors.New("must have exactly one argument: secret name") |
|
161 |
+ } |
|
162 |
+ o.SecretName = args[0] |
|
163 |
+ |
|
164 |
+ if f != nil { |
|
165 |
+ client, err := f.Client() |
|
166 |
+ if err != nil { |
|
167 |
+ return err |
|
168 |
+ } |
|
169 |
+ namespace, _, err := f.DefaultNamespace() |
|
170 |
+ if err != nil { |
|
171 |
+ return err |
|
172 |
+ } |
|
173 |
+ o.SecretsInterface = client.Secrets(namespace) |
|
174 |
+ } |
|
175 |
+ |
|
176 |
+ return nil |
|
177 |
+} |
|
178 |
+ |
|
179 |
+// Validate check if all necessary fields from CreateBasicAuthSecretOptions are present. |
|
180 |
+func (o CreateBasicAuthSecretOptions) Validate() error { |
|
181 |
+ if len(o.SecretName) == 0 { |
|
182 |
+ return errors.New("basic authentication secret name must be present") |
|
183 |
+ } |
|
184 |
+ |
|
185 |
+ if o.PromptForPassword { |
|
186 |
+ if len(o.Password) != 0 { |
|
187 |
+ return errors.New("must provide either --prompt or --password flag") |
|
188 |
+ } |
|
189 |
+ if cmdutil.IsTerminal(o.Reader) { |
|
190 |
+ o.Password = cmdutil.PromptForPasswordString(o.Reader, o.Out, "Password: ") |
|
191 |
+ if len(o.Password) == 0 { |
|
192 |
+ return errors.New("password must be provided") |
|
193 |
+ } |
|
194 |
+ } else { |
|
195 |
+ return errors.New("provided reader is not a terminal") |
|
196 |
+ } |
|
197 |
+ } else { |
|
198 |
+ if len(o.Username) == 0 && len(o.Password) == 0 && len(o.CertificatePath) == 0 { |
|
199 |
+ return errors.New("must provide basic authentication credentials") |
|
200 |
+ } |
|
201 |
+ } |
|
202 |
+ |
|
203 |
+ return nil |
|
204 |
+} |
|
205 |
+ |
|
206 |
+// GetOut check if the CreateBasicAuthSecretOptions Out Writer is set. Returns it if the Writer |
|
207 |
+// is present, if not returns Writer on which all Write calls succeed without doing anything. |
|
208 |
+func (o CreateBasicAuthSecretOptions) GetOut() io.Writer { |
|
209 |
+ if o.Out == nil { |
|
210 |
+ return ioutil.Discard |
|
211 |
+ } |
|
212 |
+ |
|
213 |
+ return o.Out |
|
214 |
+} |
0 | 215 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,78 @@ |
0 |
+package secrets |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "testing" |
|
4 |
+) |
|
5 |
+ |
|
6 |
+func TestValidateBasicAuth(t *testing.T) { |
|
7 |
+ tests := []struct { |
|
8 |
+ testName string |
|
9 |
+ args []string |
|
10 |
+ params CreateBasicAuthSecretOptions |
|
11 |
+ expErr bool |
|
12 |
+ }{ |
|
13 |
+ { |
|
14 |
+ testName: "validArgs", |
|
15 |
+ args: []string{"testSecret"}, |
|
16 |
+ params: CreateBasicAuthSecretOptions{ |
|
17 |
+ Username: "testUser", |
|
18 |
+ Password: "testPassword", |
|
19 |
+ }, |
|
20 |
+ expErr: false, |
|
21 |
+ }, |
|
22 |
+ { |
|
23 |
+ testName: "validArgsWithCertificate", |
|
24 |
+ args: []string{"testSecret"}, |
|
25 |
+ params: CreateBasicAuthSecretOptions{ |
|
26 |
+ Username: "testUser", |
|
27 |
+ Password: "testPassword", |
|
28 |
+ CertificatePath: "./bsFixtures/valid/ca.crt", |
|
29 |
+ }, |
|
30 |
+ expErr: false, |
|
31 |
+ }, |
|
32 |
+ { |
|
33 |
+ testName: "validArgsWithGitconfig", |
|
34 |
+ args: []string{"testSecret"}, |
|
35 |
+ params: CreateBasicAuthSecretOptions{ |
|
36 |
+ Username: "testUser", |
|
37 |
+ Password: "testPassword", |
|
38 |
+ GitConfigPath: "./bsFixtures/leadingdot/.gitconfig", |
|
39 |
+ }, |
|
40 |
+ expErr: false, |
|
41 |
+ }, |
|
42 |
+ { |
|
43 |
+ testName: "noName", |
|
44 |
+ args: []string{}, |
|
45 |
+ params: CreateBasicAuthSecretOptions{ |
|
46 |
+ Username: "testUser", |
|
47 |
+ Password: "testPassword", |
|
48 |
+ }, |
|
49 |
+ expErr: true, //"Must have exactly one argument: secret name" |
|
50 |
+ }, |
|
51 |
+ { |
|
52 |
+ testName: "noParams", |
|
53 |
+ args: []string{"testSecret"}, |
|
54 |
+ params: CreateBasicAuthSecretOptions{}, |
|
55 |
+ expErr: true, //"Must provide basic authentication credentials" |
|
56 |
+ }, |
|
57 |
+ { |
|
58 |
+ testName: "passwordAndPrompt", |
|
59 |
+ args: []string{"testSecret"}, |
|
60 |
+ params: CreateBasicAuthSecretOptions{ |
|
61 |
+ Username: "testUser", |
|
62 |
+ Password: "testPassword", |
|
63 |
+ PromptForPassword: true, |
|
64 |
+ }, |
|
65 |
+ expErr: true, //"Must provide either --prompt or --password flag" |
|
66 |
+ }, |
|
67 |
+ } |
|
68 |
+ |
|
69 |
+ for _, test := range tests { |
|
70 |
+ options := test.params |
|
71 |
+ options.Complete(nil, test.args) |
|
72 |
+ err := options.Validate() |
|
73 |
+ if err != nil && !test.expErr { |
|
74 |
+ t.Errorf("%s: unexpected error: %v", test.testName, err) |
|
75 |
+ } |
|
76 |
+ } |
|
77 |
+} |
... | ... |
@@ -34,17 +34,16 @@ nodes to pull images on your behalf, they have to have the credentials. You can |
34 | 34 |
by creating a dockercfg secret and attaching it to your service account.` |
35 | 35 |
|
36 | 36 |
createDockercfgExample = ` // If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using: |
37 |
- $ %[1]s SECRET_NAME --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL |
|
37 |
+ $ %[1]s SECRET --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL |
|
38 | 38 |
|
39 | 39 |
// If you do already have a .dockercfg file, you can create a dockercfg secret by using: |
40 |
- $ %[2]s SECRET_NAME path/to/.dockercfg |
|
40 |
+ $ %[2]s SECRET path/to/.dockercfg |
|
41 | 41 |
|
42 | 42 |
// To add new secret to 'imagePullSecrets' for the node, or 'secrets' for builds, use: |
43 | 43 |
$ %[3]s SERVICE_ACCOUNT` |
44 | 44 |
) |
45 | 45 |
|
46 | 46 |
type CreateDockerConfigOptions struct { |
47 |
- SecretNamespace string |
|
48 | 47 |
SecretName string |
49 | 48 |
RegistryLocation string |
50 | 49 |
Username string |
... | ... |
@@ -75,7 +74,7 @@ func NewCmdCreateDockerConfigSecret(name, fullName string, f *cmdutil.Factory, o |
75 | 75 |
} |
76 | 76 |
|
77 | 77 |
if len(cmdutil.GetFlagString(c, "output")) != 0 { |
78 |
- secret, err := o.MakeDockerSecret() |
|
78 |
+ secret, err := o.NewDockerSecret() |
|
79 | 79 |
cmdutil.CheckErr(err) |
80 | 80 |
|
81 | 81 |
cmdutil.CheckErr(f.PrintObject(c, secret, out)) |
... | ... |
@@ -99,7 +98,7 @@ func NewCmdCreateDockerConfigSecret(name, fullName string, f *cmdutil.Factory, o |
99 | 99 |
} |
100 | 100 |
|
101 | 101 |
func (o CreateDockerConfigOptions) CreateDockerSecret() error { |
102 |
- secret, err := o.MakeDockerSecret() |
|
102 |
+ secret, err := o.NewDockerSecret() |
|
103 | 103 |
if err != nil { |
104 | 104 |
return err |
105 | 105 |
} |
... | ... |
@@ -113,7 +112,7 @@ func (o CreateDockerConfigOptions) CreateDockerSecret() error { |
113 | 113 |
return nil |
114 | 114 |
} |
115 | 115 |
|
116 |
-func (o CreateDockerConfigOptions) MakeDockerSecret() (*api.Secret, error) { |
|
116 |
+func (o CreateDockerConfigOptions) NewDockerSecret() (*api.Secret, error) { |
|
117 | 117 |
dockercfgAuth := credentialprovider.DockerConfigEntry{ |
118 | 118 |
Username: o.Username, |
119 | 119 |
Password: o.Password, |
... | ... |
@@ -128,7 +127,6 @@ func (o CreateDockerConfigOptions) MakeDockerSecret() (*api.Secret, error) { |
128 | 128 |
} |
129 | 129 |
|
130 | 130 |
secret := &api.Secret{} |
131 |
- secret.Namespace = o.SecretNamespace |
|
132 | 131 |
secret.Name = o.SecretName |
133 | 132 |
secret.Type = api.SecretTypeDockercfg |
134 | 133 |
secret.Data = map[string][]byte{} |
... | ... |
@@ -147,20 +145,17 @@ func (o *CreateDockerConfigOptions) Complete(f *cmdutil.Factory, args []string) |
147 | 147 |
if err != nil { |
148 | 148 |
return err |
149 | 149 |
} |
150 |
- o.SecretNamespace, _, err = f.DefaultNamespace() |
|
150 |
+ namespace, _, err := f.DefaultNamespace() |
|
151 | 151 |
if err != nil { |
152 | 152 |
return err |
153 | 153 |
} |
154 | 154 |
|
155 |
- o.SecretsInterface = client.Secrets(o.SecretNamespace) |
|
155 |
+ o.SecretsInterface = client.Secrets(namespace) |
|
156 | 156 |
|
157 | 157 |
return nil |
158 | 158 |
} |
159 | 159 |
|
160 | 160 |
func (o CreateDockerConfigOptions) Validate() error { |
161 |
- if len(o.SecretNamespace) == 0 { |
|
162 |
- return errors.New("secret namespace must be present") |
|
163 |
- } |
|
164 | 161 |
if len(o.SecretName) == 0 { |
165 | 162 |
return errors.New("secret name must be present") |
166 | 163 |
} |
167 | 164 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,195 @@ |
0 |
+package secrets |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "errors" |
|
4 |
+ "fmt" |
|
5 |
+ "io" |
|
6 |
+ "io/ioutil" |
|
7 |
+ |
|
8 |
+ "k8s.io/kubernetes/pkg/api" |
|
9 |
+ "k8s.io/kubernetes/pkg/client" |
|
10 |
+ kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
|
11 |
+ |
|
12 |
+ "github.com/spf13/cobra" |
|
13 |
+) |
|
14 |
+ |
|
15 |
+const ( |
|
16 |
+ // CreateSSHAuthSecretRecommendedCommandName represents name of subcommand for `oc secrets` command |
|
17 |
+ CreateSSHAuthSecretRecommendedCommandName = "new-sshauth" |
|
18 |
+ |
|
19 |
+ createSSHAuthSecretLong = ` |
|
20 |
+Create a new SSH authentication secret |
|
21 |
+ |
|
22 |
+SSH authentication secrets are used to authenticate against SCM servers. |
|
23 |
+ |
|
24 |
+When creating applications, you may have a SCM server that requires SSH authentication - private SSH key. |
|
25 |
+In order for the nodes to clone source code on your behalf, they have to have the credentials. You can |
|
26 |
+provide this information by creating a 'sshauth' secret and attaching it to your service account.` |
|
27 |
+ |
|
28 |
+ createSSHAuthSecretExample = ` // If your SSH authentication method requires only private SSH key, add it by using: |
|
29 |
+ $ %[1]s SECRET --ssh-privatekey=FILENAME |
|
30 |
+ |
|
31 |
+ // If your SSH authentication method requires also CA certificate, add it by using: |
|
32 |
+ $ %[1]s SECRET --ssh-privatekey=FILENAME --ca-cert=FILENAME |
|
33 |
+ |
|
34 |
+ // If you do already have a .gitconfig file needed for authentication, you can create a gitconfig secret by using: |
|
35 |
+ $ %[2]s SECRET path/to/.gitconfig` |
|
36 |
+) |
|
37 |
+ |
|
38 |
+// CreateSSHAuthSecretOptions holds the credential needed to authenticate against SCM servers. |
|
39 |
+type CreateSSHAuthSecretOptions struct { |
|
40 |
+ SecretName string |
|
41 |
+ PrivateKeyPath string |
|
42 |
+ CertificatePath string |
|
43 |
+ GitConfigPath string |
|
44 |
+ |
|
45 |
+ PromptForPassword bool |
|
46 |
+ |
|
47 |
+ Out io.Writer |
|
48 |
+ |
|
49 |
+ SecretsInterface client.SecretsInterface |
|
50 |
+} |
|
51 |
+ |
|
52 |
+// NewCmdCreateSSHAuthSecret implements the OpenShift cli secrets new-sshauth subcommand |
|
53 |
+func NewCmdCreateSSHAuthSecret(name, fullName string, f *kcmdutil.Factory, out io.Writer, newSecretFullName, ocEditFullName string) *cobra.Command { |
|
54 |
+ o := &CreateSSHAuthSecretOptions{ |
|
55 |
+ Out: out, |
|
56 |
+ } |
|
57 |
+ |
|
58 |
+ cmd := &cobra.Command{ |
|
59 |
+ Use: fmt.Sprintf("%s SECRET_NAME --ssh-privatekey=FILENAME [--ca-cert=FILENAME] [--gitconfig=FILENAME]", name), |
|
60 |
+ Short: "Create a new secret for SSH authentication", |
|
61 |
+ Long: createSSHAuthSecretLong, |
|
62 |
+ Example: fmt.Sprintf(createSSHAuthSecretExample, fullName, newSecretFullName, ocEditFullName), |
|
63 |
+ Run: func(c *cobra.Command, args []string) { |
|
64 |
+ if err := o.Complete(f, args); err != nil { |
|
65 |
+ kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error())) |
|
66 |
+ } |
|
67 |
+ |
|
68 |
+ if err := o.Validate(); err != nil { |
|
69 |
+ kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error())) |
|
70 |
+ } |
|
71 |
+ |
|
72 |
+ if len(kcmdutil.GetFlagString(c, "output")) != 0 { |
|
73 |
+ secret, err := o.NewSSHAuthSecret() |
|
74 |
+ kcmdutil.CheckErr(err) |
|
75 |
+ |
|
76 |
+ kcmdutil.CheckErr(f.PrintObject(c, secret, out)) |
|
77 |
+ return |
|
78 |
+ } |
|
79 |
+ |
|
80 |
+ if err := o.CreateSSHAuthSecret(); err != nil { |
|
81 |
+ kcmdutil.CheckErr(err) |
|
82 |
+ } |
|
83 |
+ }, |
|
84 |
+ } |
|
85 |
+ |
|
86 |
+ cmd.Flags().StringVar(&o.PrivateKeyPath, "ssh-privatekey", "", "Path to a SSH private key") |
|
87 |
+ cmd.Flags().StringVar(&o.CertificatePath, "ca-cert", "", "Path to a certificate file") |
|
88 |
+ cmd.Flags().StringVar(&o.GitConfigPath, "gitconfig", "", "Path to a .gitconfig file") |
|
89 |
+ |
|
90 |
+ // autocompletion hints |
|
91 |
+ cmd.MarkFlagFilename("ssh-privatekey") |
|
92 |
+ cmd.MarkFlagFilename("ca-cert") |
|
93 |
+ cmd.MarkFlagFilename("gitconfig") |
|
94 |
+ |
|
95 |
+ kcmdutil.AddPrinterFlags(cmd) |
|
96 |
+ |
|
97 |
+ return cmd |
|
98 |
+} |
|
99 |
+ |
|
100 |
+// CreateSSHAuthSecret saves created Secret structure and prints the secret name to the output on success. |
|
101 |
+func (o *CreateSSHAuthSecretOptions) CreateSSHAuthSecret() error { |
|
102 |
+ secret, err := o.NewSSHAuthSecret() |
|
103 |
+ if err != nil { |
|
104 |
+ return err |
|
105 |
+ } |
|
106 |
+ |
|
107 |
+ if _, err := o.SecretsInterface.Create(secret); err != nil { |
|
108 |
+ return err |
|
109 |
+ } |
|
110 |
+ |
|
111 |
+ fmt.Fprintf(o.GetOut(), "secret/%s\n", secret.Name) |
|
112 |
+ return nil |
|
113 |
+} |
|
114 |
+ |
|
115 |
+// NewSSHAuthSecret builds up the Secret structure containing secret name, type and data structure |
|
116 |
+// containing desired credentials. |
|
117 |
+func (o *CreateSSHAuthSecretOptions) NewSSHAuthSecret() (*api.Secret, error) { |
|
118 |
+ secret := &api.Secret{} |
|
119 |
+ secret.Name = o.SecretName |
|
120 |
+ secret.Type = api.SecretTypeOpaque |
|
121 |
+ secret.Data = map[string][]byte{} |
|
122 |
+ |
|
123 |
+ if len(o.PrivateKeyPath) != 0 { |
|
124 |
+ privateKeyContent, err := ioutil.ReadFile(o.PrivateKeyPath) |
|
125 |
+ if err != nil { |
|
126 |
+ return nil, err |
|
127 |
+ } |
|
128 |
+ secret.Data[SourcePrivateKey] = privateKeyContent |
|
129 |
+ } |
|
130 |
+ |
|
131 |
+ if len(o.CertificatePath) != 0 { |
|
132 |
+ caContent, err := ioutil.ReadFile(o.CertificatePath) |
|
133 |
+ if err != nil { |
|
134 |
+ return nil, err |
|
135 |
+ } |
|
136 |
+ secret.Data[SourceCertificate] = caContent |
|
137 |
+ } |
|
138 |
+ |
|
139 |
+ if len(o.GitConfigPath) != 0 { |
|
140 |
+ gitConfig, err := ioutil.ReadFile(o.GitConfigPath) |
|
141 |
+ if err != nil { |
|
142 |
+ return nil, err |
|
143 |
+ } |
|
144 |
+ secret.Data[SourceGitConfig] = gitConfig |
|
145 |
+ } |
|
146 |
+ |
|
147 |
+ return secret, nil |
|
148 |
+} |
|
149 |
+ |
|
150 |
+// Complete fills CreateSSHAuthSecretOptions fields with data and checks whether necessary |
|
151 |
+// arguments were provided. |
|
152 |
+func (o *CreateSSHAuthSecretOptions) Complete(f *kcmdutil.Factory, args []string) error { |
|
153 |
+ if len(args) != 1 { |
|
154 |
+ return errors.New("must have exactly one argument: secret name") |
|
155 |
+ } |
|
156 |
+ o.SecretName = args[0] |
|
157 |
+ |
|
158 |
+ if f != nil { |
|
159 |
+ client, err := f.Client() |
|
160 |
+ if err != nil { |
|
161 |
+ return err |
|
162 |
+ } |
|
163 |
+ namespace, _, err := f.DefaultNamespace() |
|
164 |
+ if err != nil { |
|
165 |
+ return err |
|
166 |
+ } |
|
167 |
+ o.SecretsInterface = client.Secrets(namespace) |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ return nil |
|
171 |
+} |
|
172 |
+ |
|
173 |
+// Validate check if all necessary fields from CreateSSHAuthSecretOptions are present. |
|
174 |
+func (o CreateSSHAuthSecretOptions) Validate() error { |
|
175 |
+ if len(o.SecretName) == 0 { |
|
176 |
+ return errors.New("basic authentication secret name must be present") |
|
177 |
+ } |
|
178 |
+ |
|
179 |
+ if len(o.PrivateKeyPath) == 0 { |
|
180 |
+ return errors.New("must provide SSH private key") |
|
181 |
+ } |
|
182 |
+ |
|
183 |
+ return nil |
|
184 |
+} |
|
185 |
+ |
|
186 |
+// GetOut check if the CreateSSHAuthSecretOptions Out Writer is set. Returns it if the Writer |
|
187 |
+// is present, if not returns Writer on which all Write calls succeed without doing anything. |
|
188 |
+func (o CreateSSHAuthSecretOptions) GetOut() io.Writer { |
|
189 |
+ if o.Out == nil { |
|
190 |
+ return ioutil.Discard |
|
191 |
+ } |
|
192 |
+ |
|
193 |
+ return o.Out |
|
194 |
+} |
0 | 195 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,56 @@ |
0 |
+package secrets |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "testing" |
|
4 |
+) |
|
5 |
+ |
|
6 |
+func TestValidateSSHAuth(t *testing.T) { |
|
7 |
+ tests := []struct { |
|
8 |
+ testName string |
|
9 |
+ args []string |
|
10 |
+ params CreateSSHAuthSecretOptions |
|
11 |
+ expErr bool |
|
12 |
+ }{ |
|
13 |
+ { |
|
14 |
+ testName: "validArgs", |
|
15 |
+ args: []string{"testSecret"}, |
|
16 |
+ params: CreateSSHAuthSecretOptions{ |
|
17 |
+ PrivateKeyPath: "./bsFixtures/valid/ssh-privatekey", |
|
18 |
+ }, |
|
19 |
+ expErr: false, |
|
20 |
+ }, |
|
21 |
+ { |
|
22 |
+ testName: "validArgsWithCertificate", |
|
23 |
+ args: []string{"testSecret"}, |
|
24 |
+ params: CreateSSHAuthSecretOptions{ |
|
25 |
+ PrivateKeyPath: "./bsFixtures/valid/ssh-privatekey", |
|
26 |
+ CertificatePath: "./bsFixtures/valid/ca.crt", |
|
27 |
+ }, |
|
28 |
+ expErr: false, |
|
29 |
+ }, |
|
30 |
+ { |
|
31 |
+ testName: "noName", |
|
32 |
+ args: []string{}, |
|
33 |
+ params: CreateSSHAuthSecretOptions{ |
|
34 |
+ PrivateKeyPath: "./bsFixtures/valid/ssh-privatekey", |
|
35 |
+ CertificatePath: "./bsFixtures/valid/ca.crt", |
|
36 |
+ }, |
|
37 |
+ expErr: true, //"Must have exactly one argument: secret name" |
|
38 |
+ }, |
|
39 |
+ { |
|
40 |
+ testName: "noParams", |
|
41 |
+ args: []string{"testSecret"}, |
|
42 |
+ params: CreateSSHAuthSecretOptions{}, |
|
43 |
+ expErr: true, //"Must provide SSH authentication credentials" |
|
44 |
+ }, |
|
45 |
+ } |
|
46 |
+ |
|
47 |
+ for _, test := range tests { |
|
48 |
+ options := test.params |
|
49 |
+ options.Complete(nil, test.args) |
|
50 |
+ err := options.Validate() |
|
51 |
+ if err != nil && !test.expErr { |
|
52 |
+ t.Errorf("%s: unexpected error: %v", test.testName, err) |
|
53 |
+ } |
|
54 |
+ } |
|
55 |
+} |
... | ... |
@@ -5,6 +5,7 @@ import ( |
5 | 5 |
|
6 | 6 |
"github.com/spf13/cobra" |
7 | 7 |
|
8 |
+ "github.com/openshift/origin/pkg/build/builder/cmd/scmauth" |
|
8 | 9 |
cmdutil "github.com/openshift/origin/pkg/cmd/util" |
9 | 10 |
"github.com/openshift/origin/pkg/cmd/util/clientcmd" |
10 | 11 |
) |
... | ... |
@@ -12,6 +13,19 @@ import ( |
12 | 12 |
const SecretsRecommendedName = "secrets" |
13 | 13 |
|
14 | 14 |
const ( |
15 |
+ // SourceUsername is the key of the optional username for basic authentication subcommand |
|
16 |
+ SourceUsername = scmauth.UsernameSecret |
|
17 |
+ // SourcePassword is the key of the optional password or token for basic authentication subcommand |
|
18 |
+ SourcePassword = scmauth.PasswordSecret |
|
19 |
+ // SourceCertificate is the key of the optional certificate authority for basic authentication subcommand |
|
20 |
+ SourceCertificate = scmauth.CACertName |
|
21 |
+ // SourcePrivateKey is the key of the required SSH private key for SSH authentication subcommand |
|
22 |
+ SourcePrivateKey = scmauth.SSHPrivateKeyMethodName |
|
23 |
+ // SourceGitconfig is the key of the optional gitconfig content for both basic and SSH authentication subcommands |
|
24 |
+ SourceGitConfig = scmauth.GitConfigName |
|
25 |
+) |
|
26 |
+ |
|
27 |
+const ( |
|
15 | 28 |
secretsLong = ` |
16 | 29 |
Manage secrets in your project |
17 | 30 |
|
... | ... |
@@ -20,7 +34,7 @@ They are commonly used to hold things like keys for authentication to other inte |
20 | 20 |
Docker registries.` |
21 | 21 |
) |
22 | 22 |
|
23 |
-func NewCmdSecrets(name, fullName string, f *clientcmd.Factory, out io.Writer, ocEditFullName string) *cobra.Command { |
|
23 |
+func NewCmdSecrets(name, fullName string, f *clientcmd.Factory, reader io.Reader, out io.Writer, ocEditFullName string) *cobra.Command { |
|
24 | 24 |
// Parent command to which all subcommands are added. |
25 | 25 |
cmds := &cobra.Command{ |
26 | 26 |
Use: name, |
... | ... |
@@ -32,6 +46,8 @@ func NewCmdSecrets(name, fullName string, f *clientcmd.Factory, out io.Writer, o |
32 | 32 |
newSecretFullName := fullName + " " + NewSecretRecommendedCommandName |
33 | 33 |
cmds.AddCommand(NewCmdCreateSecret(NewSecretRecommendedCommandName, newSecretFullName, f, out)) |
34 | 34 |
cmds.AddCommand(NewCmdCreateDockerConfigSecret(CreateDockerConfigSecretRecommendedName, fullName+" "+CreateDockerConfigSecretRecommendedName, f.Factory, out, newSecretFullName, ocEditFullName)) |
35 |
+ cmds.AddCommand(NewCmdCreateBasicAuthSecret(CreateBasicAuthSecretRecommendedCommandName, fullName+" "+CreateBasicAuthSecretRecommendedCommandName, f.Factory, reader, out, newSecretFullName, ocEditFullName)) |
|
36 |
+ cmds.AddCommand(NewCmdCreateSSHAuthSecret(CreateSSHAuthSecretRecommendedCommandName, fullName+" "+CreateSSHAuthSecretRecommendedCommandName, f.Factory, out, newSecretFullName, ocEditFullName)) |
|
35 | 37 |
cmds.AddCommand(NewCmdAddSecret(AddSecretRecommendedName, fullName+" "+AddSecretRecommendedName, f.Factory, out)) |
36 | 38 |
|
37 | 39 |
return cmds |
... | ... |
@@ -1422,6 +1422,66 @@ _oc_secrets_new-dockercfg() |
1422 | 1422 |
must_have_one_noun=() |
1423 | 1423 |
} |
1424 | 1424 |
|
1425 |
+_oc_secrets_new-basicauth() |
|
1426 |
+{ |
|
1427 |
+ last_command="oc_secrets_new-basicauth" |
|
1428 |
+ commands=() |
|
1429 |
+ |
|
1430 |
+ flags=() |
|
1431 |
+ two_word_flags=() |
|
1432 |
+ flags_with_completion=() |
|
1433 |
+ flags_completion=() |
|
1434 |
+ |
|
1435 |
+ flags+=("--ca-cert=") |
|
1436 |
+ flags_with_completion+=("--ca-cert") |
|
1437 |
+ flags_completion+=("_filedir") |
|
1438 |
+ flags+=("--gitconfig=") |
|
1439 |
+ flags_with_completion+=("--gitconfig") |
|
1440 |
+ flags_completion+=("_filedir") |
|
1441 |
+ flags+=("--no-headers") |
|
1442 |
+ flags+=("--output=") |
|
1443 |
+ two_word_flags+=("-o") |
|
1444 |
+ flags+=("--output-version=") |
|
1445 |
+ flags+=("--password=") |
|
1446 |
+ flags+=("--prompt") |
|
1447 |
+ flags+=("--template=") |
|
1448 |
+ two_word_flags+=("-t") |
|
1449 |
+ flags+=("--username=") |
|
1450 |
+ |
|
1451 |
+ must_have_one_flag=() |
|
1452 |
+ must_have_one_noun=() |
|
1453 |
+} |
|
1454 |
+ |
|
1455 |
+_oc_secrets_new-sshauth() |
|
1456 |
+{ |
|
1457 |
+ last_command="oc_secrets_new-sshauth" |
|
1458 |
+ commands=() |
|
1459 |
+ |
|
1460 |
+ flags=() |
|
1461 |
+ two_word_flags=() |
|
1462 |
+ flags_with_completion=() |
|
1463 |
+ flags_completion=() |
|
1464 |
+ |
|
1465 |
+ flags+=("--ca-cert=") |
|
1466 |
+ flags_with_completion+=("--ca-cert") |
|
1467 |
+ flags_completion+=("_filedir") |
|
1468 |
+ flags+=("--gitconfig=") |
|
1469 |
+ flags_with_completion+=("--gitconfig") |
|
1470 |
+ flags_completion+=("_filedir") |
|
1471 |
+ flags+=("--no-headers") |
|
1472 |
+ flags+=("--output=") |
|
1473 |
+ two_word_flags+=("-o") |
|
1474 |
+ flags+=("--output-version=") |
|
1475 |
+ flags+=("--ssh-privatekey=") |
|
1476 |
+ flags_with_completion+=("--ssh-privatekey") |
|
1477 |
+ flags_completion+=("_filedir") |
|
1478 |
+ flags+=("--template=") |
|
1479 |
+ two_word_flags+=("-t") |
|
1480 |
+ |
|
1481 |
+ must_have_one_flag=() |
|
1482 |
+ must_have_one_noun=() |
|
1483 |
+} |
|
1484 |
+ |
|
1425 | 1485 |
_oc_secrets_add() |
1426 | 1486 |
{ |
1427 | 1487 |
last_command="oc_secrets_add" |
... | ... |
@@ -1444,6 +1504,8 @@ _oc_secrets() |
1444 | 1444 |
commands=() |
1445 | 1445 |
commands+=("new") |
1446 | 1446 |
commands+=("new-dockercfg") |
1447 |
+ commands+=("new-basicauth") |
|
1448 |
+ commands+=("new-sshauth") |
|
1447 | 1449 |
commands+=("add") |
1448 | 1450 |
|
1449 | 1451 |
flags=() |
... | ... |
@@ -2877,6 +2877,66 @@ _openshift_cli_secrets_new-dockercfg() |
2877 | 2877 |
must_have_one_noun=() |
2878 | 2878 |
} |
2879 | 2879 |
|
2880 |
+_openshift_cli_secrets_new-basicauth() |
|
2881 |
+{ |
|
2882 |
+ last_command="openshift_cli_secrets_new-basicauth" |
|
2883 |
+ commands=() |
|
2884 |
+ |
|
2885 |
+ flags=() |
|
2886 |
+ two_word_flags=() |
|
2887 |
+ flags_with_completion=() |
|
2888 |
+ flags_completion=() |
|
2889 |
+ |
|
2890 |
+ flags+=("--ca-cert=") |
|
2891 |
+ flags_with_completion+=("--ca-cert") |
|
2892 |
+ flags_completion+=("_filedir") |
|
2893 |
+ flags+=("--gitconfig=") |
|
2894 |
+ flags_with_completion+=("--gitconfig") |
|
2895 |
+ flags_completion+=("_filedir") |
|
2896 |
+ flags+=("--no-headers") |
|
2897 |
+ flags+=("--output=") |
|
2898 |
+ two_word_flags+=("-o") |
|
2899 |
+ flags+=("--output-version=") |
|
2900 |
+ flags+=("--password=") |
|
2901 |
+ flags+=("--prompt") |
|
2902 |
+ flags+=("--template=") |
|
2903 |
+ two_word_flags+=("-t") |
|
2904 |
+ flags+=("--username=") |
|
2905 |
+ |
|
2906 |
+ must_have_one_flag=() |
|
2907 |
+ must_have_one_noun=() |
|
2908 |
+} |
|
2909 |
+ |
|
2910 |
+_openshift_cli_secrets_new-sshauth() |
|
2911 |
+{ |
|
2912 |
+ last_command="openshift_cli_secrets_new-sshauth" |
|
2913 |
+ commands=() |
|
2914 |
+ |
|
2915 |
+ flags=() |
|
2916 |
+ two_word_flags=() |
|
2917 |
+ flags_with_completion=() |
|
2918 |
+ flags_completion=() |
|
2919 |
+ |
|
2920 |
+ flags+=("--ca-cert=") |
|
2921 |
+ flags_with_completion+=("--ca-cert") |
|
2922 |
+ flags_completion+=("_filedir") |
|
2923 |
+ flags+=("--gitconfig=") |
|
2924 |
+ flags_with_completion+=("--gitconfig") |
|
2925 |
+ flags_completion+=("_filedir") |
|
2926 |
+ flags+=("--no-headers") |
|
2927 |
+ flags+=("--output=") |
|
2928 |
+ two_word_flags+=("-o") |
|
2929 |
+ flags+=("--output-version=") |
|
2930 |
+ flags+=("--ssh-privatekey=") |
|
2931 |
+ flags_with_completion+=("--ssh-privatekey") |
|
2932 |
+ flags_completion+=("_filedir") |
|
2933 |
+ flags+=("--template=") |
|
2934 |
+ two_word_flags+=("-t") |
|
2935 |
+ |
|
2936 |
+ must_have_one_flag=() |
|
2937 |
+ must_have_one_noun=() |
|
2938 |
+} |
|
2939 |
+ |
|
2880 | 2940 |
_openshift_cli_secrets_add() |
2881 | 2941 |
{ |
2882 | 2942 |
last_command="openshift_cli_secrets_add" |
... | ... |
@@ -2899,6 +2959,8 @@ _openshift_cli_secrets() |
2899 | 2899 |
commands=() |
2900 | 2900 |
commands+=("new") |
2901 | 2901 |
commands+=("new-dockercfg") |
2902 |
+ commands+=("new-basicauth") |
|
2903 |
+ commands+=("new-sshauth") |
|
2902 | 2904 |
commands+=("add") |
2903 | 2905 |
|
2904 | 2906 |
flags=() |
... | ... |
@@ -20,8 +20,7 @@ oc secrets new from-file .dockercfg=${HOME}/dockerconfig |
20 | 20 |
[ "$(oc secrets new-dockercfg dockercfg --docker-username=sample-user --docker-password=sample-password --docker-email=fake@example.org -o yaml | grep "kubernetes.io/dockercfg")" ] |
21 | 21 |
[ "$(oc secrets new from-file .dockercfg=${HOME}/dockerconfig -o yaml | grep "kubernetes.io/dockercfg")" ] |
22 | 22 |
# check to make sure malformed names fail as expected |
23 |
-[ "$(oc secrets new bad-name .docker=cfg=${HOME}/dockerconfig 2>&1 | grep "error: Key names or file paths cannot contain '='.")" ] |
|
24 |
- |
|
23 |
+[ "$(oc secrets new bad-name .docker=cfg=${HOME}/dockerconfig 2>&1 | grep "error: Key names or file paths cannot contain '='.")" ] |
|
25 | 24 |
|
26 | 25 |
# attach secrets to service account |
27 | 26 |
# single secret with prefix |
... | ... |
@@ -32,5 +31,29 @@ oc secrets add serviceaccounts/deployer secrets/dockercfg secrets/from-file |
32 | 32 |
oc secrets add serviceaccounts/deployer secrets/dockercfg secrets/from-file --for=pull |
33 | 33 |
# make sure we can add as as pull secret and mount secret at once |
34 | 34 |
oc secrets add serviceaccounts/deployer secrets/dockercfg secrets/from-file --for=pull,mount |
35 |
-echo "secrets: ok" |
|
36 | 35 |
|
36 |
+GIT_CONFIG_PATH=$(create_gitconfig) |
|
37 |
+CA_CERT_PATH=$(create_valid_file ca.pem) |
|
38 |
+PRIVATE_KEY_PATH=$(create_valid_file id_rsa) |
|
39 |
+ |
|
40 |
+oc secrets new-basicauth basicauth --username=sample-user --password=sample-password --gitconfig=$GIT_CONFIG_PATH --ca-cert=$PRIVATE_KEY_PATH |
|
41 |
+# check to make sure two mutual exclusive flags return error as expected |
|
42 |
+[ "$(oc secrets new-basicauth bad-file --password=sample-password --prompt 2>&1 | grep "error: must provide either --prompt or --password flag")" ] |
|
43 |
+# check to make sure incorrect .gitconfig path fail as expected |
|
44 |
+[ "$(oc secrets new-basicauth bad-file --username=user --gitconfig=/bad/path 2>&1 | grep "error: open /bad/path: no such file or directory")" ] |
|
45 |
+ |
|
46 |
+oc secrets new-sshauth sshauth --ssh-privatekey=$PRIVATE_KEY_PATH --ca-cert=$PRIVATE_KEY_PATH |
|
47 |
+# check to make sure incorrect SSH private-key path fail as expected |
|
48 |
+[ "$(oc secrets new-sshauth bad-file --ssh-privatekey=/bad/path 2>&1 | grep "error: open /bad/path: no such file or directory")" ] |
|
49 |
+ |
|
50 |
+# attach secrets to service account |
|
51 |
+# single secret with prefix |
|
52 |
+oc secrets add serviceaccounts/deployer secrets/basicauth |
|
53 |
+# don't add the same secret twice |
|
54 |
+oc secrets add serviceaccounts/deployer secrets/basicauth secrets/sshauth |
|
55 |
+# make sure we can add as as pull secret |
|
56 |
+oc secrets add serviceaccounts/deployer secrets/basicauth secrets/sshauth --for=pull |
|
57 |
+# make sure we can add as as pull secret and mount secret at once |
|
58 |
+oc secrets add serviceaccounts/deployer secrets/basicauth secrets/sshauth --for=pull,mount |
|
59 |
+ |
|
60 |
+echo "secrets: ok" |