How to deal with scoped roles when multiple roles can be activated in XACML - xacml

First the user can have multiple roles at the same time, and the role has scope. For example,
one user has three roles: /scopeA/editor, /scopeA/programmer, /scopeB/editor
and /scopeA/editor has access to resource /scopeA/post
/scopeA/programmer has access to resource /scopeA/bug
/scopeB/editor has access to resource /scopeB/post
so the question comes:
how can i declare a policy saying: if there is a role named "/XX/editor" in the role bag, then the corresponding user has access to "/YY/post", when "XX == YY"
I found a similar question here, and i proposed a way to solve the problem, but when it comes to multiple role(the role attribute value is a bag), my answer is not right. Because the role attribute value is a bag, I cannot just get the part between the first two slashes of the role attribute value, and compare to that of the resource attribute,
then i tried to find a higher-order bag function to do this, the "urn:oasis:names:tc:xacml:3.0:function:any-of" function can do this, but what about the first "function argument" of the any-of function?
here is what i do: the first argument of the any-of function is "string-equal", and the second argument is a function used to get the part between the first two slashes of the resouce-id, the third argument is the attribute value of the subject which is a bag.
so all i need to do is to define a function to get the part between the first two slashes, right?
is there a better way to do what i want? if anything is unclear, plz let me know, thanks~~

This is a great question. We call this issue the attributes of relations challenge. Essentially, a user has a role within a given context or scope as you call it.
If I read a user's role from the db based on the user's identity only, then I would get back the list of roles independently of the scope e.g. editor, publisher, reviewer...
This would lead to the risk I could edit a post outside the scope for which I have the right role.
There are several ways to solve this issue. One way is to define stricter mappings in your policy information point.
Using Policy Information Points
Assume that the XACML request says: "Can Alice edit post 123?". Your policy would state (in ALFA syntax):
policy editPost{
target clause resourceType=="post" and actionId=="edit"
apply firstApplicable
rule allowEditors{
target clause userRole=="editor"
permit
}
}
The notion of scope doesn't directly show up in the policy. The underlying mapping to the source of attributes would be as follows:
map userRole to the field role of the table usersRoleAssignment using SELECT role FROM usersRoleAssignment WHERE uid=? AND scope=?
uid would be mapped to the user identity that came in the XACML request.
scope would be a resource attribute that would also be mapped in the PIP as follows
map scope to the field scope of the table posts using SELECT scope FROM posts WHERE pid=?
pid would be mapped to the identifier of the post in question. That also came in the XACML request.
This means that your attribute userRole should really be called scopedUserRole. The modeling I gave is just one example. There are several other ways you could model with the same effect. Either way, all the heavy lifting happens inside the PIPs. The main drawback is that you lose visibility of the semantics of your authorization logic.
Using attributes values and functions
Another way of achieving a similar result is to store the relationship between scope and role in the value itself. This is what you allude to in your question.
You can use string functions such as string-starts-with or string-ends-with or string-contains to achieve what you're interested in. There is also a string-regexp-match function you can use.
Details on the functions can be found in the XACML 3.0 specification.
If the functions are not sufficient in XACML, you can:
implement your own
implement a PIP that can process your attribute values and produce new ones. More on PIPs here.
Creating a new datatype called tuple
The problem with XACML is that it flattens relationships. Using a new data type with multiple parts, i.e. a Tuple, would solve the issue. That would require custom coding though and quite some work.
Using the XML content inside a XACML request
If all the information comse from the XACML request, then it could be expressed as an XML payload as part of the <Content/> element inside a XACML request. You could then use attribute selectors and XPath to retrieve what you are interested in.
HTH. Do check out both my blog and the Axiomatics blog for more tips.

Related

Retrieving a JNDI dn with its proper case

