committed by
harture
7 changed files with 167 additions and 47 deletions
@ -0,0 +1,75 @@ |
|||
package keycloak |
|||
|
|||
import ( |
|||
"context" |
|||
"net/url" |
|||
"regexp" |
|||
"strings" |
|||
"time" |
|||
|
|||
cs "github.com/cloudtrust/common-service" |
|||
) |
|||
|
|||
// IssuerManager provides URL according to a given context
|
|||
type IssuerManager interface { |
|||
GetIssuer(ctx context.Context) OidcVerifierProvider |
|||
} |
|||
|
|||
type issuerManager struct { |
|||
domainToIssuer map[string]OidcVerifierProvider |
|||
defaultIssuer OidcVerifierProvider |
|||
} |
|||
|
|||
func getProtocolAndDomain(URL string) string { |
|||
var r = regexp.MustCompile(`^\w+:\/\/[^\/]+`) |
|||
var match = r.FindStringSubmatch(URL) |
|||
if match != nil { |
|||
return strings.ToLower(match[0]) |
|||
} |
|||
// Best effort: if not found return the whole input string
|
|||
return URL |
|||
} |
|||
|
|||
// NewIssuerManager creates a new URLProvider
|
|||
func NewIssuerManager(config Config) (IssuerManager, error) { |
|||
URLs := config.AddrTokenProvider |
|||
// Use default values when clients are not initializing these values
|
|||
cacheTTL := config.CacheTTL |
|||
if cacheTTL == 0 { |
|||
cacheTTL = 15 * time.Minute |
|||
} |
|||
errTolerance := config.ErrorTolerance |
|||
if errTolerance == 0 { |
|||
errTolerance = time.Minute |
|||
} |
|||
|
|||
var domainToIssuer = make(map[string]OidcVerifierProvider) |
|||
var defaultIssuer OidcVerifierProvider |
|||
|
|||
for _, value := range strings.Split(URLs, " ") { |
|||
uToken, err := url.Parse(value) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
issuer := NewVerifierCache(uToken, cacheTTL, errTolerance) |
|||
domainToIssuer[getProtocolAndDomain(value)] = issuer |
|||
if domainToIssuer == nil { |
|||
defaultIssuer = issuer |
|||
} |
|||
} |
|||
return &issuerManager{ |
|||
domainToIssuer: domainToIssuer, |
|||
defaultIssuer: defaultIssuer, |
|||
}, nil |
|||
} |
|||
|
|||
func (im *issuerManager) GetIssuer(ctx context.Context) OidcVerifierProvider { |
|||
if rawValue := ctx.Value(cs.CtContextIssuerDomain); rawValue != nil { |
|||
// The issuer domain has been found in the context
|
|||
issuerDomain := getProtocolAndDomain(rawValue.(string)) |
|||
if issuer, ok := im.domainToIssuer[issuerDomain]; ok { |
|||
return issuer |
|||
} |
|||
} |
|||
return im.defaultIssuer |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
package keycloak |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"testing" |
|||
|
|||
cs "github.com/cloudtrust/common-service" |
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func TestGetProtocolAndDomain(t *testing.T) { |
|||
var invalidURL = "not a valid URL" |
|||
assert.Equal(t, invalidURL, getProtocolAndDomain(invalidURL)) |
|||
assert.Equal(t, "https://elca.ch", getProtocolAndDomain("https://ELCA.CH/PATH/TO/TARGET")) |
|||
} |
|||
|
|||
func TestNewIssuerManager(t *testing.T) { |
|||
{ |
|||
_, err := NewIssuerManager(Config{AddrTokenProvider: ":"}) |
|||
assert.NotNil(t, err) |
|||
} |
|||
|
|||
defaultPath := "http://default.domain.com:5555" |
|||
myDomainPath := "http://my.domain.com/path/to/somewhere" |
|||
otherDomainPath := "http://other.domain.com:2120/" |
|||
allDomains := fmt.Sprintf("%s %s %s", defaultPath, myDomainPath, otherDomainPath) |
|||
|
|||
prov, err := NewIssuerManager(Config{AddrTokenProvider: allDomains}) |
|||
assert.Nil(t, err) |
|||
assert.NotNil(t, prov) |
|||
|
|||
// No issuer provided with context
|
|||
issuerNoContext := prov.GetIssuer(context.Background()) |
|||
// Unrecognized issuer provided in context
|
|||
issuerDefault := prov.GetIssuer(context.WithValue(context.Background(), cs.CtContextIssuerDomain, "http://unknown.issuer.com/one/path")) |
|||
// Case insensitive
|
|||
issuerMyDomain := prov.GetIssuer(context.WithValue(context.Background(), cs.CtContextIssuerDomain, "http://MY.DOMAIN.COM/issuer")) |
|||
// Other domain
|
|||
issuerOtherDomain := prov.GetIssuer(context.WithValue(context.Background(), cs.CtContextIssuerDomain, "http://other.domain.com:2120/any/thing/here")) |
|||
|
|||
assert.Equal(t, issuerNoContext, issuerDefault) |
|||
assert.NotEqual(t, issuerNoContext, issuerMyDomain) |
|||
assert.NotEqual(t, issuerNoContext, issuerOtherDomain) |
|||
assert.NotEqual(t, issuerMyDomain, issuerOtherDomain) |
|||
} |
|||
Loading…
Reference in new issue