mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 09:05:55 +00:00
added auth arg validation and set up auth package
This commit is contained in:
parent
dc1c39fd21
commit
b5ba3fb2ea
7 changed files with 189 additions and 59 deletions
47
auth/auth.go
Normal file
47
auth/auth.go
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2017 Pilosa Corp.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package auth
|
||||
|
||||
type AUTH struct {
|
||||
ClientId string
|
||||
ClientSecret string
|
||||
AuthorizeURL string
|
||||
TokenURL string
|
||||
GroupEndpointURL string
|
||||
}
|
||||
|
||||
// func (c *config) Init(ClientId, ClientSecret, AuthorizeURL, TokenURL, GroupEndpointURL string) {
|
||||
// c.ClientId = ClientId
|
||||
// c.ClientSecret = ClientSecret
|
||||
// c.AuthorizeURL = AuthorizeURL
|
||||
// c.TokenURL = TokenURL
|
||||
// c.GroupEndpointURL = GroupEndpointURL
|
||||
// }
|
||||
|
||||
// apiOption is a functional option type for pilosa.API
|
||||
type authOption func(*AUTH) error
|
||||
|
||||
func OptAuth(ClientId, ClientSecret, AuthorizeURL, TokenURL, GroupEndpointURL string) authOption {
|
||||
return func(a *AUTH) error {
|
||||
a.ClientId = ClientId
|
||||
a.ClientSecret = ClientSecret
|
||||
a.AuthorizeURL = AuthorizeURL
|
||||
a.TokenURL = TokenURL
|
||||
a.GroupEndpointURL = GroupEndpointURL
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// redirectURL
|
||||
|
|
@ -124,8 +124,10 @@ func BuildServerFlags(cmd *cobra.Command, srv *server.Command) {
|
|||
|
||||
// OAuth2.0 identity provider configuration
|
||||
flags.BoolVar(&srv.Config.Auth.Enable, "auth.enable", false, "Enable AuthN/AuthZ of featurebase, disabled by default.")
|
||||
flags.StringVar(&srv.Config.Auth.IdentityProviderURL, "auth.identity-provider-url", srv.Config.Auth.IdentityProviderURL, "Base URL for identity provider.")
|
||||
flags.StringVar(&srv.Config.Auth.AuthorizeURL, "auth.authorize-url", srv.Config.Auth.AuthorizeURL, "Base URL for authorize.")
|
||||
flags.StringVar(&srv.Config.Auth.UserInfoURL, "auth.user-info-url", srv.Config.Auth.UserInfoURL, "Base URL for user info.")
|
||||
flags.StringVar(&srv.Config.Auth.ClientId, "auth.client-id", srv.Config.Auth.ClientId, "Application/Client ID")
|
||||
flags.StringVar(&srv.Config.Auth.ClientId, "auth.client-id", srv.Config.Auth.ClientId, "Identity Provider's Application/Client ID.")
|
||||
flags.StringVar(&srv.Config.Auth.ClientSecret, "auth.client-secret", srv.Config.Auth.ClientSecret, "Identity Provider's Application/Client Secret.")
|
||||
flags.StringVar(&srv.Config.Auth.AuthorizeURL, "auth.authorize-url", srv.Config.Auth.AuthorizeURL, "Identity Provider's Authorize URL.")
|
||||
flags.StringVar(&srv.Config.Auth.TokenURL, "auth.token-url", srv.Config.Auth.TokenURL, "Identity Provider's Token URL for identity provider.")
|
||||
flags.StringVar(&srv.Config.Auth.GroupEndpointURL, "auth.group-endpoint-url", srv.Config.Auth.GroupEndpointURL, "Identity Provider's Group endpoint URL.")
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -375,7 +375,8 @@ log-path = "/var/log/molecula/featurebase.log"
|
|||
# Can choose identity provider, pass authorize and user-info endpoints, and client id
|
||||
# [auth]
|
||||
# enable = false
|
||||
# identity-provider-url = "http://place-holder"
|
||||
# authorize-url = "http://place-holder"
|
||||
# user-info-url = "http://place-holder"
|
||||
# client-id = "http://place-holder"
|
||||
# client-id = ""
|
||||
# client-secret = ""
|
||||
# authorize-url = ""
|
||||
# token-url = ""
|
||||
# group-endpoint-url = ""
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2017 Pilosa Corp.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package server
|
||||
|
||||
type Options struct {
|
||||
Enable bool `toml:"enable"`
|
||||
IdentityProviderURL string `toml:"identity-provider-url"`
|
||||
AuthorizeURL string `toml:"authorize-url"`
|
||||
UserInfoURL string `toml:"user-info-url"`
|
||||
ClientId string `toml:"client-id"`
|
||||
}
|
||||
|
||||
func authenticateUser(opt Options) (resp bool) {
|
||||
|
||||
// fmt.Println("IdentityProviderURL", opt.IdentityProviderURL)
|
||||
// fmt.Println("AuthorizeURL", opt.AuthorizeURL)
|
||||
// fmt.Println("UserInfoURL", opt.UserInfoURL)
|
||||
// fmt.Println("ClientId", opt.ClientId)
|
||||
|
||||
resp = false
|
||||
|
||||
return resp
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -246,17 +247,20 @@ type Config struct {
|
|||
// Enable AuthZ/AuthN for featurebase server
|
||||
Enable bool `toml:"enable"`
|
||||
|
||||
// Base URL for identity provider
|
||||
IdentityProviderURL string `toml:"identity-provider-url"`
|
||||
// Application/Client ID
|
||||
ClientId string `toml:"client-id"`
|
||||
|
||||
// Client Secret
|
||||
ClientSecret string `toml:"client-secret"`
|
||||
|
||||
// Authorize URL
|
||||
AuthorizeURL string `toml:"authorize-url"`
|
||||
|
||||
// User info URL
|
||||
UserInfoURL string `toml:"user-info-url"`
|
||||
// Token URL
|
||||
TokenURL string `toml:"token-url"`
|
||||
|
||||
// Application/Client ID
|
||||
ClientId string `toml:"client-id"`
|
||||
// Group Endpoint URL
|
||||
GroupEndpointURL string `toml:"group-endpoint-url"`
|
||||
} `toml:"auth"`
|
||||
}
|
||||
|
||||
|
|
@ -291,6 +295,7 @@ func (c *Config) validate() error {
|
|||
"Etcd.ClusterURL", c.Etcd.ClusterURL,
|
||||
"Postgres.Bind", c.Postgres.Bind,
|
||||
}
|
||||
|
||||
ports := make(map[int]bool)
|
||||
n := len(hostPort)
|
||||
for i := 0; i < n; i += 2 {
|
||||
|
|
@ -411,12 +416,7 @@ func NewConfig() *Config {
|
|||
c.SchemaDetailsOn = true
|
||||
|
||||
// AuthZ/AuthN disabled by default
|
||||
// default identity provider is azure active directory
|
||||
c.Auth.Enable = false
|
||||
c.Auth.IdentityProviderURL = "http://holder-identity-provider"
|
||||
c.Auth.AuthorizeURL = "http://holder-authorize-url"
|
||||
c.Auth.UserInfoURL = "http://holder-user-info-url"
|
||||
c.Auth.ClientId = "http://holder-client-id"
|
||||
|
||||
return c
|
||||
}
|
||||
|
|
@ -628,3 +628,37 @@ func lookupAddr(ctx context.Context, resolver *net.Resolver, host string) (strin
|
|||
// No IPv4 address, return the first resolved address instead.
|
||||
return addrs[0].String(), nil
|
||||
}
|
||||
|
||||
func (c *Config) ValidateAuth() error {
|
||||
authURL := []string{
|
||||
"ClientId", c.Auth.ClientId,
|
||||
"ClientSecret", c.Auth.ClientSecret,
|
||||
"AuthorizeURL", c.Auth.AuthorizeURL,
|
||||
"TokenURL", c.Auth.TokenURL,
|
||||
"GroupEndpointURL", c.Auth.GroupEndpointURL,
|
||||
}
|
||||
|
||||
n := len(authURL)
|
||||
for i := 0; i < n; i += 2 {
|
||||
name := authURL[i]
|
||||
value := authURL[i+1]
|
||||
if strings.Contains(name, "URL") {
|
||||
_, err := url.ParseRequestURI(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid URL for auth config %s: %s", name, err)
|
||||
}
|
||||
} else {
|
||||
if value == "" {
|
||||
return fmt.Errorf("Empty string for auth config %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) MustValidateAuth() {
|
||||
err := c.ValidateAuth()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,3 +288,86 @@ func TestConfig_validateAddrsGRPC(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
type params struct {
|
||||
enable bool
|
||||
clientId string
|
||||
clientSecret string
|
||||
authorizeURL string
|
||||
tokenURL string
|
||||
groupEndpointURL string
|
||||
}
|
||||
|
||||
func TestConfig_validateAuth(t *testing.T) {
|
||||
tests := []struct {
|
||||
expErr string
|
||||
input params
|
||||
expected params
|
||||
}{
|
||||
{"Empty string for auth config ClientId",
|
||||
params{true, "", "", "", "", ""},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"Empty string for auth config ClientSecret",
|
||||
params{true, "clientid", "", "", "", ""},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"Empty string for auth config ClientId",
|
||||
params{true, "", "clientSecret", "", "", ""},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"Invalid URL for auth config AuthorizeURL",
|
||||
params{true, "client", "secret", "", "", ""},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"Invalid URL for auth config TokenURL",
|
||||
params{true, "client", "secret", "https://url.com/", "", ""},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"Invalid URL for auth config GroupEndpointURL",
|
||||
params{true, "client", "secret", "https://url.com/", "https://url.com/", ""},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"Invalid URL for auth config AuthorizeURL",
|
||||
params{true, "client", "secret", "string", "https://url.com/", "https://url.com/"},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"Invalid URL for auth config TokenURL",
|
||||
params{true, "client", "secret", "https://url.com/", "not-a-url", ""},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"Invalid URL for auth config GroupEndpointURL",
|
||||
params{true, "client", "secret", "https://url.com/", "https://url.com/", "not-valid-url"},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
{"",
|
||||
params{true, "client", "secret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
params{true, "clientidstring", "clientSecret", "https://url.com/", "https://url.com/", "https://url.com/"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
c := NewConfig()
|
||||
c.Auth.Enable = test.input.enable
|
||||
c.Auth.ClientId = test.input.clientId
|
||||
c.Auth.ClientSecret = test.input.clientSecret
|
||||
c.Auth.AuthorizeURL = test.input.authorizeURL
|
||||
c.Auth.TokenURL = test.input.tokenURL
|
||||
c.Auth.GroupEndpointURL = test.input.groupEndpointURL
|
||||
|
||||
err := c.ValidateAuth()
|
||||
|
||||
if err != nil && test.expErr == "" {
|
||||
t.Fatal(err)
|
||||
} else if err == nil && test.expErr != "" {
|
||||
t.Fatalf("expected error string to contain %s, but got no error", test.expErr)
|
||||
} else if err != nil && test.expErr != "" {
|
||||
if !strings.Contains(err.Error(), test.expErr) {
|
||||
t.Fatalf("expected error string to contain %s, but got %s", test.expErr, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import (
|
|||
"golang.org/x/sync/errgroup"
|
||||
|
||||
pilosa "github.com/molecula/featurebase/v2"
|
||||
"github.com/molecula/featurebase/v2/auth"
|
||||
"github.com/molecula/featurebase/v2/boltdb"
|
||||
"github.com/molecula/featurebase/v2/encoding/proto"
|
||||
petcd "github.com/molecula/featurebase/v2/etcd"
|
||||
|
|
@ -235,11 +236,8 @@ func (m *Command) Start() (err error) {
|
|||
}
|
||||
|
||||
if m.Config.Auth.Enable == true {
|
||||
// check authentication for user
|
||||
resp := authenticateUser(m.Config.Auth)
|
||||
if resp == false {
|
||||
log.Fatalf("Authentication failed: Unable to access to featurebase server")
|
||||
}
|
||||
m.Config.MustValidateAuth()
|
||||
auth.OptAuth(m.Config.Auth.ClientId, m.Config.Auth.ClientSecret, m.Config.Auth.AuthorizeURL, m.Config.Auth.TokenURL, m.Config.Auth.GroupEndpointURL)
|
||||
}
|
||||
|
||||
// Initialize server.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue