Skip to content

Commit ef130b9

Browse files
committed
rewrite url code and support granted-containers
- Add support for Granted Containers option - Rewrite internal/utils/url.go API completely - Rework the setup wizard to handle new options for Firefox/Exec Fixes: #400
1 parent 3b79f5a commit ef130b9

18 files changed

+831
-588
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
specify a Color/Icon tag #392
1212
* `config` wizard now intelligently selects a default value for
1313
`ConfigProfilesUrlAction` #387
14+
* Add support for Granted Containers Firefox plugin (`UrlAction: granted-containers`)
1415

1516
### Changes
1617

1718
* Replace `list --profile-prefix` with a more flexible `list --prefix` option #395
19+
* `FirefoxOpenUrlInContainer` config option has been deprecated
20+
* `UrlAction` and `ConfigProfilesUrlAction` now support `open-url-in-container`
1821

1922
### Bugs
2023

cmd/config_profiles_cmd.go

+16-13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"os"
2424

25+
"github.com/synfinatic/aws-sso-cli/internal/url"
2526
"github.com/synfinatic/aws-sso-cli/internal/utils"
2627
)
2728

@@ -34,30 +35,32 @@ credential_process = {{ $profile.BinaryPath }} -u {{ $profile.Open }} -S "{{ $pr
3435
{{end}}{{end}}{{end}}`
3536
)
3637

37-
var CONFIG_OPEN_OPTIONS []string = []string{
38-
"clip",
39-
"exec",
40-
"open",
41-
}
42-
4338
type ConfigProfilesCmd struct {
4439
Diff bool `kong:"help='Print a diff of changes to the config file instead of modifying it',xor='action'"`
4540
Force bool `kong:"help='Write a new config file without prompting'"`
46-
Open string `kong:"help='Specify how to open URLs: [clip|exec|open]'"`
41+
Open string `kong:"help='Specify how to open URLs: [clip|exec|open|granted-containers|open-url-in-container]'"`
4742
Print bool `kong:"help='Print profile entries instead of modifying config file',xor='action'"`
4843
}
4944

5045
func (cc *ConfigProfilesCmd) Run(ctx *RunContext) error {
51-
open := ctx.Settings.ConfigProfilesUrlAction
52-
if utils.StrListContains(ctx.Cli.ConfigProfiles.Open, CONFIG_OPEN_OPTIONS) {
53-
open = ctx.Cli.ConfigProfiles.Open
46+
var err error
47+
var action url.ConfigProfilesAction
48+
49+
if ctx.Cli.ConfigProfiles.Open != "" {
50+
if action, err = url.NewConfigProfilesAction(ctx.Cli.ConfigProfiles.Open); err != nil {
51+
return err
52+
}
53+
} else {
54+
action = ctx.Settings.ConfigProfilesUrlAction
5455
}
5556

56-
if len(open) == 0 {
57-
return fmt.Errorf("Please specify --open [clip|exec|open]")
57+
if action == url.ConfigProfilesUndef {
58+
return fmt.Errorf("Please specify --open [clip|exec|open|granted-containers|open-url-in-container]")
5859
}
5960

60-
profiles, err := ctx.Settings.GetAllProfiles(open)
61+
urlAction, _ := url.NewAction(string(action))
62+
63+
profiles, err := ctx.Settings.GetAllProfiles(urlAction)
6164
if err != nil {
6265
return err
6366
}

cmd/console_cmd.go

+11-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
"fmt"
2525
"io"
2626
"net/http"
27-
"net/url"
27+
neturl "net/url"
2828
"os/user"
2929
"regexp"
3030
"strings"
@@ -35,6 +35,7 @@ import (
3535
"github.com/aws/aws-sdk-go-v2/service/sts"
3636
"github.com/c-bata/go-prompt"
3737
// "github.com/davecgh/go-spew/spew"
38+
"github.com/synfinatic/aws-sso-cli/internal/url"
3839
"github.com/synfinatic/aws-sso-cli/internal/utils"
3940
"github.com/synfinatic/aws-sso-cli/sso"
4041
"github.com/synfinatic/aws-sso-cli/storage"
@@ -317,19 +318,17 @@ func openConsoleAccessKey(ctx *RunContext, creds *storage.RoleCredentials,
317318
Destination: fmt.Sprintf("https://console.aws.amazon.com/console/home?region=%s", region),
318319
SigninToken: loginResponse.SigninToken,
319320
}
320-
awsUrl := login.GetUrl()
321321

322-
if ctx.Settings.FirefoxOpenUrlInContainer {
323-
awsUrl = firefoxContainerUrl(ctx, accountId, role, awsUrl)
324-
}
322+
urlOpener := url.NewHandleUrl(ctx.Settings.UrlAction, login.GetUrl(),
323+
ctx.Settings.Browser, ctx.Settings.UrlExecCommand)
324+
325+
urlOpener.ContainerSettings(containerParams(ctx, accountId, role))
325326

326-
urlOpener := utils.NewHandleUrl(ctx.Settings.UrlAction, ctx.Settings.Browser, ctx.Settings.UrlExecCommand)
327-
return urlOpener.Open(awsUrl,
328-
"Please open the following URL in your browser:\n\n", "\n\n")
327+
return urlOpener.Open()
329328
}
330329

331-
// firefoxContainerUrl generates a URL for the Firefox container plugin
332-
func firefoxContainerUrl(ctx *RunContext, accountId int64, role, awsUrl string) string {
330+
// containerParams generates the name, color, icon for the Firefox container plugin
331+
func containerParams(ctx *RunContext, accountId int64, role string) (string, string, string) {
333332
rFlat, _ := ctx.Settings.Cache.GetRole(utils.MakeRoleARN(accountId, role))
334333
profile, err := rFlat.ProfileName(ctx.Settings)
335334
if err != nil && strings.Contains(profile, "&") {
@@ -339,7 +338,7 @@ func firefoxContainerUrl(ctx *RunContext, accountId int64, role, awsUrl string)
339338
color := rFlat.Tags["Color"]
340339
icon := rFlat.Tags["Icon"]
341340

342-
return utils.FirefoxContainerUrl(awsUrl, profile, color, icon)
341+
return profile, color, icon
343342
}
344343

345344
type LoginResponse struct {
@@ -364,7 +363,7 @@ type SessionUrlParams struct {
364363

365364
func (sup *SessionUrlParams) Encode() string {
366365
s, _ := json.Marshal(sup)
367-
return url.QueryEscape(string(s))
366+
return neturl.QueryEscape(string(s))
368367
}
369368

370369
type LoginUrlParams struct {

cmd/main.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/synfinatic/aws-sso-cli/awsconfig"
3131
"github.com/synfinatic/aws-sso-cli/internal/helper"
3232
"github.com/synfinatic/aws-sso-cli/internal/predictor"
33+
"github.com/synfinatic/aws-sso-cli/internal/url"
3334
"github.com/synfinatic/aws-sso-cli/internal/utils"
3435
"github.com/synfinatic/aws-sso-cli/sso"
3536
"github.com/synfinatic/aws-sso-cli/storage"
@@ -98,7 +99,7 @@ type CLI struct {
9899
ConfigFile string `kong:"name='config',default='${CONFIG_FILE}',help='Config file',env='AWS_SSO_CONFIG'"`
99100
LogLevel string `kong:"short='L',name='level',help='Logging level [error|warn|info|debug|trace] (default: warn)'"`
100101
Lines bool `kong:"help='Print line number in logs'"`
101-
UrlAction string `kong:"short='u',help='How to handle URLs [clip|exec|open|print|printurl] (default: open)'"`
102+
UrlAction string `kong:"short='u',help='How to handle URLs [clip|exec|open|print|printurl|granted-containers|open-url-in-container] (default: open)'"`
102103
SSO string `kong:"short='S',help='Override default AWS SSO Instance',env='AWS_SSO',predictor='sso'"`
103104
STSRefresh bool `kong:"help='Force refresh of STS Token Credentials'"`
104105
NoConfigCheck bool `kong:"help='Disable automatic ~/.aws/config updates'"`
@@ -128,12 +129,13 @@ func main() {
128129

129130
log = logrus.New()
130131
ctx, override := parseArgs(&cli)
131-
sso.SetLogger(log)
132-
storage.SetLogger(log)
133-
utils.SetLogger(log)
134132
awsconfig.SetLogger(log)
135133
helper.SetLogger(log)
136134
predictor.SetLogger(log)
135+
sso.SetLogger(log)
136+
storage.SetLogger(log)
137+
url.SetLogger(log)
138+
utils.SetLogger(log)
137139

138140
if err := logLevelValidate(cli.LogLevel); err != nil {
139141
log.Fatalf("%s", err.Error())
@@ -228,8 +230,13 @@ func parseArgs(cli *CLI) (*kong.Context, sso.OverrideSettings) {
228230
ctx, err := parser.Parse(os.Args[1:])
229231
parser.FatalIfErrorf(err)
230232

233+
action, err := url.NewAction(cli.UrlAction)
234+
if err != nil {
235+
log.Fatalf("Invalid --url-action %s", cli.UrlAction)
236+
}
237+
231238
override := sso.OverrideSettings{
232-
UrlAction: cli.UrlAction,
239+
UrlAction: action,
233240
Browser: cli.Browser,
234241
DefaultSSO: cli.SSO,
235242
LogLevel: cli.LogLevel,
@@ -334,10 +341,11 @@ func doAuth(ctx *RunContext) *sso.AWSSSO {
334341

335342
// should we update our config??
336343
if !ctx.Cli.NoConfigCheck && ctx.Settings.AutoConfigCheck {
337-
if utils.StrListContains(ctx.Settings.ConfigProfilesUrlAction, CONFIG_OPEN_OPTIONS) {
344+
if ctx.Settings.ConfigProfilesUrlAction != url.ConfigProfilesUndef {
338345
cfgFile := utils.GetHomePath("~/.aws/config")
339346

340-
profiles, err := ctx.Settings.GetAllProfiles(ctx.Settings.ConfigProfilesUrlAction)
347+
action, _ := url.NewAction(string(ctx.Settings.ConfigProfilesUrlAction))
348+
profiles, err := ctx.Settings.GetAllProfiles(action)
341349
if err != nil {
342350
log.Warnf("Unable to update %s: %s", cfgFile, err.Error())
343351
return AwsSSO

cmd/process_cmd.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ package main
2121
import (
2222
"encoding/json"
2323
"fmt"
24-
"strings"
2524

2625
// log "github.com/sirupsen/logrus"
2726
"github.com/synfinatic/aws-sso-cli/internal/utils"
@@ -40,7 +39,8 @@ type ProcessCmd struct {
4039
func (cc *ProcessCmd) Run(ctx *RunContext) error {
4140
var err error
4241

43-
if strings.Contains(ctx.Settings.UrlAction, "print") {
42+
switch ctx.Cli.UrlAction {
43+
case "print", "printurl":
4444
return fmt.Errorf("unsupported --url-action=print|printurl option")
4545
}
4646

cmd/setup_cmd.go

+49-82
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"time"
2727

2828
"github.com/manifoldco/promptui"
29+
"github.com/synfinatic/aws-sso-cli/internal/url"
2930
"github.com/synfinatic/aws-sso-cli/internal/utils"
3031
"github.com/synfinatic/aws-sso-cli/sso"
3132
)
@@ -101,12 +102,7 @@ func (cc *ConfigCmd) Run(ctx *RunContext) error {
101102
}
102103

103104
func setupWizard(ctx *RunContext, reconfig, addSSO bool) error {
104-
var instanceName, startHostname, ssoRegion, defaultRegion, urlAction string
105-
var defaultLevel, firefoxBrowserPath, browser, configProfilesUrlAction string
106-
var hLimit, hMinutes, cacheRefresh int64
107-
var consoleDuration int32
108-
var autoConfigCheck bool
109-
var urlExecCommand []string
105+
var s = ctx.Settings
110106

111107
// Don't run setup twice
112108
if ranSetup {
@@ -123,110 +119,81 @@ func setupWizard(ctx *RunContext, reconfig, addSSO bool) error {
123119
`)
124120

