github.com/jenkins-x/jx/v2@v2.1.155/pkg/cmd/step/step_credential.go (about) 1 package step 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "sort" 7 8 "github.com/jenkins-x/jx/v2/pkg/cmd/opts/step" 9 10 "github.com/jenkins-x/jx/v2/pkg/cmd/helper" 11 12 "github.com/jenkins-x/jx-logging/pkg/log" 13 "github.com/jenkins-x/jx/v2/pkg/cmd/opts" 14 "github.com/jenkins-x/jx/v2/pkg/cmd/templates" 15 "github.com/jenkins-x/jx/v2/pkg/kube" 16 "github.com/jenkins-x/jx/v2/pkg/util" 17 "github.com/pkg/errors" 18 "github.com/spf13/cobra" 19 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 20 ) 21 22 // StepCredentialOptions contains the command line arguments for this command 23 type StepCredentialOptions struct { 24 step.StepOptions 25 26 Namespace string 27 Secret string 28 Key string 29 File string 30 Optional bool 31 } 32 33 var ( 34 stepCredentialLong = templates.LongDesc(` 35 Returns a credential from a Secret for easy scripting in pipeline steps. 36 37 Supports the [Jenkins Credentials Provider labels on the Secrets](https://jenkinsci.github.io/kubernetes-credentials-provider-plugin/examples/) 38 39 If you specify --optional then if the key or secret doesn't exist then the command will only print a warning and will not error. 40 `) 41 42 stepCredentialExample = templates.Examples(` 43 # get the password of a secret 'foo' which uses the Jenkins Credentials Provider labels 44 export MY_PWD="$(jx step credential -s foo)" 45 46 # get the password entry of a secret 'foo' as an environment variable 47 export MY_PWD="$(jx step credential -s foo -k passwordj)" 48 49 # create a local file from a file based secret using the Jenkins Credentials Provider labels 50 export MY_KEY_FILE="$(jx step credential -s foo)" 51 52 # create a local file called cheese from a given key 53 export MY_KEY_FILE="$(jx step credential -s foo -f cheese -k data)" 54 55 # create a local file called cheese from a given key, if the key exists' 56 export MY_KEY_FILE="$(jx step credential -s foo -f cheese -k data --optional)" 57 58 `) 59 ) 60 61 // NewCmdStepCredential creates the command 62 func NewCmdStepCredential(commonOpts *opts.CommonOptions) *cobra.Command { 63 options := StepCredentialOptions{ 64 StepOptions: step.StepOptions{ 65 CommonOptions: commonOpts, 66 }, 67 } 68 cmd := &cobra.Command{ 69 Use: "credential", 70 Short: "Returns a secret entry for easy scripting in pipeline steps", 71 Long: stepCredentialLong, 72 Example: stepCredentialExample, 73 Aliases: []string{"secret", "cred"}, 74 Run: func(cmd *cobra.Command, args []string) { 75 options.Cmd = cmd 76 options.Args = args 77 err := options.Run() 78 helper.CheckErr(err) 79 }, 80 } 81 82 cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", "", "the namespace to look for a Secret") 83 cmd.Flags().StringVarP(&options.Secret, "name", "s", "", "the name of the Secret") 84 cmd.Flags().StringVarP(&options.Key, "key", "k", "", "the key in the Secret to output") 85 cmd.Flags().StringVarP(&options.File, "file", "f", "", "the key for the filename to use if this is a file based Secret") 86 cmd.Flags().BoolVarP(&options.Optional, "optional", "", false, "if true, then the command will only warn (not error) if the secret or the key doesn't exist") 87 88 return cmd 89 } 90 91 // Run runs the command 92 func (o *StepCredentialOptions) Run() error { 93 kubeClient, devNs, err := o.KubeClientAndDevNamespace() 94 if err != nil { 95 return err 96 } 97 98 ns := o.Namespace 99 if ns == "" { 100 ns = devNs 101 } 102 103 name := o.Secret 104 if name == "" { 105 return util.MissingOption("name") 106 } 107 secret, err := kubeClient.CoreV1().Secrets(ns).Get(name, metav1.GetOptions{}) 108 if err != nil { 109 if o.Optional { 110 log.Logger().Warnf("failed to find Secret %s in namespace %s", name, ns) 111 return nil 112 } 113 return errors.Wrapf(err, "failed to find Secret %s in namespace %s", name, ns) 114 } 115 data := secret.Data 116 if data == nil { 117 if o.Optional { 118 log.Logger().Warnf("Secret %s in namespace %s has no data", name, ns) 119 return nil 120 } 121 return errors.Wrapf(err, "Secret %s in namespace %s has no data", name, ns) 122 } 123 keys := []string{} 124 for k := range data { 125 keys = append(keys, k) 126 } 127 sort.Strings(keys) 128 129 filename := o.File 130 key := o.Key 131 132 labels := secret.Labels 133 if labels != nil { 134 kind := labels[kube.LabelCredentialsType] 135 if filename == "" && kind == kube.ValueCredentialTypeSecretFile { 136 filenameData, ok := data["filename"] 137 if ok { 138 filename = string(filenameData) 139 } else { 140 return fmt.Errorf("the Secret %s in namespace %s has label %s with value %s but has no filename key", name, ns, kube.LabelCredentialsType, kind) 141 } 142 if key == "" { 143 key = "data" 144 } 145 } 146 147 if key == "" && kind == kube.ValueCredentialTypeUsernamePassword { 148 key = "password" 149 } 150 } 151 152 if key == "" { 153 return util.MissingOptionWithOptions("key", keys) 154 } 155 156 value, ok := data[key] 157 if !ok { 158 log.Logger().Warnf("Secret %s in namespace %s does not have key %s", name, ns, key) 159 if o.Optional { 160 return nil 161 } 162 return util.InvalidOption("key", key, keys) 163 } 164 if filename != "" { 165 err = ioutil.WriteFile(filename, value, util.DefaultWritePermissions) 166 if err != nil { 167 return errors.Wrapf(err, "failed to store file %s", filename) 168 } 169 fmt.Fprintf(o.Out, "%s\n", filename) 170 return nil 171 } 172 fmt.Fprintf(o.Out, "%s\n", value) 173 return nil 174 }