From d826d9f000bc861ae98f7f535e9b524474bc5fc2 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 7 Jun 2023 11:26:58 +0200 Subject: [PATCH 01/16] First attempt at using Viper/Cobra This is the first attempt at using a very established argument parser and cobra as configuration management. These tools also generate completions for the shell. Can also suggest fixes for incorrectly typed commands --- .cobra.yaml | 3 + LICENSE | 14 +- cmd/login.go | 253 +++++++++++++++++++++++++++++++++++++ cmd/root.go | 47 +++++++ cmd/version.go | 10 ++ go.mod | 24 +++- go.sum | 65 +++++++++- login.go => login/login.go | 7 +- main.go | 244 +++-------------------------------- oldmain.go | 231 +++++++++++++++++++++++++++++++++ 10 files changed, 651 insertions(+), 247 deletions(-) create mode 100644 .cobra.yaml create mode 100644 cmd/login.go create mode 100644 cmd/root.go create mode 100644 cmd/version.go rename login.go => login/login.go (95%) create mode 100644 oldmain.go diff --git a/.cobra.yaml b/.cobra.yaml new file mode 100644 index 00000000..e365e6b8 --- /dev/null +++ b/.cobra.yaml @@ -0,0 +1,3 @@ +author: IITS-Consulting +license: GPLv3 +useViper: false diff --git a/LICENSE b/LICENSE index f288702d..1840fd9e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found. GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -653,22 +653,22 @@ Also add information on how to contact you by electronic and paper mail. notice like this when it starts in an interactive mode: Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. + under certain conditions; type 'show c' for details. -The hypothetical commands `show w' and `show c' should show the appropriate +The hypothetical commands 'show w' and 'show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see -. +. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. +. diff --git a/cmd/login.go b/cmd/login.go new file mode 100644 index 00000000..1c7e8ce5 --- /dev/null +++ b/cmd/login.go @@ -0,0 +1,253 @@ +/* +Copyright © 2023 IITS-Consulting + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +package cmd + +import ( + "fmt" + "github.com/spf13/pflag" + "otc-auth/common" + "otc-auth/config" + "otc-auth/login" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var loginCmd = &cobra.Command{ + Use: "login", + Short: loginCmdHelp, +} + +var loginIamCmd = &cobra.Command{ + Use: "iam", + Short: loginIamCmdHelp, + Long: "Here we can put a longer description of this command", // TODO + Example: "Here comes an example usage of this command", // TODO + PreRunE: func(cmd *cobra.Command, args []string) error { + return initializeConfig(cmd, loginIamFlagToEnv) + }, + Run: func(cmd *cobra.Command, args []string) { + authInfo := common.AuthInfo{ + AuthType: "iam", + Username: username, + Password: password, + DomainName: domainName, + Otp: totp, + UserDomainId: userDomainId, + OverwriteFile: overwriteToken, + } + login.AuthenticateAndGetUnscopedToken(authInfo) + }, +} + +var loginIdpSamlCmd = &cobra.Command{ + Use: "idp-saml", + Short: loginIdpSamlCmdHelp, + Long: "Here we can put a longer description of this command", // TODO + Example: "Here comes an example usage of this command", // TODO + PreRunE: func(cmd *cobra.Command, args []string) error { + return initializeConfig(cmd, loginIdpSamlOidcFlagToEnv) + }, + Run: func(cmd *cobra.Command, args []string) { + authInfo := common.AuthInfo{ + AuthType: "idp", + Username: username, + Password: password, + DomainName: domainName, + IdpName: idpName, + IdpUrl: idpUrl, + AuthProtocol: "saml", + OverwriteFile: overwriteToken, + } + login.AuthenticateAndGetUnscopedToken(authInfo) + }, +} + +var loginIdpOidcCmd = &cobra.Command{ + Use: "idp-oidc", + Short: loginIdpOidcCmdHelp, // TODO + Long: "Here we can put a longer description of this command", // TODO + Example: "Here comes an example usage of this command", // TODO + PreRunE: func(cmd *cobra.Command, args []string) error { + return initializeConfig(cmd, loginIdpSamlOidcFlagToEnv) + }, + Run: func(cmd *cobra.Command, args []string) { + authInfo := common.AuthInfo{ + AuthType: "idp", + Username: username, + Password: password, + DomainName: domainName, + IdpName: idpName, + IdpUrl: idpUrl, + AuthProtocol: "oidc", + OverwriteFile: overwriteToken, + } + login.AuthenticateAndGetUnscopedToken(authInfo) + }, +} + +var loginRemoveCmd = &cobra.Command{ + Use: "remove", + Short: loginRemoveCmdHelp, + Long: "Here we can put a longer description of this command", // TODO + Example: "Here comes an example usage of this command", // TODO + PreRunE: func(cmd *cobra.Command, args []string) error { + return initializeConfig(cmd, loginRemoveFlagToEnv) + }, + Run: func(cmd *cobra.Command, args []string) { + config.RemoveCloudConfig(domainName) + }, +} + +var ( + username string + password string + domainName string + overwriteToken bool + idpName string + idpUrl string + totp string + userDomainId string + + loginIamFlagToEnv = map[string]string{ + usernameFlag: usernameEnv, + passwordFlag: passwordEnv, + domainNameFlag: domainNameEnv, + userDomainIdFlag: userDomainIdEnv, + idpNameFlag: idpNameEnv, + idpUrlFlag: idpUrlEnv, + } + + loginIdpSamlOidcFlagToEnv = map[string]string{ + usernameFlag: usernameEnv, + passwordFlag: passwordEnv, + domainNameFlag: domainNameEnv, + userDomainIdFlag: userDomainIdEnv, + idpNameFlag: idpNameEnv, + idpUrlFlag: idpUrlEnv, + } + + loginRemoveFlagToEnv = map[string]string{ + userDomainIdFlag: userDomainIdEnv, + } +) + +/* +initializeConfig is a helper function which sets the environment variable for a flag. It gives precedence to the flag, +meaning that the env is only taken if the flag is empty. It assigns the environment variables to the flags which are +defined in the map flagToEnvMap. +*/ +func initializeConfig(cmd *cobra.Command, flagToEnvMapping map[string]string) error { + v := viper.New() + v.AutomaticEnv() + + cmd.Flags().VisitAll( + func(f *pflag.Flag) { + configName, ok := flagToEnvMapping[f.Name] + if !ok { + return + } + if !f.Changed && v.IsSet(configName) { + val := v.Get(configName) + _ = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) + } + }) + return nil +} + +func init() { + RootCmd.AddCommand(loginCmd) + + loginCmd.AddCommand(loginIamCmd) + loginIamCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) + loginIamCmd.MarkFlagRequired(usernameFlag) + loginIamCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) + loginIamCmd.MarkFlagRequired(passwordFlag) + loginIamCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + loginIamCmd.MarkFlagRequired(domainNameFlag) + loginIamCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) + loginIamCmd.Flags().StringVarP(&totp, totpFlag, totpShortFlag, "", totpUsage) + loginIamCmd.Flags().StringVarP(&userDomainId, userDomainIdFlag, "", "", userDomainIdUsage) + loginIamCmd.MarkFlagsRequiredTogether(totpFlag, userDomainIdFlag) + + loginCmd.AddCommand(loginIdpSamlCmd) + loginIdpSamlCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) + loginIdpSamlCmd.MarkFlagRequired(usernameFlag) + loginIdpSamlCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) + loginIdpSamlCmd.MarkFlagRequired(passwordFlag) + loginIdpSamlCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + loginIdpSamlCmd.MarkFlagRequired(domainNameFlag) + loginIdpSamlCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) + loginIdpSamlCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) + loginIdpSamlCmd.MarkPersistentFlagRequired(idpNameFlag) + loginIdpSamlCmd.PersistentFlags().StringVarP(&idpUrl, idpUrlFlag, "", "", idpUrlUsage) + loginIdpSamlCmd.MarkPersistentFlagRequired(idpUrlFlag) + + loginCmd.AddCommand(loginIdpOidcCmd) + loginIdpOidcCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) + loginIdpOidcCmd.MarkFlagRequired(usernameFlag) + loginIdpOidcCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) + loginIdpOidcCmd.MarkFlagRequired(passwordFlag) + loginIdpOidcCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + loginIdpOidcCmd.MarkFlagRequired(domainNameFlag) + loginIdpOidcCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) + loginIdpOidcCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) + loginIdpOidcCmd.MarkPersistentFlagRequired(idpNameFlag) + loginIdpOidcCmd.PersistentFlags().StringVarP(&idpUrl, idpUrlFlag, "", "", idpUrlUsage) + loginIdpOidcCmd.MarkPersistentFlagRequired(idpUrlFlag) + + loginCmd.AddCommand(loginRemoveCmd) + loginRemoveCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + loginRemoveCmd.MarkFlagRequired(domainNameFlag) + +} + +const ( + loginCmdHelp = "Login to the Open Telekom Cloud and receive an unscoped token." + loginIamCmdHelp = "Login to the Open Telekom Cloud through its Identity and Access Management system." + loginIdpSamlCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and SAML." + loginIdpOidcCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and OIDC." + loginRemoveCmdHelp = "Removes login information for a cloud" + usernameFlag = "os-username" + usernameShortFlag = "u" + usernameEnv = "OS_USERNAME" + usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." + passwordFlag = "os-password" + passwordShortFlag = "p" + passwordEnv = "OS_PASSWORD" + passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." + domainNameFlag = "os-domain-name" + domainNameShortFlag = "d" + domainNameEnv = "OS_DOMAIN_NAME" + domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." + overwriteTokenFlag = "overwrite-token" + overwriteTokenShortFlag = "o" + overwriteTokenUsage = "Overrides .otc-info file." + idpNameFlag = "idp-name" + idpNameShortFlag = "i" + idpNameEnv = "IDP_NAME" + idpNameUsage = "Required for authentication with IdP." + idpUrlFlag = "idp-url" + idpUrlEnv = "IDP_URL" + idpUrlUsage = "Required for authentication with IdP." + totpFlag = "totp" + totpShortFlag = "t" + totpUsage = "6-digit time-based one-time password (TOTP) used for the MFA login flow. Required together with the user-domain-id." + userDomainIdFlag = "os-user-domain-id" + userDomainIdEnv = "OS_USER_DOMAIN_ID" + userDomainIdUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIdEnv + "." +) diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 00000000..b7d8d4ef --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,47 @@ +/* +Copyright © 2023 IITS-Consulting + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "otc-auth", + Short: "A brief description of your application", + Long: `A longer description that spans multiple lines and likely contains +examples and usage of using your application. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) { }, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the RootCmd. +func Execute() { + err := RootCmd.Execute() + if err != nil { + os.Exit(1) + } +} diff --git a/cmd/version.go b/cmd/version.go new file mode 100644 index 00000000..05a5eacd --- /dev/null +++ b/cmd/version.go @@ -0,0 +1,10 @@ +package cmd + +import ( + "fmt" + "github.com/spf13/cobra" +) + +func SetVersionInfo(cmd *cobra.Command, version, date string) { + cmd.Version = fmt.Sprintf("%s built on %s", version, date) +} diff --git a/go.mod b/go.mod index b7a5d905..b5297069 100644 --- a/go.mod +++ b/go.mod @@ -10,38 +10,52 @@ require ( github.com/google/uuid v1.1.2 github.com/gophercloud/utils v0.0.0-20230330070308-5bd5e1d608f8 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 - golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.15.0 + golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 gopkg.in/yaml.v2 v2.4.0 k8s.io/client-go v0.25.2 ) require ( + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gophercloud/gophercloud v1.3.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.12 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.0 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/spf13/afero v1.9.3 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/subosito/gotenv v1.4.2 // indirect golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect + golang.org/x/time v0.1.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.25.2 // indirect k8s.io/klog/v2 v2.80.1 // indirect k8s.io/utils v0.0.0-20220922104903-7796b5f52b7e // indirect diff --git a/go.sum b/go.sum index e4d2f11b..e5131cfd 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -15,6 +16,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -52,6 +54,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -83,6 +86,8 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu6g= github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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= @@ -99,6 +104,9 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -164,7 +172,6 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -181,6 +188,7 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -198,6 +206,7 @@ github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/Oth github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gophercloud/gophercloud v1.3.0 h1:RUKyCMiZoQR3VlVR5E3K7PK1AC3/qppsWYo6dtBiqs8= github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gophercloud/utils v0.0.0-20230330070308-5bd5e1d608f8 h1:K9r5WEeAiaEgFZsuOP0OYjE4TtyFcCLG1nI08t9AP6A= @@ -206,10 +215,14 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -217,43 +230,70 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= +github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= +github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -276,7 +316,9 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 h1:a5Yg6ylndHHYJqIPrdq0AhvR6KTvDTAvgBtaidhEevY= golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -346,6 +388,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= @@ -385,8 +428,8 @@ golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -432,11 +475,13 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -461,6 +506,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -483,8 +529,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -532,6 +578,7 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -628,7 +675,9 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -728,6 +777,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/login.go b/login/login.go similarity index 95% rename from login.go rename to login/login.go index 31b969bd..aac612f1 100644 --- a/login.go +++ b/login/login.go @@ -1,6 +1,7 @@ -package main +package login import ( + "otc-auth" "otc-auth/common" "otc-auth/config" "otc-auth/iam" @@ -21,9 +22,9 @@ func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) { var tokenResponse common.TokenResponse switch authInfo.AuthType { case "idp": - if authInfo.AuthProtocol == protocolSAML { + if authInfo.AuthProtocol == main.protocolSAML { tokenResponse = saml.AuthenticateAndGetUnscopedToken(authInfo) - } else if authInfo.AuthProtocol == protocolOIDC { + } else if authInfo.AuthProtocol == main.protocolOIDC { tokenResponse = oidc.AuthenticateAndGetUnscopedToken(authInfo) } else { common.OutputErrorMessageToConsoleAndExit("fatal: unsupported login protocol.\n\nAllowed values are \"saml\" or \"oidc\". Please provide a valid argument and try again.") diff --git a/main.go b/main.go index af7eee1d..86e5b2dc 100644 --- a/main.go +++ b/main.go @@ -1,236 +1,30 @@ +/* +Copyright © 2023 IITS-Consulting + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ package main -import ( - "fmt" - "github.com/akamensky/argparse" - "os" - "otc-auth/accesstoken" - "otc-auth/cce" - "otc-auth/common" - "otc-auth/config" - "otc-auth/iam" - "otc-auth/openstack" -) +import "otc-auth/cmd" -// GoReleaser will set the following 2 ldflags by default var ( version = "dev" date = "unknown" ) -const ( - osUsername = "os-username" - osPassword = "os-password" - overwriteTokenArg = "overwrite-token" - osDomainName = "os-domain-name" - osUserDomainId = "os-user-domain-id" - osProjectName = "os-project-name" - totpArg = "totp" - idpName = "idp-name" - idpUrlArg = "idp-url" - clientIdArg = "client-id" - clientSecretArg = "client-secret" - clusterArg = "cluster" - isServiceAccountArg = "service-account" - oidcScopesArg = "oidc-scopes" -) - func main() { - const ( - provideArgumentHelp = "Either provide this argument or set the environment variable" - overwriteTokenHelp = "Overrides .otc-info file" - requiredForIdp = "Required for authentication with IdP." - ) - var ( - domainName *string - username *string - password *string - overwriteToken *bool - identityProvider *string - identityProviderUrl *string - isServiceAccount *bool - idpCommandHelp = fmt.Sprintf("The name of the identity provider. Allowed values in the iam section of the OTC UI. %s %s %s", requiredForIdp, provideArgumentHelp, envIdpName) - idpUrlCommandHelp = fmt.Sprintf("Url from the identity provider (e.g. ...realms/myrealm/protocol/saml). %s %s %s", requiredForIdp, provideArgumentHelp, envIdpUrl) - isServiceAccountHelp = "Flag to set if the account is a service account. The service account needs to be configured in your identity provider." - oidcScopesHelp = "Flag to set the scopes which are expected from the OIDC request." - ) - - parser := argparse.NewParser("otc-auth", "OTC-Auth Command Line Interface for managing OTC clouds.") - - // Version - versionCommand := parser.NewCommand("version", "Returns OTC-Auth's version.") - - // Login & common commands - loginCommand := parser.NewCommand("login", "Login to the Open Telekom Cloud and receive an unscoped token.") - username = loginCommand.String("u", osUsername, &argparse.Options{Required: false, Help: fmt.Sprintf("Username for the OTC IAM system. %s %s", provideArgumentHelp, envOsUsername)}) - password = loginCommand.String("p", osPassword, &argparse.Options{Required: false, Help: fmt.Sprintf("Password for the OTC IAM system. %s %s", provideArgumentHelp, envOsPassword)}) - domainName = loginCommand.String("d", osDomainName, &argparse.Options{Required: false, Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName)}) - overwriteToken = loginCommand.Flag("o", overwriteTokenArg, &argparse.Options{Required: false, Help: overwriteTokenHelp, Default: false}) - identityProvider = loginCommand.String("i", idpName, &argparse.Options{Required: false, Help: idpCommandHelp}) - identityProviderUrl = loginCommand.String("", idpUrlArg, &argparse.Options{Required: false, Help: idpUrlCommandHelp}) - - // Remove Login information - removeLoginCommand := loginCommand.NewCommand("remove", "Removes login information for a cloud") - - // Login with IAM - loginIamCommand := loginCommand.NewCommand("iam", "Login to the Open Telekom Cloud through its Identity and Access Management system.") - totp := loginIamCommand.String("t", totpArg, &argparse.Options{Required: false, Help: "6-digit time-based one-time password (TOTP) used for the MFA login flow."}) - userDomainId := loginIamCommand.String("", osUserDomainId, &argparse.Options{Required: false, Help: fmt.Sprintf("User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. %s %s", provideArgumentHelp, envOsUserDomainId)}) - - // Login with IDP + SAML - loginIdpSamlCommand := loginCommand.NewCommand("idp-saml", "Login to the Open Telekom Cloud through an Identity Provider and SAML.") - - // Login with IDP + OIDC - loginIdpOidcCommand := loginCommand.NewCommand("idp-oidc", "Login to the Open Telekom Cloud through an Identity Provider and OIDC.") - clientId := loginIdpOidcCommand.String("c", clientIdArg, &argparse.Options{Required: false, Help: fmt.Sprintf("Client Id as set on the IdP. %s %s", provideArgumentHelp, envClientId)}) - clientSecret := loginIdpOidcCommand.String("s", clientSecretArg, &argparse.Options{Required: false, Help: fmt.Sprintf("Secret Id as set on the IdP. %s %s", provideArgumentHelp, envClientSecret)}) - isServiceAccount = loginIdpOidcCommand.Flag("", isServiceAccountArg, &argparse.Options{Required: false, Help: isServiceAccountHelp}) - oidcScopes := loginIdpOidcCommand.String("", oidcScopesArg, &argparse.Options{Required: false, Help: oidcScopesHelp}) - // List Projects - projectsCommand := parser.NewCommand("projects", "Manage Project Information") - listProjectsCommand := projectsCommand.NewCommand("list", "List Projects in Active Cloud") - - // Manage Cloud Container Engine - cceCommand := parser.NewCommand("cce", "Manage Cloud Container Engine.") - projectName := cceCommand.String("p", osProjectName, &argparse.Options{Required: false, Help: fmt.Sprintf("Name of the project you want to access. %s %s.", provideArgumentHelp, envOsProjectName)}) - cceDomainName := cceCommand.String("d", osDomainName, &argparse.Options{Required: false, Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName)}) - - // List clusters - getClustersCommand := cceCommand.NewCommand("list", "Lists Project Clusters in CCE.") - - // Get Kubernetes Configuration - getKubeConfigCommand := cceCommand.NewCommand("get-kube-config", "Get remote kube config and merge it with existing local config file.") - clusterName := getKubeConfigCommand.String("c", clusterArg, &argparse.Options{Required: false, Help: fmt.Sprintf("Name of the clusterArg you want to access %s %s.", provideArgumentHelp, envClusterName)}) - daysValid := getKubeConfigCommand.String("v", "days-valid", &argparse.Options{Required: false, Help: "Period (in days) that the config will be valid", Default: "7"}) - targetLocation := getKubeConfigCommand.String("l", "target-location", &argparse.Options{Required: false, Help: "Where the kube config should be saved, Default: ~/.kube/config"}) - - // AK/SK Management - accessTokenCommand := parser.NewCommand("access-token", "Manage AK/SK.") - accessTokenCommandCreate := accessTokenCommand.NewCommand("create", "Create new AK/SK.") - atDomainName := accessTokenCommand.String("d", osDomainName, &argparse.Options{Required: false, Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName)}) - durationSeconds := accessTokenCommandCreate.Int("t", "duration-seconds", &argparse.Options{Required: false, Help: "Lifetime of AK/SK, min 900 seconds.", Default: 900}) - - //Openstack Management - openStackCommand := parser.NewCommand("openstack", "Manage Openstack Integration") - openStackCommandCreateConfigFile := openStackCommand.NewCommand("config-create", "Creates new clouds.yaml") - openStackConfigLocation := openStackCommand.String("l", "config-location", &argparse.Options{Required: false, Help: "Where the config should be saved, Default: ~/.config/openstack/clouds.yaml"}) - - err := parser.Parse(os.Args) - if err != nil { - common.OutputErrorMessageToConsoleAndExit(parser.Usage(err)) - } - - if versionCommand.Happened() { - _, err := fmt.Fprintf(os.Stdout, "OTC-Auth %s (%s)", version, date) - if err != nil { - common.OutputErrorToConsoleAndExit(err, "fatal: could not print tool version.") - } - } - - if loginIamCommand.Happened() { - totpToken, userId := checkMFAFlowIAM(*totp, *userDomainId) - authInfo := common.AuthInfo{ - AuthType: authTypeIAM, - Username: getUsernameOrThrow(*username), - Password: getPasswordOrThrow(*password), - DomainName: getDomainNameOrThrow(*domainName), - Otp: totpToken, - UserDomainId: userId, - OverwriteFile: *overwriteToken, - } - - AuthenticateAndGetUnscopedToken(authInfo) - } - - if loginIdpSamlCommand.Happened() { - identityProvider, identityProviderUrl := getIdpInfoOrThrow(*identityProvider, *identityProviderUrl) - authInfo := common.AuthInfo{ - AuthType: authTypeIDP, - Username: getUsernameOrThrow(*username), - Password: getPasswordOrThrow(*password), - DomainName: getDomainNameOrThrow(*domainName), - IdpName: identityProvider, - IdpUrl: identityProviderUrl, - AuthProtocol: protocolSAML, - OverwriteFile: *overwriteToken, - } - - AuthenticateAndGetUnscopedToken(authInfo) - } - - if loginIdpOidcCommand.Happened() { - identityProvider, identityProviderUrl := getIdpInfoOrThrow(*identityProvider, *identityProviderUrl) - authInfo := common.AuthInfo{ - AuthType: authTypeIDP, - IdpName: identityProvider, - IdpUrl: identityProviderUrl, - AuthProtocol: protocolOIDC, - DomainName: getDomainNameOrThrow(*domainName), - ClientId: getClientIdOrThrow(*clientId), - ClientSecret: findClientSecretOrReturnEmpty(*clientSecret), - OverwriteFile: *overwriteToken, - IsServiceAccount: *isServiceAccount, - OidcScopes: getOidcScopes(*oidcScopes), - } - - AuthenticateAndGetUnscopedToken(authInfo) - } - - if removeLoginCommand.Happened() { - domainNameToRemove := getDomainNameOrThrow(*domainName) - config.RemoveCloudConfig(domainNameToRemove) - } - - if listProjectsCommand.Happened() { - iam.GetProjectsInActiveCloud() - } - - if cceCommand.Happened() { - domainName := getDomainNameOrThrow(*cceDomainName) - config.LoadCloudConfig(domainName) - - if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit("fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") - } - - project := getProjectNameOrThrow(*projectName) - - if getKubeConfigCommand.Happened() { - cluster := getClusterNameOrThrow(*clusterName) - - kubeConfigParams := cce.KubeConfigParams{ - ProjectName: project, - ClusterName: cluster, - DaysValid: *daysValid, - TargetLocation: *targetLocation, - } - - cce.GetKubeConfig(kubeConfigParams) - return - } - - if getClustersCommand.Happened() { - cce.GetClusterNames(project) - return - } - } - - if accessTokenCommandCreate.Happened() { - domainName := getDomainNameOrThrow(*atDomainName) - config.LoadCloudConfig(domainName) - - if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit("fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") - } - - if *durationSeconds < 900 { - common.OutputErrorMessageToConsoleAndExit("fatal: argument duration-seconds may not be smaller then 900 seconds") - } - accesstoken.CreateAccessToken(*durationSeconds) - } - - if openStackCommandCreateConfigFile.Happened() { - openstack.WriteOpenStackCloudsYaml(*openStackConfigLocation) - } + cmd.SetVersionInfo(cmd.RootCmd, version, date) + cmd.Execute() } diff --git a/oldmain.go b/oldmain.go new file mode 100644 index 00000000..f6d2cbbc --- /dev/null +++ b/oldmain.go @@ -0,0 +1,231 @@ +package main + +import ( + "fmt" + "github.com/akamensky/argparse" + "os" + "otc-auth/accesstoken" + "otc-auth/cce" + "otc-auth/common" + "otc-auth/config" + "otc-auth/iam" + "otc-auth/login" + "otc-auth/openstack" +) + +const ( + osUsername = "os-username" + osPassword = "os-password" + overwriteTokenArg = "overwrite-token" + osDomainName = "os-domain-name" + osUserDomainId = "os-user-domain-id" + osProjectName = "os-project-name" + totpArg = "totp" + idpName = "idp-name" + idpUrlArg = "idp-url" + clientIdArg = "client-id" + clientSecretArg = "client-secret" + clusterArg = "cluster" + isServiceAccountArg = "service-account" + oidcScopesArg = "oidc-scopes" +) + +func nomain() { + const ( + provideArgumentHelp = "Either provide this argument or set the environment variable" + overwriteTokenHelp = "Overrides .otc-info file" + requiredForIdp = "Required for authentication with IdP." + ) + var ( + domainName *string + username *string + password *string + overwriteToken *bool + identityProvider *string + identityProviderUrl *string + isServiceAccount *bool + idpCommandHelp = fmt.Sprintf("The name of the identity provider. Allowed values in the iam section of the OTC UI. %s %s %s", requiredForIdp, provideArgumentHelp, envIdpName) + idpUrlCommandHelp = fmt.Sprintf("Url from the identity provider (e.g. ...realms/myrealm/protocol/saml). %s %s %s", requiredForIdp, provideArgumentHelp, envIdpUrl) + isServiceAccountHelp = "Flag to set if the account is a service account. The service account needs to be configured in your identity provider." + oidcScopesHelp = "Flag to set the scopes which are expected from the OIDC request." + ) + + parser := argparse.NewParser("otc-auth", "OTC-Auth Command Line Interface for managing OTC clouds.") + + // Version + versionCommand := parser.NewCommand("version", "Returns OTC-Auth's version.") + + // Login & common commands + loginCommand := parser.NewCommand("login", "Login to the Open Telekom Cloud and receive an unscoped token.") + username = loginCommand.String("u", osUsername, &argparse.Options{Required: false, Help: fmt.Sprintf("Username for the OTC IAM system. %s %s", provideArgumentHelp, envOsUsername)}) + password = loginCommand.String("p", osPassword, &argparse.Options{Required: false, Help: fmt.Sprintf("Password for the OTC IAM system. %s %s", provideArgumentHelp, envOsPassword)}) + domainName = loginCommand.String("d", osDomainName, &argparse.Options{Required: false, Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName)}) + overwriteToken = loginCommand.Flag("o", overwriteTokenArg, &argparse.Options{Required: false, Help: overwriteTokenHelp, Default: false}) + identityProvider = loginCommand.String("i", idpName, &argparse.Options{Required: false, Help: idpCommandHelp}) + identityProviderUrl = loginCommand.String("", idpUrlArg, &argparse.Options{Required: false, Help: idpUrlCommandHelp}) + + // Remove Login information + removeLoginCommand := loginCommand.NewCommand("remove", "Removes login information for a cloud") + + // Login with IAM + loginIamCommand := loginCommand.NewCommand("iam", "Login to the Open Telekom Cloud through its Identity and Access Management system.") + totp := loginIamCommand.String("t", totpArg, &argparse.Options{Required: false, Help: "6-digit time-based one-time password (TOTP) used for the MFA login flow."}) + userDomainId := loginIamCommand.String("", osUserDomainId, &argparse.Options{Required: false, Help: fmt.Sprintf("User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. %s %s", provideArgumentHelp, envOsUserDomainId)}) + + // Login with IDP + SAML + loginIdpSamlCommand := loginCommand.NewCommand("idp-saml", "Login to the Open Telekom Cloud through an Identity Provider and SAML.") + + // Login with IDP + OIDC + loginIdpOidcCommand := loginCommand.NewCommand("idp-oidc", "Login to the Open Telekom Cloud through an Identity Provider and OIDC.") + clientId := loginIdpOidcCommand.String("c", clientIdArg, &argparse.Options{Required: false, Help: fmt.Sprintf("Client Id as set on the IdP. %s %s", provideArgumentHelp, envClientId)}) + clientSecret := loginIdpOidcCommand.String("s", clientSecretArg, &argparse.Options{Required: false, Help: fmt.Sprintf("Secret Id as set on the IdP. %s %s", provideArgumentHelp, envClientSecret)}) + isServiceAccount = loginIdpOidcCommand.Flag("", isServiceAccountArg, &argparse.Options{Required: false, Help: isServiceAccountHelp}) + oidcScopes := loginIdpOidcCommand.String("", oidcScopesArg, &argparse.Options{Required: false, Help: oidcScopesHelp}) + // List Projects + projectsCommand := parser.NewCommand("projects", "Manage Project Information") + listProjectsCommand := projectsCommand.NewCommand("list", "List Projects in Active Cloud") + + // Manage Cloud Container Engine + cceCommand := parser.NewCommand("cce", "Manage Cloud Container Engine.") + projectName := cceCommand.String("p", osProjectName, &argparse.Options{Required: false, Help: fmt.Sprintf("Name of the project you want to access. %s %s.", provideArgumentHelp, envOsProjectName)}) + cceDomainName := cceCommand.String("d", osDomainName, &argparse.Options{Required: false, Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName)}) + + // List clusters + getClustersCommand := cceCommand.NewCommand("list", "Lists Project Clusters in CCE.") + + // Get Kubernetes Configuration + getKubeConfigCommand := cceCommand.NewCommand("get-kube-config", "Get remote kube config and merge it with existing local config file.") + clusterName := getKubeConfigCommand.String("c", clusterArg, &argparse.Options{Required: false, Help: fmt.Sprintf("Name of the clusterArg you want to access %s %s.", provideArgumentHelp, envClusterName)}) + daysValid := getKubeConfigCommand.String("v", "days-valid", &argparse.Options{Required: false, Help: "Period (in days) that the config will be valid", Default: "7"}) + targetLocation := getKubeConfigCommand.String("l", "target-location", &argparse.Options{Required: false, Help: "Where the kube config should be saved, Default: ~/.kube/config"}) + + // AK/SK Management + accessTokenCommand := parser.NewCommand("access-token", "Manage AK/SK.") + accessTokenCommandCreate := accessTokenCommand.NewCommand("create", "Create new AK/SK.") + atDomainName := accessTokenCommand.String("d", osDomainName, &argparse.Options{Required: false, Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName)}) + durationSeconds := accessTokenCommandCreate.Int("t", "duration-seconds", &argparse.Options{Required: false, Help: "Lifetime of AK/SK, min 900 seconds.", Default: 900}) + + //Openstack Management + openStackCommand := parser.NewCommand("openstack", "Manage Openstack Integration") + openStackCommandCreateConfigFile := openStackCommand.NewCommand("config-create", "Creates new clouds.yaml") + openStackConfigLocation := openStackCommand.String("l", "config-location", &argparse.Options{Required: false, Help: "Where the config should be saved, Default: ~/.config/openstack/clouds.yaml"}) + + err := parser.Parse(os.Args) + if err != nil { + common.OutputErrorMessageToConsoleAndExit(parser.Usage(err)) + } + + if versionCommand.Happened() { + _, err := fmt.Fprintf(os.Stdout, "OTC-Auth %s (%s)", version, date) + if err != nil { + common.OutputErrorToConsoleAndExit(err, "fatal: could not print tool version.") + } + } + + if loginIamCommand.Happened() { + totpToken, userId := checkMFAFlowIAM(*totp, *userDomainId) + authInfo := common.AuthInfo{ + AuthType: authTypeIAM, + Username: getUsernameOrThrow(*username), + Password: getPasswordOrThrow(*password), + DomainName: getDomainNameOrThrow(*domainName), + Otp: totpToken, + UserDomainId: userId, + OverwriteFile: *overwriteToken, + } + + login.AuthenticateAndGetUnscopedToken(authInfo) + } + + if loginIdpSamlCommand.Happened() { + identityProvider, identityProviderUrl := getIdpInfoOrThrow(*identityProvider, *identityProviderUrl) + authInfo := common.AuthInfo{ + AuthType: authTypeIDP, + Username: getUsernameOrThrow(*username), + Password: getPasswordOrThrow(*password), + DomainName: getDomainNameOrThrow(*domainName), + IdpName: identityProvider, + IdpUrl: identityProviderUrl, + AuthProtocol: protocolSAML, + OverwriteFile: *overwriteToken, + } + + login.AuthenticateAndGetUnscopedToken(authInfo) + } + + if loginIdpOidcCommand.Happened() { + identityProvider, identityProviderUrl := getIdpInfoOrThrow(*identityProvider, *identityProviderUrl) + authInfo := common.AuthInfo{ + AuthType: authTypeIDP, + IdpName: identityProvider, + IdpUrl: identityProviderUrl, + AuthProtocol: protocolOIDC, + DomainName: getDomainNameOrThrow(*domainName), + ClientId: getClientIdOrThrow(*clientId), + ClientSecret: findClientSecretOrReturnEmpty(*clientSecret), + OverwriteFile: *overwriteToken, + IsServiceAccount: *isServiceAccount, + OidcScopes: getOidcScopes(*oidcScopes), + } + + login.AuthenticateAndGetUnscopedToken(authInfo) + } + + if removeLoginCommand.Happened() { + domainNameToRemove := getDomainNameOrThrow(*domainName) + config.RemoveCloudConfig(domainNameToRemove) + } + + if listProjectsCommand.Happened() { + iam.GetProjectsInActiveCloud() + } + + if cceCommand.Happened() { + domainName := getDomainNameOrThrow(*cceDomainName) + config.LoadCloudConfig(domainName) + + if !config.IsAuthenticationValid() { + common.OutputErrorMessageToConsoleAndExit("fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + } + + project := getProjectNameOrThrow(*projectName) + + if getKubeConfigCommand.Happened() { + cluster := getClusterNameOrThrow(*clusterName) + + kubeConfigParams := cce.KubeConfigParams{ + ProjectName: project, + ClusterName: cluster, + DaysValid: *daysValid, + TargetLocation: *targetLocation, + } + + cce.GetKubeConfig(kubeConfigParams) + return + } + + if getClustersCommand.Happened() { + cce.GetClusterNames(project) + return + } + } + + if accessTokenCommandCreate.Happened() { + domainName := getDomainNameOrThrow(*atDomainName) + config.LoadCloudConfig(domainName) + + if !config.IsAuthenticationValid() { + common.OutputErrorMessageToConsoleAndExit("fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + } + + if *durationSeconds < 900 { + common.OutputErrorMessageToConsoleAndExit("fatal: argument duration-seconds may not be smaller then 900 seconds") + } + accesstoken.CreateAccessToken(*durationSeconds) + } + + if openStackCommandCreateConfigFile.Happened() { + openstack.WriteOpenStackCloudsYaml(*openStackConfigLocation) + } + +} From e1f5a9eedfc30954c1926f7a75f9d32cf193f0d4 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 28 Jun 2023 11:14:40 +0200 Subject: [PATCH 02/16] Better help message and usage --- cmd/login.go | 6 ++++-- go.mod | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/login.go b/cmd/login.go index 1c7e8ce5..97677e20 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -35,8 +35,8 @@ var loginCmd = &cobra.Command{ var loginIamCmd = &cobra.Command{ Use: "iam", Short: loginIamCmdHelp, - Long: "Here we can put a longer description of this command", // TODO - Example: "Here comes an example usage of this command", // TODO + Long: loginIamCmdLongHelp, + Example: loginIamCmdExample, PreRunE: func(cmd *cobra.Command, args []string) error { return initializeConfig(cmd, loginIamFlagToEnv) }, @@ -219,6 +219,8 @@ func init() { const ( loginCmdHelp = "Login to the Open Telekom Cloud and receive an unscoped token." loginIamCmdHelp = "Login to the Open Telekom Cloud through its Identity and Access Management system." + loginIamCmdLongHelp = "Login to the Open Telekom Cloud and receive an unscoped token." + loginIamCmdExample = "otc-auth login iam --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" loginIdpSamlCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and SAML." loginIdpOidcCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and OIDC." loginRemoveCmdHelp = "Removes login information for a cloud" diff --git a/go.mod b/go.mod index b5297069..d04ca122 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module otc-auth -go 1.19 +go 1.20 require ( github.com/akamensky/argparse v1.4.0 From f9e3b51647c3f656731d099b67c4c4d3f4b000a5 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 28 Jun 2023 11:20:11 +0200 Subject: [PATCH 03/16] Remove accidental cyclic dependency --- argument_verifier.go | 146 ------------------------------------- login/argument_verifier.go | 22 ++++++ login/login.go | 5 +- 3 files changed, 24 insertions(+), 149 deletions(-) delete mode 100644 argument_verifier.go create mode 100644 login/argument_verifier.go diff --git a/argument_verifier.go b/argument_verifier.go deleted file mode 100644 index 76152030..00000000 --- a/argument_verifier.go +++ /dev/null @@ -1,146 +0,0 @@ -package main - -import ( - "fmt" - "os" - "otc-auth/common" - "strings" -) - -const ( - envOsUsername = "OS_USERNAME" - envOsPassword = "OS_PASSWORD" - envOsDomainName = "OS_DOMAIN_NAME" - envOsUserDomainId = "OS_USER_DOMAIN_ID" - envOsProjectName = "OS_PROJECT_NAME" - envIdpName = "IDP_NAME" - envIdpUrl = "IDP_URL" - envClientId = "CLIENT_ID" - envClientSecret = "CLIENT_SECRET" - envClusterName = "CLUSTER_NAME" - envOidScopes = "OIDC_SCOPES" - envOidcScopesDefault = "openid,profile,roles,name,groups,email" - - authTypeIDP = "idp" - authTypeIAM = "iam" - - protocolSAML = "saml" - protocolOIDC = "oidc" -) - -func getProjectNameOrThrow(projectName string) string { - if projectName != "" { - return projectName - } - - return getEnvironmentVariableOrThrow(osProjectName, envOsProjectName) -} - -func getClusterNameOrThrow(clusterName string) string { - if clusterName != "" { - return clusterName - } - - return getEnvironmentVariableOrThrow(clusterArg, envClusterName) -} - -func getIdpInfoOrThrow(provider string, url string) (string, string) { - provider = checkIDPProviderIsSet(provider) - url = checkIdpUrlIsSet(url) - return provider, url -} - -func checkIDPProviderIsSet(provider string) string { - if provider != "" { - return provider - } - - return getEnvironmentVariableOrThrow(idpName, envIdpName) -} - -func checkIdpUrlIsSet(url string) string { - if url != "" { - return url - } - - return getEnvironmentVariableOrThrow(idpUrlArg, envIdpUrl) -} - -func getUsernameOrThrow(username string) string { - if username != "" { - return username - } - - return getEnvironmentVariableOrThrow(osUsername, envOsUsername) -} - -func getPasswordOrThrow(password string) string { - if password != "" { - return password - } - - return getEnvironmentVariableOrThrow(osPassword, envOsPassword) -} - -func getDomainNameOrThrow(domainName string) string { - if domainName != "" { - return domainName - } - - return getEnvironmentVariableOrThrow(osDomainName, envOsDomainName) -} - -func checkMFAFlowIAM(otp string, userId string) (string, string) { - if otp != "" { - if userId != "" { - return otp, userId - } - userId = getEnvironmentVariableOrThrow(osUserDomainId, envOsUserDomainId) - } - - return otp, userId -} - -func getClientIdOrThrow(id string) string { - if id != "" { - return id - } - - return getEnvironmentVariableOrThrow(clientIdArg, envClientId) -} - -func findClientSecretOrReturnEmpty(secret string) string { - if secret != "" { - return secret - } else if secretEnvVar, ok := os.LookupEnv(envClientSecret); ok { - return secretEnvVar - } else { - println(fmt.Sprintf("info: argument --%s not set. Continuing...\n", clientSecretArg)) - return "" - } -} - -func getOidcScopes(scopesFromFlag string) []string { - if scopesFromFlag != "" { - return strings.Split(scopesFromFlag, ",") - } - - scopeFromEnv, ok := os.LookupEnv(envOidScopes) - if ok { - return strings.Split(scopeFromEnv, ",") - } - return strings.Split(envOidcScopesDefault, ",") -} - -func getEnvironmentVariableOrThrow(argument string, envVarName string) string { - environmentVariable, ok := os.LookupEnv(envVarName) - if !ok || environmentVariable == "" { - common.OutputErrorMessageToConsoleAndExit(noArgumentProvidedErrorMessage(fmt.Sprintf("--%s", argument), envVarName)) - } - - return environmentVariable -} - -func noArgumentProvidedErrorMessage(argument string, environmentVariable string) string { - return fmt.Sprintf("fatal: %s not provided.\n\nPlease make sure the argument %s is provided or the environment variable %s is set.", argument, argument, environmentVariable) -} diff --git a/login/argument_verifier.go b/login/argument_verifier.go new file mode 100644 index 00000000..4e92653a --- /dev/null +++ b/login/argument_verifier.go @@ -0,0 +1,22 @@ +package login + +const ( + envOsUsername = "OS_USERNAME" + envOsPassword = "OS_PASSWORD" + envOsDomainName = "OS_DOMAIN_NAME" + envOsUserDomainId = "OS_USER_DOMAIN_ID" + envOsProjectName = "OS_PROJECT_NAME" + envIdpName = "IDP_NAME" + envIdpUrl = "IDP_URL" + envClientId = "CLIENT_ID" + envClientSecret = "CLIENT_SECRET" + envClusterName = "CLUSTER_NAME" + envOidScopes = "OIDC_SCOPES" + envOidcScopesDefault = "openid,profile,roles,name,groups,email" + + authTypeIDP = "idp" + authTypeIAM = "iam" + + protocolSAML = "saml" + protocolOIDC = "oidc" +) diff --git a/login/login.go b/login/login.go index aac612f1..399767ac 100644 --- a/login/login.go +++ b/login/login.go @@ -1,7 +1,6 @@ package login import ( - "otc-auth" "otc-auth/common" "otc-auth/config" "otc-auth/iam" @@ -22,9 +21,9 @@ func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) { var tokenResponse common.TokenResponse switch authInfo.AuthType { case "idp": - if authInfo.AuthProtocol == main.protocolSAML { + if authInfo.AuthProtocol == protocolSAML { tokenResponse = saml.AuthenticateAndGetUnscopedToken(authInfo) - } else if authInfo.AuthProtocol == main.protocolOIDC { + } else if authInfo.AuthProtocol == protocolOIDC { tokenResponse = oidc.AuthenticateAndGetUnscopedToken(authInfo) } else { common.OutputErrorMessageToConsoleAndExit("fatal: unsupported login protocol.\n\nAllowed values are \"saml\" or \"oidc\". Please provide a valid argument and try again.") From bbef7be0ae392dfe5f5779c378fe17454f8581bc Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 5 Jul 2023 12:34:46 +0200 Subject: [PATCH 04/16] Refactoring and adding project and cce --- cmd/cmd_config.go | 38 ++++++ cmd/login.go | 255 ---------------------------------- cmd/root.go | 341 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 368 insertions(+), 266 deletions(-) create mode 100644 cmd/cmd_config.go delete mode 100644 cmd/login.go diff --git a/cmd/cmd_config.go b/cmd/cmd_config.go new file mode 100644 index 00000000..b423d4fa --- /dev/null +++ b/cmd/cmd_config.go @@ -0,0 +1,38 @@ +package cmd + +import ( + "fmt" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/spf13/viper" +) + +/* +initializeConfig is a helper function which sets the environment variable for a flag. It gives precedence to the flag, +meaning that the env is only taken if the flag is empty. It assigns the environment variables to the flags which are +defined in the map flagToEnvMap. +*/ +func initializeConfig(cmd *cobra.Command, flagToEnvMapping map[string]string) error { + v := viper.New() + v.AutomaticEnv() + + cmd.Flags().VisitAll( + func(f *pflag.Flag) { + configName, ok := flagToEnvMapping[f.Name] + if !ok { + return + } + if !f.Changed && v.IsSet(configName) { + val := v.Get(configName) + _ = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) + } + }) + + return nil +} + +func configureCmdFlagsAgainstEnvs(flagToEnvMapping map[string]string) func(*cobra.Command, []string) error { + return func(cmd *cobra.Command, args []string) error { + return initializeConfig(cmd, flagToEnvMapping) + } +} diff --git a/cmd/login.go b/cmd/login.go deleted file mode 100644 index 0a1c529b..00000000 --- a/cmd/login.go +++ /dev/null @@ -1,255 +0,0 @@ -/* -Copyright © 2023 IITS-Consulting - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -package cmd - -import ( - "fmt" - "github.com/spf13/pflag" - "otc-auth/common" - "otc-auth/config" - "otc-auth/login" - - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var loginCmd = &cobra.Command{ - Use: "login", - Short: loginCmdHelp, -} - -var loginIamCmd = &cobra.Command{ - Use: "iam", - Short: loginIamCmdHelp, - Long: loginIamCmdLongHelp, - Example: loginIamCmdExample, - PreRunE: func(cmd *cobra.Command, args []string) error { - return initializeConfig(cmd, loginIamFlagToEnv) - }, - Run: func(cmd *cobra.Command, args []string) { - authInfo := common.AuthInfo{ - AuthType: "iam", - Username: username, - Password: password, - DomainName: domainName, - Otp: totp, - UserDomainID: userDomainId, - OverwriteFile: overwriteToken, - } - login.AuthenticateAndGetUnscopedToken(authInfo) - }, -} - -var loginIdpSamlCmd = &cobra.Command{ - Use: "idp-saml", - Short: loginIdpSamlCmdHelp, - Long: "Here we can put a longer description of this command", // TODO - Example: "Here comes an example usage of this command", // TODO - PreRunE: func(cmd *cobra.Command, args []string) error { - return initializeConfig(cmd, loginIdpSamlOidcFlagToEnv) - }, - Run: func(cmd *cobra.Command, args []string) { - authInfo := common.AuthInfo{ - AuthType: "idp", - Username: username, - Password: password, - DomainName: domainName, - IdpName: idpName, - IdpURL: idpUrl, - AuthProtocol: "saml", - OverwriteFile: overwriteToken, - } - login.AuthenticateAndGetUnscopedToken(authInfo) - }, -} - -var loginIdpOidcCmd = &cobra.Command{ - Use: "idp-oidc", - Short: loginIdpOidcCmdHelp, // TODO - Long: "Here we can put a longer description of this command", // TODO - Example: "Here comes an example usage of this command", // TODO - PreRunE: func(cmd *cobra.Command, args []string) error { - return initializeConfig(cmd, loginIdpSamlOidcFlagToEnv) - }, - Run: func(cmd *cobra.Command, args []string) { - authInfo := common.AuthInfo{ - AuthType: "idp", - Username: username, - Password: password, - DomainName: domainName, - IdpName: idpName, - IdpURL: idpUrl, - AuthProtocol: "oidc", - OverwriteFile: overwriteToken, - } - login.AuthenticateAndGetUnscopedToken(authInfo) - }, -} - -var loginRemoveCmd = &cobra.Command{ - Use: "remove", - Short: loginRemoveCmdHelp, - Long: "Here we can put a longer description of this command", // TODO - Example: "Here comes an example usage of this command", // TODO - PreRunE: func(cmd *cobra.Command, args []string) error { - return initializeConfig(cmd, loginRemoveFlagToEnv) - }, - Run: func(cmd *cobra.Command, args []string) { - config.RemoveCloudConfig(domainName) - }, -} - -var ( - username string - password string - domainName string - overwriteToken bool - idpName string - idpUrl string - totp string - userDomainId string - - loginIamFlagToEnv = map[string]string{ - usernameFlag: usernameEnv, - passwordFlag: passwordEnv, - domainNameFlag: domainNameEnv, - userDomainIdFlag: userDomainIdEnv, - idpNameFlag: idpNameEnv, - idpUrlFlag: idpUrlEnv, - } - - loginIdpSamlOidcFlagToEnv = map[string]string{ - usernameFlag: usernameEnv, - passwordFlag: passwordEnv, - domainNameFlag: domainNameEnv, - userDomainIdFlag: userDomainIdEnv, - idpNameFlag: idpNameEnv, - idpUrlFlag: idpUrlEnv, - } - - loginRemoveFlagToEnv = map[string]string{ - userDomainIdFlag: userDomainIdEnv, - } -) - -/* -initializeConfig is a helper function which sets the environment variable for a flag. It gives precedence to the flag, -meaning that the env is only taken if the flag is empty. It assigns the environment variables to the flags which are -defined in the map flagToEnvMap. -*/ -func initializeConfig(cmd *cobra.Command, flagToEnvMapping map[string]string) error { - v := viper.New() - v.AutomaticEnv() - - cmd.Flags().VisitAll( - func(f *pflag.Flag) { - configName, ok := flagToEnvMapping[f.Name] - if !ok { - return - } - if !f.Changed && v.IsSet(configName) { - val := v.Get(configName) - _ = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) - } - }) - return nil -} - -func init() { - RootCmd.AddCommand(loginCmd) - - loginCmd.AddCommand(loginIamCmd) - loginIamCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) - loginIamCmd.MarkFlagRequired(usernameFlag) - loginIamCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) - loginIamCmd.MarkFlagRequired(passwordFlag) - loginIamCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - loginIamCmd.MarkFlagRequired(domainNameFlag) - loginIamCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) - loginIamCmd.Flags().StringVarP(&totp, totpFlag, totpShortFlag, "", totpUsage) - loginIamCmd.Flags().StringVarP(&userDomainId, userDomainIdFlag, "", "", userDomainIdUsage) - loginIamCmd.MarkFlagsRequiredTogether(totpFlag, userDomainIdFlag) - - loginCmd.AddCommand(loginIdpSamlCmd) - loginIdpSamlCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) - loginIdpSamlCmd.MarkFlagRequired(usernameFlag) - loginIdpSamlCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) - loginIdpSamlCmd.MarkFlagRequired(passwordFlag) - loginIdpSamlCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - loginIdpSamlCmd.MarkFlagRequired(domainNameFlag) - loginIdpSamlCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) - loginIdpSamlCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) - loginIdpSamlCmd.MarkPersistentFlagRequired(idpNameFlag) - loginIdpSamlCmd.PersistentFlags().StringVarP(&idpUrl, idpUrlFlag, "", "", idpUrlUsage) - loginIdpSamlCmd.MarkPersistentFlagRequired(idpUrlFlag) - - loginCmd.AddCommand(loginIdpOidcCmd) - loginIdpOidcCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) - loginIdpOidcCmd.MarkFlagRequired(usernameFlag) - loginIdpOidcCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) - loginIdpOidcCmd.MarkFlagRequired(passwordFlag) - loginIdpOidcCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - loginIdpOidcCmd.MarkFlagRequired(domainNameFlag) - loginIdpOidcCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) - loginIdpOidcCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) - loginIdpOidcCmd.MarkPersistentFlagRequired(idpNameFlag) - loginIdpOidcCmd.PersistentFlags().StringVarP(&idpUrl, idpUrlFlag, "", "", idpUrlUsage) - loginIdpOidcCmd.MarkPersistentFlagRequired(idpUrlFlag) - - loginCmd.AddCommand(loginRemoveCmd) - loginRemoveCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - loginRemoveCmd.MarkFlagRequired(domainNameFlag) - -} - -const ( - loginCmdHelp = "Login to the Open Telekom Cloud and receive an unscoped token." - loginIamCmdHelp = "Login to the Open Telekom Cloud through its Identity and Access Management system." - loginIamCmdLongHelp = "Login to the Open Telekom Cloud and receive an unscoped token." - loginIamCmdExample = "otc-auth login iam --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" - loginIdpSamlCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and SAML." - loginIdpOidcCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and OIDC." - loginRemoveCmdHelp = "Removes login information for a cloud" - usernameFlag = "os-username" - usernameShortFlag = "u" - usernameEnv = "OS_USERNAME" - usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." - passwordFlag = "os-password" - passwordShortFlag = "p" - passwordEnv = "OS_PASSWORD" - passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." - domainNameFlag = "os-domain-name" - domainNameShortFlag = "d" - domainNameEnv = "OS_DOMAIN_NAME" - domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." - overwriteTokenFlag = "overwrite-token" - overwriteTokenShortFlag = "o" - overwriteTokenUsage = "Overrides .otc-info file." - idpNameFlag = "idp-name" - idpNameShortFlag = "i" - idpNameEnv = "IDP_NAME" - idpNameUsage = "Required for authentication with IdP." - idpUrlFlag = "idp-url" - idpUrlEnv = "IDP_URL" - idpUrlUsage = "Required for authentication with IdP." - totpFlag = "totp" - totpShortFlag = "t" - totpUsage = "6-digit time-based one-time password (TOTP) used for the MFA login flow. Required together with the user-domain-id." - userDomainIdFlag = "os-user-domain-id" - userDomainIdEnv = "OS_USER_DOMAIN_ID" - userDomainIdUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIdEnv + "." -) diff --git a/cmd/root.go b/cmd/root.go index b7d8d4ef..a8ddc075 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,7 +17,15 @@ along with this program. If not, see . package cmd import ( + "k8s.io/client-go/util/homedir" "os" + "otc-auth/cce" + "otc-auth/common" + "otc-auth/config" + "otc-auth/iam" + "otc-auth/login" + "strconv" + "strings" "github.com/spf13/cobra" ) @@ -25,23 +33,334 @@ import ( // RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ Use: "otc-auth", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: + Short: "OTC-Auth Command Line Interface for managing OTC clouds", +} + +var loginCmd = &cobra.Command{ + Use: "login", + Short: loginCmdHelp, +} + +var loginIamCmd = &cobra.Command{ + Use: "iam", + Short: loginIamCmdHelp, + Example: loginIamCmdExample, + PreRunE: configureCmdFlagsAgainstEnvs(loginIamFlagToEnv), + Run: func(cmd *cobra.Command, args []string) { + authInfo := common.AuthInfo{ + AuthType: "iam", + Username: username, + Password: password, + DomainName: domainName, + Otp: totp, + UserDomainID: userDomainId, + OverwriteFile: overwriteToken, + Region: region, + } + login.AuthenticateAndGetUnscopedToken(authInfo) + }, +} + +var loginIdpSamlCmd = &cobra.Command{ + Use: "idp-saml", + Short: loginIdpSamlCmdHelp, + Example: loginIdpSamlCmdExample, + PreRunE: configureCmdFlagsAgainstEnvs(loginIdpSamlOidcFlagToEnv), + Run: func(cmd *cobra.Command, args []string) { + authInfo := common.AuthInfo{ + AuthType: "idp", + Username: username, + Password: password, + DomainName: domainName, + IdpName: idpName, + IdpURL: idpUrl, + AuthProtocol: "saml", + OverwriteFile: overwriteToken, + Region: region, + } + login.AuthenticateAndGetUnscopedToken(authInfo) + }, +} + +var loginIdpOidcCmd = &cobra.Command{ + Use: "idp-oidc", + Short: loginIdpOidcCmdHelp, + Example: loginIdpOidcCmdExample, + PreRunE: configureCmdFlagsAgainstEnvs(loginIdpSamlOidcFlagToEnv), + Run: func(cmd *cobra.Command, args []string) { + authInfo := common.AuthInfo{ + AuthType: "idp", + Username: username, + Password: password, + DomainName: domainName, + IdpName: idpName, + IdpURL: idpUrl, + AuthProtocol: "oidc", + OverwriteFile: overwriteToken, + Region: region, + } + login.AuthenticateAndGetUnscopedToken(authInfo) + }, +} + +var loginRemoveCmd = &cobra.Command{ + Use: "remove", + Short: loginRemoveCmdHelp, + Long: "Here we can put a longer description of this command", // TODO + Example: "Here comes an example usage of this command", // TODO + PreRunE: configureCmdFlagsAgainstEnvs(loginRemoveFlagToEnv), + Run: func(cmd *cobra.Command, args []string) { + config.RemoveCloudConfig(domainName) + }, +} + +var projectsCmd = &cobra.Command{ + Use: "projects", + Short: projectsCmdHelp, +} + +var projectsListCmd = &cobra.Command{ + Use: "list", + Short: projectsListCmdHelp, + Example: projectsListCmdExample, + Run: func(cmd *cobra.Command, args []string) { + iam.GetProjectsInActiveCloud() + }, +} + +var cceCmd = &cobra.Command{ + Use: "cce", + Short: cceCmdHelp, + PersistentPreRunE: configureCmdFlagsAgainstEnvs(cceListFlagToEnv), +} + +var cceListCmd = &cobra.Command{ + Use: "list", + Short: cceListHelp, + Example: "", // TODO + Run: func(cmd *cobra.Command, args []string) { + config.LoadCloudConfig(domainName) + if !config.IsAuthenticationValid() { + common.OutputErrorMessageToConsoleAndExit("fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + } + cce.GetClusterNames(projectName) + }, +} + +var cceGetKubeConfigCmd = &cobra.Command{ + Use: "get-kube-config", + Short: cceGetKubeConfigHelp, + Example: "", // TODO + PreRunE: configureCmdFlagsAgainstEnvs(cceGetKubeConfigFlagToEnv), + Run: func(cmd *cobra.Command, args []string) { + config.LoadCloudConfig(domainName) + if !config.IsAuthenticationValid() { + common.OutputErrorMessageToConsoleAndExit("fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + } + + daysValidString := strconv.Itoa(daysValid) -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, + if strings.HasPrefix(targetLocation, "~") { + targetLocation = strings.Replace(targetLocation, "~", homedir.HomeDir(), 1) + } + + kubeConfigParams := cce.KubeConfigParams{ + ProjectName: projectName, + ClusterName: clusterName, + DaysValid: daysValidString, + TargetLocation: targetLocation, + } + + cce.GetKubeConfig(kubeConfigParams) + }, } -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the RootCmd. func Execute() { err := RootCmd.Execute() if err != nil { os.Exit(1) } } + +func init() { + RootCmd.AddCommand(loginCmd) + + loginCmd.AddCommand(loginIamCmd) + loginIamCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) + loginIamCmd.MarkFlagRequired(usernameFlag) + loginIamCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) + loginIamCmd.MarkFlagRequired(passwordFlag) + loginIamCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + loginIamCmd.MarkFlagRequired(domainNameFlag) + loginIamCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) + loginIamCmd.Flags().StringVarP(&totp, totpFlag, totpShortFlag, "", totpUsage) + loginIamCmd.Flags().StringVarP(&userDomainId, userDomainIdFlag, "", "", userDomainIdUsage) + loginIamCmd.MarkFlagsRequiredTogether(totpFlag, userDomainIdFlag) + loginIamCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) + loginIamCmd.MarkFlagRequired(regionFlag) + + loginCmd.AddCommand(loginIdpSamlCmd) + loginIdpSamlCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) + loginIdpSamlCmd.MarkFlagRequired(usernameFlag) + loginIdpSamlCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) + loginIdpSamlCmd.MarkFlagRequired(passwordFlag) + loginIdpSamlCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + loginIdpSamlCmd.MarkFlagRequired(domainNameFlag) + loginIdpSamlCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) + loginIdpSamlCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) + loginIdpSamlCmd.MarkPersistentFlagRequired(idpNameFlag) + loginIdpSamlCmd.PersistentFlags().StringVarP(&idpUrl, idpUrlFlag, "", "", idpUrlUsage) + loginIdpSamlCmd.MarkPersistentFlagRequired(idpUrlFlag) + loginIdpSamlCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) + loginIdpSamlCmd.MarkFlagRequired(regionFlag) + + loginCmd.AddCommand(loginIdpOidcCmd) + loginIdpOidcCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) + loginIdpOidcCmd.MarkFlagRequired(usernameFlag) + loginIdpOidcCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) + loginIdpOidcCmd.MarkFlagRequired(passwordFlag) + loginIdpOidcCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + loginIdpOidcCmd.MarkFlagRequired(domainNameFlag) + loginIdpOidcCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) + loginIdpOidcCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) + loginIdpOidcCmd.MarkPersistentFlagRequired(idpNameFlag) + loginIdpOidcCmd.PersistentFlags().StringVarP(&idpUrl, idpUrlFlag, "", "", idpUrlUsage) + loginIdpOidcCmd.MarkPersistentFlagRequired(idpUrlFlag) + loginIdpOidcCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) + loginIdpOidcCmd.MarkFlagRequired(regionFlag) + + loginCmd.AddCommand(loginRemoveCmd) + loginRemoveCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + loginRemoveCmd.MarkFlagRequired(domainNameFlag) + + RootCmd.AddCommand(projectsCmd) + projectsCmd.AddCommand(projectsListCmd) + + RootCmd.AddCommand(cceCmd) + cceCmd.PersistentFlags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + cceCmd.MarkPersistentFlagRequired(domainNameFlag) + cceCmd.PersistentFlags().StringVarP(&projectName, projectNameFlag, projectNameShortFlag, "", projectNameUsage) + cceCmd.MarkPersistentFlagRequired(projectNameFlag) + + cceCmd.AddCommand(cceListCmd) + + cceCmd.AddCommand(cceGetKubeConfigCmd) + cceGetKubeConfigCmd.Flags().StringVarP(&clusterName, clusterNameFlag, clusterNameShortFlag, "", clusterNameUsage) + cceGetKubeConfigCmd.MarkFlagRequired(clusterNameFlag) + cceGetKubeConfigCmd.Flags().IntVarP(&daysValid, daysValidFlag, daysValidShortFlag, 7, daysValidUsage) + cceGetKubeConfigCmd.MarkFlagRequired(daysValidFlag) + cceGetKubeConfigCmd.Flags().StringVarP(&targetLocation, targetLocationFlag, targetLocationShortFlag, "~/.kube/config", targetLocationUsage) + cceGetKubeConfigCmd.MarkFlagRequired(targetLocationFlag) +} + +var ( + username string + password string + domainName string + overwriteToken bool + idpName string + idpUrl string + totp string + userDomainId string + region string + projectName string + clusterName string + daysValid int + targetLocation string + + loginIamFlagToEnv = map[string]string{ + usernameFlag: usernameEnv, + passwordFlag: passwordEnv, + domainNameFlag: domainNameEnv, + userDomainIdFlag: userDomainIdEnv, + idpNameFlag: idpNameEnv, + idpUrlFlag: idpUrlEnv, + regionFlag: regionEnv, + } + + loginIdpSamlOidcFlagToEnv = map[string]string{ + usernameFlag: usernameEnv, + passwordFlag: passwordEnv, + domainNameFlag: domainNameEnv, + userDomainIdFlag: userDomainIdEnv, + idpNameFlag: idpNameEnv, + idpUrlFlag: idpUrlEnv, + regionFlag: regionEnv, + } + + loginRemoveFlagToEnv = map[string]string{ + userDomainIdFlag: userDomainIdEnv, + } + + cceListFlagToEnv = map[string]string{ + projectNameFlag: projectNameEnv, + domainNameFlag: domainNameEnv, + } + + cceGetKubeConfigFlagToEnv = map[string]string{ + clusterNameFlag: clusterNameEnv, + } +) + +const ( + loginCmdHelp = "Login to the Open Telekom Cloud and receive an unscoped token." + loginIamCmdHelp = "Login to the Open Telekom Cloud through its Identity and Access Management system and receive an unscoped token." + loginIamCmdExample = "otc-auth login iam --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" + loginIdpSamlCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and SAML and receive an unscoped token." + loginIdpSamlCmdExample = "otc-auth login idp-saml --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" // TODO: add some more examples here + loginIdpOidcCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and OIDC and receive an unscoped token." + loginIdpOidcCmdExample = "otc-auth login idp-oidc --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" // TODO: add some more examples here + loginRemoveCmdHelp = "Removes login information for a cloud" + projectsCmdHelp = "Manage Project Information" + projectsListCmdHelp = "List Projects in Active Cloud" + projectsListCmdExample = "otc-auth projects list" + cceCmdHelp = "Manage Cloud Container Engine." + cceListHelp = "Lists Project Clusters in CCE." + cceGetKubeConfigHelp = "Get remote kube config and merge it with existing local config file." + usernameFlag = "os-username" + usernameShortFlag = "u" + usernameEnv = "OS_USERNAME" + usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." + passwordFlag = "os-password" + passwordShortFlag = "p" + passwordEnv = "OS_PASSWORD" + passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." + domainNameFlag = "os-domain-name" + domainNameShortFlag = "d" + domainNameEnv = "OS_DOMAIN_NAME" + domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." + overwriteTokenFlag = "overwrite-token" + overwriteTokenShortFlag = "o" + overwriteTokenUsage = "Overrides .otc-info file." + idpNameFlag = "idp-name" + idpNameShortFlag = "i" + idpNameEnv = "IDP_NAME" + idpNameUsage = "Required for authentication with IdP." + idpUrlFlag = "idp-url" + idpUrlEnv = "IDP_URL" + idpUrlUsage = "Required for authentication with IdP." + totpFlag = "totp" + totpShortFlag = "t" + totpUsage = "6-digit time-based one-time password (TOTP) used for the MFA login flow. Required together with the user-domain-id." + userDomainIdFlag = "os-user-domain-id" + userDomainIdEnv = "OS_USER_DOMAIN_ID" + userDomainIdUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIdEnv + "." + regionFlag = "region" + regionShortFlag = "r" + regionEnv = "REGION" + regionUsage = "OTC region code. Either provide this argument or set the environment variable " + regionEnv + "." // TODO: fill out the region + projectNameFlag = "os-project-name" + projectNameShortFlag = "p" + projectNameEnv = "OS_PROJECT_NAME" + projectNameUsage = "Name of the project you want to access. Either provide this argument or set the environment variable " + projectNameEnv + "." + clusterNameFlag = "cluster" + clusterNameShortFlag = "c" + clusterNameEnv = "CLUSTER_NAME" + clusterNameUsage = "Name of the clusterArg you want to access. Either provide this argument or set the environment variable " + clusterNameEnv + "." + daysValidFlag = "days-valid" + daysValidShortFlag = "v" + daysValidUsage = "Period (in days) that the config will be valid." + targetLocationFlag = "target-location" + targetLocationShortFlag = "l" + targetLocationUsage = "Where the kube config should be saved" +) From 58dc5c44241bc452c93cfe4382c0ead7212e2db3 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 5 Jul 2023 14:26:53 +0200 Subject: [PATCH 05/16] Adding accesstoken subcommands --- cmd/root.go | 249 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 176 insertions(+), 73 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index a8ddc075..7be40245 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -18,7 +18,9 @@ package cmd import ( "k8s.io/client-go/util/homedir" + "log" "os" + "otc-auth/accesstoken" "otc-auth/cce" "otc-auth/common" "otc-auth/config" @@ -175,6 +177,77 @@ var cceGetKubeConfigCmd = &cobra.Command{ }, } +var accessTokenCmd = &cobra.Command{ + Use: "access-token", + Short: accessTokenCmdHelp, + PersistentPreRunE: configureCmdFlagsAgainstEnvs(accessTokenFlagToEnv), +} + +var accessTokenCreateCmd = &cobra.Command{ + Use: "create", + Short: accessTokenCreateCmdHelp, + Run: func(cmd *cobra.Command, args []string) { + config.LoadCloudConfig(domainName) + if !config.IsAuthenticationValid() { + common.OutputErrorMessageToConsoleAndExit( + "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + } + + accesstoken.CreateAccessToken(accessTokenCreateDescription) + }, +} + +var accessTokenListCmd = &cobra.Command{ + Use: "list", + Short: accessTokenListCmdHelp, + Run: func(cmd *cobra.Command, args []string) { + config.LoadCloudConfig(domainName) + if !config.IsAuthenticationValid() { + common.OutputErrorMessageToConsoleAndExit( + "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + } + + accessTokens, err2 := accesstoken.ListAccessToken() + if err2 != nil { + common.OutputErrorToConsoleAndExit(err2) + } + if len(accessTokens) > 0 { + log.Println("\nAccess Tokens:") + for _, aT := range accessTokens { + log.Printf("\nToken: \t\t%s\n"+ + "Description: \t%s\n"+ + "Created by: \t%s\n"+ + "Last Used: \t%s\n"+ + "Active: \t%s\n \n", + aT.AccessKey, aT.Description, aT.UserID, aT.LastUseTime, aT.Status) + } + } else { + log.Println("No access-tokens found") + } + }, +} + +var accessTokenDeleteCmd = &cobra.Command{ + Use: "delete", + Short: accessTokenDeleteCmdHelp, + Run: func(cmd *cobra.Command, args []string) { + config.LoadCloudConfig(domainName) + + if !config.IsAuthenticationValid() { + common.OutputErrorMessageToConsoleAndExit( + "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + } + + if token == "" { + common.OutputErrorMessageToConsoleAndExit("fatal: argument token cannot be empty.") + } + errDelete := accesstoken.DeleteAccessToken(token) + if errDelete != nil { + common.OutputErrorToConsoleAndExit(errDelete) + } + }, +} + func Execute() { err := RootCmd.Execute() if err != nil { @@ -251,22 +324,38 @@ func init() { cceGetKubeConfigCmd.MarkFlagRequired(daysValidFlag) cceGetKubeConfigCmd.Flags().StringVarP(&targetLocation, targetLocationFlag, targetLocationShortFlag, "~/.kube/config", targetLocationUsage) cceGetKubeConfigCmd.MarkFlagRequired(targetLocationFlag) + + RootCmd.AddCommand(accessTokenCmd) + accessTokenCmd.PersistentFlags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) + accessTokenCmd.MarkPersistentFlagRequired(domainNameFlag) + + accessTokenCmd.AddCommand(accessTokenCreateCmd) + accessTokenCreateCmd.Flags().StringVarP(&accessTokenCreateDescription, accessTokenDescriptionFlag, accessTokenDescriptionShortFlag, "Token by otc-auth", accessTokenDescriptionUsage) + accessTokenCreateCmd.MarkFlagRequired(accessTokenDescriptionFlag) + + accessTokenCmd.AddCommand(accessTokenListCmd) + + accessTokenCmd.AddCommand(accessTokenDeleteCmd) + accessTokenDeleteCmd.Flags().StringVarP(&token, accessTokenTokenFlag, accessTokenTokenShortFlag, "", accessTokenTokenUsage) + accessTokenDeleteCmd.MarkFlagRequired(accessTokenTokenFlag) } var ( - username string - password string - domainName string - overwriteToken bool - idpName string - idpUrl string - totp string - userDomainId string - region string - projectName string - clusterName string - daysValid int - targetLocation string + username string + password string + domainName string + overwriteToken bool + idpName string + idpUrl string + totp string + userDomainId string + region string + projectName string + clusterName string + daysValid int + targetLocation string + accessTokenCreateDescription string + token string loginIamFlagToEnv = map[string]string{ usernameFlag: usernameEnv, @@ -300,67 +389,81 @@ var ( cceGetKubeConfigFlagToEnv = map[string]string{ clusterNameFlag: clusterNameEnv, } + + accessTokenFlagToEnv = map[string]string{ + domainNameFlag: domainNameEnv, + } ) const ( - loginCmdHelp = "Login to the Open Telekom Cloud and receive an unscoped token." - loginIamCmdHelp = "Login to the Open Telekom Cloud through its Identity and Access Management system and receive an unscoped token." - loginIamCmdExample = "otc-auth login iam --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" - loginIdpSamlCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and SAML and receive an unscoped token." - loginIdpSamlCmdExample = "otc-auth login idp-saml --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" // TODO: add some more examples here - loginIdpOidcCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and OIDC and receive an unscoped token." - loginIdpOidcCmdExample = "otc-auth login idp-oidc --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" // TODO: add some more examples here - loginRemoveCmdHelp = "Removes login information for a cloud" - projectsCmdHelp = "Manage Project Information" - projectsListCmdHelp = "List Projects in Active Cloud" - projectsListCmdExample = "otc-auth projects list" - cceCmdHelp = "Manage Cloud Container Engine." - cceListHelp = "Lists Project Clusters in CCE." - cceGetKubeConfigHelp = "Get remote kube config and merge it with existing local config file." - usernameFlag = "os-username" - usernameShortFlag = "u" - usernameEnv = "OS_USERNAME" - usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." - passwordFlag = "os-password" - passwordShortFlag = "p" - passwordEnv = "OS_PASSWORD" - passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." - domainNameFlag = "os-domain-name" - domainNameShortFlag = "d" - domainNameEnv = "OS_DOMAIN_NAME" - domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." - overwriteTokenFlag = "overwrite-token" - overwriteTokenShortFlag = "o" - overwriteTokenUsage = "Overrides .otc-info file." - idpNameFlag = "idp-name" - idpNameShortFlag = "i" - idpNameEnv = "IDP_NAME" - idpNameUsage = "Required for authentication with IdP." - idpUrlFlag = "idp-url" - idpUrlEnv = "IDP_URL" - idpUrlUsage = "Required for authentication with IdP." - totpFlag = "totp" - totpShortFlag = "t" - totpUsage = "6-digit time-based one-time password (TOTP) used for the MFA login flow. Required together with the user-domain-id." - userDomainIdFlag = "os-user-domain-id" - userDomainIdEnv = "OS_USER_DOMAIN_ID" - userDomainIdUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIdEnv + "." - regionFlag = "region" - regionShortFlag = "r" - regionEnv = "REGION" - regionUsage = "OTC region code. Either provide this argument or set the environment variable " + regionEnv + "." // TODO: fill out the region - projectNameFlag = "os-project-name" - projectNameShortFlag = "p" - projectNameEnv = "OS_PROJECT_NAME" - projectNameUsage = "Name of the project you want to access. Either provide this argument or set the environment variable " + projectNameEnv + "." - clusterNameFlag = "cluster" - clusterNameShortFlag = "c" - clusterNameEnv = "CLUSTER_NAME" - clusterNameUsage = "Name of the clusterArg you want to access. Either provide this argument or set the environment variable " + clusterNameEnv + "." - daysValidFlag = "days-valid" - daysValidShortFlag = "v" - daysValidUsage = "Period (in days) that the config will be valid." - targetLocationFlag = "target-location" - targetLocationShortFlag = "l" - targetLocationUsage = "Where the kube config should be saved" + loginCmdHelp = "Login to the Open Telekom Cloud and receive an unscoped token." + loginIamCmdHelp = "Login to the Open Telekom Cloud through its Identity and Access Management system and receive an unscoped token." + loginIamCmdExample = "otc-auth login iam --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" + loginIdpSamlCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and SAML and receive an unscoped token." + loginIdpSamlCmdExample = "otc-auth login idp-saml --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" // TODO: add some more examples here + loginIdpOidcCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and OIDC and receive an unscoped token." + loginIdpOidcCmdExample = "otc-auth login idp-oidc --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" // TODO: add some more examples here + loginRemoveCmdHelp = "Removes login information for a cloud" + projectsCmdHelp = "Manage Project Information" + projectsListCmdHelp = "List Projects in Active Cloud" + projectsListCmdExample = "otc-auth projects list" + cceCmdHelp = "Manage Cloud Container Engine." + cceListHelp = "Lists Project Clusters in CCE." + cceGetKubeConfigHelp = "Get remote kube config and merge it with existing local config file." + accessTokenCmdHelp = "Manage AK/SK." + accessTokenCreateCmdHelp = "Create new AK/SK." + accessTokenListCmdHelp = "List existing AK/SKs." + accessTokenDeleteCmdHelp = "Delete existing AK/SKs." + usernameFlag = "os-username" + usernameShortFlag = "u" + usernameEnv = "OS_USERNAME" + usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." + passwordFlag = "os-password" + passwordShortFlag = "p" + passwordEnv = "OS_PASSWORD" + passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." + domainNameFlag = "os-domain-name" + domainNameShortFlag = "d" + domainNameEnv = "OS_DOMAIN_NAME" + domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." + overwriteTokenFlag = "overwrite-token" + overwriteTokenShortFlag = "o" + overwriteTokenUsage = "Overrides .otc-info file." + idpNameFlag = "idp-name" + idpNameShortFlag = "i" + idpNameEnv = "IDP_NAME" + idpNameUsage = "Required for authentication with IdP." + idpUrlFlag = "idp-url" + idpUrlEnv = "IDP_URL" + idpUrlUsage = "Required for authentication with IdP." + totpFlag = "totp" + totpShortFlag = "t" + totpUsage = "6-digit time-based one-time password (TOTP) used for the MFA login flow. Required together with the user-domain-id." + userDomainIdFlag = "os-user-domain-id" + userDomainIdEnv = "OS_USER_DOMAIN_ID" + userDomainIdUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIdEnv + "." + regionFlag = "region" + regionShortFlag = "r" + regionEnv = "REGION" + regionUsage = "OTC region code. Either provide this argument or set the environment variable " + regionEnv + "." // TODO: fill out the region + projectNameFlag = "os-project-name" + projectNameShortFlag = "p" + projectNameEnv = "OS_PROJECT_NAME" + projectNameUsage = "Name of the project you want to access. Either provide this argument or set the environment variable " + projectNameEnv + "." + clusterNameFlag = "cluster" + clusterNameShortFlag = "c" + clusterNameEnv = "CLUSTER_NAME" + clusterNameUsage = "Name of the clusterArg you want to access. Either provide this argument or set the environment variable " + clusterNameEnv + "." + daysValidFlag = "days-valid" + daysValidShortFlag = "v" + daysValidUsage = "Period (in days) that the config will be valid." + targetLocationFlag = "target-location" + targetLocationShortFlag = "l" + targetLocationUsage = "Where the kube config should be saved" + accessTokenDescriptionFlag = "description" + accessTokenDescriptionShortFlag = "s" + accessTokenDescriptionUsage = "Description of the token" + accessTokenTokenFlag = "token" + accessTokenTokenShortFlag = "t" + accessTokenTokenUsage = "The AK/SK token to delete." ) From 2830fc954cb98780999cf9320286921c1c973bb4 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 5 Jul 2023 16:37:21 +0200 Subject: [PATCH 06/16] Completed transition to cobra Includes auto-completion generation Includes documentation generation --- cmd/cmd_config.go | 1 + cmd/completion.go | 91 ++++++++++ cmd/documentation.go | 40 +++++ cmd/root.go | 311 +++++++++++++++++++++++--------- cmd/version.go | 1 + format_and_lint.sh | 17 +- go.mod | 53 +++--- go.sum | 65 ++++++- login/argument_verifier.go | 22 --- login/login.go | 5 + main.go | 2 +- oldmain.go | 351 ------------------------------------- 12 files changed, 472 insertions(+), 487 deletions(-) create mode 100644 cmd/completion.go create mode 100644 cmd/documentation.go delete mode 100644 login/argument_verifier.go delete mode 100644 oldmain.go diff --git a/cmd/cmd_config.go b/cmd/cmd_config.go index b423d4fa..b5ccabf4 100644 --- a/cmd/cmd_config.go +++ b/cmd/cmd_config.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" diff --git a/cmd/completion.go b/cmd/completion.go new file mode 100644 index 00000000..313c9829 --- /dev/null +++ b/cmd/completion.go @@ -0,0 +1,91 @@ +/* +Copyright © 2023 IITS-Consulting + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +//nolint:gochecknoglobals // commands as globals is the cleanest and easiest way to create (sub)commands +var completionCmd = &cobra.Command{ + Use: "completion [bash|zsh|fish|powershell]", + Short: "Generate completion script", + Long: fmt.Sprintf(`To load completions: + +Bash: + + $ source <(%[1]s completion bash) + + # To load completions for each session, execute once: + # Linux: + $ %[1]s completion bash > /etc/bash_completion.d/%[1]s + # macOS: + $ %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s + +Zsh: + + # If shell completion is not already enabled in your environment, + # you will need to enable it. You can execute the following once: + + $ echo "autoload -U compinit; compinit" >> ~/.zshrc + + # To load completions for each session, execute once: + $ %[1]s completion zsh > "${fpath[1]}/_%[1]s" + + # You will need to start a new shell for this setup to take effect. + +fish: + + $ %[1]s completion fish | source + + # To load completions for each session, execute once: + $ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish + +PowerShell: + + PS> %[1]s completion powershell | Out-String | Invoke-Expression + + # To load completions for every new session, run: + PS> %[1]s completion powershell > %[1]s.ps1 + # and source this file from your PowerShell profile. +`, RootCmd.Name()), + DisableFlagsInUseLine: true, + ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, + Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), + RunE: func(cmd *cobra.Command, args []string) error { + var err error + switch args[0] { + case "bash": + err = cmd.Root().GenBashCompletion(os.Stdout) + case "zsh": + err = cmd.Root().GenZshCompletion(os.Stdout) + case "fish": + err = cmd.Root().GenFishCompletion(os.Stdout, true) + case "powershell": + err = cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) + } + return err + }, +} + +//nolint:gochecknoinits // autogenerated and recommended by spf13/cobra +func init() { + RootCmd.AddCommand(completionCmd) +} diff --git a/cmd/documentation.go b/cmd/documentation.go new file mode 100644 index 00000000..2e08ebde --- /dev/null +++ b/cmd/documentation.go @@ -0,0 +1,40 @@ +/* +Copyright © 2023 IITS-Consulting + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +package cmd + +import ( + "log" + + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +//nolint:gochecknoglobals // autogenerated and recommended by spf13/cobra +var documentationCmd = &cobra.Command{ + Use: "documentation", + Short: "Generates markdown documentation", + RunE: func(cmd *cobra.Command, args []string) error { + err := doc.GenMarkdownTree(cmd.Root(), "./generated-docs/") + log.Println("documentation generated") + return err + }, +} + +//nolint:gochecknoinits // autogenerated and recommended by spf13/cobra +func init() { + RootCmd.AddCommand(documentationCmd) +} diff --git a/cmd/root.go b/cmd/root.go index 7be40245..e0fc5446 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -14,25 +14,27 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ +//nolint:gochecknoglobals // Globals are used to make the parsing and reuseability of the cmd functionality easier package cmd import ( - "k8s.io/client-go/util/homedir" "log" "os" + "strconv" + "strings" + "otc-auth/accesstoken" "otc-auth/cce" "otc-auth/common" "otc-auth/config" "otc-auth/iam" "otc-auth/login" - "strconv" - "strings" + "otc-auth/openstack" "github.com/spf13/cobra" + "k8s.io/client-go/util/homedir" ) -// RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ Use: "otc-auth", Short: "OTC-Auth Command Line Interface for managing OTC clouds", @@ -55,7 +57,7 @@ var loginIamCmd = &cobra.Command{ Password: password, DomainName: domainName, Otp: totp, - UserDomainID: userDomainId, + UserDomainID: userDomainID, OverwriteFile: overwriteToken, Region: region, } @@ -75,7 +77,7 @@ var loginIdpSamlCmd = &cobra.Command{ Password: password, DomainName: domainName, IdpName: idpName, - IdpURL: idpUrl, + IdpURL: idpURL, AuthProtocol: "saml", OverwriteFile: overwriteToken, Region: region, @@ -96,7 +98,7 @@ var loginIdpOidcCmd = &cobra.Command{ Password: password, DomainName: domainName, IdpName: idpName, - IdpURL: idpUrl, + IdpURL: idpURL, AuthProtocol: "oidc", OverwriteFile: overwriteToken, Region: region, @@ -108,8 +110,7 @@ var loginIdpOidcCmd = &cobra.Command{ var loginRemoveCmd = &cobra.Command{ Use: "remove", Short: loginRemoveCmdHelp, - Long: "Here we can put a longer description of this command", // TODO - Example: "Here comes an example usage of this command", // TODO + Example: loginRemoveCmdExample, PreRunE: configureCmdFlagsAgainstEnvs(loginRemoveFlagToEnv), Run: func(cmd *cobra.Command, args []string) { config.RemoveCloudConfig(domainName) @@ -138,12 +139,14 @@ var cceCmd = &cobra.Command{ var cceListCmd = &cobra.Command{ Use: "list", - Short: cceListHelp, - Example: "", // TODO + Short: cceListCmdHelp, + Example: cceListCmdExample, Run: func(cmd *cobra.Command, args []string) { config.LoadCloudConfig(domainName) if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit("fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + common.OutputErrorMessageToConsoleAndExit( + "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.", + ) } cce.GetClusterNames(projectName) }, @@ -151,13 +154,15 @@ var cceListCmd = &cobra.Command{ var cceGetKubeConfigCmd = &cobra.Command{ Use: "get-kube-config", - Short: cceGetKubeConfigHelp, - Example: "", // TODO + Short: cceGetKubeConfigCmdHelp, + Example: cceGetKubeConfigCmdExample, PreRunE: configureCmdFlagsAgainstEnvs(cceGetKubeConfigFlagToEnv), Run: func(cmd *cobra.Command, args []string) { config.LoadCloudConfig(domainName) if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit("fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + common.OutputErrorMessageToConsoleAndExit( + "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.", + ) } daysValidString := strconv.Itoa(daysValid) @@ -184,8 +189,9 @@ var accessTokenCmd = &cobra.Command{ } var accessTokenCreateCmd = &cobra.Command{ - Use: "create", - Short: accessTokenCreateCmdHelp, + Use: "create", + Short: accessTokenCreateCmdHelp, + Example: accessTokenCreateCmdExample, Run: func(cmd *cobra.Command, args []string) { config.LoadCloudConfig(domainName) if !config.IsAuthenticationValid() { @@ -228,8 +234,9 @@ var accessTokenListCmd = &cobra.Command{ } var accessTokenDeleteCmd = &cobra.Command{ - Use: "delete", - Short: accessTokenDeleteCmdHelp, + Use: "delete", + Short: accessTokenDeleteCmdHelp, + Example: accessTokenDeleteCmdExample, Run: func(cmd *cobra.Command, args []string) { config.LoadCloudConfig(domainName) @@ -248,14 +255,32 @@ var accessTokenDeleteCmd = &cobra.Command{ }, } +var openstackCmd = &cobra.Command{ + Use: "openstack", + Short: openstackCmdHelp, +} + +var openstackConfigCreateCmd = &cobra.Command{ + Use: "config-create", + Short: openstackConfigCreateCmdHelp, + Run: func(cmd *cobra.Command, args []string) { + if strings.HasPrefix(openStackConfigLocation, "~") { + openStackConfigLocation = strings.Replace(openStackConfigLocation, "~", homedir.HomeDir(), 1) + } + openstack.WriteOpenStackCloudsYaml(openStackConfigLocation) + }, +} + func Execute() { + setupRootCmd() err := RootCmd.Execute() if err != nil { os.Exit(1) } } -func init() { +//nolint:errcheck,funlen // error never occurs, setup has to be that lengthy +func setupRootCmd() { RootCmd.AddCommand(loginCmd) loginCmd.AddCommand(loginIamCmd) @@ -267,8 +292,8 @@ func init() { loginIamCmd.MarkFlagRequired(domainNameFlag) loginIamCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) loginIamCmd.Flags().StringVarP(&totp, totpFlag, totpShortFlag, "", totpUsage) - loginIamCmd.Flags().StringVarP(&userDomainId, userDomainIdFlag, "", "", userDomainIdUsage) - loginIamCmd.MarkFlagsRequiredTogether(totpFlag, userDomainIdFlag) + loginIamCmd.Flags().StringVarP(&userDomainID, userDomainIDFlag, "", "", userDomainIDUsage) + loginIamCmd.MarkFlagsRequiredTogether(totpFlag, userDomainIDFlag) loginIamCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) loginIamCmd.MarkFlagRequired(regionFlag) @@ -279,11 +304,17 @@ func init() { loginIdpSamlCmd.MarkFlagRequired(passwordFlag) loginIdpSamlCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) loginIdpSamlCmd.MarkFlagRequired(domainNameFlag) - loginIdpSamlCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) + loginIdpSamlCmd.Flags().BoolVarP( + &overwriteToken, + overwriteTokenFlag, + overwriteTokenShortFlag, + false, + overwriteTokenUsage, + ) loginIdpSamlCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) loginIdpSamlCmd.MarkPersistentFlagRequired(idpNameFlag) - loginIdpSamlCmd.PersistentFlags().StringVarP(&idpUrl, idpUrlFlag, "", "", idpUrlUsage) - loginIdpSamlCmd.MarkPersistentFlagRequired(idpUrlFlag) + loginIdpSamlCmd.PersistentFlags().StringVarP(&idpURL, idpURLFlag, "", "", idpURLUsage) + loginIdpSamlCmd.MarkPersistentFlagRequired(idpURLFlag) loginIdpSamlCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) loginIdpSamlCmd.MarkFlagRequired(regionFlag) @@ -294,11 +325,17 @@ func init() { loginIdpOidcCmd.MarkFlagRequired(passwordFlag) loginIdpOidcCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) loginIdpOidcCmd.MarkFlagRequired(domainNameFlag) - loginIdpOidcCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) + loginIdpOidcCmd.Flags().BoolVarP( + &overwriteToken, + overwriteTokenFlag, + overwriteTokenShortFlag, + false, + overwriteTokenUsage, + ) loginIdpOidcCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) loginIdpOidcCmd.MarkPersistentFlagRequired(idpNameFlag) - loginIdpOidcCmd.PersistentFlags().StringVarP(&idpUrl, idpUrlFlag, "", "", idpUrlUsage) - loginIdpOidcCmd.MarkPersistentFlagRequired(idpUrlFlag) + loginIdpOidcCmd.PersistentFlags().StringVarP(&idpURL, idpURLFlag, "", "", idpURLUsage) + loginIdpOidcCmd.MarkPersistentFlagRequired(idpURLFlag) loginIdpOidcCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) loginIdpOidcCmd.MarkFlagRequired(regionFlag) @@ -320,9 +357,21 @@ func init() { cceCmd.AddCommand(cceGetKubeConfigCmd) cceGetKubeConfigCmd.Flags().StringVarP(&clusterName, clusterNameFlag, clusterNameShortFlag, "", clusterNameUsage) cceGetKubeConfigCmd.MarkFlagRequired(clusterNameFlag) - cceGetKubeConfigCmd.Flags().IntVarP(&daysValid, daysValidFlag, daysValidShortFlag, 7, daysValidUsage) + cceGetKubeConfigCmd.Flags().IntVarP( + &daysValid, + daysValidFlag, + daysValidShortFlag, + daysValidDefaultValue, + daysValidUsage, + ) cceGetKubeConfigCmd.MarkFlagRequired(daysValidFlag) - cceGetKubeConfigCmd.Flags().StringVarP(&targetLocation, targetLocationFlag, targetLocationShortFlag, "~/.kube/config", targetLocationUsage) + cceGetKubeConfigCmd.Flags().StringVarP( + &targetLocation, + targetLocationFlag, + targetLocationShortFlag, + "~/.kube/config", + targetLocationUsage, + ) cceGetKubeConfigCmd.MarkFlagRequired(targetLocationFlag) RootCmd.AddCommand(accessTokenCmd) @@ -330,14 +379,36 @@ func init() { accessTokenCmd.MarkPersistentFlagRequired(domainNameFlag) accessTokenCmd.AddCommand(accessTokenCreateCmd) - accessTokenCreateCmd.Flags().StringVarP(&accessTokenCreateDescription, accessTokenDescriptionFlag, accessTokenDescriptionShortFlag, "Token by otc-auth", accessTokenDescriptionUsage) + accessTokenCreateCmd.Flags().StringVarP( + &accessTokenCreateDescription, + accessTokenDescriptionFlag, + accessTokenDescriptionShortFlag, + "Token by otc-auth", + accessTokenDescriptionUsage, + ) accessTokenCreateCmd.MarkFlagRequired(accessTokenDescriptionFlag) accessTokenCmd.AddCommand(accessTokenListCmd) accessTokenCmd.AddCommand(accessTokenDeleteCmd) - accessTokenDeleteCmd.Flags().StringVarP(&token, accessTokenTokenFlag, accessTokenTokenShortFlag, "", accessTokenTokenUsage) + accessTokenDeleteCmd.Flags().StringVarP( + &token, + accessTokenTokenFlag, + accessTokenTokenShortFlag, + "", + accessTokenTokenUsage, + ) accessTokenDeleteCmd.MarkFlagRequired(accessTokenTokenFlag) + + RootCmd.AddCommand(openstackCmd) + openstackCmd.AddCommand(openstackConfigCreateCmd) + openstackConfigCreateCmd.Flags().StringVarP( + &openStackConfigLocation, + openstackConfigCreateConfigLocationFlag, + openstackConfigCreateConfigLocationShortFlag, + "~/.config/openstack/clouds.yaml", + openstackConfigCreateConfigLocationUsage, + ) } var ( @@ -346,9 +417,9 @@ var ( domainName string overwriteToken bool idpName string - idpUrl string + idpURL string totp string - userDomainId string + userDomainID string region string projectName string clusterName string @@ -356,14 +427,15 @@ var ( targetLocation string accessTokenCreateDescription string token string + openStackConfigLocation string loginIamFlagToEnv = map[string]string{ usernameFlag: usernameEnv, passwordFlag: passwordEnv, domainNameFlag: domainNameEnv, - userDomainIdFlag: userDomainIdEnv, + userDomainIDFlag: userDomainIDEnv, idpNameFlag: idpNameEnv, - idpUrlFlag: idpUrlEnv, + idpURLFlag: idpURLEnv, regionFlag: regionEnv, } @@ -371,14 +443,14 @@ var ( usernameFlag: usernameEnv, passwordFlag: passwordEnv, domainNameFlag: domainNameEnv, - userDomainIdFlag: userDomainIdEnv, + userDomainIDFlag: userDomainIDEnv, idpNameFlag: idpNameEnv, - idpUrlFlag: idpUrlEnv, + idpURLFlag: idpURLEnv, regionFlag: regionEnv, } loginRemoveFlagToEnv = map[string]string{ - userDomainIdFlag: userDomainIdEnv, + userDomainIDFlag: userDomainIDEnv, } cceListFlagToEnv = map[string]string{ @@ -395,57 +467,133 @@ var ( } ) +//nolint:lll // The long lines represent const ( - loginCmdHelp = "Login to the Open Telekom Cloud and receive an unscoped token." - loginIamCmdHelp = "Login to the Open Telekom Cloud through its Identity and Access Management system and receive an unscoped token." - loginIamCmdExample = "otc-auth login iam --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" - loginIdpSamlCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and SAML and receive an unscoped token." - loginIdpSamlCmdExample = "otc-auth login idp-saml --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" // TODO: add some more examples here - loginIdpOidcCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and OIDC and receive an unscoped token." - loginIdpOidcCmdExample = "otc-auth login idp-oidc --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName" // TODO: add some more examples here - loginRemoveCmdHelp = "Removes login information for a cloud" - projectsCmdHelp = "Manage Project Information" - projectsListCmdHelp = "List Projects in Active Cloud" - projectsListCmdExample = "otc-auth projects list" - cceCmdHelp = "Manage Cloud Container Engine." - cceListHelp = "Lists Project Clusters in CCE." - cceGetKubeConfigHelp = "Get remote kube config and merge it with existing local config file." - accessTokenCmdHelp = "Manage AK/SK." - accessTokenCreateCmdHelp = "Create new AK/SK." - accessTokenListCmdHelp = "List existing AK/SKs." - accessTokenDeleteCmdHelp = "Delete existing AK/SKs." - usernameFlag = "os-username" - usernameShortFlag = "u" - usernameEnv = "OS_USERNAME" - usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." - passwordFlag = "os-password" - passwordShortFlag = "p" - passwordEnv = "OS_PASSWORD" - passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." - domainNameFlag = "os-domain-name" - domainNameShortFlag = "d" - domainNameEnv = "OS_DOMAIN_NAME" - domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." - overwriteTokenFlag = "overwrite-token" - overwriteTokenShortFlag = "o" + loginCmdHelp = "Login to the Open Telekom Cloud and receive an unscoped token." + loginIamCmdHelp = "Login to the Open Telekom Cloud through its Identity and Access Management system and receive an unscoped token." + loginIamCmdExample = `$ otc-auth login iam --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName + +$ export OS_USERNAME=YourUsername +$ export OS_PASSWORD=YourPassword +$ export OS_DOMAIN_NAME=YourDomainName +$ otc-auth login iam + +$ export OS_USERNAME=YourUsername +$ export OS_PASSWORD=YourPassword +$ export OS_DOMAIN_NAME=YourDomainName +$ export REGION=YourRegion +$ otc-auth login iam --overwrite-token --region YourRegion` + loginIdpSamlCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and SAML and receive an unscoped token." + loginIdpSamlCmdExample = `otc-auth login idp-saml --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName + +export OS_DOMAIN_NAME=MyDomain +export OS_USERNAME=MyUsername +export OS_PASSWORD=MyPassword +export REGION=MyRegion +otc-auth login idp-saml --idp-name MyIdP --idp-url https://example.com/saml + +export OS_DOMAIN_NAME=MyDomain +export OS_PASSWORD=MyPassword +otc-auth login idp-saml --idp-name MyIdP --idp-url https://example.com/saml --os-username MyUsername --region MyRegion` + loginIdpOidcCmdHelp = "Login to the Open Telekom Cloud through an Identity Provider and OIDC and receive an unscoped token." + loginIdpOidcCmdExample = `otc-auth login idp-oidc --os-username YourUsername --os-password YourPassword --os-domain-name YourDomainName + +export OS_DOMAIN_NAME=MyDomain +export OS_USERNAME=MyUsername +export OS_PASSWORD=MyPassword +export REGION=MyRegion +otc-auth login idp-oidc --idp-name MyIdP --idp-url https://example.com/oidc + +export OS_DOMAIN_NAME=MyDomain +export OS_PASSWORD=MyPassword +otc-auth login idp-oidc --idp-name MyIdP --idp-url https://example.com/oidc --os-username MyUsername --region MyRegion` + loginRemoveCmdHelp = "Removes login information for a cloud" + loginRemoveCmdExample = `$ otc-auth login remove --os-domain-name MyLogin + +$ export OS_DOMAIN_NAME=MyLogin +$ otc-auth login remove` + projectsCmdHelp = "Manage Project Information" + projectsListCmdHelp = "List Projects in Active Cloud" + projectsListCmdExample = "otc-auth projects list" + cceCmdHelp = "Manage Cloud Container Engine." + cceListCmdHelp = "Lists Project Clusters in CCE." + cceListCmdExample = `$ otc-auth cce list --os-project-name MyProject + +$ export OS_DOMAIN_NAME=MyDomain +$ export OS_PROJECT_NAME=MyProject +$ otc-auth cce list + +$ export OS_PROJECT_NAME=MyProject +$ otc-auth cce list` + cceGetKubeConfigCmdHelp = "Get remote kube config and merge it with existing local config file." + cceGetKubeConfigCmdExample = `$ otc-auth cce get-kube-config --cluster MyCluster --target-location /path/to/config + +$ export CLUSTER_NAME=MyCluster +$ export OS_DOMAIN_NAME=MyDomain +$ export OS_PROJECT_NAME=MyProject +$ otc-auth cce get-kube-config --days-valid 14 + +$ export CLUSTER_NAME=MyCluster +$ export OS_DOMAIN_NAME=MyDomain +$ export OS_PROJECT_NAME=MyProject +$ otc-auth cce get-kube-config` + + //nolint:gosec // This is not a hardcoded credential but a help message containing ak/sk + accessTokenCmdHelp = "Manage AK/SK." + //nolint:gosec // This is not a hardcoded credential but a help message containing ak/sk + accessTokenCreateCmdHelp = "Create new AK/SK." + + //nolint:gosec // This is not a hardcoded credential but a help message containing ak/sk + accessTokenCreateCmdExample = `$ otc-auth access-token create --description "Custom token description" + +$ otc-auth access-token create + +$ export OS_DOMAIN_NAME=MyDomain +$ otc-auth access-token create` + accessTokenListCmdHelp = "List existing AK/SKs." + accessTokenDeleteCmdHelp = "Delete existing AK/SKs." + accessTokenDeleteCmdExample = `$ otc-auth access-token delete --token YourToken + +$ export OS_DOMAIN_NAME=YourDomain +$ export AK_SK_TOKEN=YourToken +$ otc-auth access-token delete + +$ otc-auth access-token delete --token YourToken --os-domain-name YourDomain` + openstackCmdHelp = "Manage Openstack Integration" + openstackConfigCreateCmdHelp = "Creates new clouds.yaml" + usernameFlag = "os-username" + usernameShortFlag = "u" + usernameEnv = "OS_USERNAME" + usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." + passwordFlag = "os-password" + passwordShortFlag = "p" + passwordEnv = "OS_PASSWORD" + passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." + domainNameFlag = "os-domain-name" + domainNameShortFlag = "d" + domainNameEnv = "OS_DOMAIN_NAME" + domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." + overwriteTokenFlag = "overwrite-token" + overwriteTokenShortFlag = "o" + //nolint:gosec // This is not a hardcoded credential but a help message with a filename inside overwriteTokenUsage = "Overrides .otc-info file." idpNameFlag = "idp-name" idpNameShortFlag = "i" idpNameEnv = "IDP_NAME" idpNameUsage = "Required for authentication with IdP." - idpUrlFlag = "idp-url" - idpUrlEnv = "IDP_URL" - idpUrlUsage = "Required for authentication with IdP." + idpURLFlag = "idp-url" + idpURLEnv = "IDP_URL" + idpURLUsage = "Required for authentication with IdP." totpFlag = "totp" totpShortFlag = "t" totpUsage = "6-digit time-based one-time password (TOTP) used for the MFA login flow. Required together with the user-domain-id." - userDomainIdFlag = "os-user-domain-id" - userDomainIdEnv = "OS_USER_DOMAIN_ID" - userDomainIdUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIdEnv + "." + userDomainIDFlag = "os-user-domain-id" + userDomainIDEnv = "OS_USER_DOMAIN_ID" + userDomainIDUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIDEnv + "." regionFlag = "region" regionShortFlag = "r" regionEnv = "REGION" - regionUsage = "OTC region code. Either provide this argument or set the environment variable " + regionEnv + "." // TODO: fill out the region + regionUsage = "OTC region code. Either provide this argument or set the environment variable " + regionEnv + "." projectNameFlag = "os-project-name" projectNameShortFlag = "p" projectNameEnv = "OS_PROJECT_NAME" @@ -455,6 +603,7 @@ const ( clusterNameEnv = "CLUSTER_NAME" clusterNameUsage = "Name of the clusterArg you want to access. Either provide this argument or set the environment variable " + clusterNameEnv + "." daysValidFlag = "days-valid" + daysValidDefaultValue = 7 daysValidShortFlag = "v" daysValidUsage = "Period (in days) that the config will be valid." targetLocationFlag = "target-location" @@ -465,5 +614,9 @@ const ( accessTokenDescriptionUsage = "Description of the token" accessTokenTokenFlag = "token" accessTokenTokenShortFlag = "t" - accessTokenTokenUsage = "The AK/SK token to delete." + //nolint:gosec // This is not a hardcoded credential but a help message containing ak/sk + accessTokenTokenUsage = "The AK/SK token to delete." + openstackConfigCreateConfigLocationFlag = "config-location" + openstackConfigCreateConfigLocationShortFlag = "l" + openstackConfigCreateConfigLocationUsage = "Where the config should be saved." ) diff --git a/cmd/version.go b/cmd/version.go index 05a5eacd..6a6c2bc4 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "github.com/spf13/cobra" ) diff --git a/format_and_lint.sh b/format_and_lint.sh index 8bd3fb05..7bdfad97 100644 --- a/format_and_lint.sh +++ b/format_and_lint.sh @@ -1,8 +1,11 @@ #!/bin/zsh -reset && \ -gci write . && \ -go vet . && \ -goimports -w . && \ -gofmt -w . && \ -gofumpt -w . && \ -$HOME/go/bin/golangci-lint run -v \ No newline at end of file + +PATH="$PATH:$HOME/go/bin" + +reset +gci write . +go vet . +goimports -w . +gofmt -w . +gofumpt -w . +golangci-lint run -v diff --git a/go.mod b/go.mod index 09e75fd4..22d42465 100644 --- a/go.mod +++ b/go.mod @@ -3,33 +3,34 @@ module otc-auth go 1.20 require ( - github.com/akamensky/argparse v1.4.0 - github.com/coreos/go-oidc/v3 v3.4.0 + github.com/coreos/go-oidc/v3 v3.6.0 github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a - github.com/google/uuid v1.1.2 - github.com/gophercloud/utils v0.0.0-20230330070308-5bd5e1d608f8 - github.com/opentelekomcloud/gophertelekomcloud v0.6.1 + github.com/google/uuid v1.3.0 + github.com/gophercloud/utils v0.0.0-20230523080330-de873b9cf00d + github.com/opentelekomcloud/gophertelekomcloud v0.7.0 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.15.0 - golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 + github.com/spf13/viper v1.16.0 + golang.org/x/oauth2 v0.9.0 gopkg.in/yaml.v2 v2.4.0 - k8s.io/client-go v0.25.2 + k8s.io/client-go v0.27.3 ) require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.6.9 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/gophercloud/gophercloud v1.3.0 // indirect + github.com/gophercloud/gophercloud v1.5.0 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -37,29 +38,29 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/spf13/afero v1.9.3 // indirect - github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect - golang.org/x/crypto v0.1.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/time v0.1.0 // indirect + golang.org/x/crypto v0.10.0 // indirect + golang.org/x/net v0.11.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/term v0.9.0 // indirect + golang.org/x/text v0.11.0 // indirect + golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apimachinery v0.25.2 // indirect - k8s.io/klog/v2 v2.80.1 // indirect - k8s.io/utils v0.0.0-20220922104903-7796b5f52b7e // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + k8s.io/apimachinery v0.27.3 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 080dab0f..d29fc2c3 100644 --- a/go.sum +++ b/go.sum @@ -84,6 +84,8 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu6g= github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw= +github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o= +github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -91,6 +93,7 @@ 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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -103,6 +106,7 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -111,9 +115,13 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a h1:v6zMvHuY9yue4+QkG/HQ/W67wvtQmWJ4SDo9aK/GIno= github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw= +github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= +github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= @@ -150,6 +158,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -195,6 +205,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -207,9 +219,14 @@ github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gophercloud/gophercloud v1.3.0 h1:RUKyCMiZoQR3VlVR5E3K7PK1AC3/qppsWYo6dtBiqs8= github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= +github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gophercloud/utils v0.0.0-20230330070308-5bd5e1d608f8 h1:K9r5WEeAiaEgFZsuOP0OYjE4TtyFcCLG1nI08t9AP6A= github.com/gophercloud/utils v0.0.0-20230330070308-5bd5e1d608f8/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto= +github.com/gophercloud/utils v0.0.0-20230523080330-de873b9cf00d h1:6Gvua77nKyAiZQpu0N3AsamGu1L6Mlnhp3tAtDcqwvc= +github.com/gophercloud/utils v0.0.0-20230523080330-de873b9cf00d/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -219,6 +236,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -233,6 +252,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -251,8 +271,12 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/opentelekomcloud/gophertelekomcloud v0.6.1 h1:au6sQ6RbJJ16gcpRAL+o0pkb2C23zHmNoAvjpPzo0Gg= github.com/opentelekomcloud/gophertelekomcloud v0.6.1/go.mod h1:9Deb3q2gJvq5dExV+aX+iO+G+mD9Zr9uFt+YY9ONmq0= +github.com/opentelekomcloud/gophertelekomcloud v0.7.0 h1:MRo/I0DpoxY57ebX8KoOfCHMxWQQC8kym+HivdwFThk= +github.com/opentelekomcloud/gophertelekomcloud v0.7.0/go.mod h1:9Deb3q2gJvq5dExV+aX+iO+G+mD9Zr9uFt+YY9ONmq0= github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -263,13 +287,18 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= @@ -278,6 +307,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= +github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -292,6 +323,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -314,14 +347,18 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -408,6 +445,8 @@ golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -431,6 +470,8 @@ golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7Lm golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs= +golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -507,16 +548,20 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -529,11 +574,15 @@ 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.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -772,6 +821,8 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -802,20 +853,32 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.25.2 h1:v6G8RyFcwf0HR5jQGIAYlvtRNrxMJQG1xJzaSeVnIS8= +k8s.io/api v0.27.3 h1:yR6oQXXnUEBWEWcvPWS0jQL575KoAboQPfJAuKNrw5Y= k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs= k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA= +k8s.io/apimachinery v0.27.3 h1:Ubye8oBufD04l9QnNtW05idcOe9Z3GQN8+7PqmuVcUM= +k8s.io/apimachinery v0.27.3/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= k8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo= k8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4= +k8s.io/client-go v0.27.3 h1:7dnEGHZEJld3lYwxvLl7WoehK6lAq7GvgjxpA3nv1E8= +k8s.io/client-go v0.27.3/go.mod h1:2MBEKuTo6V1lbKy3z1euEGnhPfGZLKTS9tiJ2xodM48= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= k8s.io/utils v0.0.0-20220922104903-7796b5f52b7e h1:VCa0oVHFkQCgny6nAwFEmNCzJcviA831cY/rZPShVdU= k8s.io/utils v0.0.0-20220922104903-7796b5f52b7e/go.mod h1:G4gXLUBxr2awE32MvACDCarw5gMwh+m/ka6hN8lR5jA= +k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= +k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= diff --git a/login/argument_verifier.go b/login/argument_verifier.go deleted file mode 100644 index 4e92653a..00000000 --- a/login/argument_verifier.go +++ /dev/null @@ -1,22 +0,0 @@ -package login - -const ( - envOsUsername = "OS_USERNAME" - envOsPassword = "OS_PASSWORD" - envOsDomainName = "OS_DOMAIN_NAME" - envOsUserDomainId = "OS_USER_DOMAIN_ID" - envOsProjectName = "OS_PROJECT_NAME" - envIdpName = "IDP_NAME" - envIdpUrl = "IDP_URL" - envClientId = "CLIENT_ID" - envClientSecret = "CLIENT_SECRET" - envClusterName = "CLUSTER_NAME" - envOidScopes = "OIDC_SCOPES" - envOidcScopesDefault = "openid,profile,roles,name,groups,email" - - authTypeIDP = "idp" - authTypeIAM = "iam" - - protocolSAML = "saml" - protocolOIDC = "oidc" -) diff --git a/login/login.go b/login/login.go index 17190f49..43dd0293 100644 --- a/login/login.go +++ b/login/login.go @@ -10,6 +10,11 @@ import ( "otc-auth/saml" ) +const ( + protocolSAML = "saml" + protocolOIDC = "oidc" +) + func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) { config.LoadCloudConfig(authInfo.DomainName) diff --git a/main.go b/main.go index 86e5b2dc..36c96bb3 100644 --- a/main.go +++ b/main.go @@ -18,13 +18,13 @@ package main import "otc-auth/cmd" +//nolint:gochecknoglobals // required to set the version and date by ldflags var ( version = "dev" date = "unknown" ) func main() { - cmd.SetVersionInfo(cmd.RootCmd, version, date) cmd.Execute() } diff --git a/oldmain.go b/oldmain.go deleted file mode 100644 index 2cc35d97..00000000 --- a/oldmain.go +++ /dev/null @@ -1,351 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - "otc-auth/login" - - "otc-auth/accesstoken" - "otc-auth/cce" - "otc-auth/common" - "otc-auth/config" - "otc-auth/iam" - "otc-auth/openstack" - - "github.com/akamensky/argparse" -) - -const ( - osUsername = "os-username" - osPassword = "os-password" - overwriteTokenArg = "overwrite-token" - osDomainName = "os-domain-name" - region = "region" - osUserDomainID = "os-user-domain-id" - osProjectName = "os-project-name" - totpArg = "totp" - idpName = "idp-name" - idpURLArg = "idp-url" - clientIDArg = "client-id" - clientSecretArg = "client-secret" - clusterArg = "cluster" - isServiceAccountArg = "service-account" - oidcScopesArg = "oidc-scopes" -) - -//nolint:funlen,gocognit -func main() { - log.SetFlags(0) // Remove timestamps from printed messages - const ( - provideArgumentHelp = "Either provide this argument or set the environment variable" - overwriteTokenHelp = "Overrides .otc-info file" //nolint:gosec // gosec thinks these are hardcoded credentials - requiredForIdp = "Required for authentication with IdP." - ) - var ( - domainName *string - regionCode *string - username *string - password *string - overwriteToken *bool - identityProvider *string - identityProviderURL *string - isServiceAccount *bool - idpCommandHelp = fmt.Sprintf( - "The name of the identity provider. Allowed values in the iam section of the OTC UI. %s %s %s", - requiredForIdp, provideArgumentHelp, envIdpName) - idpURLCommandHelp = fmt.Sprintf("Url from the identity provider (e.g. ...realms/myrealm/protocol/saml). %s %s %s", - requiredForIdp, provideArgumentHelp, envIdpURL) - isServiceAccountHelp = "Flag to set if the account is a service account. " + - "The service account needs to be configured in your identity provider." - oidcScopesHelp = "Flag to set the scopes which are expected from the OIDC request." - ) - - parser := argparse.NewParser("otc-auth", "OTC-Auth Command Line Interface for managing OTC clouds.") - - // Version - versionCommand := parser.NewCommand("version", "Returns OTC-Auth's version.") - - // Login & common commands - loginCommand := parser.NewCommand("login", "Login to the Open Telekom Cloud and receive an unscoped token.") - username = loginCommand.String( - "u", osUsername, - &argparse.Options{Required: false, Help: fmt.Sprintf( - "Username for the OTC IAM system. %s %s", provideArgumentHelp, envOsUsername)}) - password = loginCommand.String( - "p", osPassword, - &argparse.Options{Required: false, Help: fmt.Sprintf( - "Password for the OTC IAM system. %s %s", provideArgumentHelp, envOsPassword)}) - domainName = loginCommand.String( - "d", osDomainName, - &argparse.Options{ - Required: false, - Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName), - }) - regionCode = loginCommand.String( - "r", region, &argparse.Options{ - Required: false, - Help: fmt.Sprintf("OTC region code. %s %s", provideArgumentHelp, envRegion), - }) - overwriteToken = loginCommand.Flag( - "o", overwriteTokenArg, &argparse.Options{Required: false, Help: overwriteTokenHelp, Default: false}) - identityProvider = loginCommand.String("i", idpName, &argparse.Options{Required: false, Help: idpCommandHelp}) - identityProviderURL = loginCommand.String("", idpURLArg, &argparse.Options{Required: false, Help: idpURLCommandHelp}) - - // Remove Login information - removeLoginCommand := loginCommand.NewCommand("remove", "Removes login information for a cloud") - - // Login with IAM - loginIamCommand := loginCommand.NewCommand( - "iam", "Login to the Open Telekom Cloud through its Identity and Access Management system.") - totp := loginIamCommand.String( - "t", totpArg, - &argparse.Options{Required: false, Help: "6-digit time-based one-time password (TOTP) used for the MFA login flow."}) - userDomainID := loginIamCommand.String( - "", osUserDomainID, - &argparse.Options{Required: false, Help: fmt.Sprintf( - "User ID number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp"+ - " is provided. %s %s", provideArgumentHelp, envOsUserDomainID)}) - - // Login with IDP + SAML - loginIdpSamlCommand := loginCommand.NewCommand( - "idp-saml", "Login to the Open Telekom Cloud through an Identity Provider and SAML.") - - // Login with IDP + OIDC - loginIdpOidcCommand := loginCommand.NewCommand( - "idp-oidc", "Login to the Open Telekom Cloud through an Identity Provider and OIDC.") - clientID := loginIdpOidcCommand.String( - "c", clientIDArg, - &argparse.Options{Required: false, Help: fmt.Sprintf("Client ID as set on the IdP. %s %s", - provideArgumentHelp, envClientID)}) - clientSecret := loginIdpOidcCommand.String( - "s", clientSecretArg, - &argparse.Options{Required: false, Help: fmt.Sprintf("Secret ID as set on the IdP. %s %s", - provideArgumentHelp, envClientSecret)}) - isServiceAccount = loginIdpOidcCommand.Flag( - "", isServiceAccountArg, &argparse.Options{Required: false, Help: isServiceAccountHelp}) - oidcScopes := loginIdpOidcCommand.String("", oidcScopesArg, &argparse.Options{Required: false, Help: oidcScopesHelp}) - // List Projects - projectsCommand := parser.NewCommand("projects", "Manage Project Information") - listProjectsCommand := projectsCommand.NewCommand("list", "List Projects in Active Cloud") - - // Manage Cloud Container Engine - cceCommand := parser.NewCommand("cce", "Manage Cloud Container Engine.") - projectName := cceCommand.String( - "p", osProjectName, - &argparse.Options{Required: false, Help: fmt.Sprintf("Name of the project you want to access. %s %s.", - provideArgumentHelp, envOsProjectName)}) - cceDomainName := cceCommand.String( - "d", osDomainName, - &argparse.Options{Required: false, Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName)}) - - // List clusters - getClustersCommand := cceCommand.NewCommand("list", "Lists Project Clusters in CCE.") - - // Get Kubernetes Configuration - getKubeConfigCommand := cceCommand.NewCommand( - "get-kube-config", "Get remote kube config and merge it with existing local config file.") - clusterName := getKubeConfigCommand.String( - "c", clusterArg, &argparse.Options{ - Required: false, - Help: fmt.Sprintf("Name of the clusterArg you want to access %s %s.", provideArgumentHelp, envClusterName), - }) - daysValid := getKubeConfigCommand.String( - "v", "days-valid", - &argparse.Options{Required: false, Help: "Period (in days) that the config will be valid", Default: "7"}) - targetLocation := getKubeConfigCommand.String( - "l", "target-location", - &argparse.Options{Required: false, Help: "Where the kube config should be saved, Default: ~/.kube/config"}) - - // AK/SK Management - accessTokenCommand := parser.NewCommand("access-token", "Manage AK/SK.") - accessTokenCommandCreate := accessTokenCommand.NewCommand("create", "Create new AK/SK.") - tokenDescription := accessTokenCommandCreate.String( - "s", "description", - &argparse.Options{Required: false, Help: "Description of the token.", Default: "Token by otc-auth"}) - accessTokenCommandList := accessTokenCommand.NewCommand("list", "List existing AK/SKs.") - accessTokenCommandDelete := accessTokenCommand.NewCommand("delete", "Delete existing AK/SK.") - token := accessTokenCommandDelete.String( - "t", "token", &argparse.Options{Required: true, Help: "The AK/SK token to delete."}) - atDomainName := accessTokenCommand.String("d", osDomainName, &argparse.Options{ - Required: false, - Help: fmt.Sprintf("OTC domain name. %s %s", provideArgumentHelp, envOsDomainName), - }) - - // Openstack Management - openStackCommand := parser.NewCommand("openstack", "Manage Openstack Integration") - openStackCommandCreateConfigFile := openStackCommand.NewCommand("config-create", "Creates new clouds.yaml") - openStackConfigLocation := openStackCommand.String( - "l", "config-location", - &argparse.Options{ - Required: false, - Help: "Where the config should be saved, Default: ~/.config/openstack/clouds.yaml", - }) - - err := parser.Parse(os.Args) - if err != nil { - common.OutputErrorMessageToConsoleAndExit(parser.Usage(err)) - } - - if versionCommand.Happened() { - _, errVersion := fmt.Fprintf(os.Stdout, "OTC-Auth %s (%s)", version, date) - if errVersion != nil { - common.OutputErrorToConsoleAndExit(errVersion, "fatal: could not print tool version.") - } - } - - if loginIamCommand.Happened() { - totpToken, userID := checkMFAFlowIAM(*totp, *userDomainID) - - authInfo := common.AuthInfo{ - AuthType: authTypeIAM, - Username: getUsernameOrThrow(*username), - Password: getPasswordOrThrow(*password), - DomainName: getDomainNameOrThrow(*domainName), - Otp: totpToken, - UserDomainID: userID, - OverwriteFile: *overwriteToken, - Region: getRegionCodeOrThrow(*regionCode), - } - - login.AuthenticateAndGetUnscopedToken(authInfo) - } - - if loginIdpSamlCommand.Happened() { - identityProvider, identityProviderURL := getIdpInfoOrThrow(*identityProvider, *identityProviderURL) - authInfo := common.AuthInfo{ - AuthType: authTypeIDP, - Username: getUsernameOrThrow(*username), - Password: getPasswordOrThrow(*password), - DomainName: getDomainNameOrThrow(*domainName), - IdpName: identityProvider, - IdpURL: identityProviderURL, - AuthProtocol: protocolSAML, - OverwriteFile: *overwriteToken, - Region: getRegionCodeOrThrow(*regionCode), - } - - login.AuthenticateAndGetUnscopedToken(authInfo) - } - - if loginIdpOidcCommand.Happened() { - identityProvider, identityProviderURL := getIdpInfoOrThrow(*identityProvider, *identityProviderURL) - authInfo := common.AuthInfo{ - AuthType: authTypeIDP, - IdpName: identityProvider, - IdpURL: identityProviderURL, - AuthProtocol: protocolOIDC, - DomainName: getDomainNameOrThrow(*domainName), - ClientID: getClientIDOrThrow(*clientID), - ClientSecret: findClientSecretOrReturnEmpty(*clientSecret), - OverwriteFile: *overwriteToken, - IsServiceAccount: *isServiceAccount, - OidcScopes: getOidcScopes(*oidcScopes), - Region: getRegionCodeOrThrow(*regionCode), - } - - login.AuthenticateAndGetUnscopedToken(authInfo) - } - - if removeLoginCommand.Happened() { - domainNameToRemove := getDomainNameOrThrow(*domainName) - config.RemoveCloudConfig(domainNameToRemove) - } - - if listProjectsCommand.Happened() { - iam.GetProjectsInActiveCloud() - } - - if cceCommand.Happened() { - domainName := getDomainNameOrThrow(*cceDomainName) - config.LoadCloudConfig(domainName) - - if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit( - "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") - } - - project := getProjectNameOrThrow(*projectName) - - if getKubeConfigCommand.Happened() { - cluster := getClusterNameOrThrow(*clusterName) - - kubeConfigParams := cce.KubeConfigParams{ - ProjectName: project, - ClusterName: cluster, - DaysValid: *daysValid, - TargetLocation: *targetLocation, - } - - cce.GetKubeConfig(kubeConfigParams) - return - } - - if getClustersCommand.Happened() { - cce.GetClusterNames(project) - return - } - } - - if accessTokenCommandCreate.Happened() { - domainName := getDomainNameOrThrow(*atDomainName) - config.LoadCloudConfig(domainName) - - if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit( - "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") - } - - accesstoken.CreateAccessToken(*tokenDescription) - } - - if accessTokenCommandList.Happened() { - domainName := getDomainNameOrThrow(*atDomainName) - config.LoadCloudConfig(domainName) - - if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit( - "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") - } - - accessTokens, err2 := accesstoken.ListAccessToken() - if err2 != nil { - common.OutputErrorToConsoleAndExit(err2) - } - if len(accessTokens) > 0 { - log.Println("\nAccess Tokens:") - for _, aT := range accessTokens { - log.Printf("\nToken: \t\t%s\n"+ - "Description: \t%s\n"+ - "Created by: \t%s\n"+ - "Last Used: \t%s\n"+ - "Active: \t%s\n \n", - aT.AccessKey, aT.Description, aT.UserID, aT.LastUseTime, aT.Status) - } - } else { - log.Println("No access-tokens found") - } - } - - if accessTokenCommandDelete.Happened() { - domainName := getDomainNameOrThrow(*atDomainName) - config.LoadCloudConfig(domainName) - - if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit( - "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") - } - - if *token == "" { - common.OutputErrorMessageToConsoleAndExit("fatal: argument token cannot be empty.") - } - errDelete := accesstoken.DeleteAccessToken(*token) - if errDelete != nil { - common.OutputErrorToConsoleAndExit(errDelete) - } - } - - if openStackCommandCreateConfigFile.Happened() { - openstack.WriteOpenStackCloudsYaml(*openStackConfigLocation) - } -} From 739549a99b509fa7119da0c553ccb780158809d6 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 5 Jul 2023 16:43:54 +0200 Subject: [PATCH 07/16] Fix linter --- .gitignore | 3 ++- cmd/root.go | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 08adc5b9..82366cb5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .DS_Store # Files generated by JetBrains IDEs, e.g. IntelliJ IDEA .idea/ -*.iml \ No newline at end of file +*.iml +generated-docs \ No newline at end of file diff --git a/cmd/root.go b/cmd/root.go index e0fc5446..0750d142 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -550,8 +550,9 @@ $ otc-auth access-token create $ export OS_DOMAIN_NAME=MyDomain $ otc-auth access-token create` - accessTokenListCmdHelp = "List existing AK/SKs." - accessTokenDeleteCmdHelp = "Delete existing AK/SKs." + accessTokenListCmdHelp = "List existing AK/SKs." + accessTokenDeleteCmdHelp = "Delete existing AK/SKs." + //nolint:gosec // This is not a hardcoded credential but a help message containing ak/sk accessTokenDeleteCmdExample = `$ otc-auth access-token delete --token YourToken $ export OS_DOMAIN_NAME=YourDomain From b0a9bf0d51076d9054abe78604de6d541623d637 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Thu, 3 Aug 2023 15:05:22 +0200 Subject: [PATCH 08/16] ci: adding action to release the wiki automatically --- .github/workflows/release.yml | 28 ++++ go.mod | 1 - go.sum | 258 +--------------------------------- 3 files changed, 32 insertions(+), 255 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 775c324b..427f38ad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,3 +65,31 @@ jobs: ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} commit_message: "Bump to ${{ github.github_ref_name }}" ssh_keyscan_types: rsa,dsa,ecdsa,ed25519 + + wikiupdate: + runs-on: ubuntu-latest + steps: + - name: Setup Go environment + uses: actions/setup-go@v3 + with: + go-version: ^1.20 + - name: Checkout + uses: actions/checkout@v2 + - name: Get dependencies + run: go mod download + - name: Build + run: go run main.go documentation + - name: Checkout wiki code + uses: actions/checkout@v2 + with: + repository: ${{github.repository}}.wiki + path: markdown + - name: Push to wiki + run: | + cp -r generated_docs markdown/docs + cd markdown + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add . + git diff-index --quiet HEAD || git commit -m "Updated docs" && git push + diff --git a/go.mod b/go.mod index 22d42465..ffa01e19 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,6 @@ require ( gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.27.3 // indirect k8s.io/klog/v2 v2.100.1 // indirect diff --git a/go.sum b/go.sum index d29fc2c3..bd1c2ebb 100644 --- a/go.sum +++ b/go.sum @@ -17,34 +17,14 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -55,20 +35,14 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/akamensky/argparse v1.4.0 h1:YGzvsTqCvbEZhL8zZu2AiA5nq805NZh75JNj4ajn1xc= -github.com/akamensky/argparse v1.4.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -76,14 +50,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu6g= -github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw= github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o= github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= @@ -92,20 +59,15 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -118,13 +80,11 @@ github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I7 github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -138,8 +98,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -155,12 +113,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= @@ -173,12 +128,8 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -186,7 +137,6 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -197,32 +147,16 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gophercloud/gophercloud v1.3.0 h1:RUKyCMiZoQR3VlVR5E3K7PK1AC3/qppsWYo6dtBiqs8= github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= -github.com/gophercloud/utils v0.0.0-20230330070308-5bd5e1d608f8 h1:K9r5WEeAiaEgFZsuOP0OYjE4TtyFcCLG1nI08t9AP6A= -github.com/gophercloud/utils v0.0.0-20230330070308-5bd5e1d608f8/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto= github.com/gophercloud/utils v0.0.0-20230523080330-de873b9cf00d h1:6Gvua77nKyAiZQpu0N3AsamGu1L6Mlnhp3tAtDcqwvc= github.com/gophercloud/utils v0.0.0-20230523080330-de873b9cf00d/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -234,8 +168,6 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -251,14 +183,13 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -269,12 +200,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/opentelekomcloud/gophertelekomcloud v0.6.1 h1:au6sQ6RbJJ16gcpRAL+o0pkb2C23zHmNoAvjpPzo0Gg= -github.com/opentelekomcloud/gophertelekomcloud v0.6.1/go.mod h1:9Deb3q2gJvq5dExV+aX+iO+G+mD9Zr9uFt+YY9ONmq0= github.com/opentelekomcloud/gophertelekomcloud v0.7.0 h1:MRo/I0DpoxY57ebX8KoOfCHMxWQQC8kym+HivdwFThk= github.com/opentelekomcloud/gophertelekomcloud v0.7.0/go.mod h1:9Deb3q2gJvq5dExV+aX+iO+G+mD9Zr9uFt+YY9ONmq0= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= @@ -286,17 +213,12 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= -github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= @@ -305,8 +227,6 @@ github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmq github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -321,8 +241,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= @@ -334,7 +252,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -342,7 +259,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -352,10 +268,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= @@ -382,7 +296,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -393,7 +306,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -423,28 +335,14 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -456,20 +354,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs= golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -482,8 +366,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -516,50 +398,23 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -572,15 +427,11 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/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.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -632,19 +483,11 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -664,26 +507,6 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -728,51 +551,8 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -791,20 +571,7 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -818,9 +585,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -833,8 +597,6 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -852,31 +614,19 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.25.2 h1:v6G8RyFcwf0HR5jQGIAYlvtRNrxMJQG1xJzaSeVnIS8= k8s.io/api v0.27.3 h1:yR6oQXXnUEBWEWcvPWS0jQL575KoAboQPfJAuKNrw5Y= -k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs= -k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA= k8s.io/apimachinery v0.27.3 h1:Ubye8oBufD04l9QnNtW05idcOe9Z3GQN8+7PqmuVcUM= k8s.io/apimachinery v0.27.3/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= -k8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo= -k8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4= k8s.io/client-go v0.27.3 h1:7dnEGHZEJld3lYwxvLl7WoehK6lAq7GvgjxpA3nv1E8= k8s.io/client-go v0.27.3/go.mod h1:2MBEKuTo6V1lbKy3z1euEGnhPfGZLKTS9tiJ2xodM48= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= -k8s.io/utils v0.0.0-20220922104903-7796b5f52b7e h1:VCa0oVHFkQCgny6nAwFEmNCzJcviA831cY/rZPShVdU= -k8s.io/utils v0.0.0-20220922104903-7796b5f52b7e/go.mod h1:G4gXLUBxr2awE32MvACDCarw5gMwh+m/ka6hN8lR5jA= k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= From 1396e91799253d4f470a3fc1ed4502f000d5bbd0 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Thu, 3 Aug 2023 15:22:00 +0200 Subject: [PATCH 09/16] fix documentation gneration and improve git-ignore --- .gitignore | 328 ++++++++++++++++++++++++++++++++++++++++++- cmd/documentation.go | 2 + 2 files changed, 325 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 82366cb5..e8fc93e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,324 @@ -# OSX trash +generated-docs + +# Created by https://www.toptal.com/developers/gitignore/api/go,goland+all,intellij+all,vim,emacs,macos,linux,visualstudiocode,git +# Edit at https://www.toptal.com/developers/gitignore?templates=go,goland+all,intellij+all,vim,emacs,macos,linux,visualstudiocode,git + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +### Go ### +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +### GoLand+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### GoLand+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + +.idea/* + +!.idea/codeStyles +!.idea/runConfigurations + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff + +# AWS User-specific + +# Generated files + +# Sensitive or high-churn files + +# Gradle + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake + +# Mongo Explorer plugin + +# File-based project format + +# IntelliJ + +# mpeltonen/sbt-idea plugin + +# JIRA plugin + +# Cursive Clojure plugin + +# SonarLint plugin + +# Crashlytics plugin (for Android Studio and IntelliJ) + +# Editor-based Rest Client + +# Android studio 3.1+ serialized cache file + +### Intellij+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + + + +### Linux ### + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General .DS_Store -# Files generated by JetBrains IDEs, e.g. IntelliJ IDEA -.idea/ -*.iml -generated-docs \ No newline at end of file +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/go,goland+all,intellij+all,vim,emacs,macos,linux,visualstudiocode,git \ No newline at end of file diff --git a/cmd/documentation.go b/cmd/documentation.go index 2e08ebde..634ab177 100644 --- a/cmd/documentation.go +++ b/cmd/documentation.go @@ -18,6 +18,7 @@ package cmd import ( "log" + "os" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" @@ -28,6 +29,7 @@ var documentationCmd = &cobra.Command{ Use: "documentation", Short: "Generates markdown documentation", RunE: func(cmd *cobra.Command, args []string) error { + os.Mkdir("./generated-docs", 0700) err := doc.GenMarkdownTree(cmd.Root(), "./generated-docs/") log.Println("documentation generated") return err From d4b819d7b619b4bd1572723a98c1de854b65a25e Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Thu, 3 Aug 2023 15:27:39 +0200 Subject: [PATCH 10/16] fix ci pipeline --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 427f38ad..4ba88448 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,15 +17,15 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: 1.20 - name: Run GoReleaser uses: goreleaser/goreleaser-action@v3 with: version: latest - args: release --rm-dist + args: release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -86,7 +86,7 @@ jobs: path: markdown - name: Push to wiki run: | - cp -r generated_docs markdown/docs + cp -r generated-docs markdown/docs cd markdown git config --local user.email "action@github.com" git config --local user.name "GitHub Action" From 01308833eb0e46c4bb497f006fdb4cb554aebe5c Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 23 Aug 2023 10:15:03 +0200 Subject: [PATCH 11/16] fixed docs and improved doc generation for GH Wiki --- .github/workflows/release.yml | 2 +- .gitignore | 2 +- cmd/completion.go | 38 +++++++++++++++++------------------ cmd/documentation.go | 16 +++++++++------ go.mod | 3 +-- go.sum | 7 +++++-- 6 files changed, 37 insertions(+), 31 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4ba88448..845d6c58 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,7 +86,7 @@ jobs: path: markdown - name: Push to wiki run: | - cp -r generated-docs markdown/docs + cp -r generated-documentation.md markdown/ cd markdown git config --local user.email "action@github.com" git config --local user.name "GitHub Action" diff --git a/.gitignore b/.gitignore index e8fc93e3..fb5f27d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -generated-docs +generated-documentation.md # Created by https://www.toptal.com/developers/gitignore/api/go,goland+all,intellij+all,vim,emacs,macos,linux,visualstudiocode,git # Edit at https://www.toptal.com/developers/gitignore?templates=go,goland+all,intellij+all,vim,emacs,macos,linux,visualstudiocode,git diff --git a/cmd/completion.go b/cmd/completion.go index 313c9829..af677865 100644 --- a/cmd/completion.go +++ b/cmd/completion.go @@ -31,40 +31,40 @@ var completionCmd = &cobra.Command{ Bash: - $ source <(%[1]s completion bash) + $ source <(%[1]s completion bash) - # To load completions for each session, execute once: - # Linux: - $ %[1]s completion bash > /etc/bash_completion.d/%[1]s - # macOS: - $ %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s + # To load completions for each session, execute once: + # Linux: + $ %[1]s completion bash > /etc/bash_completion.d/%[1]s + # macOS: + $ %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s Zsh: - # If shell completion is not already enabled in your environment, - # you will need to enable it. You can execute the following once: + # If shell completion is not already enabled in your environment, + # you will need to enable it. You can execute the following once: - $ echo "autoload -U compinit; compinit" >> ~/.zshrc + $ echo "autoload -U compinit; compinit" >> ~/.zshrc - # To load completions for each session, execute once: - $ %[1]s completion zsh > "${fpath[1]}/_%[1]s" + # To load completions for each session, execute once: + $ %[1]s completion zsh > "${fpath[1]}/_%[1]s" - # You will need to start a new shell for this setup to take effect. + # You will need to start a new shell for this setup to take effect. fish: - $ %[1]s completion fish | source + $ %[1]s completion fish | source - # To load completions for each session, execute once: - $ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish + # To load completions for each session, execute once: + $ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish PowerShell: - PS> %[1]s completion powershell | Out-String | Invoke-Expression + PS> %[1]s completion powershell | Out-String | Invoke-Expression - # To load completions for every new session, run: - PS> %[1]s completion powershell > %[1]s.ps1 - # and source this file from your PowerShell profile. + # To load completions for every new session, run: + PS> %[1]s completion powershell > %[1]s.ps1 + # and source this file from your PowerShell profile. `, RootCmd.Name()), DisableFlagsInUseLine: true, ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, diff --git a/cmd/documentation.go b/cmd/documentation.go index 634ab177..221f1d34 100644 --- a/cmd/documentation.go +++ b/cmd/documentation.go @@ -17,11 +17,11 @@ along with this program. If not, see . package cmd import ( - "log" + "bytes" "os" + "github.com/gavv/cobradoc" "github.com/spf13/cobra" - "github.com/spf13/cobra/doc" ) //nolint:gochecknoglobals // autogenerated and recommended by spf13/cobra @@ -29,10 +29,14 @@ var documentationCmd = &cobra.Command{ Use: "documentation", Short: "Generates markdown documentation", RunE: func(cmd *cobra.Command, args []string) error { - os.Mkdir("./generated-docs", 0700) - err := doc.GenMarkdownTree(cmd.Root(), "./generated-docs/") - log.Println("documentation generated") - return err + + buf := bytes.NewBufferString("") + if err := cobradoc.WriteDocument(buf, cmd.Root(), cobradoc.Markdown, cobradoc.Options{}); err != nil { + return err + } + + documentation := "./generated-documentation.md" + return os.WriteFile(documentation, buf.Bytes(), 0755) }, } diff --git a/go.mod b/go.mod index ffa01e19..90ec2c6d 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.20 require ( github.com/coreos/go-oidc/v3 v3.6.0 + github.com/gavv/cobradoc v1.1.0 github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a github.com/google/uuid v1.3.0 github.com/gophercloud/utils v0.0.0-20230523080330-de873b9cf00d @@ -18,7 +19,6 @@ require ( ) require ( - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-jose/go-jose/v3 v3.0.0 // indirect @@ -39,7 +39,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect diff --git a/go.sum b/go.sum index bd1c2ebb..c2061e74 100644 --- a/go.sum +++ b/go.sum @@ -53,7 +53,6 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o= github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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= @@ -71,6 +70,8 @@ github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gavv/cobradoc v1.1.0 h1:UVAfle1xOwRdqlY5qJhDEJ4SgLyQtTdGCqLNYixp1m4= +github.com/gavv/cobradoc v1.1.0/go.mod h1:Dz0SCTUhrmpCY1FJ+hudpCMWUeCjasu6SREDygYw9sA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -170,6 +171,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -214,13 +216,13 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= @@ -427,6 +429,7 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/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.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From dcac2a566721db826b9b7ef661a07dbb61fff7de Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 23 Aug 2023 10:21:06 +0200 Subject: [PATCH 12/16] change file permissions from 755 to 600 for docs --- cmd/documentation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/documentation.go b/cmd/documentation.go index 221f1d34..41b6709a 100644 --- a/cmd/documentation.go +++ b/cmd/documentation.go @@ -36,7 +36,7 @@ var documentationCmd = &cobra.Command{ } documentation := "./generated-documentation.md" - return os.WriteFile(documentation, buf.Bytes(), 0755) + return os.WriteFile(documentation, buf.Bytes(), 0600) }, } From 1722862d470f79ae1eff617e9d4822b7915acc32 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 23 Aug 2023 10:59:39 +0200 Subject: [PATCH 13/16] improve readme with completions --- README.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d7a75b23..c47a98b0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # OTC-Auth + Open Source CLI for the Authorization with the Open Telekom Cloud. [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/iits-consulting/otc-auth/blob/main/LICENSE) @@ -14,9 +15,11 @@ After you have retrieved an unscoped token, you can use it to get a list of the This tool can also be used to manage (create) a pair of Access Key/ Secret Key in order to make requests more secure. ## Demo + https://user-images.githubusercontent.com/19291722/208880256-b0da924e-254e-4bc4-b9ee-396c43234a5b.mp4 ## Install + You can download the binary for your system in the [releases page](https://github.com/iits-consulting/otc-auth/releases). Unpack the binary and add it to your PATH and you are good to go! @@ -25,9 +28,11 @@ Unpack the binary and add it to your PATH and you are good to go! Users of Arch Linux may use the package published in the [AUR](https://aur.archlinux.org/packages/otc-auth) ## Login + Use the `login` command to retrieve an unscoped token either by logging in directly with the Service Provider or through an IdP. You can see the help page by entering `login --help` or `login -h`. There are three log in options (`iam`, `idp-saml`, and `idp-oidc`) and one of them must be provided. ### Service Provider Login (IAM) + To log in directly with the Open Telekom Cloud's IAM, you will have to supply the domain name you're attempting to log in to (usually starting with "OTC-EU", following the region and a longer identifier), your username and password. `otc-auth login iam --os-username --os-password --os-domain-name --region ` @@ -41,19 +46,22 @@ otc-auth login iam --os-username --os-password --os-domain The OTP Token is 6-digit long and refreshes every 30 seconds. For more information on MFA please refer to the [OTC's documentation](https://docs.otc.t-systems.com/en-us/usermanual/iam/iam_10_0002.html). ### Identity Provider Login (IdP) + You can log in with an external IdP using either the `saml` or the `oidc` protocols. In both cases you will need to specify the authorization URL, the name of the Identity Provider (as set on the OTC), as well as username and password for the SAML login and client id (and optionally client secret) for the OIDC login flow. #### External IdP and SAML + The SAML login flow is SP initiated and requires you to send username and password to the SP. The SP then authorizes you with the configured IdP and returns either an unscoped token or an error, if the user is not allowed to log in. -```otc-auth login idp-saml --os-username --os-password --idp-name --idp-url --os-domain-name --region ``` +`otc-auth login idp-saml --os-username --os-password --idp-name --idp-url --os-domain-name --region ` At the moment, no MFA is supported for this login flow. #### External IdP and OIDC + The OIDC login flow is user initiated and will open a browser window with the IdP's authorization URL for the user to log in as desired. This flow does support MFA (this requires it to be configured on the IdP). After being successfully authenticated with the IdP, the SP will be contacted with the corresponding credentials and will return either an unscoped token or an error, if the user is not allowed to log in. -```otc-auth login idp-oidc --idp-name --idp-url --client-id --os-domain-name --region [--client-secret ]``` +`otc-auth login idp-oidc --idp-name --idp-url --client-id --os-domain-name --region [--client-secret ]` The argument `--client-id` is required, but the argument `--client-secret` is only needed if configured on the IdP. @@ -61,7 +69,6 @@ The argument `--client-id` is required, but the argument `--client-secret` is on If you have set up your IdP to provide service accounts then you can utilize service account with `otc-auth` too. Make also sure that the IdP is correctly configured in the OTC Identity and Access Management. Then run the `otc-auth` as follows: - ```shell otc-auth login idp-oidc \ --idp-name NameOfClientInIdp \ @@ -77,22 +84,25 @@ otc-auth login idp-oidc \ The OIDC scopes can be configured if required. To do so simply provide one of the following two when logging in with `idp-oidc`: -- provide the flag `--oidc-scopes pleasePut,HereAll,YourScopes,WhichYouNeed` +- provide the flag `--oidc-scopes pleasePut,HereAll,YourScopes,WhichYouNeed` - provide the environment variable `export OIDC_SCOPES="pleasePut,HereAll,YourScopes,WhichYouNeed"` The default value is `openid,profile,roles,name,groups,email` ### Remove Login + Clouds are differentiated by their identifier `--os-domain-name`. To delete a cloud, use the `remove` command. `otc-auth login remove --os-domain-name --region ` ## List Projects + It is possible to get a list of all projects in the current cloud. For that, use the following command. `otc-auth projects list` ## Cloud Container Engine + Use the `cce` command to retrieve a list of available clusters in your project and/or get the remote kube configuration file. You can see the help page by entering `cce --help` or `cce -h`. To retrieve a list of clusters for a project use the following command. The project name will be checked against the ones in the cloud at the moment of the request. @@ -107,6 +117,7 @@ To retrieve the remote kube configuration file (and merge to your local one) use Alternatively you can pass the argument `--days-valid` to set the period of days the configuration will be valid, the default is 7 days. ## Manage Access Key and Secret Key Pair + You can use the OTC-Auth tool to download the AK/SK pair directly from the OTC. It will download the "ak-sk-env.sh" file to the current directory. The file contains four environment variables. `otc-auth access-token create --os-domain-name --region ` @@ -114,6 +125,7 @@ You can use the OTC-Auth tool to download the AK/SK pair directly from the OTC. The "ak-sk-env.sh" file must then be sourced before you can start using the environment variables. ## Openstack Integration + The OTC-Auth tool is able to generate the clouds.yaml config file for openstack. With this file it is possible to reuse the clouds.yaml with terraform. @@ -121,14 +133,15 @@ If you execute this command `otc-auth openstack config-create` -It will create a cloud config for every project which you have access to and generate a scoped token. After that it overrides +It will create a cloud config for every project which you have access to and generate a scoped token. After that it overrides the clouds.yaml (by default: ~/.config/openstack/clouds.yaml) file. ## Environment Variables + The OTC-Auth tool also provides environment variables for all the required arguments. For the sake of compatibility, they are aligned with the Open Stack environment variables (starting with OS). | Environment Variable | Argument | Short | Description | -|----------------------|-----------------------|:-----:|-----------------------------------------------| +| -------------------- | --------------------- | :---: | --------------------------------------------- | | CLIENT_ID | `--client-id` | `c` | Client id as configured on the IdP | | CLIENT_SECRET | `--client-secret` | `s` | Client secret as configured on the IdP | | CLUSTER_NAME | `--cluster` | `c` | Cluster name on the OTC | @@ -140,3 +153,7 @@ The OTC-Auth tool also provides environment variables for all the required argum | OS_USERNAME | `--os-username` | `u` | Username (iam or idp) | | IDP_NAME | `--idp-name` | `i` | Identity Provider name (as configured on OTC) | | IDP_URL | `--idp-url` | N/A | Authorization endpoint on the IDP | + +## Auto-Completions + +You install the auto completions for your shell by running. Please follow the instructions by running `otc-auth completion --help` in your terminal. From 59a0afdb9ab857ee601af3efbdb493963bbb0153 Mon Sep 17 00:00:00 2001 From: Zeljko Bekcic Date: Wed, 23 Aug 2023 11:10:58 +0200 Subject: [PATCH 14/16] make nicer errors --- accesstoken/accesstoken.go | 5 +++-- cmd/root.go | 12 +++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/accesstoken/accesstoken.go b/accesstoken/accesstoken.go index 0d78c2ed..4344dd5e 100644 --- a/accesstoken/accesstoken.go +++ b/accesstoken/accesstoken.go @@ -70,14 +70,15 @@ func makeAccessFile(resp *credentials.Credential, tempResp *credentials.Temporar log.Println("Please source the ak-sk-env.sh file in the current directory manually") } -func CreateTemporaryAccessToken(durationSeconds int) { +func CreateTemporaryAccessToken(durationSeconds int) error { log.Println("Creating temporary access token file with GTC...") resp, err := getTempAccessTokenFromServiceProvider(durationSeconds) if err != nil { - common.OutputErrorToConsoleAndExit(err) + return err } makeAccessFile(nil, resp) + return nil } func ListAccessToken() ([]credentials.Credential, error) { diff --git a/cmd/root.go b/cmd/root.go index 535a1288..c31d45d1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -18,6 +18,7 @@ along with this program. If not, see . package cmd import ( + "errors" "log" "os" "strconv" @@ -192,14 +193,19 @@ var tempAccessTokenCreateCmd = &cobra.Command{ Use: "create", Short: tempAccessTokenCreateCmdHelp, Example: tempAccessTokenCreateCmdExample, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { config.LoadCloudConfig(domainName) if !config.IsAuthenticationValid() { - common.OutputErrorMessageToConsoleAndExit( - "fatal: no valid unscoped token found.\n\nPlease obtain an unscoped token by logging in first.") + return errors.New( + "fatal: no valid unscoped token found, please obtain an unscoped token by logging in first", + ) } + if temporaryAccessTokenDurationSeconds < 900 || temporaryAccessTokenDurationSeconds > 86400 { + return errors.New("fatal: token duration must be between 900 and 86400 seconds (15m and 24h)") + } accesstoken.CreateTemporaryAccessToken(temporaryAccessTokenDurationSeconds) + return nil }, } From d1f4a20a8739cfcea807aff547a502adb08bf2e4 Mon Sep 17 00:00:00 2001 From: Mweya Ruider Date: Wed, 23 Aug 2023 15:16:40 +0200 Subject: [PATCH 15/16] Added flag for insecure tls Also fixed some small bugs and now *actually* handle potential errors --- cmd/documentation.go | 3 +- cmd/root.go | 194 ++++++++++++++++++++++++---------------- common/http_client.go | 9 +- login/login.go | 6 +- oidc/oidc.go | 10 +-- oidc/service_account.go | 4 +- saml/saml.go | 20 ++--- 7 files changed, 147 insertions(+), 99 deletions(-) diff --git a/cmd/documentation.go b/cmd/documentation.go index 41b6709a..7bd1842a 100644 --- a/cmd/documentation.go +++ b/cmd/documentation.go @@ -29,14 +29,13 @@ var documentationCmd = &cobra.Command{ Use: "documentation", Short: "Generates markdown documentation", RunE: func(cmd *cobra.Command, args []string) error { - buf := bytes.NewBufferString("") if err := cobradoc.WriteDocument(buf, cmd.Root(), cobradoc.Markdown, cobradoc.Options{}); err != nil { return err } documentation := "./generated-documentation.md" - return os.WriteFile(documentation, buf.Bytes(), 0600) + return os.WriteFile(documentation, buf.Bytes(), 0o600) }, } diff --git a/cmd/root.go b/cmd/root.go index c31d45d1..e69fd00e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -37,8 +37,9 @@ import ( ) var RootCmd = &cobra.Command{ - Use: "otc-auth", - Short: "OTC-Auth Command Line Interface for managing OTC clouds", + Use: "otc-auth", + Short: "OTC-Auth Command Line Interface for managing OTC clouds", + PreRunE: configureCmdFlagsAgainstEnvs(rootFlagToEnv), } var loginCmd = &cobra.Command{ @@ -62,7 +63,7 @@ var loginIamCmd = &cobra.Command{ OverwriteFile: overwriteToken, Region: region, } - login.AuthenticateAndGetUnscopedToken(authInfo) + login.AuthenticateAndGetUnscopedToken(authInfo, skipTLS) }, } @@ -70,7 +71,7 @@ var loginIdpSamlCmd = &cobra.Command{ Use: "idp-saml", Short: loginIdpSamlCmdHelp, Example: loginIdpSamlCmdExample, - PreRunE: configureCmdFlagsAgainstEnvs(loginIdpSamlOidcFlagToEnv), + PreRunE: configureCmdFlagsAgainstEnvs(loginIdpSamlFlagToEnv), Run: func(cmd *cobra.Command, args []string) { authInfo := common.AuthInfo{ AuthType: "idp", @@ -83,7 +84,7 @@ var loginIdpSamlCmd = &cobra.Command{ OverwriteFile: overwriteToken, Region: region, } - login.AuthenticateAndGetUnscopedToken(authInfo) + login.AuthenticateAndGetUnscopedToken(authInfo, skipTLS) }, } @@ -91,20 +92,21 @@ var loginIdpOidcCmd = &cobra.Command{ Use: "idp-oidc", Short: loginIdpOidcCmdHelp, Example: loginIdpOidcCmdExample, - PreRunE: configureCmdFlagsAgainstEnvs(loginIdpSamlOidcFlagToEnv), + PreRunE: configureCmdFlagsAgainstEnvs(loginIdpOidcFlagToEnv), Run: func(cmd *cobra.Command, args []string) { authInfo := common.AuthInfo{ AuthType: "idp", - Username: username, - Password: password, + ClientID: clientID, + ClientSecret: clientSecret, DomainName: domainName, IdpName: idpName, IdpURL: idpURL, AuthProtocol: "oidc", OverwriteFile: overwriteToken, Region: region, + OidcScopes: oidcScopes, } - login.AuthenticateAndGetUnscopedToken(authInfo) + login.AuthenticateAndGetUnscopedToken(authInfo, skipTLS) }, } @@ -204,7 +206,10 @@ var tempAccessTokenCreateCmd = &cobra.Command{ if temporaryAccessTokenDurationSeconds < 900 || temporaryAccessTokenDurationSeconds > 86400 { return errors.New("fatal: token duration must be between 900 and 86400 seconds (15m and 24h)") } - accesstoken.CreateTemporaryAccessToken(temporaryAccessTokenDurationSeconds) + err := accesstoken.CreateTemporaryAccessToken(temporaryAccessTokenDurationSeconds) + if err != nil { + return err + } return nil }, } @@ -306,31 +311,25 @@ func Execute() { } } -//nolint:errcheck,funlen // error never occurs, setup has to be that lengthy +//nolint:funlen // setup has to be that lengthy func setupRootCmd() { RootCmd.AddCommand(loginCmd) + RootCmd.Flags().BoolVarP(&skipTLS, skipTLSFlag, skipTLSShortFlag, false, skipTLSUsage) loginCmd.AddCommand(loginIamCmd) loginIamCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) - loginIamCmd.MarkFlagRequired(usernameFlag) loginIamCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) - loginIamCmd.MarkFlagRequired(passwordFlag) loginIamCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - loginIamCmd.MarkFlagRequired(domainNameFlag) loginIamCmd.Flags().BoolVarP(&overwriteToken, overwriteTokenFlag, overwriteTokenShortFlag, false, overwriteTokenUsage) loginIamCmd.Flags().StringVarP(&totp, totpFlag, totpShortFlag, "", totpUsage) loginIamCmd.Flags().StringVarP(&userDomainID, userDomainIDFlag, "", "", userDomainIDUsage) loginIamCmd.MarkFlagsRequiredTogether(totpFlag, userDomainIDFlag) loginIamCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) - loginIamCmd.MarkFlagRequired(regionFlag) loginCmd.AddCommand(loginIdpSamlCmd) loginIdpSamlCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) - loginIdpSamlCmd.MarkFlagRequired(usernameFlag) loginIdpSamlCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) - loginIdpSamlCmd.MarkFlagRequired(passwordFlag) loginIdpSamlCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - loginIdpSamlCmd.MarkFlagRequired(domainNameFlag) loginIdpSamlCmd.Flags().BoolVarP( &overwriteToken, overwriteTokenFlag, @@ -339,19 +338,11 @@ func setupRootCmd() { overwriteTokenUsage, ) loginIdpSamlCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) - loginIdpSamlCmd.MarkPersistentFlagRequired(idpNameFlag) loginIdpSamlCmd.PersistentFlags().StringVarP(&idpURL, idpURLFlag, "", "", idpURLUsage) - loginIdpSamlCmd.MarkPersistentFlagRequired(idpURLFlag) loginIdpSamlCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) - loginIdpSamlCmd.MarkFlagRequired(regionFlag) loginCmd.AddCommand(loginIdpOidcCmd) - loginIdpOidcCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) - loginIdpOidcCmd.MarkFlagRequired(usernameFlag) - loginIdpOidcCmd.Flags().StringVarP(&password, passwordFlag, passwordShortFlag, "", passwordUsage) - loginIdpOidcCmd.MarkFlagRequired(passwordFlag) loginIdpOidcCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - loginIdpOidcCmd.MarkFlagRequired(domainNameFlag) loginIdpOidcCmd.Flags().BoolVarP( &overwriteToken, overwriteTokenFlag, @@ -360,30 +351,27 @@ func setupRootCmd() { overwriteTokenUsage, ) loginIdpOidcCmd.PersistentFlags().StringVarP(&idpName, idpNameFlag, idpNameShortFlag, "", idpNameUsage) - loginIdpOidcCmd.MarkPersistentFlagRequired(idpNameFlag) loginIdpOidcCmd.PersistentFlags().StringVarP(&idpURL, idpURLFlag, "", "", idpURLUsage) - loginIdpOidcCmd.MarkPersistentFlagRequired(idpURLFlag) loginIdpOidcCmd.Flags().StringVarP(®ion, regionFlag, regionShortFlag, "", regionUsage) - loginIdpOidcCmd.MarkFlagRequired(regionFlag) + loginIdpOidcCmd.Flags().StringVarP(&clientSecret, clientSecretFlag, clientSecretShortFlag, "", clientSecretUsage) + loginIdpOidcCmd.Flags().StringVarP(&clientID, clientIDFlag, clientIDShortFlag, "", clientIDUsage) + loginIdpOidcCmd.Flags().StringArrayVarP(&oidcScopes, oidcScopesFlag, oidcScopesShortFlag, + []string{"openid"}, oidcScopesUsage) loginCmd.AddCommand(loginRemoveCmd) loginRemoveCmd.Flags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - loginRemoveCmd.MarkFlagRequired(domainNameFlag) RootCmd.AddCommand(projectsCmd) projectsCmd.AddCommand(projectsListCmd) RootCmd.AddCommand(cceCmd) cceCmd.PersistentFlags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - cceCmd.MarkPersistentFlagRequired(domainNameFlag) cceCmd.PersistentFlags().StringVarP(&projectName, projectNameFlag, projectNameShortFlag, "", projectNameUsage) - cceCmd.MarkPersistentFlagRequired(projectNameFlag) cceCmd.AddCommand(cceListCmd) cceCmd.AddCommand(cceGetKubeConfigCmd) cceGetKubeConfigCmd.Flags().StringVarP(&clusterName, clusterNameFlag, clusterNameShortFlag, "", clusterNameUsage) - cceGetKubeConfigCmd.MarkFlagRequired(clusterNameFlag) cceGetKubeConfigCmd.Flags().IntVarP( &daysValid, daysValidFlag, @@ -391,7 +379,6 @@ func setupRootCmd() { daysValidDefaultValue, daysValidUsage, ) - cceGetKubeConfigCmd.MarkFlagRequired(daysValidFlag) cceGetKubeConfigCmd.Flags().StringVarP( &targetLocation, targetLocationFlag, @@ -399,25 +386,21 @@ func setupRootCmd() { "~/.kube/config", targetLocationUsage, ) - cceGetKubeConfigCmd.MarkFlagRequired(targetLocationFlag) RootCmd.AddCommand(tempAccessTokenCmd) tempAccessTokenCmd.PersistentFlags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - tempAccessTokenCmd.MarkPersistentFlagRequired(domainNameFlag) - tempAccessTokenCmd.AddCommand(tempAccessTokenCreateCmd) - tempAccessTokenCmd.Flags().IntVarP( + tempAccessTokenCreateCmd.Flags().IntVarP( &temporaryAccessTokenDurationSeconds, temporaryAccessTokenDurationSecondsFlag, temporaryAccessTokenDurationSecondsShortFlag, - 15*60, // default is 15 minutes + //nolint:gomnd // default key pair lifetime is 15 minutes + 15*60, temporaryAccessTokenDurationSecondsUsage, ) RootCmd.AddCommand(accessTokenCmd) accessTokenCmd.PersistentFlags().StringVarP(&domainName, domainNameFlag, domainNameShortFlag, "", domainNameUsage) - accessTokenCmd.MarkPersistentFlagRequired(domainNameFlag) - accessTokenCmd.AddCommand(accessTokenCreateCmd) accessTokenCreateCmd.Flags().StringVarP( &accessTokenCreateDescription, @@ -426,10 +409,8 @@ func setupRootCmd() { "Token by otc-auth", accessTokenDescriptionUsage, ) - accessTokenCreateCmd.MarkFlagRequired(accessTokenDescriptionFlag) accessTokenCmd.AddCommand(accessTokenListCmd) - accessTokenCmd.AddCommand(accessTokenDeleteCmd) accessTokenDeleteCmd.Flags().StringVarP( &token, @@ -438,7 +419,6 @@ func setupRootCmd() { "", accessTokenTokenUsage, ) - accessTokenDeleteCmd.MarkFlagRequired(accessTokenTokenFlag) RootCmd.AddCommand(openstackCmd) openstackCmd.AddCommand(openstackConfigCreateCmd) @@ -449,6 +429,31 @@ func setupRootCmd() { "~/.config/openstack/clouds.yaml", openstackConfigCreateConfigLocationUsage, ) + + cobra.CheckErr(errors.Join( + loginIamCmd.MarkFlagRequired(usernameFlag), + loginIamCmd.MarkFlagRequired(passwordFlag), + loginIamCmd.MarkFlagRequired(domainNameFlag), + loginIamCmd.MarkFlagRequired(regionFlag), + loginIdpSamlCmd.MarkFlagRequired(usernameFlag), + loginIdpSamlCmd.MarkFlagRequired(passwordFlag), + loginIdpSamlCmd.MarkFlagRequired(domainNameFlag), + loginIdpSamlCmd.MarkPersistentFlagRequired(idpNameFlag), + loginIdpSamlCmd.MarkFlagRequired(regionFlag), + loginIdpOidcCmd.MarkFlagRequired(domainNameFlag), + loginIdpSamlCmd.MarkPersistentFlagRequired(idpURLFlag), + loginIdpOidcCmd.MarkPersistentFlagRequired(idpNameFlag), + loginIdpOidcCmd.MarkPersistentFlagRequired(idpURLFlag), + loginIdpOidcCmd.MarkFlagRequired(regionFlag), + loginIdpOidcCmd.MarkFlagRequired(clientIDFlag), + loginRemoveCmd.MarkFlagRequired(domainNameFlag), + cceCmd.MarkPersistentFlagRequired(domainNameFlag), + cceCmd.MarkPersistentFlagRequired(projectNameFlag), + cceGetKubeConfigCmd.MarkFlagRequired(clusterNameFlag), + tempAccessTokenCmd.MarkPersistentFlagRequired(domainNameFlag), + accessTokenCmd.MarkPersistentFlagRequired(domainNameFlag), + accessTokenDeleteCmd.MarkFlagRequired(accessTokenTokenFlag), + )) } var ( @@ -469,6 +474,14 @@ var ( temporaryAccessTokenDurationSeconds int token string openStackConfigLocation string + skipTLS bool + clientSecret string + clientID string + oidcScopes []string + + rootFlagToEnv = map[string]string{ + skipTLSFlag: skipTLSEnv, + } loginIamFlagToEnv = map[string]string{ usernameFlag: usernameEnv, @@ -480,7 +493,17 @@ var ( regionFlag: regionEnv, } - loginIdpSamlOidcFlagToEnv = map[string]string{ + loginIdpSamlFlagToEnv = map[string]string{ + usernameFlag: usernameEnv, + passwordFlag: passwordEnv, + domainNameFlag: domainNameEnv, + userDomainIDFlag: userDomainIDEnv, + idpNameFlag: idpNameEnv, + idpURLFlag: idpURLEnv, + regionFlag: regionEnv, + } + + loginIdpOidcFlagToEnv = map[string]string{ usernameFlag: usernameEnv, passwordFlag: passwordEnv, domainNameFlag: domainNameEnv, @@ -488,6 +511,8 @@ var ( idpNameFlag: idpNameEnv, idpURLFlag: idpURLEnv, regionFlag: regionEnv, + clientIDFlag: clientIDEnv, + clientSecretFlag: clientSecretEnv, } loginRemoveFlagToEnv = map[string]string{ @@ -601,43 +626,62 @@ $ export AK_SK_TOKEN=YourToken $ otc-auth access-token delete $ otc-auth access-token delete --token YourToken --os-domain-name YourDomain` + //nolint:gosec // This example code does not actually contain credentials tempAccessTokenCreateCmdExample = `$ otc-auth temp-access-token create -t 900 -d YourDomainName # this creates a temp AK/SK which is 15 minutes valid (15 * 60 = 900) $ otc-auth temp-access-token create --duration-seconds 1800` openstackCmdHelp = "Manage Openstack Integration" openstackConfigCreateCmdHelp = "Creates new clouds.yaml" usernameFlag = "os-username" - usernameShortFlag = "u" - usernameEnv = "OS_USERNAME" - usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." - passwordFlag = "os-password" - passwordShortFlag = "p" - passwordEnv = "OS_PASSWORD" - passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." - domainNameFlag = "os-domain-name" - domainNameShortFlag = "d" - domainNameEnv = "OS_DOMAIN_NAME" - domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." - overwriteTokenFlag = "overwrite-token" - overwriteTokenShortFlag = "o" + skipTLSFlag = "skip-tls-verify" + + usernameShortFlag = "u" + skipTLSShortFlag = "" + usernameEnv = "OS_USERNAME" + usernameUsage = "Username for the OTC IAM system. Either provide this argument or set the environment variable " + usernameEnv + "." + skipTLSUsage = "Skip TLS Verification. This is insecure. Either provide this argument or set the environment variable " + skipTLSEnv + passwordFlag = "os-password" + passwordShortFlag = "p" + passwordEnv = "OS_PASSWORD" + passwordUsage = "Password for the OTC IAM system. Either provide this argument or set the environment variable " + passwordEnv + "." + domainNameFlag = "os-domain-name" + domainNameShortFlag = "d" + domainNameEnv = "OS_DOMAIN_NAME" + domainNameUsage = "OTC domain name. Either provide this argument or set the environment variable " + domainNameEnv + "." + overwriteTokenFlag = "overwrite-token" + overwriteTokenShortFlag = "o" //nolint:gosec // This is not a hardcoded credential but a help message with a filename inside - overwriteTokenUsage = "Overrides .otc-info file." - idpNameFlag = "idp-name" - idpNameShortFlag = "i" - idpNameEnv = "IDP_NAME" - idpNameUsage = "Required for authentication with IdP." - idpURLFlag = "idp-url" - idpURLEnv = "IDP_URL" - idpURLUsage = "Required for authentication with IdP." - totpFlag = "totp" - totpShortFlag = "t" - totpUsage = "6-digit time-based one-time password (TOTP) used for the MFA login flow. Required together with the user-domain-id." - userDomainIDFlag = "os-user-domain-id" - userDomainIDEnv = "OS_USER_DOMAIN_ID" - userDomainIDUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIDEnv + "." - regionFlag = "region" - regionShortFlag = "r" - regionEnv = "REGION" + overwriteTokenUsage = "Overrides .otc-info file." + idpNameFlag = "idp-name" + idpNameShortFlag = "i" + idpNameEnv = "IDP_NAME" + idpNameUsage = "Required for authentication with IdP." + idpURLFlag = "idp-url" + idpURLEnv = "IDP_URL" + idpURLUsage = "Required for authentication with IdP." + totpFlag = "totp" + totpShortFlag = "t" + totpUsage = "6-digit time-based one-time password (TOTP) used for the MFA login flow. Required together with the user-domain-id." + userDomainIDFlag = "os-user-domain-id" + userDomainIDEnv = "OS_USER_DOMAIN_ID" + userDomainIDUsage = "User Id number, can be obtained on the \"My Credentials page\" on the OTC. Required if --totp is provided. Either provide this argument or set the environment variable " + userDomainIDEnv + "." + regionFlag = "region" + regionShortFlag = "r" + regionEnv = "REGION" + skipTLSEnv = "SKIP_TLS_VERIFICATION" + oidcScopesEnv = "OIDC_SCOPES" + oidcScopesFlag = "oidc-scopes" + oidcScopesShortFlag = "" + oidcScopesUsage = "Flag to set the scopes which are expected from the OIDC request. Either provide this argument or set the environment variable " + oidcScopesEnv + + clientIDEnv = "CLIENT_ID" + clientIDFlag = "client-id" + clientIDShortFlag = "c" + clientIDUsage = "Client ID as set on the IdP. Either provide this argument or set the environment variable " + clientIDEnv + clientSecretEnv = "CLIENT_SECRET" + clientSecretFlag = "client-secret" + clientSecretShortFlag = "s" + clientSecretUsage = "Secret ID as set on the IdP. Either provide this argument or set the environment variable " + clientSecretEnv regionUsage = "OTC region code. Either provide this argument or set the environment variable " + regionEnv + "." projectNameFlag = "os-project-name" projectNameShortFlag = "p" diff --git a/common/http_client.go b/common/http_client.go index 3742e2f7..330327d0 100644 --- a/common/http_client.go +++ b/common/http_client.go @@ -1,6 +1,7 @@ package common import ( + "crypto/tls" "fmt" "io" "net/http" @@ -8,8 +9,12 @@ import ( "strconv" ) -func HTTPClientMakeRequest(request *http.Request) *http.Response { - httpClient := http.Client{} +func HTTPClientMakeRequest(request *http.Request, skipTLS bool) *http.Response { + tr := &http.Transport{ + //nolint:gosec // Needs to be explicitly set to true via a flag to skip TLS verification. + TLSClientConfig: &tls.Config{InsecureSkipVerify: skipTLS}, + } + httpClient := http.Client{Transport: tr} response, err := httpClient.Do(request) if err != nil { OutputErrorToConsoleAndExit(err, "fatal: error making a request %s") diff --git a/login/login.go b/login/login.go index 43dd0293..879177ef 100644 --- a/login/login.go +++ b/login/login.go @@ -15,7 +15,7 @@ const ( protocolOIDC = "oidc" ) -func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) { +func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo, skipTLS bool) { config.LoadCloudConfig(authInfo.DomainName) if config.IsAuthenticationValid() && !authInfo.OverwriteFile { @@ -32,9 +32,9 @@ func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) { case "idp": switch authInfo.AuthProtocol { case protocolSAML: - tokenResponse = saml.AuthenticateAndGetUnscopedToken(authInfo) + tokenResponse = saml.AuthenticateAndGetUnscopedToken(authInfo, skipTLS) case protocolOIDC: - tokenResponse = oidc.AuthenticateAndGetUnscopedToken(authInfo) + tokenResponse = oidc.AuthenticateAndGetUnscopedToken(authInfo, skipTLS) default: common.OutputErrorMessageToConsoleAndExit( "fatal: unsupported login protocol.\n\nAllowed values are \"saml\" or \"oidc\". " + diff --git a/oidc/oidc.go b/oidc/oidc.go index 73ab0f32..8c884e0a 100644 --- a/oidc/oidc.go +++ b/oidc/oidc.go @@ -12,19 +12,19 @@ import ( "github.com/go-http-utils/headers" ) -func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) common.TokenResponse { +func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo, skipTLS bool) common.TokenResponse { var oidcCredentials common.OidcCredentialsResponse if authInfo.IsServiceAccount { - oidcCredentials = authenticateServiceAccountWithIdp(authInfo) + oidcCredentials = authenticateServiceAccountWithIdp(authInfo, skipTLS) } else { oidcCredentials = authenticateWithIdp(authInfo) } - return authenticateWithServiceProvider(oidcCredentials, authInfo) + return authenticateWithServiceProvider(oidcCredentials, authInfo, skipTLS) } //nolint:lll // This function will be removed soon -func authenticateWithServiceProvider(oidcCredentials common.OidcCredentialsResponse, authInfo common.AuthInfo) common.TokenResponse { +func authenticateWithServiceProvider(oidcCredentials common.OidcCredentialsResponse, authInfo common.AuthInfo, skipTLS bool) common.TokenResponse { var tokenResponse common.TokenResponse url := endpoints.IdentityProviders(authInfo.IdpName, authInfo.AuthProtocol, authInfo.Region) @@ -37,7 +37,7 @@ func authenticateWithServiceProvider(oidcCredentials common.OidcCredentialsRespo headers.Authorization, oidcCredentials.BearerToken, ) - response := common.HTTPClientMakeRequest(request) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon + response := common.HTTPClientMakeRequest(request, skipTLS) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon tokenResponse = common.GetCloudCredentialsFromResponseOrThrow(response) tokenResponse.Token.User.Name = oidcCredentials.Claims.PreferredUsername diff --git a/oidc/service_account.go b/oidc/service_account.go index 8abc12d5..b8a43704 100644 --- a/oidc/service_account.go +++ b/oidc/service_account.go @@ -33,13 +33,13 @@ type ServiceAccountResponse struct { Scope string `json:"scope"` } -func authenticateServiceAccountWithIdp(params common.AuthInfo) common.OidcCredentialsResponse { +func authenticateServiceAccountWithIdp(params common.AuthInfo, skipTLS bool) common.OidcCredentialsResponse { idpTokenURL, err := url.JoinPath(params.IdpURL, "protocol/openid-connect/token") if err != nil { common.OutputErrorToConsoleAndExit(err) } request := createServiceAccountAuthenticateRequest(idpTokenURL, params.ClientID, params.ClientSecret) - response := common.HTTPClientMakeRequest(request) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon + response := common.HTTPClientMakeRequest(request, skipTLS) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon bodyBytes := common.GetBodyBytesFromResponse(response) var result ServiceAccountResponse diff --git a/saml/saml.go b/saml/saml.go index 348ed03b..b38f18da 100644 --- a/saml/saml.go +++ b/saml/saml.go @@ -14,10 +14,10 @@ import ( "github.com/go-http-utils/headers" ) -func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) (tokenResponse common.TokenResponse) { - spInitiatedRequest := getServiceProviderInitiatedRequest(authInfo) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon +func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo, skipTLS bool) (tokenResponse common.TokenResponse) { + spInitiatedRequest := getServiceProviderInitiatedRequest(authInfo, skipTLS) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon - bodyBytes := authenticateWithIdp(authInfo, spInitiatedRequest) + bodyBytes := authenticateWithIdp(authInfo, spInitiatedRequest, skipTLS) assertionResult := common.SamlAssertionResponse{} @@ -26,7 +26,7 @@ func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) (tokenResponse co common.OutputErrorToConsoleAndExit(err, "fatal: error deserializing xml.\ntrace: %s") } - response := validateAuthenticationWithServiceProvider(assertionResult, bodyBytes) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon + response := validateAuthenticationWithServiceProvider(assertionResult, bodyBytes, skipTLS) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon tokenResponse = common.GetCloudCredentialsFromResponseOrThrow(response) defer func(Body io.ReadCloser) { @@ -39,29 +39,29 @@ func AuthenticateAndGetUnscopedToken(authInfo common.AuthInfo) (tokenResponse co return tokenResponse } -func getServiceProviderInitiatedRequest(params common.AuthInfo) *http.Response { +func getServiceProviderInitiatedRequest(params common.AuthInfo, skipTLS bool) *http.Response { request := common.GetRequest(http.MethodGet, endpoints.IdentityProviders(params.IdpName, params.AuthProtocol, params.Region), nil) request.Header.Add(headers.Accept, headervalues.ApplicationPaos) request.Header.Add(header.Paos, headervalues.Paos) - return common.HTTPClientMakeRequest(request) + return common.HTTPClientMakeRequest(request, skipTLS) } -func authenticateWithIdp(params common.AuthInfo, samlResponse *http.Response) []byte { +func authenticateWithIdp(params common.AuthInfo, samlResponse *http.Response, skipTLS bool) []byte { request := common.GetRequest(http.MethodPost, params.IdpURL, samlResponse.Body) request.Header.Add(headers.ContentType, headervalues.TextXML) request.SetBasicAuth(params.Username, params.Password) - response := common.HTTPClientMakeRequest(request) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon + response := common.HTTPClientMakeRequest(request, skipTLS) //nolint:bodyclose,lll // Works fine for now, this method will be replaced soon return common.GetBodyBytesFromResponse(response) } //nolint:lll // This function will be removed soon -func validateAuthenticationWithServiceProvider(assertionResult common.SamlAssertionResponse, responseBodyBytes []byte) *http.Response { +func validateAuthenticationWithServiceProvider(assertionResult common.SamlAssertionResponse, responseBodyBytes []byte, skipTLS bool) *http.Response { request := common.GetRequest(http.MethodPost, assertionResult.Header.Response.AssertionConsumerServiceURL, bytes.NewReader(responseBodyBytes)) request.Header.Add(headers.ContentType, headervalues.ApplicationPaos) - return common.HTTPClientMakeRequest(request) + return common.HTTPClientMakeRequest(request, skipTLS) } From 42f8a925b0adc41c06d874e3cc94f3a016fe93a3 Mon Sep 17 00:00:00 2001 From: Mweya Ruider Date: Wed, 23 Aug 2023 15:40:12 +0200 Subject: [PATCH 16/16] Review Don't remove binaries after building them with goreleaser, actually register skip-tls-verification option --- .github/workflows/release.yml | 2 +- README.md | 93 ++++++++++++++++++++++------------- cmd/root.go | 4 +- 3 files changed, 63 insertions(+), 36 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d2baa17..72f8e0a9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,7 +47,7 @@ jobs: uses: goreleaser/goreleaser-action@v3 with: version: latest - args: release + args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NOTARYTOOL_PASS: ${{ secrets.NOTARYTOOL_PASS }} diff --git a/README.md b/README.md index c47a98b0..2f7e7111 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,12 @@ Open Source CLI for the Authorization with the Open Telekom Cloud. ![CodeQL](https://github.com/iits-consulting/otc-auth/workflows/CodeQL/badge.svg) ![ViewCount](https://views.whatilearened.today/views/github/iits-consulting/otc-auth.svg) -With this CLI you can log in to the OTC through its Identity Access Manager (IAM) or through an external Identity Provider (IdP) in order to get an unscoped token. The allowed protocols for IdP login are SAML and OIDC. When logging in directly with Telekom's IAM it is also possible to use Multi-Factor Authentication (MFA) in the process. +With this CLI you can log in to the OTC through its Identity Access Manager (IAM) or through an external Identity +Provider (IdP) in order to get an unscoped token. The allowed protocols for IdP login are SAML and OIDC. When logging in +directly with Telekom's IAM it is also possible to use Multi-Factor Authentication (MFA) in the process. -After you have retrieved an unscoped token, you can use it to get a list of the clusters in a project from the Cloud Container Engine (CCE) and also get the remote kube config file and merge with your local file. +After you have retrieved an unscoped token, you can use it to get a list of the clusters in a project from the Cloud +Container Engine (CCE) and also get the remote kube config file and merge with your local file. This tool can also be used to manage (create) a pair of Access Key/ Secret Key in order to make requests more secure. @@ -20,7 +23,8 @@ https://user-images.githubusercontent.com/19291722/208880256-b0da924e-254e-4bc4- ## Install -You can download the binary for your system in the [releases page](https://github.com/iits-consulting/otc-auth/releases). +You can download the binary for your system in +the [releases page](https://github.com/iits-consulting/otc-auth/releases). Unpack the binary and add it to your PATH and you are good to go! ### Arch Linux @@ -29,29 +33,38 @@ Users of Arch Linux may use the package published in the [AUR](https://aur.archl ## Login -Use the `login` command to retrieve an unscoped token either by logging in directly with the Service Provider or through an IdP. You can see the help page by entering `login --help` or `login -h`. There are three log in options (`iam`, `idp-saml`, and `idp-oidc`) and one of them must be provided. +Use the `login` command to retrieve an unscoped token either by logging in directly with the Service Provider or through +an IdP. You can see the help page by entering `login --help` or `login -h`. There are three log in +options (`iam`, `idp-saml`, and `idp-oidc`) and one of them must be provided. ### Service Provider Login (IAM) -To log in directly with the Open Telekom Cloud's IAM, you will have to supply the domain name you're attempting to log in to (usually starting with "OTC-EU", following the region and a longer identifier), your username and password. +To log in directly with the Open Telekom Cloud's IAM, you will have to supply the domain name you're attempting to log +in to (usually starting with "OTC-EU", following the region and a longer identifier), your username and password. `otc-auth login iam --os-username --os-password --os-domain-name --region ` -In addition, it is possible to use MFA if that's desired and/or required. In this case both arguments `--os-user-domain-id` and `--totp` are required. The user id can be obtained in the "My Credentials" page on the OTC. +In addition, it is possible to use MFA if that's desired and/or required. In this case both +arguments `--os-user-domain-id` and `--totp` are required. The user id can be obtained in the "My Credentials" page on +the OTC. ``` otc-auth login iam --os-username --os-password --os-domain-name --os-user-domain-id --totp <6_digit_token> --region ``` -The OTP Token is 6-digit long and refreshes every 30 seconds. For more information on MFA please refer to the [OTC's documentation](https://docs.otc.t-systems.com/en-us/usermanual/iam/iam_10_0002.html). +The OTP Token is 6-digit long and refreshes every 30 seconds. For more information on MFA please refer to +the [OTC's documentation](https://docs.otc.t-systems.com/en-us/usermanual/iam/iam_10_0002.html). ### Identity Provider Login (IdP) -You can log in with an external IdP using either the `saml` or the `oidc` protocols. In both cases you will need to specify the authorization URL, the name of the Identity Provider (as set on the OTC), as well as username and password for the SAML login and client id (and optionally client secret) for the OIDC login flow. +You can log in with an external IdP using either the `saml` or the `oidc` protocols. In both cases you will need to +specify the authorization URL, the name of the Identity Provider (as set on the OTC), as well as username and password +for the SAML login and client id (and optionally client secret) for the OIDC login flow. #### External IdP and SAML -The SAML login flow is SP initiated and requires you to send username and password to the SP. The SP then authorizes you with the configured IdP and returns either an unscoped token or an error, if the user is not allowed to log in. +The SAML login flow is SP initiated and requires you to send username and password to the SP. The SP then authorizes you +with the configured IdP and returns either an unscoped token or an error, if the user is not allowed to log in. `otc-auth login idp-saml --os-username --os-password --idp-name --idp-url --os-domain-name --region ` @@ -59,7 +72,10 @@ At the moment, no MFA is supported for this login flow. #### External IdP and OIDC -The OIDC login flow is user initiated and will open a browser window with the IdP's authorization URL for the user to log in as desired. This flow does support MFA (this requires it to be configured on the IdP). After being successfully authenticated with the IdP, the SP will be contacted with the corresponding credentials and will return either an unscoped token or an error, if the user is not allowed to log in. +The OIDC login flow is user initiated and will open a browser window with the IdP's authorization URL for the user to +log in as desired. This flow does support MFA (this requires it to be configured on the IdP). After being successfully +authenticated with the IdP, the SP will be contacted with the corresponding credentials and will return either an +unscoped token or an error, if the user is not allowed to log in. `otc-auth login idp-oidc --idp-name --idp-url --client-id --os-domain-name --region [--client-secret ]` @@ -67,7 +83,9 @@ The argument `--client-id` is required, but the argument `--client-secret` is on #### Service Account via external IdP and OIDC -If you have set up your IdP to provide service accounts then you can utilize service account with `otc-auth` too. Make also sure that the IdP is correctly configured in the OTC Identity and Access Management. Then run the `otc-auth` as follows: +If you have set up your IdP to provide service accounts then you can utilize service account with `otc-auth` too. Make +also sure that the IdP is correctly configured in the OTC Identity and Access Management. Then run the `otc-auth` as +follows: ```shell otc-auth login idp-oidc \ @@ -82,7 +100,8 @@ otc-auth login idp-oidc \ ### OIDC Scopes -The OIDC scopes can be configured if required. To do so simply provide one of the following two when logging in with `idp-oidc`: +The OIDC scopes can be configured if required. To do so simply provide one of the following two when logging in +with `idp-oidc`: - provide the flag `--oidc-scopes pleasePut,HereAll,YourScopes,WhichYouNeed` - provide the environment variable `export OIDC_SCOPES="pleasePut,HereAll,YourScopes,WhichYouNeed"` @@ -103,9 +122,11 @@ It is possible to get a list of all projects in the current cloud. For that, use ## Cloud Container Engine -Use the `cce` command to retrieve a list of available clusters in your project and/or get the remote kube configuration file. You can see the help page by entering `cce --help` or `cce -h`. +Use the `cce` command to retrieve a list of available clusters in your project and/or get the remote kube configuration +file. You can see the help page by entering `cce --help` or `cce -h`. -To retrieve a list of clusters for a project use the following command. The project name will be checked against the ones in the cloud at the moment of the request. +To retrieve a list of clusters for a project use the following command. The project name will be checked against the +ones in the cloud at the moment of the request. If the desired project isn't found, you will receive an error message. `otc-auth cce list --os-domain-name --region --os-project-name ` @@ -114,11 +135,13 @@ To retrieve the remote kube configuration file (and merge to your local one) use `otc-auth cce get-kube-config --os-domain-name --region --os-project-name --cluster ` -Alternatively you can pass the argument `--days-valid` to set the period of days the configuration will be valid, the default is 7 days. +Alternatively you can pass the argument `--days-valid` to set the period of days the configuration will be valid, the +default is 7 days. ## Manage Access Key and Secret Key Pair -You can use the OTC-Auth tool to download the AK/SK pair directly from the OTC. It will download the "ak-sk-env.sh" file to the current directory. The file contains four environment variables. +You can use the OTC-Auth tool to download the AK/SK pair directly from the OTC. It will download the "ak-sk-env.sh" file +to the current directory. The file contains four environment variables. `otc-auth access-token create --os-domain-name --region ` @@ -133,27 +156,31 @@ If you execute this command `otc-auth openstack config-create` -It will create a cloud config for every project which you have access to and generate a scoped token. After that it overrides +It will create a cloud config for every project which you have access to and generate a scoped token. After that it +overrides the clouds.yaml (by default: ~/.config/openstack/clouds.yaml) file. ## Environment Variables -The OTC-Auth tool also provides environment variables for all the required arguments. For the sake of compatibility, they are aligned with the Open Stack environment variables (starting with OS). - -| Environment Variable | Argument | Short | Description | -| -------------------- | --------------------- | :---: | --------------------------------------------- | -| CLIENT_ID | `--client-id` | `c` | Client id as configured on the IdP | -| CLIENT_SECRET | `--client-secret` | `s` | Client secret as configured on the IdP | -| CLUSTER_NAME | `--cluster` | `c` | Cluster name on the OTC | -| OS_DOMAIN_NAME | `--os-domain-name` | `d` | Domain Name from OTC Tenant | -| REGION | `--region` | `r` | Region code for the cloud (eu-de for example) | -| OS_PASSWORD | `--os-password` | `p` | Password (iam or idp) | -| OS_PROJECT_NAME | `--os-project-name` | `p` | Project name on the OTC | -| OS_USER_DOMAIN_ID | `--os-user-domain-id` | `i` | User id from OTC Tenant | -| OS_USERNAME | `--os-username` | `u` | Username (iam or idp) | -| IDP_NAME | `--idp-name` | `i` | Identity Provider name (as configured on OTC) | -| IDP_URL | `--idp-url` | N/A | Authorization endpoint on the IDP | +The OTC-Auth tool also provides environment variables for all the required arguments. For the sake of compatibility, +they are aligned with the Open Stack environment variables (starting with OS). + +| Environment Variable | Argument | Short | Description | +|-----------------------|---------------------------|:-----:|-----------------------------------------------| +| CLIENT_ID | `--client-id` | `c` | Client id as configured on the IdP | +| CLIENT_SECRET | `--client-secret` | `s` | Client secret as configured on the IdP | +| CLUSTER_NAME | `--cluster` | `c` | Cluster name on the OTC | +| OS_DOMAIN_NAME | `--os-domain-name` | `d` | Domain Name from OTC Tenant | +| REGION | `--region` | `r` | Region code for the cloud (eu-de for example) | +| OS_PASSWORD | `--os-password` | `p` | Password (iam or idp) | +| OS_PROJECT_NAME | `--os-project-name` | `p` | Project name on the OTC | +| OS_USER_DOMAIN_ID | `--os-user-domain-id` | `i` | User id from OTC Tenant | +| OS_USERNAME | `--os-username` | `u` | Username (iam or idp) | +| IDP_NAME | `--idp-name` | `i` | Identity Provider name (as configured on OTC) | +| IDP_URL | `--idp-url` | N/A | Authorization endpoint on the IDP | +| SKIP_TLS_VERIFICATION | `--skip-tls-verification` | N/A | Skips TLS Verification | ## Auto-Completions -You install the auto completions for your shell by running. Please follow the instructions by running `otc-auth completion --help` in your terminal. +You install the auto completions for your shell by running. Please follow the instructions by +running `otc-auth completion --help` in your terminal. diff --git a/cmd/root.go b/cmd/root.go index e69fd00e..a3966724 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -314,7 +314,7 @@ func Execute() { //nolint:funlen // setup has to be that lengthy func setupRootCmd() { RootCmd.AddCommand(loginCmd) - RootCmd.Flags().BoolVarP(&skipTLS, skipTLSFlag, skipTLSShortFlag, false, skipTLSUsage) + RootCmd.PersistentFlags().BoolVarP(&skipTLS, skipTLSFlag, skipTLSShortFlag, false, skipTLSUsage) loginCmd.AddCommand(loginIamCmd) loginIamCmd.Flags().StringVarP(&username, usernameFlag, usernameShortFlag, "", usernameUsage) @@ -633,7 +633,7 @@ $ otc-auth access-token delete --token YourToken --os-domain-name YourDomain` openstackCmdHelp = "Manage Openstack Integration" openstackConfigCreateCmdHelp = "Creates new clouds.yaml" usernameFlag = "os-username" - skipTLSFlag = "skip-tls-verify" + skipTLSFlag = "skip-tls-verification" usernameShortFlag = "u" skipTLSShortFlag = ""