diff --git a/.github/workflows/keyfactor-bootstrap-workflow.yml b/.github/workflows/keyfactor-bootstrap-workflow.yml index 5d3b5f0..4a58139 100644 --- a/.github/workflows/keyfactor-bootstrap-workflow.yml +++ b/.github/workflows/keyfactor-bootstrap-workflow.yml @@ -223,5 +223,4 @@ jobs: token: ${{ secrets.V2BUILDTOKEN}} APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}} gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }} - gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }} - GITHUB_TOKEN: ${{ secrets.V2BUILDTOKEN }} \ No newline at end of file + gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }} \ No newline at end of file diff --git a/cmd/helm_uo.go b/cmd/helm_uo.go index 2060926..ceeee6e 100644 --- a/cmd/helm_uo.go +++ b/cmd/helm_uo.go @@ -20,6 +20,7 @@ import ( "fmt" "log" + "github.com/Keyfactor/keyfactor-auth-client-go/auth_providers" "github.com/spf13/cobra" "github.com/spf13/pflag" "kfutil/pkg/cmdutil" @@ -171,13 +172,13 @@ func (f *HelmUoFlags) ToOptions(cmd *cobra.Command, args []string) (*HelmUoOptio } // Get the command config entry from global flags - commandConfig, _ := authConfigFile(configFile, profile, "", noPrompt, false) + commandConfig, _ := auth_providers.ReadConfigFromJSON(configFile) // Get the hostname from the command config entry, ok := commandConfig.Servers[profile] if ok { - if entry.Hostname != "" { - options.CommandHostname = commandConfig.Servers[profile].Hostname + if entry.Host != "" { + options.CommandHostname = commandConfig.Servers[profile].Host } } diff --git a/cmd/login.go b/cmd/login.go index 578990e..6e34772 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -16,7 +16,6 @@ package cmd import ( "bufio" - "encoding/json" "fmt" "io" stdlog "log" @@ -25,7 +24,6 @@ import ( "strings" "github.com/Keyfactor/keyfactor-auth-client-go/auth_providers" - "github.com/Keyfactor/keyfactor-go-client/v3/api" "github.com/google/go-cmp/cmp" "github.com/rs/zerolog/log" "github.com/spf13/cobra" @@ -329,28 +327,6 @@ func getDomainFromUsername(username string) string { return "" } -func createConfigFile( - hostname string, - username string, - password string, - domain string, - apiPath string, - profileName string, -) ConfigurationFile { - output := ConfigurationFile{ - Servers: map[string]ConfigurationFileEntry{ - profileName: { - Hostname: hostname, - Username: username, - Password: password, - Domain: domain, - APIPath: apiPath, - }, - }, - } - return output -} - func promptForInteractiveParameter(parameterName string, defaultValue string) string { var input string fmt.Printf("Enter %s [%s]: \n", parameterName, defaultValue) @@ -423,26 +399,6 @@ func handleInteractiveError(err error, parameterName string) error { return nil } -func saveConfigFile(configFile ConfigurationFile, configPath string, profileName string) (ConfigurationFile, error) { - if profileName == "" { - profileName = "default" - } - - configurationErr := createOrUpdateConfigurationFile(configFile.Servers[profileName], profileName, configPath) - if configurationErr != nil { - //log.Fatal("[ERROR] Unable to save configuration file to disk: ", configurationErr) - log.Error().Err(configurationErr) - return configFile, configurationErr - } - loadedConfig, loadErr := loadConfigurationFile(configPath, true) - if loadErr != nil { - //log.Fatal("[ERROR] Unable to load configuration file after save: ", loadErr) - log.Error().Err(loadErr) - return configFile, loadErr - } - return loadedConfig, nil -} - func authInteractive( serverConf *auth_providers.Server, profileName string, @@ -572,775 +528,3 @@ func prepHomeDir() (string, error) { } return userHomeDir, hErr } - -func loadConfigFileData( - profileName string, - configPath string, - noPrompt bool, - configurationFile ConfigurationFile, -) (string, string, string, string, string) { - log.Debug().Str("profileName", profileName). - Str("configPath", configPath). - Bool("noPrompt", noPrompt). - Msg("loadConfigFileData() called") - - log.Debug().Msg("calling authEnvVars()") - envConfig, _ := authEnvVars(configPath, profileName, false) //Load env vars first - log.Debug().Msg("authEnvVars() returned") - - // Check if profileName exists in config file - log.Debug().Str("profileName", profileName).Msg("checking if profileName exists in config file") - configProfile, profileExists := configurationFile.Servers[profileName] - if !profileExists { - log.Error(). - Str("profileName", profileName). - Msg("profileName does not exist in config file") - if noPrompt { // TODO: If profile doesn't exist how does this work? - log.Error().Msg("noPrompt is set, unable to prompt for missing profileName") - return envConfig.Servers[profileName].Hostname, envConfig.Servers[profileName].Username, envConfig.Servers[profileName].Password, envConfig.Servers[profileName].Domain, envConfig.Servers[profileName].APIPath - } - } else { - //log.Println("[INFO] Using kfutil config profileName: ", profileName) - log.Info().Str("profileName", profileName).Msg("Using kfutil config profileName") - hostName := configProfile.Hostname - userName := configProfile.Username - password := configProfile.Password - domain := configProfile.Domain - apiPath := configProfile.APIPath - authProvider := configProfile.AuthProvider - log.Debug().Str("hostName", hostName). - Str("userName", userName). - Str("password", hashSecretValue(password)). - Str("domain", domain). - Str("apiPath", apiPath). - Str("authProvider", fmt.Sprintf("%+v", authProvider)). - Msg("configProfile values") - - if authProvider.Type != "" && authProvider.Parameters != nil { - // cALL authViaProviderParams - log.Info().Str("authProvider.Type", authProvider.Type). - Msg("Authenticating via authProvider") - log.Debug().Msg("calling authViaProviderParams()") - authConfig, authErr := authViaProviderParams(&authProvider) - if authErr != nil { - //log.Println("[ERROR] Unable to authenticate via provider: ", authErr) - log.Error().Err(authErr).Msg("Unable to authenticate via provider") - return "", "", "", "", "" - } - - // Check if authProvider profile is set - if authProvider.Profile == "" { - authProvider.Profile = "default" - log.Info().Msg("Using default authProvider profile") - } - - hostName = authConfig.Servers[authProvider.Profile].Hostname - userName = authConfig.Servers[authProvider.Profile].Username - password = authConfig.Servers[authProvider.Profile].Password - domain = authConfig.Servers[authProvider.Profile].Domain - apiPath = authConfig.Servers[authProvider.Profile].APIPath - - log.Debug().Str("hostName", hostName). - Str("userName", userName). - Str("password", hashSecretValue(password)). - Str("domain", domain). - Str("apiPath", apiPath). - Msg("authConfig values") - - return hostName, userName, password, domain, apiPath - } - - if hostName == "" && envConfig.Servers[profileName].Hostname != "" { - hostName = envConfig.Servers[profileName].Hostname - } - if userName == "" && envConfig.Servers[profileName].Username != "" { - userName = envConfig.Servers[profileName].Username - } - if password == "" && envConfig.Servers[profileName].Password != "" { - password = envConfig.Servers[profileName].Password - } - if domain == "" && envConfig.Servers[profileName].Domain != "" { - domain = envConfig.Servers[profileName].Domain - } - if apiPath == "" && envConfig.Servers[profileName].APIPath != "" { - apiPath = envConfig.Servers[profileName].APIPath - } - - log.Debug().Str("hostName", hostName). - Str("userName", userName). - Str("password", hashSecretValue(password)). - Str("domain", domain). - Str("apiPath", apiPath). - Msg("configProfile values") - - return hostName, userName, password, domain, apiPath - } - log.Error().Msg("Unable to load config file data") - return "", "", "", "", "" -} - -func authViaProvider() (*api.Client, error) { - var clientAuth api.AuthConfig - var commandConfig auth_providers.Config - if providerType != "" { - log.Info().Str("providerType", providerType).Msg("attempting to auth via auth provider") - var providerConfig AuthProvider - if providerProfile == "" { - log.Info().Str( - "providerProfile", - providerProfile, - ).Msg("auth provider profile not set, defaulting to 'default'") - providerProfile = "default" - } - - providerConfig = AuthProvider{ - Type: providerType, - Profile: providerProfile, - Parameters: nil, - } - - if configFile == "" { - homeDir, hdErr := os.UserHomeDir() - if hdErr != nil { - homeDir, hdErr = os.Getwd() - if hdErr != nil { - homeDir = "." // Default to current directory - } - } - configFile = path.Join(homeDir, ".keyfactor", DefaultConfigFileName) - } - - // Load config file - log.Debug().Str("configFile", configFile).Msg("configFile is set, loading config file") - log.Debug().Msg("calling loadConfigurationFile()") - configurationFile, cErr := loadConfigurationFile(configFile, true) - log.Debug().Msg("loadConfigurationFile() returned") - if cErr != nil { - log.Error().Err(cErr).Msg("unable to load provider config file") - return nil, cErr - } - // look for profile in config file - log.Debug().Str("profile", profile). - Str("providerProfile", providerProfile). - Msg("checking if providerProfile exists in config file") - - providerConfigEntry, providerProfileExists := configurationFile.Servers[providerProfile] - if !providerProfileExists { - log.Error().Str("providerProfile", providerProfile).Msg("providerProfile does not exist in config file") - return nil, fmt.Errorf("providerProfile '%s' does not exist in config file", providerProfile) - } - params := providerConfigEntry.AuthProvider.Parameters - if params == nil { - log.Error().Msg("providerProfile parameters are empty") - return nil, fmt.Errorf("providerProfile '%s' parameters are empty", providerProfile) - } - providerConfig.Parameters = params - - log.Debug().Str("providerConfig.Type", providerConfig.Type). - Msg("call: authViaProviderParams()") - pvConfig, pErr := authViaProviderParams(&providerConfig) - log.Debug().Msg("returned: authViaProviderParams()") - if pErr != nil { - log.Error().Err(pErr). - Str("providerConfig.Type", providerConfig.Type). - Str("providerConfig.Profile", providerConfig.Profile). - Msg("unable to auth via provider") - return nil, pErr - } - log.Trace().Interface("pvConfig", pvConfig).Send() - - //commandConfig = pvConfig //TODO: Handle this ab#55467 - clientConfig := clientAuth.GetServerConfig() - clientConfig.Username = commandConfig.Servers[providerProfile].Username - clientConfig.Password = commandConfig.Servers[providerProfile].Password - clientConfig.Domain = commandConfig.Servers[providerProfile].Domain - clientConfig.Host = commandConfig.Servers[providerProfile].Host - clientConfig.ClientID = commandConfig.Servers[providerProfile].ClientID - clientConfig.ClientSecret = commandConfig.Servers[providerProfile].ClientSecret - clientConfig.OAuthTokenUrl = commandConfig.Servers[providerProfile].OAuthTokenUrl - clientConfig.APIPath = commandConfig.Servers[providerProfile].APIPath - - log.Debug(). - Str("clientAuth.Username", clientConfig.Username). - Str("clientAuth.Password", hashSecretValue(clientConfig.Password)). - Str("clientAuth.Domain", clientConfig.Domain). - Str("clientAuth.ClientID", clientConfig.ClientID). - Str("clientAuth.ClientSecret", hashSecretValue(clientConfig.ClientSecret)). - Str("clientAuth.Hostname", clientConfig.Host). - Str("clientAuth.APIPath", clientConfig.APIPath). - Msg("Client authentication params") - - log.Debug().Msg("call: api.NewKeyfactorClient()") - c, err := api.NewKeyfactorClient(clientConfig, nil) - log.Debug().Msg("complete: api.NewKeyfactorClient()") - - if err != nil { - //fmt.Printf("Error connecting to Keyfactor: %s\n", err) - outputError(err, true, "text") - //log.Fatalf("[ERROR] creating Keyfactor client: %s", err) - return nil, fmt.Errorf("unable to create Keyfactor Command client: %s", err) - } - log.Info().Msg("Keyfactor Command client created") - log.Debug().Str("flagAuthProvider", providerType). - Str("providerProfile", providerProfile). - Msg("returning from provider auth") - return c, nil - } - return nil, fmt.Errorf("unable to auth via provider, providerType is empty") -} - -func authViaProviderParams(providerConfig *AuthProvider) (ConfigurationFile, error) { - - pt := providerConfig.Type - // First check if provider type and provider config are not empty - if pt == "" || providerConfig == nil { - return ConfigurationFile{}, fmt.Errorf("provider type and provider config cannot be empty") - } - - // Check if auth provider is valid - if !validAuthProvider(pt) { - return ConfigurationFile{}, fmt.Errorf( - "invalid auth provider type '%s'. Valid auth providers are: %v", - pt, - ValidAuthProviders, - ) - } - - // Check if provider type matches requested provider type - switch pt { - case "azure-id", "azid", "az-id", "azureid": - //load provider config params into AuthProviderAzureIdParams struct - log.Debug().Msg("authenticating via azure-id provider") - var providerParams AuthProviderAzureIDParams - log.Debug().Msg("marshalling providerConfig.Parameters") - paramsJson, _ := json.Marshal(providerConfig.Parameters) - log.Debug().Msg("unmarshalling providerParams") - jsonErr := json.Unmarshal(paramsJson, &providerParams) - if jsonErr != nil { - log.Error().Err(jsonErr).Msg("unable to unmarshal providerParams") - return ConfigurationFile{}, jsonErr - } - - // Check if required params are set - if providerParams.SecretName == "" || providerParams.AzureVaultName == "" { - return ConfigurationFile{}, fmt.Errorf("provider params secret_name and vault_name are required") - } - log.Debug().Msgf("providerParams: %+v", providerParams) - return providerParams.authenticate() - case "az-cli", "azcli", "azure-cli", "azurecli": - log.Debug().Msg("authenticating via azure-cli provider") - break - default: - //log.Println("[ERROR] invalid auth provider type") - log.Error().Msg("invalid auth provider type") - break - } - return ConfigurationFile{}, fmt.Errorf( - "invalid auth provider type '%s'. Valid auth providers are: %v", - pt, - ValidAuthProviders, - ) -} - -func validAuthProvider(providerType string) bool { - log.Debug().Str("providerType", providerType).Msg("validAuthProvider() called") - if providerType == "" { - return true // default to Username/Password - } - for _, validProvider := range ValidAuthProviders { - if validProvider == providerType { - log.Debug().Str("providerType", providerType).Msg("is valid auth provider type") - return true - } - } - log.Error().Str("providerType", providerType).Msg("is not valid auth provider type") - return false -} - -func authConfigFile( - configPath string, - profileName string, - authProviderProfile string, - noPrompt bool, - saveConfig bool, -) (ConfigurationFile, []error) { - var configurationFile ConfigurationFile - var ( - hostName string - userName string - password string - domain string - apiPath string - - //hostSet bool - //userSet bool - //passSet bool - //domainSet bool - //apiPathSet bool - //profileSet bool - ) - - //log.Println("[DEBUG] Using profileName: ", profileName) - log.Debug().Str("profileName", profileName). - Msg("Using profileName") - - if configPath == "" { - log.Debug().Msg("configPath is empty, setting to default") - log.Debug().Msg("calling prepHomeDir()") - userHomeDir, _ := prepHomeDir() - log.Debug().Msg("prepHomeDir() returned") - - configPath = fmt.Sprintf("%s/%s", userHomeDir, DefaultConfigFileName) - log.Debug().Str("configPath", configPath).Msg("configPath set") - } - configurationFile, _ = loadConfigurationFile(configPath, noPrompt) - - if configurationFile.Servers == nil { - configurationFile.Servers = make(map[string]ConfigurationFileEntry) - } - if profileName == "" { - log.Debug().Msg("profileName is empty, setting to default") - profileName = "default" - } - - log.Debug().Msg("calling loadConfigFileData()") - hostName, userName, password, domain, apiPath = loadConfigFileData( - profileName, - configPath, - noPrompt, - configurationFile, - ) - log.Debug().Msg("loadConfigFileData() returned") - - log.Debug().Str("hostName", hostName). - Str("userName", userName). - Str("password", hashSecretValue(password)). - Str("domain", domain). - Str("apiPath", apiPath). - Msg("loadConfigFileData() values") - - log.Debug().Msg("calling createConfigFile()") - confFile := createConfigFile(hostName, userName, password, domain, apiPath, profileName) - log.Debug().Msg("createConfigFile() returned") - - if saveConfig { - log.Info().Str("configPath", configPath). - Str("profileName", profileName). - Msg("Saving configuration file") - log.Debug().Msg("calling saveConfigFile()") - savedConfigFile, saveErr := saveConfigFile(confFile, configPath, profileName) - log.Debug().Msg("saveConfigFile() returned") - if saveErr != nil { - log.Error().Err(saveErr) - return confFile, []error{saveErr} - } - log.Info().Str("configPath", configPath). - Str("profileName", profileName). - Msg("Configuration file saved") - - log.Debug().Msg("returning savedConfigFile") - return savedConfigFile, nil - } - - configurationFile.Servers[profileName] = confFile.Servers[profileName] - return configurationFile, nil -} - -func authEnvProvider(authProvider *AuthProvider, configProfile string) (ConfigurationFile, []error) { - //log.Println(fmt.Sprintf("[INFO] authenticating with auth provider '%s' params from environment variables", authProvider.Type)) - log.Info().Str( - "authProvider.Type", - authProvider.Type, - ).Msg("authenticating with auth provider params from environment variables") - - if configProfile == "" { - log.Debug().Msg("configProfile is empty, setting to default") - configProfile = "default" - } - // attempt to cast authProvider.Parameters to string - authProviderParams, ok := authProvider.Parameters.(string) - if !ok { - //log.Println("[ERROR] unable to cast authProvider.Parameters to string") - log.Error().Msg("unable to cast authProvider.Parameters to string") - return ConfigurationFile{}, []error{fmt.Errorf("invalid configuration, unable to cast authProvider.Parameters to string")} - } - - if strings.HasPrefix(authProviderParams, "{") && strings.HasSuffix(authProviderParams, "}") { - // authProviderParams is a json string - //log.Println("[DEBUG] authProviderParams is a json string") - log.Debug().Msg("authProviderParams is a json string") - var providerParams interface{} - //log.Println("[DEBUG] converting authProviderParams to unescaped json") - log.Debug().Msg("converting authProviderParams to unescaped json") - jsonErr := json.Unmarshal([]byte(authProviderParams), &providerParams) - if jsonErr != nil { - //log.Println("[ERROR] unable to unmarshal authProviderParams: ", jsonErr) - log.Error().Err(jsonErr).Msg("unable to unmarshal authProviderParams") - return ConfigurationFile{}, []error{jsonErr} - } - authProvider.Parameters = providerParams - } else { - // attempt to read as json file path - //log.Println("[DEBUG] authProviderParams is a json file path") - log.Debug().Msg("authProviderParams is a json file path") - var providerParams interface{} - var providerConfigFile ConfigurationFile - var authProviderConfig AuthProvider - //log.Println("[DEBUG] opening authProviderParams file ", authProviderParams) - log.Debug().Str("authProviderParams", authProviderParams).Msg("opening authProviderParams file") - - jsonFile, jsonFileErr := os.Open(authProviderParams) - if jsonFileErr != nil { - //log.Println("[ERROR] unable to open authProviderParams file: ", jsonFileErr) - log.Error().Err(jsonFileErr).Msg("unable to open authProviderParams file") - return ConfigurationFile{}, []error{jsonFileErr} - } - defer jsonFile.Close() - //log.Println(fmt.Sprintf("[DEBUG] reading authProviderParams file %s as bytes", authProviderParams)) - log.Debug().Str("authProviderParams", authProviderParams).Msg("reading authProviderParams file as bytes") - jsonBytes, jsonBytesErr := os.ReadFile(authProviderParams) - if jsonBytesErr != nil { - //log.Println("[ERROR] unable to read authProviderParams file: ", jsonBytesErr) - log.Error().Err(jsonBytesErr).Msg("unable to read authProviderParams file") - return ConfigurationFile{}, []error{jsonBytesErr} - } - //log.Println("[DEBUG] converting authProviderParams to unescaped json") - log.Debug().Msg("converting authProviderParams to unescaped json") - jsonErr := json.Unmarshal(jsonBytes, &providerParams) - if jsonErr != nil { - //log.Println("[ERROR] unable to unmarshal authProviderParams: ", jsonErr) - log.Error().Err(jsonErr).Msg("unable to unmarshal authProviderParams") - return ConfigurationFile{}, []error{jsonErr} - } - - //Check if provider params is a configuration file - //log.Println("[DEBUG] checking if authProviderParams is a configuration file") - log.Debug().Msg("checking if authProviderParams is a configuration file") - jsonErr = json.Unmarshal(jsonBytes, &providerConfigFile) - if jsonErr == nil && providerConfigFile.Servers != nil { - // lookup params based on configProfile - //log.Println("[DEBUG] authProviderParams is a configuration file") - log.Debug().Msg("authProviderParams is a configuration file") - // check to see if profile exists in config file - if _, isConfigFile := providerConfigFile.Servers[configProfile]; isConfigFile { - //log.Println(fmt.Sprintf("[DEBUG] profile '%s' found in authProviderParams file", configProfile)) - log.Debug().Str("configProfile", configProfile).Msg("profile found in authProviderParams file") - providerParams = providerConfigFile.Servers[configProfile] - // check if providerParams is a ConfigurationFileEntry - if _, isConfigFileEntry := providerParams.(ConfigurationFileEntry); !isConfigFileEntry { - //log.Println("[ERROR] unable to cast providerParams to ConfigurationFileEntry") - log.Error().Msg("unable to cast providerParams to ConfigurationFileEntry") - return ConfigurationFile{}, []error{fmt.Errorf("invalid configuration, unable to cast providerParams to ConfigurationFileEntry")} - } - // set providerParams to ConfigurationFileEntry.AuthProvider.Parameters - providerParams = providerConfigFile.Servers[configProfile].AuthProvider.Parameters - } else { - //log.Println(fmt.Sprintf("[DEBUG] profile '%s' not found in authProviderParams file", configProfile)) - log.Debug().Str("configProfile", configProfile).Msg("profile not found in authProviderParams file") - return ConfigurationFile{}, []error{ - fmt.Errorf( - "profile '%s' not found in authProviderParams file", - configProfile, - ), - } - } - } else { - //check if provider params is an AuthProvider - //log.Println("[DEBUG] checking if authProviderParams is an AuthProvider") - log.Debug().Msg("checking if authProviderParams is an AuthProvider") - - //log.Println("[DEBUG] converting authProviderParams to unescaped json") - log.Debug().Msg("converting authProviderParams to unescaped json") - - //check if providerParams is a map[string]interface{} - if _, isMap := providerParams.(map[string]interface{}); isMap { - //check if 'auth_provider' key exists and if it does convert to json bytes - log.Debug().Msg("authProviderParams is a map") - if _, isAuthProvider := providerParams.(map[string]interface{})["auth_provider"]; isAuthProvider { - //log.Println("[DEBUG] authProviderParams is a map[string]interface{}") - //log.Println("[DEBUG] converting authProviderParams to unescaped json") - log.Debug().Msg("authProviderParams is a map[string]interface{}") - log.Debug().Msg("converting authProviderParams to unescaped json") - jsonBytes, jsonBytesErr = json.Marshal(providerParams.(map[string]interface{})["auth_provider"]) - if jsonBytesErr != nil { - //log.Println("[ERROR] unable to marshal authProviderParams: ", jsonBytesErr) - log.Error().Err(jsonBytesErr).Msg("unable to marshal authProviderParams") - return ConfigurationFile{}, []error{jsonBytesErr} - } - } - } - - jsonErr = json.Unmarshal(jsonBytes, &authProviderConfig) - if jsonErr == nil && authProviderConfig.Type != "" && authProviderConfig.Parameters != nil { - //log.Println("[DEBUG] authProviderParams is an AuthProvider") - log.Debug().Msg("authProviderParams is an AuthProvider") - providerParams = authProviderConfig.Parameters - } - } - authProvider.Parameters = providerParams - } - //log.Println("[INFO] Attempting to fetch kfutil creds from auth provider ", authProvider) - log.Info().Str( - "authProvider", - fmt.Sprintf("%+v", authProvider), - ).Msg("Attempting to fetch kfutil creds from auth provider") - configFile, authErr := authViaProviderParams(authProvider) - if authErr != nil { - //log.Println("[ERROR] Unable to authenticate via provider: ", authErr) - log.Error().Err(authErr).Msg("Unable to authenticate via provider") - return ConfigurationFile{}, []error{authErr} - } - //log.Println("[INFO] Successfully retrieved kfutil creds via auth provider") - log.Info().Msg("Successfully retrieved kfutil creds via auth provider") - return configFile, nil -} - -func authEnvVars(configPath string, profileName string, saveConfig bool) (ConfigurationFile, []error) { - hostname, hostSet := os.LookupEnv("KEYFACTOR_HOSTNAME") - username, userSet := os.LookupEnv("KEYFACTOR_USERNAME") - password, passSet := os.LookupEnv("KEYFACTOR_PASSWORD") - domain, domainSet := os.LookupEnv("KEYFACTOR_DOMAIN") - apiPath, apiPathSet := os.LookupEnv("KEYFACTOR_API_PATH") - envProfileName, _ := os.LookupEnv("KFUTIL_PROFILE") - authProviderType, _ := os.LookupEnv("KFUTIL_AUTH_PROVIDER_TYPE") - authProviderProfile, _ := os.LookupEnv("KUTIL_AUTH_PROVIDER_PROFILE") - authProviderParams, _ := os.LookupEnv("KFUTIL_AUTH_PROVIDER_PARAMS") // this is a json string or a json file path - - if authProviderType != "" || authProviderParams != "" { - if authProviderParams == "" { - authProviderParams = fmt.Sprintf("%s/.keyfactor/%s", os.Getenv("HOME"), DefaultConfigFileName) - } - if authProviderProfile == "" { - authProviderProfile = "default" - } - authProvider := AuthProvider{ - Type: authProviderType, - Profile: authProviderProfile, - Parameters: authProviderParams, - } - //check if authProviderParams is a json string or a json file path - return authEnvProvider(&authProvider, profileName) - } - - if profileName == "" && envProfileName != "" { - profileName = envProfileName - } else if profileName == "" { - profileName = "default" - } - - log.Printf("KEYFACTOR_HOSTNAME: %s\n", hostname) - log.Printf("KEYFACTOR_USERNAME: %s\n", username) - log.Printf("KEYFACTOR_DOMAIN: %s\n", domain) - - if domain == "" && username != "" { - domain = getDomainFromUsername(username) - } - - var outputErr []error - if !hostSet { - outputErr = append( - outputErr, - fmt.Errorf("KEYFACTOR_HOSTNAME environment variable not set. Please set the KEYFACTOR_HOSTNAME environment variable"), - ) - } - if !userSet { - outputErr = append( - outputErr, - fmt.Errorf("KEYFACTOR_USERNAME environment variable not set. Please set the KEYFACTOR_USERNAME environment variable"), - ) - } - if !passSet { - outputErr = append( - outputErr, - fmt.Errorf("KEYFACTOR_PASSWORD environment variable not set. Please set the KEYFACTOR_PASSWORD environment variable"), - ) - } - if !domainSet { - outputErr = append( - outputErr, - fmt.Errorf("KEYFACTOR_DOMAIN environment variable not set. Please set the KEYFACTOR_DOMAIN environment variable"), - ) - } - if !apiPathSet { - apiPath = DefaultAPIPath - apiPathSet = true - } - - if !hostSet && !userSet && !passSet && !domainSet { - return ConfigurationFile{}, outputErr - } - - confFile := createConfigFile(hostname, username, password, domain, apiPath, profileName) - - if len(outputErr) > 0 { - return confFile, outputErr - } - - if saveConfig { - savedConfigFile, saveErr := saveConfigFile(confFile, configPath, profileName) - if saveErr != nil { - return confFile, []error{saveErr} - } - return savedConfigFile, nil - } - return confFile, nil -} - -func createOrUpdateConfigurationFile(cfgFile ConfigurationFileEntry, profile string, configPath string) error { - //log.Println("[INFO] Creating or updating configuration file") - log.Info().Str("configPath", configPath). - Str("profile", profile). - Msg("Creating or updating configuration file") - //log.Println("[DEBUG] configuration file path: ", configPath) - - if len(profile) == 0 { - log.Debug().Msg("profile is empty, setting to default") - profile = "default" - } - //check if configPath exists - if configPath == "" { - defaultDir, _ := os.UserHomeDir() - configPath = path.Join(defaultDir, ".keyfactor", DefaultConfigFileName) - //log.Println("[WARN] no config path provided. Using '" + configPath + "'.") - log.Debug().Str("configPath", configPath).Msg("no config path provided using default") - } - confFileExists, fileErr := os.Stat(configPath) - if fileErr != nil { - //log.Println("[WARN] ", fileErr) - log.Error().Err(fileErr).Msg("error checking if config file exists") - } - - existingConfig, _ := loadConfigurationFile(configPath, true) - if len(existingConfig.Servers) > 0 { - // check if the config name already exists - if _, ok := existingConfig.Servers[profile]; ok { - //log.Println(fmt.Sprintf("[WARN] config name '%s' already exists. Overwriting existing config.", profile)) - log.Info(). - Str("profile", profile). - Msg("config profile already exists, overwriting existing config") - //log.Println(fmt.Sprintf("[DEBUG] existing config: %v", existingConfig.Servers[profile])) - log.Debug().Str("profile", profile). - Str("existingConfig", fmt.Sprintf("%+v", existingConfig.Servers[profile])). - Msg("existing config") - //log.Println(fmt.Sprintf("[DEBUG] new config: %v", cfgFile)) - // print out the diff between the two configs - diff := cmp.Diff(existingConfig.Servers[profile], cfgFile) - if len(diff) == 0 && confFileExists != nil { - //log.Println("[DEBUG] no configuration changes detected") - log.Debug().Msg("no configuration changes detected") - return nil - } - //log.Println(fmt.Sprintf("[DEBUG] diff: %s", diff)) - log.Debug().Str("diff", diff).Msg("config diff") - } - existingConfig.Servers[profile] = cfgFile - } else { - //log.Println(fmt.Sprintf("[INFO] adding new config name '%s'", profile)) - log.Info().Str("profile", profile).Msg("adding new profile") - existingConfig.Servers = make(map[string]ConfigurationFileEntry) - existingConfig.Servers[profile] = cfgFile - } - - //log.Println("[DEBUG] kfcfg entry: ", cfgFile) - log.Debug().Str("cfgFile", fmt.Sprintf("%+v", cfgFile)).Msg("kfcfg entry") - - f, fErr := os.OpenFile(fmt.Sprintf("%s", configPath), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0600) - defer f.Close() - if fErr != nil { - msg := fmt.Errorf("unable to create command configuration file %s: %s", configPath, fErr) - outputError(msg, false, outputFormat) - log.Error().Err(fErr).Msg("unable to create command configuration file") - return fErr - } - - // convert existingConfig to json - jsonData, jsErr := json.MarshalIndent(existingConfig, "", " ") - if jsErr != nil { - //fmt.Println("Unable to read kfcfg file due to invalid format. ", jsErr) - outputError(jsErr, false, outputFormat) - //log.Println("[ERROR] marshalling kfcfg file: ", jsErr) - log.Error().Err(jsErr).Msg("marshalling command config file") - return jsErr - } - _, enErr := f.Write(jsonData) - if enErr != nil { - //fmt.Println("Unable to read kfcfg file due to invalid format. ", enErr) - outputError(enErr, false, outputFormat) - //log.Println("[ERROR] encoding kfcfg file: ", enErr) - log.Error().Err(enErr).Msg("encoding command config file") - return enErr - } - return nil -} - -func loadConfigurationFile(filePath string, silent bool) (ConfigurationFile, error) { - log.Debug().Str("filePath", filePath).Msg("loadConfigurationFile() called") - //data := ConfigurationFile{Servers: make(map[string]ConfigurationFileEntry)} - data := ConfigurationFile{} - if filePath == "" { - log.Debug().Msg("filePath is empty, setting to default") - defaultDir, _ := os.UserHomeDir() - filePath = path.Join(defaultDir, ".keyfactor", DefaultConfigFileName) - } - log.Debug().Str("filePath", filePath).Msg("filePath set") - - // attempt to make the directory if it doesn't exist - dirPath := path.Dir(filePath) - if _, dirErr := os.Stat(dirPath); os.IsNotExist(dirErr) { - //log.Println("[DEBUG] config directory does not exist, creating: ", dirPath) - log.Debug().Str("dirPath", dirPath).Msg("config directory does not exist, creating") - err := os.MkdirAll(dirPath, 0700) - if err != nil { - //log.Println("[ERROR] creating config directory: ", err) - log.Error().Err(err).Msg("creating config directory") - return data, err - } - return data, nil // return empty data since the directory didn't exist the file won't exist - } - - // check if file exists - if _, fileErr := os.Stat(filePath); os.IsNotExist(fileErr) { - //log.Println("[DEBUG] config file does not exist: ", filePath) - log.Debug().Str("filePath", filePath).Msg("config file does not exist") - return data, nil // return empty data since the file doesn't exist - } - - f, rFErr := os.ReadFile(filePath) - if rFErr != nil { - if !silent { - //fmt.Println(fmt.Sprintf("Unable to read config file '%s'.", rFErr)) - outputError(rFErr, true, outputFormat) - //log.Fatal("[FATAL] Error reading config file: ", rFErr) - log.Error().Err(rFErr).Msg("error reading config file") - } - return data, rFErr - } - - // Try to unmarshal as a single entry first - var singleEntry ConfigurationFileEntry - sjErr := json.Unmarshal(f, &singleEntry) - if sjErr != nil { - //log.Println(fmt.Sprintf("[DEBUG] config file '%s' is a not single entry, will attempt to parse as v1 config file", filePath)) - log.Debug().Str( - "filePath", - filePath, - ).Msg("config file is not a single entry, will attempt to parse as v1 config file") - } else if (singleEntry != ConfigurationFileEntry{}) { - // if we successfully unmarshalled a single entry, add it to the map as the default entry - //log.Println(fmt.Sprintf("[DEBUG] config file '%s' is a single entry, adding to map", filePath)) - log.Debug().Str("filePath", filePath).Msg("config file is a single entry, adding to map") - data.Servers = make(map[string]ConfigurationFileEntry) - data.Servers["default"] = singleEntry - return data, nil - } - - jErr := json.Unmarshal(f, &data) - if jErr != nil { - //fmt.Println("Unable to read config file due to invalid format. ", jErr) - //log.Println("[ERROR] decoding config file: ", jErr) - log.Error().Err(jErr).Msg("decoding config file") - return data, jErr - } - - return data, nil -} diff --git a/cmd/root.go b/cmd/root.go index 85dcbfa..18e1daf 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -53,6 +53,7 @@ var ( offline bool ) +// hashSecretValue hashes the secret value using bcrypt func hashSecretValue(secretValue string) string { log.Debug().Msg("Enter hashSecretValue()") if secretValue == "" { @@ -73,6 +74,7 @@ func hashSecretValue(secretValue string) string { return string(hashedPassword) } +// getServerConfigFromFile reads the configuration file and returns the server configuration func getServerConfigFromFile(configFile string, profile string) (*auth_providers.Server, error) { var commandConfig *auth_providers.Config var serverConfig auth_providers.Server @@ -114,6 +116,7 @@ func getServerConfigFromFile(configFile string, profile string) (*auth_providers return &serverConfig, nil } +// getServerConfigFromEnv reads the environment variables and returns the server configuration func getServerConfigFromEnv() (*auth_providers.Server, error) { log.Debug().Msg("Enter getServerConfigFromEnv()") @@ -204,6 +207,7 @@ func getServerConfigFromEnv() (*auth_providers.Server, error) { } +// authViaConfigFile authenticates using the configuration file func authViaConfigFile(cfgFile string, cfgProfile string) (*api.Client, error) { var ( c *api.Client @@ -219,6 +223,12 @@ func authViaConfigFile(cfgFile string, cfgProfile string) (*api.Client, error) { return nil, err } if conf != nil { + if conf.AuthProvider.Type != "" { + switch conf.AuthProvider.Type { + case "azid", "azure", "az", "akv": + return authViaProvider(cfgFile, cfgProfile) + } + } log.Debug().Msg("call: api.NewKeyfactorClient()") c, cErr = api.NewKeyfactorClient(conf, nil) log.Debug().Msg("complete: api.NewKeyfactorClient()") @@ -239,6 +249,8 @@ func authViaConfigFile(cfgFile string, cfgProfile string) (*api.Client, error) { log.Error().Msg("unable to authenticate via config file") return nil, fmt.Errorf("unable to authenticate via config file '%s' using profile '%s'", cfgFile, cfgProfile) } + +// authSdkViaConfigFile authenticates using the configuration file func authSdkViaConfigFile(cfgFile string, cfgProfile string) (*keyfactor.APIClient, error) { var ( c *keyfactor.APIClient @@ -254,6 +266,18 @@ func authSdkViaConfigFile(cfgFile string, cfgProfile string) (*keyfactor.APIClie return nil, err } if conf != nil { + if conf.AuthProvider.Type != "" { + switch conf.AuthProvider.Type { + case "azid", "azure", "az", "akv": + log.Debug(). + Str("providerType", conf.AuthProvider.Type). + Str("providerProfile", conf.AuthProvider.Profile). + Str("cfgFile", cfgFile). + Str("cfgProfile", cfgProfile). + Msg("call: authSdkViaProvider()") + return authSdkViaProvider(cfgFile, cfgProfile) + } + } log.Debug().Msg("call: keyfactor.NewAPIClient()") c, cErr = keyfactor.NewAPIClient(conf) log.Debug().Msg("complete: keyfactor.NewAPIClient()") @@ -275,6 +299,7 @@ func authSdkViaConfigFile(cfgFile string, cfgProfile string) (*keyfactor.APIClie return nil, fmt.Errorf("unable to authenticate via config file '%s' using profile '%s'", cfgFile, cfgProfile) } +// authViaEnvVars authenticates using the environment variables func authViaEnvVars() (*api.Client, error) { var ( c *api.Client @@ -312,6 +337,8 @@ func authViaEnvVars() (*api.Client, error) { log.Debug().Msg("return: authViaEnvVars()") return nil, fmt.Errorf("unable to authenticate via environment variables") } + +// authSdkViaEnvVars authenticates using the environment variables func authSdkViaEnvVars() (*keyfactor.APIClient, error) { var ( c *keyfactor.APIClient @@ -350,6 +377,154 @@ func authSdkViaEnvVars() (*keyfactor.APIClient, error) { return nil, fmt.Errorf("unable to authenticate via environment variables") } +// authViaProvider authenticates using the provider +func authViaProvider(cfgFile string, cfgProfile string) (*api.Client, error) { + log.Debug(). + Str("providerType", providerType). + Str("providerProfile", providerProfile). + Str("cfgFile", cfgFile). + Str("cfgProfile", cfgProfile). + Msg("enter: authViaProvider()") + var ( + c *api.Client + cErr error + ) + + log.Debug().Msg("call: getServerConfigFromFile()") + conf, err := getServerConfigFromFile(cfgFile, cfgProfile) + log.Debug().Msg("complete: getServerConfigFromFile()") + if err != nil { + log.Error().Err(err).Msg("unable to authenticate via provider") + return nil, err + } + + if providerType == "" { + providerType = conf.AuthProvider.Type + } + + if providerType == "azid" || providerType == "azure" { + azConfig := &auth_providers.ConfigProviderAzureKeyVault{} + secretName, sOk := os.LookupEnv(auth_providers.EnvAzureSecretName) + vaultName, vOk := os.LookupEnv(auth_providers.EnvAzureVaultName) + if !sOk { + secretName, sOk = conf.AuthProvider.Parameters["secret_name"].(string) + } + if !vOk { + vaultName, vOk = conf.AuthProvider.Parameters["vault_name"].(string) + } + aErr := azConfig. + WithSecretName(secretName). + WithVaultName(vaultName). + Authenticate() + if aErr != nil { + log.Error().Err(aErr).Msg("unable to authenticate via provider") + return nil, aErr + } + cfg, cfgErr := azConfig.LoadConfigFromAzureKeyVault() + if cfgErr != nil { + log.Error().Err(cfgErr).Msg("unable to load config from Azure Key Vault") + return nil, cfgErr + } + log.Debug().Msg("call: api.NewKeyfactorClient()") + serverConfig, serOk := cfg.Servers[providerProfile] + if !serOk { + log.Error().Str("profile", providerProfile).Msg("invalid profile") + return nil, fmt.Errorf("invalid profile: %s", providerProfile) + } + c, cErr = api.NewKeyfactorClient(&serverConfig, nil) + log.Debug().Msg("complete: api.NewKeyfactorClient()") + if cErr != nil { + log.Error().Err(cErr).Msg("unable to create Keyfactor client") + return nil, cErr + } + log.Debug().Msg("call: c.AuthClient.Authenticate()") + authErr := c.AuthClient.Authenticate() + log.Debug().Msg("complete: c.AuthClient.Authenticate()") + if authErr != nil { + log.Error().Err(authErr).Msg("unable to authenticate via provider") + return nil, authErr + } + return c, nil + } + log.Error().Str("providerType", providerType).Msg("unsupported provider type") + return nil, fmt.Errorf("unsupported provider type: %s", providerType) +} + +// authSdkViaProvider authenticates using the provider +func authSdkViaProvider(cfgFile string, cfgProfile string) (*keyfactor.APIClient, error) { + log.Debug(). + Str("providerType", providerType). + Str("providerProfile", providerProfile). + Str("cfgFile", cfgFile). + Str("cfgProfile", cfgProfile). + Msg("enter: authViaProvider()") + var ( + c *keyfactor.APIClient + cErr error + ) + + log.Debug().Msg("call: getServerConfigFromFile()") + conf, err := getServerConfigFromFile(cfgFile, cfgProfile) + log.Debug().Msg("complete: getServerConfigFromFile()") + if err != nil { + log.Error().Err(err).Msg("unable to authenticate via provider") + return nil, err + } + + if providerType == "" { + providerType = conf.AuthProvider.Type + } + + if providerType == "azid" || providerType == "azure" { + azConfig := &auth_providers.ConfigProviderAzureKeyVault{} + secretName, sOk := os.LookupEnv(auth_providers.EnvAzureSecretName) + vaultName, vOk := os.LookupEnv(auth_providers.EnvAzureVaultName) + if !sOk { + secretName, sOk = conf.AuthProvider.Parameters["secret_name"].(string) + } + if !vOk { + vaultName, vOk = conf.AuthProvider.Parameters["vault_name"].(string) + } + aErr := azConfig. + WithSecretName(secretName). + WithVaultName(vaultName). + Authenticate() + if aErr != nil { + log.Error().Err(aErr).Msg("unable to authenticate via provider") + return nil, aErr + } + cfg, cfgErr := azConfig.LoadConfigFromAzureKeyVault() + if cfgErr != nil { + log.Error().Err(cfgErr).Msg("unable to load config from Azure Key Vault") + return nil, cfgErr + } + + serverConfig, serOk := cfg.Servers[providerProfile] + if !serOk { + log.Error().Str("profile", providerProfile).Msg("invalid profile") + return nil, fmt.Errorf("invalid profile: %s", providerProfile) + } + log.Debug().Msg("call: keyfactor.NewAPIClient()") + c, cErr = keyfactor.NewAPIClient(&serverConfig) + log.Debug().Msg("complete: keyfactor.NewAPIClient()") + if cErr != nil { + log.Error().Err(cErr).Msg("unable to create Keyfactor client") + return nil, cErr + } + log.Debug().Msg("call: c.AuthClient.Authenticate()") + authErr := c.AuthClient.Authenticate() + log.Debug().Msg("complete: c.AuthClient.Authenticate()") + if authErr != nil { + log.Error().Err(authErr).Msg("unable to authenticate via provider") + return nil, authErr + } + return c, nil + } + log.Error().Str("providerType", providerType).Msg("unsupported provider type") + return nil, fmt.Errorf("unsupported provider type: %s", providerType) +} + +// initClient initializes the legacy Command API client func initClient(saveConfig bool) (*api.Client, error) { log.Debug(). Str("configFile", configFile). @@ -378,7 +553,7 @@ func initClient(saveConfig bool) (*api.Client, error) { log.Debug(). Str("providerType", providerType). Msg("call: authViaProvider()") - return authViaProvider() + return authViaProvider("", "") } log.Debug(). Msg("providerType is empty attempting to authenticate via params") @@ -429,6 +604,7 @@ func initClient(saveConfig bool) (*api.Client, error) { return nil, fmt.Errorf("unable to authenticate to Keyfactor Command") } +// initGenClient initializes the SDK Command API client func initGenClient( saveConfig bool, ) (*keyfactor.APIClient, error) { @@ -459,9 +635,8 @@ func initGenClient( if providerType != "" { log.Debug(). Str("providerType", providerType). - Msg("call: authViaProvider()") - //return authViaProvider() - return nil, fmt.Errorf("provider auth not supported using Keyfactor Command SDK") + Msg("call: authSdkViaProvider()") + return authSdkViaProvider("", "") } log.Debug(). Msg("providerType is empty attempting to authenticate via params") @@ -511,89 +686,6 @@ func initGenClient( return nil, fmt.Errorf("unable to authenticate to Keyfactor Command with provided credentials, please check your configuration") } -//func initGenClientV1( -// flagConfig string, -// flagProfile string, -// noPrompt bool, -// authConfig *api.AuthConfig, -// saveConfig bool, -//) (*keyfactor.APIClient, error) { -// var commandConfig ConfigurationFile -// -// if providerType != "" { -// return authViaProviderGenClient() -// } -// -// commandConfig, _ = authEnvVars(flagConfig, "", saveConfig) -// -// if flagConfig != "" || !validConfigFileEntry(commandConfig, flagProfile) { -// commandConfig, _ = authConfigFile(flagConfig, flagProfile, "", noPrompt, saveConfig) -// } -// -// if flagProfile == "" { -// flagProfile = "default" -// } -// -// //Params from authConfig take precedence over everything else -// if authConfig != nil { -// // replace commandConfig with authConfig params that aren't null or empty -// configEntry := commandConfig.Servers[flagProfile] -// if authConfig.Hostname != "" { -// configEntry.Hostname = authConfig.Hostname -// } -// if authConfig.Username != "" { -// configEntry.Username = authConfig.Username -// } -// if authConfig.Password != "" { -// configEntry.Password = authConfig.Password -// } -// if authConfig.Domain != "" { -// configEntry.Domain = authConfig.Domain -// } else if authConfig.Username != "" { -// tDomain := getDomainFromUsername(authConfig.Username) -// if tDomain != "" { -// configEntry.Domain = tDomain -// } -// } -// if authConfig.APIPath != "" { -// configEntry.APIPath = authConfig.APIPath -// } -// commandConfig.Servers[flagProfile] = configEntry -// } -// -// if !validConfigFileEntry(commandConfig, flagProfile) { -// if !noPrompt { -// // Auth user interactively -// authConfigEntry := commandConfig.Servers[flagProfile] -// commandConfig, _ = authInteractive( -// authConfigEntry.Hostname, -// authConfigEntry.Username, -// authConfigEntry.Password, -// authConfigEntry.Domain, -// authConfigEntry.APIPath, -// flagProfile, -// false, -// false, -// flagConfig, -// ) -// } else { -// //log.Fatalf("[ERROR] auth config profile: %s", flagProfile) -// log.Error().Str("flagProfile", flagProfile).Msg("invalid auth config profile") -// return nil, fmt.Errorf("auth config profile: %s", flagProfile) -// } -// } -// -// sdkClientConfig := make(map[string]string) -// sdkClientConfig["host"] = commandConfig.Servers[flagProfile].Hostname -// sdkClientConfig["username"] = commandConfig.Servers[flagProfile].Username -// sdkClientConfig["password"] = commandConfig.Servers[flagProfile].Password -// sdkClientConfig["domain"] = commandConfig.Servers[flagProfile].Domain -// -// configuration := keyfactor.NewConfiguration(sdkClientConfig) -// c := keyfactor.NewAPIClient(configuration) -// return c, nil -//} - var makeDocsCmd = &cobra.Command{ Use: "makedocs", Short: "Generate markdown documentation for kfutil", diff --git a/go.mod b/go.mod index 50efeb3..984670a 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ toolchain go1.23.2 require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 github.com/Jeffail/gabs v1.4.0 - github.com/Keyfactor/keyfactor-auth-client-go v1.0.0-rc.18 + github.com/Keyfactor/keyfactor-auth-client-go v1.1.0-rc.3 github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0-rc.2 github.com/Keyfactor/keyfactor-go-client/v3 v3.0.0-rc.11 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 @@ -22,14 +22,16 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 - golang.org/x/crypto v0.25.0 - golang.org/x/term v0.22.0 + golang.org/x/crypto v0.27.0 + golang.org/x/term v0.24.0 gopkg.in/yaml.v3 v3.0.1 //github.com/google/go-cmp/cmp v0.5.9 ) require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.12.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -48,9 +50,9 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spbsoluble/go-pkcs12 v0.3.3 // indirect go.mozilla.org/pkcs7 v0.9.0 // indirect - golang.org/x/net v0.27.0 // indirect + golang.org/x/net v0.29.0 // indirect golang.org/x/oauth2 v0.24.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index cc8b5dd..602a011 100644 --- a/go.sum +++ b/go.sum @@ -2,22 +2,32 @@ github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkk github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.12.0 h1:xnO4sFyG8UH2fElBkcqLTOZsAajvKfnSlgBBW8dXYjw= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.12.0/go.mod h1:XD3DIOOVgBCO03OleB1fHjgktVRFxlT++KwKgIOewdM= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Keyfactor/keyfactor-auth-client-go v1.0.0-rc.18 h1:PMH/pST30UEQ1dz6YcxYCaoA14iGS3BoL+e3M9m3eyw= -github.com/Keyfactor/keyfactor-auth-client-go v1.0.0-rc.18/go.mod h1:00PVslvswI2+6Uln50XKymEiEafmxfrcOxsNEz3bOME= +github.com/Keyfactor/keyfactor-auth-client-go v1.1.0-rc.3 h1:pQvbBM3DmSDdGMLh9s648Md+fHOoZtL7tjmVnHNDeVc= +github.com/Keyfactor/keyfactor-auth-client-go v1.1.0-rc.3/go.mod h1:Ia3VmXsumFrr01BMc1Rp5OpDWmfXWjdeMituda14T4I= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0-rc.2 h1:RNrfgrC+mPvqOc1wPsFjB4thuw7qJbP3gOycRDcRwxI= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0-rc.2/go.mod h1:11WXGG9VVKSV0EPku1IswjHbGGpzHDKqD4pe2vD7vas= github.com/Keyfactor/keyfactor-go-client/v3 v3.0.0-rc.11 h1:nYc7fEidu26ZKGwEByQNr2EWPCsCs0zxnHUKnRT6/rY= github.com/Keyfactor/keyfactor-go-client/v3 v3.0.0-rc.11/go.mod h1:HWb+S60YAALFVSfB8QuQ8ugjsjr+FHLQET0/4K7EVWw= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -27,6 +37,8 @@ github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfv github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -49,6 +61,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -75,6 +89,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= +github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -98,14 +114,14 @@ go.mozilla.org/pkcs7 v0.9.0 h1:yM4/HS9dYv7ri2biPtxt8ikvB37a980dg69/pKmS+eI= go.mozilla.org/pkcs7 v0.9.0/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -125,18 +141,18 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=