-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f85556b
commit bd677cb
Showing
11 changed files
with
530 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"net/url" | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go/aws/credentials" | ||
"github.com/miquella/vaulted/lib" | ||
"github.com/pkg/browser" | ||
) | ||
|
||
var ( | ||
ErrInvalidTemporaryCredentials = errors.New("Temporary session credentials found. Console cannot be opened with temporary credentials.\nIf the AWS Key is set in a vault, the permanent credentials can be used by specifying the vault name.") | ||
ErrInvalidDuration = errors.New("Minimum console duration must be at least 15 minutes.") | ||
ErrNoCredentialsFound = errors.New("No credentials found. Console cannot be opened.") | ||
) | ||
|
||
const ( | ||
CONSOLE_URL = "https://console.aws.amazon.com/console/home" | ||
SIGNIN_URL = "https://signin.aws.amazon.com/federation" | ||
|
||
MinConsoleDuration = 15 * time.Minute | ||
MaxConsoleDuration = 12 * time.Hour | ||
) | ||
|
||
type Console struct { | ||
VaultName string | ||
Role string | ||
} | ||
|
||
func (c *Console) Run(store vaulted.Store) error { | ||
signinToken, err := c.getSigninToken(store) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// console signin | ||
signinUrl, _ := url.Parse(SIGNIN_URL) | ||
loginQuery := make(url.Values) | ||
loginQuery.Set("Action", "login") | ||
loginQuery.Set("SigninToken", signinToken) | ||
loginQuery.Set("Destination", CONSOLE_URL) | ||
|
||
signinUrl.RawQuery = loginQuery.Encode() | ||
err = browser.OpenURL(signinUrl.String()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *Console) getSigninToken(store vaulted.Store) (string, error) { | ||
// Setup default values (may be overwritten by values from vault) | ||
duration := 1 * time.Hour | ||
var awsKey vaulted.AWSKey | ||
|
||
// Override defaults with values from specified vault | ||
if c.VaultName != "" { | ||
v, _, err := store.OpenVault(c.VaultName) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
duration = v.Duration | ||
|
||
if v.AWSKey.Valid() { | ||
awsKey = *v.AWSKey | ||
if c.Role != "" { | ||
awsKey.Role = c.Role | ||
} | ||
} | ||
} | ||
|
||
return c.getSigninTokenFromCreds(store, awsKey, duration) | ||
} | ||
|
||
func (c *Console) getSigninTokenFromCreds(store vaulted.Store, awsKey vaulted.AWSKey, duration time.Duration) (string, error) { | ||
// Get creds from environment if no creds loaded from vault | ||
creds, err := awsKey.AWSCredentials.WithLocalDefault() | ||
if err != nil && err != credentials.ErrNoValidProvidersFoundInChain { | ||
return "", err | ||
} else if err == credentials.ErrNoValidProvidersFoundInChain || !creds.Valid() { | ||
return "", ErrNoCredentialsFound | ||
} | ||
|
||
if creds.ValidSession() { | ||
return "", ErrInvalidTemporaryCredentials | ||
} | ||
|
||
duration, err = capDuration(duration) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
// assume provided role or get a federation token | ||
if awsKey.Role != "" { | ||
if awsKey.MFA != "" { | ||
tokenCode, tokenErr := store.Steward().GetMFAToken(c.VaultName) | ||
if tokenErr != nil { | ||
return "", tokenErr | ||
} | ||
creds, err = creds.AssumeRoleWithMFA(awsKey.MFA, tokenCode, awsKey.Role, 15*time.Minute) | ||
} else { | ||
creds, err = creds.AssumeRole(awsKey.Role, 15*time.Minute) | ||
} | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return creds.GetSigninToken(&duration) | ||
|
||
} else { | ||
creds, err = creds.GetFederationToken(duration) | ||
if err != nil { | ||
return "", err | ||
} | ||
return creds.GetSigninToken(nil) | ||
} | ||
} | ||
|
||
func capDuration(duration time.Duration) (time.Duration, error) { | ||
if duration < MinConsoleDuration { | ||
return time.Duration(0), ErrInvalidDuration | ||
} | ||
if duration > MaxConsoleDuration { | ||
duration = MaxConsoleDuration | ||
fmt.Println("Your vault duration is greater than the max console duration.\nCurrent console session duration set to 12 hours.") | ||
} | ||
return duration, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/miquella/vaulted/lib" | ||
) | ||
|
||
func TestConsole(t *testing.T) { | ||
var c Console = Console{ | ||
VaultName: "one", | ||
} | ||
var err error | ||
store := NewTestStore() | ||
store.Vaults["one"] = &vaulted.Vault{ | ||
AWSKey: &vaulted.AWSKey{}, | ||
} | ||
|
||
err = c.Run(store) | ||
if err != ErrNoCredentialsFound { | ||
t.Error("No credentials provided, should have cause an ErrNoCredentialsFound") | ||
} | ||
|
||
store.Vaults["one"].AWSKey.AWSCredentials = vaulted.AWSCredentials{ | ||
ID: "id", | ||
Secret: "secret", | ||
} | ||
err = c.Run(store) | ||
if err != ErrInvalidDuration { | ||
t.Error("Should have caused an invalid duration error") | ||
} | ||
|
||
store.Vaults["one"].AWSKey.AWSCredentials = vaulted.AWSCredentials{ | ||
ID: "id", | ||
Secret: "secret", | ||
Token: "token", | ||
} | ||
err = c.Run(store) | ||
if err != ErrInvalidTemporaryCredentials { | ||
t.Log(err) | ||
t.Error("Temporary session credentials provided, should have cause an invalid temp credentials error") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
.TH vaulted\-console 1 | ||
.SH NAME | ||
.PP | ||
vaulted console \- Opens the AWS console in the default web browser | ||
.SH SYNOPSIS | ||
.PP | ||
\fB\fCvaulted console\fR | ||
\fB\fCvaulted console\fR \fIname\fP [\fIOPTIONS\fP] | ||
.br | ||
\fB\fCvaulted console \-\-assume\fR \fIarn\fP [\fIOPTIONS\fP] | ||
.SH DESCRIPTION | ||
.PP | ||
Opens the AWS console in the default web browser. Uses either the credentials in the current environment or the credentials in the specified vault. Console sessions either use the provided vault's duration or defaults to 1 hour. | ||
.PP | ||
Durations must be at least 15 min and less than 12 hours. | ||
.SH OPTIONS | ||
.TP | ||
\fB\fC\-\-assume\fR \fIarn\fP | ||
Specifies the full ARN of the role to assume. See \fBASSUMING A ROLE\fP below | ||
for details on how Vaulted assumes roles. | ||
.IP | ||
Role assumption may be performed without specifying a vault to spawn from. | ||
When invoked this way, credentials are sourced from default locations (e.g. | ||
environment, configuration files, instance profile, etc.). | ||
.SH ASSUMING A ROLE | ||
.PP | ||
A role to assume can be specified either in a vault's configuration (via | ||
\fB\fCvaulted edit\fR) or specified via the \fB\fC\-\-assume\fR option. | ||
.PP | ||
Vaulted first opens the specified vault to retrieve the appropriate credentials. If a role is specified in the vault's configuration it will use that unless a role is explicitly passed in through the \fB\fC\-\-assume\fR option. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
vaulted-console 1 | ||
============= | ||
|
||
NAME | ||
---- | ||
|
||
vaulted console - Opens the AWS console in the default web browser | ||
|
||
SYNOPSIS | ||
-------- | ||
|
||
`vaulted console` | ||
`vaulted console` *name* [*OPTIONS*] | ||
`vaulted console --assume` *arn* [*OPTIONS*] | ||
|
||
DESCRIPTION | ||
----------- | ||
|
||
Opens the AWS console in the default web browser. Uses either the credentials in the current environment or the credentials in the specified vault. Console sessions either use the provided vault's duration or defaults to 1 hour. | ||
|
||
Durations must be at least 15 min and less than 12 hours. | ||
|
||
OPTIONS | ||
------- | ||
|
||
`--assume` *arn* | ||
Specifies the full ARN of the role to assume. See **ASSUMING A ROLE** below | ||
for details on how Vaulted assumes roles. | ||
|
||
Role assumption may be performed without specifying a vault to spawn from. | ||
When invoked this way, credentials are sourced from default locations (e.g. | ||
environment, configuration files, instance profile, etc.). | ||
|
||
|
||
ASSUMING A ROLE | ||
--------------- | ||
|
||
A role to assume can be specified either in a vault's configuration (via | ||
`vaulted edit`) or specified via the `--assume` option. | ||
|
||
Vaulted first opens the specified vault to retrieve the appropriate credentials. If a role is specified in the vault's configuration it will use that unless a role is explicitly passed in through the `--assume` option. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.