Roles in Cubes (SSAS) - sql-server

My current Cube has two roles:
AdminSec: are for a few users only and refers to a Group of administrators in my Active Directory.
GlobalSec: refers to "Everyone" and gives everyone access to read all data.
We are now planning to incorporate a new department (MinimalDepartment) in our company. This department should not have access to very much of the information in our company, so my plan is to create a third role (DepartmentSec) and assigning a new Active Directory Group (MinimalDepartment) to this role. Also I will limit the access to my dimension data by deselecting all departments and only grant access to the relevant department in the Department dimension.
My question is: If an employee is a member of the Active Directory Group MinimalDepartment will they then only be able to see the data in the cube which the role DepartmentSec allows (which is what I want)? Or will they be able to see all data as they are also part of "everyone" and therefore also the role GlobalSec?
If it is the latter is it then possible somehow to create the role so "everyone" has access except those in AD-group MinimalDepartment?

It seems that I have to create a new group in my AD which contains all the departments which I want to include and then use this instead of "everyone". Fortunately my IT-supports could tell me that we already have this group so for me its not a problem.

Related

Active Directory Group Members don't match member attribute

I'm working with a vendor who needs to use LDAP queries to pull information on our Active Directory. The query pulls from the 'members' attribute of the AD Group directly. However it only pulls 8 of the 20+ users in this group. If I look at the group's Members tab, I can see all of the users, and they work without an issue. I switch to the Attributes tab and scroll to the members entry view the values which shows only 8 of the users. The LDAP query only pulls these 8 and not the rest of the users.
How do I fix this so the attribute and members list match without deleting/recreating the group? If I delete and recreate it would take down our production environment.
I've tried removing and re-adding users to the group and it does not fix the issue.
I'm going to guess that this group is the primary group for the users that you don't see in the member attribute. Members don't appear in the member attribute if the group is the primary group. I don't know why this is... blame Microsoft.
To find those users, look at the primaryGroupToken of the group. It will be a number. Then search for users that have that value in their primaryGroupId attribute.
Usually, the primary group is the built-in Domain Users group, which always has a primaryGroupToken of 513. So to find users of that, you would use this LDAP query:
(primaryGroupId=513)
According to the documentation, the primaryGroupId attribute is indexed, so you don't need any other criteria.
If you want to learn more about how memberships work, I wrote an article a while ago about What makes a member a member?

Roles Metadata Tables in Snowflake

I need to check the roles and grants given to users, but from the metadata tables.
Basically, I need the metadata table, where I can query this, using multiple roles, eg. XXX, YYY,ZZZ. I need this to get the hierarchy of the roles that might have been granted.
I can do show grants OF role XXX - This'll give me all the users/ roles to which this role is granted, but I have to do for one role at a time.
If I do
SELECT *
FROM SNOWFLAKE.ACCOUNT_USAGE.GRANTS_TO_USERS
WHERE ROLE='XXX'
AND DELETED_ON IS null;
It gives me only the users who have been granted this role, not the roles itself.
If I check on GRANTS_TO_ROLES table - it gives me the actual privileges given for that role, but not the other roles to which the particular role is granted to.
What you can do is use the SHOW syntax rather than select:
show roles in account;
will give you the full list of roles (still coming from metadata). Not sure what exactly you want to do with them further, but in case you'd actually want to proceed the results as a query you can follow it by
select * from table(result_scan(last_query_id()));
and use to join with other tables or just to copy into some sort of temporary table and join further from there
You mentioned the hierarchy - I suspect you want to see which roles are granted to other roles..
Try this:
show grants of role Your_Role
In the table returned you will see that some roles are assigned to other roles and to users..i.e. column granted_to

Snowflake warehouse: get all roles (including inherited ones) assigned to a user