125121
if reconfig {
126-
defaultLevel = ctx.Settings.LogLevel
127-
defaultRegion = ctx.Settings.DefaultRegion
128-
urlAction = ctx.Settings.UrlAction
129-
urlExecCommand = ctx.Settings.UrlExecCommand
130-
if ctx.Settings.FirefoxOpenUrlInContainer {
131-
firefoxBrowserPath = urlExecCommand[0]
122+
// migrate old boolean flag to enum
123+
if s.FirefoxOpenUrlInContainer {
124+
s.UrlAction = url.OpenUrlContainer
132125
}
133-
autoConfigCheck = ctx.Settings.AutoConfigCheck
134-
cacheRefresh = ctx.Settings.CacheRefresh
135-
hLimit = ctx.Settings.HistoryLimit
136-
hMinutes = ctx.Settings.HistoryMinutes
137-
browser = ctx.Settings.Browser
138-
consoleDuration = ctx.Settings.ConsoleDuration
139126

140127
// upgrade deprecated config option
141-
configProfilesUrlAction = ctx.Settings.ConfigProfilesUrlAction
142-
if ctx.Settings.ConfigUrlAction != "" && configProfilesUrlAction == "" {
143-
configProfilesUrlAction = ctx.Settings.ConfigUrlAction
144-
ctx.Settings.ConfigUrlAction = ""
128+
if s.ConfigUrlAction != "" && s.ConfigProfilesUrlAction == "" {
129+
s.ConfigProfilesUrlAction, _ = url.NewConfigProfilesAction(s.ConfigUrlAction)
130+
s.ConfigUrlAction = ""
145131
}
146132
// skips:
147133
// - SSORegion
148134
// - DefaultRegion
149135
// - StartUrl/startHostname
150136
// - InstanceName
151137
} else {
152-
hMinutes = 1440
153-
hLimit = 10
154-
defaultLevel = "warn"
155-
}
156-
157-
if err := logLevelValidate(defaultLevel); err != nil {
158-
log.Fatalf("Invalid value for --default-level %s", defaultLevel)
159-
}
160-
161-
if !reconfig {
162-
instanceName = promptSsoInstance("")
163-
startHostname = promptStartUrl("")
164-
ssoRegion = promptAwsSsoRegion("")
165-
defaultRegion = promptDefaultRegion(defaultRegion)
166-
167-
ctx.Settings = &sso.Settings{}
168-
ctx.Settings.SSO = map[string]*sso.SSOConfig{}
138+
instanceName := promptSsoInstance("")
139+
startHostname := promptStartUrl("")
140+
ssoRegion := promptAwsSsoRegion("")
141+
defaultRegion := promptDefaultRegion(ssoRegion)
142+
143+
s = &sso.Settings{
144+
SSO: map[string]*sso.SSOConfig{},
145+
UrlAction: "open",
146+
LogLevel: "error",
147+
DefaultRegion: defaultRegion,
148+
ConsoleDuration: 60,
149+
CacheRefresh: 168,
150+
AutoConfigCheck: false,
151+
HistoryLimit: 10,
152+
HistoryMinutes: 1440,
153+
UrlExecCommand: []string{},
154+
}
169155

170-
ctx.Settings.SSO[instanceName] = &sso.SSOConfig{
156+
s.SSO[instanceName] = &sso.SSOConfig{
171157
SSORegion: ssoRegion,
172158
StartUrl: fmt.Sprintf(START_URL_FORMAT, startHostname),
173159
DefaultRegion: defaultRegion,
174160
}
175-
consoleDuration = 60
176-
cacheRefresh = 168
177-
autoConfigCheck = false
178-
hLimit = 10
179-
hMinutes = 1440
180-
urlAction = "open"
181-
defaultLevel = "error"
182-
} else if reconfig {
183-
// don't do anything with the SSO for reconfig
184-
} else if addSSO {
185-
log.Errorf("sorry, not supported yet")
186161
}
187162

188-
ctx.Settings.CacheRefresh = promptCacheRefresh(cacheRefresh)
163+
// first, caching
164+
s.CacheRefresh = promptCacheRefresh(s.CacheRefresh)
189165

190-
if ctx.Settings.CacheRefresh > 0 {
191-
ctx.Settings.AutoConfigCheck = promptAutoConfigCheck(autoConfigCheck)
166+
if s.CacheRefresh > 0 {
167+
s.AutoConfigCheck = promptAutoConfigCheck(s.AutoConfigCheck)
192168
}
193169

194-
// First check if using Firefox w/ Containers
195-
firefoxBrowserPath = promptUseFirefox(firefoxBrowserPath)
170+
// next how we open URLs
171+
s.UrlAction = promptUrlAction(s.UrlAction)
172+
s.ConfigProfilesUrlAction = promptConfigProfilesUrlAction(s.ConfigProfilesUrlAction, s.UrlAction)
196173

197-
// if yes, then configure urlAction = 'exec' and our UrlExecCommand
198-
if firefoxBrowserPath != "" {
199-
ctx.Settings.FirefoxOpenUrlInContainer = true
200-
ctx.Settings.UrlAction = "exec"
201-
ctx.Settings.UrlExecCommand = []string{
202-
firefoxBrowserPath,
203-
`%s`,
204-
}
174+
// do we need urlExecCommand?
175+
if s.UrlAction == url.Exec {
176+
s.UrlExecCommand = promptUrlExecCommand(s.UrlExecCommand)
177+
} else if s.UrlAction.IsContainer() {
178+
s.UrlExecCommand = promptUseFirefox(s.UrlExecCommand)
205179
} else {
206-
// Not using firefox containers...
207-
ctx.Settings.FirefoxOpenUrlInContainer = false
208-
ctx.Settings.UrlAction = promptUrlAction(urlAction, ctx.Settings.FirefoxOpenUrlInContainer)
180+
s.UrlExecCommand = []string{}
209181
}
210182

211-
ctx.Settings.ConfigProfilesUrlAction = promptConfigProfilesUrlAction(
212-
configProfilesUrlAction, ctx.Settings.UrlAction, ctx.Settings.FirefoxOpenUrlInContainer)
213-
214183
// should we prompt user to override default browser?
215-
if ctx.Settings.UrlAction == "open" || ctx.Settings.ConfigProfilesUrlAction == "open" {
216-
ctx.Settings.Browser = promptDefaultBrowser(browser)
184+
if s.UrlAction == url.Open || s.ConfigProfilesUrlAction == url.Open {
185+
s.Browser = promptDefaultBrowser(s.Browser)
217186
}
218187

219-
// Does either action call `exec` without firefox containers?
220-
if ctx.Settings.UrlAction == "exec" || ctx.Settings.ConfigProfilesUrlAction == "exec" {
221-
if !ctx.Settings.FirefoxOpenUrlInContainer {
222-
ctx.Settings.UrlExecCommand = promptUrlExecCommand(urlExecCommand)
223-
}
188+
s.ConsoleDuration = promptConsoleDuration(s.ConsoleDuration)
189+
s.HistoryLimit = promptHistoryLimit(s.HistoryLimit)
190+
s.HistoryMinutes = promptHistoryMinutes(s.HistoryMinutes)
191+
s.LogLevel = promptLogLevel(s.LogLevel)
192+
193+
if err := s.Validate(); err != nil {
194+
return err
224195
}
225196

226-
ctx.Settings.ConsoleDuration = promptConsoleDuration(consoleDuration)
227-
ctx.Settings.HistoryLimit = promptHistoryLimit(hLimit)
228-
ctx.Settings.HistoryMinutes = promptHistoryMinutes(hMinutes)
229-
ctx.Settings.LogLevel = promptLogLevel(defaultLevel)
230197
fmt.Printf("\nAwesome! Saving the new %s\n", ctx.Cli.ConfigFile)
231-
return ctx.Settings.Save(ctx.Cli.ConfigFile, reconfig)
198+
return s.Save(ctx.Cli.ConfigFile, reconfig)
232199
}

0 commit comments

Comments
 (0)