Skip to content

Commit

Permalink
policy: provide rest endpoint for policy updates - closes #305
Browse files Browse the repository at this point in the history
  • Loading branch information
Aeneas Rekkas (arekkas) committed Dec 29, 2016
1 parent e954cee commit f1c2025
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 39 deletions.
154 changes: 118 additions & 36 deletions cmd/cli/handler_policy.go
Expand Up @@ -34,12 +34,12 @@ func (h *PolicyHandler) CreatePolicy(cmd *cobra.Command, args []string) {
for _, path := range files {
reader, err := os.Open(path)
pkg.Must(err, "Could not open file %s: %s", path, err)
var policy ladon.DefaultPolicy
err = json.NewDecoder(reader).Decode(&policy)
var p ladon.DefaultPolicy
err = json.NewDecoder(reader).Decode(&p)
pkg.Must(err, "Could not parse JSON: %s", err)
err = h.M.Create(&policy)
err = h.M.Create(&p)
pkg.Must(err, "Could not create policy: %s", err)
fmt.Printf("Imported policy %s from %s.\n", policy.ID, path)
fmt.Printf("Imported policy %s from %s.\n", p.ID, path)
}
return
}
Expand All @@ -61,21 +61,21 @@ func (h *PolicyHandler) CreatePolicy(cmd *cobra.Command, args []string) {
effect = ladon.AllowAccess
}

policy := &ladon.DefaultPolicy{
p := &ladon.DefaultPolicy{
ID: id,
Description: description,
Subjects: subjects,
Resources: resources,
Actions: actions,
Effect: effect,
}
err := h.M.Create(policy)
err := h.M.Create(p)
if h.M.Dry {
fmt.Printf("%s\n", err)
return
}
pkg.Must(err, "Could not create policy: %s", err)
fmt.Printf("Created policy %s.\n", policy.ID)
fmt.Printf("Created policy %s.\n", p.ID)

}

Expand All @@ -89,20 +89,13 @@ func (h *PolicyHandler) AddResourceToPolicy(cmd *cobra.Command, args []string) {
return
}

policy, err := h.M.Get(args[0])
pp, err := h.M.Get(args[0])
pkg.Must(err, "Could not get policy: %s", err)

err = h.M.Delete(args[0])
if h.M.Dry {
fmt.Printf("%s\n", err)
} else {
pkg.Must(err, "Could not prepare policy for update: %s", err)
}

p := policy.(*ladon.DefaultPolicy)
p := pp.(*ladon.DefaultPolicy)
p.Resources = append(p.Resources, args[1:]...)

