Skip to content

Commit

Permalink
Merge pull request #108 from Versent/feature/command_specific_help
Browse files Browse the repository at this point in the history
Feature/command specific help
  • Loading branch information
wolfeidau authored Dec 14, 2017
2 parents 1ab4061 + 779e251 commit 88c0b19
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 128 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
.credentials
dist
build
Expand Down
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,36 +39,40 @@ A command line tool to help with SAML access to the AWS token service.
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--verbose Enable verbose logging
--version Show application version.
--verbose Enable verbose logging
-i, --provider=PROVIDER This flag it is obsolete see https://github.com/Versent/saml2aws#adding-idp-accounts.
-a, --idp-account="default" The name of the configured IDP account
--idp-provider=IDP-PROVIDER
The configured IDP provider
--mfa="Auto" The name of the mfa
-p, --profile="saml" The AWS profile to save the temporary credentials
-s, --skip-verify Skip verification of server certificate.
-i, --provider=PROVIDER This flag it is obsolete see https://github.com/Versent/saml2aws#adding-idp-accounts.
--url=URL The URL of the SAML IDP server used to login.
--username=USERNAME The username used to login.
--password=PASSWORD The password used to login.
--role=ROLE The ARN of the role to assume.
--aws-urn=AWS-URN The URN used by SAML when you login.
--skip-prompt Skip prompting for parameters during login.
Commands:
help [<command>...]
Show help.
login
configure
Configure a new IDP account.
login [<flags>]
Login to a SAML 2.0 IDP and convert the SAML assertion to an STS token.
--password=PASSWORD The password used to login.
-p, --profile="saml" The AWS profile to save the temporary credentials
exec [<command>...]
exec [<flags>] [<command>...]
Exec the supplied command with env vars from STS token.
configure
Configure a new IDP account.
--password=PASSWORD The password used to login.
-p, --profile="saml" The AWS profile to save the temporary credentials
```

Expand Down
9 changes: 5 additions & 4 deletions cmd/saml2aws/commands/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import (
"github.com/pkg/errors"
"github.com/versent/saml2aws"
"github.com/versent/saml2aws/pkg/cfg"
"github.com/versent/saml2aws/pkg/flags"
)

// Configure configure account profiles
func Configure(loginFlags *LoginFlags, cmdline []string) error {
func Configure(configFlags *flags.CommonFlags) error {

idpAccountName := loginFlags.IdpAccount
idpAccountName := configFlags.IdpAccount

cfgm, err := cfg.NewConfigManager(cfg.DefaultConfigPath)
if err != nil {
Expand All @@ -24,10 +25,10 @@ func Configure(loginFlags *LoginFlags, cmdline []string) error {
}

// update username and hostname if supplied
applyFlagOverrides(loginFlags, account)
flags.ApplyFlagOverrides(configFlags, account)

// do we need to prompt for values now?
if !loginFlags.SkipPrompt {
if !configFlags.SkipPrompt {
err = saml2aws.PromptForConfigurationDetails(account)
if err != nil {
return errors.Wrap(err, "failed to input configuration")
Expand Down
9 changes: 5 additions & 4 deletions cmd/saml2aws/commands/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ import (
"github.com/aws/aws-sdk-go/service/sts"
"github.com/pkg/errors"
"github.com/versent/saml2aws/pkg/awsconfig"
"github.com/versent/saml2aws/pkg/flags"
"github.com/versent/saml2aws/pkg/shell"
)

// Exec execute the supplied command after seeding the environment
func Exec(loginFlags *LoginFlags, cmdline []string) error {
func Exec(execFlags *flags.LoginExecFlags, cmdline []string) error {

if len(cmdline) < 1 {
return fmt.Errorf("Command to execute required")
}

sharedCreds := awsconfig.NewSharedCredentials(loginFlags.Profile)
sharedCreds := awsconfig.NewSharedCredentials(execFlags.Profile)

// this checks if the credentials file has been created yet
// can only really be triggered if saml2aws exec is run on a new
Expand All @@ -34,13 +35,13 @@ func Exec(loginFlags *LoginFlags, cmdline []string) error {
return nil
}

ok, err := checkToken(loginFlags.Profile)
ok, err := checkToken(execFlags.Profile)
if err != nil {
return errors.Wrap(err, "error validating token")
}

if !ok {
err = Login(loginFlags)
err = Login(execFlags)
}
if err != nil {
return errors.Wrap(err, "error logging in")
Expand Down
81 changes: 15 additions & 66 deletions cmd/saml2aws/commands/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,14 @@ import (
"github.com/versent/saml2aws/pkg/awsconfig"
"github.com/versent/saml2aws/pkg/cfg"
"github.com/versent/saml2aws/pkg/creds"
"github.com/versent/saml2aws/pkg/flags"
)

// MaxDurationSeconds the maximum duration in seconds for an STS session
const MaxDurationSeconds = 3600

// LoginFlags login specific command flags
type LoginFlags struct {
IdpAccount string
IdpProvider string
MFA string
Profile string
URL string
Username string
Password string
RoleArn string
AmazonWebservicesURN string
SkipVerify bool
Timeout int
SkipPrompt bool
Provider string
}

// RoleSupplied role arn has been passed as a flag
func (lf *LoginFlags) RoleSupplied() bool {
return lf.RoleArn != ""
}

// Login login to ADFS
func Login(loginFlags *LoginFlags) error {
func Login(loginFlags *flags.LoginExecFlags) error {

logger := logrus.WithField("command", "login")

Expand Down Expand Up @@ -125,13 +104,13 @@ func Login(loginFlags *LoginFlags) error {
return nil
}

func buildIdpAccount(loginFlags *LoginFlags) (*cfg.IDPAccount, error) {
func buildIdpAccount(loginFlags *flags.LoginExecFlags) (*cfg.IDPAccount, error) {
cfgm, err := cfg.NewConfigManager(cfg.DefaultConfigPath)
if err != nil {
return nil, errors.Wrap(err, "failed to load configuration")
}

account, err := cfgm.LoadVerifyIDPAccount(loginFlags.IdpAccount)
account, err := cfgm.LoadVerifyIDPAccount(loginFlags.CommonFlags.IdpAccount)
if err != nil {
if cfg.IsErrIdpAccountNotFound(err) {
fmt.Printf("%v\n", err)
Expand All @@ -141,7 +120,7 @@ func buildIdpAccount(loginFlags *LoginFlags) (*cfg.IDPAccount, error) {
}

// update username and hostname if supplied
applyFlagOverrides(loginFlags, account)
flags.ApplyFlagOverrides(loginFlags.CommonFlags, account)

err = account.Validate()
if err != nil {
Expand All @@ -151,13 +130,13 @@ func buildIdpAccount(loginFlags *LoginFlags) (*cfg.IDPAccount, error) {
return account, nil
}

func resolveLoginDetails(account *cfg.IDPAccount, loginFlags *LoginFlags) (*creds.LoginDetails, error) {
func resolveLoginDetails(account *cfg.IDPAccount, loginFlags *flags.LoginExecFlags) (*creds.LoginDetails, error) {

// fmt.Printf("loginFlags %+v\n", loginFlags)

loginDetails := &creds.LoginDetails{URL: account.URL, Username: account.Username}

fmt.Printf("Using IDP Account %s to access %s %s\n", loginFlags.IdpAccount, account.Provider, account.URL)
fmt.Printf("Using IDP Account %s to access %s %s\n", loginFlags.CommonFlags.IdpAccount, account.Provider, account.URL)

err := credentials.LookupCredentials(loginDetails)
if err != nil {
Expand All @@ -169,8 +148,8 @@ func resolveLoginDetails(account *cfg.IDPAccount, loginFlags *LoginFlags) (*cred
// fmt.Printf("%s %s\n", savedUsername, savedPassword)

// if you supply a username in a flag it takes precedence
if loginFlags.Username != "" {
loginDetails.Username = loginFlags.Username
if loginFlags.CommonFlags.Username != "" {
loginDetails.Username = loginFlags.CommonFlags.Username
}

// if you supply a password in a flag it takes precedence
Expand All @@ -181,7 +160,7 @@ func resolveLoginDetails(account *cfg.IDPAccount, loginFlags *LoginFlags) (*cred
// fmt.Printf("loginDetails %+v\n", loginDetails)

// if skip prompt was passed just pass back the flag values
if loginFlags.SkipPrompt {
if loginFlags.CommonFlags.SkipPrompt {
return loginDetails, nil
}

Expand All @@ -193,12 +172,12 @@ func resolveLoginDetails(account *cfg.IDPAccount, loginFlags *LoginFlags) (*cred
return loginDetails, nil
}

func resolveRole(awsRoles []*saml2aws.AWSRole, samlAssertion string, loginFlags *LoginFlags) (*saml2aws.AWSRole, error) {
func resolveRole(awsRoles []*saml2aws.AWSRole, samlAssertion string, loginFlags *flags.LoginExecFlags) (*saml2aws.AWSRole, error) {
var role = new(saml2aws.AWSRole)

if len(awsRoles) == 1 {
if loginFlags.RoleSupplied() {
return saml2aws.LocateRole(awsRoles, loginFlags.RoleArn)
if loginFlags.CommonFlags.RoleSupplied() {
return saml2aws.LocateRole(awsRoles, loginFlags.CommonFlags.RoleArn)
}
return awsRoles[0], nil
} else if len(awsRoles) == 0 {
Expand All @@ -212,8 +191,8 @@ func resolveRole(awsRoles []*saml2aws.AWSRole, samlAssertion string, loginFlags

saml2aws.AssignPrincipals(awsRoles, awsAccounts)

if loginFlags.RoleSupplied() {
return saml2aws.LocateRole(awsRoles, loginFlags.RoleArn)
if loginFlags.CommonFlags.RoleSupplied() {
return saml2aws.LocateRole(awsRoles, loginFlags.CommonFlags.RoleArn)
}

for {
Expand Down Expand Up @@ -267,33 +246,3 @@ func loginToStsUsingRole(role *saml2aws.AWSRole, samlAssertion string, profile s

return nil
}

func applyFlagOverrides(loginFlags *LoginFlags, account *cfg.IDPAccount) {
if loginFlags.URL != "" {
account.URL = loginFlags.URL
}

if loginFlags.Username != "" {
account.Username = loginFlags.Username
}

if loginFlags.SkipVerify {
account.SkipVerify = loginFlags.SkipVerify
}

if loginFlags.IdpProvider != "" {
account.Provider = loginFlags.IdpProvider
}

if loginFlags.MFA != "" {
account.MFA = loginFlags.MFA
}

if loginFlags.AmazonWebservicesURN != "" {
account.AmazonWebservicesURN = loginFlags.AmazonWebservicesURN
}

if loginFlags.Timeout > 0 {
account.Timeout = loginFlags.Timeout
}
}
6 changes: 4 additions & 2 deletions cmd/saml2aws/commands/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import (
"github.com/versent/saml2aws"
"github.com/versent/saml2aws/pkg/cfg"
"github.com/versent/saml2aws/pkg/creds"
"github.com/versent/saml2aws/pkg/flags"
)

func TestResolveLoginDetailsWithFlags(t *testing.T) {

loginFlags := &LoginFlags{URL: "https://id.example.com", Username: "wolfeidau", Password: "testtestlol", SkipPrompt: true}
commonFlags := &flags.CommonFlags{URL: "https://id.example.com", Username: "wolfeidau", SkipPrompt: true}
loginFlags := &flags.LoginExecFlags{CommonFlags: commonFlags, Password: "testtestlol"}

idpa := &cfg.IDPAccount{
URL: "https://id.example.com",
Expand All @@ -37,7 +39,7 @@ func TestResolveRoleSingleEntry(t *testing.T) {
adminRole,
}

got, err := resolveRole(awsRoles, "", &LoginFlags{})
got, err := resolveRole(awsRoles, "", &flags.LoginExecFlags{CommonFlags: &flags.CommonFlags{}})
assert.Empty(t, err)
assert.Equal(t, got, adminRole)
}
Loading

0 comments on commit 88c0b19

Please sign in to comment.