Skip to content

Commit

Permalink
Add custom metadata to policies (#115)
Browse files Browse the repository at this point in the history
Signed-off-by: Erik Pinders <erik.pinders@gmail.com>
  • Loading branch information
pinders authored and arekkas committed Apr 25, 2018
1 parent d963cb9 commit 76e069e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 9 deletions.
24 changes: 22 additions & 2 deletions manager/sql/databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,18 @@ var Migrations = map[string]Statements{
"DROP INDEX ladon_resource_compiled_idx",
},
},
{
Id: "4",
Up: []string{
"ALTER TABLE ladon_policy ADD COLUMN meta json",
},
Down: []string{
"ALTER TABLE ladon_policy DROP COLUMN IF EXISTS meta",
},
},
},
},
QueryInsertPolicy: `INSERT INTO ladon_policy(id, description, effect, conditions) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_policy WHERE id = $1)`,
QueryInsertPolicy: `INSERT INTO ladon_policy(id, description, effect, conditions, meta) SELECT $1::varchar, $2, $3, $4, $5 WHERE NOT EXISTS (SELECT 1 FROM ladon_policy WHERE id = $1)`,
QueryInsertPolicyActions: `INSERT INTO ladon_action (id, template, compiled, has_regex) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_action WHERE id = $1)`,
QueryInsertPolicyActionsRel: `INSERT INTO ladon_policy_action_rel (policy, action) SELECT $1::varchar, $2::varchar WHERE NOT EXISTS (SELECT 1 FROM ladon_policy_action_rel WHERE policy = $1 AND action = $2)`,
QueryInsertPolicyResources: `INSERT INTO ladon_resource (id, template, compiled, has_regex) SELECT $1::varchar, $2, $3, $4 WHERE NOT EXISTS (SELECT 1 FROM ladon_resource WHERE id = $1)`,
Expand All @@ -151,6 +160,7 @@ var Migrations = map[string]Statements{
p.effect,
p.conditions,
p.description,
p.meta,
subject.template AS subject,
resource.template AS resource,
action.template AS action
Expand Down Expand Up @@ -187,9 +197,18 @@ var Migrations = map[string]Statements{
"DROP INDEX ladon_resource_compiled_idx",
},
},
{
Id: "4",
Up: []string{
"ALTER TABLE ladon_policy ADD COLUMN meta text",
},
Down: []string{
"ALTER TABLE ladon_policy DROP COLUMN meta",
},
},
},
},
QueryInsertPolicy: `INSERT IGNORE INTO ladon_policy (id, description, effect, conditions) VALUES(?,?,?,?)`,
QueryInsertPolicy: `INSERT IGNORE INTO ladon_policy (id, description, effect, conditions, meta) VALUES(?,?,?,?,?)`,
QueryInsertPolicyActions: `INSERT IGNORE INTO ladon_action (id, template, compiled, has_regex) VALUES(?,?,?,?)`,
QueryInsertPolicyActionsRel: `INSERT IGNORE INTO ladon_policy_action_rel (policy, action) VALUES(?,?)`,
QueryInsertPolicyResources: `INSERT IGNORE INTO ladon_resource (id, template, compiled, has_regex) VALUES(?,?,?,?)`,
Expand All @@ -202,6 +221,7 @@ var Migrations = map[string]Statements{
p.effect,
p.conditions,
p.description,
p.meta,
subject.template AS subject,
resource.template AS resource,
action.template AS action
Expand Down
13 changes: 9 additions & 4 deletions manager/sql/manager_sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,16 @@ func (s *SQLManager) create(policy Policy, tx *sqlx.Tx) (err error) {
}
}

meta := []byte("{}")
if policy.GetMeta() != nil {
meta = policy.GetMeta()
}

if _, ok := Migrations[s.database]; !ok {
return errors.Errorf("Database %s is not supported", s.database)
}

