From f922cccf603573de0358c231af3ac80aa21aee7c Mon Sep 17 00:00:00 2001 From: Mike Mondragon Date: Fri, 3 Jan 2025 14:46:03 -0800 Subject: [PATCH 1/2] Toggle User-Agent to be simple "okta-aws-cli" with global flag `--short-user-agent` Closes #248 --- README.md | 2 ++ cmd/root/root.go | 7 ++++++ internal/config/config.go | 39 ++++++++++++++++++++++++++++--- internal/m2mauth/m2mauth.go | 2 +- internal/webssoauth/webssoauth.go | 12 +++++----- 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8da7bb7..52a14ee 100644 --- a/README.md +++ b/README.md @@ -382,6 +382,8 @@ These global settings are optional unless marked otherwise: | Verbosely print all API calls/responses to the screen | `true` if flag is present | `--debug-api-calls` | `OKTA_AWSCLI_DEBUG_API_CALLS=true` | | HTTP/HTTPS Proxy support | HTTP/HTTPS URL of proxy service (based on golang [net/http/httpproxy](https://pkg.go.dev/golang.org/x/net/http/httpproxy) package) | n/a | `HTTP_PROXY` or `HTTPS_PROXY` | | Execute arguments after CLI arg terminator `--` as a separate process. Process will be executed with AWS cred values as AWS env vars `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`. | `true` if flag is present | `--exec` | `OKTA_AWSCLI_EXEC=true` | +| Short user agent. HTTP requests made to the Okta API have user-agent set to `okta-aws-cli` allowing for a simple UA value in a policy rule. | `true` if flag is present | `--short-user-agent` | `OKTA_AWSCLI_SHORT_USER_AGENT=true` | + ### Web command settings diff --git a/cmd/root/root.go b/cmd/root/root.go index 5394197..df4c8d0 100644 --- a/cmd/root/root.go +++ b/cmd/root/root.go @@ -150,6 +150,13 @@ func init() { Usage: "Execute any shell commands after the '--' CLI arguments termination", EnvVar: config.ExecEnvVar, }, + { + Name: config.ShortUserAgentFlag, + Short: "y", + Value: false, + Usage: "Set CLI's User-Agent header to okta-aws-cli so it can be used in a policy rule", + EnvVar: config.ShortUserAgentEnvVar, + }, } rootCmd = NewRootCommand() diff --git a/internal/config/config.go b/internal/config/config.go index c518dca..8e9dd23 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -31,11 +31,14 @@ import ( "gopkg.in/yaml.v2" ) -// UserAgentValue the user agent value -var UserAgentValue string +// longUserAgent the long user agent value +var longUserAgent string + +// shortUserAgent the short user agent value +var shortUserAgent = "okta-aws-cli" func init() { - UserAgentValue = fmt.Sprintf("okta-aws-cli/%s (%s; %s; %s)", Version, runtime.Version(), runtime.GOOS, runtime.GOARCH) + longUserAgent = fmt.Sprintf("okta-aws-cli/%s (%s; %s; %s)", Version, runtime.Version(), runtime.GOOS, runtime.GOARCH) } const ( @@ -105,6 +108,8 @@ const ( QRCodeFlag = "qr-code" // SessionDurationFlag cli flag const SessionDurationFlag = "session-duration" + // ShortUserAgentFlag cli flag const + ShortUserAgentFlag = "short-user-agent" // WriteAWSCredentialsFlag cli flag const WriteAWSCredentialsFlag = "write-aws-credentials" // LegacyAWSVariablesFlag cli flag const @@ -174,6 +179,8 @@ const ( ProfileEnvVar = "OKTA_AWSCLI_PROFILE" // QRCodeEnvVar env var const QRCodeEnvVar = "OKTA_AWSCLI_QR_CODE" + // ShortUserAgentEnvVar env var const + ShortUserAgentEnvVar = "OKTA_AWSCLI_DEBUG_SHORT_USER_AGENT" // WriteAWSCredentialsEnvVar env var const WriteAWSCredentialsEnvVar = "OKTA_AWSCLI_WRITE_AWS_CREDENTIALS" @@ -269,6 +276,7 @@ type Config struct { privateKeyFile string profile string qrCode bool + shortUserAgent bool writeAWSCredentials bool clock Clock } @@ -300,6 +308,7 @@ type Attributes struct { PrivateKeyFile string Profile string QRCode bool + ShortUserAgent bool WriteAWSCredentials bool } @@ -344,6 +353,7 @@ func NewConfig(attrs *Attributes) (*Config, error) { privateKeyFile: attrs.PrivateKeyFile, profile: attrs.Profile, qrCode: attrs.QRCode, + shortUserAgent: attrs.ShortUserAgent, writeAWSCredentials: attrs.WriteAWSCredentials, } err = cfg.SetOrgDomain(attrs.OrgDomain) @@ -458,6 +468,7 @@ func readConfig() (Attributes, error) { KeyID: viper.GetString(getFlagNameFromProfile(awsProfile, KeyIDFlag)), Profile: awsProfile, QRCode: viper.GetBool(getFlagNameFromProfile(awsProfile, QRCodeFlag)), + ShortUserAgent: viper.GetBool(getFlagNameFromProfile(awsProfile, ShortUserAgentFlag)), WriteAWSCredentials: viper.GetBool(getFlagNameFromProfile(awsProfile, WriteAWSCredentialsFlag)), } if attrs.Format == "" { @@ -590,6 +601,9 @@ func readConfig() (Attributes, error) { if !attrs.CacheAccessToken { attrs.CacheAccessToken = viper.GetBool(downCase(CacheAccessTokenEnvVar)) } + if !attrs.ShortUserAgent { + attrs.ShortUserAgent = viper.GetBool(downCase(ShortUserAgentEnvVar)) + } if !attrs.Exec { attrs.Exec = viper.GetBool(downCase(ExecEnvVar)) } @@ -908,6 +922,25 @@ func (c *Config) SetQRCode(qrCode bool) error { return nil } +// ShortUserAgent -- +func (c *Config) ShortUserAgent() bool { + return c.shortUserAgent +} + +// SetDebugAPICalls -- +func (c *Config) SetShortUserAgent(shortUserAgent bool) error { + c.shortUserAgent = shortUserAgent + return nil +} + +// UserAgent the user agent value +func (c *Config) UserAgent() string { + if c.shortUserAgent { + return shortUserAgent + } + return longUserAgent +} + // OktaConfigPath returns OS specific path to the okta config file, for example // $HOME/.okta/okta.yaml func OktaConfigPath() (path string, err error) { diff --git a/internal/m2mauth/m2mauth.go b/internal/m2mauth/m2mauth.go index 5840a3e..6e17240 100644 --- a/internal/m2mauth/m2mauth.go +++ b/internal/m2mauth/m2mauth.go @@ -236,7 +236,7 @@ func (m *M2MAuthentication) accessToken() (*okta.AccessToken, error) { } req.Header.Add("Accept", utils.ApplicationJSON) req.Header.Add(utils.ContentType, utils.ApplicationXFORM) - req.Header.Add(utils.UserAgentHeader, config.UserAgentValue) + req.Header.Add(utils.UserAgentHeader, m.config.UserAgent()) req.Header.Add(utils.XOktaAWSCLIOperationHeader, utils.XOktaAWSCLIM2MOperation) resp, err := m.config.HTTPClient().Do(req) if err != nil { diff --git a/internal/webssoauth/webssoauth.go b/internal/webssoauth/webssoauth.go index 77a58cf..8a42fb7 100644 --- a/internal/webssoauth/webssoauth.go +++ b/internal/webssoauth/webssoauth.go @@ -652,7 +652,7 @@ func (w *WebSSOAuthentication) fetchSAMLAssertion(at *okta.AccessToken) (asserti return assertion, err } req.Header.Add(accept, "text/html") - req.Header.Add(utils.UserAgentHeader, config.UserAgentValue) + req.Header.Add(utils.UserAgentHeader, w.config.UserAgent()) req.Header.Add(utils.XOktaAWSCLIOperationHeader, utils.XOktaAWSCLIWebOperation) resp, err := w.config.HTTPClient().Do(req) @@ -695,7 +695,7 @@ func (w *WebSSOAuthentication) fetchSSOWebToken(clientID, awsFedAppID string, at } req.Header.Add(accept, utils.ApplicationJSON) req.Header.Add(utils.ContentType, utils.ApplicationXFORM) - req.Header.Add(utils.UserAgentHeader, config.UserAgentValue) + req.Header.Add(utils.UserAgentHeader, w.config.UserAgent()) req.Header.Add(utils.XOktaAWSCLIOperationHeader, utils.XOktaAWSCLIWebOperation) resp, err := w.config.HTTPClient().Do(req) @@ -777,7 +777,7 @@ func (w *WebSSOAuthentication) listFedAppsFromAppLinks(clientID string, at *okta headers := map[string]string{ accept: utils.ApplicationJSON, utils.ContentType: utils.ApplicationJSON, - utils.UserAgentHeader: config.UserAgentValue, + utils.UserAgentHeader: w.config.UserAgent(), utils.XOktaAWSCLIOperationHeader: utils.XOktaAWSCLIWebOperation, "Authorization": fmt.Sprintf("%s %s", at.TokenType, at.AccessToken), } @@ -824,7 +824,7 @@ func (w *WebSSOAuthentication) accessToken(deviceAuth *okta.DeviceAuthorization) } req.Header.Add(accept, utils.ApplicationJSON) req.Header.Add(utils.ContentType, utils.ApplicationXFORM) - req.Header.Add(utils.UserAgentHeader, config.UserAgentValue) + req.Header.Add(utils.UserAgentHeader, w.config.UserAgent()) req.Header.Add(utils.XOktaAWSCLIOperationHeader, utils.XOktaAWSCLIWebOperation) var bodyBytes []byte @@ -896,7 +896,7 @@ func (w *WebSSOAuthentication) authorize() (*okta.DeviceAuthorization, error) { } req.Header.Add(accept, utils.ApplicationJSON) req.Header.Add(utils.ContentType, utils.ApplicationXFORM) - req.Header.Add(utils.UserAgentHeader, config.UserAgentValue) + req.Header.Add(utils.UserAgentHeader, w.config.UserAgent()) req.Header.Add(utils.XOktaAWSCLIOperationHeader, utils.XOktaAWSCLIWebOperation) resp, err := w.config.HTTPClient().Do(req) @@ -1010,7 +1010,7 @@ func (w *WebSSOAuthentication) isClassicOrg() bool { return false } req.Header.Add(accept, utils.ApplicationJSON) - req.Header.Add(utils.UserAgentHeader, config.UserAgentValue) + req.Header.Add(utils.UserAgentHeader, w.config.UserAgent()) req.Header.Add(utils.XOktaAWSCLIOperationHeader, utils.XOktaAWSCLIWebOperation) resp, err := w.config.HTTPClient().Do(req) From d8663f1a6874abc08c577b07b09ed9d51b9c0fbc Mon Sep 17 00:00:00 2001 From: Mike Mondragon Date: Mon, 6 Jan 2025 08:16:34 -0800 Subject: [PATCH 2/2] Update qc --- go.sum | 2 ++ internal/config/config.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.sum b/go.sum index fc8bc87..b4167c6 100644 --- a/go.sum +++ b/go.sum @@ -435,6 +435,8 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/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.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 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= diff --git a/internal/config/config.go b/internal/config/config.go index 8e9dd23..eb1e7b6 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -927,7 +927,7 @@ func (c *Config) ShortUserAgent() bool { return c.shortUserAgent } -// SetDebugAPICalls -- +// SetShortUserAgent -- func (c *Config) SetShortUserAgent(shortUserAgent bool) error { c.shortUserAgent = shortUserAgent return nil