From the docs I read that it's possible to define attribute-level permissions (as well as resource and instance levels)
Attribute Level - The permission now specifies an attribute of an instance or resource. A user can edit the address on the IBM customer record.
How can these permissions be defined declaratively using the <resource>:<action>:<instance> format in which permissions in Shiro are usually defined? It would seem logical to be if it's possible to do something like <resource>:<action>:<instance>:<attributename> but I can't find docs anywhere discussing this.
Did you check http://shiro.apache.org/permissions.html?
You can create the strings yourself from your own information. In our code we use custom realms to add the permissions programmatically like so:
public class OurAuthorizingReam extends AuthorizingRealm {
...
#Override
public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
... code to find permission infp
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
while (.. looping through permission info){
info.addStringPermission(... the permission string constructed);
}
return info;
}
Related
i am trying to give default role as Internal/Subscriber to all users.
i made changes in we made changes in file /_system/config/apimgt/applicationdata/tenant-conf.json and added role such as to Internal/creator,Internal/everyone,apimrole
"Name": "apim:subscribe",
"Roles": "admin,Internal/creator,Internal/everyone,apimrole,Internal/subscriber"
it gives me below error
org.wso2.carbon.apimgt.api.APIManagementException: Error while adding the subscriber
laxman#gmail.com#carbon.super#carbon.super
any help appreciated
New user creation takes place in the WSO2 API Manager in two ways.
Through the management console of the API Manager
Self signup
In 1st way you can assign roles when creating users.
For self signed-up users there already exists a handler to assign Internal/subscriber role to the new users who are having Internal/selfsignup role.
To assign role: Internal/subscriber to new users or existing role not assigned users we have below two options:
Option 1
If you wish to assign subscriber role to existing role not assigned users using Management Console, then you can go to roles listing page there:
There is an option: Assign Users in Actions column in role list relevant to Internal/subscriber role.
It will list all the users who have not assigned Internal/subscriber role and there are several options to select many users at once and assign the role.
Option 2
You can write a custom user operation event listener and add it as OSGI bundle.
In this case you can refer this WSO2 IS doc and write a event listener extending AbstractIdentityUserOperationEventListener.
This sample code worked for me:
public class SampleEventListener extends AbstractIdentityUserOperationEventListener {
private static final String EVENT_LISTENER_TYPE = "org.wso2.carbon.user.core.listener.UserOperationEventListener";
private static final String SUBSCRIBER_ROLE = "Internal/subscriber";
#Override
public boolean doPreAddUser(String userName, Object credential, String[] roleList, Map<String, String> claims,
String profile, UserStoreManager userStoreManager) throws UserStoreException {
List<String> roles = new ArrayList<>(Arrays.asList(roleList));
if (!roles.isEmpty() && !roles.contains(SUBSCRIBER_ROLE)) {
userStoreManager.updateRoleListOfUser(userName, new String[]{}, new String[] { SUBSCRIBER_ROLE });
}
return true;
}
This will add Internal/subscriber role to each newly adding user, if the user doesn't have that role in the process of adding new user.
Here it has mentioned multiple interfaces with which you can implement User Store Listeners.
For OSGI bundle creation and deployment process you can find this sample GitHub project. You can copy the built jar file to the directory <APIM_HOME>/repository/components/dropins/ by following the steps have been mentioned there. (Since WSO2 API Manager is also using WSO2 IS components you can follow the same steps mentioned in README with the API Manger as well)
You can go through this blog post to get complete idea about OSGI bundling.
I want to understand the use case/usage of "User Group Source Plugins - Java Plugin Type"
1) can I use the plugin's returned roles/groups in authorization policies(/etc/rundeck/myadmin.aclpolicy)
2) what is the property and its value of this plugin, I should mention here?
framework.plugin.UserGroupSource.[your_plugin_name].[property]=value
In below case, framework.plugin.UserGroupSource.example-user-group-source-plugin.[property]=value
3) Can I connect to a RDBMS and get the roles from DB using java class constuctor
package example;
#Plugin(name = "example-user-group-source-plugin",service= ServiceNameConstants.UserGroupSource)
public class ExampleUserGroupSourcePlugin implements UserGroupSourcePlugin {
List<String> groups = new ArrayList<>();
public ExampleUserGroupSourcePlugin() {
groups.add("RUNDECK_USER"); //This group would get added to all users
//TODO: DBConnect code to get roles from RDBMS
}
#Override
public List<String> getGroups(final String username, final Map<String, Object> config) {
//some code
return groups;
}
}```
Yes, the ACL definition can take the roles defined in your plugin. In the same way which LDAP roles for example.
What you define in your code as you see here (maybe the documentation needs some update to specify that).
Theoretically yes, using the right way to connect to DB like this.
The JAVA EE #DeclareRoles annotation is a way to declare the list of possible roles of the users to match with the annotation #RolesAllowed.
But what if our roles are stored in database and if the list of the potential roles is long ?
I currently use roles to specify an atomic access to functionnalities on my website, so I have a long list of roles as some users can access functionnality-1 but not the 2, and some can on the 2 but not on the 1, etc...
I want to avoid editing the #DeclareRoles annotation every time I am creating a new role for a new functionnality, so the question is :
Is there any way to programmatically setup the #DeclareRoles annotation or to specify that it should load from a database ?
Since the introduction of the JavaEE 8 security API you have the ability to write your own identity store. This allows you to fetch users and user data from a custom location and a custom service. You asked about using a database - so here is an example using a database facade together with a custom identity store;
#ApplicationScoped
public class MyIdentityStore implements IdentityStore {
#EJB private UserFacade userFacade;
#Override
public int priority() {
return 50;
}
#Override
public Set<ValidationType> validationTypes() {
return EnumSet.of(ValidationType.PROVIDE_GROUPS, ValidationType.VALIDATE);
}
#Override
public Set<String> getCallerGroups(CredentialValidationResult validationResult) {
final String userName = validationResult.getCallerPrincipal().getName();
final User user= usersFacade.find(userName);
return user.getRoles();
}
public CredentialValidationResult validate(UsernamePasswordCredential credential) {
/* Handle validation/login of the user here */
}
}
To explain the above slightly more - the getCallerGroups() will return the roles that the user is part of - something you can then use throughout the JavaEE security API and lockdown methods such as #RolesAllowed. The validate() method handles the validation of the user when a check is requested by the container. Finally, the validationTypes() method simply specifies what this Identity store should be used for - in this case we have specified both the fetching of roles and handling of validation.
So since EE8 introduced this - it has become really flexible and easy to take advantage of the security features in the platform.
Here are some really great references on the subject;
https://www.ibm.com/developerworks/library/j-javaee8-security-api-1
https://www.ibm.com/developerworks/library/j-javaee8-security-api-2
https://www.ibm.com/developerworks/library/j-javaee8-security-api-3
https://www.baeldung.com/java-ee-8-security
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();
}
Given the following Controller
namespace MyNamespace.Api.Controllers
{
[Authorize]
public class AccountController : ODataController
{
private Entities db = new Entities();
// GET odata/Account
[Queryable]
[ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Read", Resource = "Account")]
public IQueryable<Account> GetAccount()
{
return db.Accounts();
}
...
}
}
I override the ClaimsAuthorizationManager.CheckAccess(...)
public class AuthorizationManager : ClaimsAuthorizationManager
{
public override bool CheckAccess(AuthorizationContext context)
{
var resource = context.Resource.First().Value;
var action = context.Action.First().Value;
return Policies.Validate(resource, action);
}
}
This is useful only to the point where I can check whether or not the Current Principal in general can Read Account. However, if I'd want to check which accounts a certain user is allowed to Read, I am lost.
Let's say I have a Manager user who should be able to read all Accounts for which he is a manager for whereas a non-manager user should be able to read only their own account.
Is there a best practice for this or have you done something like this previously and give me a few hints to look for?
I do not use ClaimsPrincipalPermissionAttribute because I cannot pass any dynamic parameters to it like requested Account from your sample.
Have a look at the book "Pro APS.NET Web API Security" page 97. They suggest to invoke AuthorizationManager from your controller action implementation by code new IdentityConfiguration().ClaimsAuthorizationManager.CheckAccess(context), where context is constructed manually so you can pass Account requested (for example) as Resource to check it in your AuthorizationManager implementation.
Also have a look at pluralsight training "Introduction to Identity and Access Control in .NET 4.5". There are also some info about how to implement claim-based security in Web API.
Now I am in progress of implementing the security you are talking about and I am interesting in the subject too.
My case is: role Administrator is assigned by Country, every Administrator can see entities only related to the countries they have access to.
UPDATE: After several projects I forgot about Claims-based security as this is extremely difficult way to make security checks. Today I use decorator pattern where all the security checks are done. It appears to be very easy to implement security even in OData Controllers like this:
public IQueriable MyQuriableEntitySet
{
get{ return implementationWithoutSecurity.MyQuriableEntitySet.Where(e=>e.Country.Code = currentUser.AssignedTo.CountryCode || currentUser.IsSuperAdmin); }
}