github.com/versent/saml2aws@v2.17.0+incompatible/README.md (about) 1 # saml2aws [](https://travis-ci.org/Versent/saml2aws) [](https://ci.appveyor.com/project/davidobrien1985/saml2aws/branch/master) 2 3 CLI tool which enables you to login and retrieve [AWS](https://aws.amazon.com/) temporary credentials using 4 with [ADFS](https://msdn.microsoft.com/en-us/library/bb897402.aspx) or [PingFederate](https://www.pingidentity.com/en/products/pingfederate.html) Identity Providers. 5 6 This is based on python code from [ 7 How to Implement a General Solution for Federated API/CLI Access Using SAML 2.0](https://blogs.aws.amazon.com/security/post/TxU0AVUS9J00FP/How-to-Implement-a-General-Solution-for-Federated-API-CLI-Access-Using-SAML-2-0). 8 9 The process goes something like this: 10 11 * Setup an account alias, either using the default or given a name 12 * Prompt user for credentials 13 * Log in to Identity Provider using form based authentication 14 * Build a SAML assertion containing AWS roles 15 * Exchange the role and SAML assertion with [AWS STS service](https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html) to get a temporary set of credentials 16 * Save these credentials to an aws profile named "saml" 17 18 ## Table of Contents 19 20 - [Table of Contents](#table-of-contents) 21 - [Requirements](#requirements) 22 - [Caveats](#caveats) 23 - [Install](#install) 24 - [OSX](#osx) 25 - [Windows](#windows) 26 - [Dependency Setup](#dependency-setup) 27 - [Usage](#usage) 28 - [`saml2aws script`](#saml2aws-script) 29 - [Configuring IDP Accounts](#configuring-idp-accounts) 30 - [Example](#example) 31 - [Advanced Configuration](#advanced-configuration) 32 - [Dev Account Setup](#dev-account-setup) 33 - [Test Account Setup](#test-account-setup) 34 - [Building](#building) 35 - [Environment vars](#environment-vars) 36 - [Provider Specific Documentation](#provider-specific-documentation) 37 38 ## Requirements 39 40 * One of the supported Identity Providers 41 * ADFS (2.x or 3.x) 42 * PingFederate + PingId 43 * [Okta](pkg/provider/okta/README.md) 44 * KeyCloak + (TOTP) 45 * [Google Apps](pkg/provider/googleapps/README.md) 46 * [Shibboleth](pkg/provider/shibboleth/README.md) 47 * [F5APM](pkg/provider/f5apm/README.md) 48 * [PSU](pkg/provider/psu/README.md) 49 * AWS SAML Provider configured 50 51 ## Caveats 52 53 Aside from Okta, most of the providers in this project are using screen scraping to log users into SAML, this isn't ideal and hopefully vendors make this easier in the future. In addition to this there are some things you need to know: 54 55 1. AWS defaults to session tokens being issued with a duration of up to 3600 seconds (1 hour), this can now be configured as per [Enable Federated API Access to your AWS Resources for up to 12 hours Using IAM Roles](https://aws.amazon.com/blogs/security/enable-federated-api-access-to-your-aws-resources-for-up-to-12-hours-using-iam-roles/) and `--session-duration` flag. 56 2. Every SAML provider is different, the login process, MFA support is pluggable and therefore some work may be needed to integrate with your identity server 57 58 ## Install 59 60 ### OSX 61 62 If you're on OSX you can install saml2aws using homebrew! 63 64 ``` 65 brew tap versent/homebrew-taps 66 brew install saml2aws 67 ``` 68 69 ### Windows 70 71 If you're on Windows you can install saml2aws using chocolatey! 72 73 ``` 74 choco install saml2aws 75 saml2aws --version 76 ``` 77 78 ## Dependency Setup 79 80 Install the AWS CLI [see](https://docs.aws.amazon.com/cli/latest/userguide/installing.html), in our case we are using [homebrew](http://brew.sh/) on OSX. 81 82 ``` 83 brew install awscli 84 ``` 85 86 ## Usage 87 88 ``` 89 usage: saml2aws [<flags>] <command> [<args> ...] 90 91 A command line tool to help with SAML access to the AWS token service. 92 93 Flags: 94 --help Show context-sensitive help (also try --help-long 95 and --help-man). 96 --version Show application version. 97 --verbose Enable verbose logging 98 -i, --provider=PROVIDER This flag is obsolete. See: 99 https://github.com/Versent/saml2aws#configuring-idp-accounts 100 -a, --idp-account="default" The name of the configured IDP account. (env: 101 SAML2AWS_IDP_ACCOUNT) 102 --idp-provider=IDP-PROVIDER 103 The configured IDP provider. (env: 104 SAML2AWS_IDP_PROVIDER) 105 --mfa=MFA The name of the mfa. (env: SAML2AWS_MFA) 106 -s, --skip-verify Skip verification of server certificate. 107 --url=URL The URL of the SAML IDP server used to login. 108 (env: SAML2AWS_URL) 109 --username=USERNAME The username used to login. (env: 110 SAML2AWS_USERNAME) 111 --password=PASSWORD The password used to login. (env: 112 SAML2AWS_PASSWORD) 113 --mfa-token=MFA-TOKEN The current MFA token (supported in Keycloak, 114 ADFS). (env: SAML2AWS_MFA_TOKEN) 115 --role=ROLE The ARN of the role to assume. (env: 116 SAML2AWS_ROLE) 117 --aws-urn=AWS-URN The URN used by SAML when you login. (env: 118 SAML2AWS_AWS_URN) 119 --duo-mfa-option The MFA option you want to use to authenticate (env: SAML_DUO_MFA_OPTION) 120 --skip-prompt Skip prompting for parameters during login. 121 --exec-profile Execute the given command utilizing a specific profile from your ~/.aws/config file 122 --session-duration=SESSION-DURATION 123 The duration of your AWS Session. (env: 124 SAML2AWS_SESSION_DURATION) 125 126 Commands: 127 help [<command>...] 128 Show help. 129 130 configure [<flags>] 131 Configure a new IDP account. 132 133 login [<flags>] 134 Login to a SAML 2.0 IDP and convert the SAML assertion to an STS token. 135 136 exec [<flags>] [<command>...] 137 Exec the supplied command with env vars from STS token. 138 139 list-roles 140 List available role ARNs. 141 142 script [<flags>] 143 Emit a script that will export environment variables. 144 ``` 145 146 147 ### `saml2aws script` 148 149 If the `script` sub-command is called, `saml2aws` will output the following temporary security credentials: 150 ``` 151 export AWS_ACCESS_KEY_ID="ASIAI....UOCA" 152 export AWS_SECRET_ACCESS_KEY="DuH...G1d" 153 export AWS_SESSION_TOKEN="AQ...1BQ==" 154 export AWS_SECURITY_TOKEN="AQ...1BQ==" 155 SAML2AWS_PROFILE=saml 156 ``` 157 158 Powershell, and fish shells are supported as well. 159 160 If you use `eval $(saml2aws script)` frequently, you may want to create a alias for it: 161 162 zsh: 163 ``` 164 alias s2a="function(){eval $( $(command saml2aws) script --shell=bash --profile=$@);}" 165 ``` 166 167 bash: 168 ``` 169 function s2a { eval $( $(which saml2aws) script --shell=bash --profile=$@); } 170 ``` 171 172 ### `saml2aws exec` 173 174 If the `exec` sub-command is called, `saml2aws` will execute the command given as an argument: 175 By default saml2aws will execute the command with temp credentials generated via `saml2aws login`. 176 177 The `--exec-profile` flag allows for a command to execute using an aws profile which may have chained "assume role" actions. (via 'source_profile' in ~/.aws/config) *See section "blah" for scenario where this is useful as well as example below. 178 179 ``` 180 options: 181 --exec-profile Execute the given command utilizing a specific profile from your ~/.aws/config file 182 ``` 183 184 ### Configuring IDP Accounts 185 186 This is the *new* way of adding IDP provider accounts, it enables you to have named accounts with whatever settings you like and supports having one *default* account which is used if you omit the account flag. This replaces the --provider flag and old configuration file in 1.x. 187 188 To add a default IdP account to saml2aws just run the following command and follow the prompts. 189 190 ``` 191 $ saml2aws configure 192 ? Please choose a provider: Ping 193 ? AWS Profile myaccount 194 195 ? URL https://example.com 196 ? Username me@example.com 197 198 ? Password 199 No password supplied 200 201 account { 202 URL: https://example.com 203 Username: me@example.com 204 Provider: Ping 205 MFA: Auto 206 SkipVerify: false 207 AmazonWebservicesURN: urn:amazon:webservices 208 SessionDuration: 3600 209 Profile: myaccount 210 } 211 212 Configuration saved for IDP account: default 213 ``` 214 215 Then to login using this account. 216 217 ``` 218 saml2aws login 219 ``` 220 221 You can also add named accounts, below is an example where I am setting up an account under the `wolfeidau` alias, again just follow the prompts. 222 223 ``` 224 saml2aws configure -a wolfeidau 225 ``` 226 227 You can also configure the account alias without prompts. 228 229 ``` 230 saml2aws configure -a wolfeidau --idp-provider KeyCloak --username mark@wolfe.id.au \ 231 --url https://keycloak.wolfe.id.au/auth/realms/master/protocol/saml/clients/amazon-aws --skip-prompt 232 ``` 233 234 Then your ready to use saml2aws. 235 236 ## Example 237 238 Log into a service (without MFA). 239 240 ``` 241 $ saml2aws login 242 Using IDP Account default to access Ping https://id.example.com 243 To use saved password just hit enter. 244 Username [mark.wolfe@example.com]: 245 Password: ************ 246 247 Authenticating as mark.wolfe@example.com ... 248 Selected role: arn:aws:iam::123123123123:role/AWS-Admin-CloudOPSNonProd 249 Requesting AWS credentials using SAML assertion 250 Saving credentials 251 Logged in as: arn:aws:sts::123123123123:assumed-role/AWS-Admin-CloudOPSNonProd/wolfeidau@example.com 252 253 Your new access key pair has been stored in the AWS configuration 254 Note that it will expire at 2016-09-19 15:59:49 +1000 AEST 255 To use this credential, call the AWS CLI with the --profile option (e.g. aws --profile saml ec2 describe-instances). 256 ``` 257 258 Log into a service (with MFA). 259 260 ``` 261 $ saml2aws login 262 Using IDP Account default to access Ping https://id.example.com 263 To use saved password just hit enter. 264 Username [mark.wolfe@example.com]: 265 Password: ************ 266 267 Authenticating as mark.wolfe@example.com ... 268 Enter passcode: 123456 269 270 Selected role: arn:aws:iam::123123123123:role/AWS-Admin-CloudOPSNonProd 271 Requesting AWS credentials using SAML assertion 272 Saving credentials 273 Logged in as: arn:aws:sts::123123123123:assumed-role/AWS-Admin-CloudOPSNonProd/wolfeidau@example.com 274 275 Your new access key pair has been stored in the AWS configuration 276 Note that it will expire at 2016-09-19 15:59:49 +1000 AEST 277 To use this credential, call the AWS CLI with the --profile option (e.g. aws --profile saml ec2 describe-instances --region us-east-1). 278 ``` 279 280 ## Advanced Configuration 281 282 Configuring multiple accounts with custom role and profile in `~/.aws/config` with goal being isolation between infra code when deploying to these environments. This setup assumes you're using separate roles and probably AWS accounts for `dev` and `test` and is designed to help operations staff avoid accidentally deploying to the wrong AWS account in complex environments. Note that this method configures SAML authentication to each AWS account directly (in this case different AWS accounts). In the example below, separate authentication values are configured for AWS accounts 'profile=customer-dev/awsAccount=was 121234567890' and 'profile=customer-test/awsAccount=121234567891' 283 284 ### Dev Account Setup 285 286 To setup the dev account run the following and enter URL, username and password, and assign a standard role to be automatically selected on login. 287 288 ``` 289 saml2aws configure -a customer-dev --role=arn:aws:iam::121234567890:role/customer-admin-role -p customer-dev 290 ``` 291 292 This will result in the following configuration in `~/.saml2aws`. 293 294 ``` 295 [customer-dev] 296 url = https://id.customer.cloud 297 username = mark@wolfe.id.au 298 provider = Ping 299 mfa = Auto 300 skip_verify = false 301 timeout = 0 302 aws_urn = urn:amazon:webservices 303 aws_session_duration = 28800 304 aws_profile = customer-dev 305 role_arn = arn:aws:iam::121234567890:role/customer-admin-role 306 ``` 307 308 To use this you will need to export `AWS_DEFAULT_PROFILE=customer-dev` environment variable to target `dev`. 309 310 ### Test Account Setup 311 312 To setup the test account run the following and enter URL, username and password. 313 314 ``` 315 saml2aws configure -a customer-test --role=arn:aws:iam::121234567891:role/customer-admin-role -p customer-test 316 ``` 317 318 This results in the following configuration in `~/.saml2aws`. 319 320 ``` 321 [customer-test] 322 url = https://id.customer.cloud 323 username = mark@wolfe.id.au 324 provider = Ping 325 mfa = Auto 326 skip_verify = false 327 timeout = 0 328 aws_urn = urn:amazon:webservices 329 aws_session_duration = 28800 330 aws_profile = customer-test 331 role_arn = arn:aws:iam::121234567891:role/customer-admin-role 332 ``` 333 334 To use this you will need to export `AWS_DEFAULT_PROFILE=customer-test` environment variable to target `test`. 335 336 ## Advanced Configuration (Multiple AWS account access but SAML authenticate against a single 'SSO' AWS account) 337 338 Example: 339 (Authenticate to my 'SSO' AWS account. With this setup, there is no need to authenticate again. We can now rely on IAM to assume role cross account) 340 341 ~/.aws/credentials: #(these are generated by `saml2aws login`. Sets up SAML authentication into my AWS 'SSO' account) 342 ``` 343 [saml] 344 aws_access_key_id = AAAAAAAAAAAAAAAAB 345 aws_secret_access_key = duqhdZPRjEdZPRjE=dZPRjEhKjfB 346 aws_session_token = #REMOVED# 347 aws_security_token = #REMOVED# 348 x_principal_arn = arn:aws:sts::000000000123:assumed-role/myInitialAccount 349 x_security_token_expires = 2019-08-19T15:00:56-06:00 350 ``` 351 352 (Use AWS profiles to assume an aws role cross-account) 353 (Note that the "source_profile" is set to SAML which is my SSO AWS account since it is already authenticated) 354 355 ~/.aws/config: 356 ``` 357 [profile roleIn2ndAwsAccount] 358 source_profile=saml 359 role_arn=arn:aws:iam::123456789012:role/OtherRoleInAnyFederatedAccount # Note the different account number here 360 role_session_name=myAccountName 361 ``` 362 363 Running saml2aws without --exec-profile flag: 364 ``` 365 saml2aws exec aws sts get-caller-identity 366 { 367 "UserId": "AROAYAROAYAROAYOO:myInitialAccount", 368 "Account": "000000000123", 369 "Arn": "arn:aws:sts::000000000123:assumed-role/myInitialAccount" # This shows my 'SSO' account (SAML profile) 370 } 371 372 ``` 373 374 Running saml2aws with --exec-profile flag: 375 ``` 376 saml2aws exec --exec-profile roleIn2ndAwsAccount aws sts get-caller-identity 377 { 378 "UserId": "YOOYOOYOOYOOYOOA:/myAccountName", 379 "Account": "123456789012", 380 "Arn": "arn:aws:sts::123456789012:assumed-role/myAccountName" # When using '--exec-profile' I can assume-role into a # different AWS account without re-authenticating. 381 # Note that it does not re-authenitcate since we are 382 # alredy authenticated via the SSO account 383 } 384 ``` 385 386 As an example 387 388 ``` 389 saml2aws login 390 391 aws s3 ls --profile saml 392 393 An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied 394 # This is denied in this example because there are no S3 buckets in the 'SSO' AWS account 395 396 saml2aws exec --exec-profile roleIn2ndAwsAccount aws s3 ls # Runs given CMD with environment configured from --exec-profile role 397 398 # If we check env variables we see that our environment is configured with temporary credentials for our 'assumed role' 399 env | grep AWS 400 AWS_SESSION_TTL=12h 401 AWS_FEDERATION_TOKEN_TTL=12h 402 AWS_ASSUME_ROLE_TTL=1h 403 AWS_ACCESS_KEY_ID=AAAAAAAASORTENED 404 AWS_SECRET_ACCESS_KEY=secretShortened+6jJ5SMqsM5CkYi3Gw7 405 AWS_SESSION_TOKEN=ShortenedTokenXXX= 406 AWS_SECURITY_TOKEN=ShortenedSecurityTokenXXX= 407 408 # If we desire to execute multiple commands utilizing our assumed profile, we can obtain a new shell with Env variables configured for access 409 410 saml2aws exec --exec-profile roleIn2ndAwsAccount $SHELL # Get a new shell with AWS env vars configured for 'assumed role' account access 411 412 # We are now able to execute AWS cli commands with our assume role permissions 413 414 # Note that we do not need a --profile flag because our environment variables were set up for this access when we obtained a new shell with the --exec-profile flag 415 416 aws s3 ls 417 2019-07-30 01:32:59 264998d7606497040-sampleBucket 418 419 aws iam list-groups 420 { 421 "Groups": [ 422 { 423 "Path": "/", 424 "GroupName": "MyGroup", 425 "GroupId": "AGAGTENTENTENGOCQFK", 426 "Arn": "arn:aws:iam::123456789012:group/MyGroup", 427 "CreateDate": "2019-05-13T16:12:19Z" 428 ] 429 } 430 } 431 432 ## Building 433 434 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`. 435 436 ``` 437 make deps 438 ``` 439 440 Install the binary to `$GOPATH/bin`. 441 442 ``` 443 make install 444 ``` 445 446 Then to test the software just run. 447 448 ``` 449 make test 450 ``` 451 452 ## Environment vars 453 454 The exec sub command will export the following environment variables. 455 456 * AWS_ACCESS_KEY_ID 457 * AWS_SECRET_ACCESS_KEY 458 * AWS_SESSION_TOKEN 459 * AWS_SECURITY_TOKEN 460 * EC2_SECURITY_TOKEN 461 * AWS_PROFILE 462 * AWS_DEFAULT_PROFILE 463 464 Note: That profile environment variables enable you to use `exec` with a script or command which requires an explicit profile. 465 466 ## Provider Specific Documentation 467 468 * [Azure Active Directory](./doc/provider/aad) 469 * [JumpCloud](./doc/provider/jumpcloud) 470 471 # Dependencies 472 473 This tool would not be possible without some great opensource libraries. 474 475 * [goquery](https://github.com/PuerkitoBio/goquery) html querying 476 * [etree](https://github.com/beevik/etree) xpath selector 477 * [kingpin](https://github.com/alecthomas/kingpin) command line flags 478 * [aws-sdk-go](https://github.com/aws/aws-sdk-go) AWS Go SDK 479 * [go-ini](https://github.com/go-ini/ini) INI file parser 480 * [go-ntlmssp](https://github.com/Azure/go-ntlmssp) NTLM/Negotiate authentication 481 482 # Releasing 483 484 Install `github-release`. 485 486 ``` 487 go get github.com/buildkite/github-release 488 ``` 489 490 To release run. 491 492 ``` 493 make release 494 ``` 495 496 # Debugging Issues with IDPs 497 498 There are two levels of debugging, first emits debug information and the URL / Method / Status line of requests. 499 500 ``` 501 saml2aws login --verbose 502 ``` 503 504 The second emits the content of requests and responses, this includes authentication related information so don't copy and paste it into chat or tickets! 505 506 ``` 507 DUMP_CONTENT=true saml2aws login --verbose 508 ``` 509 510 # License 511 512 This code is Copyright (c) 2018 [Versent](http://versent.com.au) 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. 513