Skip to content

Commit

Permalink
continue ecs cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
synfinatic committed Jul 9, 2024
1 parent a7cd2fe commit a874e6e
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 47 deletions.
46 changes: 23 additions & 23 deletions cmd/aws-sso/ecs_client_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,18 @@ import (
"github.com/synfinatic/gotable"
)

type EcsListCmd struct {
Server string `kong:"help='Endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

type EcsLoadCmd struct {
// AWS Params
Arn string `kong:"short='a',help='ARN of role to assume',env='AWS_SSO_ROLE_ARN',predictor='arn'"`
AccountId int64 `kong:"name='account',short='A',help='AWS AccountID of role to assume',env='AWS_SSO_ACCOUNT_ID',predictor='accountId',xor='account'"`
Role string `kong:"short='R',help='Name of AWS Role to assume',env='AWS_SSO_ROLE_NAME',predictor='role',xor='role'"`
Profile string `kong:"short='p',help='Name of AWS Profile to assume',predictor='profile',xor='account,role'"`
Arn string `kong:"short='a',help='ARN of role to load',env='AWS_SSO_ROLE_ARN',predictor='arn'"`
AccountId int64 `kong:"name='account',short='A',help='AWS AccountID of role to load',env='AWS_SSO_ACCOUNT_ID',predictor='accountId',xor='account'"`
Role string `kong:"short='R',help='Name of AWS Role to load',env='AWS_SSO_ROLE_NAME',predictor='role',xor='role'"`
Profile string `kong:"short='p',help='Name of AWS Profile to load',predictor='profile',xor='account,role'"`

// Other params
Server string `kong:"help='Endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
Slotted bool `kong:"short='s',help='Load credentials in a unique slot using the ProfileName as the key'"`
}

