saml2aws

package module
v1.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 7, 2017 License: MIT Imports: 21 Imported by: 50

README

saml2aws

CLI tool which enables you to login and retrieve AWS temporary credentials using SAML with ADFS or PingFederate Identity Providers.

This is based on python code from How to Implement a General Solution for Federated API/CLI Access Using SAML 2.0.

The process goes something like this:

  • Prompt user for credentials
  • Log in to Identity Provider using form based authentication
  • Build a SAML assertion containing AWS roles
  • Exchange the role and SAML assertion with AWS STS service to get a temporary set of credentials
  • Save these creds to an aws profile named "saml"

Requirements

  • Identity Provider
    • ADFS (2.x or 3.x)
    • PingFederate + PingId
  • AWS SAML Provider configured

Usage

usage: saml2aws [<flags>] <command> [<args> ...]

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).
  -p, --profile="saml"  The AWS profile to save the temporary credentials
  -s, --skip-verify     Skip verification of server certificate.
  -i, --provider="ADFS" The type of SAML IDP provider.
      --version         Show application version.

Commands:
  help [<command>...]
    Show help.


  login
    Login to a SAML 2.0 IDP and convert the SAML assertion to an STS token.


  exec [<command>...]
    Exec the supplied command with env vars from STS token.

saml2aws will default to using ADFS 3.x as the Identity Provider. To use another provider, use the --provider flag:

IdP
ADFS 2.x --provider=ADFS2
PingFederate --provider=Ping
JumpCloud --provider=JumpCloud

Install

If your on OSX you can install saml2aws using homebrew!

brew tap versent/homebrew-taps
brew install saml2aws

Setup

Install the AWS CLI see https://docs.aws.amazon.com/cli/latest/userguide/installing.html, in our case we are using homebrew on OSX.

brew install awscli

Configure an empty default profile with your region of choice.

$ aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: us-west-2
Default output format [None]:

Then your ready to use saml2aws.

Example

Log into a service.

$ saml2aws login
Hostname [id.example.com]:
Username [mark.wolfe@example.com]:
Password: ************

ADFS https://id.example.com
Authenticating to ADFS...
Please choose the role you would like to assume:
[ 0 ]:  arn:aws:iam::123123123123:role/AWS-Admin-CloudOPSBuild
[ 1 ]:  arn:aws:iam::123123123123:role/AWS-Admin-CloudOPSNonProd
Selection: 1
Selected role: arn:aws:iam::123123123123:role/AWS-Admin-CloudOPSNonProd
Requesting AWS credentials using SAML assertion
Saving credentials
Logged in as: arn:aws:sts::123123123123:assumed-role/AWS-Admin-CloudOPSNonProd/wolfeidau@example.com

Your new access key pair has been stored in the AWS configuration
Note that it will expire at 2016-09-19 15:59:49 +1000 AEST
To use this credential, call the AWS CLI with the --profile option (e.g. aws --profile saml ec2 describe-instances).

Run ansible with an expired token present, exec verifies the token and requests login.

$ saml2aws exec --skip-verify -- ansible-playbook -e "aws_region=ap-southeast-2" playbook.yml
Hostname [id.example.com]:
Username [mark.wolfe@example.com]:
Password: ************

ADFS https://id.example.com
Authenticating to ADFS...
Please choose the role you would like to assume:
[ 0 ]:  arn:aws:iam::123123123123:role/AWS-Admin-CloudOPSBuild
[ 1 ]:  arn:aws:iam::123123123123:role/AWS-Admin-CloudOPSNonProd
Selection: 1
Selected role: arn:aws:iam::123123123123:role/AWS-Admin-CloudOPSNonProd
Requesting AWS credentials using SAML assertion
Saving credentials
Logged in as: arn:aws:sts::123123123123:assumed-role/AWS-Admin-CloudOPSNonProd/wolfeidau@example.com