if _, err = tx.Exec(s.db.Rebind(Migrations[s.database].QueryInsertPolicy), policy.GetID(), policy.GetDescription(), policy.GetEffect(), conditions); err != nil {
if _, err = tx.Exec(s.db.Rebind(Migrations[s.database].QueryInsertPolicy), policy.GetID(), policy.GetDescription(), policy.GetEffect(), conditions, meta); err != nil {
return errors.WithStack(err)
}

Expand Down Expand Up @@ -217,7 +222,7 @@ func scanRows(rows *sql.Rows) (Policies, error) {
p.Subjects = []string{}
p.Resources = []string{}

if err := rows.Scan(&p.ID, &p.Effect, &conditions, &p.Description, &subject, &resource, &action); err == sql.ErrNoRows {
if err := rows.Scan(&p.ID, &p.Effect, &conditions, &p.Description, &p.Meta, &subject, &resource, &action); err == sql.ErrNoRows {
return nil, NewErrResourceNotFound(err)
} else if err != nil {
return nil, errors.WithStack(err)
Expand Down Expand Up @@ -271,7 +276,7 @@ func scanRows(rows *sql.Rows) (Policies, error) {
}

var getQuery = `SELECT
p.id, p.effect, p.conditions, p.description,
p.id, p.effect, p.conditions, p.description, p.meta,
subject.template as subject, resource.template as resource, action.template as action
FROM
ladon_policy as p
Expand All @@ -287,7 +292,7 @@ LEFT JOIN ladon_resource as resource ON rr.resource = resource.id
WHERE p.id=?`

var getAllQuery = `SELECT
p.id, p.effect, p.conditions, p.description,
p.id, p.effect, p.conditions, p.description, p.meta,
subject.template as subject, resource.template as resource, action.template as action
FROM
(SELECT * from ladon_policy ORDER BY id LIMIT ? OFFSET ?) as p
Expand Down
11 changes: 8 additions & 3 deletions manager/sql/manager_sql_migration_0_5_to_0_6.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (s *SQLManagerMigrateFromMajor0Minor6ToMajor0Minor7) GetManager() ladon.Man

// Get retrieves a policy.
func (s *SQLManagerMigrateFromMajor0Minor6ToMajor0Minor7) Migrate() error {
rows, err := s.DB.Query(s.DB.Rebind("SELECT id, description, effect, conditions FROM ladon_policy"))
rows, err := s.DB.Query(s.DB.Rebind("SELECT id, description, effect, conditions, meta FROM ladon_policy"))
if err != nil {
return errors.WithStack(err)
}
Expand All @@ -55,7 +55,7 @@ func (s *SQLManagerMigrateFromMajor0Minor6ToMajor0Minor7) Migrate() error {
var p DefaultPolicy
var conditions []byte

if err := rows.Scan(&p.ID, &p.Description, &p.Effect, &conditions); err != nil {
if err := rows.Scan(&p.ID, &p.Description, &p.Effect, &conditions, &p.Meta); err != nil {
return errors.WithStack(err)
}

Expand Down Expand Up @@ -131,9 +131,14 @@ func (s *SQLManagerMigrateFromMajor0Minor6ToMajor0Minor7) Create(policy Policy)
}
}

meta := []byte("{}")
if policy.GetMeta() != nil {
meta = policy.GetMeta()
}

if tx, err := s.DB.Begin(); err != nil {
return errors.WithStack(err)
} else if _, err = tx.Exec(s.DB.Rebind("INSERT INTO ladon_policy (id, description, effect, conditions) VALUES (?, ?, ?, ?)"), policy.GetID(), policy.GetDescription(), policy.GetEffect(), conditions); err != nil {
} else if _, err = tx.Exec(s.DB.Rebind("INSERT INTO ladon_policy (id, description, effect, conditions, meta) VALUES (?, ?, ?, ?, ?)"), policy.GetID(), policy.GetDescription(), policy.GetEffect(), conditions, meta); err != nil {
if err := tx.Rollback(); err != nil {
return errors.WithStack(err)
}
Expand Down
20 changes: 20 additions & 0 deletions policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ type Policy interface {
// GetConditions returns the policies conditions.
GetConditions() Conditions

// GetMeta returns the policies arbitrary metadata set by the user.
GetMeta() []byte

// GetStartDelimiter returns the delimiter which identifies the beginning of a regular expression.
GetStartDelimiter() byte

Expand All @@ -71,6 +74,7 @@ type DefaultPolicy struct {
Resources []string `json:"resources" gorethink:"resources"`
Actions []string `json:"actions" gorethink:"actions"`
Conditions Conditions `json:"conditions" gorethink:"conditions"`
Meta []byte `json:"meta" gorethink:"meta"`
}

// UnmarshalJSON overwrite own policy with values of the given in policy in JSON format
Expand All @@ -83,6 +87,7 @@ func (p *DefaultPolicy) UnmarshalJSON(data []byte) error {
Resources []string `json:"resources" gorethink:"resources"`
Actions []string `json:"actions" gorethink:"actions"`
Conditions Conditions `json:"conditions" gorethink:"conditions"`
Meta []byte `json:"meta" gorethink:"meta"`
}{
Conditions: Conditions{},
}
Expand All @@ -99,10 +104,20 @@ func (p *DefaultPolicy) UnmarshalJSON(data []byte) error {
Resources: pol.Resources,
Actions: pol.Actions,
Conditions: pol.Conditions,
Meta: pol.Meta,
}
return nil
}

// UnmarshalMeta parses the policies []byte encoded metadata and stores the result in the value pointed to by v.
func (p *DefaultPolicy) UnmarshalMeta(v interface{}) error {
if err := json.Unmarshal(p.Meta, &v); err != nil {
return errors.WithStack(err)
}

return nil
}

// GetID returns the policies id.
func (p *DefaultPolicy) GetID() string {
return p.ID
Expand Down Expand Up @@ -143,6 +158,11 @@ func (p *DefaultPolicy) GetConditions() Conditions {
return p.Conditions
}

// GetMeta returns the policies arbitrary metadata set by the user.
func (p *DefaultPolicy) GetMeta() []byte {
return p.Meta
}

// GetEndDelimiter returns the delimiter which identifies the end of a regular expression.
func (p *DefaultPolicy) GetEndDelimiter() byte {
return '>'
Expand Down
22 changes: 22 additions & 0 deletions policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ var policyCases = []*DefaultPolicy{
},
}

type TestMeta struct {
Key string `json:"key"`
}

func TestHasAccess(t *testing.T) {
assert.True(t, policyCases[0].AllowAccess())
assert.False(t, policyCases[1].AllowAccess())
Expand All @@ -71,6 +75,24 @@ func TestMarshalling(t *testing.T) {
}
}

func TestMetaUnmarshalling(t *testing.T) {
var m = TestMeta{
Key: "test",
}
var mm TestMeta
var p = DefaultPolicy{}

data, err := json.Marshal(&m)
RequireError(t, false, err)

p.Meta = data

err = p.UnmarshalMeta(&mm)
RequireError(t, false, err)

assert.Equal(t, &m, &mm)
}

func TestGetters(t *testing.T) {
for _, c := range policyCases {
assert.Equal(t, c.ID, c.GetID())
Expand Down

0 comments on commit 76e069e

Please sign in to comment.