assumerole

package module
v0.0.0-...-c71e18c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2020 License: Apache-2.0 Imports: 22 Imported by: 0

README

CLI for AssumeRole

CLI for AssumeRole is a CLI tool for running programs with temporary AWS credentials. It is intended to be used by operators for running scripts and other tools that don't have native AssumeRole support.

Example

Run myscript.py using the "admin" role in your AWS account:

assume-role --role admin ./myscript.py

Features

  • Caches credentials with configurable expiry time (e.g. 15 mins before credentials are due to expire)
  • Interoperability with awscli
  • Supports MFA and attempts to autodetect when MFA is required
  • Configurable via autoloading config file

Getting started

Set up base policy

assume-role requires the user performing the AssumeRole call has the iam:GetUser permission, to identify the username and use that as the session name (so the user's name shows up in the CloudTrail UI).

If MFA needs to be provided, assume-role also requires that the current user can list their own MFA devices.

Create the following policy (e.g. named "allow-assume-role-script") and attach this to users or groups who will be performing the AssumeRole:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:GetUser",
                "iam:ListMFADevices"
            ],
            "Resource": "arn:aws:iam::<account-ID>:user/${aws:username}"
        }
    ]
}

(Replace <account-ID> with your AWS account ID.)

Create a configuration file

The --role option takes the full ARN of the role you want to assume (e.g. arn:aws:iam::1234567890:role/admin). To save humans on typing, you can specify the role prefix in configuration, so that you only need to use the named part of the role (i.e. --role admin).

Create a YAML-based configuration file called assume-role.yaml in root of your project directory:

role_prefix: arn:aws:iam::1234567890:role/

This allows you to execute assume-role by using the short role name, e.g.:

assume-role --role myrolename

To see other useful configuration, see Configuration options below.

Install and run it

You can install assume-role using go get:

go get -u github.com/uber/assume-role-cli/cli/assume-role

Now, run a command:

assume-role --role admin ./myscript.py

If you run it without a command to execute, environment variables will be printed to the console instead:

assume-role --role admin
AWS_ACCESS_KEY_ID=ASIAQWERTYUIOPASDFGHJKL
AWS_SECRET_ACCESS_KEY=8qLCbGYKhOWXU38ZVj+RhY1f7+zvuZ3vHMIhNGTxnhs=
AWS_SESSION_TOKEN=Wt5owtYQ/zObHy+8KLAgejM/CKGlt3Fa67PpRt+dVaDv4+NqmuFBu6VCkV1jmtfr82eABf9R2sN76ezZ1NIaaKnnkx8fk1WIH7jb7e5KYD0gsaOaAFIKEsMBMixvrFcxTe4Xth8D7lCohZZLTU2I2kazJxOrE249Xwq61hh1ZTezKHNvqek9BbItQdaWoniEkJz9vtTgXYSxnBJoV+VIsSa7KyDcLrteHVKdLx7qkxvsZvXkvmPRnQtnrGBeT3pm7LIlc2xOiKgAxuDf8gW5RWORrz71DdzFfPVqi0lAw5Hx0Qx/9gipuTPr5DICUzah8l64w4t21R0L9T1r84NAjA==

That's it!

Configuration options

Configuration is done by placing a file named assume-role.yaml in your project directory, or in ~/.aws.

assume-role will locate this file if you are running it from within a project subdirectory.

The following configuration options are available:

  • refresh_before_expiry: <duration> (default 15m)

    When you run assume-role credentials are cached and subsequent invocations just read from the cache. When the credentials expire, a refresh is triggered (doing the AssumeRole again).

    This value controls how long before the credentials are due to expire we'll refresh them anyway. This is so that credentials don't expire in the middle of running a command.

  • role_prefix: <string> (default: empty)

    To avoid typing the full ARN at the command-line every time, you can a prefix so you no longer have to type:

    assume-role --role arn:aws:iam::123:role/admin
    

    Instead you can do:

    assume-role --role admin
    

    By configuring arn:aws:iam::123:role/ as the prefix.

  • profile_name_prefix: <string> (defaults to empty, which uses your AWS account ID instead)

    When you do an assume-role, the credentials are saved to ~/.aws/credentials under a name in the format <profile_name_prefix>-<role_name>. This allows you to then use the profile with other tools using the AWS_PROFILE variable, or for example when executing awscli directly: aws --profile=myaccount-admin s3 ls bucket://mybucket/.

    This is a convenience helper but is generally not needed if you always just run all your commands through assume-role.

Documentation

Overview