I want to retrieve a user DN as stored in the LDAP server, keeping the original characters case. For example, let's assume the DN in my server is "cn=Bob, o=MyOrg". I want to query the server using "cn=bob, o=myorg" and retrieve the original "cn=Bob, o=MyOrg", as a result.
The DirContext.getAttributes(dn) method can return a set of attributes but this does not include the DN itself. On the other hand, DirContext.search() returns a SearchResult that has this information using getNameInNamespace(). Unfortunately, search expressions do not seem to allow search on DN, which is what I have.
I understand that I might achieve this by first retrieving a unique attribute using getAttributes(), and then use this attribute value in search(). But this leads to 2 connections. Plus I need to make sure that I have a unique, not null, attribute I can search() on.
Let me reply to my question with the solution I found.
It involves the search() function, where the name parameter (search context) should be the DN, and the query filter is empty or like (objectClass=*). It then returns one row, corresponding to the DN being searched. The original DN is then available in the SearchResult.
Just do a lookup of the DN. The resulting DirContext should have its getNameInNamespace() in the correct case.
A search will also work but it's less efficient and more code.

Retrieving group membership in LDAP

I am using a sample LDAP which is available online here.
I want to retrieve a user's group membership given their uid. In the example, Gauss (uid=gauss) is a member of the Mathematicians group (ou=mathematicians,dc=example,dc=com).
I tried several LDAP queries but I cannot seem to find the one that returns me the ou=mathematicians given the uid.
There are a lot of similar answers on SO but none seem to fit this very simple use case.
Thanks,
David.
You won't be able to retrieve the group membership by simply using the uid as the groupmemberships are stored using the uniqueMember-attribute which requires a complete DN as value. Therefore you'll have to use a searchfilter like uniqueMember=uid=gauss,dc=example,dc=com.
You might think "that's great, so I just add uid=gauss to the baseDN and I'm finished". You might not always have luck with that as it's not defined that users have to be located right in the baseDN. They might be distributed acros the complete LDAP-tree and then it's going to be tough. But when you already have searched for the user (IE for binding) you got the DN back "for free" so you can use that on.
Hope that helps!
Not sure if I get right what you want to do, but retrieving group membership is done by a filter similar to this one:
(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=<<<USER-DN>>>))
I always pull the user dn with a seperate search:
(&(objectCategory=person)(objectClass=user)(samaccountname=<<<USER LOGON NAME>>>))
I don't know if uid, dn and samaccountname can be used in every filter interchangeable, but try it with uid=<<>> instead.
See this article for details : https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx

RESTful API - URI Structure Advice

I have REST API URL structure similar to:
/api/contacts GET Returns an array of contacts
/api/contacts/:id GET Returns the contact with id of :id
/api/contacts POST Adds a new contact and return it with an id added
/api/contacts/:id PUT Updates the contact with id of :id
/api/contacts/:id PATCH Partially updates the contact with id of :id
/api/contacts/:id DELETE Deletes the contact with id of :id
My question is about:
/api/contacts/:id GET
Suppose that in addition to fetching the contact by ID, I also want to fetch it by an unique alias.
What should be URI structure be if I want to be able to fetch contact by either ID or Alias?
If you're alias's are not numeric i would suggest using the same URI structure and figuring out if it's an ID or an alias on your end. Just like Facebook does with username and user_id. facebook.com/user_id or facebook.com/username.
Another approach would be to have the client use GET /contacts with some extra GET parameters as filters to first search for a contact and then looking up the ID from that response.
Last option i think would be to use a structure like GET /contacts/alias/:alias. But this would kinda imply that alias is a subresource of contacts.
The path and query part of IRIs are up to you. The path is for hierarchical data, like api/version/module/collection/item/property, the query is for non-hierarchical data, like ?display-fields="id,name,etc..." or ?search="brown teddy bear"&offset=125&count=25, etc...
What you have to keep in mind, that you are working with resources and not operations. So the IRIs are resource identifiers, like DELETE /something, and not operation identifiers, like POST /something/delete. You don't have to follow any structure by IRIs, so for example you could use simply POST /dashuif328rgfiwa. The server would understand, but it would be much harder to write a router for this kind of IRIs, that's why we use nice IRIs.
What is important that a single IRI always belongs only to a single resource. So you cannot read cat properties with GET /cats/123 and write dog properties with PUT /cats/123. What ppl usually don't understand, that a single resource can have multiple IRIs, so for example /cats/123, /cats/name:kitty, /users/123/cats/kitty, cats/123?fields="id,name", etc... can belong to the same resource. Or if you want to give an IRI to a thing (the living cat, not the document which describes it), then you can use /cats/123#thing or /users/123#kitty, etc... You usually do that in RDF documents.
What should be URI structure be if I want to be able to fetch contact
by either ID or Alias?
It can be /api/contacts/name:{name} for example /api/contacts/name:John, since it is clearly hierarchical. Or you can check if the param contains numeric or string in the /api/contacts/{param}.
You can use the query too, but I don't recommend that. For example the following IRI can have 2 separate meanings: /api/contacts?name="John". You want to list every contact with name John, or you want one exact contact. So you have to make some conventions about this kind of requests in the router of your server side application.
I would consider adding a "search" resource when you are trying to resolve a resource with the alias:
GET /api/contacts/:id
and
GET /api/contacts?alias=:alias
or
GET /api/contacts/search?q=:alias
First of all, the 'ID' in the URL doesn't have to be a numerical ID generated by your database. You could use any piece of data (including the alias) in the URL, as long as its unique. Of course, if you are using numerical ID's everywhere, it is more consistent to do the same in your contacts API. But you could choose to use the aliases instead of numeric IDs (as long as they are always unique).
Another approach would be, as Stromgren suggested, to allow both numeric IDs and aliases in the URL:
/api/contacts/123
/api/contacts/foobar
But this can obviously cause problems if aliases can be numeric, because then you wouldn't have any way to differentiate between an ID and a (numeric) alias.
Last but not least, you can implement a way of filtering the complete collection, as shlomi33 already suggested. I wouldn't introduce a search resource, as that isn't really RESTful, so I'd go for the other solution instead:
/api/contacts?alias=foobar
Which should return all contacts with foobar as alias. Since the alias should be unique, this will return 1 or 0 results.

