resource id in xacml for a REST API - api

If I have an API
https://api.example.org/api/v1/resources
and there is access to a resource with id
https://api.example.org/api/v1/resources/:id
How can I write a XACML policy where the resource is an URL with a resource id (the second URL from above)?
How can I put a placeholder/variable there so that I can write a rule for it?

Are you saying that you need to write separate policies for various possible id? E.g.
P1 that handles access to resource https://api.example.org/api/v1/resources/:1 and
P2 that handles access to resource https://api.example.org/api/v1/resources/:2 etc.
If so, the idea would be to use an attribute id, say the resource-id attribute, to capture the value of the id in the URL at the PEP side and pass it to the PDP and to write policies where the target is specified as string-equals(resource-id,1) for P1 and string-equals(resource-id,2) for P2 etc.
(edit)
Based on the clarification, provided, you can do it as follows:
The reasoning in such a case will be similar. You write a Policy that handles all rules for resources and specify its target as string-equals(resource-type,"resources") and in that policy specify rules for each resource-id. At the rule level the target would be string-equals(resource-id,"1"), string-equals(resource-id,"2") etc.

Related

Specifying multiple Domain Bases in Rocket.Chat LDAP

On Rocket.Chat's LDAP configuration page, the helper text for Domain Base states that you should enter (emphasis mine):
The fully qualified Distinguished Name (DN) of an LDAP subtree you want to search for users and groups. You can add as many as you like; however, each group must be defined in the same domain base as the users that belong to it. If you specify restricted user groups, only users that belong to those groups will be in scope. We recommend that you specify the top level of your LDAP directory tree as your domain base and use search filter to control access.
Problem is, I don't know how to enter more than one.
My DN looks like this:
OU=IT,OU=Staff,DC=companyname,DC=local
And I want the following users to also be synced:
OU=Example,OU=Staff,DC=companyname,DC=local
But I don't know how to add them both, as the docs aren't clear, and the source code is even less clear.
I've tried the following ways:
Space separated
Semicolon separated
Ampersand (and double ampersand) separated
Wrapping them up in an array (e.g. ["OU=Example ...", "OU=IT ..."]) and as a JSON object
Pipe (and double pipe) separated
'Plus' separated (e.g. DC=local + OU=Example)
But no matter what I do, it won't sync users. The logs tell me:
Exception while invoking method 'ldap_sync_users' NoSuchObjectError: 0000208D: NameErr: DSID-03100238, problem 2001 (NO_OBJECT), data 0, best match of: at Object.Future.wait (/snap/rocketchat-server/511/node_modules/fibers/future.js:449:15) ...
I know I can set up a group restriction so only users in a certain group will be synced, but the helper text says I can use multiple DNs, and I want to know how to use multiple DNs
After reading RFC-4514, I discovered I should construct my DN like so:
OU=Example+OU=IT,OU=Staff,DC=companyname,DC=local
With the plus occurring between the two OUs I wish to add. Now my users are syncing correctly.

Hierarchical attributes in XACML Policy

We are using WSO2 Identity Server 5.1.0 .
We have a location hierarchy like Plant1->Area1->unit1. Now if a user is having attribute for the Plant1, he should get access to unit1 as well (all children of the parent in a tree).
Can we specify this in XACML? We have the hierarchy stored in DB. We can provide the list of hierarchical elements as a list of attributes also if so required.
Problem explained in sample :
A user bob has been given access to area2 as shown below :
Plant1
|--Area1
|--Unit1
|--Area2
|--Unit2
We want to specify the Area2 location in XACML policy. Now if the request with area2 or unit2 comes that should be permitted while if the request with plant1, area1 or unit1 comes that should get denied.
I need the structure for XACML policy.
You can implement this with a custom PIP (Policy Information Point, aka Attribute Provider) in XACML implementations like AuthzForce. I don't know WSO2 IS as much but according to the doc, it is also extensible with custom PIPs, so I assume this should do the trick.
The idea is that in the XACML Policy, you use an AttributeDesignator with a custom AttributeId to indicate that the top parent value in the hierarchy of some attribute is requested, e.g. AttributeId = resource-id-parent for the parent value of resource-id attribute value.
What your custom PIP does: when this custom attribute id resource-id-parent is requested, the PIP gets the value of the attribute resource-id from the request, i.e. "area2" or "unit2", then gets the corresponding top value in the hierarchy from your DB (or all the values above if you will) and return it as bag. Then, in the XACML Policy, you can use string-equal in a Match or string-at-least-one-member-of in a Condition to match the AttributeDesignator with "area2" (remember an AttributeDesignator always evaluate to a bag).

JMeter: Passing Key Value Pairs Not Working