Package assumerole is a wrapper around AWS's sts:AssumeRole API call to get temporary credentials and cache them locally in ~/.aws config files.

  • Copyright (c) 2018 Uber Technologies, Inc. *

  • Licensed under the Apache License, Version 2.0 (the "License");

  • you may not use this file except in compliance with the License.

  • You may obtain a copy of the License at *

  • http://www.apache.org/licenses/LICENSE-2.0 *

  • Unless required by applicable law or agreed to in writing, software

  • distributed under the License is distributed on an "AS IS" BASIS,

  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  • See the License for the specific language governing permissions and

  • limitations under the License.

  • Copyright (c) 2018 Uber Technologies, Inc. *

  • Licensed under the Apache License, Version 2.0 (the "License");

  • you may not use this file except in compliance with the License.

  • You may obtain a copy of the License at *

  • http://www.apache.org/licenses/LICENSE-2.0 *

  • Unless required by applicable law or agreed to in writing, software

  • distributed under the License is distributed on an "AS IS" BASIS,

  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  • See the License for the specific language governing permissions and

  • limitations under the License.

  • Copyright (c) 2018 Uber Technologies, Inc. *

  • Licensed under the Apache License, Version 2.0 (the "License");

  • you may not use this file except in compliance with the License.

  • You may obtain a copy of the License at *

  • http://www.apache.org/licenses/LICENSE-2.0 *

  • Unless required by applicable law or agreed to in writing, software

  • distributed under the License is distributed on an "AS IS" BASIS,

  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  • See the License for the specific language governing permissions and

  • limitations under the License.

  • Copyright (c) 2018 Uber Technologies, Inc. *

  • Licensed under the Apache License, Version 2.0 (the "License");

  • you may not use this file except in compliance with the License.

  • You may obtain a copy of the License at *

  • http://www.apache.org/licenses/LICENSE-2.0 *

  • Unless required by applicable law or agreed to in writing, software

  • distributed under the License is distributed on an "AS IS" BASIS,

  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  • See the License for the specific language governing permissions and

  • limitations under the License.

  • Copyright (c) 2018 Uber Technologies, Inc. *

  • Licensed under the Apache License, Version 2.0 (the "License");

  • you may not use this file except in compliance with the License.

  • You may obtain a copy of the License at *

  • http://www.apache.org/licenses/LICENSE-2.0 *

  • Unless required by applicable law or agreed to in writing, software

  • distributed under the License is distributed on an "AS IS" BASIS,

  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  • See the License for the specific language governing permissions and

  • limitations under the License.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsAWSAccessDeniedError

func IsAWSAccessDeniedError(err error) bool

IsAWSAccessDeniedError indicates whether an error is an AWS "access denied" error.

Types

type AWS

type AWS struct {
	// contains filtered or unexported fields
}

AWS is the default implementation of AWSProvider that talks to the real AWS.

func (*AWS) AssumeRole

func (a *AWS) AssumeRole(roleARN string, sessionName string) (*TemporaryCredentials, error)

AssumeRole calls sts:AssumeRole and returns temporary credentials.

func (*AWS) AssumeRoleWithMFA

func (a *AWS) AssumeRoleWithMFA(roleARN string, sessionName string, mfaDeviceARN string, mfaToken string) (*TemporaryCredentials, error)

AssumeRoleWithMFA calls sts:AssumeRole (with MFA information) and returns temporary credentials.

func (*AWS) CurrentPrincipalARN

func (a *AWS) CurrentPrincipalARN() (string, error)

CurrentPrincipalARN returns the ARN of the current IAM principal.

func (*AWS) MFADevices

func (a *AWS) MFADevices() ([]string, error)

MFADevices lists the MFA devices on the current user's account.

func (*AWS) Username

func (a *AWS) Username() (string, error)

Username returns the username of the current AWS user.

type AWSConfig

type AWSConfig struct {
	// contains filtered or unexported fields
}

AWSConfig represents the default AWS config files that exist on a system at ~/.aws/{config,credentials}. These two files are inherently linked for us, because while the credentials are stored in the credentials file, the metadata about these credentials are stored in the profile config file.

func NewAWSConfig

func NewAWSConfig(config AWSConfigOpts) (*AWSConfig, error)

NewAWSConfig returns a new AWSConfig, that will lazily read credentials and configuration from the default AWS config at ~/.aws.

func (*AWSConfig) GetCredentials

func (c *AWSConfig) GetCredentials(profileName string) (*TemporaryCredentials, error)

GetCredentials retrieves the named credentials from the AWS credential file.

func (*AWSConfig) GetProfile

func (c *AWSConfig) GetProfile(profileName string) (*ProfileConfiguration, error)

GetProfile returns the AWS profile metadata information from the shared config file.

func (*AWSConfig) SetCredentials

func (c *AWSConfig) SetCredentials(profileName string, creds *TemporaryCredentials) error

SetCredentials saves the credentials to the AWS credential file.

func (*AWSConfig) SetProfile

func (c *AWSConfig) SetProfile(profileName string, profile *ProfileConfiguration) error

SetProfile writes the specified profile information to the shared AWS config config file.

type AWSConfigOpts

type AWSConfigOpts struct {
	// ConfigFilePath is the path to the shared AWS config file, usually at
	// ~/.aws/config. If you leave this blank, the default location will be
	// used.
	ConfigFilePath string
	// CredentialsFilePath is the path to the shared AWS config file, usually
	// at ~/.aws/credentials. If you leave this blank, the default location
	// will be used.
	CredentialsFilePath string
}

AWSConfigOpts are the options for the AWSConfig.

type AWSConfigProvider

