Skip to content

Commit

Permalink
Makes policy resource names prefixes configurable (ory#672)
Browse files Browse the repository at this point in the history
  • Loading branch information
arekkas authored Dec 4, 2017
1 parent 84bcd68 commit aee603b
Show file tree
Hide file tree
Showing 17 changed files with 199 additions and 84 deletions.
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,15 @@ This list makes you aware of any breaking and substantial non-breaking changes.

## 0.10.0-alpha.22

### Breaking changes

The JWK algorithm `ES521` was renamed to `ES512`. If you want to generate a key using this algorithm, you have to use
the update name in the future.

### Additions

It is now possible to alter resource name prefixes (`rn:hydra`) using the `RESOURCE_NAME_PREFIX` environment variable.

## 0.10.0-alpha.16

Versions `0.10.0-alpha.13`, `0.10.0-alpha.14`, and `0.10.0-alpha.15` had issues with the static binary of ORY Hydra which has been resolved.
Expand Down
33 changes: 23 additions & 10 deletions client/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,34 @@ import (
)

type Handler struct {
Manager Manager
H herodot.Writer
W firewall.Firewall
Manager Manager
H herodot.Writer
W firewall.Firewall
ResourcePrefix string
}

const (
ClientsHandlerPath = "/clients"
)

const (
ClientsResource = "rn:hydra:clients"
ClientResource = "rn:hydra:clients:%s"
ClientsResource = "clients"
ClientResource = "clients:%s"
Scope = "hydra.clients"
)

func (h *Handler) PrefixResource(resource string) string {
if h.ResourcePrefix == "" {
h.ResourcePrefix = "rn:hydra"
}

if h.ResourcePrefix[len(h.ResourcePrefix)-1] == ':' {
h.ResourcePrefix = h.ResourcePrefix[:len(h.ResourcePrefix)-1]
}

return h.ResourcePrefix + ":" + resource
}

func (h *Handler) SetRoutes(r *httprouter.Router) {
r.GET(ClientsHandlerPath, h.List)
r.POST(ClientsHandlerPath, h.Create)
Expand Down Expand Up @@ -107,7 +120,7 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request, _ httprouter.Pa
}

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: ClientsResource,
Resource: h.PrefixResource(ClientsResource),
Action: "create",
Context: map[string]interface{}{
"owner": c.Owner,
Expand Down Expand Up @@ -199,7 +212,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request, ps httprouter.P
}

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: ClientsResource,
Resource: h.PrefixResource(ClientsResource),
Action: "update",
Context: ladon.Context{
"owner": o.Owner,
Expand Down Expand Up @@ -264,7 +277,7 @@ func (h *Handler) List(w http.ResponseWriter, r *http.Request, ps httprouter.Par
var ctx = r.Context()

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: ClientsResource,
Resource: h.PrefixResource(ClientsResource),
Action: "get",
}, Scope); err != nil {
h.H.WriteError(w, r, err)
Expand Down Expand Up @@ -343,7 +356,7 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request, ps httprouter.Para
}

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: fmt.Sprintf(ClientResource, id),
Resource: fmt.Sprintf(h.PrefixResource(ClientResource), id),
Action: "get",
Context: ladon.Context{
"owner": c.GetOwner(),
Expand Down Expand Up @@ -409,7 +422,7 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request, ps httprouter.P
}

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: fmt.Sprintf(ClientResource, id),
Resource: fmt.Sprintf(h.PrefixResource(ClientResource), id),
Action: "delete",
Context: ladon.Context{
"owner": c.GetOwner(),
Expand Down
4 changes: 4 additions & 0 deletions cmd/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ CORE CONTROLS
visit https://ory.gitbooks.io/hydra/content/telemetry.html
Example: DISABLE_TELEMETRY="1"
- RESOURCE_NAME_PREFIX: Allows the alternation of the "rn:hydra:" prefix in all resource names declared by ORY Hydra.
Defaults to "rn:hydra" if empty and removes the last trailing colon.
Example: RESOURCE_NAME_PREFIX="resources:my-domain.com"
OAUTH2 CONTROLS
===============
Expand Down
3 changes: 3 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ func initConfig() {
viper.BindEnv("LOG_FORMAT")
viper.SetDefault("LOG_FORMAT", "")

viper.BindEnv("RESOURCE_NAME_PREFIX")
viper.SetDefault("RESOURCE_NAME_PREFIX", "")

// If a config file is found, read it in.
if err := viper.ReadInConfig(); err != nil {
fmt.Printf(`Config file not found because "%s"`, err)
Expand Down
7 changes: 4 additions & 3 deletions cmd/server/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,10 @@ func (h *Handler) registerRoutes(router *httprouter.Router) {
h.OAuth2 = newOAuth2Handler(c, router, ctx.ConsentManager, oauth2Provider)
h.Warden = warden.NewHandler(c, router)
h.Groups = &group.Handler{
H: herodot.NewJSONWriter(c.GetLogger()),
W: ctx.Warden,
Manager: ctx.GroupManager,
H: herodot.NewJSONWriter(c.GetLogger()),
W: ctx.Warden,
Manager: ctx.GroupManager,
ResourcePrefix: c.AccessControlResourcePrefix,
}
h.Groups.SetRoutes(router)
_ = newHealthHandler(c, router)
Expand Down
1 change: 1 addition & 0 deletions cmd/server/handler_client_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func newClientHandler(c *config.Config, router *httprouter.Router, manager clien
h := &client.Handler{
H: herodot.NewJSONWriter(c.GetLogger()),
W: ctx.Warden, Manager: manager,
ResourcePrefix: c.AccessControlResourcePrefix,
}

h.SetRoutes(router)
Expand Down
1 change: 1 addition & 0 deletions cmd/server/handler_consent_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func newConsentHanlder(c *config.Config, router *httprouter.Router) *oauth2.Cons
h := &oauth2.ConsentSessionHandler{
H: herodot.NewJSONWriter(c.GetLogger()),
W: ctx.Warden, M: ctx.ConsentManager,
ResourcePrefix: c.AccessControlResourcePrefix,
}

h.SetRoutes(router)
Expand Down
7 changes: 4 additions & 3 deletions cmd/server/handler_health_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import (

func newHealthHandler(c *config.Config, router *httprouter.Router) *health.Handler {
h := &health.Handler{
Metrics: c.GetMetrics(),
H: herodot.NewJSONWriter(c.GetLogger()),
W: c.Context().Warden,
Metrics: c.GetMetrics(),
H: herodot.NewJSONWriter(c.GetLogger()),
W: c.Context().Warden,
ResourcePrefix: c.AccessControlResourcePrefix,
}
h.SetRoutes(router)
return h
Expand Down
7 changes: 4 additions & 3 deletions cmd/server/handler_jwk_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ func injectJWKManager(c *config.Config) {
func newJWKHandler(c *config.Config, router *httprouter.Router) *jwk.Handler {
ctx := c.Context()
h := &jwk.Handler{
H: herodot.NewJSONWriter(c.GetLogger()),
W: ctx.Warden,
Manager: ctx.KeyManager,
H: herodot.NewJSONWriter(c.GetLogger()),
W: ctx.Warden,
Manager: ctx.KeyManager,
ResourcePrefix: c.AccessControlResourcePrefix,
}
h.SetRoutes(router)
return h
Expand Down
7 changes: 4 additions & 3 deletions cmd/server/handler_policy_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ import (
func newPolicyHandler(c *config.Config, router *httprouter.Router) *policy.Handler {
ctx := c.Context()
h := &policy.Handler{
H: herodot.NewJSONWriter(c.GetLogger()),
W: ctx.Warden,
Manager: ctx.LadonManager,
H: herodot.NewJSONWriter(c.GetLogger()),
W: ctx.Warden,
Manager: ctx.LadonManager,
ResourcePrefix: c.AccessControlResourcePrefix,
}
h.SetRoutes(router)
return h
Expand Down
37 changes: 19 additions & 18 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,25 @@ type Config struct {
ClientSecret string `mapstructure:"CLIENT_SECRET" yaml:"client_secret,omitempty"`

// These are used by the host command
BindPort int `mapstructure:"PORT" yaml:"-"`
BindHost string `mapstructure:"HOST" yaml:"-"`
Issuer string `mapstructure:"ISSUER" yaml:"-"`
SystemSecret string `mapstructure:"SYSTEM_SECRET" yaml:"-"`
DatabaseURL string `mapstructure:"DATABASE_URL" yaml:"-"`
DatabasePlugin string `mapstructure:"DATABASE_PLUGIN" yaml:"-"`
ConsentURL string `mapstructure:"CONSENT_URL" yaml:"-"`
AllowTLSTermination string `mapstructure:"HTTPS_ALLOW_TERMINATION_FROM" yaml:"-"`
BCryptWorkFactor int `mapstructure:"BCRYPT_COST" yaml:"-"`
AccessTokenLifespan string `mapstructure:"ACCESS_TOKEN_LIFESPAN" yaml:"-"`
ScopeStrategy string `mapstructure:"SCOPE_STRATEGY" yaml:"-"`
AuthCodeLifespan string `mapstructure:"AUTH_CODE_LIFESPAN" yaml:"-"`
IDTokenLifespan string `mapstructure:"ID_TOKEN_LIFESPAN" yaml:"-"`
ChallengeTokenLifespan string `mapstructure:"CHALLENGE_TOKEN_LIFESPAN" yaml:"-"`
CookieSecret string `mapstructure:"COOKIE_SECRET" yaml:"-"`
LogLevel string `mapstructure:"LOG_LEVEL" yaml:"-"`
LogFormat string `mapstructure:"LOG_FORMAT" yaml:"-"`
ForceHTTP bool `yaml:"-"`
BindPort int `mapstructure:"PORT" yaml:"-"`
BindHost string `mapstructure:"HOST" yaml:"-"`
Issuer string `mapstructure:"ISSUER" yaml:"-"`
SystemSecret string `mapstructure:"SYSTEM_SECRET" yaml:"-"`
DatabaseURL string `mapstructure:"DATABASE_URL" yaml:"-"`
DatabasePlugin string `mapstructure:"DATABASE_PLUGIN" yaml:"-"`
ConsentURL string `mapstructure:"CONSENT_URL" yaml:"-"`
AllowTLSTermination string `mapstructure:"HTTPS_ALLOW_TERMINATION_FROM" yaml:"-"`
BCryptWorkFactor int `mapstructure:"BCRYPT_COST" yaml:"-"`
AccessTokenLifespan string `mapstructure:"ACCESS_TOKEN_LIFESPAN" yaml:"-"`
ScopeStrategy string `mapstructure:"SCOPE_STRATEGY" yaml:"-"`
AuthCodeLifespan string `mapstructure:"AUTH_CODE_LIFESPAN" yaml:"-"`
IDTokenLifespan string `mapstructure:"ID_TOKEN_LIFESPAN" yaml:"-"`
ChallengeTokenLifespan string `mapstructure:"CHALLENGE_TOKEN_LIFESPAN" yaml:"-"`
CookieSecret string `mapstructure:"COOKIE_SECRET" yaml:"-"`
LogLevel string `mapstructure:"LOG_LEVEL" yaml:"-"`
LogFormat string `mapstructure:"LOG_FORMAT" yaml:"-"`
AccessControlResourcePrefix string `mapstructure:"RESOURCE_NAME_PREFIX" yaml:"-"`
ForceHTTP bool `yaml:"-"`

BuildVersion string `yaml:"-"`
BuildHash string `yaml:"-"`
Expand Down
21 changes: 17 additions & 4 deletions health/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,22 @@ import (
)

type Handler struct {
Metrics *metrics.MetricsManager
H *herodot.JSONWriter
W firewall.Firewall
Metrics *metrics.MetricsManager
H *herodot.JSONWriter
W firewall.Firewall
ResourcePrefix string
}

func (h *Handler) PrefixResource(resource string) string {
if h.ResourcePrefix == "" {
h.ResourcePrefix = "rn:hydra"
}

if h.ResourcePrefix[len(h.ResourcePrefix)-1] == ':' {
h.ResourcePrefix = h.ResourcePrefix[:len(h.ResourcePrefix)-1]
}

return h.ResourcePrefix + ":" + resource
}

func (h *Handler) SetRoutes(r *httprouter.Router) {
Expand Down Expand Up @@ -91,7 +104,7 @@ func (h *Handler) Statistics(w http.ResponseWriter, r *http.Request, ps httprout
var ctx = r.Context()

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:health:stats",
Resource: h.PrefixResource("health:stats"),
Action: "get",
}, "hydra.health"); err != nil {
h.H.WriteError(w, r, err)
Expand Down
41 changes: 27 additions & 14 deletions jwk/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,23 @@ const (
)

type Handler struct {
Manager Manager
Generators map[string]KeyGenerator
H herodot.Writer
W firewall.Firewall
Manager Manager
Generators map[string]KeyGenerator
H herodot.Writer
W firewall.Firewall
ResourcePrefix string
}

func (h *Handler) PrefixResource(resource string) string {
if h.ResourcePrefix == "" {
h.ResourcePrefix = "rn:hydra"
}

if h.ResourcePrefix[len(h.ResourcePrefix)-1] == ':' {
h.ResourcePrefix = h.ResourcePrefix[:len(h.ResourcePrefix)-1]
}

return h.ResourcePrefix + ":" + resource
}

func (h *Handler) GetGenerators() map[string]KeyGenerator {
Expand Down Expand Up @@ -114,12 +127,12 @@ type joseWebKeySetRequest struct {
func (h *Handler) WellKnown(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var ctx = context.Background()
if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:keys:" + IDTokenKeyName + ":public",
Resource: h.PrefixResource("keys:" + IDTokenKeyName + ":public"),
Action: "get",
}, "hydra.keys.get"); err != nil {
if err := h.W.IsAllowed(ctx, &firewall.AccessRequest{
Subject: "",
Resource: "rn:hydra:keys:" + IDTokenKeyName + ":public",
Resource: h.PrefixResource("keys:" + IDTokenKeyName + ":public"),
Action: "get",
}); err != nil {
h.H.WriteError(w, r, err)
Expand Down Expand Up @@ -177,12 +190,12 @@ func (h *Handler) GetKey(w http.ResponseWriter, r *http.Request, ps httprouter.P
var keyName = ps.ByName("key")

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:keys:" + setName + ":" + keyName,
Resource: h.PrefixResource("keys:" + setName + ":" + keyName),
Action: "get",
}, "hydra.keys.get"); err != nil {
if err := h.W.IsAllowed(ctx, &firewall.AccessRequest{
Subject: "",
Resource: "rn:hydra:keys:" + setName + ":" + keyName,
Resource: h.PrefixResource("keys:" + setName + ":" + keyName),
Action: "get",
}); err != nil {
h.H.WriteError(w, r, err)
Expand Down Expand Up @@ -246,7 +259,7 @@ func (h *Handler) GetKeySet(w http.ResponseWriter, r *http.Request, ps httproute

for _, key := range keys.Keys {
if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:keys:" + setName + ":" + key.KeyID,
Resource: h.PrefixResource("keys:" + setName + ":" + key.KeyID),
Action: "get",
}, "hydra.keys.get"); err != nil {
h.H.WriteError(w, r, err)
Expand Down Expand Up @@ -300,7 +313,7 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request, ps httprouter.P
var set = ps.ByName("set")

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:keys:" + set,
Resource: h.PrefixResource("keys:" + set),
Action: "create",
}, "hydra.keys.create"); err != nil {
h.H.WriteError(w, r, err)
Expand Down Expand Up @@ -371,7 +384,7 @@ func (h *Handler) UpdateKeySet(w http.ResponseWriter, r *http.Request, ps httpro
var set = ps.ByName("set")

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:keys:" + set,
Resource: h.PrefixResource("keys:" + set),
Action: "update",
}, "hydra.keys.update"); err != nil {
h.H.WriteError(w, r, err)
Expand Down Expand Up @@ -443,7 +456,7 @@ func (h *Handler) UpdateKey(w http.ResponseWriter, r *http.Request, ps httproute
}

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:keys:" + set + ":" + key.KeyID,
Resource: h.PrefixResource("keys:" + set + ":" + key.KeyID),
Action: "update",
}, "hydra.keys.update"); err != nil {
h.H.WriteError(w, r, err)
Expand Down Expand Up @@ -493,7 +506,7 @@ func (h *Handler) DeleteKeySet(w http.ResponseWriter, r *http.Request, ps httpro
var setName = ps.ByName("set")

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:keys:" + setName,
Resource: h.PrefixResource("keys:" + setName),
Action: "delete",
}, "hydra.keys.delete"); err != nil {
h.H.WriteError(w, r, err)
Expand Down Expand Up @@ -544,7 +557,7 @@ func (h *Handler) DeleteKey(w http.ResponseWriter, r *http.Request, ps httproute
var keyName = ps.ByName("key")

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: "rn:hydra:keys:" + setName + ":" + keyName,
Resource: h.PrefixResource("keys:" + setName + ":" + keyName),
Action: "delete",
}, "hydra.keys.delete"); err != nil {
h.H.WriteError(w, r, err)
Expand Down
Loading

0 comments on commit aee603b

Please sign in to comment.