Grant permissions for specific time of day - sql

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;

Related

ORA-00942 cannot find table

I ran these statements:
create table SAMPLE(
ID INT
);
INSERT INTO SAMPLE VALUES(1);
COMMIT;
GRANT INSERT, SELECT, UPDATE, DELETE ON SAMPLE TO NEWLEC;
COMMIT;
But Eclipse says cannot find the table.
How can I resolve it?
You are connecting as the newlec user, and unqualified references to tables will look for them in that schema, not under other users.
You can qualify the table name:
SELECT * FROM real_owner.SAMPLE
For example, if you were connected as HR when you created the table, you would do:
SELECT * FROM HR.SAMPLE
You could also create a public synonym, which is probably overkill and can cause other issues and confusion; or create a private synonym for the newlec user which points to the rea table, e.g.:
CREATE SYNONYM SAMPLE FOR real_owner.SAMPLE;
SELECT * FROM SAMPLE;
so the unqualified query now sees the synonym, and through that the real table owned by someone else. Or you could set your current_schema after logon:
ALTER SESSION SET CURRENT_SCHEMA=real_owner;
SELECT * FROM SAMPLE;
so all unqualified queries now see objects owned by that user, not newlec.
However, if this is a basic assignment on a beginner course then you are probably just expected to qualify the name.

I have restricted select access at table level in sql server. But users are able to access views which are created top of that table

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;

Redshift Table Invisible to Owner

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

Role to access the table only but not data from Table in Oracle Exadata

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.

How do I make one user see a different table with same name

Goal: When everybody else does SELECT * FROM mytable they see one version of the table. But when a specific user does SELECT * FROM mytable they see another version of the table.
I think I'm like halfway there with creating a new role and putting the single user in it. Then creating a copy of the default table with SELECT * INTO newrole.mytable FROM dbo.mytable. But when the user does SELECT * FROM mytable they still see the dbo.mytable. How do I get them to default to the newrole.mytable? I still need them to see all the other dbo tables just not this one.
Create a new schema, and a duplicate table (or view onto dbo.table if that's what you want) in it - eg., otheruser.table. Then, set the user's login to default to that schema:
USE atest
GO
CREATE ROLE [arole]
GO
CREATE SCHEMA [aschema] AUTHORIZATION [arole]
GO
CREATE USER [auser] FOR LOGIN [modify_user] WITH DEFAULT_SCHEMA = aschema
GO
EXEC sp_addrolemember 'arole', 'auser'
GO
CREATE TABLE dbo.atable ( col1 int )
GO
CREATE TABLE aschema.atable (col2 varchar(10))
GO
INSERT INTO dbo.atable( col1 ) VALUES( 1 )
GO
INSERT INTO aschema.atable( col2 ) VALUES( 'One' )
GO
PRINT 'dbo'
SELECT * FROM atable
GO
EXECUTE AS USER = 'auser'
GO
PRINT 'aschema'
SELECT * FROM atable
GO
REVERT
GO
I don't know if this may help but you may be able to make a view of a different table with the same name, here is an excerpt from http://www.w3schools.com/SQl/sql_view.asp:
In SQL, a view is a virtual table based on the result-set of an SQL statement.
A view contains rows and columns, just like a real table. The fields in a view are fields from one or more real tables in the database.
You can add SQL functions, WHERE, and JOIN statements to a view and present the data as if the data were coming from one single table.
I use Postgres primarily, so YMMV, but in postgres you need to
1) Create the new schema, preferably owned by the new role, and put the table in it
2) Set the search_path variable to include that schema BEFORE the other one.
Hope it helps.
This is a very bad idea. I'm not sure why people try all these crazy methods to improve security but it's just plain counter productive.
Ultimately every security system comes down to some line like the following if(User.HasAccessTo(object)). In fact, if you've designed a well thought out security system that's almost exactly how it should work. The more disjointed your authentication checks, the more likely you'll make a mistake. If only some users have access to certain record information you should add a flag to those records and verify access based on that.