次のコマンドを実行するSQL Server 2014エージェントジョブ(タイプ: "オペレーティングシステム(CmdExec)"、実行: "SQL Serverエージェントサービスアカウント"、所有者:sa)があります。
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');"
SQL Serverエージェントが実行されているサービスアカウントには、インスタンスに対するsysadmin権限がありますが、サーバーへの管理者アクセス権はありません。
エージェントのサービスアカウントとしてサーバーにRDPを実行すると、コマンドプロンプトからコマンドを正常に実行できます。
しかし、SQL Serverエージェントジョブを実行すると、「アクセス拒否」エラーで失敗します。
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
ジョブの[別のユーザーとして実行]を、インスタンスに対するsysadmin特権とサーバーへの管理者アクセス権を持つプロキシアカウントに設定した場合、成功しますが、それは私の質問にはあまり関係ありません。
編集:署名されていないPowershellスクリプトを実行する必要があるため、PowershellではなくCmdExecとしてすべてを実行しています(問題の原因ではないため、コードには含まれていません)。 TypeをPowershellに変更すると、同じエラーが発生します。
私の質問:同じコマンドがジョブとして失敗するが、同じサーバー上の同じユーザーアカウントから両方を実行するとコンソールから成功するのはなぜですか?
エージェントジョブからSQL Server CmdExec
を介してPowerShellを実行しているため、生のPowerShellコマンドを実行するのではなく、保存されたPSロジックを含むPowerShellスクリプトを呼び出して、潜在的な違いがあるかどうかを確認できます。回避策。
CmdExec
シェル内のPowerShellで環境変数が正しく機能していない場合に問題が発生する場合に備えて、PowerShell.exe
を指すようにサーバーの完全なOSパスを明示的に指定してから、PowerShellコマンドを渡してください。 。
私の質問:同じコマンドがジョブとして失敗するが、同じサーバー上の同じユーザーアカウントから両方を実行するとコンソールから成功するのはなぜですか?
CmdExec
シェルを使用してSQL Serverエージェントジョブを介してPowerShell.exe
を呼び出すときに問題が発生する可能性があります。また、実行時に、実行されたアカウント(またはサービスアカウント)のセキュリティコンテキストを解釈する方法このようにPowerShell.exe
を実行して、EXEへの実行アクセスを認証できないようにします。次のことを行う必要があります。
<DomainName>\<ServiceAccount>
)<DomainName>\<ServiceAccount>
)<DomainName>\<ServiceAccount>
)アカウント認証情報でSQL認証情報を作成し、以下は、上記の4つのステップを実行した後に実行するこのプロセスのT-SQL部分のスクリプトです。このスクリプトは、私の環境で常に機能し、達成しようとしている説明と似ているように見えます。 。また、ADアカウントに強力で複雑なパスワードが設定されていることを確認し、有効期限が切れないように設定する必要があります。
--- // 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'