type EcsProfileCmd struct {
Server string `kong:"help='URL endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

type EcsUnloadCmd struct {
Profile string `kong:"short='p',help='Name of AWS Profile to unload',predictor='profile'"`
Server string `kong:"help='Endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

func (cc *EcsLoadCmd) Run(ctx *RunContext) error {
sci := NewSelectCliArgs(ctx.Cli.Ecs.Load.Arn, ctx.Cli.Ecs.Load.AccountId, ctx.Cli.Ecs.Load.Role, ctx.Cli.Ecs.Load.Profile)
if awssso, err := sci.Update(ctx); err == nil {
Expand All @@ -70,6 +57,10 @@ func (cc *EcsLoadCmd) Run(ctx *RunContext) error {
return ctx.PromptExec(ecsLoadCmd)
}

type EcsProfileCmd struct {
Server string `kong:"help='URL endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

func (cc *EcsProfileCmd) Run(ctx *RunContext) error {
c := newClient(ctx.Cli.Ecs.Profile.Server, ctx)

Expand All @@ -88,12 +79,6 @@ func (cc *EcsProfileCmd) Run(ctx *RunContext) error {
return listProfiles(profiles)
}

func (cc *EcsUnloadCmd) Run(ctx *RunContext) error {
c := newClient(ctx.Cli.Ecs.Unload.Server, ctx)

return c.Delete(ctx.Cli.Ecs.Unload.Profile)
}

// Loads our AWS API creds into the ECS Server
func ecsLoadCmd(ctx *RunContext, awssso *sso.AWSSSO, accountId int64, role string) error {
c := newClient(ctx.Cli.Ecs.Load.Server, ctx)
Expand Down Expand Up @@ -122,6 +107,10 @@ func ecsLoadCmd(ctx *RunContext, awssso *sso.AWSSSO, accountId int64, role strin
return c.SubmitCreds(creds, rFlat.Profile, ctx.Cli.Ecs.Load.Slotted)
}

type EcsListCmd struct {
Server string `kong:"help='Endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

func (cc *EcsListCmd) Run(ctx *RunContext) error {
c := newClient(ctx.Cli.Ecs.Profile.Server, ctx)

Expand All @@ -137,6 +126,17 @@ func (cc *EcsListCmd) Run(ctx *RunContext) error {
return listProfiles(profiles)
}

type EcsUnloadCmd struct {
Profile string `kong:"short='p',help='Slot of AWS Profile to unload',predictor='profile'"`
Server string `kong:"help='Endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

func (cc *EcsUnloadCmd) Run(ctx *RunContext) error {
c := newClient(ctx.Cli.Ecs.Unload.Server, ctx)

return c.Delete(ctx.Cli.Ecs.Unload.Profile)
}

func listProfiles(profiles []ecs.ListProfilesResponse) error {
// sort our results
sort.Slice(profiles, func(i, j int) bool {
Expand Down
2 changes: 1 addition & 1 deletion cmd/aws-sso/ecs_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ func (cc *EcsAuthCmd) Run(ctx *RunContext) error {
}

type EcsSSLCmd struct {
Save EcsSSLSaveCmd `kong:"cmd,help='Save a new SSL certificate/private key'"`
Delete EcsSSLDeleteCmd `kong:"cmd,help='Delete the current SSL certificate/private key'"`
Print EcsSSLPrintCmd `kong:"cmd,help='Print the current SSL certificate'"`
Save EcsSSLSaveCmd `kong:"cmd,help='Save a new SSL certificate/private key'"`
}

type EcsSSLSaveCmd struct {
Expand Down
9 changes: 7 additions & 2 deletions cmd/aws-sso/ecs_server_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ type EcsServerCmd struct {
BindIP string `kong:"help='Bind address for ECS Server',default='127.0.0.1'"`
Port int `kong:"help='TCP port to listen on',default=4144"`
// hidden flags are for internal use only when running in a docker container
Docker bool `kong:"hidden"`
DisableSSL bool `kong:"help='Disable SSL/TLS for the ECS Server'"`
Docker bool `kong:"hidden"`
DisableAuth bool `kong:"help='Disable HTTP Auth for the ECS Server'"`
DisableSSL bool `kong:"help='Disable SSL/TLS for the ECS Server'"`
}

func (cc *EcsServerCmd) Run(ctx *RunContext) error {
Expand Down Expand Up @@ -88,6 +89,10 @@ func (cc *EcsServerCmd) Run(ctx *RunContext) error {
certChain = ""
}

if ctx.Cli.Ecs.Server.DisableAuth {
bearerToken = ""
}

if bearerToken == "" {
log.Warnf("HTTP Auth: disabled. Use 'aws-sso ecs bearer-token' to enable")
} else {
Expand Down
21 changes: 12 additions & 9 deletions docs/commands-ecs.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ SSL/TLS for the ECS Server.

### ecs ssl print

Prints the SSL certificate stored in the SecureStore.
Prints the SSL public certificate stored in the SecureStore.

---

Expand All @@ -54,7 +54,8 @@ Starts the ECS Server in the foreground.

Flags:

* `--disable-ssl` -- Disables SSL/TLS, even if a certificate and private key are available.
* `--disable-auth` -- Disables HTTP Authentication, even if a Bearer Token is available
* `--disable-ssl` -- Disables SSL/TLS, even if a certificate and private key are available

---

Expand Down Expand Up @@ -97,10 +98,14 @@ Flags:
* `--account <account>`, `-A` -- AWS AccountID of role to assume (`$AWS_SSO_ACCOUNT_ID`)
* `--role <role>`, `-R` -- Name of AWS Role to assume (requires `--account`) (`$AWS_SSO_ROLE_NAME`)
* `--profile <profile>`, `-p` -- Name of AWS Profile to assume
* `--account` -- AWS AccountID of the IAM Role to load.
* `--server` -- host:port of the ECS Server (default `localhost:4144`)
* `--slotted` -- Load the IAM credentials into a unique slot using the ProfileName as the key

You can provide `--profile` or `--arn` or (`--account` and `--role`) to specify the IAM role to load.

If you do not specify `--slotted`, the role will be loaded into the default URL path at `/`. If you
would like to load multiple roles, specify `--slotted` and the role will be loaded into `/slot/<profile name>`

---

### ecs unload
Expand All @@ -109,13 +114,11 @@ Removes the AWS IAM Role credentials from the ECS Server and makes them unavaila

Flags:

* `--arn <arn>`, `-a` -- ARN of role to assume (`$AWS_SSO_ROLE_ARN`)
* `--account <account>`, `-A` -- AWS AccountID of role to assume (`$AWS_SSO_ACCOUNT_ID`)
* `--role <role>`, `-R` -- Name of AWS Role to assume (requires `--account`) (`$AWS_SSO_ROLE_NAME`)
* `--profile <profile>`, `-p` -- Name of AWS Profile to assume
* `--account` -- AWS AccountID of the IAM Role to load.
* `--profile <profile>`, `-p` -- Slot of AWS Profile to unload
* `--server` -- host:port of the ECS Server (default `localhost:4144`)
* `--slotted` -- Load the IAM credentials into a unique slot using the ProfileName as the key

By default, this will unload the IAM credentials for the default role. Passing in
`--profile <profile name>` will unload the credentials in the named slot.

---

Expand Down
28 changes: 22 additions & 6 deletions docs/ecs-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ an alternative IP/port via the `--bind-ip` and `--port` flags.
### Running the ECS Server in the background

The recommended way to run the ECS server in the background is via the
[aws-sso-cli-ecs-server](https://hub.docker.com/repository/docker/synfinatic/xb8-docsis-stats/general)
[aws-sso-cli-ecs-server](https://hub.docker.com/repository/docker/synfinatic/aws-sso-cli-ecs-server/general)
Docker image and the `aws-sso ecs docker [start|stop]` commands as this will
automatically configure your SSL key pair and bearer token from the secure store
in the most secure means possible.
Expand All @@ -61,12 +61,16 @@ AWS IAM authentication tokens.

#### ECS Server SSL Certificate

**Important:** Due to a [bug in the AWS Boto3 SDK](https://github.com/synfinatic/aws-sso-cli/issues/936)
you can not enable SSL at this time. I'm currently unsure if other AWS SDKs
(like the Go SDK used by Terraform) also experience this issue. __I'd greatly
**Important:** Due to a [bug in the AWS SDK](https://github.com/aws/aws-sdk/issues/774)
you can not easily enable SSL at this time. __I'd greatly
appreciate people to upvote my ticket with AWS and help get it greater
visibility at AWS and hopefully addressed sooner rather than later.__

You will need to create an SSL certificate which is _signed by a well trusted CA_
such as DigiCert, Let's Encrypt, Thwate, etc. Currently, the AWS SDK does __NOT__
support self-signed certificates or private CA's for this endpoint.

<!--
You will need to create an SSL certificate/key pair in PKCS#8/PEM format. Typically,
this will be a self-signed certificate which can be generated thusly:
Expand All @@ -88,6 +92,8 @@ $ openssl req -x509 -out localhost.crt -keyout localhost.key \
$ rm config.ssl
```
-->

Once you have your certificate and private key, you will need to save them into the
`aws-sso` secure store:

Expand All @@ -109,6 +115,7 @@ $ aws-sso ecs ssl print

**Note:** At this time, there is no way to extract the SSL Private Key from the Secure Store.

<!--
#### AWS SDK SSL Limitations
If you create a self-signed certificate as described above, you will not be able to use the
Expand All @@ -117,6 +124,15 @@ not trust self-signed certificates. Right now, it is best to get a signed cert
like Let's Encrypt. Due to the complexity of this at this time, getting this to work is left
as an exercise to the reader.
-->

##### Using self-signed certificates

In theory, you can add your self-signed certificate or custom CA into the AWS SDK certificate bundle.
However, this file is SDK specific (the Boto3 SDK ships with it's own `cacert.pem` while the Go v2 SDK uses
the system default bundle). Managing this is not just language specific, but likely to be site-specific
so getting this to work is left as an exercise to the reader.

#### ECS Server HTTP Authentication

The way to configure HTTP Authentication is with a
Expand Down Expand Up @@ -176,9 +192,9 @@ for all AWS Client SDKs using it.
Ensure you have exported the following shell ENV variable:
`export AWS_CONTAINER_CREDENTIALS_FULL_URI=http://localhost:4144/creds`
`export AWS_CONTAINER_CREDENTIALS_FULL_URI=http://localhost:4144/`
**Note:** If you have configured an SSL certificate as described above, use `https://localhost:4144/creds`.
**Note:** If you have configured an SSL certificate as described above, use `https://localhost:4144/`.
Then just:
Expand Down
23 changes: 17 additions & 6 deletions docs/remote-ssh.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ and/or any IAM Credentials stored in the ECS Server if you have not [enabled SSL
or [tmux](https://hamvocke.com/blog/a-quick-and-easy-guide-to-tmux/) session:
`aws-sso ecs run`
1. Load your selected IAM credentials into the ECS Server:<br>
`aws-sso ecs load --profile=<aws profile name>`
`aws-sso ecs load --profile=<profile name>`
1. SSH to the remote system using the [-R flag to forward tcp/4144](https://man.openbsd.org/ssh#R):<br>
`ssh -R 4144:localhost:4144 <remotehost>`

Expand All @@ -38,11 +38,22 @@ or [tmux](https://hamvocke.com/blog/a-quick-and-easy-guide-to-tmux/) session:
**Note:** The following commands assume you are using `bash`. You may have to tweak for other shells.

1. Tell the AWS SDK how to talk to the ECS Server over SSH:<br>
`export AWS_CONTAINER_CREDENTIALS_FULL_URI=https://localhost:4144/` (or `http` if you did not enable SSL)
`export AWS_CONTAINER_CREDENTIALS_FULL_URI=https://localhost:4144/` (or `http` if you did not enable SSL)
1. Tell the AWS SDK the bearer token secret from the first step on your local system:<br>
`export AWS_CONTAINER_AUTHORIZATION_TOKEN='Bearer <secret>'`
1. Verify everything works:
`aws sts get-caller-identity`
`export AWS_CONTAINER_AUTHORIZATION_TOKEN='Bearer <secret>'`
1. Verify everything works: `aws sts get-caller-identity`

See the [ECS Server documentation](ecs-server.md) for more information about the ECS server and
how to use multiple IAM role credentials simultaneously.
how to use multiple IAM role credentials simultaneously.

## Advanced Usage

The above instructions grant any host you ssh to, access to the same AWS IAM Role. But what if
you want to access multiple roles?

For each role you'd like to access you will need to do two things:

1. On your local host, load that role into an individual slot in the ECS Server:<br>
`aws-sso ecs load --slotted --profile <profile name>`
2. On the remote host, specify the correct URL:<br>
`export AWS_CONTAINER_CREDENTIALS_FULL=https://localhost:4144/slot/<profile name>`

0 comments on commit a874e6e

Please sign in to comment.