Casbin: Retrieve all objects for subject with particular action. RBAC use case - casbin

I need to implement custom RBAC support for my product and I stumbled upon casbin/jcasbin that looks promising.
I am checking java API and I do not seem to find a way to fetch all objects of a particular type that a user has access to.
Say, I am implementing an API (not necessarily a REST-based) that is supposed to return a list of all entities the user has read access to.
What jcasbin API call would that be?
I am looking into Enforcer interface and it seems to check whether a user (subject) can do a particular action on the given object.
How do I list all the objects for a user with the given action?
I think RBAC with resource roles is what I want, my model.conf:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
g2 = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && g2(r.obj, p.obj) && r.act == p.act
p, role:viewer, context, read
g, alice, role:viewer
g2, c1, context
g2, c2, context
Here, viewer role grants read permission to the entity type context.
alice is assigned viewer role.
c1 and c2 objects are of type context.
Now, I want to read all contexts for the user alice.
P.S.: I am not sure if SO is the right venue for these types of questions.

Use the new added batchEnforce() API: https://github.com/casbin/jcasbin/issues/187

Related

Google Assistant webhook slot filling customize

I am using Google Assistant integrated webhook with spring boot application.
I have created 3 slots in agent dialogflow, all are required.
a1, a2, a3.
Suppose a2's value depends on a1's value.
If a1 > 100, I want to skip a2 and ask for a3.
So when user speak something that should be populated in a3, instead of a2.
If a1<=100 then ask a2 and then a3.
How to tell the google agent which slot needs to be filled?
You can set parameters programmatically in your fulfillment webhook by setting the needed context's and their parameters. Note that this is not the intended use of slot filling.
Dialogflow by default creates 3 output contexts when filling in parameters
<intentId>_id_dialog_context
<intentname>_dialog_context
<intentname>_dialog_params_<parameterName>
You can find these contexts by using Webhookclient.contexts
Note that the context containing the parameterName will change according to which parameter is being asked for by Dialogflow.
For instance, if you fill in parameter a1, dialog will ask for a2. The context will be <intentname>_dialog_params_a2
All of these contexts contain the parameters needed for the intent.
You can programmatically set these parameters using this approach:
Users fills in a1
In your webhook, determine if a2 should be asked or skipped
if it should be asked, do nothing or send in a different prompt using webhookClient.add(responses)
if it should be skipped:
set both _dialog_context contexts using
webhookClient.setContext(context)
while setting them, send in the parameter a2 as something being not null
remove the context _params_a2
set context _params_a3, with the same parameters
Probably your parameters now look something like:
{a1 : 'someUserValue', a2 : 'someValueByWebhook', a3 : ''}
By doing this Dialogflow already has a value for a2, and won't ask for it again
You have to use webhooks for slot fullfilment and mark all the slots as not required in dialog flow console. After getting request in webhook after user interacted with google assistant you can set output context in response to specifically load other slots.
For example user says I want 100 item where 100 is value of slot a1
Then from webhook you can create a response with fulfilment text Please provide slot a2 and also you need to set output context as a2.
To accept slot value for a2 create a dialogflow intent which has an input context a2 , so that dialogflow is biased while resolving slot a2.
Similarly To accept slot value for a3 create a dialogflow intent which has an input context a3 .
In cases like this (where parameters are optionally required), you can't use slot filling or mark them as required.
The solution is to manage this yourself using contexts and additional intents. So while you might design your Intent to accept answers that include all the parameters, but not mark any of them as required. You then build your webhook to determine if a parameter is necessary and missing and, if so, ask for it. Store the parameters you collect in a context so you have them all available once you have everything you need - you may need to use a different parameter name so they are not overwritten. You may also want to set a context when prompting for a value so you can narrow which Intents make sense when answering the question.

ABAC with keycloak - Using Resource attributes in policy

What I am trying to achieve
Protect a resource in Keycloak with policy like:
if (resource.status == 'draft') $evaluation.grant();
else $evaluation.deny();
Going by their official documents and mailing list responses, it seems attribute based access control is possible, however, I could not find a way of getting it to work.
What I have tried
Using Authorization Services: I was unable to figure out where and how I can inject the attributes from the resource instance.
Using Authorization Context: I was hoping to get the policies associated with a resource and a scope so that I could evaluate them my self.
So far, I have managed to get no where with both approaches. To be honest, I have been overwhelmed by the terminology used in the Authorization services.
Question
How can I use attributes of a resource instance while defining a policy in keycloak?
I solved this problem in Keycloak 4.3 by creating a JavaScript policy because Attribute policies don't exist (yet). Here is an example of the code I got working (note that the attribute values are a list, so you have to compare against the first item in the list):
var permission = $evaluation.getPermission();
var resource = permission.getResource();
var attributes = resource.getAttributes();
if (attributes.status !== null && attributes.status[0] == "draft") {
$evaluation.grant();
} else {
$evaluation.deny();
}
Currently there is no way to do what you are looking to do. ResourceRepresentation class only has (id, name, uri, type, iconUri, owner) fields. So you can use owner to determine ownership per Keycloak example. I've seen a thread that talks about adding additional resource attributes, but haven't seen a Keycloak JIRA for it.
Perhaps you could use Contextual Attributes in some way by setting what you need at runtime and writing a Policy around it.
var context = $evaluation.getContext();
var attributes = context.getAttributes();
var fooValue = attributes.getValue("fooAttribute");
if (fooValue.equals("something"))
{
$evaluation.grant();
}

Claim rules reference previous claims in ADFS?