err = h.M.Create(policy)
err = h.M.Update(p)
if h.M.Dry {
fmt.Printf("%s\n", err)
return
Expand All @@ -112,7 +105,40 @@ func (h *PolicyHandler) AddResourceToPolicy(cmd *cobra.Command, args []string) {
}

func (h *PolicyHandler) RemoveResourceFromPolicy(cmd *cobra.Command, args []string) {
fmt.Println("Not yet implemented.")
h.M.Dry, _ = cmd.Flags().GetBool("dry")
h.M.Endpoint = h.Config.Resolve("/policies")
h.M.Client = h.Config.OAuth2Client(cmd)

if len(args) < 2 {
fmt.Print(cmd.UsageString())
return
}

pp, err := h.M.Get(args[0])
pkg.Must(err, "Could not get policy: %s", err)

p := pp.(*ladon.DefaultPolicy)
resources := []string{}
for _, r := range p.Resources {
var filter bool
for _, a := range args[1:] {
if r == a {
filter = true
}
}
if !filter {
resources = append(resources, r)
}
}
p.Resources = resources

err = h.M.Update(p)
if h.M.Dry {
fmt.Printf("%s\n", err)
return
}
pkg.Must(err, "Could not update policy: %s", err)
fmt.Printf("Added resources to policy %s", p.ID)
}

func (h *PolicyHandler) AddSubjectToPolicy(cmd *cobra.Command, args []string) {
Expand All @@ -125,20 +151,17 @@ func (h *PolicyHandler) AddSubjectToPolicy(cmd *cobra.Command, args []string) {
return
}

policy, err := h.M.Get(args[0])
pp, err := h.M.Get(args[0])
if h.M.Dry {
fmt.Printf("%s\n", err)
} else {
pkg.Must(err, "Could not get policy: %s", err)
}

err = h.M.Delete(args[0])
pkg.Must(err, "Could not prepare policy for update: %s", err)

p := policy.(*ladon.DefaultPolicy)
p := pp.(*ladon.DefaultPolicy)
p.Subjects = append(p.Subjects, args[1:]...)

err = h.M.Create(policy)
err = h.M.Update(p)
if h.M.Dry {
fmt.Printf("%s\n", err)
return
Expand All @@ -148,10 +171,6 @@ func (h *PolicyHandler) AddSubjectToPolicy(cmd *cobra.Command, args []string) {
}

func (h *PolicyHandler) RemoveSubjectFromPolicy(cmd *cobra.Command, args []string) {
fmt.Println("Not yet implemented.")
}

func (h *PolicyHandler) AddActionToPolicy(cmd *cobra.Command, args []string) {
h.M.Dry, _ = cmd.Flags().GetBool("dry")
h.M.Endpoint = h.Config.Resolve("/policies")
h.M.Client = h.Config.OAuth2Client(cmd)
Expand All @@ -161,30 +180,93 @@ func (h *PolicyHandler) AddActionToPolicy(cmd *cobra.Command, args []string) {
return
}

p, err := h.M.Get(args[0])
pp, err := h.M.Get(args[0])
pkg.Must(err, "Could not get policy: %s", err)

err = h.M.Delete(args[0])
p := pp.(*ladon.DefaultPolicy)
subjects := []string{}
for _, r := range p.Subjects {
var filter bool
for _, a := range args[1:] {
if r == a {
filter = true
}
}
if !filter {
subjects = append(subjects, r)
}
}
p.Subjects = subjects

err = h.M.Update(p)
if h.M.Dry {
fmt.Printf("%s\n", err)
} else {
pkg.Must(err, "Could not prepare policy for update: %s", err)
return
}
pkg.Must(err, "Could not update policy: %s", err)
fmt.Printf("Added resources to policy %s", p.ID)
}

func (h *PolicyHandler) AddActionToPolicy(cmd *cobra.Command, args []string) {
h.M.Dry, _ = cmd.Flags().GetBool("dry")
h.M.Endpoint = h.Config.Resolve("/policies")
h.M.Client = h.Config.OAuth2Client(cmd)

if len(args) < 2 {
fmt.Print(cmd.UsageString())
return
}

encp := p.(*ladon.DefaultPolicy)
encp.Actions = append(encp.Actions, args[1:]...)
pp, err := h.M.Get(args[0])
pkg.Must(err, "Could not get policy: %s", err)

p := pp.(*ladon.DefaultPolicy)
p.Actions = append(p.Actions, args[1:]...)

err = h.M.Create(p)
if h.M.Dry {
fmt.Printf("%s\n", err)
return
}
pkg.Must(err, "Could not update policy: %s", err)
fmt.Printf("Added actions to policy %s", encp.ID)
fmt.Printf("Added actions to policy %s", p.ID)
}

func (h *PolicyHandler) RemoveActionFromPolicy(cmd *cobra.Command, args []string) {
fmt.Println("Not yet implemented.")
h.M.Dry, _ = cmd.Flags().GetBool("dry")
h.M.Endpoint = h.Config.Resolve("/policies")
h.M.Client = h.Config.OAuth2Client(cmd)

if len(args) < 2 {
fmt.Print(cmd.UsageString())
return
}

pp, err := h.M.Get(args[0])
pkg.Must(err, "Could not get policy: %s", err)

p := pp.(*ladon.DefaultPolicy)
actions := []string{}
for _, r := range p.Actions {
var filter bool
for _, a := range args[1:] {
if r == a {
filter = true
}
}
if !filter {
actions = append(actions, r)
}
}
p.Actions = actions

err = h.M.Update(p)
if h.M.Dry {
fmt.Printf("%s\n", err)
return
}
pkg.Must(err, "Could not update policy: %s", err)
fmt.Printf("Added resources to policy %s", p.ID)
}

func (h *PolicyHandler) GetPolicy(cmd *cobra.Command, args []string) {
Expand Down
37 changes: 37 additions & 0 deletions policy/handler.go
Expand Up @@ -30,6 +30,7 @@ func (h *Handler) SetRoutes(r *httprouter.Router) {
r.POST(endpoint, h.Create)
r.GET(endpoint, h.Find)
r.GET(endpoint + "/:id", h.Get)
r.PUT(endpoint + "/:id", h.Update)
r.DELETE(endpoint + "/:id", h.Delete)
}

Expand Down Expand Up @@ -124,3 +125,39 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request, ps httprouter.P

w.WriteHeader(http.StatusNoContent)
}

func (h *Handler) Update(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var id = ps.ByName("id")
var p = ladon.DefaultPolicy{Conditions: ladon.Conditions{}}
var ctx = herodot.NewContext()

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &firewall.TokenAccessRequest{
Resource: fmt.Sprintf(policiesResource, id),
Action: "update",
}, scope); err != nil {
h.H.WriteError(ctx, w, r, err)
return
}

if err := json.NewDecoder(r.Body).Decode(&p); err != nil {
h.H.WriteError(ctx, w, r, errors.WithStack(err))
return
}

if p.ID != id {
h.H.WriteErrorCode(ctx, w, r, http.StatusBadRequest, errors.New("Payload ID does not match ID from URL"))
return
}

if err := h.Manager.Delete(p.ID); err != nil {
h.H.WriteError(ctx, w, r, errors.WithStack(err))
return
}

if err := h.Manager.Create(&p); err != nil {
h.H.WriteError(ctx, w, r, errors.WithStack(err))
return
}

h.H.Write(ctx, w, r, p)
}
11 changes: 11 additions & 0 deletions policy/manager.go
@@ -0,0 +1,11 @@
package policy

import "github.com/ory-am/ladon"

// Manager is responsible for managing and persisting policies.
type Manager interface {
ladon.Manager

// Update a policy.
Update(policy ladon.Policy) error
}
9 changes: 8 additions & 1 deletion policy/manager_http.go
Expand Up @@ -34,6 +34,14 @@ func (m *HTTPManager) Create(policy ladon.Policy) error {
return r.Create(policy)
}

// Update the policy.
func (m *HTTPManager) Update(policy ladon.Policy) error {
var r = pkg.NewSuperAgent(pkg.JoinURL(m.Endpoint, policy.GetID()).String())
r.Client = m.Client
r.Dry = m.Dry
return r.Update(policy)
}

// Get retrieves a policy.
func (m *HTTPManager) Get(id string) (ladon.Policy, error) {
var policy = ladon.DefaultPolicy{
Expand All @@ -47,7 +55,6 @@ func (m *HTTPManager) Get(id string) (ladon.Policy, error) {
}

return &policy, nil

}

// Delete removes a policy.
Expand Down
13 changes: 11 additions & 2 deletions policy/manager_test.go
Expand Up @@ -18,15 +18,15 @@ import (
"github.com/stretchr/testify/require"
)

var managers = map[string]ladon.Manager{}
var managers = map[string]Manager{}

func init() {
localWarden, httpClient := compose.NewFirewall("hydra", "alice", fosite.Arguments{scope},
&ladon.DefaultPolicy{
ID: "1",
Subjects: []string{"alice"},
Resources: []string{"rn:hydra:policies<.*>"},
Actions: []string{"create", "get", "delete", "find"},
Actions: []string{"create", "get", "delete", "find", "update"},
Effect: ladon.AllowAccess,
},
)
Expand Down Expand Up @@ -86,6 +86,15 @@ func TestManagers(t *testing.T) {
pkg.AssertError(t, false, err, k)
assert.Len(t, ps, 0, "%s", k)

p.Subjects = []string{"stan"}
err = m.Update(p)
pkg.AssertError(t, false, err, k)

ps, err = m.FindPoliciesForSubject("stan")
pkg.RequireError(t, false, err, k)
require.Len(t, ps, 1, "%s", k)
assert.Equal(t, p, ps[0], "%s", k)

pkg.AssertError(t, false, m.Delete(p.ID), k)

_, err = m.Get(p.ID)
Expand Down

0 comments on commit f1c2025

Please sign in to comment.