Skip to content

Commit

Permalink
Merge pull request #141 from 99designs/refactor-order-in-which-access…
Browse files Browse the repository at this point in the history
…-to-keychain-is-requested

Refactor order in which access to keychain is requested
  • Loading branch information
lox authored Sep 2, 2017
2 parents 7d4cd04 + c867a32 commit 24a152d
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 39 deletions.
2 changes: 1 addition & 1 deletion vault/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,5 @@ func FormatCredentialError(profileKey string, from Profiles, err error) string {
sourceDescr, source)
}

return fmt.Sprintf("Failed to get credentials for %s: %v", err, sourceDescr)
return fmt.Sprintf("Failed to get credentials for %s: %v", sourceDescr, err)
}
91 changes: 57 additions & 34 deletions vault/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,42 +87,12 @@ func NewVaultProvider(k keyring.Keyring, profile string, opts VaultOptions) (*Va
}, nil
}

// Retrieve returns credentials protected by a GetSessionToken. If there is an associated
// role in the profile then AssumeRole is applied. The benefit of a session is that it doesn't
// require MFA or a user prompt to access the keychain item, much like sudo.
func (p *VaultProvider) Retrieve() (credentials.Value, error) {
creds, err := p.getMasterCreds()
if err != nil {
return credentials.Value{}, err
}

window := p.ExpiryWindow
if window == 0 {
window = time.Minute * 5
}

if p.NoSession {
if role, ok := p.profiles[p.profile]["role_arn"]; ok {
session, err := p.assumeRole(creds, role)
if err != nil {
return credentials.Value{}, err
}

log.Printf("Using role ****************%s, expires in %s",
(*session.AccessKeyId)[len(*session.AccessKeyId)-4:],
session.Expiration.Sub(time.Now()).String())

p.SetExpiration(*session.Expiration, window)
p.expires = *session.Expiration

value := credentials.Value{
AccessKeyID: *session.AccessKeyId,
SecretAccessKey: *session.SecretAccessKey,
SessionToken: *session.SessionToken,
}

return value, nil
}

// no role, exposes master credentials which don't expire
return creds, nil
return p.RetrieveWithoutSessionToken()
}

session, err := p.sessions.Retrieve(p.profile, p.SessionDuration)
Expand All @@ -133,6 +103,12 @@ func (p *VaultProvider) Retrieve() (credentials.Value, error) {
log.Println(err)
}

// session lookup missed, we need to create a new one
creds, err := p.getMasterCreds()
if err != nil {
return credentials.Value{}, err
}

session, err = p.getSessionToken(&creds)
if err != nil {
return credentials.Value{}, err
Expand All @@ -158,6 +134,11 @@ func (p *VaultProvider) Retrieve() (credentials.Value, error) {
session.Expiration.Sub(time.Now()).String())
}

window := p.ExpiryWindow
if window == 0 {
window = time.Minute * 5
}

p.SetExpiration(*session.Expiration, window)
p.expires = *session.Expiration

Expand All @@ -170,6 +151,48 @@ func (p *VaultProvider) Retrieve() (credentials.Value, error) {
return value, nil
}

// RetrieveWithoutSessionToken returns credentials that are either the master credentials or
// a session created with AssumeRole. This allows for usecases where a token created with AssumeRole
// wouldn't work.
func (p *VaultProvider) RetrieveWithoutSessionToken() (credentials.Value, error) {
log.Println("Skipping session token and using master credentials directly")

creds, err := p.getMasterCreds()
if err != nil {
return credentials.Value{}, err
}

if role, ok := p.profiles[p.profile]["role_arn"]; ok {
session, err := p.assumeRole(creds, role)
if err != nil {
return credentials.Value{}, err
}

log.Printf("Using role ****************%s, expires in %s",
(*session.AccessKeyId)[len(*session.AccessKeyId)-4:],
session.Expiration.Sub(time.Now()).String())

window := p.ExpiryWindow
if window == 0 {
window = time.Minute * 5
}

p.SetExpiration(*session.Expiration, window)
p.expires = *session.Expiration

value := credentials.Value{
AccessKeyID: *session.AccessKeyId,
SecretAccessKey: *session.SecretAccessKey,
SessionToken: *session.SessionToken,
}

return value, nil
}

// no role, exposes master credentials which don't expire
return creds, nil
}

func (p *VaultProvider) getMasterCreds() (credentials.Value, error) {
if p.MasterCreds != nil {
return *p.MasterCreds, nil
Expand Down
9 changes: 5 additions & 4 deletions vault/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,11 @@ func (s *KeyringSessions) Store(profile string, session sts.Credentials, duratio

log.Printf("Writing session for %s to keyring", profile)
s.Keyring.Set(keyring.Item{
Key: s.key(profile, duration),
Label: "aws-vault session for " + profile,
Data: bytes,
TrustSelf: true,
Key: s.key(profile, duration),
Label: "aws-vault session for " + profile,
Description: "aws-vault session for " + profile,
Data: bytes,
TrustSelf: false,
})

return nil
Expand Down

0 comments on commit 24a152d

Please sign in to comment.