Skip to content

Commit

Permalink
refactor: use koanf configuration system (ory#999)
Browse files Browse the repository at this point in the history
Closes ory#757

Co-authored-by: Patrik <[email protected]>
  • Loading branch information
hperl and zepatrik authored Sep 8, 2022
1 parent 54c40f2 commit 6bac536
Show file tree
Hide file tree
Showing 95 changed files with 3,957 additions and 1,743 deletions.
22 changes: 4 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,6 @@ jobs:
run: |
bash <(curl -s https://codecov.io/bash)
setup-tests:
runs-on: ubuntu-latest
name: Setup tests
steps:
- uses: ory/ci/checkout@master
- uses: actions/setup-go@v2
with:
go-version: "1.18"
- run: make install
- uses: actions/cache@v2
with:
path: ~/go/bin/oathkeeper
key: oathkeeper-${{ hashFiles('~/go/bin/oathkeeper') }}
restore-keys: |
oathkeeper-
test:
runs-on: ubuntu-latest
name: Run tests
Expand All @@ -82,7 +66,6 @@ jobs:
name: ["reload", "e2e", "forwarded-header"]
needs:
- sdk-generate
- setup-tests
steps:
- uses: ory/ci/checkout@master
- uses: actions/setup-go@v2
Expand All @@ -92,7 +75,10 @@ jobs:
with:
path: ~/go/bin/oathkeeper
key: oathkeeper-${{ hashFiles('~/go/bin/oathkeeper') }}
- run: ./test/${{ matrix.name }}/run.sh
- run: |
make install
go version -m $(which oathkeeper) | grep "\w*build"
./test/${{ matrix.name }}/run.sh
docs-cli:
runs-on: ubuntu-latest
Expand Down
9 changes: 9 additions & 0 deletions .schema/embed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package schema

import "embed"

//go:embed *.json all:pipeline
var FS embed.FS

//go:embed config.schema.json
var Config []byte
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ format: .bin/goimports node_modules
# Generates the SDK
.PHONY: sdk
sdk: .bin/swagger .bin/ory node_modules
rm -rf internal/httpclient
mkdir -p internal/httpclient

swagger generate spec -m -o spec/swagger.json \
-c github.com/ory/oathkeeper \
-c github.com/ory/x/healthx
Expand All @@ -50,8 +53,6 @@ sdk: .bin/swagger .bin/ory node_modules
-p file://.schema/openapi/patches/meta.yaml \
spec/swagger.json spec/api.json

rm -rf internal/httpclient
mkdir -p internal/httpclient
swagger generate client -f ./spec/swagger.json -t internal/httpclient -A Ory_Oathkeeper

make format
Expand Down
14 changes: 7 additions & 7 deletions api/credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ func (h *CredentialsHandler) SetRoutes(r *x.RouterAPI) {

// swagger:route GET /.well-known/jwks.json api getWellKnownJSONWebKeys
//
// Lists Cryptographic Keys
// # Lists Cryptographic Keys
//
// This endpoint returns cryptographic keys that are required to, for example, verify signatures of ID Tokens.
//
// Produces:
// - application/json
// Produces:
// - application/json
//
// Schemes: http, https
// Schemes: http, https
//
// Responses:
// 200: jsonWebKeySet
// 500: genericError
// Responses:
// 200: jsonWebKeySet
// 500: genericError
func (h *CredentialsHandler) wellKnown(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
urls, err := h.jwksURLs()
if err != nil {
Expand Down
20 changes: 16 additions & 4 deletions api/credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/ory/viper"
"github.com/ory/x/configx"

"github.com/ory/oathkeeper/driver/configuration"
"github.com/ory/oathkeeper/internal"
Expand All @@ -21,13 +21,25 @@ import (
)

func TestCredentialsHandler(t *testing.T) {
conf := internal.NewConfigurationWithDefaults()
viper.Set(configuration.ViperKeyMutatorIDTokenJWKSURL, "file://../test/stub/jwks-rsa-multiple.json")
conf := internal.NewConfigurationWithDefaults(configx.SkipValidation())
conf.SetForTest(t, configuration.MutatorIDTokenJWKSURL, "file://../test/stub/jwks-rsa-multiple.json")

r := internal.NewRegistry(conf)

require.NoError(t, r.RuleRepository().Set(
context.Background(),
[]rule.Rule{{Mutators: []rule.Handler{{Handler: "id_token", Config: json.RawMessage(`{"jwks_url":"file://../test/stub/jwks-rsa-single.json"}`)}}}}),
[]rule.Rule{{
Match: &rule.Match{URL: "http://example.com/*"},
Authenticators: []rule.Handler{{Handler: "anonymous"}},
Authorizer: rule.Handler{Handler: "allow"},
Mutators: []rule.Handler{{
Handler: "id_token",
Config: json.RawMessage(`
{
"jwks_url": "file://../test/stub/jwks-rsa-single.json",
"issuer_url": "https://example.com"
}
`)}}}}),
)

router := x.NewAPIRouter()
Expand Down
16 changes: 8 additions & 8 deletions api/decision.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,22 @@ func (h *DecisionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request, next

// swagger:route GET /decisions api decisions
//
// Access Control Decision API
// # Access Control Decision API
//
// > This endpoint works with all HTTP Methods (GET, POST, PUT, ...) and matches every path prefixed with /decision.
//
// This endpoint mirrors the proxy capability of ORY Oathkeeper's proxy functionality but instead of forwarding the
// request to the upstream server, returns 200 (request should be allowed), 401 (unauthorized), or 403 (forbidden)
// status codes. This endpoint can be used to integrate with other API Proxies like Ambassador, Kong, Envoy, and many more.
//
// Schemes: http, https
// Schemes: http, https
//
// Responses:
// 200: emptyResponse
// 401: genericError
// 403: genericError
// 404: genericError
// 500: genericError
// Responses:
// 200: emptyResponse
// 401: genericError
// 403: genericError
// 404: genericError
// 500: genericError
func (h *DecisionHandler) decisions(w http.ResponseWriter, r *http.Request) {
fields := map[string]interface{}{
"http_method": r.Method,
Expand Down
15 changes: 7 additions & 8 deletions api/decision_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,18 @@ import (
"github.com/ory/oathkeeper/pipeline/authn"
"github.com/ory/oathkeeper/proxy"
"github.com/ory/oathkeeper/rule"
"github.com/ory/viper"
"github.com/ory/x/logrusx"
)

func TestDecisionAPI(t *testing.T) {
conf := internal.NewConfigurationWithDefaults()
viper.Set(configuration.ViperKeyAuthenticatorNoopIsEnabled, true)
viper.Set(configuration.ViperKeyAuthenticatorUnauthorizedIsEnabled, true)
viper.Set(configuration.ViperKeyAuthenticatorAnonymousIsEnabled, true)
viper.Set(configuration.ViperKeyAuthorizerAllowIsEnabled, true)
viper.Set(configuration.ViperKeyAuthorizerDenyIsEnabled, true)
viper.Set(configuration.ViperKeyMutatorNoopIsEnabled, true)
viper.Set(configuration.ViperKeyErrorsWWWAuthenticateIsEnabled, true)
conf.SetForTest(t, configuration.AuthenticatorNoopIsEnabled, true)
conf.SetForTest(t, configuration.AuthenticatorUnauthorizedIsEnabled, true)
conf.SetForTest(t, configuration.AuthenticatorAnonymousIsEnabled, true)
conf.SetForTest(t, configuration.AuthorizerAllowIsEnabled, true)
conf.SetForTest(t, configuration.AuthorizerDenyIsEnabled, true)
conf.SetForTest(t, configuration.MutatorNoopIsEnabled, true)
conf.SetForTest(t, configuration.ErrorsWWWAuthenticateIsEnabled, true)
reg := internal.NewRegistry(conf).WithBrokenPipelineMutator()

d := reg.DecisionHandler()
Expand Down
34 changes: 17 additions & 17 deletions api/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package api
//
// swagger:route GET /health/alive api isInstanceAlive
//
// Check Alive Status
// # Check Alive Status
//
// This endpoint returns a 200 status code when the HTTP server is up running.
// This status does currently not include checks whether the database connection is working.
Expand All @@ -15,19 +15,19 @@ package api
// Be aware that if you are running multiple nodes of this service, the health status will never
// refer to the cluster state, only to a single instance.
//
// Produces:
// - application/json
// Produces:
// - application/json
//
// Responses:
// 200: healthStatus
// 500: genericError
// Responses:
// 200: healthStatus
// 500: genericError
func swaggerIsInstanceAlive() {}

// Ready returns an ok status if the instance is ready to handle HTTP requests and all ReadyCheckers are ok.
//
// swagger:route GET /health/ready api isInstanceReady
//
// Check Readiness Status
// # Check Readiness Status
//
// This endpoint returns a 200 status code when the HTTP server is up running and the environment dependencies (e.g.
// the database) are responsive as well.
Expand All @@ -38,19 +38,19 @@ func swaggerIsInstanceAlive() {}
// Be aware that if you are running multiple nodes of this service, the health status will never
// refer to the cluster state, only to a single instance.
//
// Produces:
// - application/json
// Produces:
// - application/json
//
// Responses:
// 200: healthStatus
// 503: healthNotReadyStatus
// Responses:
// 200: healthStatus
// 503: healthNotReadyStatus
func swaggerIsInstanceReady() {}

// Version returns this service's versions.
//
// swagger:route GET /version api getVersion
//
// Get Service Version
// # Get Service Version
//
// This endpoint returns the service version typically notated using semantic versioning.
//
Expand All @@ -60,9 +60,9 @@ func swaggerIsInstanceReady() {}
// Be aware that if you are running multiple nodes of this service, the health status will never
// refer to the cluster state, only to a single instance.
//
// Produces:
// - application/json
// Produces:
// - application/json
//
// Responses:
// 200: version
// Responses:
// 200: version
func swaggerGetVersion() {}
19 changes: 12 additions & 7 deletions api/health_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,21 @@ type statusResult struct {
// Status should contains "ok" in case of success
Status string `json:"status"`
// Otherwise a map of error messages is returned
Errors map[string]string `json:"errors"`
Error *statusError `json:"error"`
}

type statusError struct {
Code int `json:"code"`
Status string `json:"status"`
Message string `json:"message"`
}

func TestHealth(t *testing.T) {
conf := internal.NewConfigurationWithDefaults()
r := internal.NewRegistry(conf)

router := x.NewAPIRouter()
r.HealthHandler().SetRoutes(router.Router, true)
r.HealthHandler().SetHealthRoutes(router.Router, true)
server := httptest.NewServer(router)
defer server.Close()

Expand All @@ -40,7 +46,7 @@ func TestHealth(t *testing.T) {
require.Equal(t, http.StatusOK, res.StatusCode)
require.NoError(t, json.NewDecoder(res.Body).Decode(&result))
assert.Equal(t, "ok", result.Status)
assert.Len(t, result.Errors, 0)
assert.Nil(t, result.Error)

result = statusResult{}
res, err = server.Client().Get(server.URL + "/health/ready")
Expand All @@ -49,8 +55,7 @@ func TestHealth(t *testing.T) {
require.Equal(t, http.StatusServiceUnavailable, res.StatusCode)
require.NoError(t, json.NewDecoder(res.Body).Decode(&result))
assert.Empty(t, result.Status)
assert.Len(t, result.Errors, 1)
assert.Equal(t, rulereadiness.ErrRuleNotYetLoaded.Error(), result.Errors[rulereadiness.ProbeName])
assert.Equal(t, rulereadiness.ErrRuleNotYetLoaded.Error(), result.Error.Message)

r.Init()
// Waiting for rule load and health event propagation
Expand All @@ -64,7 +69,7 @@ func TestHealth(t *testing.T) {
require.Equal(t, http.StatusOK, res.StatusCode)
require.NoError(t, json.NewDecoder(res.Body).Decode(&result))
assert.Equal(t, "ok", result.Status)
assert.Len(t, result.Errors, 0)
assert.Nil(t, result.Error)

result = statusResult{}
res, err = server.Client().Get(server.URL + "/health/ready")
Expand All @@ -73,5 +78,5 @@ func TestHealth(t *testing.T) {
require.Equal(t, http.StatusOK, res.StatusCode)
require.NoError(t, json.NewDecoder(res.Body).Decode(&result))
assert.Equal(t, "ok", result.Status)
assert.Len(t, result.Errors, 0)
assert.Nil(t, result.Error)
}
38 changes: 19 additions & 19 deletions api/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,22 @@ func (h *RuleHandler) SetRoutes(r *x.RouterAPI) {

// swagger:route GET /rules api listRules
//
// List All Rules
// # List All Rules
//
// This method returns an array of all rules that are stored in the backend. This is useful if you want to get a full
// view of what rules you have currently in place.
//
// Consumes:
// - application/json
// Consumes:
// - application/json
//
// Produces:
// - application/json
// Produces:
// - application/json
//
// Schemes: http, https
// Schemes: http, https
//
// Responses:
// 200: rules
// 500: genericError
// Responses:
// 200: rules
// 500: genericError
func (h *RuleHandler) listRules(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
limit, offset := pagination.Parse(r, 50, 0, 500)
rules, err := h.r.RuleRepository().List(r.Context(), limit, offset)
Expand All @@ -90,22 +90,22 @@ func (h *RuleHandler) listRules(w http.ResponseWriter, r *http.Request, _ httpro

// swagger:route GET /rules/{id} api getRule
//
// Retrieve a Rule
// # Retrieve a Rule
//
// Use this method to retrieve a rule from the storage. If it does not exist you will receive a 404 error.
//
// Consumes:
// - application/json
// Consumes:
// - application/json
//
// Produces:
// - application/json
// Produces:
// - application/json
//
// Schemes: http, https
// Schemes: http, https
//
// Responses:
// 200: rule
// 404: genericError
// 500: genericError
// Responses:
// 200: rule
// 404: genericError
// 500: genericError
func (h *RuleHandler) getRules(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
rl, err := h.r.RuleRepository().Get(r.Context(), ps.ByName("id"))
if errors.Cause(err) == helper.ErrResourceNotFound {
Expand Down
Loading

0 comments on commit 6bac536

Please sign in to comment.