From 0c1dbdfa05c55fada2e4b5f669e9c62fcb0fc11f Mon Sep 17 00:00:00 2001 From: Victor Kareh Date: Thu, 19 May 2022 10:30:30 -0400 Subject: [PATCH] fedramp: Add GovCloud configuration To allow users to login against the development FedRAMP GovCloud environment, we add a way of tracking the various APIs and AWS Cognito user pool and client data. --- cmd/login/cmd.go | 123 +++++++++++++++++++++++++++--------------- go.sum | 27 ++++++++++ pkg/fedramp/config.go | 59 ++++++++++++++++++++ pkg/fedramp/flag.go | 46 ++++++++++++++++ pkg/fedramp/token.go | 40 ++++++++++++++ pkg/ocm/client.go | 3 +- pkg/ocm/config.go | 34 ++++++++++-- 7 files changed, 283 insertions(+), 49 deletions(-) create mode 100644 pkg/fedramp/config.go create mode 100644 pkg/fedramp/flag.go create mode 100644 pkg/fedramp/token.go diff --git a/cmd/login/cmd.go b/cmd/login/cmd.go index 102f642c8e..09682e8f04 100644 --- a/cmd/login/cmd.go +++ b/cmd/login/cmd.go @@ -26,6 +26,7 @@ import ( "github.com/spf13/cobra" "github.com/openshift/rosa/cmd/logout" + "github.com/openshift/rosa/pkg/fedramp" "github.com/openshift/rosa/pkg/interactive" "github.com/openshift/rosa/pkg/logging" "github.com/openshift/rosa/pkg/ocm" @@ -33,7 +34,7 @@ import ( ) // #nosec G101 -const uiTokenPage = "https://console.redhat.com/openshift/token/rosa" +var uiTokenPage string = "https://console.redhat.com/openshift/token/rosa" var reAttempt bool @@ -58,9 +59,8 @@ var Cmd = &cobra.Command{ "\t3. Environment variable (OCM_TOKEN)\n"+ "\t4. Configuration file\n"+ "\t5. Command-line prompt\n", uiTokenPage), - Example: " # Login to the OpenShift API with an existing token generated from " + - `https://console.redhat.com/openshift/token/rosa - rosa login --token=$OFFLINE_ACCESS_TOKEN`, + Example: fmt.Sprintf(` # Login to the OpenShift API with an existing token generated from %s + rosa login --token=$OFFLINE_ACCESS_TOKEN`, uiTokenPage), Run: run, } @@ -110,7 +110,7 @@ func init() { "token", "t", "", - "Access or refresh token generated from https://console.redhat.com/openshift/token/rosa.", + fmt.Sprintf("Access or refresh token generated from %s.", uiTokenPage), ) flags.BoolVar( &args.insecure, @@ -119,6 +119,7 @@ func init() { "Enables insecure communication with the server. This disables verification of TLS "+ "certificates and host names.", ) + fedramp.AddFlag(flags) } func run(cmd *cobra.Command, argv []string) { @@ -126,7 +127,8 @@ func run(cmd *cobra.Command, argv []string) { logger := logging.CreateLoggerOrExit(reporter) // Check mandatory options: - if args.env == "" { + env := args.env + if env == "" { reporter.Errorf("Option '--env' is mandatory") os.Exit(1) } @@ -142,10 +144,23 @@ func run(cmd *cobra.Command, argv []string) { } token := args.token + + if fedramp.Enabled() { + cfg.FedRAMP = true + } else if cfg.FedRAMP && token == "" { + fedramp.Enable() + cfg.FedRAMP = true + } else if fedramp.IsCognitoToken(token) { + fedramp.Enable() + cfg.FedRAMP = true + } else { + cfg.FedRAMP = false + } + haveReqs := token != "" // Verify environment variables: - if !haveReqs && !reAttempt { + if !haveReqs && !reAttempt && !fedramp.Enabled() { token = os.Getenv("ROSA_TOKEN") if token == "" { token = os.Getenv("OCM_TOKEN") @@ -163,6 +178,10 @@ func run(cmd *cobra.Command, argv []string) { haveReqs = armed } + if fedramp.Enabled() { + uiTokenPage = fedramp.TokenPage[env] + } + // Prompt the user for token: if !haveReqs { fmt.Println("To login to your Red Hat account, get an offline access token at", uiTokenPage) @@ -182,6 +201,41 @@ func run(cmd *cobra.Command, argv []string) { os.Exit(1) } + if token != "" { + if fedramp.Enabled() || fedramp.IsCognitoToken(token) { + cfg.AccessToken = "" + cfg.RefreshToken = token + cfg.FedRAMP = true + fedramp.Enable() + } else { + // If a token has been provided parse it: + parser := new(jwt.Parser) + jwtToken, _, err := parser.ParseUnverified(token, jwt.MapClaims{}) + if err != nil { + reporter.Errorf("Failed to parse token '%s': %v", token, err) + os.Exit(1) + } + + // Put the token in the place of the configuration that corresponds to its type: + typ, err := tokenType(jwtToken) + if err != nil { + reporter.Errorf("Failed to extract type from 'typ' claim of token '%s': %v", token, err) + os.Exit(1) + } + switch typ { + case "Bearer", "": + cfg.AccessToken = token + cfg.RefreshToken = "" + case "Refresh", "Offline": + cfg.AccessToken = "" + cfg.RefreshToken = token + default: + reporter.Errorf("Don't know how to handle token type '%s' in token '%s'", typ, token) + os.Exit(1) + } + } + } + // Apply the default OpenID details if not explicitly provided by the user: tokenURL := sdk.DefaultTokenURL if args.tokenURL != "" { @@ -194,11 +248,26 @@ func run(cmd *cobra.Command, argv []string) { // If the value of the `--env` is any of the aliases then replace it with the corresponding // real URL: - gatewayURL, ok := ocm.URLAliases[args.env] + gatewayURL, ok := ocm.URLAliases[env] if !ok { - gatewayURL = args.env + gatewayURL = env } + if fedramp.Enabled() { + if env == sdk.DefaultURL { + env = "production" + } + if args.tokenURL == "" { + tokenURL = fedramp.TokenURLs[env] + } + if args.clientID == "" { + clientID = fedramp.ClientIDs[env] + } + gatewayURL, ok = fedramp.URLAliases[env] + if !ok { + gatewayURL = env + } + } // Update the configuration with the values given in the command line: cfg.TokenURL = tokenURL cfg.ClientID = clientID @@ -207,34 +276,6 @@ func run(cmd *cobra.Command, argv []string) { cfg.URL = gatewayURL cfg.Insecure = args.insecure - if token != "" { - // If a token has been provided parse it: - parser := new(jwt.Parser) - jwtToken, _, err := parser.ParseUnverified(token, jwt.MapClaims{}) - if err != nil { - reporter.Errorf("Failed to parse token '%s': %v", token, err) - os.Exit(1) - } - - // Put the token in the place of the configuration that corresponds to its type: - typ, err := tokenType(jwtToken) - if err != nil { - reporter.Errorf("Failed to extract type from 'typ' claim of token '%s': %v", token, err) - os.Exit(1) - } - switch typ { - case "Bearer", "": - cfg.AccessToken = token - cfg.RefreshToken = "" - case "Refresh", "Offline": - cfg.AccessToken = "" - cfg.RefreshToken = token - default: - reporter.Errorf("Don't know how to handle token type '%s' in token '%s'", typ, token) - os.Exit(1) - } - } - // Create a connection and get the token to verify that the crendentials are correct: ocmClient, err := ocm.NewClient(). Config(cfg). @@ -273,12 +314,8 @@ func run(cmd *cobra.Command, argv []string) { username, err := cfg.GetData("username") if err != nil { - reporter.Debugf("Failed to get username: %v", err) - username, err = cfg.GetData("preferred_username") - if err != nil { - reporter.Errorf("Failed to get username: %v", err) - os.Exit(1) - } + reporter.Errorf("Failed to get username: %v", err) + os.Exit(1) } reporter.Infof("Logged in as '%s' on '%s'", username, cfg.URL) diff --git a/go.sum b/go.sum index b79da12551..4465b96608 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,7 @@ github.com/AlecAivazis/survey/v2 v2.2.15/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZt 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/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -81,8 +82,10 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -92,6 +95,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF 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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -155,6 +159,7 @@ 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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -201,16 +206,21 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/itchyny/gojq v0.12.7 h1:hYPTpeWfrJ1OT+2j6cvBScbhl0TkdwGM4bc66onUSOQ= github.com/itchyny/gojq v0.12.7/go.mod h1:ZdvNHVlzPgUf8pgjnuDTmGfHA/21KoutQUJ3An/xNuw= +github.com/itchyny/timefmt-go v0.1.3 h1:7M3LGVDsqcd0VZH2U+x393obrzZisp7C0uEe921iRkU= github.com/itchyny/timefmt-go v0.1.3/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= @@ -218,12 +228,16 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.12.0 h1:/RvQ24k3TnNdfBSW0ou9EOi5jx2cX7zfE8n2nLKuiP0= github.com/jackc/pgconn v1.12.0/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -231,17 +245,21 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.0 h1:brH0pCGBDkBW07HWlN/oSBXrmo3WB0UvZd1pIuDcL8Y= github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.11.0 h1:u4uiGPz/1hryuXzyaBhSk6dnIyyG2683olG2OV+UUgs= github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.16.0 h1:4k1tROTJctHotannFYzu77dY3bgtMRymQP7tXQjqpPk= github.com/jackc/pgx/v4 v4.16.0/go.mod h1:N0A9sFdWzkw/Jy1lwoiB64F2+ugFZi987zRxcPez/wI= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -250,6 +268,7 @@ github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dv github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -272,10 +291,13 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kubermatic/glog-logrus v0.0.0-20180829085450-3fa5b9870d1d h1:JV46OtdhH2vVt8mJ1EWUE94k99vbN9fZs1WQ8kcEapU= github.com/kubermatic/glog-logrus v0.0.0-20180829085450-3fa5b9870d1d/go.mod h1:CHQ3o5KBH1PIS2Fb1mRLTIWO5YzP9kSUB3KoCICwlvA= @@ -351,6 +373,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -420,6 +443,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf 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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -466,6 +490,7 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc= golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -694,6 +719,7 @@ golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8T 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= @@ -774,6 +800,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/pkg/fedramp/config.go b/pkg/fedramp/config.go new file mode 100644 index 0000000000..e4673007b7 --- /dev/null +++ b/pkg/fedramp/config.go @@ -0,0 +1,59 @@ +/* +Copyright (c) 2022 Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// This file contains the types and functions used to manage the configuration of the command line +// client when running in FedRAMP mode. + +package fedramp + +// nolint:lll +var TokenPage = map[string]string{ + "production": "https://.execute-api.us-gov-west-1.amazonaws.com/api/auth", + "staging": "https://.execute-api.us-gov-west-1.amazonaws.com/api/auth", + "integration": "https://yuw9wqbds8.execute-api.us-gov-west-1.amazonaws.com/api/auth", + "dev": "https://7mj19sjo7i.execute-api.us-east-1.amazonaws.com/api/auth", +} + +var Regions = map[string]string{ + "production": "us-gov-west-1", + "staging": "us-gov-west-1", + "integration": "us-gov-west-1", + "dev": "us-east-1", +} + +// ClientIDs allows the value of the `--env` option to map to the various AWS Cognito user pool clients. +var ClientIDs = map[string]string{ + "production": "", + "staging": "", + "integration": "20fbrpgl28f8oehp6709mk3nnr", + "dev": "3p9rlk0cfs8ba5l7t1d78vcdot", +} + +// URLAliases allows the value of the `--env` option to map to the various API URLs. +var URLAliases = map[string]string{ + "production": "https://api.appsrefrp01ugw1.p1.openshiftusgov.com:6443", + "staging": "https://api.appsrefrs01ugw1.p1.openshiftusgov.com:6443", + "integration": "https://yuw9wqbds8.execute-api.us-gov-west-1.amazonaws.com", + "dev": "https://clusters-service.apps-crc.testing", +} + +// ClientIDs allows the value of the `--env` option to map to the various AWS Cognito token URLs. +var TokenURLs = map[string]string{ + "production": "https://rh-ocm-appsre-prod.auth-fips.us-gov-west-1.amazoncognito.com/oauth2/token", + "staging": "https://rh-ocm-appsre-stage.auth-fips.us-gov-west-1.amazoncognito.com/oauth2/token", + "integration": "https://rh-ocm-appsre-integration.auth-fips.us-gov-west-1.amazoncognito.com/oauth2/token", + "dev": "https://rh-ocm-dev.auth.us-east-1.amazoncognito.com/oauth2/token", +} diff --git a/pkg/fedramp/flag.go b/pkg/fedramp/flag.go new file mode 100644 index 0000000000..ee74909f77 --- /dev/null +++ b/pkg/fedramp/flag.go @@ -0,0 +1,46 @@ +/* +Copyright (c) 2022 Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// This file contains functions used to implement the '--govcloud' command line option. + +package fedramp + +import ( + "github.com/spf13/pflag" +) + +// AddFlag adds the govcloud flag to the given set of command line flags. +func AddFlag(flags *pflag.FlagSet) { + flags.BoolVar( + &enabled, + "govcloud", + false, + "Uses the FedRAMP High OpenShift Cluster Manager API for creating clusters in AWS GovCloud regions", + ) +} + +// Enabled returns a boolean flag that indicates if the fedramp mode is enabled. +func Enabled() bool { + return enabled +} + +// Enable sets the flag for the rest of the command +func Enable() { + enabled = true +} + +// enabled is a boolean flag that indicates that the govcloud mode is enabled. +var enabled bool diff --git a/pkg/fedramp/token.go b/pkg/fedramp/token.go new file mode 100644 index 0000000000..b09477c9c1 --- /dev/null +++ b/pkg/fedramp/token.go @@ -0,0 +1,40 @@ +/* +Copyright (c) 2022 Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// This file contains token functions for the OCM client when running in FedRAMP mode. + +package fedramp + +import ( + "encoding/base64" + "strings" +) + +func IsCognitoToken(textToken string) bool { + parts := strings.Split(textToken, ".") + if len(parts) != 5 { + return false + } + decoded, _ := base64.StdEncoding.DecodeString(parts[0]) + if len(decoded) == 0 { + return false + } + header := string(decoded) + if strings.Contains(header, "\"cty\":\"JWT\"") && strings.Contains(header, "\"alg\":\"RSA-OAEP\"") { + return true + } + return false +} diff --git a/pkg/ocm/client.go b/pkg/ocm/client.go index c551e340ee..25b941e063 100644 --- a/pkg/ocm/client.go +++ b/pkg/ocm/client.go @@ -140,8 +140,9 @@ func (b *ClientBuilder) Build() (result *Client, err error) { return nil, fmt.Errorf("your authorization token needs to be updated. " + "Please login again using rosa login") } - return nil, fmt.Errorf("error creating connection. Not able to get authentication token") + return nil, fmt.Errorf("error creating connection. Not able to get authentication token: %s", err) } + return &Client{ ocm: conn, }, nil diff --git a/pkg/ocm/config.go b/pkg/ocm/config.go index fdf7ca2525..1073957592 100644 --- a/pkg/ocm/config.go +++ b/pkg/ocm/config.go @@ -32,6 +32,7 @@ import ( sdk "github.com/openshift-online/ocm-sdk-go" "github.com/openshift/rosa/pkg/debug" + "github.com/openshift/rosa/pkg/fedramp" ) // URLAliases allows the value of the `--env` option to map to the various API URLs. @@ -51,15 +52,31 @@ type Config struct { Scopes []string `json:"scopes,omitempty"` TokenURL string `json:"token_url,omitempty"` URL string `json:"url,omitempty"` + FedRAMP bool `json:"fedramp,omitempty"` } -func GetEnv() (string, error) { - cfg, err := Load() - if err != nil { - return "", err +func GetEnv(cfgs ...*Config) (string, error) { + var cfg *Config + var err error + if len(cfgs) == 1 { + cfg = cfgs[0] + } else { + cfg, err = Load() + if err != nil { + return "", err + } + } + + if cfg == nil { + return "", nil + } + + urlAliases := URLAliases + if cfg.FedRAMP { + urlAliases = fedramp.URLAliases } - for env, api := range URLAliases { + for env, api := range urlAliases { if api == cfg.URL { return env, nil } @@ -227,6 +244,13 @@ func (c *Config) Armed() (armed bool, err error) { } } if c.RefreshToken != "" { + if fedramp.IsCognitoToken(c.RefreshToken) { + // We have no way of knowing an AWS Cognito refresh token expiration, as + // it's a JWE token. So we assume it's valid and let the access token + // request fail. + armed = true + return + } var expires bool var left time.Duration var refreshToken *jwt.Token