Your new access key pair has been stored in the AWS configuration
Note that it will expire at 2016-09-19 15:59:49 +1000 AEST
To use this credential, call the AWS CLI with the --profile option (e.g. aws --profile saml ec2 describe-instances).

PLAY [create cloudformation stack] *************************************************

...

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0

Building

To build this software on osx clone to the repo to $GOPATH/src/github.com/versent/saml2aws and ensure you have $GOPATH/bin in your $PATH.

If you don't have glide installed you can install it using homebrew.

brew install glide

Then to build the software just run.

make

Install the binary to $GOPATH/bin.

make install

To release run.

make release

Environment vars

The exec sub command will export the following environment variables.

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_SESSION_TOKEN
  • AWS_SECURITY_TOKEN
  • EC2_SECURITY_TOKEN

Dependencies

This tool would not be possible without some great opensource libraries.

License

This code is Copyright (c) 2015 Versent and released under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE.md file for more details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrCredentialsHomeNotFound returned when a user home directory can't be located.
	ErrCredentialsHomeNotFound = errors.New("user home directory not found")

	// ErrCredentialsNotFound returned when the required aws credentials don't exist.
	ErrCredentialsNotFound = errors.New("aws credentials not found")
)
View Source
var (
	// ErrConfigHomeNotFound returned when a user home directory can't be located.
	ErrConfigHomeNotFound = errors.New("user home directory not found")

	// ErrConfigFileNotFound returned when the required aws credentials file doesn't exist.
	ErrConfigFileNotFound = errors.New("aws credentials file not found")
)
View Source
var (
	ErrMissingAssertion = ErrMissingElement{Tag: assertionTag}
)

ErrMissingAssertion indicates that an appropriate assertion element could not be found in the SAML Response

Functions

func ExtractAwsRoles

func ExtractAwsRoles(data []byte) ([]string, error)

ExtractAwsRoles given an assertion document extract the aws roles

Types

type ADFS2Client added in v1.4.0

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

func NewADFS2Client added in v1.4.0

func NewADFS2Client(skipVerify bool) (*ADFS2Client, error)

func (*ADFS2Client) Authenticate added in v1.4.0

func (ac *ADFS2Client) Authenticate(loginDetails *LoginDetails) (string, error)

type ADFSClient

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

ADFSClient wrapper around ADFS enabling authentication and retrieval of assertions

func NewADFSClient

func NewADFSClient(skipVerify bool) (*ADFSClient, error)

NewADFSClient create a new ADFS client

func (*ADFSClient) Authenticate

func (ac *ADFSClient) Authenticate(loginDetails *LoginDetails) (string, error)

Authenticate authenticate to ADFS and return the data from the body of the SAML assertion.

type AWSAccount added in v1.5.0

type AWSAccount struct {
	Name  string
	Roles []*AWSRole
}

func ExtractAWSAccounts added in v1.5.0

func ExtractAWSAccounts(data []byte) ([]*AWSAccount, error)

func ParseAWSAccounts added in v1.5.0

func ParseAWSAccounts(samlAssertion string) ([]*AWSAccount, error)

type AWSRole

type AWSRole struct {
	RoleARN      string
	PrincipalARN string
	Name         string
}

AWSRole aws role attributes

func ParseAWSRoles added in v1.3.0

func ParseAWSRoles(roles []string) ([]*AWSRole, error)

ParseAWSRoles parses and splits the roles while also validating the contents

func PromptForAWSRoleSelection

func PromptForAWSRoleSelection(accounts []*AWSAccount) (*AWSRole, error)

PromptForAWSRoleSelection present a list of roles to the user for selection

type ConfigLoader added in v1.1.0

type ConfigLoader struct {
	Filename string
	Profile  string
}

ConfigLoader loads config options

func NewConfigLoader added in v1.1.0

func NewConfigLoader(profile string) *ConfigLoader

NewConfigLoader helper to create the config

