193 lines
7.3 KiB
Transact-SQL
193 lines
7.3 KiB
Transact-SQL
:setvar ShadowSourceLogin "ft546_shadow_ro"
|
|
:setvar ShadowSourceUser "ft546_shadow_ro"
|
|
:setvar ShadowSourcePassword "REPLACE_AT_DEPLOY_TIME"
|
|
:setvar ShadowSourceDatabase "FT546-wcs"
|
|
|
|
SET NOCOUNT ON;
|
|
SET XACT_ABORT ON;
|
|
|
|
IF N'$(ShadowSourcePassword)' = N'REPLACE_AT_DEPLOY_TIME'
|
|
THROW 51000, 'Supply ShadowSourcePassword through the approved secret channel.', 1;
|
|
|
|
IF DB_ID() <> DB_ID(N'$(ShadowSourceDatabase)')
|
|
THROW 51001, 'Run the shadow source-login script only in ShadowSourceDatabase.', 1;
|
|
|
|
DECLARE @sourceLoginCreated bit = 0;
|
|
IF NOT EXISTS (SELECT 1 FROM sys.server_principals
|
|
WHERE name = N'$(ShadowSourceLogin)')
|
|
BEGIN
|
|
DECLARE @createLogin nvarchar(max) =
|
|
N'CREATE LOGIN ' + QUOTENAME(N'$(ShadowSourceLogin)')
|
|
+ N' WITH PASSWORD = N'''
|
|
+ REPLACE(N'$(ShadowSourcePassword)', N'''', N'''''')
|
|
+ N''', CHECK_POLICY = ON, CHECK_EXPIRATION = ON';
|
|
EXEC sys.sp_executesql @createLogin;
|
|
SET @sourceLoginCreated = 1;
|
|
END;
|
|
|
|
BEGIN TRY
|
|
IF EXISTS (
|
|
SELECT 1
|
|
FROM sys.server_role_members rm
|
|
JOIN sys.server_principals role_principal
|
|
ON role_principal.principal_id = rm.role_principal_id
|
|
JOIN sys.server_principals login_principal
|
|
ON login_principal.principal_id = rm.member_principal_id
|
|
WHERE login_principal.name = N'$(ShadowSourceLogin)'
|
|
)
|
|
THROW 51002, 'The shadow source login must not belong to a server role.', 1;
|
|
|
|
DECLARE @serverContextSet bit = 0;
|
|
BEGIN TRY
|
|
EXECUTE AS LOGIN = N'$(ShadowSourceLogin)';
|
|
SET @serverContextSet = 1;
|
|
IF EXISTS (
|
|
SELECT 1
|
|
FROM sys.fn_my_permissions(NULL, N'SERVER')
|
|
WHERE permission_name NOT IN (N'CONNECT SQL', N'VIEW ANY DATABASE')
|
|
)
|
|
THROW 51007, 'The shadow source login retains forbidden server permissions.', 1;
|
|
REVERT;
|
|
SET @serverContextSet = 0;
|
|
END TRY
|
|
BEGIN CATCH
|
|
IF @serverContextSet = 1
|
|
REVERT;
|
|
THROW;
|
|
END CATCH;
|
|
|
|
BEGIN TRANSACTION;
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.database_principals
|
|
WHERE name = N'$(ShadowSourceUser)')
|
|
BEGIN
|
|
DECLARE @createUser nvarchar(max) =
|
|
N'CREATE USER ' + QUOTENAME(N'$(ShadowSourceUser)')
|
|
+ N' FOR LOGIN ' + QUOTENAME(N'$(ShadowSourceLogin)');
|
|
EXEC sys.sp_executesql @createUser;
|
|
END
|
|
ELSE IF SUSER_SID(N'$(ShadowSourceLogin)') <> USER_SID(N'$(ShadowSourceUser)')
|
|
THROW 51003, 'The existing shadow source user maps to a different login.', 1;
|
|
|
|
DECLARE @principal nvarchar(258) = QUOTENAME(N'$(ShadowSourceUser)');
|
|
DECLARE @permissions nvarchar(max) =
|
|
N'GRANT CONNECT TO ' + @principal + N';'
|
|
+ N'REVOKE CONTROL FROM ' + @principal + N';'
|
|
+ N'REVOKE SELECT FROM ' + @principal + N';'
|
|
+ N'GRANT SELECT ON SCHEMA::shadow_ro TO ' + @principal + N';'
|
|
+ N'DENY INSERT, UPDATE, DELETE, EXECUTE, ALTER, TAKE OWNERSHIP '
|
|
+ N'TO ' + @principal + N';'
|
|
+ N'DENY CONTROL ON OBJECT::dbo.wcs_srgv_queue TO ' + @principal + N';'
|
|
+ N'DENY CONTROL ON OBJECT::dbo.wcs_srgv_queue_finish TO ' + @principal + N';'
|
|
+ N'DENY CONTROL ON OBJECT::dbo.device_srgv TO ' + @principal + N';'
|
|
+ N'DENY CONTROL ON OBJECT::dbo.wcs_srgv_map TO ' + @principal + N';'
|
|
+ N'DENY CONTROL ON OBJECT::dbo.bas_cargo_space TO ' + @principal + N';'
|
|
+ N'DENY CONTROL ON OBJECT::dbo.tsj_device_execution_queue TO '
|
|
+ @principal + N';'
|
|
+ N'DENY SELECT ON OBJECT::dbo.wcs_srgv_queue TO ' + @principal + N';'
|
|
+ N'DENY SELECT ON OBJECT::dbo.wcs_srgv_queue_finish TO ' + @principal + N';'
|
|
+ N'DENY SELECT ON OBJECT::dbo.device_srgv TO ' + @principal + N';'
|
|
+ N'DENY SELECT ON OBJECT::dbo.wcs_srgv_map TO ' + @principal + N';'
|
|
+ N'DENY SELECT ON OBJECT::dbo.bas_cargo_space TO ' + @principal + N';'
|
|
+ N'DENY SELECT ON OBJECT::dbo.tsj_device_execution_queue TO '
|
|
+ @principal + N';';
|
|
EXEC sys.sp_executesql @permissions;
|
|
|
|
DECLARE @role sysname;
|
|
DECLARE forbidden_roles CURSOR LOCAL FAST_FORWARD FOR
|
|
SELECT role_principal.name
|
|
FROM sys.database_principals role_principal
|
|
JOIN sys.database_role_members rm
|
|
ON rm.role_principal_id = role_principal.principal_id
|
|
JOIN sys.database_principals member_principal
|
|
ON member_principal.principal_id = rm.member_principal_id
|
|
WHERE role_principal.type = 'R'
|
|
AND member_principal.name = N'$(ShadowSourceUser)';
|
|
|
|
OPEN forbidden_roles;
|
|
FETCH NEXT FROM forbidden_roles INTO @role;
|
|
WHILE @@FETCH_STATUS = 0
|
|
BEGIN
|
|
IF IS_ROLEMEMBER(@role, N'$(ShadowSourceUser)') = 1
|
|
BEGIN
|
|
DECLARE @dropRole nvarchar(max) = N'ALTER ROLE '
|
|
+ QUOTENAME(@role) + N' DROP MEMBER ' + @principal;
|
|
EXEC sys.sp_executesql @dropRole;
|
|
END;
|
|
FETCH NEXT FROM forbidden_roles INTO @role;
|
|
END;
|
|
CLOSE forbidden_roles;
|
|
DEALLOCATE forbidden_roles;
|
|
|
|
DECLARE @databaseContextSet bit = 0;
|
|
BEGIN TRY
|
|
EXECUTE AS USER = N'$(ShadowSourceUser)';
|
|
SET @databaseContextSet = 1;
|
|
IF HAS_PERMS_BY_NAME(DB_NAME(), N'DATABASE', N'SELECT') <> 0
|
|
OR HAS_PERMS_BY_NAME(DB_NAME(), N'DATABASE', N'INSERT') <> 0
|
|
OR HAS_PERMS_BY_NAME(DB_NAME(), N'DATABASE', N'UPDATE') <> 0
|
|
OR HAS_PERMS_BY_NAME(DB_NAME(), N'DATABASE', N'DELETE') <> 0
|
|
OR HAS_PERMS_BY_NAME(DB_NAME(), N'DATABASE', N'EXECUTE') <> 0
|
|
OR HAS_PERMS_BY_NAME(DB_NAME(), N'DATABASE', N'ALTER') <> 0
|
|
OR HAS_PERMS_BY_NAME(DB_NAME(), N'DATABASE', N'CONTROL') <> 0
|
|
OR HAS_PERMS_BY_NAME(DB_NAME(), N'DATABASE', N'TAKE OWNERSHIP') <> 0
|
|
THROW 51004, 'The shadow source login retains forbidden database permissions.', 1;
|
|
|
|
IF EXISTS (
|
|
SELECT 1
|
|
FROM sys.schemas s
|
|
CROSS APPLY sys.fn_my_permissions(QUOTENAME(s.name), N'SCHEMA') p
|
|
WHERE s.name NOT IN (N'sys', N'INFORMATION_SCHEMA')
|
|
AND NOT (s.name = N'shadow_ro' AND p.permission_name = N'SELECT')
|
|
)
|
|
THROW 51005, 'The shadow source login retains forbidden schema permissions.', 1;
|
|
|
|
IF EXISTS (
|
|
SELECT 1
|
|
FROM sys.objects o
|
|
JOIN sys.schemas s ON s.schema_id = o.schema_id
|
|
CROSS APPLY sys.fn_my_permissions(
|
|
QUOTENAME(s.name) + N'.' + QUOTENAME(o.name), N'OBJECT') p
|
|
WHERE o.is_ms_shipped = 0
|
|
AND NOT (
|
|
s.name = N'shadow_ro'
|
|
AND o.name IN (
|
|
N'v_wcs_srgv_queue', N'v_wcs_srgv_queue_finish',
|
|
N'v_device_srgv', N'v_wcs_srgv_map',
|
|
N'v_bas_cargo_space', N'v_tsj_execution',
|
|
N'v_current_database_clock')
|
|
AND p.permission_name = N'SELECT'
|
|
)
|
|
)
|
|
THROW 51006, 'The shadow source login retains forbidden object permissions.', 1;
|
|
|
|
SELECT TOP (0) * FROM shadow_ro.v_wcs_srgv_queue;
|
|
SELECT TOP (0) * FROM shadow_ro.v_wcs_srgv_queue_finish;
|
|
SELECT TOP (0) * FROM shadow_ro.v_device_srgv;
|
|
SELECT TOP (0) * FROM shadow_ro.v_wcs_srgv_map;
|
|
SELECT TOP (0) * FROM shadow_ro.v_bas_cargo_space;
|
|
SELECT TOP (0) * FROM shadow_ro.v_tsj_execution;
|
|
SELECT TOP (0) * FROM shadow_ro.v_current_database_clock;
|
|
REVERT;
|
|
SET @databaseContextSet = 0;
|
|
END TRY
|
|
BEGIN CATCH
|
|
IF @databaseContextSet = 1
|
|
REVERT;
|
|
THROW;
|
|
END CATCH;
|
|
|
|
COMMIT TRANSACTION;
|
|
END TRY
|
|
BEGIN CATCH
|
|
IF XACT_STATE() <> 0
|
|
ROLLBACK TRANSACTION;
|
|
IF @sourceLoginCreated = 1
|
|
BEGIN
|
|
DECLARE @dropSourceLogin nvarchar(max) =
|
|
N'DROP LOGIN ' + QUOTENAME(N'$(ShadowSourceLogin)');
|
|
EXEC sys.sp_executesql @dropSourceLogin;
|
|
END;
|
|
THROW;
|
|
END CATCH;
|