Skip to content

Commit

Permalink
Initial code
Browse files Browse the repository at this point in the history
  • Loading branch information
emilio5072 committed Mar 3, 2024
1 parent 63c3237 commit 65ddfe0
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 0 deletions.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# aws-session-go

## A simple tool to generate an AWS MFA session

> **NOTES:** <br>
> - Expects to use config file and not environment variables for your local aws config (A custom file can be specified)
> - Expects MFA device to be named the same as your IAM username (This can be adjusted if needed. Please just submit a PR or issue)
> - Currently only supports for IAM users (SSO and other users can be included later)
> - ==This tool will modify your aws credentials file if not alternate credentials file is specified==
### **Usage**
```
Usage of aws-session-go:
-creds-file string
Path to AWS credentials file
-duration int
Duration in seconds (default 3600)
-help
Show usage
-mfa-token string
MFA token (required)
-profile string
AWS profile (default "default")
```

### Examples
```
Usage: go run main.go -mfa-token <mfa-token> -profile <profile> -duration <duration> -config-file <path/to/credentials/file>
Example: go run main.go -mfa-token 123456 -profile default -duration 3600 -config-file /path/to/credentials/file
```

#### *Installation*
```
git clone https://github.com/emilio507/aws-session-go.git
cd aws-session-go
go build .
sudo mv aws-session-go /usr/local/bin
aws-session-go -h
```
20 changes: 20 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module aws-session-go

go 1.22.0

