Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Commit 9e77da2

Browse files
thisisaaronlandsfomuseumbot
andauthored
Add code to derive temporary STS credentials for Cognito Identity provider (#2)
* snapshot: block out tool to derive creds from cognito * snapshot: derive credentials, not sure anything works though * rename aws-sts-credentials as aws-cognito-credentials * snapshot: add cmd/aws-credentials-json-to-ini * add docs for cognito and credentials json-to-ini stuff --------- Co-authored-by: sfomuseumbot <sfomuseumbot@localhost>
1 parent 975f1dc commit 9e77da2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+16511
-129
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ LDFLAGS=-s -w
44
cli:
55
go build -mod $(GOMOD) -ldflags="$(LDFLAGS)" -o bin/aws-mfa-session cmd/aws-mfa-session/main.go
66
go build -mod $(GOMOD) -ldflags="$(LDFLAGS)" -o bin/aws-get-credentials cmd/aws-get-credentials/main.go
7+
go build -mod $(GOMOD) -ldflags="$(LDFLAGS)" -o bin/aws-cognito-credentials cmd/aws-cognito-credentials/main.go
78
go build -mod $(GOMOD) -ldflags="$(LDFLAGS)" -o bin/aws-set-env cmd/aws-set-env/main.go
9+
go build -mod $(GOMOD) -ldflags="$(LDFLAGS)" -o bin/aws-credentials-json-to-ini cmd/aws-credentials-json-to-ini/main.go

README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,81 @@ go build -mod vendor -o bin/aws-get-credentials cmd/aws-get-credentials/main.go
1717
go build -mod vendor -o bin/aws-set-env cmd/aws-set-env/main.go
1818
```
1919

20+
## aws-cognito-credentials
21+
22+
`aws-cognito-credentials` generates temporary STS credentials for a given user in a Cognito identity pool.
23+
24+
```
25+
$> ./bin/aws-cognito-credentials -h
26+
Usage of ./bin/aws-cognito-credentials:
27+
-aws-config-uri string
28+
A valid github.com/aaronland/go-aws-auth.Config URI.
29+
-duration int
30+
The duration, in seconds, of the role session. Can not be less than 900. (default 900)
31+
-identity-pool-id string
32+
A valid AWS Cognito Identity Pool ID.
33+
-login value
34+
One or more key=value strings mapping to AWS Cognito authentication providers.
35+
-role-arn string
36+
A valid AWS IAM role ARN to assign to STS credentials.
37+
-role-session-name string
38+
An identifier for the assumed role session.
39+
```
40+
41+
For example:
42+
43+
```
44+
$> go bin/aws-cognito-credentials \
45+
-aws-config-uri 'aws://us-east-1?credentials=session' \
46+
-identity-pool-id us-east-1:{GUID} \
47+
-login org.sfomuseum=bob
48+
-role-session-name bob -role-arn 'arn:aws:iam::{ACCOUNT_ID}:role/{ROLE}' \
49+
50+
| jq
51+
52+
{
53+
"AccessKeyId": "...",
54+
"Expiration": "...",
55+
"SecretAccessKey": "...",
56+
"SessionToken": "..."
57+
}
58+
```
59+
60+
### aws-credentials-json-to-ini
61+
62+
`aws-credentials-json-to-ini` reads JSON-encoded AWS credentials information and generates an AWS ini-style configuration file with those data.
63+
64+
```
65+
$> ./bin/aws-credentials-json-to-ini -h
66+
Usage of ./bin/aws-credentials-json-to-ini:
67+
-ini string
68+
Path to the ini-style file where AWS credentials should be written. If "-" then data will be written to STDOUT.
69+
-json string
70+
Path to the JSON file containing AWS credentials. If "-" then data will be read from STDIN.
71+
-name string
72+
The name of the ini section where AWS credentials should be written. (default "default")
73+
-region string
74+
The AWS region for the AWS credentials. (default "us-east-1")
75+
```
76+
77+
For example:
78+
79+
```
80+
$> go bin/aws-cognito-credentials \
81+
-aws-config-uri 'aws://us-east-1?credentials=session' \
82+
-identity-pool-id us-east-1:{GUID} \
83+
-login org.sfomuseum=bob
84+
-role-session-name bob -role-arn 'arn:aws:iam::{ACCOUNT_ID}:role/{ROLE}' \
85+
86+
| ./bin/aws-credentials-json-to-ini -json - -ini -
87+
88+
[default]
89+
region = us-east-1
90+
aws_access_key_id = ...
91+
aws_secret_access_key = ...
92+
aws_session_token = ...
93+
```
94+
2095
### aws-get-credentials
2196

2297
`aws-get-credentials` is a command line tool to emit one or more keys from a given profile in an AWS .credentials file.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// aws-cognito-credentials generates temporary STS credentials for a given user in a Cognito identity pool.
2+
package main
3+
4+
import (
5+
"context"
6+
"encoding/json"
7+
"flag"
8+
"log"
9+
"os"
10+
11+
"github.com/aaronland/go-aws-auth"
12+
"github.com/sfomuseum/go-flags/multi"
13+
)
14+
15+
func main() {
16+
17+
var aws_config_uri string
18+
19+
var identity_pool_id string
20+
var role_arn string
21+
var role_session_name string
22+
var duration int
23+
24+
var kv_logins multi.KeyValueString
25+
26+
flag.StringVar(&aws_config_uri, "aws-config-uri", "", "A valid github.com/aaronland/go-aws-auth.Config URI.")
27+
28+
flag.StringVar(&identity_pool_id, "identity-pool-id", "", "A valid AWS Cognito Identity Pool ID.")
29+
flag.StringVar(&role_arn, "role-arn", "", "A valid AWS IAM role ARN to assign to STS credentials.")
30+
flag.StringVar(&role_session_name, "role-session-name", "", "An identifier for the assumed role session.")
31+
flag.IntVar(&duration, "duration", 900, "The duration, in seconds, of the role session. Can not be less than 900.") // Note: Can not be less than 900
32+
flag.Var(&kv_logins, "login", "One or more key=value strings mapping to AWS Cognito authentication providers.")
33+
34+
flag.Parse()
35+
36+
ctx := context.Background()
37+
38+
cfg, err := auth.NewConfig(ctx, aws_config_uri)
39+
40+
if err != nil {
41+
log.Fatalf("Failed to derive AWS config, %v", err)
42+
}
43+
44+
logins := make(map[string]string, 0)
45+
46+
for _, kv := range kv_logins {
47+
logins[kv.Key()] = kv.Value().(string)
48+
}
49+
50+
opts := &auth.STSCredentialsForDeveloperIdentityOptions{
51+
RoleArn: role_arn,
52+
RoleSessionName: role_session_name,
53+
Duration: int32(duration),
54+
IdentityPoolId: identity_pool_id,
55+
Logins: logins,
56+
}
57+
58+
creds, err := auth.STSCredentialsForDeveloperIdentity(ctx, cfg, opts)
59+
60+
if err != nil {
61+
log.Fatalf("Failed to derive credentials, %v", err)
62+
}
63+
64+
enc := json.NewEncoder(os.Stdout)
65+
err = enc.Encode(creds)
66+
67+
if err != nil {
68+
log.Fatalf("Failed to encode credentials, %v", err)
69+
}
70+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[{{.Name}}]
2+
region = {{ .Region }}
3+
aws_access_key_id = {{ .KeyId }}
4+
aws_secret_access_key = {{ .KeySecret }}
5+
aws_session_token = {{ .SessionToken }}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// aws-credentials-json-to-ini reads JSON-encoded AWS credentials information and generates an AWS ini-style configuration file with those data.
2+
package main
3+
4+
import (
5+
"bufio"
6+
_ "embed"
7+
"encoding/json"
8+
"flag"
9+
"fmt"
10+
"io"
11+
"log"
12+
"os"
13+
"text/template"
14+
15+
"github.com/aws/aws-sdk-go-v2/service/sts/types"
16+
)
17+
18+
//go:embed credentials.ini
19+
var credentials_t string
20+
21+
type CredentialsVars struct {
22+
Name string
23+
Region string
24+
KeyId string
25+
KeySecret string
26+
SessionToken string
27+
}
28+
29+
func main() {
30+
31+
var infile string
32+
var outfile string
33+
34+
var name string
35+
var region string
36+
37+
flag.StringVar(&infile, "json", "", "Path to the JSON file containing AWS credentials. If \"-\" then data will be read from STDIN.")
38+
flag.StringVar(&outfile, "ini", "", "Path to the ini-style file where AWS credentials should be written. If \"-\" then data will be written to STDOUT.")
39+
40+
flag.StringVar(&name, "name", "default", "The name of the ini section where AWS credentials should be written.")
41+
flag.StringVar(&region, "region", "us-east-1", "The AWS region for the AWS credentials.")
42+
43+
flag.Parse()
44+
45+
var r io.ReadCloser
46+
var wr io.WriteCloser
47+
48+
switch infile {
49+
case "-":
50+
br := bufio.NewReader(os.Stdin)
51+
r = io.NopCloser(br)
52+
default:
53+
54+
_r, err := os.Open(infile)
55+
56+
if err != nil {
57+
log.Fatalf("Failed to open %s for reading, %v", infile, err)
58+
}
59+
60+
r = _r
61+
}
62+
63+
defer r.Close()
64+
65+
switch outfile {
66+
case "-":
67+
wr = os.Stdout
68+
default:
69+
_wr, err := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE, 0600)
70+
71+
if err != nil {
72+
log.Fatalf("Failed to open %s for writing, %v", outfile, err)
73+
}
74+
75+
wr = _wr
76+
}
77+
78+
err := Convert(r, wr, name, region)
79+
80+
if err != nil {
81+
log.Fatalf("Failed to convert credentials, %v", err)
82+
}
83+
84+
err = wr.Close()
85+
86+
if err != nil {
87+
log.Fatalf("Failed to close %s after writing, %v", outfile, err)
88+
}
89+
90+
}
91+
92+
func Convert(r io.Reader, wr io.Writer, name string, region string) error {
93+
94+
t, err := template.New("credentials").Parse(credentials_t)
95+
96+
if err != nil {
97+
return fmt.Errorf("Failed to parse credentials template, %w", err)
98+
}
99+
100+
var creds *types.Credentials
101+
102+
dec := json.NewDecoder(r)
103+
err = dec.Decode(&creds)
104+
105+
if err != nil {
106+
return fmt.Errorf("Failed to decode credentials reader, %w", err)
107+
}
108+
109+
vars := CredentialsVars{
110+
Name: name,
111+
Region: region,
112+
KeyId: *creds.AccessKeyId,
113+
KeySecret: *creds.SecretAccessKey,
114+
SessionToken: *creds.SessionToken,
115+
}
116+
117+
err = t.Execute(wr, vars)
118+
119+
if err != nil {
120+
return fmt.Errorf("Failed to write credentials template, %w", err)
121+
}
122+
123+
return nil
124+
}

cmd/aws-get-credentials/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"os"
1010

1111
"github.com/aaronland/go-aws-auth"
12-
"github.com/go-ini/ini"
12+
"github.com/go-ini/ini"
1313
)
1414

1515
func main() {

cmd/aws-mfa-session/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// a given profile and multi-factor authentication (MFA) token and then writing that key and secret
33
// back to a "credentials" file in a specific profile section. For example, when used in a Makefile with
44
// https://github.com/Yubico/yubikey-manager/tree/master/ykman
5+
//
56
// $(eval CODE := $(shell ykman oath code sfomuseum:aws | awk '{ print $$2 }'))
67
// bin/$aws-mfa-session -code $(CODE) -duration PT8H
78
package main
@@ -15,7 +16,7 @@ import (
1516
"time"
1617

1718
"github.com/aaronland/go-aws-auth"
18-
"github.com/sfomuseum/iso8601duration"
19+
"github.com/sfomuseum/iso8601duration"
1920
)
2021

2122
func readline(prompt string) string {

cmd/aws-set-env/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import (
66
"flag"
77
"log"
88
"os"
9-
9+
1010
"github.com/aaronland/go-aws-auth"
11-
"github.com/go-ini/ini"
11+
"github.com/go-ini/ini"
1212
)
1313

1414
func main() {

cmd/aws-sign/main.go

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)