Skip to content

Commit

Permalink
fix: handle basic auth provided in nomad address
Browse files Browse the repository at this point in the history
- allow to have a scheme in the address with basic auth
- fix nil point dereference error
  • Loading branch information
stind committed Sep 13, 2023
1 parent a94eb6d commit 9ef14cc
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 13 deletions.
45 changes: 32 additions & 13 deletions internal/cli/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,29 @@ func clientOptsFromCLI(c *baseCommand) *api.Config {
// format and if it is, it returns user, password and address. It returns "", "",
// address otherwise.
func handleBasicAuth(s string) (string, string, string) {
before, after, found := strings.Cut(s, "@")
if found {
user, pass, found := strings.Cut(before, ":")
if found {
return user, pass, after
}
beforeAt, afterAt, found := strings.Cut(s, "@")
if !found {
return "", "", s
}

scheme, userpass, schemeFound := strings.Cut(beforeAt, "//")
if !schemeFound {
userpass = beforeAt
}

user, pass, found := strings.Cut(userpass, ":")
if !found {
return "", "", s
}
return "", "", before

var addr string
if schemeFound {
addr = fmt.Sprintf("%s//%s", scheme, afterAt)
} else {
addr = afterAt
}

return user, pass, addr
}

// clientOptsFromEnvironment populates api client conf with environment
Expand All @@ -434,9 +449,11 @@ func clientOptsFromEnvironment(conf *api.Config) {
// we support user:pass@addr here
user, pass, addr := handleBasicAuth(v)
conf.Address = addr
if user != "" && pass != "" {
conf.HttpAuth.Username = user
conf.HttpAuth.Password = pass
if user != "" || pass != "" {
conf.HttpAuth = &api.HttpBasicAuth{
Username: user,
Password: pass,
}
}
}
if v := os.Getenv("NOMAD_NAMESPACE"); v != "" {
Expand Down Expand Up @@ -471,9 +488,11 @@ func clientOptsFromFlags(c *baseCommand, conf *api.Config) {
// we support user:pass@addr here
user, pass, addr := handleBasicAuth(cfg.address)
conf.Address = addr
if user != "" && pass != "" {
conf.HttpAuth.Username = user
conf.HttpAuth.Password = pass
if user != "" || pass != "" {
conf.HttpAuth = &api.HttpBasicAuth{
Username: user,
Password: pass,
}
}
}
if cfg.namespace != "" {
Expand Down
124 changes: 124 additions & 0 deletions internal/cli/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package cli

import (
"testing"

"github.com/hashicorp/nomad/api"
"github.com/shoenig/test/must"
)

func TestHelpers_handleBasicAuth(t *testing.T) {
cases := []struct {
addr string
expectedUser string
expectedPass string
expectedAddr string
}{
{"addr", "", "", "addr"},
{"addr:port", "", "", "addr:port"},
{"user:pass@addr", "user", "pass", "addr"},
{"user:pass@addr:port", "user", "pass", "addr:port"},
{"scheme://addr", "", "", "scheme://addr"},
{"scheme://user:pass@addr", "user", "pass", "scheme://addr"},
{"scheme://user:pass@addr:port", "user", "pass", "scheme://addr:port"},
{"scheme://user:@addr:port", "user", "", "scheme://addr:port"},
{"scheme://:pass@addr:port", "", "pass", "scheme://addr:port"},
{"//user:pass@addr:port", "user", "pass", "//addr:port"},
{"foo@bar", "", "", "foo@bar"},
{"", "", "", ""},
}

for _, c := range cases {
t.Run(c.addr, func(t *testing.T) {
user, pass, addr := handleBasicAuth(c.addr)

must.Eq(t, c.expectedUser, user)
must.Eq(t, c.expectedPass, pass)
must.Eq(t, c.expectedAddr, addr)
})
}
}

func TestHelpers_clientOptsFromEnvironment_Address(t *testing.T) {
cases := []struct {
name string
addr string
expectedAddress string
expectedHttpAuth *api.HttpBasicAuth
}{
{
addr: "addr",
expectedAddress: "addr",
expectedHttpAuth: nil,
},
{
addr: "scheme://user:pass@addr",
expectedAddress: "scheme://addr",
expectedHttpAuth: &api.HttpBasicAuth{Username: "user", Password: "pass"},
},
{
addr: "scheme://user:@addr",
expectedAddress: "scheme://addr",
expectedHttpAuth: &api.HttpBasicAuth{Username: "user", Password: ""},
},
{
addr: "scheme://:pass@addr",
expectedAddress: "scheme://addr",
expectedHttpAuth: &api.HttpBasicAuth{Username: "", Password: "pass"},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
t.Setenv("NOMAD_ADDR", c.addr)

conf := api.Config{HttpAuth: nil}
clientOptsFromEnvironment(&conf)

must.Eq(t, c.expectedAddress, conf.Address)
must.Eq(t, c.expectedHttpAuth, conf.HttpAuth)
})
}
}

func TestHelpers_clientOptsFromFlags_Address(t *testing.T) {
cases := []struct {
name string
addr string
expectedAddress string
expectedHttpAuth *api.HttpBasicAuth
}{
{
addr: "addr",
expectedAddress: "addr",
expectedHttpAuth: nil,
},
{
addr: "scheme://user:pass@addr",
expectedAddress: "scheme://addr",
expectedHttpAuth: &api.HttpBasicAuth{Username: "user", Password: "pass"},
},
{
addr: "scheme://user:@addr",
expectedAddress: "scheme://addr",
expectedHttpAuth: &api.HttpBasicAuth{Username: "user", Password: ""},
},
{
addr: "scheme://:pass@addr",
expectedAddress: "scheme://addr",
expectedHttpAuth: &api.HttpBasicAuth{Username: "", Password: "pass"},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
cmd := baseCommand{nomadConfig: nomadConfig{address: c.addr}}

conf := api.Config{HttpAuth: nil}
clientOptsFromFlags(&cmd, &conf)

must.Eq(t, c.expectedAddress, conf.Address)
must.Eq(t, c.expectedHttpAuth, conf.HttpAuth)
})
}
}

0 comments on commit 9ef14cc

Please sign in to comment.