forked from TrueCloudLab/certificates
Merge pull request #105 from smallstep/okta-support
Address support on OIDC provisioners
This commit is contained in:
commit
59526d3225
4 changed files with 46 additions and 12 deletions
|
@ -4,7 +4,10 @@ import (
|
|||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -55,6 +58,7 @@ type OIDC struct {
|
|||
Admins []string `json:"admins,omitempty"`
|
||||
Domains []string `json:"domains,omitempty"`
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
ListenAddress string `json:"listenAddress,omitempty"`
|
||||
Claims *Claims `json:"claims,omitempty"`
|
||||
configuration openIDConfiguration
|
||||
keyStore *keyStore
|
||||
|
@ -133,13 +137,27 @@ func (o *OIDC) Init(config Config) (err error) {
|
|||
return errors.New("configurationEndpoint cannot be empty")
|
||||
}
|
||||
|
||||
// Validate listenAddress if given
|
||||
if o.ListenAddress != "" {
|
||||
if _, _, err := net.SplitHostPort(o.ListenAddress); err != nil {
|
||||
return errors.Wrap(err, "error parsing listenAddress")
|
||||
}
|
||||
}
|
||||
|
||||
// Update claims with global ones
|
||||
if o.claimer, err = NewClaimer(o.Claims, config.Claims); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Decode and validate openid-configuration endpoint
|
||||
if err := getAndDecode(o.ConfigurationEndpoint, &o.configuration); err != nil {
|
||||
u, err := url.Parse(o.ConfigurationEndpoint)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error parsing %s", o.ConfigurationEndpoint)
|
||||
}
|
||||
if !strings.Contains(u.Path, "/.well-known/openid-configuration") {
|
||||
u.Path = path.Join(u.Path, "/.well-known/openid-configuration")
|
||||
}
|
||||
if err := getAndDecode(u.String(), &o.configuration); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.configuration.Validate(); err != nil {
|
||||
|
|
|
@ -81,6 +81,7 @@ func TestOIDC_Init(t *testing.T) {
|
|||
Claims *Claims
|
||||
Admins []string
|
||||
Domains []string
|
||||
ListenAddress string
|
||||
}
|
||||
type args struct {
|
||||
config Config
|
||||
|
@ -91,16 +92,21 @@ func TestOIDC_Init(t *testing.T) {
|
|||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{"oidc", "name", "client-id", "client-secret", srv.URL + "/openid-configuration", nil, nil, nil}, args{config}, false},
|
||||
{"ok-admins", fields{"oidc", "name", "client-id", "client-secret", srv.URL + "/openid-configuration", nil, []string{"foo@smallstep.com"}, nil}, args{config}, false},
|
||||
{"ok-domains", fields{"oidc", "name", "client-id", "client-secret", srv.URL + "/openid-configuration", nil, nil, []string{"smallstep.com"}}, args{config}, false},
|
||||
{"ok-no-secret", fields{"oidc", "name", "client-id", "", srv.URL + "/openid-configuration", nil, nil, nil}, args{config}, false},
|
||||
{"no-name", fields{"oidc", "", "client-id", "client-secret", srv.URL + "/openid-configuration", nil, nil, nil}, args{config}, true},
|
||||
{"no-type", fields{"", "name", "client-id", "client-secret", srv.URL + "/openid-configuration", nil, nil, nil}, args{config}, true},
|
||||
{"no-client-id", fields{"oidc", "name", "", "client-secret", srv.URL + "/openid-configuration", nil, nil, nil}, args{config}, true},
|
||||
{"no-configuration", fields{"oidc", "name", "client-id", "client-secret", "", nil, nil, nil}, args{config}, true},
|
||||
{"bad-configuration", fields{"oidc", "name", "client-id", "client-secret", srv.URL, nil, nil, nil}, args{config}, true},
|
||||
{"bad-claims", fields{"oidc", "name", "client-id", "client-secret", srv.URL + "/openid-configuration", badClaims, nil, nil}, args{config}, true},
|
||||
{"ok", fields{"oidc", "name", "client-id", "client-secret", srv.URL, nil, nil, nil, ""}, args{config}, false},
|
||||
{"ok-admins", fields{"oidc", "name", "client-id", "client-secret", srv.URL + "/.well-known/openid-configuration", nil, []string{"foo@smallstep.com"}, nil, ""}, args{config}, false},
|
||||
{"ok-domains", fields{"oidc", "name", "client-id", "client-secret", srv.URL, nil, nil, []string{"smallstep.com"}, ""}, args{config}, false},
|
||||
{"ok-listen-port", fields{"oidc", "name", "client-id", "client-secret", srv.URL, nil, nil, nil, ":10000"}, args{config}, false},
|
||||
{"ok-listen-host-port", fields{"oidc", "name", "client-id", "client-secret", srv.URL, nil, nil, nil, "127.0.0.1:10000"}, args{config}, false},
|
||||
{"ok-no-secret", fields{"oidc", "name", "client-id", "", srv.URL, nil, nil, nil, ""}, args{config}, false},
|
||||
{"no-name", fields{"oidc", "", "client-id", "client-secret", srv.URL, nil, nil, nil, ""}, args{config}, true},
|
||||
{"no-type", fields{"", "name", "client-id", "client-secret", srv.URL, nil, nil, nil, ""}, args{config}, true},
|
||||
{"no-client-id", fields{"oidc", "name", "", "client-secret", srv.URL, nil, nil, nil, ""}, args{config}, true},
|
||||
{"no-configuration", fields{"oidc", "name", "client-id", "client-secret", "", nil, nil, nil, ""}, args{config}, true},
|
||||
{"bad-configuration", fields{"oidc", "name", "client-id", "client-secret", srv.URL + "/random", nil, nil, nil, ""}, args{config}, true},
|
||||
{"bad-claims", fields{"oidc", "name", "client-id", "client-secret", srv.URL + "/.well-known/openid-configuration", badClaims, nil, nil, ""}, args{config}, true},
|
||||
{"bad-parse-url", fields{"oidc", "name", "client-id", "client-secret", ":", nil, nil, nil, ""}, args{config}, true},
|
||||
{"bad-get-url", fields{"oidc", "name", "client-id", "client-secret", "https://", nil, nil, nil, ""}, args{config}, true},
|
||||
{"bad-listen-address", fields{"oidc", "name", "client-id", "client-secret", srv.URL, nil, nil, nil, "127.0.0.1"}, args{config}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -111,9 +117,12 @@ func TestOIDC_Init(t *testing.T) {
|
|||
ConfigurationEndpoint: tt.fields.ConfigurationEndpoint,
|
||||
Claims: tt.fields.Claims,
|
||||
Admins: tt.fields.Admins,
|
||||
Domains: tt.fields.Domains,
|
||||
ListenAddress: tt.fields.ListenAddress,
|
||||
}
|
||||
if err := p.Init(tt.args.config); (err != nil) != tt.wantErr {
|
||||
t.Errorf("OIDC.Init() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if tt.wantErr == false {
|
||||
assert.Len(t, 2, p.keyStore.keySet.Keys)
|
||||
|
|
|
@ -709,7 +709,7 @@ func generateJWKServer(n int) *httptest.Server {
|
|||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
case "/hits":
|
||||
writeJSON(w, hits)
|
||||
case "/openid-configuration", "/.well-known/openid-configuration":
|
||||
case "/.well-known/openid-configuration":
|
||||
writeJSON(w, openIDConfiguration{Issuer: "the-issuer", JWKSetURI: srv.URL + "/jwks_uri"})
|
||||
case "/random":
|
||||
keySet := must(generateJSONWebKeySet(n))[0].(jose.JSONWebKeySet)
|
||||
|
|
|
@ -111,6 +111,7 @@ is G-Suite.
|
|||
"configurationEndpoint": "https://accounts.google.com/.well-known/openid-configuration",
|
||||
"admins": ["you@smallstep.com"],
|
||||
"domains": ["smallstep.com"],
|
||||
"listenAddress": ":10000",
|
||||
"claims": {
|
||||
"maxTLSCertDuration": "8h",
|
||||
"defaultTLSCertDuration": "2h",
|
||||
|
@ -141,6 +142,12 @@ is G-Suite.
|
|||
* `domains` (optional): is the list of domains valid. If provided only the
|
||||
emails with the provided domains will be able to authenticate.
|
||||
|
||||
* `listenAddress` (optional): is the loopback address (`:port` or `host:port`)
|
||||
where the authorization server will redirect to complete the authorization
|
||||
flow. If it's not defined `step` will use `127.0.0.1` with a random port. This
|
||||
configuration is only required if the authorization server doesn't allow any
|
||||
port to be specified at the time of the request for loopback IP redirect URIs.
|
||||
|
||||
* `claims` (optional): overwrites the default claims set in the authority, see
|
||||
the [JWK](#jwk) section for all the options.
|
||||
|
||||
|
|
Loading…
Reference in a new issue