I created two Groups (Confirmed using SELECT groname FROM pg_group)
Test_Group_A
Test_Group_AB
Created two External Schemas (Confirmed using SELECT schemaname FROM svv_external_schemas)
External_Schema_A
External_Schema_B
Granted permissions to these groups on external schemas, as follows:
GRANT USAGE ON SCHEMA External_Schema_A TO GROUP Test_Group_A;
GRANT USAGE ON SCHEMA External_Schema_A TO GROUP Test_Group_AB;
GRANT USAGE ON SCHEMA External_Schema_B TO GROUP Test_Group_AB;
Using metadata, how do I get the list of
Schemas that Test_Group_X and Test_Group_XY can access
OR
Groups that have access to External_Schema_X and External_Schema_Y
Thanks!
The easiest way I would think would be to operate as a member of these groups and test the permissions. The easiest way to "become" another user (while connected as a superuser) is "set session authorization 'user_name';". This will give you the rights and authorization of this user. When done you can "reset session authorization;".
SELECT
*
FROM
(
SELECT
pg_get_userbyid(b.nspowner)::text AS objowner,
b.nspname::text AS objname,
TRIM(SPLIT_PART(array_to_string(b.nspacl, ','), ',', NS.n))::text AS access_control_list_string
FROM
(
SELECT
oid,
generate_series(1, array_upper(nspacl, 1)) AS n
FROM
pg_catalog.pg_namespace
)
ns
INNER JOIN
pg_catalog.pg_namespace B
ON b.oid = ns.oid
AND ns.n <= array_upper(b.nspacl, 1)
)
WHERE
objname = '<external_schema_name>'
Related
Question:
"For each user, show me the groups they belong (1) to and the tables they can query as a result of being part of that group (2)."
Details: This is on redshift.
I'm curious if anyone has done anything like this.
The first part isn't hard, I did that with this:
SELECT usename, groname
FROM pg_user,
pg_group
WHERE pg_user.usesysid = ANY (pg_group.grolist)
AND pg_group.groname in (SELECT DISTINCT pg_group.groname from pg_group)
The second part is much harder I think. Showing table permissions isn't, but that's not really what's being asked. That can be accomplished with this:
SELECT has_table_privilege(user, table, 'select'::text) as select...
But that does not show which group gives the user that permission.
Any advice is great!
I have a dataset similar to the following dataset:
WITH CTE AS (
SELECT ';000d6a11,Adult' AS Policy
UNION ALL
SELECT ';0003ga21,Child' AS Policy
UNION ALL
SELECT ';000d6a11,Adult;;0003ga21,Child' AS Policy
Policy
;000d6a11,Adult
;0003ga21,Child
;000d6a11,Adult;;0003ga21,Child
I want to return the following:
Policy
PolicyNo
;000d6a11,Adult
000d6a11
;0003ga21,Child
0003ga21
;000d6a11,Adult;;0003ga21,Child
000d6a11,0003ga21
I have tried using REGEXP_EXTRACT_ALL() however this returns the PolicyNo on multiple rows and does not remove the ; before the second instance of the PolicyNo:
Policy
PolicyNo
;000d6a11,Adult
000d6a11
;0003ga21,Child
0003ga21
;000d6a11,Adult;;0003ga21,Child
000d6a11
;0003ga21
The query I have used is:
WITH CTE AS (
SELECT ';000d6a11,Adult' AS Policy
UNION ALL
SELECT ';0003ga21,Child' AS Policy
UNION ALL
SELECT ';000d6a11,Adult;;0003ga21,Child' AS Policy
) SELECT Policy
,REGEXP_EXTRACT_ALL(Policy, ';(.+?),')
FROM CTE
How can I achieve the desired result?
You can use
ARRAY_TO_STRING(REGEXP_EXTRACT_ALL(Policy, ';([^;,]+),'), ',')
where
;([^;,]+), captures into Group 1 any one or more chars other than ; and , (excluding them from the value)
ARRAY_TO_STRING will create a single comma-separated string from the found matches.
I am trying to implement row-level security on one table based on a separate users table. I've seen this talked about in places like this, but haven't been able to get things working for my case.
Users table:
Transactions table:
The table I'd like to secure is called Transactions. One of the fields in each row is CompanyID. The Users table contains three columns: AccountID, UserEmail, and CompanyID. What I'd like is for only users assigned to given CompanyIDs to be able to view rows in the Transactions table with those CompanyIDs.
Since more than one User may view a given row, I established a one-to-many relationship from Transactions to Users on the CompanyID field.
I created a DAX expression that filters on the Users table with the following:
[UserEmail] = USERPRINCIPALNAME()
When I select "View As -> Other User" in Power BI Desktop and enter a random email, though, I can still see the entire report. Any idea what I'm leaving out?
EDIT:
I left out an important stipulation: Any user associated with a CompanyID of 1 can view all the records of the Transaction table. I've tried approaches similar to this
[UserEmail] = USERPRINCIPALNAME() ||
COUNTROWS(FILTER('Users', [UserEmail] = USERPRINCIPALNAME() && [CompanyId] = 1)) = 1
but they don't work. Even users with CompanyId of 1 are prohibited from viewing the table.
From the docs:
By default, row-level security filtering uses single-directional
filters, whether the relationships are set to single direction or
bi-directional. You can manually enable bi-directional cross-filtering
with row-level security by selecting the relationship and checking the
Apply security filter in both directions checkbox. Select this option
when you've also implemented dynamic row-level security at the server
level, where row-level security is based on username or login ID.
https://learn.microsoft.com/en-us/power-bi/admin/service-admin-rls
It is possible to save User Role Assignments? When I replace application or remove it and add new with same application id, Apex removes User Role Assignments from APEX_APPL_ACL_USERS table. Actually I can create custom table to store User Role Assigments and later use to insert in APEX_APPL_ACL_USERS table, but I think isn't good solution.
There currently isn't. The safest way is to backup your user roles before replacing the app. I found that when I do an import through the UI the users are preserved, when you delete the app the users are gone. There is a great blog about how to generate a script to restore user roles.
For a single app, here is a script (mostly taken from above blog). Replace the 12345 with your application id. It generates a script that you have to execute after you have recreated your application.
WITH application_id (app_id) AS
(SELECT 12345 FROM dual)
SELECT txt
FROM (SELECT 1 x, 'BEGIN' txt FROM DUAL
UNION ALL
SELECT 2,
RPAD(' ', 3)
|| CASE
WHEN rn = 1 THEN REPLACE(q'[APEX_UTIL.set_workspace('~workspace~');]', '~workspace~', workspace)
END
|| REPLACE(
REPLACE(
REPLACE(
q'[APEX_ACL.ADD_USER_ROLE(p_application_id=>~app~,p_user_name=>'~user~',p_role_static_id=>'~role~');]',
'~app~',
application_id),
'~user~',
user_name),
'~role~',
role_static_id) txt
FROM (SELECT workspace,
ROW_NUMBER() OVER(PARTITION BY workspace ORDER BY application_id, user_name, role_static_id) rn,
application_id,
user_name,
role_static_id
FROM apex_appl_acl_user_roles
JOIN application_id a ON a.app_id = application_id)
UNION ALL
SELECT 3, ' COMMIT;' FROM DUAL
UNION ALL
SELECT 4, 'END;' FROM DUAL)
ORDER BY x;
Getting the list of users belonging to a group in Redshift seems to be a fairly common task but I don't know how to interpret BLOB in grolist field.
I am literally getting "BLOB" in grolist field from TeamSQL. Not so sure this is specific to TeamSQL but I kind of remember thatI got a list of IDs there instead previously in other tool
This worked for me:
select usename
from pg_user , pg_group
where pg_user.usesysid = ANY(pg_group.grolist) and
pg_group.groname='<YOUR_GROUP_NAME>';
SELECT usename, groname
FROM pg_user, pg_group
WHERE pg_user.usesysid = ANY(pg_group.grolist)
AND pg_group.groname in (SELECT DISTINCT pg_group.groname from pg_group);
This will provide the usernames along with the respective groups.
this worked better for me:
SELECT
pu.usename,
pg.groname
FROM
pg_user pu
left join pg_group pg
on pu.usesysid = ANY(pg.grolist)
order by pu.usename