Multipe user roles with one single virtual resource in Puppet - puppet

For managing users on different nodes, I use a similar/customized module in Puppet, as seen here:
puppet_users_with_virtual_resources
In the example, there are two roles. If one roles has been assigned to a user, it cannot assign an additional role to the user (because the virtual resource has already been created).
In my case, I have different roles (like sudo, web-dev, mysql) and every role assign specific groups to the user.
But as already mentioned, I'm only able to assign one single role to the user. If I add another role to the user, the user will still only have one role (because the user with the groups from one role has already been assigned to the user and the resource has been created).
How can I fix this so I can assign unlimited roles to one user?

I usually tackle this by defining virtual users in a centralized place (e.g. profile::users) and storing user/group information in Hiera. Then each place in the code that needs the users can realize them by the corresponding tag. This assumes though that the requisite groups exist on all of the servers that you care about.
Here's a minimal example.
Their data is defined in Hiera:
# common.yaml
---
profile::users::users:
auser:
groups: ['webserver', 'mysql']
tags: ['users::webserver', 'users::mysql']
anotheruser:
groups: ['webserver']
tags: ['users::webserver']
They are declared in a common profile:
class profile::users (
$users,
) {
$users.each |$username, $info| {
#user { $username:
ensure => present,
groups => $info['groups'],
tags => $info['tags'],
}
}
}
They are realized where they are needed:
class role::webserver {
include profile::base
include profile::webserver
User <| tag == 'users::webserver' |>
}
You could also do a lot of that programmatically, e.g. defining tags based on group membership.

Related

NestJS - How to implement RBAC with organization-scoped roles

