Skip to content

Commit

Permalink
Merge pull request #995 from synfinatic/no-auto-config
Browse files Browse the repository at this point in the history
No auto-config check except login/cache
  • Loading branch information
synfinatic authored Jul 14, 2024
2 parents d351922 + 79b8124 commit 3c21d64
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 66 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* Warnings about invalid accounts/roles in config.yaml are now Debug messages #980
* Default ProfileFormat is now the `Friendly` format #992
* `config`, `config-profiles` and `completions` are now sub-commands of `setup` #975
* Only the and `cache` command will auto-update the contents of `~/.aws/config` #974
* `tags` command no longer supports the `--force-update` option

### New Features

Expand Down
24 changes: 22 additions & 2 deletions cmd/aws-sso/cache_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ package main

import (
"fmt"

"github.com/synfinatic/aws-sso-cli/internal/awsconfig"
"github.com/synfinatic/aws-sso-cli/internal/url"
)

type CacheCmd struct{}
type CacheCmd struct {
NoConfigCheck bool `kong:"help='Disable automatic ~/.aws/config updates'"`
Threads int `kong:"help='Override number of threads for talking to AWS',default=${DEFAULT_THREADS}"`
}

func (cc *CacheCmd) Run(ctx *RunContext) error {
s, err := ctx.Settings.GetSelectedSSO(ctx.Cli.SSO)
Expand All @@ -35,7 +41,7 @@ func (cc *CacheCmd) Run(ctx *RunContext) error {
log.Fatalf(err.Error())
}

err = ctx.Settings.Cache.Refresh(AwsSSO, s, ssoName, ctx.Cli.Threads)
added, deleted, err := ctx.Settings.Cache.Refresh(AwsSSO, s, ssoName, ctx.Cli.Cache.Threads)
if err != nil {
return fmt.Errorf("unable to refresh role cache: %s", err.Error())
}
Expand All @@ -46,5 +52,19 @@ func (cc *CacheCmd) Run(ctx *RunContext) error {
return fmt.Errorf("unable to save role cache: %s", err.Error())
}

if added > 0 || deleted > 0 {
log.Infof("Updated cache: %d added, %d deleted", added, deleted)
// should we update our config??
if !ctx.Cli.Cache.NoConfigCheck && ctx.Settings.AutoConfigCheck {
if ctx.Settings.ConfigProfilesUrlAction != url.ConfigProfilesUndef {
action, _ := url.NewAction(string(ctx.Settings.ConfigProfilesUrlAction))
err := awsconfig.UpdateAwsConfig(ctx.Settings, action, "", true, false)
if err != nil {
log.Errorf("Unable to auto-update aws config file: %s", err.Error())
}
}
}
}

return nil
}
25 changes: 10 additions & 15 deletions cmd/aws-sso/login_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ package main
*/

import (
"github.com/synfinatic/aws-sso-cli/internal/awsconfig"
"github.com/synfinatic/aws-sso-cli/internal/sso"
"github.com/synfinatic/aws-sso-cli/internal/url"
)

type LoginCmd struct{}
type LoginCmd struct {
Threads int `kong:"help='Override number of threads for talking to AWS',default=${DEFAULT_THREADS}"`
}

