Syntax error near 'unlock' - 'alter role warehouse_user unlock' - sybase

Trying to run - 'alter role warehouse_user unlock' on Sybase IQ
Failed due to
SQL Anywhere Error -131: Syntax error near 'unlock' on line 1
someone knows why?

The alter role statement doesn't appear to have anything to do with locked users (or roles):
IQ - ALTER ROLE statement
SQLAnywhere - ALTER ROLE statement
Assuming the objective is to unlock a user account ... older versions of IQ (eg, 12.6, 12.7) had a stored proc named sp_iqlocklogin (currently unable to find an online reference); this proc appears to have been deprecated in favor of the alter user statement:
alter user <user_id> reset login policy
IQ - Unlocking User Accounts
SQLAnywhere - ALTER USER statement

Related

ALTER permissions for Index but not Table

In SQL Server, is there a combination of permissions that will allow some user to run ALTER INDEX statements but not DROP INDEX/TABLE/etc statements? From what I've read, it looks like granting ALTER gives all the ALTER/DROP/TRUNCATE permissions, and indexes aren't a securable so I can't limit the acceptable statements to just ALTER/DROP indexes (this would be suboptimal, but would be better than just letting the user drop anything).
Thanks to the recommendation in the comments from Ben, I was able to achieve this through signed stored procedure functionality. I basically followed the instructions here, but in case that's gone in the future, these were the steps to get there (including some of the code from the linked tutorial):
Create Cert
CREATE CERTIFICATE TestCreditRatingCer
ENCRYPTION BY PASSWORD = 'pGFD4bb925DGvbd2439587y'
WITH SUBJECT = 'Credit Rating Records Access',
EXPIRY_DATE = '12/31/2021'; -- Error 3701 will occur if this date is not in the future
GO
Create Stored Procedure to do the narrow task (alter indexes in this case) and sign using the cert from step 1
ADD SIGNATURE TO TestCreditRatingSP
BY CERTIFICATE TestCreditRatingCer
WITH PASSWORD = 'pGFD4bb925DGvbd2439587y';
GO
Create login for running the stored procedure using the cert above and the new users for the applicable databases
CREATE USER TestCreditRatingcertificateAccount
FROM CERTIFICATE TestCreditRatingCer;
GO
Grant ALTER rights on the appropriate objects to the new certificate user and EXEC on the new stored proc to the user(s) you want to be able to run the ALTER statements.

Cannot ALTER SEQUENCE in SQL Server

I'm having trouble using the ALTER SEQUENCE statement in SQL Server.
This is the code I'm using:
ALTER SEQUENCE MakatiORSeries RESTART WITH 23;
And this is what I'm getting:
Msg 15151, Level 16, State 1, Line 7
Cannot alter the sequence 'MakatiORSeries', because it does not exist or you do not have permission.
But when I select all the sequences from sys.sequences, it is there
SELECT *
FROM sys.sequences
WHERE [name] = 'MakatiORSeries'
I tried these references too:
SQL Server sequence set current value
Use a variable or parameter to specify restart value for ALTER SEQUENCE
Any help is greatly appreciated. Thanks!
The ALTER permission on the sequence or the schema is required to change this. Ownership chaining in a procedure allows basic DML such as INSERT, UPDATE, DELETE, SELECT, and EXECUTE. It does not extend to ALTER. The account that runs the procedure will also need the ALTER permission on the sequence.
If there are permissions that can't be granted to the login because of security concerns, then you can sign the procedure to run as another credential.
If you want to restart the sequence to set it to a specific value use
SELECT setval('seq',0,false);
It sets the value of the sequence "seq" to 0.

How enable non-sysadmin accounts to execute the "DBCC CHECKIDENT"?

