Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Before you can start generating temporary credentials, you'll need to create a b
sp_identity_url = <url to IDP initiated SP login>
```

You can overwrite the default one hour key expiry duration in the configuration.
```
duration = <new duration in seconds>
```

You can then generate temporary credentials by running the `aws-cli-federator` utility:

```
Expand All @@ -36,16 +41,22 @@ export AWS_SESSION_TOKEN=<redacted>
These credentials will remain valid until 2017-01-03 03:29:22 +0000 UTC
```

If you log into multiple accounts using different IDP URL's, you can add multiple `sp_identity_url`'s (under unique section names) and request credentials like so:
If you log into multiple accounts using different IDP URL's or session expiry times, you can add multiple `sp_identity_url`'s or `duration`'s (under unique section names) and request credentials like so:

```
$ aws-cli-federator --account <account name>
```

Alternatively you are able to overwrite the duration parameter in the config file with a `-duration` flag.

```
$ aws-cli-federator -account <account name>
$ aws-cli-federator --duration <duration>
```

This tool can also write the generated temporary credentials to the `~/.aws/credentials` file using the `-profile <section name>` flag. The section and credentials will be created if they do not already exist and overwritten if they do.

```
$ aws-cli-federator -acount <account name> -profile <profile name>
$ aws-cli-federator --acount <account name> --profile <profile name>
```

If your IDP federates authentication to a number of different accounts, it can get difficult to keep track of which account number is which account. To simplify this, you can add a list of alias' to the `federatedcli` configuration file to overwrite the account number with a more memerable name.
Expand All @@ -71,4 +82,4 @@ This utility tries to remain agnostic and should work with most SAML/SHIB/ADFS i
## Contributing / Issues
If you have any feature suggestions or bug fixes, please open an issue or a pull request!

If you have an issue, please include as much information as possible including running the utility in debug mode (`-v` flag).
If you have an issue, please include as much information as possible including running the utility in debug mode (`-v` flag).
16 changes: 12 additions & 4 deletions federator/federator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/RobotsAndPencils/go-saml"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/sts"
"golang.org/x/net/html"
)
Expand Down Expand Up @@ -103,19 +104,26 @@ func (a *Federator) GetRoles() ([]Role, error) {
return r, nil
}

func (a *Federator) AssumeRole(r Role) (Credentials, error) {
func (a *Federator) AssumeRole(r Role, duration int64) (Credentials, error) {
if a.samlResponse == nil {
return Credentials{}, fmt.Errorf("You must call Login before assuming a role")
}

svc := sts.New(session.New())
params := &sts.AssumeRoleWithSAMLInput{
PrincipalArn: aws.String(r.PrincipalArn()),
RoleArn: aws.String(r.RoleArn()),
SAMLAssertion: aws.String(a.samlResponse64),
DurationSeconds: aws.Int64(duration),
PrincipalArn: aws.String(r.PrincipalArn()),
RoleArn: aws.String(r.RoleArn()),
SAMLAssertion: aws.String(a.samlResponse64),
}

resp, err := svc.AssumeRoleWithSAML(params)
//print (err.Code());
if awsErr, ok := err.(awserr.Error); ok {
if ( awsErr.Code() == "ValidationError" ) {
return Credentials{}, fmt.Errorf("You need to either change the requested duration to be >900 and <3600 or alter the role's MaxSessionDuration via the console.")
}
}
if err != nil {
return Credentials{}, fmt.Errorf("Unable to assume role: %s", err)
}
Expand Down
24 changes: 22 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type configuration struct {

account string
profile string
duration int64
}

var Version = "1.0.0"
Expand All @@ -40,6 +41,7 @@ func init() {
flag.StringVar(&c.account, "account", "", "set which AWS account configuration should be used")
flag.StringVar(&c.account, "acct", "", "set which AWS account configuration should be used (shorthand)")
flag.StringVar(&c.profile, "profile", "", "set which AWS credential profile the temporary credentials should be written to. Defaults to 'default'")
flag.Int64Var(&c.duration, "duration", int64(-1), "sets the duration of the CLI credentials. Defaults to 3600.")

flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", filepath.Base(os.Args[0]))
Expand Down Expand Up @@ -113,6 +115,24 @@ func main() {
os.Exit(1)
}

// get key duration, defaults to 3600
var duration = int64(3600)
if (c.duration != int64(-1)) {
duration = int64(c.duration)
} else if (acct.HasKey("duration")) {
var err error
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: Could not get duration: %s\n", err)
os.Exit(1)
}
duration, err = acct.Key("duration").Int64()
}

if duration > 43200 || duration < 900 {
fmt.Fprintf(os.Stderr, "ERROR: Duration needs to be a value in the range between 900 and 43200\n")
os.Exit(1)
}

if !acct.HasKey("sp_identity_url") {
fmt.Fprintf(os.Stderr, "ERROR: Account configuration '%s' does not have an 'sp_identity_url' defined\n", c.account)
os.Exit(1)
Expand Down Expand Up @@ -215,9 +235,9 @@ func main() {

l.Printf("User has selected ARN: %s\n", roleToAssume)
l.Printf("Attempting to AssumeRoleWithSAML\n")
creds, err := aws.AssumeRole(roleToAssume)
creds, err := aws.AssumeRole(roleToAssume, duration)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: Failed to assume role: %s", err)
fmt.Fprintf(os.Stderr, "ERROR: Failed to assume role: %s\n", err)
os.Exit(1)
}

Expand Down