func (cc *LoginCmd) Run(ctx *RunContext) error {
doAuth(ctx)
Expand Down Expand Up @@ -71,22 +71,17 @@ func doAuth(ctx *RunContext) {
if err != nil {
log.Fatalf(err.Error())
}
if err = ctx.Settings.Cache.Refresh(AwsSSO, s, ssoName, ctx.Cli.Threads); err != nil {
added, deleted, err := ctx.Settings.Cache.Refresh(AwsSSO, s, ssoName, ctx.Cli.Login.Threads)
if err != nil {
log.WithError(err).Fatalf("Unable to refresh cache")
}
if err = ctx.Settings.Cache.Save(true); err != nil {
log.WithError(err).Errorf("Unable to save cache")

if added > 0 || deleted > 0 {
log.Infof("Updated cache: %d added, %d deleted", added, deleted)
}

// should we update our config??
if !ctx.Cli.NoConfigCheck && ctx.Settings.AutoConfigCheck {
if ctx.Settings.ConfigProfilesUrlAction != url.ConfigProfilesUndef {
action, _ := url.NewAction(string(ctx.Settings.ConfigProfilesUrlAction))
err := awsconfig.UpdateAwsConfig(ctx.Settings, action, "", true, false)
if err != nil {
log.Errorf("Unable to auto-update aws config file: %s", err.Error())
}
}
if err = ctx.Settings.Cache.Save(true); err != nil {
log.WithError(err).Errorf("Unable to save cache")
}
}
}
33 changes: 20 additions & 13 deletions cmd/aws-sso/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ type RunContext struct {
}

const (
DEFAULT_STORE = "file"
COPYRIGHT_YEAR = "2021-2024"
DEFAULT_STORE = "file"
COPYRIGHT_YEAR = "2021-2024"
DEFAULT_THREADS = 5
)

var DEFAULT_CONFIG map[string]interface{} = map[string]interface{}{
Expand Down Expand Up @@ -95,22 +96,20 @@ var DEFAULT_CONFIG map[string]interface{} = map[string]interface{}{
"UrlAction": "open",
"LogLevel": "warn",
"ProfileFormat": NICE_PROFILE_FORMAT,
"Threads": 5,
"Threads": DEFAULT_THREADS,
"MaxBackoff": 5, // seconds
"MaxRetry": 10,
}

type CLI struct {
// Common Arguments
Browser string `kong:"short='b',help='Path to browser to open URLs with',env='AWS_SSO_BROWSER'"`
ConfigFile string `kong:"name='config',default='${CONFIG_FILE}',help='Config file',env='AWS_SSO_CONFIG',predict='allFiles'"`
LogLevel string `kong:"short='L',name='level',help='Logging level [error|warn|info|debug|trace] (default: warn)'"`
Lines bool `kong:"help='Print line number in logs'"`
UrlAction string `kong:"short='u',help='How to handle URLs [clip|exec|open|print|printurl|granted-containers|open-url-in-container] (default: open)'"`
SSO string `kong:"short='S',help='Override default AWS SSO Instance',env='AWS_SSO',predictor='sso'"`
STSRefresh bool `kong:"help='Force refresh of STS Token Credentials'"`
NoConfigCheck bool `kong:"help='Disable automatic ~/.aws/config updates'"`
Threads int `kong:"help='Override number of threads for talking to AWS (default: 5)'"`
Browser string `kong:"short='b',help='Path to browser to open URLs with',env='AWS_SSO_BROWSER'"`
ConfigFile string `kong:"name='config',default='${CONFIG_FILE}',help='Config file',env='AWS_SSO_CONFIG',predict='allFiles'"`
LogLevel string `kong:"short='L',name='level',help='Logging level [error|warn|info|debug|trace] (default: warn)'"`
Lines bool `kong:"help='Print line number in logs'"`
UrlAction string `kong:"short='u',help='How to handle URLs [clip|exec|open|print|printurl|granted-containers|open-url-in-container] (default: open)'"`
SSO string `kong:"short='S',help='Override default AWS SSO Instance',env='AWS_SSO',predictor='sso'"`
STSRefresh bool `kong:"help='Force refresh of STS Token Credentials'"`

// Commands
Cache CacheCmd `kong:"cmd,help='Force reload of cached AWS SSO role info and config.yaml'"`
Expand Down Expand Up @@ -251,6 +250,7 @@ func parseArgs(cli *CLI) (*kong.Context, sso.OverrideSettings) {
"CONFIG_DIR": config.ConfigDir(false),
"CONFIG_FILE": config.ConfigFile(false),
"DEFAULT_STORE": DEFAULT_STORE,
"DEFAULT_THREADS": fmt.Sprintf("%d", DEFAULT_THREADS),
"JSON_STORE_FILE": config.JsonStoreFile(false),
"VERSION": Version,
}
Expand Down Expand Up @@ -292,12 +292,19 @@ func parseArgs(cli *CLI) (*kong.Context, sso.OverrideSettings) {
log.Fatalf("Invalid --url-action %s", cli.UrlAction)
}

threads := 0
if cli.Cache.Threads != DEFAULT_THREADS {
threads = cli.Cache.Threads
} else if cli.Login.Threads != DEFAULT_THREADS {
threads = cli.Login.Threads
}

override := sso.OverrideSettings{
Browser: cli.Browser,
DefaultSSO: cli.SSO,
LogLevel: cli.LogLevel,
LogLines: cli.Lines,
Threads: cli.Threads,
Threads: threads, // must be > 0 to override config
UrlAction: action,
}

Expand Down
39 changes: 10 additions & 29 deletions cmd/aws-sso/tags_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,24 @@ import (
)

type TagsCmd struct {
AccountId int64 `kong:"name='account',short='A',help='Filter results based on AWS AccountID'"`
Role string `kong:"short='R',help='Filter results based on AWS Role Name'"`
ForceUpdate bool `kong:"help='Force account/role cache update'"`
AccountId int64 `kong:"name='account',short='A',help='Filter results based on AWS AccountID'"`
Role string `kong:"short='R',help='Filter results based on AWS Role Name'"`
}

func (cc *TagsCmd) Run(ctx *RunContext) error {
set := ctx.Settings
cache := ctx.Settings.Cache.GetSSO()
if ctx.Cli.Tags.ForceUpdate {
s := set.SSO[ctx.Cli.SSO]

ssoName, err := ctx.Settings.GetSelectedSSOName(ctx.Cli.SSO)
if err != nil {
log.Fatalf(err.Error())
}
s, err := ctx.Settings.GetSelectedSSO(ctx.Cli.SSO)
if err != nil {
return err
}

err = set.Cache.Refresh(AwsSSO, s, ssoName, ctx.Cli.Threads)
if err != nil {
log.WithError(err).Fatalf("Unable to refresh role cache")
}
err = set.Cache.Save(true)
if err != nil {
log.WithError(err).Errorf("Unable to save cache")
}
} else {
s, err := ctx.Settings.GetSelectedSSO(ctx.Cli.SSO)
if err != nil {
if err := set.Cache.Expired(s); err != nil {
log.Warn(err.Error())
c := &CacheCmd{}
if err = c.Run(ctx); err != nil {
return err
}

if err := set.Cache.Expired(s); err != nil {
log.Warn(err.Error())
c := &CacheCmd{}
if err = c.Run(ctx); err != nil {
return err
}
}
}
roles := []*sso.AWSRoleFlat{}

Expand Down
12 changes: 10 additions & 2 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
* `--url-action`, `-u` -- How to handle URLs for your SSO provider
* `--sso <name>`, `-S` -- Specify non-default AWS SSO instance to use (`$AWS_SSO`)
* `--sts-refresh` -- Force refresh of STS Token Credentials
* `--no-config-check` -- Disable automatic updating of `~/.aws/config`
* `--threads <int>` -- Number of threads to use with AWS (default: 5)

## Commands

Expand All @@ -24,6 +22,11 @@ hours, but you can force this data to be refreshed immediately.
Cache data is also automatically updated anytime the `config.yaml` file is
modified.

Flags:

* `--no-config-check` -- Disable automatic updating of `~/.aws/config`
* `--threads <int>` -- Number of threads to use with AWS (default: 5)

---

### console
Expand Down Expand Up @@ -245,6 +248,11 @@ case-sensitive manner.
Login via AWS IAM Identity Center (AWS SSO) and retrieve a security token
used to fetch IAM Role credentials.

Flags:

* `--no-config-check` -- Disable automatic updating of `~/.aws/config`
* `--threads <int>` -- Number of threads to use with AWS (default: 5)

---

### logout
Expand Down
36 changes: 31 additions & 5 deletions internal/sso/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"encoding/json"
"fmt"
"os"
"slices"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -277,11 +278,11 @@ func (c *Cache) deleteOldHistory() {
}

// Refresh updates our cached Roles based on AWS SSO & our Config
// but does not save this data!
func (c *Cache) Refresh(sso *AWSSSO, config *SSOConfig, ssoName string, threads int) error {
// but does not save this data! Returns the number of roles added/deleted
func (c *Cache) Refresh(sso *AWSSSO, config *SSOConfig, ssoName string, threads int) (int, int, error) {
// Only refresh once per execution
if c.refreshed {
return nil
return 0, 0, nil
}
c.refreshed = true
log.Debugf("refreshing %s SSO cache", ssoName)
Expand Down Expand Up @@ -311,16 +312,41 @@ func (c *Cache) Refresh(sso *AWSSSO, config *SSOConfig, ssoName string, threads
}

// zero out our current roles cache entries so they don't get merged
oldRoles := cache.Roles.GetAllRoles()
oldRoleArns := []string{}
for _, role := range oldRoles {
oldRoleArns = append(oldRoleArns, role.Arn)
}

c.SSO[ssoName].Roles = &Roles{}
c.SSO[ssoName].ConfigHash = config.GetConfigHash(c.settings.ProfileFormat)

// load our AWSSSO & Config
r, err := c.NewRoles(sso, config, threads)
if err != nil {
return err
return 0, 0, err
}
c.SSO[ssoName].Roles = r

// figure out what roles were added/deleted
newRoles := c.SSO[ssoName].Roles.GetAllRoles()
newRoleArns := []string{}
for _, role := range newRoles {
newRoleArns = append(newRoleArns, role.Arn)
}

added, deleted := 0, 0
for _, arn := range newRoleArns {
if !slices.Contains(oldRoleArns, arn) {
added++
}
}
for _, arn := range oldRoleArns {
if !slices.Contains(newRoleArns, arn) {
deleted++
}
}

// restore our history tags & expires
for _, account := range c.SSO[ssoName].Roles.Accounts {
for _, role := range account.Roles {
Expand All @@ -333,7 +359,7 @@ func (c *Cache) Refresh(sso *AWSSSO, config *SSOConfig, ssoName string, threads
}
}
c.ConfigCreatedAt = config.CreatedAt()
return nil
return added, deleted, nil
}

// pruneSSO removes any SSO instances that are no longer configured
Expand Down

0 comments on commit 3c21d64

Please sign in to comment.