web-dev-qa-db-fra.com

La commande échoue comme travail cmdexec mais réussit à partir de la console

J'ai un système d'exploitation d'agent SQL Server 2014 (type: "Système d'exploitation (CMDEXEC)", exécuté comme: "Compte de service SQL Server Server", propriétaire: SA) qui exécute la commande suivante:

powershell -ExecutionPolicy Bypass -Command "$objServiceManager = New-Object -ComObject 'Microsoft.Update.ServiceManager'; $objService = $objServiceManager.AddService2('7971f918-a847-4430-9279-4a52d1efe18d',2,''); $objService.PSTypeNames.Add('PSWindowsUpdate.WUServiceManager');"

Le compte de service que SQL Server Agent est exécuté sous Sysadmin Privilèges à l'instance, mais n'a pas d'accès administrateur au serveur.

Si je suis dans le serveur en tant que compte de service de l'agent, je peux exécuter la commande avec succès à partir d'une invite de commande:

enter image description here

Mais si j'exécute le travail de l'agent SQL Server, il échoue avec une erreur "Accès refusé":

Exception calling "AddService2" with "3" argument(s): "Access is denied. 
(Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
At line:1 char:79
+ $objServiceManager = New-Object -ComObject 
'Microsoft.Update.ServiceManager'; $o ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation

You cannot call a method on a null-valued expression.
At line:1 char:170
+ ... efe18d',2,''); 
$objService.PSTypeNames.Add('PSWindowsUpdate.WUServiceManager');
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

J'ai constaté que si je définissais le "Courant" comme "pour le poste à un compte proxy contenant des privilèges Sysadmin sur l'instance et l'accès administrateur au serveur, il réussit, mais ce n'est pas vraiment pertinent pour ma question.

EDIT: J'exécute tout comme CMDEXEC, et non PowerShell, car je dois exécuter un script de PowerShell non signé (non inclus dans mon code, car cela ne cause pas de problème). Je reçois la même erreur si je change le type à PowerShell.

Ma question: Pourquoi la même commande échoue-t-elle qu'un travail, mais réussisse de la console lorsqu'elle est exécutée à partir du même compte d'utilisateur sur le même serveur?

3
CaptainSlock

Solutions de contournement potentielles

  1. Puisque vous exécutez PowerShell via SQL Server CmdExec à partir d'un travail d'agent, vous pouvez essayer d'appeler un script PowerShell avec votre logique PS enregistrée dans celle-ci plutôt que d'exécuter des commandes RAW PowerShell pour voir si cela fait une différence pour un potentiel. solution de contournement.

  2. Essayez de placer explicitement le chemin d'exploitation complet sur le serveur pour pointer vers PowerShell.exe Et ensuite transmettre vos commandes PowerShell après cela, si la question a trait à des variables environnementales ne fonctionnant pas correctement pour PowerShell dans la coquille CmdExec.

Ma question: Pourquoi la même commande échoue-t-elle qu'un travail, mais réussisse de la console lorsqu'elle est exécutée à partir du même compte d'utilisateur sur le même serveur?

raisons potentielles

  • Cela pourrait être un problème lorsque vous appelez PowerShell.exe à travers le travail d'agent SQL Server avec le shell CmdExec _ Shell et comment il interprète le contexte de sécurité du compte, il est exécuté à partir de ou comme (par exemple, le compte de service) lorsqu'il essaie d'exécuter PowerShell.exe De cette façon, il n'est donc pas capable d'authentifier l'accès à l'exécution à l'exe en raison de cela.
  • Vérifiez et lisez la version de PowerShell installée, la version de SQL Server installé et la Windows OS Tout cela sont actives et exécutées pour des problèmes "connus" liés aux incompatibilités de la version à cet égard - il peut s'agir d'un problème connu en fonction de Tous les détails de cet environnement.

Un chemin de travail I Exécutez PowerShell à partir d'emplois SQL Agent

Tu devras:

  1. Créez le compte de service [Objet de compte d'utilisateur] dans AD (<DomainName>\<ServiceAccount>)
  2. Créez un identifiant SQL I.e. Le compte de service dans # 1 (<DomainName>\<ServiceAccount>)
  3. Créez un identifiant SQL avec cela même (<DomainName>\<ServiceAccount>) des informations d'identification du compte,
  4. Créer un proxy d'agent SQL Server Compte à utiliser pour "Exécuter comme" à partir du travail de l'agent SQL pour exécuter PowerShell

Vous trouverez ci-dessous un script de la partie T-SQL de ce processus que je cours après avoir effectué 4 étapes ci-dessus, et cela fonctionne toujours dans mon environnement pour accomplir ce qui semble être similaire à ce que vous avez expliqué que vous essayez d'accomplir . Je dois également vous assurer que le compte d'annonces ait un mot de passe fort/complexe et de le définir pour ne jamais expirer.

--- // Create login on SQL Instance for domain\PSSQLJobs service account if it does not exist
IF NOT EXISTS (
        SELECT *
        FROM sys.server_principals
        WHERE NAME = N'domain\PSSQLJobs'
        )
BEGIN
    CREATE LOGIN [domain\PSSQLJobs]
    FROM WINDOWS WITH DEFAULT_DATABASE = [master]
        ,DEFAULT_LANGUAGE = [us_english]
END

USE [master]

IF NOT EXISTS (
        SELECT *
        FROM sys.database_principals
        WHERE NAME = N'domain\PSSQLJobs'
        )
    CREATE USER [domain\PSSQLJobs]
    FOR LOGIN [domain\PSSQLJobs]
    WITH DEFAULT_SCHEMA = [dbo]

EXEC sp_addrolemember N'db_datareader'
    ,N'domain\PSSQLJobs'

GRANT CONNECT
    ON DATABASE::[master]
    TO [domain\PSSQLJobs]

USE [msdb]

IF NOT EXISTS (
        SELECT *
        FROM sys.database_principals
        WHERE NAME = N'domain\PSSQLJobs'
        )
    CREATE USER [domain\PSSQLJobs]
    FOR LOGIN [domain\PSSQLJobs]
    WITH DEFAULT_SCHEMA = [dbo]

EXEC sp_addrolemember N'db_datareader'
    ,N'domain\PSSQLJobs'

EXEC sp_addrolemember N'SQLAgentOperatorRole'
    ,N'domain\PSSQLJobs'

EXEC sp_addrolemember N'SQLAgentReaderRole'
    ,N'domain\PSSQLJobs'

EXEC sp_addrolemember N'SQLAgentUserRole'
    ,N'domain\PSSQLJobs'

GRANT CONNECT
    ON DATABASE::[msdb]
    TO [domain\PSSQLJobs]



--- // Create Credential *** Type in password of account into value of SECRET ***
USE [msdb]

CREATE CREDENTIAL PSSQLJobs
    WITH IDENTITY = 'domain\PSSQLJobs'
        ,SECRET = '*******'


--- // Create PowerShell Proxy account and give PSSQLJobs access to it
USE [msdb]

EXEC msdb.dbo.sp_add_proxy @proxy_name = N'ExecutePowershell'
    ,@credential_name = N'PSSQLJobs'
    ,@enabled = 1

EXEC msdb.dbo.sp_grant_proxy_to_subsystem @proxy_name = N'ExecutePowershell'
    ,@subsystem_id = 12

EXEC msdb.dbo.sp_grant_login_to_proxy @proxy_name = N'ExecutePowershell'
    ,@login_name = N'domain\PSSQLJobs'
2
Pimp Juice IT