type AWSConfigProvider interface {
	GetCredentials(profileName string) (*TemporaryCredentials, error)
	SetCredentials(profileName string, creds *TemporaryCredentials) error
	GetProfile(profileName string) (*ProfileConfiguration, error)
	SetProfile(profileName string, profile *ProfileConfiguration) error
}

AWSConfigProvider is an interface to the AWS configuration (usually kept in files in ~/.aws).

type AWSProvider

type AWSProvider interface {
	AssumeRole(roleARN string, sessionName string) (*TemporaryCredentials, error)
	AssumeRoleWithMFA(roleARN string, sessionName string, mfaDeviceARN string, mfaToken string) (*TemporaryCredentials, error)
	MFADevices() ([]string, error)
	Username() (string, error)
	CurrentPrincipalARN() (string, error)
}

AWSProvider is an interface to AWS.

func NewAWS

func NewAWS() (AWSProvider, error)

NewAWS creates a new connection to AWS.

type App

type App struct {
	// contains filtered or unexported fields
}

App is the main AssumeRole app.

func NewApp

func NewApp(opts ...Option) (*App, error)

NewApp creates a new App.

func (*App) AssumeRole

func (app *App) AssumeRole(options AssumeRoleParameters) (*TemporaryCredentials, error)

AssumeRole takes a role name and calls AWS AssumeRole, returning a set of temporary credentials. If MFA is required, it will prompt for an MFA token interactively.

func (*App) CurrentPrincipalIsAssumedRole

func (app *App) CurrentPrincipalIsAssumedRole() (bool, error)

CurrentPrincipalIsAssumedRole returns true is the current principal is an assumed role.

type AssumeRoleParameters

type AssumeRoleParameters struct {
	// UserRole is the ARN of the role to be assumed
	UserRole string

	// RoleSessionName is the session name for the AWS AssumeRole call; if it is
	// the empty string, the current username will be used
	RoleSessionName string

	// When ForceRefresh is true, assumerole will bypass the local cache and do a
	// call to sts:AssumeRole to retrieve fresh credentials.
	ForceRefresh bool
}

AssumeRoleParameters are the parameters for the AssumeRole call

type Clock

type Clock interface {
	Now() time.Time
}

Clock is the clock interface we expect.

type Config

type Config struct {
	// RefreshBeforeExpiry is a duration prior to the credentials expiring
	// where we'll refresh them anyway. This is to prevent a command running
	// just before credentials are about to expire. Defaults to 15m.
	RefreshBeforeExpiry time.Duration `json:"refresh_before_expiry"`

	// RolePrefix allows the user to specify a prefix for the role ARN that
	// will be combined with what is specified as the role when executing the
	// app. For example, if the prefix is "arn:aws:iam::123:role/" and the user
	// executes the app with role "foobar", the final ARN will become:
	// "arn:aws:iam::123:role/foobar".
	RolePrefix string `json:"role_prefix"`

	// ProfileNamePrefix is a prefix that will prepended to the role name to
	// create the profile name under which the AWS configuration will be saved.
	ProfileNamePrefix string `json:"profile_name_prefix"`
}

Config is the config for the AssumeRole app.

func LoadConfig

func LoadConfig(configFilePath string) (*Config, error)

LoadConfig reads config values from a file and returns the config.

type Option

type Option func(*App) error

Option is an option for the App that allows for changing of options or dependency injection for testing.

func WithAWS

func WithAWS(aws AWSProvider) Option

WithAWS allows you to pass a custom AWSProvider for talking to AWS.

func WithAWSConfig

func WithAWSConfig(awsConfig AWSConfigProvider) Option

WithAWSConfig allows you to pass a custom AWSConfigProvider, which stores config and credentials for talking to AWS.

func WithClock

func WithClock(clock Clock) Option

WithClock allows you to specify a custom clock implementation (for tests).

func WithConfig

func WithConfig(config *Config) Option

WithConfig allows you to customise the configuration for the AssumeRole app itself.

func WithStderr

func WithStderr(stderr io.Writer) Option

WithStderr allows you to pass a custom stderr.

func WithStdin

func WithStdin(stdin io.Reader) Option

WithStdin allows you to pass a custom stdin.

type ProfileConfiguration

type ProfileConfiguration struct {
	Expires         time.Time
	MFASerial       string
	SourceProfile   string
	RoleARN         string
	RoleSessionName string
}

ProfileConfiguration holds the configuration from a single profile usually in ~/.aws/config.

type TemporaryCredentials

type TemporaryCredentials struct {
	AccessKeyID     string
	SecretAccessKey string
	SessionToken    string
	Expires         time.Time
}

TemporaryCredentials is a set of Amazon security credentials, along with an expiry.

Directories

Path Synopsis
cli
Package cli is reponsible for cli interaction * Copyright (c) 2018 Uber Technologies, Inc.
Package cli is reponsible for cli interaction * Copyright (c) 2018 Uber Technologies, Inc.
assume-role
* Copyright (c) 2018 Uber Technologies, Inc.
* Copyright (c) 2018 Uber Technologies, Inc.
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL