Eu tenho que configurar um sistema onde UserA
tenha controle quase total sobre um banco de dados (não o servidor), exceto por uma tabela que é usada pelo sa
, e por isso sa
sempre precisará de acesso a essa tabela.
Até agora tenho:
-- executing as sa
CREATE SCHEMA [sa_schema];
CREATE TABLE [sa_schema].[table1] ( ... );
GRANT SELECT , REFERENCES ON OBJECT::[sa_schema].[table1] TO PUBLIC
CREATE USER [UserA] WITHOUT LOGIN;
GRANT CONTROL TO [UserA] WITH GRANT OPTION;
DENY ALTER , DELETE , INSERT , TAKE OWNERSHIP , VIEW CHANGE TRACKING , UPDATE
ON SCHEMA::[sa_schema] TO [UserA];
DENY ALTER ON USER::[sa] TO [UserA];
Eu pensei que isso seria suficiente, mas acontece que não é. É perfeitamente legal para UserA
executar:
-- executing as UserA
CREATE ROLE [Denied]
DENY SELECT ON OBJECT::[sa_schema].[table1] TO [Denied]
ALTER ROLE [Denied] ADD MEMBER [sa]
E agora sa
não pode mais ler a partir desta tabela.
-- executing as sa
SELECT * FROM [sa_schema].[table1]
Msg 229, Nível 14, Estado 5, Linha 2
A permissão SELECT foi negada no objeto 'table1', banco de dados 'mydb', esquema 'sa_schema'.
Claro, sa
poderia consultar o banco de dados para descobrir os papéis aos quais ele foi adicionado e remover-se deles, mas isso parece um kludge e muito trabalho apenas para executar um select. Acho que poderia evitar esse problema certificando-se de UserA
que não tem a capacidade de adicionar sa
a nenhuma função de banco de dados ou garantindo UserA
que não possa modificar as permissões neste objeto, portanto, não importa quais funções sa
seriam adicionadas, nunca haverá um DENY
sobre isso objeto.
Alguém tem alguma idéia de como garantir que sempresa
terá acesso a esta tabela, independentemente de outras alterações ?UserA
SA é um login como qualquer outro. Você pode querer fazer alguma pesquisa sobre as melhores práticas em relação à conta SA. Não precisa ter superpoderes.
Os membros da função sysadmin, no entanto, não podem ser bloqueados de nada e os membros dessa função ignoram as verificações de segurança. Se o SA for membro do sysadmin, não deve haver nada que você precise fazer.
Uma abordagem programática pode ser criar um trabalho do SQL Agent que restaure as associações corretas (de acordo com você) para contas de administrador. Defina isso para ser executado em um cronograma e você terá a garantia de ter as permissões restauradas (a menos que o UserA decida mexer com o trabalho).
No entanto, isso é realmente mais uma questão de pessoal. As pessoas que têm esse nível de permissão em um servidor devem ser experientes e confiáveis o suficiente para não mexer nas permissões de nível administrativo. Se eles não sabem o que estão fazendo, eles não devem ser capazes de fazê-lo. Se eles sabem o que estão fazendo e fazem de qualquer maneira, você tem um problema diferente. Isso pode ser melhor tratado por uma política de negócios indicando que qualquer pessoa que mexa com permissões de nível administrativo pode estar sujeita a ação disciplinar.
Acho que descobri uma maneira complicada de fazer isso. Eu tenho que mudar
DENY
para:Isso tem dois efeitos:
É muito mais difícil
UserA
selecionar na tabela, apesar de ser pública:Não é possível modificar permissões na tabela:
Isso ainda parece um pouco estranho, mas é melhor do que
sa
redefinir suas permissões constantemente.Esta questão é completamente louca a partir de tentativas de dar/negar permissões para sysadmin terminando com manipulações com usuário SA. Não pode haver nenhum usuário SA no banco de dados, você apenas não tem permissão para executar
Esta tentativa sempre falhará com erro
Msg 15405, Nível 16, Estado 1, Linha 1
Não é possível usar o principal especial 'sa'.