Before each DAO test I clean my database and I need to reset the identity value of some tables. I've created the following stored procedure:
CREATE PROCEDURE SET_IDENTITY
#pTableName varchar(120),
#pSeedValue int
AS
BEGIN
DBCC CHECKIDENT(#pTableName, RESEED, #pSeedValue);
END
My problem is I need to call this stored procedure with a "normal" user. In order works, This user cannot be member of: sysadmin, db_owner, db_ddladmin.
I've tried with:
a) CREATE PROCEDURE WITH EXECUTE AS OWNER
b) EXECUTE AS USER = 'sa' before call DBCC CHECKIDENT
But in both cases I got back:
The server principal sa is not able to access the database my_db_name under the current security context.
I'm using Microsoft SQL Server Express (64-bit) 11.0.2100.60
Thank you in advance,
Abel
This is easy enough to do, but generally speaking you shouldn't need to reset identity values each time. Specific identity values shouldn't matter, so the only concern should be potentially reaching the max value due to repeated testing. And in that case I would not recommend resetting each time as it is also a good test to let IDs reach high values so you can make sure that all code paths handle them properly and find areas that don't before your users do ;-).
That being said, all you need to do (assuming this is localized to a single DB) is create an Asymmetric Key, then create a User from it, then add that User to the db_ddladmin fixed Database Role, and finally sign your Stored Procedure with that same Asymmetric Key.
The following example illustrates this behavior:
USE [tempdb];
CREATE TABLE dbo.CheckIdent
(
[ID] INT NOT NULL IDENTITY(1, 1) CONSTRAINT [PK_CheckIdentity] PRIMARY KEY,
[Something] VARCHAR(50)
);
EXEC(N'
CREATE PROCEDURE dbo.SET_IDENTITY
#pTableName sysname,
#pSeedValue int
AS
BEGIN
DBCC CHECKIDENT(#pTableName, RESEED, #pSeedValue);
END;
');
CREATE USER [MrNobody] WITHOUT LOGIN;
GRANT EXECUTE ON dbo.SET_IDENTITY TO [MrNobody];
-------
EXECUTE AS USER = N'MrNobody';
SELECT SESSION_USER AS [CurrentUser], ORIGINAL_LOGIN() AS [OriginalLogin];
EXEC dbo.SET_IDENTITY N'dbo.CheckIdent', 12;
/*
Msg 2557, Level 14, State 5, Procedure SET_IDENTITY, Line 7 [Batch Start Line 30]
User 'MrNobody' does not have permission to run DBCC CHECKIDENT for object 'CheckIdent'.
*/
REVERT;
SELECT SESSION_USER AS [CurrentUser], ORIGINAL_LOGIN() AS [OriginalLogin];
-------
CREATE ASYMMETRIC KEY [DdlAdminPermissionsKey]
WITH ALGORITHM = RSA_2048
ENCRYPTION BY PASSWORD = 'not_a_good_password';
CREATE USER [DdlAdminPermissions]
FROM ASYMMETRIC KEY [DdlAdminPermissionsKey];
ALTER ROLE [db_ddladmin] ADD MEMBER [DdlAdminPermissions];
ADD SIGNATURE
TO dbo.SET_IDENTITY
BY ASYMMETRIC KEY [DdlAdminPermissionsKey]
WITH PASSWORD = 'not_a_good_password';
-------
EXECUTE AS USER = N'MrNobody';
SELECT SESSION_USER AS [CurrentUser], ORIGINAL_LOGIN() AS [OriginalLogin];
EXEC dbo.SET_IDENTITY N'dbo.CheckIdent', 12;
-- Success!
REVERT;
SELECT SESSION_USER AS [CurrentUser], ORIGINAL_LOGIN() AS [OriginalLogin];
Other minor notes:
You cannot execute as User = sa since sa is a Login (server level) and not a User (database level). You can use EXECUTE AS LOGIN = 'sa'; but that then requires IMPERSONATE permission and is a security hole since the non-privileged Login can run EXECUTE AS LOGIN = 'sa' whenever they want. So don't do that.
For variables / parameters that hold names of SQL Server objects, indexes, etc, you should use NVARCHAR and not VARCHAR. Most internal names use sysname which is a system alias for NVARCHAR(128), so sysname is usually the preferred datatype.
Caller has to own schema or be db_owner:
From doc: DBCC CHECKIDENT
Permissions
Caller must own the schema that contains the table, or be a member of the sysadmin fixed server role, the db_owner fixed database role, or the db_ddladmin fixed database role.
LiveDemo

The server principal "sa" is not able to access the database "model" under the current security context

I created a stored procedure which performs a series of operations that require special permissions, e.g. create database, restore database, etc. I create this stored procedure with
execute as self
...so that it runs as SA. This is because I want to give a SQL user without any permissions the ability to run only these commands which I have defined.
But when I run this stored proc, I get
The server principal "sa" is not able to access the database "model" under the current security context.
How come SA can't access the model database? I actually ran the code in the stored proc on its own, under SA, and it ran fine.
Read Extending Database Impersonation by Using EXECUTE AS before you continue.
when impersonating a principal by using the EXECUTE AS USER statement,
or within a database-scoped module by using the EXECUTE AS clause, the
scope of impersonation is restricted to the database by default. This
means that references to objects outside the scope of the database
will return an error.
You need to use module signing. Here is an example.
For anybody else coming here looking for this info, here is sample code that demonstrates exactly what OP (and I) wanted (based on excellent info from Remus above):
-- how to sign a stored procedure so it can access other Databases on same server
-- adapted from this very helpful article
-- http://rusanu.com/2006/03/01/signing-an-activated-procedure/
USE [master]
GO
CREATE DATABASE TempDB1
CREATE DATABASE OtherDB2
GO
USE TempDB1
GO
-- create a user for TempDB1
CREATE USER [foo] WITHOUT LOGIN
GO
CREATE PROCEDURE TempDB1_SP
AS
BEGIN
CREATE TABLE OtherDB2.dbo.TestTable (ID int NULL)
IF ##ERROR=0 PRINT 'Successfully created table.'
END
GO
GRANT EXECUTE ON dbo.TempDB1_SP TO [foo]
GO
EXECUTE AS User='foo'
PRINT 'Try to run an SP that accesses another database:'
EXECUTE dbo.TempDB1_SP
GO
REVERT
-- Output: Msg 916, Level 14, State 1, Procedure TempDB1_SP, Line 5
-- [Batch Start Line 14]
-- The server principal "..." is not able to access the database
-- "OtherDB2" under the current security context.
PRINT ''
PRINT 'Fix: Try again with signed SP...'
-- Create cert with private key to sign the SP with.
-- Password not important, will drop private key
USE TempDB1
GO
-- create a self-signed cert
CREATE CERTIFICATE [DB_Cert]
ENCRYPTION BY PASSWORD = 'Password1'
WITH SUBJECT = 'Signing for cross-DB SPs';
-- Sign the procedure with the certificate’s private key
ADD SIGNATURE TO OBJECT::[TempDB1_SP]
BY CERTIFICATE [DB_Cert]
WITH PASSWORD = 'Password1'
-- Drop the private key. This way it cannot be used again to sign other procedures.
ALTER CERTIFICATE [DB_Cert] REMOVE PRIVATE KEY
-- Copy the public key part of the cert to [master] database
-- backup to a file and create cert from file in [master]
BACKUP CERTIFICATE [DB_Cert] TO FILE = 'C:\Users\Public\DBCert.cer'
USE [OtherDB2] -- or use [master] = all DBs on server accessible
GO
CREATE CERTIFICATE [DB_Cert] FROM FILE = 'C:\Users\Public\DBCert.cer';
-- the 'certificate user' carries the permissions that are automatically granted
-- when the signed SP accesses other Databases
CREATE USER [DB_CertUser] FROM CERTIFICATE [DB_Cert]
GRANT CREATE TABLE TO [DB_CertUser] -- or whatever other permissions are needed
GO
USE TempDB1
EXECUTE dbo.TempDB1_SP
GO
-- output: 'Successfully created table.'
-- clean up: everything except the cert file, have to delete that yourself sorry
USE [master]
GO
DROP DATABASE TempDB1
DROP DATABASE OtherDB2
GO

Determining the current security checks being made (SQL Server)

One thing that I've always hated more than just about anything in MS SQL Server is the way that security works. The security context constantly switches if you look at the server funny and it's often very hard (for me anyway) to predict or debug.
In dealing with an issue today, I though, "I wish I could just add a line to my code that would display the security context that SQL Server is using when this code runs." Does such a command exist? For example, SELECT security_context()
To be a little clearer... if I'm in a stored procedure and am therefor subject to the security context of the owner of the SP then I'd like to see that. If I'm in code that was called by sp_executesql and it's causing the security to be under the context of the SQL Server service account, then I would want to see that.
At least then I might be able to figure out why SQL Server thinks that I shouldn't have access to something.
Thanks!
EXAMPLE
-- Set up
CREATE USER Test_User WITHOUT LOGIN
CREATE TABLE Test_Security_Context (my_id INT)
INSERT INTO Test_Security_Context VALUES (1)
DENY SELECT ON Test_Security_Context TO Test_User
GO
CREATE PROCEDURE Test_Security_Context_SP
AS
SELECT SUSER_SNAME()
SELECT * FROM Test_Security_Context -- This will return ok
EXEC('SELECT SUSER_SNAME(); SELECT * FROM Test_Security_Context') -- SUSER_SNAME() will match above but select fails
GO
GRANT EXECUTE ON Test_Security_Context_SP TO Test_User
GO
-- Switch to the new user
SETUSER 'Test_User'
GO
-- Do the test
EXEC Test_Security_Context_SP
GO
-- Clean up
SETUSER
DROP PROCEDURE Test_Security_Context_SP
DROP TABLE Test_Security_Context
DROP USER Test_User
GO
Yes, there is such a pair of views that represents your current security context, considering all the details like EXECUTE AS or code signing:
sys.login_token for the server wide context
sys.user_token for the current database context
Every single access you get is ultimately derived from a row in the return of these results. Note that some access are implicit from hard coded role membership (like db_datareader database role or sysadmin server role).
Other that that:
ownership chaining is not related to security context: you are not under the 'context' of the SP owner. Ownership chaining simply states that access checks are skipped for objects owned by the same owner as current object (SP, View).
sp_executesql does not change the security context in any way
Not sure if this is what you mean by security context, but you can retrieve the user associated with your session like:
select SYSTEM_USER
This works for both a SQL Server login or a WIndows login. It even works inside stored procedures with execute as owner. For example,
create procedure dbo.Test
with execute as owner
as
select SYSTEM_USER
go
exec dbo.Test
select SYSTEM_USER
Prints:
sa
MyMachine\MyName
If you're looking for the Windows account that SQL Server is using to do things on your behalf, you could try to run whoami from the command like:
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
EXEC master..xp_cmdshell 'whoami'
For me, that returns nt authority\network service.
I think you want to use CURRENT_USER to see the current security context. Here's an example:
SELECT CURRENT_USER AS 'Current User Name';
GO
EXECUTE AS LOGIN = 'junk'
GO
SELECT CURRENT_USER AS 'Current User Name';
GO
REVERT
SELECT CURRENT_USER AS 'Current User Name';
GO
with output (note: I'm admin on my SQL Server for this)
Current User Name
------------------
dbo
(1 row(s) affected)
Current User Name
------------------
Junk
(1 row(s) affected)
Current User Name
------------------
dbo
(1 row(s) affected)

Resources