ndb ComputedProperty filtering

I have a User ndb.Model which has a username StringProperty that allows upper en lower case letters, at some point I wanted to fetch users by username but have the case forced to lowercase for the filtering. Therefor I added a ComputedProperty to User: username_lower which returns the lowercase version of the username as follows:
#ndb.ComputedProperty
def username_lower(self):
return self.username.lower()
then I filter the query like so:
query = query.filter(User.username_lower==username_input.lower())
This works, however it only does for users created (put) after I added this to the model. Users created before don't get filtered by this query. I first thought the ComputedProperty wasn't working for the older users. However, tried this and calling .username_lower on an old user does work.
Finally, I found a solution to this is to fetch all users and just run a .put_multi(all_users)
So seems like a ComputedProperty added later to the model works when you invoke it straight but doesn't filter at first. Does it not get indexed automatically ? or could it be a caching thing.. ?
any insight to why it was behaving like this would be welcome
thanks
this is the expected behaviour. The value of a ComputedProperty (or any property for that matter I guess) is indexed when the object is "put". The datastore does not do automatic schema updates or anything like that. When you update your schema you need to either allow for different schema versions in your code or update your entities individually. In the case of changes to indexing you have no choice but to update your entities. The MapReduce API can be used for updating entities to avoid request limitations and the like.

REST API Parameter precedence

I'm working on creating a REST API. Lets say the resource I'm serving is called object and it contains a number of properties.
Apart from requesting the entire set of objects like this
GET api.example.com/objects
I want to allow requesting a single object by providing either the objectid or objectname,
like this
GET api.example.com/objects?objectid=
GET api.example.com/objects?objectname=
What I'm confused about is, how should I handle a request like this?
GET api.example.com/objects?objectid=x&objectname=y
In this case, should I return a 400 Bad Request, or should one of the parameters take precedence over the other? How does REST define this behavior?
REST generally assumes there is a unique URL for a resource, so it would be:
GET api.example.com/objects/objectId
Parameters are commonly used for searching, so you would have something like:
GET api.example.com/objects?objectName=x
A better approach would be use a generic key in the parameter string to retrieve field values of your specific resource
GET api.example.com/objects/objectId?field=objectName,anotherField
It complements xpapad's suggestion, and can add scalable structure in how you define a consistent approach to your API design.