Skip to content

Commit

Permalink
Merge pull request #1004 from synfinatic/move-ecs-setup
Browse files Browse the repository at this point in the history
Refactor commands
  • Loading branch information
synfinatic authored Jul 18, 2024
2 parents 9802074 + 0a7f885 commit 81e0984
Show file tree
Hide file tree
Showing 23 changed files with 336 additions and 170 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

### Changes

* No longer show help for sub-commands by default
* No longer show help for sub-commands by default
* Warnings about invalid accounts/roles in config.yaml are now Debug messages #980
* Default ProfileFormat is now the `Friendly` format #992
* Refactor commands under `setup`: #975
* `config` is now `setup wizard` and `ConfigProfilesUrlAction` config option is no longer used
* `config-profiles` is now `setup profiles`
* `completions` is now `setup completions`
* `ecs ssl` is now `setup ecs ssl`
* Make `--url-action` and `--sts-refresh` command specific options
* Refactor `ecs ssl` commands to be just flags.
* Remove `--open` option from `process` command #291
Expand All @@ -24,6 +25,7 @@
* Remove `flush` command. Use `logout`
* `aws-sso` commands other than `cache` and `login` no longer can trigger a cache refresh without
update of `~/.aws/config` file
* Add support for running ECS Server via docker (`aws-sso ecs docker ...`)

## [v1.17.0] - 2024-07-10

Expand Down
6 changes: 6 additions & 0 deletions cmd/aws-sso/cache_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ type CacheCmd struct {
Threads int `kong:"help='Override number of threads for talking to AWS',default=${DEFAULT_THREADS}"`
}

// AfterApply determines if SSO auth token is required
func (c CacheCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_REQUIRED
return nil
}

