ory / ladon

A SDK for access control policies: authorization for the microservice and IoT age. Inspired by AWS IAM policies. Written for Go.

Home Page:https://www.ory.sh/?utm_source=github&utm_medium=banner&utm_campaign=ladon

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

New custom StringPairsEqual condition rejects valid input

ericalandouglas opened this issue · comments

When using the most recent version of ladon (which includes the new StringPairsEqualCondition) in a fork of Hydra, the warden was incorrectly denying requests when given valid contexts.

A sample policy to be tested against:

{
  "description": "Allow account admins full access to account resources.",
  "subjects": [
    "account-admin"
  ],
  "effect": "allow",
  "resources": [
    "rn:accounts:<[A-z0-9_-]+(:.+)?>"
  ],
  "actions": [
    "create", "read", "update", "delete"
  ],
  "conditions": {
    "account-ids": {
      "type": "StringPairsEqualCondition"
    }
  }
}

A sample context to test against:

{
  "resource": "rn:accounts:1",
  "action": "read",
  "subject": "<SUBJECT_WITH_ABOVE_POLICY>",
  "context": {
    "account-ids": [
      ["1", "1"]
    ]
  }
}

I'm wondering if this can be recreated by others. I believe the following line is failing to coerce properly, https://github.com/ory/ladon/blob/master/condition_string_pairs_equal.go#L11.

I am currently using the following implementation for this condition's Fufills function:

func (c *StringPairsEqualCondition) Fulfills(value interface{}, _ *Request) bool {
  pairs, PairsOk := value.([]interface{})

  if PairsOk {
    for _, v := range pairs {
      pair, PairOk := v.([]interface{})
      if !PairOk || (len(pair) != 2) {
        return false
      }

      a, AOk := pair[0].(string)
      b, BOk := pair[1].(string)

      if !AOk || !BOk || (a != b) {
        return false
      }
    }
    return true
  }

  return false
}

It seems Hydra was able to process the type coercion []interface{} but not [][]interface{}. I originally had a similar implementation to the above function's but I had to rework the type coercing to get tests to pass. Now Hydra seems upset :(

Not sure if this is because Hydra is doing something with the input or if it is ladon specific so I created the issue here.

hm that looks weird, does it work with

pairs, PairsOk := value.([][]string)

?

The only thing hydra is doing is decode the JSON data, that should work with nested arrays

I don't believe the coercion value.([][]string) is working either. That is a little strange since its just JSON decoded.

When using the reflect package, and the reflect.TypeOf function on the input value, the type []interface{} is returned. Is this just the mechanism of the library doing the JSON decoding?

The http payload is decoded here, this and this are the context types. Maybe just add a test that reproduces the case with json and try to fix it that way quickly?

I'll open a new branch with a coercion in the condition that will work with []interface{}. I'll update tests to respect the new implementation.

PR #54 addresses this issue and should respect the []interface{} type.