6f7bcc6e |
package secrets
import (
"errors"
"fmt"
"io"
"io/ioutil"
|
661aaef1 |
"github.com/spf13/cobra"
|
6f7bcc6e |
"k8s.io/kubernetes/pkg/api" |
3dd75654 |
client "k8s.io/kubernetes/pkg/client/unversioned" |
6f7bcc6e |
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
6366c25e |
kterm "k8s.io/kubernetes/pkg/util/term" |
6f7bcc6e |
|
6267dded |
"github.com/openshift/origin/pkg/cmd/templates" |
6366c25e |
"github.com/openshift/origin/pkg/cmd/util/term" |
6f7bcc6e |
)
|
6267dded |
// CreateBasicAuthSecretRecommendedCommandName represents name of subcommand for `oc secrets` command
const CreateBasicAuthSecretRecommendedCommandName = "new-basicauth" |
6f7bcc6e |
|
6267dded |
var (
createBasicAuthSecretLong = templates.LongDesc(`
Create a new basic authentication secret |
6f7bcc6e |
|
6267dded |
Basic authentication secrets are used to authenticate against SCM servers. |
6f7bcc6e |
|
6267dded |
When creating applications, you may have a SCM server that requires basic authentication - username, password.
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 'basicauth' secret and attaching it to your service account.`) |
6f7bcc6e |
|
6267dded |
createBasicAuthSecretExample = templates.Examples(`
# If your basic authentication method requires only username and password or token, add it by using:
%[1]s SECRET --username=USERNAME --password=PASSWORD |
6f7bcc6e |
|
6267dded |
# If your basic authentication method requires also CA certificate, add it by using:
%[1]s SECRET --username=USERNAME --password=PASSWORD --ca-cert=FILENAME |
6f7bcc6e |
|
6267dded |
# 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`) |
6f7bcc6e |
)
// CreateBasicAuthSecretOptions holds the credential needed to authenticate against SCM servers.
type CreateBasicAuthSecretOptions struct {
SecretName string
Username string
Password string
CertificatePath string
GitConfigPath string
PromptForPassword bool
Reader io.Reader
Out io.Writer
SecretsInterface client.SecretsInterface
}
// NewCmdCreateBasicAuthSecret implements the OpenShift cli secrets new-basicauth subcommand
func NewCmdCreateBasicAuthSecret(name, fullName string, f *kcmdutil.Factory, reader io.Reader, out io.Writer, newSecretFullName, ocEditFullName string) *cobra.Command {
o := &CreateBasicAuthSecretOptions{
Out: out,
Reader: reader,
}
cmd := &cobra.Command{ |
44164be6 |
Use: fmt.Sprintf("%s SECRET --username=USERNAME --password=PASSWORD [--ca-cert=FILENAME] [--gitconfig=FILENAME]", name), |
6f7bcc6e |
Short: "Create a new secret for basic authentication",
Long: createBasicAuthSecretLong,
Example: fmt.Sprintf(createBasicAuthSecretExample, 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.NewBasicAuthSecret()
kcmdutil.CheckErr(err)
|
59e6f9d2 |
mapper, _ := f.Object(false)
kcmdutil.CheckErr(f.PrintObject(c, mapper, secret, out)) |
6f7bcc6e |
return
}
if err := o.CreateBasicAuthSecret(); err != nil {
kcmdutil.CheckErr(err)
}
},
}
cmd.Flags().StringVar(&o.Username, "username", "", "Username for Git authentication")
cmd.Flags().StringVar(&o.Password, "password", "", "Password or token for Git authentication")
cmd.Flags().StringVar(&o.CertificatePath, "ca-cert", "", "Path to a certificate file")
cmd.MarkFlagFilename("ca-cert") |
a166f955 |
cmd.Flags().StringVar(&o.GitConfigPath, "gitconfig", "", "Path to a .gitconfig file") |
6f7bcc6e |
cmd.MarkFlagFilename("gitconfig") |
a166f955 |
cmd.Flags().BoolVarP(&o.PromptForPassword, "prompt", "", false, "Prompt for password or token") |
6f7bcc6e |
kcmdutil.AddPrinterFlags(cmd)
return cmd
}
// CreateBasicAuthSecret saves created Secret structure and prints the secret name to the output on success.
func (o *CreateBasicAuthSecretOptions) CreateBasicAuthSecret() error {
secret, err := o.NewBasicAuthSecret()
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
}
// NewBasicAuthSecret builds up the Secret structure containing secret name, type and data structure
// containing desired credentials.
func (o *CreateBasicAuthSecretOptions) NewBasicAuthSecret() (*api.Secret, error) {
secret := &api.Secret{}
secret.Name = o.SecretName
secret.Type = api.SecretTypeOpaque
secret.Data = map[string][]byte{}
if len(o.Username) != 0 {
secret.Data[SourceUsername] = []byte(o.Username)
}
if len(o.Password) != 0 {
secret.Data[SourcePassword] = []byte(o.Password)
}
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 CreateBasicAuthSecretOptions fields with data and checks for mutual exclusivity
// between flags from different option groups.
func (o *CreateBasicAuthSecretOptions) 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]
|
44164be6 |
if o.PromptForPassword {
if len(o.Password) != 0 {
return errors.New("must provide either --prompt or --password flag")
} |
6366c25e |
if !kterm.IsTerminal(o.Reader) { |
44164be6 |
return errors.New("provided reader is not a terminal")
}
|
6366c25e |
o.Password = term.PromptForPasswordString(o.Reader, o.Out, "Password: ") |
44164be6 |
if len(o.Password) == 0 {
return errors.New("password must be provided")
}
}
|
6f7bcc6e |
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 CreateBasicAuthSecretOptions are present.
func (o CreateBasicAuthSecretOptions) Validate() error {
if len(o.SecretName) == 0 {
return errors.New("basic authentication secret name must be present")
}
|
44164be6 |
if len(o.Username) == 0 && len(o.Password) == 0 {
return errors.New("must provide basic authentication credentials") |
6f7bcc6e |
}
return nil
}
// GetOut check if the CreateBasicAuthSecretOptions 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 CreateBasicAuthSecretOptions) GetOut() io.Writer {
if o.Out == nil {
return ioutil.Discard
}
return o.Out
} |