pomerium-cli: add support for a custom browser command (#2617)

This commit is contained in:
Caleb Doxsey 2021-09-21 08:31:30 -06:00 committed by GitHub
parent efffe57bf0
commit a7442b1498
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 17 deletions

View file

@ -16,6 +16,7 @@ import (
)
func init() {
addBrowserFlags(kubernetesExecCredentialCmd)
addTLSFlags(kubernetesExecCredentialCmd)
kubernetesCmd.AddCommand(kubernetesExecCredentialCmd)
kubernetesCmd.AddCommand(kubernetesFlushCredentialsCmd)
@ -61,7 +62,9 @@ var kubernetesExecCredentialCmd = &cobra.Command{
tlsConfig = getTLSConfig()
}
ac := authclient.New(authclient.WithTLSConfig(tlsConfig))
ac := authclient.New(
authclient.WithBrowserCommand(browserOptions.command),
authclient.WithTLSConfig(tlsConfig))
rawJWT, err := ac.GetJWT(context.Background(), serverURL)
if err != nil {
fatalf("%s", err)

View file

@ -57,3 +57,13 @@ func getTLSConfig() *tls.Config {
}
return cfg
}
var browserOptions struct {
command string
}
func addBrowserFlags(cmd *cobra.Command) {
flags := cmd.Flags()
flags.StringVar(&browserOptions.command, "browser-cmd", "",
"custom browser command to run when opening a URL")
}

View file

@ -87,6 +87,7 @@ var tcpCmd = &cobra.Command{
}()
tun := tcptunnel.New(
tcptunnel.WithBrowserCommand(browserOptions.command),
tcptunnel.WithDestinationHost(dstHost),
tcptunnel.WithProxyHost(pomeriumURL.Host),
tcptunnel.WithTLSConfig(tlsConfig),

View file

@ -9,14 +9,12 @@ import (
"net"
"net/http"
"net/url"
"os"
"time"
"github.com/skratchdot/open-golang/open"
"golang.org/x/sync/errgroup"
)
var openBrowser = open.Run
// An AuthClient retrieves an authentication JWT via the Pomerium login API.
type AuthClient struct {
cfg *config
@ -141,5 +139,11 @@ func (client *AuthClient) runOpenBrowser(ctx context.Context, li net.Listener, s
return fmt.Errorf("failed to read login url: %w", err)
}
return openBrowser(string(bs))
err = client.cfg.open(string(bs))
if err != nil {
return fmt.Errorf("failed to open browser url: %w", err)
}
_, _ = fmt.Fprintf(os.Stderr, "Your browser has been opened to visit:\n\n%s\n\n", string(bs))
return nil
}

View file

@ -36,11 +36,8 @@ func TestAuthClient(t *testing.T) {
_ = srv.Serve(li)
}()
origOpenBrowser := openBrowser
defer func() {
openBrowser = origOpenBrowser
}()
openBrowser = func(input string) error {
ac := New()
ac.cfg.open = func(input string) error {
u, err := url.Parse(input)
if err != nil {
return err
@ -64,7 +61,6 @@ func TestAuthClient(t *testing.T) {
return nil
}
ac := New()
rawJWT, err := ac.GetJWT(ctx, &url.URL{
Scheme: "http",
Host: li.Addr().String(),

View file

@ -2,14 +2,18 @@ package authclient
import (
"crypto/tls"
"github.com/skratchdot/open-golang/open"
)
type config struct {
open func(rawURL string) error
tlsConfig *tls.Config
}
func getConfig(options ...Option) *config {
cfg := new(config)
WithBrowserCommand("")(cfg)
for _, o := range options {
o(cfg)
}
@ -19,6 +23,19 @@ func getConfig(options ...Option) *config {
// An Option modifies the config.
type Option func(*config)
// WithBrowserCommand returns an option to configure the browser command.
func WithBrowserCommand(browserCommand string) Option {
return func(cfg *config) {
if browserCommand == "" {
cfg.open = open.Run
} else {
cfg.open = func(rawURL string) error {
return open.RunWith(rawURL, browserCommand)
}
}
}
}
// WithTLSConfig returns an option to configure the tls config.
func WithTLSConfig(tlsConfig *tls.Config) Option {
return func(cfg *config) {

View file

@ -9,10 +9,11 @@ import (
)
type config struct {
jwtCache cliutil.JWTCache
dstHost string
proxyHost string
tlsConfig *tls.Config
jwtCache cliutil.JWTCache
dstHost string
proxyHost string
tlsConfig *tls.Config
browserConfig string
}
func getConfig(options ...Option) *config {
@ -32,6 +33,13 @@ func getConfig(options ...Option) *config {
// An Option modifies the config.
type Option func(*config)
// WithBrowserCommand returns an option to configure the browser command.
func WithBrowserCommand(browserCommand string) Option {
return func(cfg *config) {
cfg.browserConfig = browserCommand
}
}
// WithDestinationHost returns an option to configure the destination host.
func WithDestinationHost(dstHost string) Option {
return func(cfg *config) {

View file

@ -30,8 +30,10 @@ type Tunnel struct {
func New(options ...Option) *Tunnel {
cfg := getConfig(options...)
return &Tunnel{
cfg: cfg,
auth: authclient.New(authclient.WithTLSConfig(cfg.tlsConfig)),
cfg: cfg,
auth: authclient.New(
authclient.WithBrowserCommand(cfg.browserConfig),
authclient.WithTLSConfig(cfg.tlsConfig)),
}
}