aws-oidc/cli/exec.go
2019-04-17 15:26:18 +12:00

142 lines
4.2 KiB
Go

package cli
import (
"encoding/json"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cognitoidentity"
"github.com/stoggi/aws-oidc/provider"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type ExecConfig struct {
RoleArn string
Duration int64
ProviderURL string
ClientID string
ClientSecret string
PKCE bool
Nonce bool
ReAuth bool
AgentCommant []string
}
// json metadata for AWS credential process. Ref: https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#sourcing-credentials-from-external-processes
type AwsCredentialHelperData struct {
Version int `json:"Version"`
AccessKeyID string `json:"AccessKeyId"`
SecretAccessKey string `json:"SecretAccessKey"`
SessionToken string `json:"SessionToken"`
Expiration string `json:"Expiration,omitempty"`
}
type LambdaPayload struct {
Role string `json:"role"`
Token string `json:"token"`
}
func ConfigureExec(app *kingpin.Application, config *GlobalConfig) {
execConfig := ExecConfig{}
cmd := app.Command("exec", "Execute a command with temporary AWS credentials")
cmd.Default()
cmd.Flag("role_arn", "The AWS role you want to assume").
StringVar(&execConfig.RoleArn)
cmd.Flag("duration", "The duration to assume the role for in seconds").
Default("3600").
Int64Var(&execConfig.Duration)
cmd.Flag("provider_url", "The OpenID Connect Provider URL").
Required().
StringVar(&execConfig.ProviderURL)
cmd.Flag("client_id", "The OpenID Connect Client ID").
Required().
StringVar(&execConfig.ClientID)
cmd.Flag("client_secret", "The OpenID Connect Client Secret").
Default("").
StringVar(&execConfig.ClientSecret)
cmd.Flag("pkce", "Use PKCE in the OIDC code flow").
Default("true").
BoolVar(&execConfig.PKCE)
cmd.Flag("nonce", "Require a nonce included and verified in the token").
Default("true").
BoolVar(&execConfig.Nonce)
cmd.Flag("reauth", "Require reauthentication by the identity provider").
Default("false").
BoolVar(&execConfig.ReAuth)
cmd.Arg("agent", "The executable and arguments of the local browser to use").
Default("open", "{}").
StringsVar(&execConfig.AgentCommant)
cmd.Action(func(c *kingpin.ParseContext) error {
ExecCommand(app, config, &execConfig)
return nil
})
}
func ExecCommand(app *kingpin.Application, config *GlobalConfig, execConfig *ExecConfig) {
providerConfig := &provider.ProviderConfig{
ClientID: execConfig.ClientID,
ClientSecret: execConfig.ClientSecret,
ProviderURL: execConfig.ProviderURL,
PKCE: execConfig.PKCE,
Nonce: execConfig.Nonce,
ReAuth: execConfig.ReAuth,
AgentCommand: execConfig.AgentCommant,
}
authResult, err := provider.Authenticate(providerConfig)
app.FatalIfError(err, "Error authenticating to identity provider: %v", err)
svc := cognitoidentity.New(session.New(&aws.Config{
Region: aws.String("ap-southeast-2"),
}))
inputGetID := &cognitoidentity.GetIdInput{
AccountId: aws.String("811702477007"),
IdentityPoolId: aws.String("ap-southeast-2:b0a04ab4-9989-4ee0-b9f7-9b1e56fe0f19"),
Logins: map[string]*string{
"cognito-idp.ap-southeast-2.amazonaws.com/ap-southeast-2_XloydykNV": aws.String(authResult.JWT),
},
}
getIDResult, err := svc.GetId(inputGetID)
app.FatalIfError(err, "Unable to get ID: %v", err)
inputGetCredentials := &cognitoidentity.GetCredentialsForIdentityInput{
IdentityId: getIDResult.IdentityId,
Logins: map[string]*string{
"cognito-idp.ap-southeast-2.amazonaws.com/ap-southeast-2_XloydykNV": aws.String(authResult.JWT),
},
}
credentialsResult, err := svc.GetCredentialsForIdentity(inputGetCredentials)
app.FatalIfError(err, "Unable to get credentials: %v", err)
expiry := *credentialsResult.Credentials.Expiration
credentialData := AwsCredentialHelperData{
Version: 1,
AccessKeyID: *credentialsResult.Credentials.AccessKeyId,
SecretAccessKey: *credentialsResult.Credentials.SecretKey,
SessionToken: *credentialsResult.Credentials.SessionToken,
Expiration: expiry.Format("2006-01-02T15:04:05Z"),
}
output, err := json.Marshal(credentialData)
if err != nil {
app.Fatalf("Error encoding credential json")
}
fmt.Println(string(output))
}