SCOM 2022 Installation, gMSA, Standalone Web Console Server



I recently built a new SCOM 2022 lab leveraging gMSA accounts. Included in my lab is an Always On Availability Group, SQL Failover Instance, and a standalone web console server. Ordinarily there’s not much fuss with setting up a web console but my lab uses gMSA accounts so there are a few more steps. This is not meant to be an exhaustive guide on SCOM installation, Windows cluster config, or SQL Always On, but rather just documentation of my notes for the next time so that I don’t have to reinvent the wheel. All computers are Windows Server 2022 Datacenter.


Accounts and Groups

gMSA AccountDescription
gMSA-SCOM-SQL$SQL service/SQL agent
gMSA-OMDAS$Data Access Service
gMSA-OMAA$Mgmt Server Action Account
gMSA-OMDWRead$Data Reader
gMSA-OMDWWrite$Data Writer

Global Security Group NameMembers (computers)Description
grpsec-SQLSQL21
SQL22
SQL23
SQL24
SQLINST22 (cluster: SQL23, SQL24)
AGL21 (AG Listener: SQL21, SQL22)
Computers in this group can retrieve the SQL service account password.
grpsec-OpsManServersMS21
MS22
SQLRPT21
Computers in this group can retrieve the passwords for the SCOM service accounts .

Standalone Web Server: WEB21


gMSA Stuff

Create Root Key for AD

# KDS Key for domain
Add-KdsRootKey -EffectiveImmediately



SQL Service Account

The OpsDB is destined for a SQL Always On Availability Group: SQL21,SQL22 with listener “AGL21”.
The DW is destined for a SQL Failover Cluster Instance: SQL23,SQL24 with SQL instance name: SQLINST21\INST1. These two SQL instances should provide me with some variety in my lab.
This is how I configured the SQL service account with PowerShell. I ran this code from the AD server because I happened to be logged into it at the time. Set $accountName, $domain, $groupname, and $SQLservers.
(reference)

 

$accountName = 'gMSA-SCOM-SQL' #No dollar '$' required on account name here.
$domain = 'CONTOSO.COM'
$groupname = 'grpsec-SQL' #computers in this group can retrieve the SQL account password
$SQLservers = 'sql21,sql22,sql23,sql24'

$params = @{
    Name = $accountName
    DNSHostName = "$($accountName).$($domain)"
    PrincipalsAllowedToRetrieveManagedPassword = $groupname
    ManagedPasswordIntervalInDays  = 180
    KerberosEncryptionType = 'AES128','AES256'
    Enabled = $True        
    PassThru = $True
}
New-ADServiceAccount @params

# Give the account permissions to set own SPN
dsacls (Get-ADServiceAccount -Identity $accountName).DistinguishedName /G "SELF:RPWP;servicePrincipalName"

# Verify account for good measure
Get-ADServiceAccount $accountName -Properties * | FL DNSHostName,KerberosEncryptionType,SamAccountName 

# Establish remote session on all affected/relevant servers to add the AD PowerShell tools. Required to install the gMSA account to the servers. You could run the command (within the scriptblock below and the restart) on each of the individual SQL servers
$session = New-PSSession -ComputerName $SQLservers
Invoke-Command -Session $session -ScriptBlock {Add-WindowsFeature -Name 'RSAT-AD-Tools' -Verbose} -Verbose

# Restart is necessary for group membership to activate and required before we can use Install-ADServiceAccount command below.
Invoke-Command -Session $session -ScriptBlock {Restart-Computer -Force} -Verbose

# Allow the computers to use the account
$session = New-PSSession -ComputerName $SQLservers
# If this command below fails, log into each server and run the command manually
# Install-ADServiceAccount 'your-svcaccount-name'
Invoke-Command -Session $session -ScriptBlock {param ($accountname);Install-ADServiceAccount $accountName -Verbose} -ArgumentList $accountname

#Optionally you can test the service account from the SQL server. This command should return boolean "True".
Test-ADServiceAccount -Identity $accountName



SCOM Service Accounts

This is how I configured the 4 SCOM accounts and mgmt servers with PowerShell:
(reference1, reference2)

DAS/SDK: CONTOSO\gMSA-OMDAS$
OMAA: CONTOSO\gMSA-OMAA$
Read: CONTOSO\gMSA-OMDWRead$
Write: CONTOSO\gMSA-OMDWWrite$

Run the following snippet on each mgmt server.

# Run the following on each mgmt server. 
Add-WindowsFeature -Name 'RSAT-AD-Tools' -Verbose

# Restart mgmt server
Restart-Computer -Force


