@@ -19,6 +19,7 @@ import (
1919 "fmt"
2020 "os"
2121 "path"
22+ "strconv"
2223 "strings"
2324
2425 "github.com/Keyfactor/keyfactor-auth-client-go/auth_providers"
@@ -28,6 +29,8 @@ import (
2829 "golang.org/x/term"
2930)
3031
32+ var loginSkipValidate bool
33+
3134var loginCmd = & cobra.Command {
3235 Use : "login" ,
3336 Aliases : nil ,
@@ -78,16 +81,27 @@ WARNING: This will write the environmental credentials to disk and will be store
7881 kfcOAuth * auth_providers.CommandConfigOauth
7982 kfcBasicAuth * auth_providers.CommandAuthConfigBasic
8083 )
84+ skipValidate := loginSkipValidate
8185
8286 log .Debug ().Msg ("calling getEnvConfig()" )
83- envConfig , envErr := getServerConfigFromEnv ()
87+ var envConfig * auth_providers.Server
88+ var envErr error
89+ if skipValidate {
90+ envConfig , envErr = getServerConfigFromEnvNoValidate ()
91+ } else {
92+ envConfig , envErr = getServerConfigFromEnv ()
93+ }
8494 if envErr == nil {
8595 log .Debug ().Msg ("getEnvConfig() returned" )
96+ message := fmt .Sprintf ("Login successful via environment variables to %s" , envConfig .Host )
97+ if skipValidate {
98+ message = fmt .Sprintf ("Login configuration saved from environment variables to %s; credential validation skipped" , envConfig .Host )
99+ }
86100 log .Info ().
87101 Str ("host" , envConfig .Host ).
88102 Str ("authType" , envConfig .AuthType ).
89103 Msg ("Login successful via environment variables" )
90- outputResult (fmt . Sprintf ( "Login successful via environment variables to %s" , envConfig . Host ) , outputFormat )
104+ outputResult (message , outputFormat )
91105 if profile == "" {
92106 profile = "default"
93107 }
@@ -227,13 +241,27 @@ WARNING: This will write the environmental credentials to disk and will be store
227241 log .Error ().Msg ("unable to determine auth type from interactive configuration" )
228242 }
229243 }
244+ if ! skipValidate {
245+ skipValidate = ! promptForInteractiveYesNo ("Validate credentials with Keyfactor Command now?" )
246+ }
230247 }
231248
232249 if ! isValidConfig {
233250 log .Debug ().Msg ("prompting for interactive login" )
234251 return fmt .Errorf ("unable to determine valid configuration" )
235252 }
236253
254+ if skipValidate {
255+ log .Info ().
256+ Str ("profile" , profile ).
257+ Str ("configFile" , configFile ).
258+ Str ("host" , outputServer .Host ).
259+ Str ("authType" , authType ).
260+ Msg ("Login configuration saved; credential validation skipped" )
261+ outputResult (fmt .Sprintf ("Login configuration saved to %s; credential validation skipped" , outputServer .Host ), outputFormat )
262+ return nil
263+ }
264+
237265 if authType == "oauth" {
238266 log .Debug ().
239267 Str ("profile" , profile ).
@@ -297,6 +325,98 @@ WARNING: This will write the environmental credentials to disk and will be store
297325
298326func init () {
299327 RootCmd .AddCommand (loginCmd )
328+ loginCmd .Flags ().BoolVar (
329+ & loginSkipValidate ,
330+ "skip-validate" ,
331+ false ,
332+ "Save the login configuration without validating credentials against Keyfactor Command." ,
333+ )
334+ }
335+
336+ func getServerConfigFromEnvNoValidate () (* auth_providers.Server , error ) {
337+ hostname , hOk := os .LookupEnv (auth_providers .EnvKeyfactorHostName )
338+ if ! hOk || hostname == "" {
339+ return nil , fmt .Errorf ("environment variable %s is required" , auth_providers .EnvKeyfactorHostName )
340+ }
341+
342+ apiPath := os .Getenv (auth_providers .EnvKeyfactorAPIPath )
343+ if apiPath == "" {
344+ apiPath = auth_providers .DefaultCommandAPIPath
345+ }
346+ skipVerify := skipVerifyFromEnv ()
347+
348+ username , uOk := os .LookupEnv (auth_providers .EnvKeyfactorUsername )
349+ password , pOk := os .LookupEnv (auth_providers .EnvKeyfactorPassword )
350+ if uOk && pOk {
351+ serverConfig := & auth_providers.Server {
352+ Host : hostname ,
353+ APIPath : apiPath ,
354+ Username : username ,
355+ Password : password ,
356+ Domain : os .Getenv (auth_providers .EnvKeyfactorDomain ),
357+ SkipTLSVerify : skipVerify ,
358+ AuthType : "basic" ,
359+ }
360+ if _ , err := serverConfig .GetBasicAuthClientConfig (); err != nil {
361+ return nil , err
362+ }
363+ return serverConfig , nil
364+ }
365+
366+ clientID , cOk := os .LookupEnv (auth_providers .EnvKeyfactorClientID )
367+ clientSecret , csOk := os .LookupEnv (auth_providers .EnvKeyfactorClientSecret )
368+ tokenURL , tOk := os .LookupEnv (auth_providers .EnvKeyfactorAuthTokenURL )
369+ if cOk && csOk && tOk {
370+ serverConfig := & auth_providers.Server {
371+ Host : hostname ,
372+ APIPath : apiPath ,
373+ ClientID : clientID ,
374+ ClientSecret : clientSecret ,
375+ OAuthTokenUrl : tokenURL ,
376+ Scopes : authScopesFromCSV (os .Getenv (auth_providers .EnvKeyfactorAuthScopes )),
377+ Audience : os .Getenv (auth_providers .EnvKeyfactorAuthAudience ),
378+ SkipTLSVerify : skipVerify ,
379+ AuthType : "oauth" ,
380+ }
381+ if _ , err := serverConfig .GetOAuthClientConfig (); err != nil {
382+ return nil , err
383+ }
384+ return serverConfig , nil
385+ }
386+
387+ return nil , fmt .Errorf (
388+ "incomplete environment variable configuration, " +
389+ "please provide basic auth credentials or oAuth credentials" ,
390+ )
391+ }
392+
393+ func skipVerifyFromEnv () bool {
394+ if skipVerifyFlag {
395+ return true
396+ }
397+ value := strings .ToLower (os .Getenv (auth_providers .EnvKeyfactorSkipVerify ))
398+ parsed , err := strconv .ParseBool (value )
399+ if err == nil {
400+ return parsed
401+ }
402+ return value == "yes" || value == "y"
403+ }
404+
405+ func authScopesFromCSV (scopesCSV string ) []string {
406+ if scopesCSV == "" {
407+ return auth_providers .DefaultScopes
408+ }
409+ var scopes []string
410+ for _ , scope := range strings .Split (scopesCSV , "," ) {
411+ scope = strings .TrimSpace (scope )
412+ if scope != "" {
413+ scopes = append (scopes , scope )
414+ }
415+ }
416+ if len (scopes ) == 0 {
417+ return auth_providers .DefaultScopes
418+ }
419+ return scopes
300420}
301421
302422func writeConfigFile (configFile * auth_providers.Config , configPath string ) error {
0 commit comments