I am trying to get all the roles a user is part of. In my case, the user is part of an admin role which inherits another role ingestor, this inherits another role analyst. If I query from snowflake like as follows:
show grants to user <userid>
This lists only the admin role but not other two roles (ingestor, analyst). If the same user logs into snowflake, he could see all three roles available for him in the role dropdown.
Need help to get all explicit roles irrespective of role inheritance.
As a start, the views "SNOWFLAKE"."ACCOUNT_USAGE"."GRANTS_TO_USERS" and "SNOWFLAKE"."ACCOUNT_USAGE"."GRANTS_TO_ROLES" in combination have the information you need,
but are only accessible to ACCOUNTADMIN
You also have:
SELECT * FROM "MY_DATABASE"."INFORMATION_SCHEMA"."ENABLED_ROLES";
SELECT * FROM "MY_DATABASE"."INFORMATION_SCHEMA"."APPLICABLE_ROLES";
The latter looks like a good place to start.
Edit primo 2023:
If you want to make your own near-instant expanded GRANTS_TO_ROLES, you can follow these lines:
Get roles with SHOW ROLES; RESULT_SCAN()
Iterate over roles above with SHOW GRANTS TO ROLE <role>; RESULT_SCAN()
Iterate over ALL_USER_NAMES() with SHOW GRANTS TO USER <user>; RESULT_SCAN()
Finally create a SELECT statement with a recursive Common Table Expression expanding the nested roles
i found the best way to find all roles with inherited roles.
just run below SQL.
SELECT CURRENT_AVAILABLE_ROLES()

How do I model (GitHub-like) permissions relationally?