func (*ConfigLoader) LoadHostname added in v1.1.0

func (p *ConfigLoader) LoadHostname() (string, error)

LoadHostname load the hostname

func (*ConfigLoader) LoadProvider added in v1.3.0

func (p *ConfigLoader) LoadProvider(defaultValue string) (string, error)

LoadProvider load the provider

func (*ConfigLoader) LoadUsername added in v1.1.0

func (p *ConfigLoader) LoadUsername() (string, error)

LoadUsername load the username

func (*ConfigLoader) SaveHostname added in v1.1.0

func (p *ConfigLoader) SaveHostname(hostname string) error

SaveHostname persist the hostname

func (*ConfigLoader) SaveProvider added in v1.3.0

func (p *ConfigLoader) SaveProvider(provider string) error

SaveProvider persist the provider

func (*ConfigLoader) SaveUsername added in v1.1.0

func (p *ConfigLoader) SaveUsername(username string) error

SaveUsername persist the username

type CredentialsProvider

type CredentialsProvider struct {
	Filename string
	Profile  string
}

CredentialsProvider loads aws credentials file

func NewSharedCredentials

func NewSharedCredentials(profile string) *CredentialsProvider

NewSharedCredentials helper to create the credentials provider

func (*CredentialsProvider) Load added in v1.2.0

func (p *CredentialsProvider) Load() (string, string, string, error)

Load load the aws credentials file

func (*CredentialsProvider) Save

func (p *CredentialsProvider) Save(id, secret, token string) error

Save persist the credentials

type ErrMissingElement

type ErrMissingElement struct {
	Tag, Attribute string
}

ErrMissingElement is the error type that indicates an element and/or attribute is missing. It provides a structured error that can be more appropriately acted upon.

func (ErrMissingElement) Error

func (e ErrMissingElement) Error() string

type JumpCloudClient added in v1.5.0

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

JumpCloudClient is a wrapper representing a JumpCloud SAML client

func NewJumpCloudClient added in v1.5.0

func NewJumpCloudClient(skipVerify bool) (*JumpCloudClient, error)

NewJumpCloudClient creates a new JumpCloud client

func (*JumpCloudClient) Authenticate added in v1.5.0

func (jc *JumpCloudClient) Authenticate(loginDetails *LoginDetails) (string, error)

Authenticate logs into JumpCloud and returns a SAML response

type LoginDetails added in v1.1.0

type LoginDetails struct {
	Username string
	Password string
	Hostname string
}

LoginDetails used to authenticate to ADFS

func PromptForLoginDetails added in v1.1.0

func PromptForLoginDetails(username, hostname string) (*LoginDetails, error)

PromptForLoginDetails prompt the user to present their username, password and hostname

type PingFedClient added in v1.3.0

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

PingFedClient wrapper around PingFed + PingId enabling authentication and retrieval of assertions

func NewPingFedClient added in v1.3.0

func NewPingFedClient(skipVerify bool) (*PingFedClient, error)

NewPingFedClient create a new PingFed client

func (*PingFedClient) Authenticate added in v1.3.0

func (ac *PingFedClient) Authenticate(loginDetails *LoginDetails) (string, error)

Authenticate Authenticate to PingFed and return the data from the body of the SAML assertion.

type Provider added in v1.3.0

type Provider int

Provider the SAML provider

const (
	// ADFS 3.x provider
	ADFS Provider = iota
	// Ping provider
	Ping
)

type SAMLClient added in v1.3.0

type SAMLClient interface {
	Authenticate(loginDetails *LoginDetails) (string, error)
}

SAMLClient client interface

func NewSAMLClient added in v1.3.0

func NewSAMLClient(opts *SAMLOptions) (SAMLClient, error)

NewSAMLClient create a new SAML client

type SAMLOptions added in v1.3.0

type SAMLOptions struct {
	SkipVerify bool
	Provider   string
}

SAMLOptions options for the new SAML client

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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