Skip to content

Commit

Permalink
Merge pull request #4 from openstandia/dev
Browse files Browse the repository at this point in the history
feat: support credential_process
  • Loading branch information
wadahiro committed Oct 7, 2021
2 parents 789d668 + 5e36411 commit ff2ad51
Show file tree
Hide file tree
Showing 23 changed files with 2,087 additions and 790 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,12 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

.DS_Store

bin/
dist/

*.key
*.crt

vendor/
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
NAME := aws-cli-oidc
VERSION := v0.5.1
VERSION := v0.6.0
REVISION := $(shell git rev-parse --short HEAD)

SRCS := $(shell find . -type f -name '*.go')
Expand All @@ -10,7 +10,7 @@ DIST_DIRS := find * -type d -exec
.DEFAULT_GOAL := bin/$(NAME)

bin/$(NAME): $(SRCS)
go build $(LDFLAGS) -o bin/$(NAME)
go build $(LDFLAGS) -o bin/$(NAME) cmd/aws-cli-oidc/*.go

.PHONY: clean
clean:
Expand All @@ -23,7 +23,7 @@ cross-build:
for os in darwin linux windows; do \
[ $$os = "windows" ] && EXT=".exe"; \
for arch in amd64; do \
GOOS=$$os GOARCH=$$arch CGO_ENABLED=0 go build -a -tags netgo -installsuffix netgo $(LDFLAGS) -o dist/$$os-$$arch/$(NAME)$$EXT; \
GOOS=$$os GOARCH=$$arch CGO_ENABLED=0 go build -a -tags netgo -installsuffix netgo $(LDFLAGS) -o dist/$$os-$$arch/$(NAME)$$EXT cmd/aws-cli-oidc/*.go; \
done; \
done

Expand Down
41 changes: 23 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

CLI tool for retrieving AWS temporary credentials using OIDC provider.


## How does it work?

[AWS Identity Providers and Federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html) supports IdPs that are compatible with [OpenID Connect (OIDC)](http://openid.net/connect/) or [SAML 2.0 (Security Assertion Markup Language 2.0)](https://wiki.oasis-open.org/security). This tool works with both types of IdP if it supports OIDC because it works as OIDC client. If the federation between the AWS account and the IdP is established, and an OIDC client for this tool is registered in the IdP, you can get AWS temporary credentials via standard browser login. It means you don't need to pass your credential of the IdP to this tool.
Expand All @@ -19,7 +18,6 @@ Please refer the following diagrams how it works.

![flow with saml2](flow-with-saml2.png)


## Prerequisite AWS and OIDC provider settings before using this tool

Before using this tool, the system administrator need to setup the following configuration.
Expand All @@ -39,22 +37,19 @@ Also depending on the federation type between AWS and the OIDC provider, require
- Of course, the OIDC provider must support not only OIDC but also SAML2 for federation between itself and AWS.
- The OIDC provider must support [OAuth 2.0 Token Exchange](https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-15) for exchanging access token/ID token and SAML2 assertion. `aws-cli-oidc` gets access token/ID token from the OIDC provider first, then it needs to get SAML2 assertion from the provider which is required for getting AWS temporary credentials using AWS STS API.


## Tested OIDC Provider

| OIDC Provider | OIDC | SAML2 |
| ---- | ---- | ---- |
| [Google account](https://accounts.google.com/.well-known/openid-configuration) | OK | - |
| [Keycloak](https://www.keycloak.org) | OK | OK (Note 1) |

* Note 1: You can't use SAML2 without extension which supports exchanging from access token to SAML2 assertion because Keycloak supports [OAuth 2.0 Token Exchange](https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-15) partially and doesn't support SAML2 assertion yet.
| OIDC Provider | OIDC | SAML2 |
| ------------------------------------------------------------------------------ | ---- | ----------- |
| [Google account](https://accounts.google.com/.well-known/openid-configuration) | OK | - |
| [Keycloak](https://www.keycloak.org) | OK | OK (Note 1) |

- Note 1: You need to use Keycloak 12 or higher that supports exchanging from access token to SAML2 assertion. Also, you need to enable Token Exchange feature.

## Install

Download from [Releases page](https://github.com/openstandia/aws-cli-oidc/releases).


## Usage

```
Expand All @@ -64,30 +59,30 @@ Usage:
aws-cli-oidc [command]
Available Commands:
get-cred Get AWS credentials and out to stdout
help Help about any command
setup Interactive setup of aws-cli-oidc
clear-secret Clear OS secret store that saves AWS credentials
completion generate the autocompletion script for the specified shell
get-cred Get AWS credentials and out to stdout
help Help about any command
setup Interactive setup of aws-cli-oidc
Flags:
-h, --help help for aws-cli-oidc
Use "aws-cli-oidc [command] --help" for more information about a command.
```


### Setup

Use `aws-cli-oidc setup` command and follow the guide.


### Get AWS temporary credentials

Use `aws-cli-oidc get-cred <your oidc provider name>` command. It opens your browser.
Use `aws-cli-oidc get-cred -p <your oidc provider name>` command. It opens your browser.
Now you can see the login page which the OIDC provider offers. Then do login.
If successful, AWS temporary credentials will be shown as below.

```
aws-cli-oidc get-cred myop
aws-cli-oidc get-cred -p myop
Using config file: /home/wadahiro/.aws-cli-oidc/config.yaml
Login successful!
Selected role: arn:aws:iam::123456789012:role/developer
Expand All @@ -99,12 +94,22 @@ export AWS_SECRET_ACCESS_KEY=9bkS0whPelMYQ.......
export AWS_SESSION_TOKEN=FQoGZXIvYXdzENz.......
```

### Integrate aws-cli

[Sourcing credentials with an external process](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sourcing-external.html) describes how to integrate aws-cli with external tool.
You can use `aws-cli-oidc` as the external process. Add the following lines to your `.aws/config` file.

```
[profile foo-developer]
credential_process=aws-cli-oidc get-cred -p myop -r arn:aws:iam::123456789012:role/developer -j -s -d 43200
```

Caution: The AWS temporary credentials will be saved into your OS secret store by using `-s` option to reduce authentication each time you use `aws-cli` tool.

## Licence

Licensed under the [MIT](/LICENSE) license.


## Author

- [Hiroyuki Wada](https://github.com/wadahiro)
25 changes: 25 additions & 0 deletions cmd/aws-cli-oidc/clear_secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"github.com/openstandia/aws-cli-oidc/lib"
"github.com/spf13/cobra"
)

var clearSecretCmd = &cobra.Command{
Use: "clear-secret",
Short: "Clear OS secret store that saves AWS credentials",
Long: `Clear OS secret store that saves AWS credentials.`,
Run: clearSecret,
}

func init() {
rootCmd.AddCommand(clearSecretCmd)
}

func clearSecret(cmd *cobra.Command, args []string) {
if err := lib.Clear(); err != nil {
lib.Writeln("Failed to clear the secret store")
lib.Exit(err)
}
lib.Write("The secret store has been cleared")
}
43 changes: 43 additions & 0 deletions cmd/aws-cli-oidc/get_cred.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import (
"github.com/openstandia/aws-cli-oidc/lib"
"github.com/spf13/cobra"
)

var getCredCmd = &cobra.Command{
Use: "get-cred <OIDC provider name>",
Short: "Get AWS credentials and out to stdout",
Long: `Get AWS credentials and out to stdout through your OIDC provider authentication.`,
Run: getCred,
}

func init() {
getCredCmd.Flags().StringP("provider", "p", "", "OIDC provider name")
getCredCmd.Flags().StringP("role", "r", "", "Override default assume role ARN")
getCredCmd.Flags().Int64P("max-duration", "d", 0, "Override default max session duration, in seconds, of the role session [900-43200]")
getCredCmd.Flags().BoolP("use-secret", "s", false, "Store AWS credentials into OS secret store, then load it without re-authentication")
getCredCmd.Flags().BoolP("json", "j", false, "Print the credential as JSON format")
rootCmd.AddCommand(getCredCmd)
}

func getCred(cmd *cobra.Command, args []string) {
providerName, _ := cmd.Flags().GetString("provider")
if providerName == "" {
lib.Writeln("The OIDC provider name is required")
lib.Exit(nil)
}

roleArn, _ := cmd.Flags().GetString("role")
maxDurationSeconds, _ := cmd.Flags().GetInt64("max-duration")
useSecret, _ := cmd.Flags().GetBool("use-secret")
asJson, _ := cmd.Flags().GetBool("json")

client, err := lib.CheckInstalled(providerName)
if err != nil {
lib.Writeln("Failed to login OIDC provider")
lib.Exit(err)
}

lib.Authenticate(client, roleArn, maxDurationSeconds, useSecret, asJson)
}
5 changes: 5 additions & 0 deletions cmd/aws-cli-oidc/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package main

func main() {
Execute()
}
33 changes: 33 additions & 0 deletions cmd/aws-cli-oidc/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"github.com/openstandia/aws-cli-oidc/lib"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var rootCmd = &cobra.Command{
Use: "aws-cli-oidc",
Short: "CLI tool for retrieving AWS temporary credentials using OIDC provider",
Long: `CLI tool for retrieving AWS temporary credentials using OIDC provider`,
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
lib.Writeln(err.Error())
}
}

func init() {
cobra.OnInitialize(initConfig)
}

func initConfig() {
viper.SetConfigFile(lib.ConfigPath() + "/config.yaml")

if err := viper.ReadInConfig(); err == nil {
lib.Writeln("Using config file: %s", viper.ConfigFileUsed())
}

lib.IsTraceEnabled = false // TODO: configuable
}
21 changes: 21 additions & 0 deletions cmd/aws-cli-oidc/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"github.com/openstandia/aws-cli-oidc/lib"
"github.com/spf13/cobra"
)

var setupCmd = &cobra.Command{
Use: "setup",
Short: "Interactive setup of aws-cli-oidc",
Long: `Interactive setup of aws-cli-oidc. Will prompt you for OIDC provider URL and other settings.`,
Run: setup,
}

func init() {
rootCmd.AddCommand(setupCmd)
}

func setup(cmd *cobra.Command, args []string) {
lib.RunSetup(nil)
}
47 changes: 0 additions & 47 deletions cmd/aws_oidc.go

This file was deleted.

Loading

0 comments on commit ff2ad51

Please sign in to comment.