Run the following snippet for each of the 4 SCOM accounts. Set $accountName, $domain, and $groupname as needed. I ran this code from the AD server because I happened to be logged into the AD server at the time.

# SCOM account config example. Do this for each account.
$accountName = 'gMSA-OMDAS' #No dollar '$' required on account name here.
$domain = 'CONTOSO.COM'
$groupname = 'grpsec-OpsMgrSvrs' #computers in this group can retrieve the SCOM accounts passwords

$PrincipalsAllowedToRetrieveManagedPassword = $groupname
$params = @{
    Name = $accountName
    DNSHostName = "$($accountName).$($domain)"
    PrincipalsAllowedToRetrieveManagedPassword = $PrincipalsAllowedToRetrieveManagedPassword
    ManagedPasswordIntervalInDays  = 180
    KerberosEncryptionType = 'AES128','AES256'
    Enabled = $True        
    PassThru = $True
}
New-ADServiceAccount @params

# Give permissions to set own SPN for applicable account(s)
dsacls (Get-ADServiceAccount -Identity $accountName).DistinguishedName /G "SELF:RPWP;servicePrincipalName"

# Verify account
Get-ADServiceAccount $accountName -Properties * | FL DNSHostName,KerberosEncryptionType,SamAccountName 


I had to log into each mgmt server to run the commands below. I couldn’t get it to run in a remote session and I got tired of trying. Set $accountName as needed for each SCOM account.

# Run this for each SCOM service account on each mgmt server.
$accountName = 'gMSA-OMDAS' #example
Install-ADServiceAccount $accountName -Verbose



SQL

At this point assume that the following is configured correctly:

SQL Always On Availability group: AG21. Cluster: FC21, members: SQL21, SQL22. Listener: AGL21.

SQL Failover Cluster Instance. Cluster: FC22, members: SQL23, SQL24. SQL Instance: SQLINST22\INST1.



SCOM Installation

At this point assume the following:

  • SCOM is installed on the first mgmt server using the AGL21 for the OpsDB and SQLINST22\INST1 for the DW.
  • The 4 SCOM gMSA accounts are provided during setup.
  • Web Console role is installed on WEB21 (use mixed auth), no SSL



SSRS

Server Name: SQLRPT21
Install SSRS on SQLRPT21.
Run Report Server Configuration Manager.
Service Account: CONTOSO\gMSA-OMDWRead$
Web Service URL: <default>, no changes
Database:
SQL Server Name: SQLINST22\INST1
Database Name: ReportServer
Mode: Native
Credential: Contoso\gMSA-OMDWREAD$
Web Portal URL: <default>, no changes
Email Settings: <none>
Execution Account:
Use ordinary domain service account for the Execution account (not gMSA). CONTOSO\svcOMRPTExec
Encryption Keys: I backed up the key.
Subscription Settings: CONTOSO\svcOMRPTExec
Scale-out Deployment: SQLRPT21: joined



Execution Account

Add Execution account login to SSRS database SQL instance (DW SQL clustered instance in this case: ‘SQLINST22\INST1’).
Map Execution account to ReportServer/ReportTemp databases and add RSExec role to both.
Map to Datawarehouse DB and add OpsMgrReader role.
Note: Exec account is allowed “Log on Locally” by default as a domain user.
If you “Deny log on locally”, this will break reporting.

  • Install SCOM Reporting Role on SQLRPT21



SQL AOAG Config Tasks

Copy AG logins to other Replicas with DBATools Posh module

SCOM configures all the necessary logins and permissions on the Primary Replica in the AG. However, I must manually copy those logins to the Secondary. I use the DBATools module to make this effortless. I installed directly on my mgmt server from the Gallery.

$AGLSN = 'AGL21\Inst1' #My AG Listener instance
 
$primaryReplica =    Get-DbaAgReplica -SqlInstance $AGLSN | Where Role -eq Primary
$secondaryReplicas = Get-DbaAgReplica -SqlInstance $AGLSN | Where Role -eq Secondary
     
$LoginsOnPrimary = (Get-DbaLogin -SqlInstance $primaryReplica.Name)
     
$secondaryReplicas | ForEach-Object {
        
    $LoginsOnSecondary = (Get-DbaLogin -SqlInstance $_.Name)
     
    $diff = $LoginsOnPrimary | Where-Object Name -notin ($LoginsOnSecondary.Name)
    if($diff) {
        Copy-DbaLogin -Source $primaryReplica.Name -Destination $_.Name -Login $diff.Nane
    }   
}



At some point I noticed the error described below on my AG node:

Date		9/12/2022 12:11:48 PM
Log		SQL Server (Current - 9/12/2022 12:05:00 PM)

