forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sshauth.go
197 lines (157 loc) · 5.75 KB
/
sshauth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package secrets
import (
"errors"
"fmt"
"io"
"io/ioutil"
"k8s.io/kubernetes/pkg/api"
client "k8s.io/kubernetes/pkg/client/unversioned"
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"github.com/openshift/origin/pkg/cmd/templates"
"github.com/spf13/cobra"
)
// CreateSSHAuthSecretRecommendedCommandName represents name of subcommand for `oc secrets` command
const CreateSSHAuthSecretRecommendedCommandName = "new-sshauth"
var (
createSSHAuthSecretLong = templates.LongDesc(`
Create a new SSH authentication secret
SSH authentication secrets are used to authenticate against SCM servers.
When creating applications, you may have a SCM server that requires SSH authentication - private SSH key.
In order for the nodes to clone source code on your behalf, they have to have the credentials. You can
provide this information by creating a 'sshauth' secret and attaching it to your service account.`)
createSSHAuthSecretExample = templates.Examples(`
# If your SSH authentication method requires only private SSH key, add it by using:
%[1]s SECRET --ssh-privatekey=FILENAME
# If your SSH authentication method requires also CA certificate, add it by using:
%[1]s SECRET --ssh-privatekey=FILENAME --ca-cert=FILENAME
# If you do already have a .gitconfig file needed for authentication, you can create a gitconfig secret by using:
%[2]s SECRET path/to/.gitconfig`)
)
// CreateSSHAuthSecretOptions holds the credential needed to authenticate against SCM servers.
type CreateSSHAuthSecretOptions struct {
SecretName string
PrivateKeyPath string
CertificatePath string
GitConfigPath string
PromptForPassword bool
Out io.Writer
SecretsInterface client.SecretsInterface
}
// NewCmdCreateSSHAuthSecret implements the OpenShift cli secrets new-sshauth subcommand
func NewCmdCreateSSHAuthSecret(name, fullName string, f *kcmdutil.Factory, out io.Writer, newSecretFullName, ocEditFullName string) *cobra.Command {
o := &CreateSSHAuthSecretOptions{
Out: out,
}
cmd := &cobra.Command{
Use: fmt.Sprintf("%s SECRET --ssh-privatekey=FILENAME [--ca-cert=FILENAME] [--gitconfig=FILENAME]", name),
Short: "Create a new secret for SSH authentication",
Long: createSSHAuthSecretLong,
Example: fmt.Sprintf(createSSHAuthSecretExample, fullName, newSecretFullName, ocEditFullName),
Run: func(c *cobra.Command, args []string) {
if err := o.Complete(f, args); err != nil {
kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error()))
}
if err := o.Validate(); err != nil {
kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error()))
}
if len(kcmdutil.GetFlagString(c, "output")) != 0 {
secret, err := o.NewSSHAuthSecret()
kcmdutil.CheckErr(err)
mapper, _ := f.Object(false)
kcmdutil.CheckErr(f.PrintObject(c, mapper, secret, out))
return
}
if err := o.CreateSSHAuthSecret(); err != nil {
kcmdutil.CheckErr(err)
}
},
}
cmd.Flags().StringVar(&o.PrivateKeyPath, "ssh-privatekey", "", "Path to a SSH private key file")
cmd.MarkFlagFilename("ssh-privatekey")
cmd.Flags().StringVar(&o.CertificatePath, "ca-cert", "", "Path to a certificate file")
cmd.MarkFlagFilename("ca-cert")
cmd.Flags().StringVar(&o.GitConfigPath, "gitconfig", "", "Path to a .gitconfig file")
cmd.MarkFlagFilename("gitconfig")
kcmdutil.AddPrinterFlags(cmd)
return cmd
}
// CreateSSHAuthSecret saves created Secret structure and prints the secret name to the output on success.
func (o *CreateSSHAuthSecretOptions) CreateSSHAuthSecret() error {
secret, err := o.NewSSHAuthSecret()
if err != nil {
return err
}
if _, err := o.SecretsInterface.Create(secret); err != nil {
return err
}
fmt.Fprintf(o.GetOut(), "secret/%s\n", secret.Name)
return nil
}
// NewSSHAuthSecret builds up the Secret structure containing secret name, type and data structure
// containing desired credentials.
func (o *CreateSSHAuthSecretOptions) NewSSHAuthSecret() (*api.Secret, error) {
secret := &api.Secret{}
secret.Name = o.SecretName
secret.Type = api.SecretTypeSSHAuth
secret.Data = map[string][]byte{}
if len(o.PrivateKeyPath) != 0 {
privateKeyContent, err := ioutil.ReadFile(o.PrivateKeyPath)
if err != nil {
return nil, err
}
secret.Data[SourcePrivateKey] = privateKeyContent
}
if len(o.CertificatePath) != 0 {
caContent, err := ioutil.ReadFile(o.CertificatePath)
if err != nil {
return nil, err
}
secret.Data[SourceCertificate] = caContent
}
if len(o.GitConfigPath) != 0 {
gitConfig, err := ioutil.ReadFile(o.GitConfigPath)
if err != nil {
return nil, err
}
secret.Data[SourceGitConfig] = gitConfig
}
return secret, nil
}
// Complete fills CreateSSHAuthSecretOptions fields with data and checks whether necessary
// arguments were provided.
func (o *CreateSSHAuthSecretOptions) Complete(f *kcmdutil.Factory, args []string) error {
if len(args) != 1 {
return errors.New("must have exactly one argument: secret name")
}
o.SecretName = args[0]
if f != nil {
client, err := f.Client()
if err != nil {
return err
}
namespace, _, err := f.DefaultNamespace()
if err != nil {
return err
}
o.SecretsInterface = client.Secrets(namespace)
}
return nil
}
// Validate check if all necessary fields from CreateSSHAuthSecretOptions are present.
func (o CreateSSHAuthSecretOptions) Validate() error {
if len(o.SecretName) == 0 {
return errors.New("basic authentication secret name must be present")
}
if len(o.PrivateKeyPath) == 0 {
return errors.New("must provide SSH private key")
}
return nil
}
// GetOut check if the CreateSSHAuthSecretOptions Out Writer is set. Returns it if the Writer
// is present, if not returns Writer on which all Write calls succeed without doing anything.
func (o CreateSSHAuthSecretOptions) GetOut() io.Writer {
if o.Out == nil {
return ioutil.Discard
}
return o.Out
}