I'm using JMeters to automate API testing to/from our database using basic CRUD methodology. After the record creation, I'm trying to perform 3 different types of Reads (think CRRRUD). :)
Read 1 - Retrieve by ID
HTTP (GET) the base URL is appended with the saved record ID.
http..../crud/tableName/${newRecordId}
This returns
Read 2 - Retrieve by field type with no defined value
HTTP (POST) the base URL is extended with a "search" as the end. A Key is defined ("name") with no value.
http..../crud/tableName/search
Parameter Name = name
Value = {undefined}
This returns all records within the table whose field ("name") is not null.
Read 3 - Retrieve by field type with a defined value
HTTP (POST) the base URL is extended with a "search" as the end. A Key is defined ("name") with the value generated during the creation request.
http..../crud/tableName/search
Parameter Name = name
Value = Metropolis
This, too, returns ALL of the records within the table instead of just the record(s) whose name = Metropolis.
This 3rd Retrieve works properly when using a REST client, (e.g., Postman, Advanced REST Client, etc.) when defining the Key|Value pair as "name|Metropolis". So it must be something within JMeter that I'm missing.
Any insight is appreciated!
There is only one correct answer: compare what's being sent by REST Client and JMeter using sniffer tool (i.e. Wireshark), detect the differences and configure JMeter accordingly.
Just a guess: given you mentioned "API" an "REST" words maybe you need to pass it as JSON like:
{"name":"Metropolis"}
as a single parameter value
or in formatted way (in case if server checks Content-Length and/or wants the request to be properly formatted)
You may also need to add HTTP Header Manager in order to send Content-Type header with the value of application/json. See Testing SOAP/REST Web Services Using JMeter guide for more details.

Can i use xpath-like expression in the attributevalue in a xacml plicy

I'd like to declare some policies likes:
some one can visit anything under the img path, but img folders are scattered everwhere, so the attributevalue in the xacml policy may seem like this: "/rootpath/**XPATH_PART**/img/*".
how to write policy of this kind.
I looked through the "XACML3.0 core spec", "Multiple Profile", they says
Each Individual Decision Request SHALL be identical to the original request context with two exceptions: the “multiple:content-selector” attribute SHALL NOT be present and an added “content-selector” attribute value SHALL be an XPath expression that evaluates to a single node in the <Content> element
I think this means that in the policy file, i cann't use XPath in the AttributeValue to refer to multiple resources like i said in the first place, right? because the request is resolved to individual request each asking for a resource with a specified attribute id.
Is there something in the specification i missed out or misunderstood? or can anyone suggest a better way to do what i want?
Now i'm wondering if using regular expression in the resource can do that. The corresponding function is
urn:oasis:names:tc:xacml:1.0:function:string-regexp-match.
P.S.: I'm trying to setup a authorization server for my company, XACML seems a good place to start with. But nobody around me knows about it. I would be appreciated if any one can give me any suggestion about setting up the access control system.
I chatted with some of my colleagues at Axiomatics and the conclusion is that you do not need XPath but rather regular expressions. XACML provides a regular expression function that works on URI data types. It is called anyURIRegexpMatch and it takes in a string (the regular expression) and the XACML attribute to which to apply the regular expression. It returns either true or false.
Your rule target would look as follows in ALFA (Axiomatics Language for Authorization):
policy matchResources{
apply firstApplicable
rule allow{
target clause anyURIRegexpMatch("^https?://(?:[a-z\\-]+\\.)+[a-z]{2,6}(?:/[^/#?]+)+\\.(?:jpg|gif|png)$", resourceId)
permit
}
}
See also this other example (XACML 2.0): How do I apply XACML rules to every child URI?

How about using URI path variables for an HTTP POST?

I've searched a lot but I couldn't find the proper answer to my question regarding my conditions.
I'm building a REST API, and the case, which seems a border line case to me, is the following:
-I'm dealing with two entities, Users and Roles. An User can have multiple roles assigned.
-To assign a Role to a User, the Role must be already in the DataBase.
-To assign a Role to a User, the only thing needed is the 'code' of the role, that is a short string.
-The uri path template used now is:
--Users: localhost:8080/api/users
--Given User: localhost:8080/api/users/{userId}
--Roles of a given User: localhost:8080/api/users/{userId}/roles
Now, to 'link' a given User with a given Role, two options come to my mind.
-The first is the one that sounds as best practice in any scenario, sending the post data in the body, perhaps as a JSON.
-The other one, sending it through the uri and with an empty body. For example, to link User with id U001 with role R001, one would have to post to the following uri sending no data in the body: localhost:8080/api/users/U001/roles/R001
The thing is that I don't mind using the first option, and it seems to be the best and most correct one, but in this particular case, I'm not sure wether it is better to send an almost empty body (because it only holds the role id, a very short string) posting it to 'localhost:8080/api/users/U001/roles' or skipping the body and just sending the role id through the uri as a path parameter like localhost:8080/api/users/U001/roles/R001
Thank you all in advance for your help.
There is nothing wrong with putting role in the URI. Your intuition was on the right track. I'd do it this way.
PUT: locahost:8080/api/users/{userid}/role/{roleId}
And here's why.
FIRST: The PUT verb is Idempotent. In other words (taken straight from the spec)
... the side-effects of N > 0 identical requests is the same as for a single request.
Which is what I'd assume you want in this regard. You don't want multiple records in your state storage for each instance of user & role. A user should feel at ease making the same PUT request without adversely effecting (adding duplicate records) the system.
When doing the same thing with a POST I'd expect to have a new record created for every request.
SECOND: The PUT verb is supposed to identify a specific resource. (taken straight from the spec)
... PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires that the request be applied to a different URI,
it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.
What if role R102 becomes obsolete and R104 is preferred? Return a 301 (Moved Permanently) with a HEADER (Location : localhost:8080/api/users/{userid}/role/R104).
FINALLY: When everything works well. Return a 201 (Created) when created and a 200 (No Content) on every subsequent request to the same URI. If they provide a Role that is not in the system return a 501 (Not Implemented).
Hmm - in this case - a POST with a 302 may be a bit messy.
Why not a very simple 'PUT'/'DELETE' with indeed the URIs suggested ?
With simple; 20X meaning succeeded, possibly some 30X to indicate it was already there - and anything else a fail ?