Source		Logon

Message
Database Mirroring login attempt by user 'CONTOSO\gMSA-SCOM-SQL$.' failed with error: 'Connection handshake failed. The login 'CONTOSO\gMSA-SCOM-SQL$' does not have CONNECT permission on the endpoint. State 84.'.  [CLIENT: 192.168.XX.XX]

I had to grant the SQL service account permission to connect to the replica.

-- Allow service account to connect to replica
SET NOCOUNT ON

--DECLARE VARIABLES
DECLARE @accountname nvarchar(128)
DECLARE @command1 nvarchar(MAX)
--ENTER DOMAIN ACCOUNT HERE
SET @accountname = 'CONTOSO\gMSA-SCOM-SQL$'

--CREATE LOGIN
SET @command1 = 'USE [master];
IF NOT EXISTS (SELECT [name] FROM sys.server_principals WHERE [name] = ''' + @accountname +''')
CREATE LOGIN ['+@accountname+'] FROM WINDOWS WITH DEFAULT_DATABASE=[master];
'
EXECUTE sp_executesql @command1;

GRANT CONNECT ON ENDPOINT::hadr_endpoint TO [CONTOSO\gMSA-SCOM-SQL$]
GO



Set recovery mode on OperationsManger DB to FULL.

Create full backup.

Add OperationsManager DB to AG, fully seed.

Perform test failover of OpsMan DB:

  • #stop services on mgmt servers
    • invoke-command -ComputerName ms21,ms22 -ScriptBlock {Get-Service HealthService,omsdk,cshost | Stop-Service}
  • Failover to Secondary using the AG task within SQL Server Mgmt Studio (not Failover Cluster Manager)
  • #Start services on mgmt servers
    • invoke-command -ComputerName ms21,ms22 -ScriptBlock {Get-Service omsdk,cshost,HealthService | Start-Service}
  • Resume synching of AG within SQL Server Mgmt Studio
    • Verify “Synchronized” status.


At this point I think I had installed the SQL management packs. The “Securables” monitor(s) had detected that some securables were not configured correctly. I manually corrected these with the commands below.

SQ21\INST1, SQL22\INST1

No access to the following SQL Server securable(s):

1. Tables:

• msdb.dbo.sysjobschedules

• msdb.dbo.log_shipping_primary_databases

• msdb.dbo.log_shipping_secondary_databases

2. Stored procedures:

• sys.xp_readerrorlog

• msdb.dbo.SQLAGENT_SUSER_SNAME

NOTE: I used a global security group name in the script below (“CONTOSO\grpsec-SCOMSQLMonitoring”). This global security group is added as a Login on my SQL servers and it contains my SQL RunAs account used in the SCOM SQL Discovery and Monitoring profiles. I used the permissions script here to grant the necessary discovery/monitoring permissions to the Login. My customer cannot use the service SID approach so I configured my lab to closely resemble my customer.

USE msdb
--TABLES
GRANT SELECT ON OBJECT::msdb.dbo.sysjobschedules TO [CONTOSO\grpsec-SCOMSQLMonitoring]
GRANT SELECT ON OBJECT::msdb.dbo.log_shipping_primary_databases TO [CONTOSO\grpsec-SCOMSQLMonitoring]
GRANT SELECT ON OBJECT::msdb.dbo.log_shipping_secondary_databases TO [CONTOSO\grpsec-SCOMSQLMonitoring]

--SP
GRANT EXECUTE ON msdb.dbo.SQLAGENT_SUSER_SNAME TO [CONTOSO\grpsec-SCOMSQLMonitoring] 
GO

USE [master]
--SP
GRANT EXECUTE ON sys.xp_readerrorlog  TO [CONTOSO\grpsec-SCOMSQLMonitoring] 
GO



SQLINST22\INST1

No access to the following SQL Server securable(s):

1. Server-level permissions:

• VIEW ANY DEFINITION

2. Tables:

• msdb.dbo.sysjobs_view

• msdb.dbo.sysjobschedules

• msdb.dbo.syscategories

• msdb.dbo.log_shipping_primary_databases

• msdb.dbo.log_shipping_secondary_databases

3. Stored procedures:

• sys.xp_readerrorlog

• msdb.dbo.sp_help_jobactivity

• msdb.dbo.sp_help_job

• msdb.dbo.SQLAGENT_SUSER_SNAME

USE [master]
--SP
GRANT EXECUTE ON sys.xp_readerrorlog  TO [CONTOSO\grpsec-SCOMSQLMonitoring]
GO

