I'm creating a table with a superuser (admin), and trying to GRANT ALL and change the owner of a table.
I'm running the following statements in Redshift, where (non-superuser) john is a member of the developers group (and only a member of the developers group):
GRANT ALL ON users.addresses TO GROUP developers;
ALTER TABLE users.addresses OWNER TO john;
I've confirmed that user john has select/insert/delete/update permissions on users.addresses, and is the owner of the table. I've also confirmed that user john has USAGE on the users schema.
However, when I log in as john, the table simply does not appear. When I try a SELECT * FROM users.addresses, Redshift says that the table does not exist.
What am I missing here? Is there an extra layer of permissions or security in Redshift that I'm not seeing? I've looked through the documentation, but haven't had much luck so far.
Because Redshift is saying that the table doesn't exist, that points towards the CREATE TABLE not being committed to the database when you're running it as a superuser account. If you disconnect as the superuser account and then reconnect and attempt to run the SELECT statement against the table, do you get the same error?
Try running an explicit COMMIT statement after you create the table, and then attempt querying it using the non-superuser account. If the client you are using is wrapping all query executions inside of a transaction block, it is possible that they aren't being committed prior to you connecting with the non-superuser account.
Also for reference, I ran the following queries with auto-commit enabled and was unable to replicate the issue you're describing:
-- Run as superuser account:
CREATE SCHEMA users;
CREATE TABLE users.addresses (
user_id VARCHAR(8) ,
user_address VARCHAR(512)
);
INSERT INTO users.addresses VALUES ('12345678', 'Address 1');
CREATE USER john WITH PASSWORD '********';
CREATE GROUP developers;
GRANT USAGE ON SCHEMA users TO GROUP developers;
ALTER GROUP developers ADD USER john;
GRANT ALL ON users.addresses TO GROUP developers;
ALTER TABLE users.addresses OWNER TO john;
-- Run as non-superuser account 'john':
SELECT *
FROM users.addresses;
-- Result Set:
-- user_id user_address
-- 12345678 Address 1
Related
I have restricted select access at table level for 1 single table 'A'in sql server(2016).
But users are able to access views which are created top of that table 'A'.
when users run select statement on table 'A'(select * from table 'A')users are getting 'select permission is denied on object table 'A' ' message.
when users run select statement on view (select * from view 'A') users are able to access all data.
Users are able to create new views by writing select statement on table 'A'.
How can i restrict users to access table 'A' from views as well.
This is expected behavior due to ownership chaining. Permissions on tables referenced by the view are not checked as long as the view and tables have the same owner (AUTHORIZATION).
To break the ownership chain, you could either move the table to a different schema (owned by a different user than the view schema) or change to owner of the table. Examples below.
--move table to different schema
CREATE USER RestricedTablesOwner WITHOUT LOGIN;
GO
CREATE SCHEMA RestricedTables AUTHORIZATION RestricedTablesOwner;
GO
ALTER SCHEMA RestricedTables TRANSFER dbo.A;
GO
--change table to different owner, retaining same schema
ALTER AUTHORIZATION ON OBJECT::dbo.A TO RestricedTablesOwner;
Users have create table statement with select statement from multiple tables from multiple schema. I want to restrict them to read data and allow them to create empty table in their schema with metadata only not data. This I want to do at user access and roles level.
Please tell me how I can do this?
I have tried giving them read access on underlying tables but users can see data as well.
Create table cust_acct_details
as
select *
from ep_rel.acct a
inner join ep_dnf.Cust_account ca
on a.acct_id = ca.acct_id
Tables should create without data.
Add below condition to your code
-- condition to add where 1<>1
Create table cust_acct_details
as
select *
from ep_rel.acct a
inner join ep_dnf.Cust_account ca
on a.acct_id = ca.acct_id
where 1<>1
Please make sure there are unique column names in your select statement. Oracle will not allow same column name in one table. Please use alias instead of *.
If you remove all tablespace privileges from a user they can still create tables but they won't be able to populate them.
For example, if you run this PL/SQL block to revoke all tablespace quotas from one user:
begin
for users in
(
select 'alter user '||username||' quota 0 on '||tablespace_name v_sql
from dba_ts_quotas
where username = 'TEST_USER'
order by 1
) loop
execute immediate users.v_sql;
end loop;
end;
/
Now the user can create tables but will get an error if they try to add rows:
SQL> create table test1(a number);
Table created.
SQL> insert into test1 values(1);
insert into test1 values(1)
*
ERROR at line 1:
ORA-01536: space quota exceeded for tablespace 'USERS'
For metadata, users can always see the metadata in their own schema. To allow them to view the metadata in other schema, run a grant like:
grant select_catalog_role to the_user;
Then that user can view the metadata either in the ALL_ data dictionary views, or using DBMS_METADATA.GET_DDL.
The users listed in the DBA_USERS table do not match the grantees listed in the DBA_TAB_PRIVS table.
So how to I get the privileges for users that are only listed in the DBA_USERS table?
For example, if I do
SELECT USERNAME FROM DBA_USERS;
Then I get a list of login names, such as
USERNAME
--------
BOB17
DBA
JANET5
STEVE34
SYSTEM
And now I want to know what roles and privileges the 'STEVE34' user has.
But when I run the queries suggested online:
SELECT * FROM DBA_SYS_PRIVS;
SELECT * FROM DBA_TAB_PRIVS;
SELECT * FROM DBA_ROLE_PRIVS;
The "Grantee" column does not contain 'BOB17', 'JANET5', 'STEVE34', instead it contains 'SYSTEM', 'PUBLIC', and 'DBA'.
So if 'STEVE34' is not in the Grantee column of any of the PRIVS tables, how do I find out what privileges the user 'STEVE34' has?
The question How to find the privileges and roles granted to a user in Oracle? has 8 answers, none of which solve this question.
I need to know what permissions and roles the users listed in DBA_USERS have, and those users are NOT found in the suggested tables from the linked question.
Further clarification:
If I run this query:
Select USERNAME, GRANTEE from dba_users u
LEFT JOIN dba_tab_privs p
ON u.USERNAME = p.GRANTEE
order by username
This is the result:
USERNAME GRANTEE
-------- -------
BOB17 (null)
DBA DBA
DBA DBA
DBA DBA
DBA DBA
JANET5 (null)
STEVE34 (null)
SYSTEM SYSTEM
SYSTEM SYSTEM
SYSTEM SYSTEM
How can I determine the privileges for users that are not in the DBA_TAB_PRIVS table?
I am absolutely certain that the users do exist and have some kind of privileges, I watched them log in and watched them successfully do SELECT queries.
I may be going on a limb here, but I could not help but notice the sample list of users is in lower case. If you copied and pasted the list (as opposed to incidentally typing the names in lower-case) it means those users were created using double quotes. You can only find them in any Oracle dictionary view (such as dba_users, dba_tab_privs, dba_sys_privs, dba_role_privs) if you take into account that fact. Double quoted lower case is different from non-quoted username.
Whenever a grant, revoke, create table or any other DDL must be run against the lower-case double-quoted "steve34", it needs to be double quoted or Oracle will run it against the unquoted version case-insensitive STEVE34.
Same applies to where clause in SQL on dictionary views. Double-quoted "steve34" becomes case sensitive.
Note in the example below I can create 2 users with apparently the same name, but which are different Oracle users.
FSITJA#db01> create user "steve34" identified by 123;
User created.
FSITJA#db01> create user steve34 identified by 123;
User created.
FSITJA#db01> grant create session to steve34;
Grant succeeded.
FSITJA#db01> select username from dba_users u where upper(u.username) = 'STEVE34';
USERNAME
------------------------------
steve34
STEVE34
FSITJA#db01> select * from dba_sys_privs sp where sp.grantee = 'STEVE34';
GRANTEE PRIVILEGE ADM COM
------- ---------------------------------------- --- ---
STEVE34 CREATE SESSION NO NO
FSITJA#db01> select * from dba_sys_privs sp where sp.grantee = 'steve34';
no rows selected
FSITJA#dbd01 2019-07-31 17:18:00> grant create session to "steve34" with admin option;
Grant succeeded.
FSITJA#db01> select * from dba_sys_privs sp where sp.grantee = 'steve34';
GRANTEE PRIVILEGE ADM COM
------- ---------------------------------------- --- ---
steve34 CREATE SESSION YES NO
Is it possible to give a user rights for, say the business hours of the company.
GRANT SELECT
ON client
<WHERE CONDITION>
TO Emily
I know something like this is possible to do this with MySQL where you can add a WHERE clause to the grant option so you can add context conditions to it. However, I'm working with MS SQL Server, can it be done in there?
Another solution would be to add a SQL Job to add and remove the rights on specific times, but I don't really like that, I'd prefer to do this on the granting level.
I like #Turo's suggestion of using a view.
It could just consist of something like
CREATE VIEW dbo.TimeFilteredClient
AS
SELECT *
FROM dbo.Client
WHERE CAST(GETDATE() AS TIME) BETWEEN '09:00' AND '17:00'
Then grant Emily permissions on the view and not the table. As long as the view and table share the same owner she will be able to select from the view but get no results outside the specified time.
If you are on 2016 you could also use row level security on the table to achieve much the same thing. Example below
CREATE TABLE dbo.Client
(
clientId INT IDENTITY PRIMARY KEY,
Name VARCHAR(50)
);
INSERT dbo.Client
VALUES ('client1'),
('client2');
CREATE USER Emily WITHOUT LOGIN;
GRANT SELECT ON dbo.Client TO Emily;
GO
CREATE SCHEMA Security;
GO
CREATE FUNCTION Security.EmilyTimeFilterPredicate()
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
SELECT 1 AS fn_securitypredicate_result
WHERE USER_NAME() <> 'Emily'
OR CAST(GETDATE() AS TIME) BETWEEN '09:00' AND '17:00';
GO
CREATE SECURITY POLICY EmilyTimeFilter
ADD FILTER PREDICATE Security.EmilyTimeFilterPredicate()
ON dbo.Client
WITH (STATE = ON);
GO
EXECUTE AS USER = 'Emily';
SELECT *
FROM dbo.Client;
REVERT;
SELECT *
FROM dbo.Client;
GO
DROP SECURITY POLICY EmilyTimeFilter ;
DROP TABLE dbo.Client
DROP USER Emily
DROP FUNCTION Security.EmilyTimeFilterPredicate
DROP SCHEMA Security;
We have in our DB a Table which contains a dozens of rows.
The only DML's which applied on the Table are :
1.Inserts - Rows are inserted due to Trigger execution on another table .
2.Deletes - A schedualed procedure is loading requested records to temp table, working with these records and afterwards deleting them from the specific table (there is also a SELECT from the table in order to populate the temp table each time the procedure is running).
We've build the Table with PK and when we run the deletion,
the table is deleted row by row with the ID of the PK column.
just to clarify, we dont have any UPDATES opreations on the table .
Is there any specific guidelines or recommendations when creating such a table ( without updates ) ?
Thx for your answers .
There's nothing special about a table that you don't intend to update.
You could, if you wanted for security reasons, deny update permissions to everyone, since you really only want to allow inserts, deletes, and selects, but there's nothing special about the design, and nothing forcing you to do so.
you can create this table in another schema and grant select, insert, delete to your schema without granting update
so any trying to execute update statemets from your current schema will not executed.
here is an example:
connect system/manager
grant connect, resource to user1 identified by user1;
grant connect, resource to user2 identified by user2;
disconnect
connect user1/user1
create table user1.table1(col1 number, col1_desc varchar2(16));
grant select, insert, delete on user1.table1 to user2;
disconnect
conn user2/user2
select * from user1.table1
insert into user1.table1 values (1, 'insert-user2');
commit;
insert into user1.table1 values (2, 'insert-user2');
commit;
delete from user1.table1 t where t.col1 = 2;
commit;
update user1.table1 t set t.col1_desc = 'ins-user2' where t.col1 = 1;
commit;
-- last update statement will throw ORA-01031: insufficient privileges
note: you can use table1 table name directly from user2 by using synonym for user1.table1
regards,