tl;dr: how do i implement a permissions model like (e.g.) github's
Updated to try to address some of #philipxy's comments:
I am planning to implement a permissions model similar to github's:
users
users can be in groups
users can be in organizations
groups can be in organizations
a user will be permitted any of C, R, U, and D operations on an asset, group, or organization as:
an individual user who has been permitted those (any of C, R, U, D) operations
a member of a group which has been granted those permissions
a member of an organization that has been granted those permissions
or as a member of a group where that group belongs to an org that has permissions
a user is granted Read because the asset/group/org is viewable (readable) to anonymous users ("public")
a user should also have a set of permissions to say whether they can do any of C, R, U, or D on the permissions (a user can create a permission[C,R,U,D] for another user, a group, or an org)
a user can set the permissions for any asset, group, or org they create, or any asset, group, or org for which they have been given permission to set permissions.
These permissions will control who can perform Create, Read, Update, and Delete (CRUD) actions on assets, groups, and organizations in the site.
Approximately how do I model this?
Obviously i have these models:
Asset
User
Group
Organization
What next?
Permission?
PermissionType (to capture C/R/U/D)?
I am using mysql from node (via sequelize), but I can figure out specific syntax an all that myself, I just haven't yet figured out how to do this conceptually.
More to #philipxy's point:
The very thing you are proposing I do more of is indeed the thing I think I'm asking for help with. That is, those info design methods (NIAM, FCO-IM, ORM2, IDEF1X) are what i'm looking for. I know a decent amount about relational db implementation (days of learning normalizing and normal forms and whatnot), but indeed the process of specifying business requirements and converting them into actionable specs is the challenge.
ORM2 is difficult to find because of name collisions with the nodejs module. : I have downloaded the book linked from the NIAM wikipedia page
NIAM seems to be less common in usage nowadays?
FCO-IM: I have downloaded the book from their website
IDEF1X: also looks interesting
I guess I'm going to pick up a database text book.
More work toward predicates:
U identifies a User
A identifies an Asset
G identifies a Group
a User U can be in 0 or more Groups G
O identifies an Organization
a User U can be in 0 or more Organizations O
a Group G can be in 0 or more Organizations O
an asset A can be created by a User U
CRUD on Assets:
an Entity E can be permitted (through Permission P ?) to perform actions Ac on Assets
those Actions are:
Create
Read
Update
Delete
the Entity may be of types:
User
Group
Organization
Anonymous User/"the public"
details (shown only for Read, but also relevant for Create, Update, and Delete):
a User U0 can permit another User U1 to Read an Asset A
a User U0 can permit Users U who are members of Group G to Read an Asset A
a User U0 can permit Users U who are members of Organization O to Read an Asset A
Users U in Group G1, where G1 is a Group that is in an Organization O that has been permitted to Read Asset A, are therefore permitted Read Asset A
a Permission P that references an Asset A may only be created by certain users:
By default, the User U who is the creator of an Entity can create Permissions for that Entity,
but they may only reference Assets to which they have Permission (in the base case: those Assets create by U)
a User who as been Grant(?)ed the privilege can also reference Entity E in a Permission
Gr identifies a Grant
a Grant gives an Entity the privilege to create, read, update, or delete Permissions that reference another Entity
like Permissions, Grants have a transitive nature in that:
if Organization O has been Granted the privilege to (e.g.) modify Permissions for Entity E, then
not only may Users who are members of O modify Permissions referencing E,
but also Users who are members of any Group G where G is in O have the privilege to modify Permissions referencing E
Predicates and tables
A proposition is a statement that is true or false of a business situation. A predicate is a column-parameterized statement that given a row gives a proposition. A table (base or query result) holds the rows that make a true proposition from its predicate.
user (with id) U has name N
R is a grantor (may grant permissions)
user U has permission to update asset A
grantor R gave permission to grantor E to use an operator of type 'CRUD'
grantor E is of type 'user' AND grantor E has permission to update assets
Business rules
A business rule is an always-true statement that defines a term or describes a policy or process.
A user is uniquely identified by an id assigned when their cheque clears.
A crudable is an asset, group or organization.
A grantor is a user, group, organization.
"Grantee" refers to a grantor receiving or holding a permission.
Users can be in organizations.
You can make true statements that are parameterless predicates. These can use parameter names that are bound by FOR ALL & FOR SOME (THERE EXISTS). Business rules phrased in terms of such propositional predicates and/or table names are database constraints. Given User(U,N) & Grantor(R) as shorthands for the first two predicates above as predicates for tables User & Grantor, the following lines all say the same thing:
A user is a grantor.
FOR ALL U, if U is a user then U is a grantor.
FOR ALL U, (FOR SOME N, User(U, N)) IMPLIES Grantor(U).
(SELECT U FROM User) ⊆ (SELECT R AS U FROM Grantor).
FOR ALL U & N, User(U, N) IMPLIES Grantor(U).
FOR ALL U & N, (U, N) IN User IMPLIES (U) IN Grantor.
FOREIGN KEY User (U) REFERENCES Grantor (R); states what the above do (note its similarity to the middle two) plus that R is UNIQUE NOT NULL in Grantor.
Don't confuse rules with predicates. They have different uses & usually different forms. (A parameterless sentence template can be used as either.) A rule is a true statement; a predicate is a parameterized statement. Look at how my answer separates them. Base tables and query result tables have predicates. But a rule may suggest that you need a base predicate/table to record something. We have base predicates/tables when we see from a rule that we have to record some statements about the current situation. Note some rules inspire no base predicates.
You probably want to reify types and permissions.
A user is a grantor of type 'user'.
Permission named 'C' is permission for a grantee to create a crudable.
Grantor E is of type 'user'.
Permission P is of type 'CRUD'.
Grantor R gave permission P of type 'CRUD' on crudable C to grantee E.
Design is finding necessary & sufficient rules & base predicates
Here are relevant predicates to record situations that your exposition suggests arise.
users
U identifies a user
users can be in groups
G identifies a group
user U is in group G
users can be in organizations
O identifies an organization
user U is in organization O
groups can be in organizations
group G is in organization O
a user will be permitted CRUD operations on an asset, group, or organization
A identifies a crudable of type 'asset'
user U is permitted CRUD operations on crudable C
5.1 as an individual user, or as a member of a group, or as a member of an organization (or as a member of a group where that group belongs to an org that has permissions),
P identifies a permission
organization O is permitted CRUD operations on crudable C
or because the asset/group/org is viewable (readable) to anonymous users ("public")
crudable C is public
a user should also have a set of permissions to say whether they can set the above permissions
grantor R has permission to set CRUD permission for users on crudable C --?
What are "the above permissions"? Maybe you mean user CRUD permission and organization CRUD permission? Maybe you mean there are individual permissions for operations Create, Read, etc? You need to be clearer.
What are the permissions in "a set of permissions"? By "permission" here do you instead really mean "particular permission to a particular grantee"? You need to be more clearer.
The way to be clearer is to give rules & predicates that are as simple as possible but also not so simple that they don't mention relevant entities/values. You may afterwards want to generalize multiple rules & predicates into single ones. Eg instead of dealing with users, groups, organizations and assets, have grantors and crudables: Grantors may grant permissions. & grantor R gives permission P to grantee E. If some such permissions are also associated with specific grantees you might also need predicates like grantor R gives permission P to grantee E re permission Q and grantee F.
6.1. a user can set the permissions for any asset, group, or org they create,
user U created crudable C
or any asset, group, or org for which they have been given permission to set permissions.
user U has permission to set permission P for crudable C --?
You will want to record things like that user U has name N and ....
Learn about database design
Search re database/SQL subtyping/inheritance/polymorphism idioms. Eg user, group and organization are types of permission possessors & holders; I made them subtypes of a type grantor. Maybe you want some kind of permission target type that is the union of crudable & grantor. Maybe you want types of permissions. Maybe some permission permissions have associated grantees. Maybe 'C', 'R', 'U' & 'D' are permissions, and 'CRUD' is a type of permission. You probably want to record what grantor gave what permission to a grantee.
Later we can replace tables by their join if the join is on a shared PK/UNIQUE with the same set of values in both. When we can join on a PK/UNIQUE & FK we can replace tables by one like their join but with the FK nullable. There are yet other times we can replace multiple tables by one without problems. But first identify basic predicates.
Learn about relational database design. Follow some information design method. Best are members of the the NIAM/FCO-IM/ORM2 family. Peek at IDEF1X. Don't rely on products.
Learn about constraints. They follow from predicates and business rules. They are truths about possible business situations in terms of the predicates. Equivalently, they are truths about possible database states in terms of the tables. Also learn about constraints in SQL, both declarative (PK, UNIQUE, FK) & triggered.
It seems to me that you need to create the concept of an entity which can receive permissions on a repository or an organization.
In this model the problem becomes relatively simple, as the permissions would revolve around an RepositoryPermissions table of the form:
(EntityId, RepositoryId, canCreate, canRead, canUpdate, canDelete)
and a OrganizationPermissions table of the form:
(EntityId, OrganizationId, canCreate, canRead, canUpdate, canDelete)
There are two types of Entities Groups and Users, and the permissions of any user will need to be checked in four ways:
Direct User permissions on the Repository level
User membership in a Group with permissions on the Repository level
Direct User permissions on the Organization level
User membership in a Group with permissions on the Organization level.
the following query should retrieve all permission entries pertaining to the user someUserId on repository someRepoId
SELECT
rp.canCreate,
rp.canRead,
rp.canWrite,
rp.canDelete
FROM RepositoryPermissions AS rp
Left JOIN Users AS u ON u.EntityId = rp.EntityId
Left JOIN Groups AS g ON g.EntityId = rp.EntityId
Left JOIN GroupUsers AS gu ON gu.GroupId = g.GroupId
WHERE rp.repositoryId IS "someRepoId" AND (
u.UserId IS "someUserId" OR
gu.UserId IS "someUserId"
)
UNION
SELECT
op.canCreate,
op.canRead,
op.canWrite,
op.canDelete
FROM Repositories AS r
JOIN OrganizationPermissions AS op ON r.repositoryId = op.repositoryId
Left JOIN Users AS u ON u.EntityId = op.EntityId
Left JOIN Groups AS g ON g.EntityId = op.EntityId
Left JOIN GroupUsers AS gu ON gu.GroupId = g.GroupId
WHERE r.repositoryId IS "someRepoId" AND (
u.UserId IS "someUserId" OR
gu.UserID IS "someUserID"
)
Well it is problematic when you try to make a database behave the same way as something like Github. Databases have a completely different paradigm. It is why is is just as bad to design databases based on how C# works. Not the same functionality or rules. However it is an interesting question because too few people pay attention to the permission model as part of their database design and just grant everybody rights to everything because it is easier.
In the first place, users should not be able to grant rights to others, only admins should do that. Users should NEVER be creating objects if you have a good database design. Database design has no business being handled by amateurs.
Users can be individuals or you can use application users where all database requests coming from a specific application have the same rights. Applications can even have multiple generic users such as XYZAdmin, XYZUser, XYZReadonly (often used for senior managers who need to be able to see the data but aren't going to adjust it.). From my experience the biggest problems with the generic users is that it becomes difficult to audit who changed what in the database (very important in a regulated environment) and some users may have more permissions than they really need.
In databases you have several basic types of permissions. You have permissions that extend to the whole database and object level permissions. You also have some specific server permissions such as the permissions to use Bulk insert or execute jobs. Groups should also be given permissions concerning which databases they can see on the server as most database servers have multiple databases. So you can grant a user permissions to write to any table or grant them no rights to tables but only to specific stored procedures or views. In general administrative personnel get the overall rights to everything (or server level rights such a Bulk insert rights). This includes DBAs who have full rights and other specialists such as data analysts/senior developers/build team members who may only have rights concerning jobs and data entry or creating new objects but not rights to perform tasks such as setting permissions. All other users should be locked in to object level permissions.
Now no one should be given permissions as an individual (or at least it should be a rare thing). Each person should be in various groups which have rights. Individuals can be in more that one group and how those right interact between groups can be explained in the documentation associated with the specific database product you are using (yes this is specific by product, there is no one size fits all database permissions model.) The beauty of this is that when someone is no longer a user, you only have to remove them from the group(s) and the permissions are gone rather than searching out a multitude of individual permissions.
Now when you are handling permissions by groups, you need to define the groups. You may also need to define some additional views or stored procedures if you want a group to only have permissions on a subset of the records or columns instead of the whole table. If you have multiple clients in one database and need to make sure the permissions are only for one specific client, then you need to use stored procedures/views and grant permissions only at the stored procedure/view level not at the table level. Using views for permissions can get tricky because each database product has specific rules about what makes a view updateable. You need to understand this at a deep level to determine how you are going to manage permissions.
All database objects created will need to script the specific groups being granted permission to that object as part of the creation script. (You would never create database objects through any kind of GUI, always through scripts kept in source control.)
You can also do some permissions work by client by setting up some database tables with meta data about specific pages the user can access or specific clients that he is allowed to access. Then when the application is loaded, the users data from these tables is loaded and the application would decide what he or she could do. This is frankly easier but can be risky.
It means the users have to have table level permission and users really should not have those. Because the database level permissions are broader, it is easier for a malicious user to log in outside of the application and do things that he or she should not be able to do. This is something to be especially wary of if you have internal users who can easily log in through something other than the user's application such as SSMS for SQL Server.
If your database application is in a legally regulated field such as finance or health care, you need to be very strict about permissions and using ORMs instead of stored procedures is contraindicated because at no time should you be setting permissions at the table level.

Why builtin security groups not in the attribute memberOf?

If I query the AD then for some users the attribute memberOf does not contains any builtin groups. The users with the problem are all moved in a separate OU.
The query is simple:
(&(objectClass=person)(uid=xyz))
But the "Active Directory Users and Computers" tool from Microsoft show this members. Where can be the problem? Is this an access right problem?
There is a notion of a Primary group in AD. The default is usually Domain Users.
This is represented on the user object as an attribute called PrimaryGroupID, and 513 is Domain Users.
There can and must be only one primary group, and to remove the current one, you need to first add another group as a member, to then swap with the primary group ID.

Resources