I am designing a REST backend in Nest.js that needs to allow Users to be a part of multiple Organizations. I want to use role-based access control, such that a user can have one or more named roles. Crucially, these roles need to be able to be either "global" (not dependent on any organization, ex. SUPERUSER), or "scoped" (specific to an organization, ex. MANAGER).
I have decided on this basic database design, which links Users to Organizations using the Roles table in a many-one-many relationship:
As you can see, the organizationId field on a Role is optional, and if it is present, then the user is linked to that organization through the role. If it is not present, I assume this to be a "global" role. I find this to be an elegant database design, but I am having trouble implementing the guard logic for my endpoints.
The guard logic would go something like this:
Look up all the Roles from the database that match the current userId.
For global routes, check that at least one of the returned roles is in the list of required roles for the route.
For scoped routes, do the same, but also check that the organizationId of the role matches the organization ID associated with the operation (I'll elaborate below).
Consider these two endpoints for Jobs. The first will retrieve all the jobs associated with a specified organization. The second will find a single job by its id:
Example route 1:
GET /jobs?organizationId=XXXXX
#Roles(Role.MANAGER, Role.EMPLOYEE)
#UseGuards(JwtAuthGuard, RolesGuard)
#Get()
getMyJobs(#Query() query: {organizationId: string}) {
return this.jobsService.getJobs({
organizationId: query.organizationId,
})
}
Example route 2:
GET /jobs/:jobId
#Roles(Role.MANAGER, Role.EMPLOYEE)
#UseGuards(JwtAuthGuard, RolesGuard)
#Get(':jobId')
getJob(#Param('jobId') jobId: string) {
return this.jobsService.getJob(jobId)
}
In the first example, I know the organizationId without doing any work because it is required as a query parameter. This id can be matched against the id specified in the Role. This is trivial to validate, and ensures that only users who belong to that organization can access the endpoint.
In the second example, the organizationId is not provided. I can easily query it from the database by looking up the Job, but that is work that should be done in the service/business logic. Additionally, guard logic executes before getJob. This is where I am stuck.
The only solution I can come up with is to pass the organizationId in every request, perhaps as a url parameter or HTTP header. Seems like there should be a better option than that. I'm sure this pattern is very common, but I don't know what it is called to do any research. Any help regarding this implementation would be greatly appreciated!
It is just another option for you.
You can modify a user object inside RolesGuard by adding a field that stores available organizations for him/her. So you need to calculate organizations for user, who makes a request inside a guard and then put a result array with ids of organizations to a user field (user.availableOrganizationIds = []). And then use it for filtering results
#Roles(Role.MANAGER, Role.EMPLOYEE)
#UseGuards(JwtAuthGuard, RolesGuard)
#Get()
getMyJobs(#User() user) { // get a user from request
return this.jobsService.getJobs({
organizationIds: user.availableOrganizationIds, // <<- filter by organizations
})
}

Airflow authetication with LDAP based on owner

I am trying to configure my Airflow (version 2.10) LDAP authentication with RBAC.
UI access is restricted by the AD groups (multiple groups for Python Developer, ML Developer, etc.)
Members belonging to a particular group only should be able to view the DAGs created by fellow group members while the other group members shouldn't be.
Able to provide access to users via AD groups but all the users are able to see all the DAGs created. I want to restrict this access based on the defined set of owners, (this can be achieved by switching off the LDAP and creating users directly in Airflow, but I want it with AD groups.)
added fiter_by_owner=True in airflow.cfg file, seems nothing is effected.
Any thoughts on this.
EDIT1:
From FAB,
we can configure roles & then map it to AD groups as below:
FAB_ROLES = {
"ReadOnly_Altered": [
[".*", "can_list"],
[".*", "can_show"],
[".*", "menu_access"],
[".*", "can_get"],
[".*", "can_info"]
]
}
FAB_ROLES_MAPPING = {
1: "ReadOnly_Altered"
}
And to use this, I assume we need to have the endpoints created from the application end similar to can_list, can_show .
In the case of Airflow, I am unable to find the end-points that provides access based on owner (or based on tags). I believe if we have them, I can map it to roles & then to AD groups accordingly.
With newer versions of Airlfow you can map LDAP groups to Airflow Groups.
Owner is an old and currently defunct feature which is deprecated.
You can see some examples about FAB configuration (Flask Application Builder implements all authentication features):
https://flask-appbuilder.readthedocs.io/en/latest/security.html
See the part which starts with:
You can give FlaskAppBuilder roles based on LDAP roles (note, this requires AUTH_LDAP_SEARCH to be set):
From the docs:
# a mapping from LDAP DN to a list of FAB roles
AUTH_ROLES_MAPPING = {
"cn=fab_users,ou=groups,dc=example,dc=com": ["User"],
"cn=fab_admins,ou=groups,dc=example,dc=com": ["Admin"],
}
# the LDAP user attribute which has their role DNs
AUTH_LDAP_GROUP_FIELD = "memberOf"
# if we should replace ALL the user's roles each login, or only on registration
AUTH_ROLES_SYNC_AT_LOGIN = True
# force users to re-auth after 30min of inactivity (to keep roles in sync)
PERMANENT_SESSION_LIFETIME = 1800
See here about roles (including custom roles) https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html

DDD suggest a relation between entities

I have a following structure.
Resources can have multiple endpoints.
Example:
Resource tickets can be accessed on following endpoints:
/api/tickets
/api/agent/tickets
/api/group/5/tickets
/api/tickets/closed etc.
At first, this looks like aggregate, where Resource is AR, and endpoints are child entities.
I also have UserTypes.
What I need is to build a relation between Usertypes and Endpoints, so each UserType can have a diferrent access for endpoints.
Example for, UserType admin could access all endpoints for tickets resource, while user type agent could have access to only portion of endpoints for the same resource.
What would be a suggested way to connect EndPoints and UserTypes in terms of DDD?
Do you need anything else other than a collection of mapping a between Resources and Endpoints on a UserType? This would give you all usertypes their unique resource endpoint access rights
Also seems to be the same question as Solve apparent need for outside reference to entity inside aggregate (DDD)
I would probably create something like the following:
class ResourceEndpoint {
Guid resourceId;
Guid endpointId;
}
class UserType {
List<ResourceEndpoint> ThingsICanAccess;
}

Getting Roles for Group Membership Azure AD

We got a ADAL premium license and we are able to assign more then one role to a user successfully. But we can across this problem where a user 'Rob' is in 2 different groups i.e. (Group A and Group B) and we assigned Group A to 'Spanish Translator' and Group B to 'Chinese Translators'. So what we though was the user 'Rob' will be getting multiple roles assigned to him via group membership.But for some reason we are only getting one role 'Chinese Translators'.
Code Snippet that fetches user's role:
ClaimsIdentity claimsId = ClaimsPrincipal.Current.Identity as ClaimsIdentity;
var appRoles = new List<String>();
foreach (Claim claim in ClaimsPrincipal.Current.FindAll(claimsId.RoleClaimType))
{
appRoles.Add(claim.Value);
}
Just to make sure ,I also verified the user in portal and I did see the user getting assigned with two roles. But for some reason I'm only getting one role when the user signs-in.
Nikhil, thanks for reporting this. We've identified the issue and are working on a fix - I shall update the thread as soon as it rolls out.

Symfony - Understanding super admin

I'm trying to understand something about Symfony and the "super admin".
When I use FOSUser to create a user with super admin privileges
php app/console fos:user:create adminuser --super-admin
I'd firstly like to know what means (from the doc)
[...]Specifying the --super-admin option will flag the user as a super admin[...]
I imagine it means granting ROLE_SUPER_ADMIN to the user because I don't see any super-admin field in the user table.
Secondly, while (still from the doc)
A super admin has access to any part of your application
security:
role_hierarchy:
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH, ...]
Why do we still need to configure the access hierarchy for it ?
Looking at FOSUserBundle's code you will find that the CreateUserCommand if invoked with the --super-admin flag will call the UserManipulator with a boolean argument $superadmin=true.
Now the UserManipulator calls the UserManager who will create a User Object, call it's setSuperAdmin() method and persist the new user afterwards.
The method looks as follows:
public function setSuperAdmin($boolean)
{
if (true === $boolean) {
$this->addRole(static::ROLE_SUPER_ADMIN);
} else {
$this->removeRole(static::ROLE_SUPER_ADMIN);
}
return $this;
}
So answering your first question:
Yes, the --super-admin flag causes FOSUserBundle to create a new user with the ROLE_SUPER_ADMIN role.
You still have to include the role hierarchy in your security configuration because the ROLE_SUPER_ADMIN role basically doesn't differ from any other role.
It's just a convention provided by the Symfony standard edition that users with role ROLE_SUPER_ADMIN should not have any access restrictions.
If you want the ROLE_SUPER_ADMIN to bypass all security voters by default - have a look at JMSSecurityExtraBundle's IddqdVoter which implements this for the special role ROLE_IDDQD. But this has already been suggested in your other question here.
By defining the hierarchy, you explicitly grant it the ROLE_ADMIN and ROLE_ALLOWED_TO_SWITCH roles (or other custom roles you could have)
If you comment this line, and you try to access with your ROLE_SUPER_ADMIN user to an action with a ROLE_ADMIN check, you will get a not allowed error.
The ROLE_SUPER_ADMIN is just a convention for the name the super administrator role should have, but it does not have privileges by it's own, you have to explicitly grant them to it.

Resources