Skip to content

Commit

Permalink
sign-in: make it work with all kinds of profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
verbit committed Aug 2, 2020
1 parent 806b38b commit 9495e9b
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 108 deletions.
117 changes: 11 additions & 106 deletions cmd/aws-sign-in/main.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package main

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"os/exec"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/external"
"github.com/docopt/docopt-go"
"github.com/mattn/go-shellwords"
"github.com/mbrtargeting/aws-cli-oidc/internal"
"github.com/pkg/browser"
"gopkg.in/ini.v1"
)

func main() {
Expand All @@ -24,7 +21,7 @@ func main() {
usage := `aws-sign-in.
Usage:
aws-sign-in [<profile>]
aws-sign-in
aws-sign-in -h | --help
Options:
Expand All @@ -36,25 +33,20 @@ Options:
}

var conf struct {
Profile string `docopt:"<profile>"`
}
if err := arguments.Bind(&conf); err != nil {
log.Fatalf("%v\n", err)
}

profileName := conf.Profile
if profileName == "" {
profileName = os.Getenv("AWS_PROFILE")
if profileName == "" {
profileName = "default"
}
cfg, err := external.LoadDefaultAWSConfig()
if err != nil {
fmt.Printf("unable to load SDK config: %v\n", err)
}
cfg.Region = "eu-central-1"

configPath, credentialsPath := getAWSConfigPaths()

creds, err := runCredentialProcess(configPath, credentialsPath, profileName)
creds, err := cfg.Credentials.Retrieve(context.Background())
if err != nil {
log.Fatalf("Error running the credential process: %v\n", err)
log.Fatalf("Error retrieving credentials: %v\n", err)
}

signinToken, err := getSignInToken(creds)
Expand All @@ -70,94 +62,7 @@ Options:
fmt.Printf("If the browser didn't open, please visit the following url to sign in to the AWS console: %v\n", loginURL)
}

func getAWSConfigPaths() (string, string) {
var credentialsPath string
var configPath string

awsConfigFile := os.Getenv("AWS_CONFIG_FILE")
if awsConfigFile != "" {
configPath = awsConfigFile
}

awsCredentialsFile := os.Getenv("AWS_SHARED_CREDENTIALS_FILE")
if awsCredentialsFile != "" {
credentialsPath = awsCredentialsFile
}

home, err := os.UserHomeDir()
if err == nil {
// only overwrite the paths if the respective env var was not set
if configPath == "" {
configPath = home + "/.aws/config"
}
if credentialsPath == "" {
credentialsPath = home + "/.aws/credentials"
}
}

return configPath, credentialsPath
}

func tryRunCredentialProcess(credentialProcess string) (*internal.AWSCredentialsJSON, error) {
words, err := shellwords.Parse(credentialProcess)
if err != nil || len(words) == 0 {
return nil, fmt.Errorf("invalid credential_process entry")
}
cmd := exec.Command(words[0], words[1:]...)
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failed to run the credential process: %v", err)
}

var creds internal.AWSCredentialsJSON
err = json.Unmarshal(out.Bytes(), &creds)
if err != nil {
return nil, fmt.Errorf("error parsing credential process output: %v", err)
}

return &creds, nil
}

func findCredentialProcess(path string, profile string) (string, error) {
cfg, err := ini.Load(path)
if err != nil {
return "", fmt.Errorf("failed to read file: %v", err)
}

section, err := cfg.GetSection(profile)
if err != nil {
return "", fmt.Errorf("failed to read section: %v", err)
}

key, err := section.GetKey("credential_process")
if err != nil {
return "", fmt.Errorf("failed to find credential_process entry: %v", err)
}

return key.String(), nil
}

func runCredentialProcess(configPath string, credentialsPath string, profile string) (*internal.AWSCredentialsJSON, error) {
credentialProcess, err := findCredentialProcess(credentialsPath, profile)
if err == nil {
return tryRunCredentialProcess(credentialProcess)
}

// yes, the ~/.aws/config has a different naming scheme for profile names (must be prefixed with "profile")
configProfileName := profile
if profile != "default" {
configProfileName = fmt.Sprintf("profile %s", profile)
}
credentialProcess, err = findCredentialProcess(configPath, configProfileName)
if err == nil {
return tryRunCredentialProcess(credentialProcess)
}

return nil, fmt.Errorf("not able to find a valid credential_process")
}

func getSignInToken(creds *internal.AWSCredentialsJSON) (string, error) {
func getSignInToken(creds aws.Credentials) (string, error) {
reqJSON := fmt.Sprintf(`{"sessionId":"%s","sessionKey":"%s","sessionToken":"%s"}`,
creds.AccessKeyID,
creds.SecretAccessKey,
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module github.com/mbrtargeting/aws-cli-oidc

require (
github.com/aws/aws-sdk-go v1.15.50
github.com/aws/aws-sdk-go-v2 v0.24.0
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
github.com/mattn/go-shellwords v1.0.10
github.com/natsukagami/go-input v0.0.0-20180603034138-38bb793e9754
Expand All @@ -10,9 +11,9 @@ require (
github.com/stretchr/testify v1.5.1 // indirect
github.com/zalando/go-keyring v0.0.0-20200121091418-667557018717
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678 // indirect
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
golang.org/x/net v0.0.0-20200202094626-16171245cfb2
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
gopkg.in/ini.v1 v1.52.0
gopkg.in/ini.v1 v1.52.0 // indirect
gopkg.in/yaml.v2 v2.2.2
)

Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/aws/aws-sdk-go v1.15.50 h1:3QZIQeiRXEMTs+w+BQ2c/3Fi9/Qz9KnipT/M7YI1ub4=
github.com/aws/aws-sdk-go v1.15.50/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go-v2 v0.24.0 h1:R0lL0krk9EyTI1vmO1ycoeceGZotSzCKO51LbPGq3rU=
github.com/aws/aws-sdk-go-v2 v0.24.0/go.mod h1:2LhT7UgHOXK3UXONKI5OMgIyoQL6zTAw/jwIeX6yqzw=
github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU=
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
Expand All @@ -9,14 +11,19 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo=
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
Expand All @@ -31,6 +38,7 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykE
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
Expand All @@ -45,6 +53,8 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
Expand All @@ -55,6 +65,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
Expand Down

0 comments on commit 9495e9b

Please sign in to comment.