Skip to content

Commit

Permalink
Add --server flag for ecs client commands
Browse files Browse the repository at this point in the history
Add support for connecting to a random server

Fixes: #937
  • Loading branch information
synfinatic committed Jul 6, 2024
1 parent afaeeaf commit 86a814e
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Add support for HTTP Auth/`AWS_CONTAINER_AUTHORIZATION_TOKEN` env variable #516
* Add support for HTTPS #518
* Add Docker container support #569
* Replace `--port` with `--server` flag for the `aws-sso ecs [list|load|unload|profile]` commands #937

## [v1.16.1] - 2024-06-13

Expand Down
22 changes: 11 additions & 11 deletions cmd/aws-sso/ecs_client_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
)

type EcsListCmd struct {
Port int `kong:"help='TCP port of aws-sso ECS Server',env='AWS_SSO_ECS_PORT',default=4144"` // SEE ECS_PORT in ecs_cmd.go
Server string `kong:"help='Endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

type EcsLoadCmd struct {
Expand All @@ -44,17 +44,17 @@ type EcsLoadCmd struct {
Profile string `kong:"short='p',help='Name of AWS Profile to assume',predictor='profile',xor='account,role'"`

// Other params
Port int `kong:"help='TCP port of aws-sso ECS Server',env='AWS_SSO_ECS_PORT',default=4144"` // SEE ECS_PORT in ecs_cmd.go
Slotted bool `kong:"short='s',help='Load credentials in a unique slot using the ProfileName as the key'"`
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 {
Port int `kong:"help='TCP port of aws-sso ECS Server',env='AWS_SSO_ECS_PORT',default=4144"`
Server string `kong:"help='URL endpoint of aws-sso ECS Server',env='AWS_SSO_ECS_SERVER',default='localhost:4144'"`
}

type EcsUnloadCmd struct {
Port int `kong:"help='TCP port of aws-sso ECS Server',env='AWS_SSO_ECS_PORT',default=4144"`
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 {
Expand All @@ -71,7 +71,7 @@ func (cc *EcsLoadCmd) Run(ctx *RunContext) error {
}

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

profile, err := c.GetProfile()
if err != nil {
Expand All @@ -89,14 +89,14 @@ func (cc *EcsProfileCmd) Run(ctx *RunContext) error {
}

func (cc *EcsUnloadCmd) Run(ctx *RunContext) error {
c := newClient(ctx.Cli.Ecs.Unload.Port, ctx)
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.Port, ctx)
c := newClient(ctx.Cli.Ecs.Load.Server, ctx)

creds := GetRoleCredentials(ctx, awssso, accountId, role)

Expand All @@ -123,7 +123,7 @@ func ecsLoadCmd(ctx *RunContext, awssso *sso.AWSSSO, accountId int64, role strin
}

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

profiles, err := c.ListProfiles()
if err != nil {
Expand Down Expand Up @@ -157,7 +157,7 @@ func listProfiles(profiles []ecs.ListProfilesResponse) error {
return err
}

func newClient(port int, ctx *RunContext) *client.ECSClient {
func newClient(server string, ctx *RunContext) *client.ECSClient {
certChain, err := ctx.Store.GetEcsSslCert()
if err != nil {
log.Fatalf("Unable to get ECS SSL cert: %s", err)
Expand All @@ -166,5 +166,5 @@ func newClient(port int, ctx *RunContext) *client.ECSClient {
if err != nil {
log.Fatalf("Unable to get ECS bearer token: %s", err)
}
return client.NewECSClient(port, bearerToken, certChain)
return client.NewECSClient(server, bearerToken, certChain)
}
32 changes: 22 additions & 10 deletions internal/ecs/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ import (
"io"
"net/http"
"net/url"
"strconv"
"strings"

"github.com/davecgh/go-spew/spew"
"github.com/synfinatic/aws-sso-cli/internal/ecs"
"github.com/synfinatic/aws-sso-cli/internal/storage"
)

type ECSClient struct {
port int
server string
authToken string
loadUrl string
loadSlotUrl string
Expand All @@ -43,7 +45,7 @@ type ECSClient struct {
client *http.Client
}

func NewECSClient(port int, authToken string, certChain string) *ECSClient {
func NewECSClient(server, authToken, certChain string) *ECSClient {
var client *http.Client = &http.Client{}
var proto string = "http"
var err error
Expand All @@ -52,25 +54,35 @@ func NewECSClient(port int, authToken string, certChain string) *ECSClient {
proto = "https"
client, err = NewHTTPClient(certChain)
if err != nil {
panic(fmt.Sprintf("unable to load SSL certificate: %s", err))
panic(fmt.Sprintf("unable to load SSL certificate: %s", err.Error()))

Check warning on line 57 in internal/ecs/client/client.go

View check run for this annotation

Codecov / codecov/patch

internal/ecs/client/client.go#L57

Added line #L57 was not covered by tests
}
}

if authToken == "" {
log.Warnf("No auth token provided, ECS server communication will be unauthenticated")
log.Warnf("no auth token provided, ECS server communication will be unauthenticated")
}
if certChain == "" {
log.Warnf("No SSL cert provided, ECS server communication will be unencrypted")
log.Warnf("no SSL cert provided, ECS server communication will be unencrypted")
}

hostPort := strings.Split(server, ":")
if len(hostPort) != 2 || hostPort[0] == "" || hostPort[1] == "" {
panic(fmt.Sprintf("invalid --server address: %s", server))
}

port, err := strconv.Atoi(hostPort[1])
if err != nil || port < 1 || port > 65535 {
panic(fmt.Sprintf("invalid --server port: %s", hostPort[1]))
}

return &ECSClient{
server: server,
client: client,
port: port,
authToken: authToken,
loadUrl: fmt.Sprintf("%s://localhost:%d/", proto, port),
loadSlotUrl: fmt.Sprintf("%s://localhost:%d%s", proto, port, ecs.SLOT_ROUTE),
profileUrl: fmt.Sprintf("%s://localhost:%d%s", proto, port, ecs.PROFILE_ROUTE),
listUrl: fmt.Sprintf("%s://localhost:%d%s", proto, port, ecs.SLOT_ROUTE),
loadUrl: fmt.Sprintf("%s://%s/", proto, server),
loadSlotUrl: fmt.Sprintf("%s://%s%s", proto, server, ecs.SLOT_ROUTE),
profileUrl: fmt.Sprintf("%s://%s%s", proto, server, ecs.PROFILE_ROUTE),
listUrl: fmt.Sprintf("%s://%s%s", proto, server, ecs.SLOT_ROUTE),
}
}

Expand Down
56 changes: 36 additions & 20 deletions internal/ecs/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
)

func TestCheckDoResponse(t *testing.T) {
t.Parallel()
// t.Parallel()

resp := http.Response{
StatusCode: http.StatusOK,
Expand All @@ -45,11 +45,11 @@ func TestCheckDoResponse(t *testing.T) {
}

func TestNewECSClient(t *testing.T) {
t.Parallel()
// t.Parallel()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
assert.NotNil(t, c)
assert.Equal(t, 4144, c.port)
assert.Equal(t, "localhost:4144", c.server)
assert.Equal(t, "token", c.authToken)
assert.NotEmpty(t, c.loadUrl)
assert.NotEmpty(t, c.loadSlotUrl)
Expand All @@ -58,16 +58,32 @@ func TestNewECSClient(t *testing.T) {

certChain, err := os.ReadFile("../server/testdata/localhost.crt")
assert.NoError(t, err)
c = NewECSClient(4144, "token", string(certChain))
c = NewECSClient("localhost:4144", "token", string(certChain))
assert.NotNil(t, c)

assert.Panics(t, func() { NewECSClient(4144, "token", "foobar") })
}

func TestNewEcsClientFail(t *testing.T) {
// t.Parallel()
// assert.Panics(t, func() { NewECSClient("localhost:4144", "token", "foobar") })

assert.Panics(t, func() { NewECSClient("localhost", "token", "") })

assert.Panics(t, func() { NewECSClient("localhost:", "token", "") })

assert.Panics(t, func() { NewECSClient(":4144", "token", "") })

assert.Panics(t, func() { NewECSClient("localhost:foo", "token", "") })

assert.Panics(t, func() { NewECSClient("localhost:0", "token", "") })

assert.Panics(t, func() { NewECSClient("localhost:65536", "token", "") })
}

func TestECSClientLoadUrl(t *testing.T) {
t.Parallel()
// t.Parallel()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
assert.NotNil(t, c)
assert.Equal(t, "http://localhost:4144/", c.LoadUrl(""))

Expand All @@ -76,25 +92,25 @@ func TestECSClientLoadUrl(t *testing.T) {
}

func TestECSClientProfileUrl(t *testing.T) {
t.Parallel()
// t.Parallel()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
assert.NotNil(t, c)
assert.Equal(t, "http://localhost:4144/profile", c.ProfileUrl())
}

func TestECSClientListUrl(t *testing.T) {
t.Parallel()
// t.Parallel()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
assert.NotNil(t, c)
assert.Equal(t, "http://localhost:4144/slot", c.ListUrl())
}

func TestECSClientNewRequest(t *testing.T) {
t.Parallel()

c := NewECSClient(4144, "Bearer token", "")
c := NewECSClient("localhost:4144", "Bearer token", "")
assert.NotNil(t, c)

req, err := c.newRequest(http.MethodGet, "http://localhost:4144", nil)
Expand All @@ -104,7 +120,7 @@ func TestECSClientNewRequest(t *testing.T) {
assert.Equal(t, "Bearer token", req.Header.Get("Authorization"))
assert.Equal(t, "application/json; charset=utf-8", req.Header.Get("Content-Type"))

c = NewECSClient(4144, "", "")
c = NewECSClient("localhost:4144", "", "")
req, err = c.newRequest(http.MethodGet, "http://localhost:4144", nil)
assert.NoError(t, err)
assert.NotNil(t, req)
Expand All @@ -130,7 +146,7 @@ func TestECSClientSubmitCredsPass(t *testing.T) {
)
defer ts.Close()

c := NewECSClient(4144, "", "")
c := NewECSClient("localhost:4144", "", "")
c.loadUrl = ts.URL
c.loadSlotUrl = ts.URL
assert.NotNil(t, c)
Expand Down Expand Up @@ -175,7 +191,7 @@ func TestECSClientSubmitCredsFail(t *testing.T) {
)
defer ts.Close()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
c.loadUrl = ts.URL
assert.NotNil(t, c)

Expand Down Expand Up @@ -213,7 +229,7 @@ func TestECSGetProfile(t *testing.T) {
)
defer ts.Close()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
assert.NotNil(t, c)
c.profileUrl = ts.URL

Expand Down Expand Up @@ -252,7 +268,7 @@ func TestECSAuthFailures(t *testing.T) {
)
defer ts.Close()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
assert.NotNil(t, c)
c.profileUrl = ts.URL

Expand Down Expand Up @@ -293,7 +309,7 @@ func TestECSListProfiles(t *testing.T) {
)
defer ts.Close()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
c.listUrl = ts.URL
assert.NotNil(t, c)

Expand Down Expand Up @@ -332,7 +348,7 @@ func TestECSDelete(t *testing.T) {
)
defer ts.Close()

c := NewECSClient(4144, "token", "")
c := NewECSClient("localhost:4144", "token", "")
c.loadUrl = ts.URL
c.loadSlotUrl = ts.URL
assert.NotNil(t, c)
Expand Down

0 comments on commit 86a814e

Please sign in to comment.