require (
github.com/aws/aws-sdk-go-v2 v1.25.2 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.4 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.4 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.1 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
28 changes: 28 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
github.com/aws/aws-sdk-go-v2 v1.25.2 h1:/uiG1avJRgLGiQM9X3qJM8+Qa6KRGK5rRPuXE0HUM+w=
github.com/aws/aws-sdk-go-v2 v1.25.2/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
github.com/aws/aws-sdk-go-v2/config v1.27.4 h1:AhfWb5ZwimdsYTgP7Od8E9L1u4sKmDW2ZVeLcf2O42M=
github.com/aws/aws-sdk-go-v2/config v1.27.4/go.mod h1:zq2FFXK3A416kiukwpsd+rD4ny6JC7QSkp4QdN1Mp2g=
github.com/aws/aws-sdk-go-v2/credentials v1.17.4 h1:h5Vztbd8qLppiPwX+y0Q6WiwMZgpd9keKe2EAENgAuI=
github.com/aws/aws-sdk-go-v2/credentials v1.17.4/go.mod h1:+30tpwrkOgvkJL1rUZuRLoxcJwtI/OkeBLYnHxJtVe0=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 h1:AK0J8iYBFeUk2Ax7O8YpLtFsfhdOByh2QIkHmigpRYk=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2/go.mod h1:iRlGzMix0SExQEviAyptRWRGdYNo3+ufW/lCzvKVTUc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 h1:bNo4LagzUKbjdxE0tIcR9pMzLR2U/Tgie1Hq1HQ3iH8=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2/go.mod h1:wRQv0nN6v9wDXuWThpovGQjqF1HFdcgWjporw14lS8k=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 h1:EtOU5jsPdIQNP+6Q2C5e3d65NKT1PeCiQk+9OdzO12Q=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2/go.mod h1:tyF5sKccmDz0Bv4NrstEr+/9YkSPJHrcO7UsUKf7pWM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2 h1:5ffmXjPtwRExp1zc7gENLgCPyHFbhEPwVTkTiH9niSk=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2/go.mod h1:Ru7vg1iQ7cR4i7SZ/JTLYN9kaXtbL69UdgG0OQWQxW0=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 h1:utEGkfdQ4L6YW/ietH7111ZYglLJvS+sLriHJ1NBJEQ=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1/go.mod h1:RsYqzYr2F2oPDdpy+PdhephuZxTfjHQe7SOBcZGoAU8=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 h1:9/GylMS45hGGFCcMrUZDVayQE1jYSIN6da9jo7RAYIw=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1/go.mod h1:YjAPFn4kGFqKC54VsHs5fn5B6d+PCY2tziEa3U/GB5Y=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.1 h1:3I2cBEYgKhrWlwyZgfpSO2BpaMY1LHPqXYk/QGlu2ew=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.1/go.mod h1:uQ7YYKZt3adCRrdCBREm1CD3efFLOUNH77MrUCvx5oA=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
135 changes: 135 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package main

import (
"fmt"
"context"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/sts"
"strings"
"flag"
)

type inputArgs struct {
mfaToken string
duration int32
profile string
credFile string
}

func main() {
mfaToken := flag.String("mfa-token", "", "MFA token (required)")
profile := flag.String("profile", "default", "AWS profile")
duration := flag.Int("duration", 3600, "Duration in seconds")
credFile := flag.String("creds-file", "", "Path to AWS credentials file")
help:= flag.Bool("help", false, "Show usage")
flag.Parse()

if *help {
fmt.Println("Usage: go run main.go -mfa-token <mfa-token> -profile <profile> -duration <duration> -config-file <path/to/credentials/file>")
fmt.Println("Example: go run main.go -mfa-token 123456 -profile default -duration 3600 -config-file /path/to/credentials/file")
return
}

if *mfaToken == ""{
fmt.Println("MFA token is required")
fmt.Println("Usage: go run main.go -mfa-token <mfa-token> -profile <profile> -duration <duration> -config-file <path/to/credentials/file>")
fmt.Println("Example: go run main.go -mfa-token 123456 -profile default -duration 3600 -config-file /path/to/credentials/file")
return
}

fmt.Println("MFA Token: ", *mfaToken)
fmt.Println("Profile: ", *profile)
fmt.Println("Duration: ", *duration)
fmt.Println("Config File: ", *credFile)



if *duration < 900 || *duration > 43200 {
fmt.Println("Duration must be between 900 and 43200 seconds (15 minutes and 12 hours)")
return
}

sessionArgs := inputArgs{
mfaToken: *mfaToken,
profile: *profile,
duration: int32(*duration),
credFile: *credFile,
}

cfg := aws.Config{}
err := error(nil)
if sessionArgs.credFile != "" {
cfg, err = config.LoadDefaultConfig(
context.TODO(),
config.WithSharedConfigProfile(sessionArgs.profile),
//config.WithSharedConfigFiles([]string{sessionArgs.credFile}),
config.WithSharedCredentialsFiles([]string{sessionArgs.credFile}),
)
} else {
cfg, err = config.LoadDefaultConfig(
context.TODO(),
config.WithSharedConfigProfile(sessionArgs.profile),
//config.WithSharedConfigProfile("default"),
)
}

if err != nil {
fmt.Println("Error loading configuration, ", err)
return
}


// Below is how to retrieve credentials from the config and print them
/*
data, retErr := cfg.Credentials.Retrieve(context.Background())
if retErr != nil {
fmt.Println("Error retrieving credentials, ", retErr)
fmt.Println("Please ensure you have a default profile in your ~/.aws/credentials file at minimum. If you have a different profile, you can specify it as an argument to this program. Example: go run main.go 123456 my-profile 3600")
return
}
// fmt.Println("Access Key: ", data.AccessKeyID)
// fmt.Println("Secret Key: ", data.SecretAccessKey)
// fmt.Println("Session Token: ", data.SessionToken)
// fmt.Println("Region: ", cfg.Region)
*/

if cfg.Region == "" {
cfg.Region = "us-west-2"
}

client := sts.NewFromConfig(cfg)
idInput := &sts.GetCallerIdentityInput{}
idResult, idErr := client.GetCallerIdentity(context.Background(), idInput)
if idErr != nil {
fmt.Println("Error getting identity: %s ", idErr)
}

serialNumber := strings.Replace(*idResult.Arn, "user", "mfa", 1)
sessionInput := &sts.GetSessionTokenInput{
DurationSeconds: &sessionArgs.duration,
SerialNumber: &serialNumber,
TokenCode : &sessionArgs.mfaToken,
}

sessionResult, sessionErr := client.GetSessionToken(context.Background(), sessionInput)
if sessionErr != nil {
fmt.Println("Error getting session token: ", sessionErr)
return
}

/*
fmt.Println("Session Access Key: ", *sessionResult.Credentials.AccessKeyId)
fmt.Printf("Type: %T\n", *sessionResult.Credentials.AccessKeyId)
fmt.Println("Session Secret Key: ", *sessionResult.Credentials.SecretAccessKey)
fmt.Printf("Type: %T\n", *sessionResult.Credentials.SecretAccessKey)
fmt.Println("Session Token: ", *sessionResult.Credentials.SessionToken)
fmt.Printf("Type: %T\n", *sessionResult.Credentials.SessionToken)
fmt.Println("Session Expiration: ", *sessionResult.Credentials.Expiration)
fmt.Printf("Type: %T\n", *sessionResult.Credentials.Expiration)
*/


updateConfig(sessionArgs.credFile, sessionArgs.profile + "-session", *sessionResult.Credentials.AccessKeyId, *sessionResult.Credentials.SecretAccessKey, *sessionResult.Credentials.SessionToken)
}
42 changes: 42 additions & 0 deletions updateIni.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

import (
"fmt"
"gopkg.in/ini.v1"
"os/user"
)

func updateConfig(credFile string, profile string, accessKey string, secretKey string, sessionToken string) {
if credFile == "" {
usr, err := user.Current()
if err != nil {
fmt.Println("Error getting current user: ", err)
return
}
credFile = usr.HomeDir + "/.aws/credentials"
}
cfg, err := ini.Load(credFile)
if err != nil {
fmt.Println("Error loading credentials file: ", err)
return
}

if cfg.HasSection(profile) {
cfg.Section(profile).Key("aws_access_key_id").SetValue(accessKey)
cfg.Section(profile).Key("aws_secret_access_key").SetValue(secretKey)
cfg.Section(profile).Key("aws_session_token").SetValue(sessionToken)
} else {
cfg.NewSection(profile)
cfg.Section(profile).Key("aws_access_key_id").SetValue(accessKey)
cfg.Section(profile).Key("aws_secret_access_key").SetValue(secretKey)
cfg.Section(profile).Key("aws_session_token").SetValue(sessionToken)
}

err = cfg.SaveTo(credFile)
if err != nil {
fmt.Println("Error saving to credentials file: ", err)
return
}

fmt.Println("Updated credentials file with new session token. Profile: ", profile)
}

0 comments on commit 65ddfe0

Please sign in to comment.