func (cc *CacheCmd) Run(ctx *RunContext) error {
s, err := ctx.Settings.GetSelectedSSO(ctx.Cli.SSO)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions cmd/aws-sso/completions_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ type CompleteCmd struct {
ShellScript string `kong:"help='Override file to (un)install shell completions',xor='script'"`
}

// AfterApply determines if SSO auth token is required
func (c CompleteCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_SKIP
return nil
}

func (cc *CompleteCmd) Run(ctx *RunContext) error {
var err error

Expand Down
6 changes: 6 additions & 0 deletions cmd/aws-sso/console_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ type ConsoleCmd struct {
AwsProfile string `kong:"env='AWS_PROFILE',hidden"`
}

// AfterApply determines if SSO auth token is required
func (c ConsoleCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_SKIP
return nil
}

func (cc *ConsoleCmd) Run(ctx *RunContext) error {
if ctx.Cli.Console.Duration > 0 {
ctx.Settings.ConsoleDuration = ctx.Cli.Console.Duration
Expand Down
6 changes: 6 additions & 0 deletions cmd/aws-sso/credentials_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ type CredentialsCmd struct {
Profile []string `kong:"required,short='p',name='profile',help='List of profiles to write credentials for',predictor='profile'"`
}

// AfterApply determines if SSO auth token is required
func (c CredentialsCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_REQUIRED
return nil
}

func (cc *CredentialsCmd) Run(ctx *RunContext) error {
cache := ctx.Settings.Cache.GetSSO()

Expand Down
24 changes: 24 additions & 0 deletions cmd/aws-sso/ecs_client_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ type EcsLoadCmd struct {
Slotted bool `kong:"short='s',help='Load credentials in a unique slot using the ProfileName as the key'"`
}

// AfterApply determines if SSO auth token is required
func (e EcsLoadCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_REQUIRED
return nil
}

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 err := sci.Update(ctx); err == nil {
Expand All @@ -61,6 +67,12 @@ type EcsProfileCmd struct {
Server string `kong:"help='URL endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

// AfterApply determines if SSO auth token is required
func (e EcsProfileCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_NO_CONFIG
return nil
}

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

Expand Down Expand Up @@ -111,6 +123,12 @@ type EcsListCmd struct {
Server string `kong:"help='Endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

// AfterApply determines if SSO auth token is required
func (e EcsListCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_NO_CONFIG
return nil
}

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

Expand All @@ -131,6 +149,12 @@ type EcsUnloadCmd struct {
Server string `kong:"help='Endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

// AfterApply determines if SSO auth token is required
func (e EcsUnloadCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_NO_CONFIG
return nil
}

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

Expand Down
77 changes: 1 addition & 76 deletions cmd/aws-sso/ecs_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,13 @@ package main
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import (
"fmt"
"os"
"strings"
// "github.com/davecgh/go-spew/spew"
)
// "github.com/davecgh/go-spew/spew"

const (
ECS_PORT = 4144
)

type EcsCmd struct {
Auth EcsAuthCmd `kong:"cmd,help='Manage the ECS Server/AWS Client authentication'"`
SSL EcsSSLCmd `kong:"cmd,help='Manage the ECS Server SSL configuration'"`
Server EcsServerCmd `kong:"cmd,help='Run the ECS Server locally'"`
Docker EcsDockerCmd `kong:"cmd,help='Start the ECS Server in a Docker container'"`
List EcsListCmd `kong:"cmd,help='List profiles loaded in the ECS Server'"`
Expand All @@ -40,71 +33,3 @@ type EcsCmd struct {
// login required commands
Load EcsLoadCmd `kong:"cmd,help='Load new IAM Role credentials into the ECS Server',group='login-required'"`
}

type EcsAuthCmd struct {
BearerToken string `kong:"short=t,help='Bearer token value to use for ECS Server',xor='flag'"`
Delete bool `kong:"short=d,help='Delete the current bearer token',xor='flag'"`
}

func (cc *EcsAuthCmd) Run(ctx *RunContext) error {
// Delete the token
if ctx.Cli.Ecs.Auth.Delete {
return ctx.Store.DeleteEcsBearerToken()
}

// Or store the token in the SecureStore
if ctx.Cli.Ecs.Auth.BearerToken == "" {
return fmt.Errorf("no token provided")
}
if strings.HasPrefix(ctx.Cli.Ecs.Auth.BearerToken, "Bearer ") {
return fmt.Errorf("token should not start with 'Bearer '")
}
return ctx.Store.SaveEcsBearerToken(ctx.Cli.Ecs.Auth.BearerToken)
}

type EcsSSLCmd struct {
Delete bool `kong:"short=d,help='Disable SSL and delete the current SSL cert/key',xor='flag,cert,key'"`
Print bool `kong:"short=p,help='Print the current SSL certificate',xor='flag,cert,key'"`
Certificate string `kong:"short=c,type='existingfile',help='Path to certificate chain PEM file',predictor='allFiles',group='add-ssl',xor='cert'"`
PrivateKey string `kong:"short=k,type='existingfile',help='Path to private key file PEM file',predictor='allFiles',group='add-ssl',xor='key'"`
Force bool `kong:"hidden,help='Force loading the certificate'"`
}

func (cc *EcsSSLCmd) Run(ctx *RunContext) error {
if ctx.Cli.Ecs.SSL.Delete {
return ctx.Store.DeleteEcsSslKeyPair()
} else if ctx.Cli.Ecs.SSL.Print {
cert, err := ctx.Store.GetEcsSslCert()
if err != nil {
return err
}
if cert == "" {
return fmt.Errorf("no certificate found")
}
fmt.Println(cert)
return nil
}

var privateKey, certChain []byte
var err error

if !ctx.Cli.Ecs.SSL.Force {
log.Warn("This feature is experimental and may not work as expected.")
log.Warn("Please read https://github.com/synfinatic/aws-sso-cli/issues/936 before contiuing.")
log.Fatal("Use `--force` to continue anyways.")
}

certChain, err = os.ReadFile(ctx.Cli.Ecs.SSL.Certificate)
if err != nil {
return fmt.Errorf("failed to read certificate chain file: %w", err)
}

if ctx.Cli.Ecs.SSL.PrivateKey != "" {
privateKey, err = os.ReadFile(ctx.Cli.Ecs.SSL.PrivateKey)
if err != nil {
return fmt.Errorf("failed to read private key file: %w", err)
}
}

return ctx.Store.SaveEcsSslKeyPair(privateKey, certChain)
}
47 changes: 26 additions & 21 deletions cmd/aws-sso/ecs_docker_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,18 @@ type EcsDockerCmd struct {
}

type EcsDockerStartCmd struct {
DisableSSL bool `kong:"help='Disable SSL/TLS for the ECS Docker Server'"`
BindIP string `kong:"help='Host IP address to bind to the ECS Server',default='127.0.0.1'"`
Port string `kong:"help='Host port to bind to the ECS Server',default='4144'"`
Version string `kong:"help='ECS Server docker image version',default='${VERSION}'"`
DisableAuth bool `kong:"help='Disable HTTP Auth for the ECS Docker Server'"`
DisableSSL bool `kong:"help='Disable SSL/TLS for the ECS Docker Server'"`
BindIP string `kong:"help='Host IP address to bind to the ECS Server',default='127.0.0.1'"`
Port string `kong:"help='Host port to bind to the ECS Server',default='4144'"`
Image string `kong:"help='ECS Server docker image',default='synfinatic/aws-sso-cli-ecs-server'"`
Version string `kong:"help='ECS Server docker image version',default='${VERSION}'"`
}

// AfterApply determines if SSO auth token is required
func (e EcsDockerStartCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_SKIP
return nil
}

func (cc *EcsDockerStartCmd) Run(ctx *RunContext) error {
Expand All @@ -54,7 +62,7 @@ func (cc *EcsDockerStartCmd) Run(ctx *RunContext) error {
return err
}

var privateKey, certChain string
var privateKey, certChain, bearerToken string

if !ctx.Cli.Ecs.Docker.Start.DisableSSL {
privateKey, err = ctx.Store.GetEcsSslKey()
Expand All @@ -67,19 +75,14 @@ func (cc *EcsDockerStartCmd) Run(ctx *RunContext) error {
}
}

if privateKey == "" || certChain == "" {
return fmt.Errorf("ECS Server SSL certificate not configured")
}

bearerToken, err := ctx.Store.GetEcsBearerToken()
if err != nil {
return err
}
if bearerToken == "" {
return fmt.Errorf("ECS Server bearer token not configured")
if !ctx.Cli.Ecs.Docker.Start.DisableAuth {
bearerToken, err = ctx.Store.GetEcsBearerToken()
if err != nil {
return err
}
}

image := imageName(ctx.Cli.Ecs.Docker.Start.Version)
image := fmt.Sprintf("%s:%s", ctx.Cli.Ecs.Docker.Start.Image, ctx.Cli.Ecs.Docker.Start.Version)

config := &container.Config{
AttachStdout: true,
Expand All @@ -94,7 +97,7 @@ func (cc *EcsDockerStartCmd) Run(ctx *RunContext) error {
User: fmt.Sprintf("%d:%d", os.Getuid(), os.Getgid()),
}
if ctx.Cli.LogLevel == "debug" || ctx.Cli.LogLevel == "trace" {
config.Entrypoint = []string{"./aws-sso", "ecs", "run", "--level", ctx.Cli.LogLevel, "--docker"}
config.Entrypoint = []string{"./aws-sso", "ecs", "run", "--level", string(ctx.Cli.LogLevel), "--docker"}
}

portBinding := nat.PortBinding{
Expand Down Expand Up @@ -148,6 +151,12 @@ type EcsDockerStopCmd struct {
Version string `kong:"help='ECS Server Version',default='latest'"`
}

// AfterApply determines if SSO auth token is required
func (e EcsDockerStopCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_SKIP
return nil
}

func (cc *EcsDockerStopCmd) Run(ctx *RunContext) error {
// Stop the ECS Server in a Docker container
cli, err := client.NewClientWithOpts(client.FromEnv)
Expand All @@ -161,7 +170,3 @@ func (cc *EcsDockerStopCmd) Run(ctx *RunContext) error {

return cli.ContainerRemove(context.Background(), CONTAINER_NAME, container.RemoveOptions{})
}

func imageName(version string) string {
return fmt.Sprintf("synfinatic/aws-sso-cli-ecs-server:%s", version)
}
6 changes: 6 additions & 0 deletions cmd/aws-sso/ecs_server_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ type EcsServerCmd struct {
DisableSSL bool `kong:"help='Disable SSL/TLS for the ECS Server'"`
}

// AfterApply determines if SSO auth token is required
func (e EcsServerCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_NO_CONFIG
return nil
}

func (cc *EcsServerCmd) Run(ctx *RunContext) error {
// Start the ECS Server
bindIP := ctx.Cli.Ecs.Server.BindIP
Expand Down
6 changes: 6 additions & 0 deletions cmd/aws-sso/eval_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ type EvalCmd struct {
EnvArn string `kong:"hidden,env='AWS_SSO_ROLE_ARN'"` // used for refresh
}

// AfterApply determines if SSO auth token is required
func (e EvalCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_REQUIRED
return nil
}

func (cc *EvalCmd) Run(ctx *RunContext) error {
var err error

Expand Down
6 changes: 6 additions & 0 deletions cmd/aws-sso/exec_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ type ExecCmd struct {
Args []string `kong:"arg,optional,passthrough,name='args',help='Associated arguments for the command'"`
}

// AfterApply determines if SSO auth token is required
func (e ExecCmd) AfterApply(runCtx *RunContext) error {
runCtx.Auth = AUTH_REQUIRED
return nil
}

func (cc *ExecCmd) Run(ctx *RunContext) error {
err := checkAwsEnvironment()
if err != nil {
Expand Down
Loading

0 comments on commit 81e0984

Please sign in to comment.