I'm having trouble getting ADFS to send claim to my app. The authentication is now completing successfully, but none of the claims we've set in rules are being sent with the response. I have two rules in this order.
In the first rule, my understanding is the types section is whatever my application is expecting ADFS to output, and doesn't need to correspond to LDAP values. What is really important is the query which must reference valid LDAP attributes. I am sure the query values are valid LDAP attributes, as another working Relying Party configuration uses these same query values(but they use different values in types for output).
In the second rule, I am referencing Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier". This is not a type in LDAP, but is a reference to the claim created in the first rule. Am I doing that correctly? Can the second rule reference an output type from the first rule?
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory", types =
("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"),
query = ";givenName,sn,mail,employeeI;{0}", param = c.Value);
Second rule
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType,
Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/namequalifier"] = "http://somedomain.com/adfs/services/trust",
Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/spnamequalifier"] = "https://someapp.somedomain.com/sp");
Also, is there any reason ADFS wouldn't send claims if the Relying Party is not setup with a certificate for encryption(it is using the IDP certificate to generate signatures/validate)?
The usual reason claims are not sent is that those AD attributes are null.
You can't use the same claim as input / output.
Take nameidentifier out of the first claim, have a separate claim which outputs something like http://company.com/temp and which is an add not an issue.
Then use http://company.com/temp as input to the second claim with output http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier.

Data Security using Entity Framework

What options/solutions are there for securing data using Entity Framework?
I do not talk about forms login and such here, just assume that the users are authenticated or not.
To illustrate, i attached one of my web api controllers and i wonder if this is the way to do it. The reason why i ask is that i wonder if there are easier ways to do this than writing all this logic to what data to expose in all my controllers.
Also, when looking into a system like breezejs and odata where i can add $expand=TrafficImages to my queries, i would not want users to be able to get my hole database.
So to summarize, what ways are there to securing the data exposed such the users cant download sensible data.
[AllowAnonymous]
public object GetTheoryTests()
{
var identity = ((ClaimsIdentity)((ClaimsPrincipal)HttpContext.Current.User).Identity);
//if (HttpContext.Current.User.Identity.IsAuthenticated)
if (!identity.IsAuthenticated)
return db.TheoryTests.Include(t=>t.TrafficImages).Where(t=>t.PublicAvalible)
.Select(t => new { Id = t.Id, Title = t.Title, Images = t.TrafficImages }).AsEnumerable();
if (User.IsInRole("WebAdmins"))
return db.TheoryTests.AsEnumerable();
var key = identity.GetProvider();
var member = db.Members.Include(m=>m.PayedTheoryTests).SingleOrDefault(m=>m.Identities.Any(
i=>i.identityprovider == key.provider &&
i.nameidentifier == key.id));
if(member!=null)
return db.TheoryTests.Include(t => t.TrafficImages).Where(t => t.PublicAvalible).Select(t => new { Id = t.Id, Title = t.Title, Images = t.TrafficImages }).AsEnumerable();
else
return db.TheoryTests.Include(t => t.TrafficImages).Where(t => t.PublicAvalible)
.Union(member.PayedTheoryTests).Select(t => new { Id = t.Id, Title = t.Title, Images = t.TrafficImages }).AsEnumerable();
}
When thinking about it, what i miss is something like a viewmodel untop of my database depending on the state of the user. Would it be a solution to create two entity frameworks ontop of the same database, one for limited data display and one for more advanced operations?
Meanwhile, until QueryInterceptors arrive, you should take other steps. First, you should look into the techniques for securing a Web API controller or method, a subject beyond the scope of this answer.
Second, w/r/t $expand, you are quite right to be wary of that feature. You may want to inspect which expansions are requested for some controller methods and/or disallow it altogether for others.
Fortunately, this is relatively easy to do. You have access to the request query string. You can detect the presence of "$expand" in that string and analyze it if you want to allow certain expansions and forbid others.
Breeze will add helpers for this in future. You'll have to process the string until then.
You may want to create your own action filter for this purpose if you're up to it.
Great question!. We are currently working on something called QueryInterceptors that will allow you to examine and possibly change or reject the query that was submitted to the server. The "Principal" would be a available context object within each QueryInterceptor method. Please vote for this feature on the "Breeze" website at www.breezejs.com.

Tastypie build_filters access tp request.user

Is there any way to access the user that initiated the request in build_filters override in tastypie.
I want to use the logged in user to give context to one of the filters for example filter contains the word Home and i want to use this as a lookup to the requesting users locations to find their home address.
If build filters took the request as an argument this would be easy as i could simply call
request.user.get_profile().userlocation_set.get(name_iexact=filters['location'])
Is there anyway to force the user into the list of filters or alternatively enrich get parameters before they are passed to build_filters.
There still isn't a great method for this. I'm currently overriding obj_get_list like so, so that I can manually pass the bundle object to build_filters:
def obj_get_list(self, bundle, **kwargs):
filters = {}
if hasattr(bundle.request, 'GET'):
filters = bundle.request.GET.copy()
filters.update(kwargs)
applicable_filters = self.build_filters(filters=filters, bundle=bundle)
try:
objects = self.apply_filters(bundle.request, applicable_filters)
return self.authorized_read_list(objects, bundle)
except ValueError:
raise BadRequest("Invalid resource lookup data provided (mismatched type).")
There is currently an open pull request for this change:
https://github.com/toastdriven/django-tastypie/pull/901
I haven't found a way to do that. I generally 'cheat' by adding the code into apply_authorization_limits where the session is available.