Finding Enabled Row Level Security Policies and their associated names - database

I'm looking for a way to search for a list of enabled or disabled Row-Level-Security Policies in Postgres, by table name. Whether that be through the information_schema or any other method known to you. This is in the event of forgotten naming or as a person new to the database, who needs to reference the name of the policy.

Okay so i've been angling my question all wrong, as i've been weighting it on "row level security" but i should have instead been emphasising "policy".
The answer to this question is that all Row Level Security information is under pg_policy or for a detailed listing of the Policy and it's Qualifying/Check conditions, then that is pg_policies.
So, the following...
SELECT * FROM pg_policy;
--or to search by table name or find policy details, then:
SELECT * FROM pg_policies WHERE tablename = 'table_name';

Related

Retrieve all available masking policies for an account in snowflake

How to get all the masking policies created in a particular account in snowflake? Is there any view to see it?
show masking policies only retrieves data related to the policies and not where it is applied?
How can I get all policies and in which columns in which tables it is applied?
You can query the information schema table-function POLICY_REFERENCES, see here: https://docs.snowflake.com/en/sql-reference/functions/policy_references.html
Here is also an example from the docs:
use database my_db;
use schema information_schema;
select *
from table(information_schema.policy_references(policy_name => 'ssn_mask'));
Important: You have to execute the USE DATABASE ... and USE SCHEMA INFORMATION_SCHEMA commands or use a full qualified identifier.
If this is not enough, you can query all policies with all tables and all columns when you combine the query above with your SHOW MASKING POLICIES; and the RESULT_SCAN()-function.
RESULT_SCAN() allows you to query the results of SHOW MASKING POLICIES; (https://docs.snowflake.com/en/sql-reference/functions/result_scan.html)
Consequence: You get all names of policies and for each of them you can call POLICY_REFERENCES().

How to deduce group-membership in db2

(The intro is similar to my previous question, this is not a duplicate)
I'm developing a security product for databases in java. One feature in this product is creating security recommendations based on db-privileges and activity.
In order to do that I need to extract privilege data from db2.
Privileges extracted from DB2's catalog tables have the GTYPE column which determine if the grantee is a user or a group.
In the latter case I also need to know which users are members in that group. But group membership is not defined in DB2, but is based on an external entity (OS usually).
In my case I don't have direct access to the OS of the DB i want to monitor, So the question is: Is there any way to deduce the group-user relationship from db2's catalog tables (or anywhere else)
Thanks
Similar to the AUTH_LIST_AUTHORITIES_FOR_AUTHID table function, there is another table function, AUTH_LIST_GROUPS_FOR_AUTHID that can answer the question.
$ db2 "SELECT * FROM TABLE (SYSPROC.AUTH_LIST_GROUPS_FOR_AUTHID('AMY')) AS T"
GROUP
-------------------------...-------------
BUILD
PDXDB2
2 record(s) selected.

SQL Server - Are permissions on tables required?

My question again to be more specific:
How can I modify data through a view and don't have to grant SELECT-Permissions on the table?
I am designing and developing a new database at the company i am working for.
The business rules say, that users are allowed to access specific rows in tables only.
So I use views to check the permissions of the user and return only those records, the user has access to.
So far so god.
But, I have to check the permissions also on INSERT and UPDATE and DELETE with INSTEAD-of-Triggers. Because the rows a User can SELECT may not be those, he can modify.
My problem is:
When I have an view and grant SELECT, INSERT, UPDATE and DELETE Permissions, it doesn't work. When I insert into this view, SQL Server wants INSERT-Permission at the base table. That wouldn't be a problem. But when I update or delete rows through the view, SQL Server wants SELECT and UPDATE/DELETE permissions granted on the base table.
I don't want to give SELECT-rights on the table.
Thanks
Chris
I'm thinking at:
1/ Restrict VIEW rows by adding in its definition a condition like this:
WHERE UserName = SUSER_SNAME()
or
WHERE UserName = CURRENT_USER()
or
2/ Using INSTEAD OF triggers on the involved view.
P.S. Indeed, CREATE VIEW WITH EXECUTE is not allowed. Thank you for your messages.

Normalizing Foreign Keys with Junction & Lookup Tables

I've been scratching my head lately over the relationship between database normalization and foreign keys with respect to junction tables and lookup tables.
I’ve currently have the following tables: Users, UserTypes, Roles, UsersInRoles, and Permissions. UserTypes is simply a lookup table providing the name of the type, with description, via a foreign key in the Users table. Roles are the various roles with associated Permissions linked to each User via the UsersInRoles table.
I need to come up with a structure that allows me to provide multiple Roles for each User, in addition to special permissions for each respective User that may not be covered in the fixed Roles of which they are a member.
I had a foreign key to my UsersInRoles table from the Users table, but decided that it just didn’t make sense. Conversely, it seems to make perfect sense to use a foreign key from the Users table to the UserTypes table. Is this the rule of thumb? That junction tables have foreign keys linking to the primary keys of the tables it joins, while master tables have foreign keys linking to the primary key of associated lookup tables?
Parameters:
Each User can have one or multiple Roles
Each Role has a fixed set of Permissions
Each User can have additional Permissions not provided by their Roles
I suspect I may also need a PermissionsInRoles junction table as well as one for PermissionsInUsers? But this is just ridiculous isn't it? There just must be a better way. I'm thoroughly convinced that I'm losing my mind here, lol. Any help would be greatly appreciated. This has got my head spinning :P
UPDATE
Is this basically how it would be setup? I might get rid of the UsersInRoles table so each user can only be in one role, and additional permissions can be added via the SpecialPermissions junction table. From a UI standpoint, I was thinking it might be good when assigning permissions to a user, selecting a "Role" would simply check the appropriate boxes associated with that role, then you customize that and submit. That way I think I would only need a junction table between the Users and Permissions tables perhaps? Ugh. This is quite daunting for a first time database designer haha. Remember when you were just starting out? Or maybe you guys are more of a genius than I am, lol.
Schema Image link (can't post images yet)
Here's a neat scholarly article (albeit 10 years old) on query-driven database design titled: "Robust Database Design for Diverse Query Patterns". The Conclusion section has an interesting approach.
I suspect I may also need a PermissionsInRoles junction table as well
as one for PermissionsInUsers?
Well, you already said one of the requirements was "Each Role has a fixed set of Permissions". So to fulfill that requirement, you need to store permissions that apply to each role.
Table: role_permissions
PK: (Role, Permission)
Role Permission
--
User Create
User Update
Admin Create
Admin Update
Admin Delete
You don't need two different tables to implement that requirement.
By the same token, you've already said "Each User can have additional Permissions not provided by their Roles". To fulfill that requirement, you have to store user-specific permissions.
Table: user_permissions
PK: (username, permission)
username permission
--
user1 Rename
user1 Leak to News of the World
user2 Randomly corrupt data
So, again, you don't need two different tables to implement that requirement. Both those tables are in 5NF.
But this is just ridiculous isn't it?
What's ridiculous?
That you have very elaborate requirements for permissions?
That you store business data (like permissions) in tables?
That it takes more than one table to model your permission requirements?
Something else?
If you want specific advice about your actual tables, edit your question and insert DDL for your tables.
Later
I looked at your diagram. Not every table needs an id number; id numbers have nothing to do with normalization.
If I were designing your system, I probably wouldn't use id numbers in the tables Roles, Permissions, and UserTypes until I saw a performance problem that id numbers could fix. (In most systems over the last 30 years, that means, well, almost never.) Before I used an id number, I'd also consider and test using a human-readable code instead. Human-readable codes often don't require joins; id numbers always require joins.
In most SQL dbms, you can combine a data type and check constraint in a CREATE DOMAIN statement. In PostgreSQL, you might use something like this to reduce the number of tables.
CREATE DOMAIN role AS VARCHAR(7) NOT NULL
CHECK (VALUE in ('Admin', 'User', 'Guest'));
Followed by
CREATE TABLE user_roles (
user_id integer not null references users (id),
role_name role
);
Replacing a table with a CREATE DOMAIN statement is most useful when the number of rows is stable and relatively small. Personally, I'd rather have the tables.
If you stick with id numbers, you also need UNIQUE constraints on Roles.RoleName, Permissions.Description, and UserTypes.UserType.
Otherwise, you seem to be doing fine.
If your securables are just a products table (or set of tables), and you're using SSMS (SQL-Server Management Studio) then you should not be inventing your own security schema from scratch.
What I would recommend is that you setup your users and roles in SSMS -- expand the Database, then --> Security --> Users, etc. Right-click a user, look for securables, and then you can assign the user to roles, or also, just objects (tables, etc.) directly. Or right-click roles and you have similar options. Whatever you do, stay away from creating your own security schema, if you can help it.
If you need your web app to have access to the database, then look into "utility accounts" (these are like users, created at the server level instead of the database level, but then you can bring them into your database from there.); or look into impersonation if you're able to pass users' creds from your internal network when they login to the database. Utility accounts or users can be assigned to roles, or granted direct access to database objects without roles -- whatever you need.
One thing I've done before, in a similar-sounding scenario:
Keep Roles and users in the same table.
Have an objects table (the tables/queries/forms/etc. you will be granting permissions to)
Have a permission table -- this is where you will link roles/users to objects (i.e., John can SELECT on table 1)
Finally, have an Inheritance table -- this is where you will link roles/users to each other (i.e., John has permission to do whatever Role1 can do)
For example -- a structure like this:
For example:
Users Table:
UserID -- User -- UserTypeID
1 ------- John Smith --- 1
2 ------- Sally Fort --- 1
3 ------- Public Role -- 2
4 ------- Special Role - 2
UserType Table:
UserTypeID -- Description
1 ----------- Human Being
2 ----------- Role
Objects Table:
1 -- Data-Entry Form 1
2 -- Data-Entry Form 2
3 -- Query 1
4 -- Table 1
Permissions Table
UserID -- ObjectID -- Permission
1 -- 1 -- Update (This says John can Update Data-Entry Form 1 (via direct permission))
3 -- 1 -- Update (This says that the Public Role can Update Data-Entry Form 1)
3 -- 2 -- Update (...as well as Data-Entry Form 2)
4 -- 3 -- Select (This says that the special role can Select from Query1)
4 -- 4 -- Insert (...the special role can Insert into Table1)
Permission Inheritance Table
UserID -- UserID_ToInheritFrom
1 -- 3 (this says John can do whatever the Public Role can do)
1 -- 4 (this says John can do whatever the Special Role can do)
2 -- 3 (this says Sally can do whatever the Public Role can do)
So then if you wanted to query, "What can John do?", you'd do something like this:
SELECT
ObjectID,
Permission
FROM
PermissionsTable
WHERE
UserID = 1 -- John has direct permission
OR UserID IN (SELECT UserID_ToInheritFrom FROM PermissionInheritanceTable WHERE UserID = 1)
-- John has indirect permission via the Permission Inheritance Table (or you can call it the "role
-- membership table" if that's easier for you to think of that way.)
This implementation works well. If you want to see a similar implementation, look at SQL-Server's implementation (or better yet, USE it, instead of re-creating the wheel from scratch.)

Database paid users and trial users in same table

If you had to design a database with paid users and trial users would you put them in the same table and differentiate between them with a field? Or would you put them in two separate tables?
Or would you do the best of both worlds and put them in the same table but create two views 1) PaidUsers and 2) TrialUsers
Thanks!
I just express some performance considerations in following opinions.
In single user query(ex. login check, or data retrieving for single user), there are not significant differences between these two strategies.
But if you need some statistic data, for example, one for paid users and another for trial users. And seperating to two tables may be a good idea.
Otherwise, if you need some statistic data whatever paid users or trial users, single table may be a good idea.
What if you need both of scenarios? Well, I think that would be a case which some common attributes exist between two kinds of users.
These common attributes should be put in one table, and dedicated attributes for particular users should be put in 'sub-table' inheriting from former table. Just as vonPetrushev said.
Since your paid users would probably be related to some additional data, but still have the same fieldset as non-paid, the correct way to do this is [is-a] approach:
User
id
username
password
fullname
...
Paiduser
user_id [fk->User::id]
account_id
.... [other addidional data]
EDIT: Now, the trial users will be all records in User that does not have entry in Paiduser. I'm assuming that Paiduser fieldset is a superset of the fieldset of a trial/normal user [User].
EDIT 2: To get a list of trial users, which are 'set difference' between User and Paiduser, the following sql should work:
select u.*
from (User as u
join Paiduser as p on u.id<>p.user_id)
The best solution may depend on database type. My experience is with MySQL and SQL Server. I've always put all users into a single table. Then differentiate as needed using fields. This could apply to paid/ unpaid or anything else. This solution meets 3NF standards and seems easier to me for maintenance etc. What reason would there be to use multiple tables?

Resources