Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare beta.9 release #115

Merged
merged 5 commits into from
Aug 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ jobs:
environment:
- TEST_DATABASE_POSTGRESQL=postgres://test:test@localhost:5432/oathkeeper?sslmode=disable
- TEST_DATABASE_MYSQL=root:test@(localhost:3306)/mysql?parseTime=true
- TEST_HYDRA_URL=http://localhost:4444
- image: oryd/hydra:v1.0.0-beta.2
- TEST_HYDRA_ADMIN_URL=http://localhost:4445
- image: oryd/hydra:v1.0.0-beta.8
environment:
- DATABASE_URL=memory
command: "serve --dangerous-force-http"
command: "serve all --dangerous-force-http"
- image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=test
Expand Down
88 changes: 67 additions & 21 deletions cmd/helper_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import (
"strings"
"time"

"net/url"

"github.com/ory/fosite"
"github.com/ory/go-convenience/stringsx"
"github.com/ory/hydra/sdk/go/hydra"
"github.com/ory/keto/sdk/go/keto"
"github.com/ory/oathkeeper/proxy"
Expand Down Expand Up @@ -178,41 +181,84 @@ func getScopeStrategy(key string) fosite.ScopeStrategy {
return nil
}

func authenticatorFactory(f func() (proxy.Authenticator, error)) proxy.Authenticator {
a, err := f()
if err != nil {
logger.WithError(err).Fatalf("Unable to initialize authenticator \"%s\" because an environment variable is missing or misconfigured.", a.GetID())
}
return a
}
func credentialsIssuerFactory(f func() (proxy.CredentialsIssuer, error)) proxy.CredentialsIssuer {
a, err := f()
if err != nil {
logger.WithError(err).Fatalf("Unable to initialize authenticator \"%s\" because an environment variable is missing or misconfigured.", a.GetID())
}
return a
}

func handlerFactories(keyManager rsakey.Manager) ([]proxy.Authenticator, []proxy.Authorizer, []proxy.CredentialsIssuer) {
var authorizers = []proxy.Authorizer{
proxy.NewAuthorizerAllow(),
proxy.NewAuthorizerDeny(),
}
var authenticators = []proxy.Authenticator{
proxy.NewAuthenticatorNoOp(),
proxy.NewAuthenticatorAnonymous(viper.GetString("AUTHENTICATOR_ANONYMOUS_USERNAME")),
}

if u := viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_URL"); len(u) > 0 {
authenticators = append(authenticators, authenticatorFactory(func() (proxy.Authenticator, error) {
return proxy.NewAuthenticatorOAuth2Introspection(
viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_AUTHORIZATION_CLIENT_ID"),
viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_AUTHORIZATION_CLIENT_SECRET"),
viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_AUTHORIZATION_TOKEN_URL"),
u,
stringsx.Splitx(viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_AUTHORIZATION_SCOPE"), ","),
getScopeStrategy("AUTHENTICATOR_OAUTH2_INTROSPECTION_SCOPE_STRATEGY"),
)
}))
logger.Info("Authenticator \"oauth2_introspection\" was configured and enabled successfully.")
} else {
logger.Warn("Authenticator \"oauth2_introspection\" is not configured and thus disabled.")
}

if u := viper.GetString("AUTHENTICATOR_OAUTH2_CLIENT_CREDENTIALS_TOKEN_URL"); len(u) > 0 {
authenticators = append(authenticators, authenticatorFactory(func() (proxy.Authenticator, error) {
return proxy.NewAuthenticatorOAuth2ClientCredentials(u)
}))
logger.Info("Authenticator \"oauth2_client_credentials\" was configured and enabled successfully.")
} else {
logger.Warn("Authenticator \"oauth2_client_credentials\" is not configured and thus disabled.")
}

if u := viper.GetString("AUTHENTICATOR_JWT_JWKS_URL"); len(u) > 0 {
authenticators = append(authenticators, authenticatorFactory(func() (proxy.Authenticator, error) {
return proxy.NewAuthenticatorJWT(
viper.GetString("AUTHENTICATOR_JWT_JWKS_URL"),
getScopeStrategy("AUTHENTICATOR_JWT_SCOPE_STRATEGY"),
)
}))
logger.Info("Authenticator \"jwt\" was configured and enabled successfully.")
} else {
logger.Warn("Authenticator \"jwt\" is not configured and thus disabled.")
}

if u := viper.GetString("AUTHORIZER_KETO_WARDEN_KETO_URL"); len(u) > 0 {
if _, err := url.ParseRequestURI(u); err != nil {
logger.WithError(err).Fatalf("Value \"%s\" from environment variable \"AUTHORIZER_KETO_WARDEN_KETO_URL\" is not a valid URL.", u)
}
ketoSdk, err := keto.NewCodeGenSDK(&keto.Configuration{
EndpointURL: viper.GetString("AUTHORIZER_KETO_WARDEN_KETO_URL"),
EndpointURL: u,
})
if err != nil {
logger.WithError(err).Fatal("Unable to initialize the ORY Keto SDK")
logger.WithError(err).Fatal("Unable to initialize the ORY Keto SDK.")
}
authorizers = append(authorizers, proxy.NewAuthorizerKetoWarden(ketoSdk))
} else {
logger.Warn("Authorizer \"ory-keto\" is not configured and thus disabled.")
}

return []proxy.Authenticator{
proxy.NewAuthenticatorNoOp(),
proxy.NewAuthenticatorAnonymous(viper.GetString("AUTHENTICATOR_ANONYMOUS_USERNAME")),
proxy.NewAuthenticatorOAuth2Introspection(
viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_AUTHORIZATION_CLIENT_ID"),
viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_AUTHORIZATION_CLIENT_SECRET"),
viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_AUTHORIZATION_TOKEN_URL"),
viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_URL"),
strings.Split(viper.GetString("AUTHENTICATOR_OAUTH2_INTROSPECTION_AUTHORIZATION_SCOPE"), ","),
getScopeStrategy("AUTHENTICATOR_OAUTH2_INTROSPECTION_SCOPE_STRATEGY"),
),
proxy.NewAuthenticatorOAuth2ClientCredentials(
viper.GetString("AUTHENTICATOR_OAUTH2_CLIENT_CREDENTIALS_TOKEN_URL"),
),
proxy.NewAuthenticatorJWT(
viper.GetString("AUTHENTICATOR_JWT_JWKS_URL"),
getScopeStrategy("AUTHENTICATOR_JWT_SCOPE_STRATEGY"),
),
},
return authenticators,
authorizers,
[]proxy.CredentialsIssuer{
proxy.NewCredentialsIssuerNoOp(),
Expand Down
10 changes: 8 additions & 2 deletions proxy/authenticator_jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"crypto/rsa"
"fmt"

"net/url"

"github.com/dgrijalva/jwt-go"
"github.com/ory/fosite"
"github.com/ory/go-convenience/jwtx"
Expand Down Expand Up @@ -45,12 +47,16 @@ type AuthenticatorJWT struct {
scopeStrategy fosite.ScopeStrategy
}

func NewAuthenticatorJWT(jwksURL string, scopeStrategy fosite.ScopeStrategy) *AuthenticatorJWT {
func NewAuthenticatorJWT(jwksURL string, scopeStrategy fosite.ScopeStrategy) (*AuthenticatorJWT, error) {
if _, err := url.ParseRequestURI(jwksURL); err != nil {
return new(AuthenticatorJWT), errors.Errorf(`unable to validate the JSON Web Token Authenticator's JWKs URL "%s" because %s`, jwksURL, err)
}

return &AuthenticatorJWT{
jwksURL: jwksURL,
fetcher: fosite.NewDefaultJWKSFetcherStrategy(),
scopeStrategy: scopeStrategy,
}
}, nil
}

func (a *AuthenticatorJWT) GetID() string {
Expand Down
10 changes: 9 additions & 1 deletion proxy/authenticator_jwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ func generateJWT(t *testing.T, claims jwt.Claims, method string) string {
return fmt.Sprintf("%s.%s", sign, j)
}

func TestNewAuthenticatorJWT(t *testing.T) {
_, err := NewAuthenticatorJWT("", fosite.ExactScopeStrategy)
require.Error(t, err)
_, err = NewAuthenticatorJWT("foo", fosite.ExactScopeStrategy)
require.Error(t, err)
}

func TestAuthenticatorJWT(t *testing.T) {
generateKeys(t)

Expand All @@ -97,7 +104,8 @@ func TestAuthenticatorJWT(t *testing.T) {
}))
defer ts.Close()

authenticator := NewAuthenticatorJWT(ts.URL, fosite.ExactScopeStrategy)
authenticator, err := NewAuthenticatorJWT(ts.URL, fosite.ExactScopeStrategy)
require.NoError(t, err)
assert.NotEmpty(t, authenticator.GetID())
now := time.Now().Round(time.Second)

Expand Down
8 changes: 6 additions & 2 deletions proxy/authenticator_oauth2_client_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ type AuthenticatorOAuth2ClientCredentials struct {
tokenURL string
}

func NewAuthenticatorOAuth2ClientCredentials(tokenURL string) *AuthenticatorOAuth2ClientCredentials {
func NewAuthenticatorOAuth2ClientCredentials(tokenURL string) (*AuthenticatorOAuth2ClientCredentials, error) {
if _, err := url.ParseRequestURI(tokenURL); err != nil {
return new(AuthenticatorOAuth2ClientCredentials), errors.Errorf(`unable to validate the OAuth 2.0 Client Credentials Authenticator's Token Introspection URL "%s" because %s`, tokenURL, err)
}

return &AuthenticatorOAuth2ClientCredentials{
tokenURL: tokenURL,
}
}, nil
}

func (a *AuthenticatorOAuth2ClientCredentials) GetID() string {
Expand Down
12 changes: 10 additions & 2 deletions proxy/authenticator_oauth2_client_credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ import (
"github.com/stretchr/testify/require"
)

func TestNewAuthenticatorOAuth2ClientCredentials(t *testing.T) {
_, err := NewAuthenticatorOAuth2ClientCredentials("")
require.Error(t, err)
_, err = NewAuthenticatorOAuth2ClientCredentials("oauth2/token")
require.Error(t, err)
}

func TestAuthenticatorOAuth2ClientCredentials(t *testing.T) {
h := httprouter.New()
h.POST("/oauth2/token", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
Expand All @@ -49,12 +56,13 @@ func TestAuthenticatorOAuth2ClientCredentials(t *testing.T) {
})
ts := httptest.NewServer(h)

a := NewAuthenticatorOAuth2ClientCredentials(ts.URL + "/oauth2/token")
a, err := NewAuthenticatorOAuth2ClientCredentials(ts.URL + "/oauth2/token")
require.NoError(t, err)
// "client",
// "secret",
//,
//[]string{"foo-scope"},)
assert.NotEmpty(t, NewAuthenticatorNoOp().GetID())
assert.NotEmpty(t, a.GetID())

authOk := &http.Request{Header: http.Header{}}
authOk.SetBasicAuth("client", "secret")
Expand Down
22 changes: 20 additions & 2 deletions proxy/authenticator_oauth2_introspection.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,26 @@ type AuthenticatorOAuth2Introspection struct {
scopeStrategy fosite.ScopeStrategy
}

func NewAuthenticatorOAuth2Introspection(clientID, clientSecret, tokenURL, introspectionURL string, scopes []string, strategy fosite.ScopeStrategy) *AuthenticatorOAuth2Introspection {
func NewAuthenticatorOAuth2Introspection(
clientID, clientSecret, tokenURL, introspectionURL string,
scopes []string, strategy fosite.ScopeStrategy,
) (*AuthenticatorOAuth2Introspection, error) {
if _, err := url.ParseRequestURI(introspectionURL); err != nil {
return new(AuthenticatorOAuth2Introspection), errors.Errorf(`unable to validate the OAuth 2.0 Introspection Authenticator's Token Introspection URL "%s" because %s`, introspectionURL, err)
}

c := http.DefaultClient
if len(clientID)+len(clientSecret)+len(tokenURL)+len(scopes) > 0 {
if len(clientID) == 0 {
return new(AuthenticatorOAuth2Introspection), errors.Errorf("if OAuth 2.0 Authorization is used in the OAuth 2.0 Introspection Authenticator, the OAuth 2.0 Client ID must be set but was not")
}
if len(clientSecret) == 0 {
return new(AuthenticatorOAuth2Introspection), errors.Errorf("if OAuth 2.0 Authorization is used in the OAuth 2.0 Introspection Authenticator, the OAuth 2.0 Client ID must be set but was not")
}
if _, err := url.ParseRequestURI(tokenURL); err != nil {
return new(AuthenticatorOAuth2Introspection), errors.Errorf(`if OAuth 2.0 Authorization is used in the OAuth 2.0 Introspection Authenticator, the OAuth 2.0 Token URL must be set but validating URL "%s" failed because %s`, tokenURL, err)
}

c = (&clientcredentials.Config{
ClientID: clientID,
ClientSecret: clientSecret,
Expand All @@ -52,7 +69,8 @@ func NewAuthenticatorOAuth2Introspection(clientID, clientSecret, tokenURL, intro
return &AuthenticatorOAuth2Introspection{
client: c,
introspectionURL: introspectionURL,
}
scopeStrategy: strategy,
}, nil
}

func (a *AuthenticatorOAuth2Introspection) GetID() string {
Expand Down
25 changes: 20 additions & 5 deletions proxy/authenticator_oauth2_introspection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,22 @@ import (
"github.com/stretchr/testify/require"
)

func TestAuthenticatorOAuth2Introspection(t *testing.T) {
a := NewAuthenticatorOAuth2Introspection("", "", "", "", []string{}, fosite.ExactScopeStrategy)
assert.NotEmpty(t, a.GetID())
func TestNewAuthenticatorOAuth2Introspection(t *testing.T) {
_, err := NewAuthenticatorOAuth2Introspection("", "", "", "", []string{}, fosite.ExactScopeStrategy)
require.Error(t, err)
_, err = NewAuthenticatorOAuth2Introspection("", "", "", "http://localhost:1234/oauth2/introspect", []string{}, fosite.ExactScopeStrategy)
require.NoError(t, err)
_, err = NewAuthenticatorOAuth2Introspection("foo", "", "", "http://localhost:1234/oauth2/introspect", []string{}, fosite.ExactScopeStrategy)
require.Error(t, err)
_, err = NewAuthenticatorOAuth2Introspection("", "foo", "", "http://localhost:1234/oauth2/introspect", []string{}, fosite.ExactScopeStrategy)
require.Error(t, err)
_, err = NewAuthenticatorOAuth2Introspection("foo", "foo", "foo", "http://localhost:1234/oauth2/introspect", []string{}, fosite.ExactScopeStrategy)
require.Error(t, err)
_, err = NewAuthenticatorOAuth2Introspection("foo", "foo", "http://localhost:1234/oauth2/token", "http://localhost:1234/oauth2/introspect", []string{}, fosite.ExactScopeStrategy)
require.NoError(t, err)
}

func TestAuthenticatorOAuth2Introspection(t *testing.T) {
for k, tc := range []struct {
d string
setup func(*testing.T, *httprouter.Router)
Expand Down Expand Up @@ -148,7 +160,7 @@ func TestAuthenticatorOAuth2Introspection(t *testing.T) {
}))
})
},
expectErr: false,
expectErr: true,
},
{
d: "should fail because active but issuer not matching",
Expand Down Expand Up @@ -238,7 +250,10 @@ func TestAuthenticatorOAuth2Introspection(t *testing.T) {
}
ts := httptest.NewServer(router)
defer ts.Close()
a.introspectionURL = ts.URL + "/oauth2/introspect"

a, err := NewAuthenticatorOAuth2Introspection("", "", "", ts.URL+"/oauth2/introspect", []string{}, fosite.ExactScopeStrategy)
require.NoError(t, err)
assert.NotEmpty(t, a.GetID())

sess, err := a.Authenticate(tc.r, tc.config, nil)
if tc.expectErr {
Expand Down
4 changes: 2 additions & 2 deletions rsakey/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func TestManager(t *testing.T) {
}

func connectToHydra(t *testing.T) *hydra.CodeGenSDK {
if url := os.Getenv("TEST_HYDRA_URL"); url != "" {
if url := os.Getenv("TEST_HYDRA_ADMIN_URL"); url != "" {
sdk, err := hydra.NewSDK(&hydra.Configuration{
AdminURL: url,
})
Expand Down Expand Up @@ -121,7 +121,7 @@ func connectToHydra(t *testing.T) *hydra.CodeGenSDK {

if err = pool.Retry(func() error {
var err error
u := "http://localhost:" + resource.GetPort("4444/tcp") + "/health/status"
u := "http://localhost:" + resource.GetPort("4445/tcp") + "/health/status"
t.Logf("Trying to connect to ORY Hydra at %s", u)
response, err := http.Get(u)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion rule/matcher_cached_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (m *HTTPMatcher) Refresh() error {
return errors.WithStack(err)
}
if response.StatusCode != http.StatusOK {
return errors.Errorf("Unable to fetch rules from backend, got status code %d but expected %s", response.StatusCode, http.StatusOK)
return errors.Errorf("unable to fetch rules from backend, got status code %d but expected %d", response.StatusCode, http.StatusOK)
}

inserted := map[string]bool{}
Expand Down
4 changes: 2 additions & 2 deletions rule/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ type Upstream struct {
// IsMatching returns an error if the provided method and URL do not match the rule.
func (r *Rule) IsMatching(method string, u *url.URL) error {
if !stringInSlice(method, r.Match.Methods) {
return errors.Errorf("Rule %s does not match URL %s", u)
return errors.Errorf("rule %s does not match URL %s", r.ID, u)
}

c, err := r.CompileURL()
Expand All @@ -128,7 +128,7 @@ func (r *Rule) IsMatching(method string, u *url.URL) error {
}

if !c.MatchString(u.String()) {
return errors.Errorf("Rule %s does not match URL %s", u)
return errors.Errorf("rule %s does not match URL %s", r.ID, u)
}

return nil
Expand Down
Loading