USE [msdb]
--TABLES
GRANT SELECT ON OBJECT::msdb.dbo.sysjobs_view  TO [CONTOSO\grpsec-SCOMSQLMonitoring]
GRANT SELECT ON OBJECT::msdb.dbo.sysjobschedules TO [CONTOSO\grpsec-SCOMSQLMonitoring]
GRANT SELECT ON OBJECT::msdb.dbo.syscategories  TO [CONTOSO\grpsec-SCOMSQLMonitoring]
GRANT SELECT ON OBJECT::msdb.dbo.log_shipping_primary_databases TO [CONTOSO\grpsec-SCOMSQLMonitoring]
GRANT SELECT ON OBJECT::msdb.dbo.log_shipping_secondary_databases TO [CONTOSO\grpsec-SCOMSQLMonitoring]

--SP
GRANT EXECUTE ON msdb.dbo.sp_help_jobactivity   TO [CONTOSO\grpsec-SCOMSQLMonitoring] 
GRANT EXECUTE ON msdb.dbo.sp_help_job  TO [CONTOSO\grpsec-SCOMSQLMonitoring] 
GRANT EXECUTE ON msdb.dbo.SQLAGENT_SUSER_SNAME TO [CONTOSO\grpsec-SCOMSQLMonitoring] 
GO

I also configured maintenance plans for Full, Diff, and TLOG backups of the AOAG (OpsMan) instance. At some point I will get around to adding plans to the DW instance.



Service Principal Names (SPNs)

Normally when working with Kerberos delegation, you just set the Service Principal Name (SPN) either with setspn.exe command or manually with the attribute editor in Active Directory Users and Computers. Additionally, enabling View > Advanced features in Active Directory Users and Computers adds another way to configure Kerberos delegation from the Delegation tab of a user or a computer account.

But for standalone and group Managed Service Accounts, the Delegation tab doesn’t appear, even after adding SPNs to these accounts or enabling View > Advanced features.

To configure delegation for these special accounts, you need to set the correct attributes manually. There are two attributes that you need to modify for these accounts:

  1. userAccountControl defines the type of delegation
  2. msDS-AllowedToDelegateTo defines where the SPNs for delegation will be added

These attributes can be set in different ways:

  1. Use PowerShell
  2. Manually update the userAccountControl value


Here’s what I used to make the changes in PowerShell:
NOTE: modify the gMSA account name as needed, and modify the SPNs section to include your mgmt server accounts.

#my SDK/DAS Service account
$gMSA ='gMSA-OMDAS$'

#TURN ON CONSTRAINED DELEGATION (Use any authentication protocol)
Set-ADAccountControl -Identity $gMSA -TrustedForDelegation $false -TrustedToAuthForDelegation $true -Verbose

#array for spns
$SPNS = `
 'MSOMSdkSvc/MS21.CONTOSO.COM' `
,'MSOMSdkSvc/MS21' `
,'MSOMSdkSvc/MS22' `
,'MSOMSdkSvc/MS22.CONTOSO.COM' 

# Add mgmt server SDK SPNS to the attribute. Grant Mgmt servers permission to use this account. 
Set-ADServiceAccount -Identity $gMSA -Add @{'msDS-AllowedToDelegateTo'= $SPNS } -Verbose


Also, for reference, in my lab the userAccountControl attribute is as shown below which is a combination/sum of the two permissions shown below which I believe to be correct according to the support doc.

References:

  1. https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/configure-kerberos-delegation-group-managed-service-accounts
  2. https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties



Standalone Web Server

WEB21.contoso.com

IMPORTANT: You have to allow the web server (frontend resource) access to the gMSA account on the mgmt server SDK (backend resource). Previously I was getting a 403 error until I performed this step.

# Grant Web server access to the 'backend resource'
$FrontendServer = Get-ADComputer web21 
Set-ADServiceAccount -Identity $gMSA -PrincipalsAllowedToDelegateToAccount $FrontendServer

# View account properties
Get-ADServiceAccount -Identity $gMSA -Properties *



These are my web console server SPNs. I added the SPNs enclosed in yellow to the computer object.


I created an alias for my Web Console

IIS Site Bindings

I added an SSL certificate to my IIS server at some point although I didn’t create the template correctly so there’s something wrong with the subject. It still works but with errors. I’ll fix it someday.

The localhost bindings shown for 80/443 as “[::1]” are required. Make sure you don’t skip those.

The localhost bindings shown for 80 (and/or 443) as “[::1]” are required. Make sure you don’t skip those.

App Pools

Auth



These are all of the notes that I remembered to record. Let me know if you have any specific questions and I’ll do my best to respond in a timely manner. Hope this helps others.

Leave a Reply

Your email address will not be published. Required fields are marked *