Skip to content

Commit

Permalink
implement custom templated launch for sso browser option (#750)
Browse files Browse the repository at this point in the history
* implement custom templated launch for sso browser option

* fix typo

* update custom browser logic to handle custom cases for google chrome
  • Loading branch information
meyerjrr authored Sep 24, 2024
1 parent 022150f commit 058ea6c
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 4 deletions.
1 change: 1 addition & 0 deletions pkg/assume/entrypoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ func GetCliApp() *cli.App {
if err != nil {
return err
}

if !hasSetup {
browserName, err := browser.HandleBrowserWizard(c)
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ type Config struct {
// and CustomBrowserPath fields.
AWSConsoleBrowserLaunchTemplate *BrowserLaunchTemplate `toml:",omitempty"`

// SSOBrowserLaunchTemplate is an optional launch template to use
// for opening the SSO auth flow. If specified it overrides the DefaultBrowser
// and CustomSSOBrowserPath fields.
SSOBrowserLaunchTemplate *BrowserLaunchTemplate `toml:",omitempty"`

Keyring *KeyringConfig `toml:",omitempty"`
Ordering string
ExportCredentialSuffix string
Expand Down Expand Up @@ -290,7 +295,7 @@ func Load() (*Config, error) {
_, err = toml.NewDecoder(file).Decode(&c)
if err != nil {
// if there is an error just reset the file
return &c, nil
return nil, err
}
return &c, nil
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/granted/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ var ConsoleCommand = cli.Command{
}

if startErr != nil {
return clierr.New(fmt.Sprintf("Granted was unable to open a browser session automatically due to the following error: %s", err.Error()),
return clierr.New(fmt.Sprintf("Granted was unable to open a browser session automatically due to the following error: %s", startErr.Error()),
// allow them to try open the url manually
clierr.Info("You can open the browser session manually using the following url:"),
clierr.Info(consoleURL),
Expand Down
44 changes: 43 additions & 1 deletion pkg/idclogin/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package idclogin

import (
"context"
"errors"
"fmt"
"os/exec"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ssooidc"
"github.com/common-fate/clio"
"github.com/common-fate/clio/clierr"
grantedConfig "github.com/common-fate/granted/pkg/config"
"github.com/common-fate/granted/pkg/forkprocess"
"github.com/common-fate/granted/pkg/launcher"
"github.com/common-fate/granted/pkg/securestorage"
"github.com/pkg/browser"
)
Expand Down Expand Up @@ -54,7 +59,44 @@ func Login(ctx context.Context, cfg aws.Config, startUrl string, scopes []string
return nil, err
}

if config.CustomSSOBrowserPath != "" {
if config.SSOBrowserLaunchTemplate != nil {
l, err := launcher.CustomFromLaunchTemplate(config.SSOBrowserLaunchTemplate, []string{})
if err == launcher.ErrLaunchTemplateNotConfigured {
return nil, errors.New("error configuring custom browser, ensure that [SSOBrowserLaunchTemplate] is specified in your Granted config file")
}
if err != nil {
return nil, err
}

// now build the actual command to run - e.g. 'firefox --new-tab <URL>'
args, err := l.LaunchCommand(url, "")
if err != nil {
return nil, fmt.Errorf("error building browser launch command: %w", err)
}

var startErr error
if l.UseForkProcess() {
clio.Debugf("running command using forkprocess: %s", args)
cmd, err := forkprocess.New(args...)
if err != nil {
return nil, err
}
startErr = cmd.Start()
} else {
clio.Debugf("running command without forkprocess: %s", args)
cmd := exec.Command(args[0], args[1:]...)
startErr = cmd.Start()
}

if startErr != nil {
return nil, clierr.New(fmt.Sprintf("Granted was unable to open a browser session automatically due to the following error: %s", startErr.Error()),
// allow them to try open the url manually
clierr.Info("You can open the browser session manually using the following url:"),
clierr.Info(url),
)
}

} else if config.CustomSSOBrowserPath != "" {
cmd := exec.Command(config.CustomSSOBrowserPath, url)
err = cmd.Start()
if err != nil {
Expand Down
24 changes: 23 additions & 1 deletion pkg/launcher/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package launcher
import (
"errors"
"fmt"
"regexp"
"strings"
"text/template"

Expand Down Expand Up @@ -52,10 +53,31 @@ func (l Custom) LaunchCommand(url string, profile string) ([]string, error) {
return nil, fmt.Errorf("executing command template (check that your browser launch template is valid in your Granted config): %w", err)
}

commandParts := strings.Fields(renderedCommand.String())
commandParts := splitCommand(renderedCommand.String())
return commandParts, nil
}

// splits each component of the command. Anything within quotes will be handled as one component of the command
// eg open -a "Google Chrome" <URL> returns ["open", "-a", "Google Chrome", "<URL>"]
func splitCommand(command string) []string {

re := regexp.MustCompile(`"([^"]+)"|(\S+)`)
matches := re.FindAllStringSubmatch(command, -1)

var result []string
for _, match := range matches {

if match[1] != "" {
result = append(result, match[1])
} else {

result = append(result, match[2])
}
}

return result
}

func (l Custom) UseForkProcess() bool { return l.ForkProcess }

var ErrLaunchTemplateNotConfigured = errors.New("launch template is not configured")
Expand Down

0 comments on commit 058ea6c

Please sign in to comment.