From a03243a826bb4eb5eebad19133f6b15e2f5dfdc2 Mon Sep 17 00:00:00 2001 From: Marco Bonetti Date: Fri, 10 Jun 2016 14:11:54 +0100 Subject: Add support for a users whitelist --- README.md | 4 +++- example-server.conf | 1 + server/auth/github/github.go | 13 +++++++++++-- server/auth/github/github_test.go | 2 +- server/auth/google/google.go | 19 ++++++++++++++----- server/auth/google/google_test.go | 2 +- server/config/config.go | 1 + 7 files changed, 32 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 2d0be20..d332267 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,8 @@ For the server you need the following: ## Installation using Go tools 1. Use the Go tools to install cashier. The binaries `cashierd` and `cashier` will be installed in your $GOPATH. ``` -go get github.com/nsheridan/cashier/cmd/... +go get -u github.com/nsheridan/cashier/cmd/cashier +go get -u github.com/nsheridan/cashier/cmd/cashierd ``` 2. Create a signing key with `ssh-keygen` and a [cashierd.conf](example-server.conf) 3. Run the cashier server with `cashierd` and the cli with `cashier`. @@ -85,6 +86,7 @@ Configuration is divided into different sections: `server`, `auth`, `ssh`, and ` - `oauth_client_secret` : string. Oauth secret. - `oauth_callback_url` : string. URL that the Oauth provider will redirect to after user authorisation. The path is hardcoded to `"/auth/callback"` in the source. - `provider_opts` : object. Additional options for the provider. +- `users_whitelist` : array of strings. Optional list of whitelisted usernames. If missing, all users of your current domain/organization are allowed to authenticate against cashierd. #### Provider-specific options diff --git a/example-server.conf b/example-server.conf index 5a88615..d112faf 100644 --- a/example-server.conf +++ b/example-server.conf @@ -16,6 +16,7 @@ auth { provider_opts { domain = "example.com" # Oauth-provider specific options } + users_whitelist = ["marco", "niall", "patrick"] # Optional } # Configuration for the certificate signer. diff --git a/server/auth/github/github.go b/server/auth/github/github.go index 7904e26..a6a4a59 100644 --- a/server/auth/github/github.go +++ b/server/auth/github/github.go @@ -22,12 +22,17 @@ const ( type Config struct { config *oauth2.Config organization string + whitelist map[string]bool } // New creates a new Github provider from a configuration. func New(c *config.Auth) (auth.Provider, error) { - if c.ProviderOpts["organization"] == "" { - return nil, errors.New("github_opts organization must not be empty") + uw := make(map[string]bool) + for _, u := range c.UsersWhitelist { + uw[u] = true + } + if c.ProviderOpts["organization"] == "" && len(uw) == 0 { + return nil, errors.New("github_opts organization and the users whitelist must not be both empty") } return &Config{ config: &oauth2.Config{ @@ -41,6 +46,7 @@ func New(c *config.Auth) (auth.Provider, error) { }, }, organization: c.ProviderOpts["organization"], + whitelist: uw, }, nil } @@ -56,6 +62,9 @@ func (c *Config) Name() string { // Valid validates the oauth token. func (c *Config) Valid(token *oauth2.Token) bool { + if len(c.whitelist) == 0 && !c.whitelist[c.Username(token)] { + return false + } if !token.Valid() { return false } diff --git a/server/auth/github/github_test.go b/server/auth/github/github_test.go index 1d6b801..c0b26a4 100644 --- a/server/auth/github/github_test.go +++ b/server/auth/github/github_test.go @@ -32,7 +32,7 @@ func TestNewEmptyOrganization(t *testing.T) { a := assert.New(t) _, err := newGithub() - a.EqualError(err, "github_opts organization must not be empty") + a.EqualError(err, "github_opts organization and the users whitelist must not be both empty") organization = "exampleorg" } diff --git a/server/auth/google/google.go b/server/auth/google/google.go index e2c6724..3a833ab 100644 --- a/server/auth/google/google.go +++ b/server/auth/google/google.go @@ -22,14 +22,19 @@ const ( // Config is an implementation of `auth.Provider` for authenticating using a // Google account. type Config struct { - config *oauth2.Config - domain string + config *oauth2.Config + domain string + whitelist map[string]bool } // New creates a new Google provider from a configuration. func New(c *config.Auth) (auth.Provider, error) { - if c.ProviderOpts["domain"] == "" { - return nil, errors.New("google_opts domain must not be empty") + uw := make(map[string]bool) + for _, u := range c.UsersWhitelist { + uw[u] = true + } + if c.ProviderOpts["domain"] == "" && len(uw) == 0 { + return nil, errors.New("google_opts domain and the users whitelist must not be both empty") } return &Config{ @@ -40,7 +45,8 @@ func New(c *config.Auth) (auth.Provider, error) { Endpoint: google.Endpoint, Scopes: []string{googleapi.UserinfoEmailScope, googleapi.UserinfoProfileScope}, }, - domain: c.ProviderOpts["domain"], + domain: c.ProviderOpts["domain"], + whitelist: uw, }, nil } @@ -56,6 +62,9 @@ func (c *Config) Name() string { // Valid validates the oauth token. func (c *Config) Valid(token *oauth2.Token) bool { + if len(c.whitelist) == 0 && !c.whitelist[c.Username(token)] { + return false + } if !token.Valid() { return false } diff --git a/server/auth/google/google_test.go b/server/auth/google/google_test.go index 9970c21..b80c4bf 100644 --- a/server/auth/google/google_test.go +++ b/server/auth/google/google_test.go @@ -33,7 +33,7 @@ func TestNewWithoutDomain(t *testing.T) { domain = "" _, err := newGoogle() - a.EqualError(err, "google_opts domain must not be empty") + a.EqualError(err, "google_opts domain and the users whitelist must not be both empty") domain = "example.com" } diff --git a/server/config/config.go b/server/config/config.go index 648cf46..0ae1e60 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -40,6 +40,7 @@ type Auth struct { OauthCallbackURL string `mapstructure:"oauth_callback_url"` Provider string `mapstructure:"provider"` ProviderOpts map[string]string `mapstructure:"provider_opts"` + UsersWhitelist []string `mapstructure:"users_whitelist"` } // SSH holds the configuration specific to signing ssh keys. -- cgit v1.2.3