-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #71 from nhaydel/ISS-20-basic-auth-support
Add basic auth, and default load balancer
- Loading branch information
Showing
9 changed files
with
285 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package auth | ||
|
||
import ( | ||
"errors" | ||
"io/ioutil" | ||
"log" | ||
"net/http" | ||
"os" | ||
|
||
"github.com/Frontman-Labs/frontman/config" | ||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
type BasicAuthValidator struct { | ||
Username string `yaml:"username"` | ||
Password string `yaml:"password"` | ||
} | ||
|
||
func getCredentialsFromConfig(conf *config.BasicAuthConfig) (string, string) { | ||
var username, password string | ||
if conf.Username != "" { | ||
username = conf.Username | ||
} else { | ||
username = os.Getenv(conf.UsernameEnv) | ||
} | ||
|
||
if conf.Password != "" { | ||
password = conf.Password | ||
} else { | ||
password = os.Getenv(conf.PasswordEnv) | ||
} | ||
|
||
return username, password | ||
} | ||
|
||
func NewBasicAuthValidator(conf *config.BasicAuthConfig) (*BasicAuthValidator, error) { | ||
if conf.CredentialsFile != "" { | ||
// Read credentials file to build validator | ||
yamlData, err := ioutil.ReadFile(conf.CredentialsFile) | ||
if err != nil { | ||
log.Printf("Failed to read credentials file: %s", err) | ||
return nil, err | ||
} | ||
validator := &BasicAuthValidator{} | ||
err = yaml.Unmarshal(yamlData, validator) | ||
if err != nil { | ||
log.Printf("Failed to unmarshal credentials data: %s", err) | ||
return nil, err | ||
} | ||
return validator, nil | ||
} | ||
username, password := getCredentialsFromConfig(conf) | ||
return &BasicAuthValidator{ | ||
Username: username, | ||
Password: password, | ||
}, nil | ||
} | ||
|
||
func (v BasicAuthValidator) ValidateToken(request *http.Request) (map[string]interface{}, error) { | ||
username, password, ok := request.BasicAuth() | ||
if !ok { | ||
return nil, errors.New("Error parsing authentication token") | ||
} | ||
|
||
if username != v.Username || password != v.Password { | ||
return nil, errors.New("Invalid credentials") | ||
} | ||
|
||
return nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package auth | ||
|
||
import ( | ||
"github.com/Frontman-Labs/frontman/config" | ||
"net/http" | ||
"os" | ||
"testing" | ||
) | ||
|
||
func TestNewBasicAuthValidatorFromHardcodedCredentials(t *testing.T) { | ||
conf := &config.BasicAuthConfig{ | ||
Username: "username", | ||
Password: "password", | ||
} | ||
|
||
validator, err := NewBasicAuthValidator(conf) | ||
if err != nil { | ||
t.Errorf("Failed to create basic validator: %s\n", err) | ||
} | ||
if validator.Username != "username" { | ||
t.Errorf("NewBasicAuthValidator failed to parse username from username config variable\n") | ||
} | ||
if validator.Password != "password" { | ||
t.Errorf("NewBasicAuthValidator failed to parse password from password config variable\n") | ||
} | ||
} | ||
|
||
func TestNewBasicAuthValidatorFromEnvVariables(t *testing.T) { | ||
conf := &config.BasicAuthConfig{ | ||
UsernameEnv: "FRONTMAN_TEST_BACKEND_USERNAME", | ||
PasswordEnv: "FRONTMAN_TEST_BACKEND_PASSWORD", | ||
} | ||
|
||
os.Setenv("FRONTMAN_TEST_BACKEND_USERNAME", "username_from_env") | ||
os.Setenv("FRONTMAN_TEST_BACKEND_PASSWORD", "password_from_env") | ||
|
||
validator, err := NewBasicAuthValidator(conf) | ||
if err != nil { | ||
t.Errorf("Failed to create basic validator: %s\n", err) | ||
} | ||
if validator.Username != "username_from_env" { | ||
t.Errorf("NewBasicAuthValidator failed to parse username from username environment variable\n") | ||
} | ||
if validator.Password != "password_from_env" { | ||
t.Errorf("NewBasicAuthValidator failed to parse password from password environment variable\n") | ||
} | ||
} | ||
|
||
func TestBasicAuthValidCredentials(t *testing.T) { | ||
validator := &BasicAuthValidator{ | ||
Username: "test", | ||
Password: "test", | ||
} | ||
|
||
req := &http.Request{ | ||
Header: make(http.Header), | ||
} | ||
req.SetBasicAuth("test", "test") | ||
_, err := validator.ValidateToken(req) | ||
if err != nil { | ||
t.Errorf("Failed to validate correct basic auth: %s\n", err) | ||
} | ||
} | ||
|
||
func TestBasicAuthInvalidCredentials(t *testing.T) { | ||
validator := &BasicAuthValidator{ | ||
Username: "test", | ||
Password: "test", | ||
} | ||
|
||
req := &http.Request{ | ||
Header: make(http.Header), | ||
} | ||
req.SetBasicAuth("blah", "blah") | ||
_, err := validator.ValidateToken(req) | ||
if err == nil { | ||
t.Errorf("Failed to validate correctly identify invalid basic auth credentials\n") | ||
} | ||
|
||
if err.Error() != "Invalid credentials" { | ||
t.Errorf("Invalid error message returned when parsing invalid credentials: %s\n", err) | ||
} | ||
} | ||
|
||
func TestBasicAuthMissingCredentials(t *testing.T) { | ||
validator := &BasicAuthValidator{ | ||
Username: "test", | ||
Password: "test", | ||
} | ||
|
||
req := &http.Request{ | ||
Header: make(http.Header), | ||
} | ||
_, err := validator.ValidateToken(req) | ||
if err == nil { | ||
t.Errorf("Failed to validate correctly identify missing basic auth credentials\n") | ||
} | ||
|
||
if err.Error() != "Error parsing authentication token" { | ||
t.Errorf("Invalid error message returned when parsing invalid credentials: %s\n", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.