Skip to content

Commit

Permalink
DSOS-2635: powershell ad updates for new DC (#600)
Browse files Browse the repository at this point in the history
* fix typo

* Rename Get-ModPlatformADCredential function

* Add additional AD Credential functions

* test

* fix

* fix

* fix

* fix

* Fix

* update
  • Loading branch information
drobinson-moj authored Mar 8, 2024
1 parent eacf89a commit 2edb9e6
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 29 deletions.
8 changes: 5 additions & 3 deletions powershell/Modules/ModPlatformAD/ModPlatformAD.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# Generated by: Ministry of Justice
#
# Generated on: 12/02/2024
# Generated on: 05/03/2024
#

@{
Expand All @@ -12,7 +12,7 @@
# RootModule = ''

# Version number of this module.
ModuleVersion = '1.0.0.2'
ModuleVersion = '1.0.0.3'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down Expand Up @@ -73,7 +73,9 @@ NestedModules = @('ModPlatformADComputer.psm1',
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = 'Rename-ModPlatformADComputer', 'Add-ModPlatformADComputer',
'Remove-ModPlatformADComputer', 'Get-ModPlatformADConfig',
'Get-ModPlatformADCredential'
'Get-ModPlatformADSecret', 'Get-ModPlatformADJoinCredential',
'Get-ModPlatformADAdminCredential',
'Get-ModPlatformADSafeModeAdministratorPassword'

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = '*'
Expand Down
4 changes: 2 additions & 2 deletions powershell/Modules/ModPlatformAD/ModPlatformADComputer.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function Add-ModPlatformADComputer {
HashTable as returned from Get-ModPlatformADConfig function
.PARAMETER ModPlatformADCredential
AD credential as returned from Get-ModPlatformADCredential function.
AD credential as returned from Get-ModPlatformADJoinCredential function.
.EXAMPLE
Add-ModPlatformADComputer $ModPlatformADConfig $ModPlatformADCredential
Expand Down Expand Up @@ -124,7 +124,7 @@ function Remove-ModPlatformADComputer {
Returns true if successful and a reboot required, false if already removed.
.PARAMETER ModPlatformADCredential
AD credential as returned from Get-ModPlatformADCredential function.
AD credential as returned from Get-ModPlatformADJoinCredential function.
.EXAMPLE
Add-ModPlatformADComputer $ModPlatformADConfig $ModPlatformADCredential
Expand Down
2 changes: 2 additions & 0 deletions powershell/Modules/ModPlatformAD/ModPlatformADConfig.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function Get-ModPlatformADConfig {
"DomainNameFQDN" = "azure.noms.root"
"DomainNameNetbios" = "AZURE"
"DomainJoinUsername" = "svc_join_domain"
"DomainAdminUsername" = "svc_admin"
}
"azure.hmpp.root" = @{
"AccountIdsSSMParameterName" = "account_ids"
Expand All @@ -44,6 +45,7 @@ function Get-ModPlatformADConfig {
"DomainNameFQDN" = "azure.hmpp.root"
"DomainNameNetbios" = "HMPP"
"DomainJoinUsername" = "svc_join_domain"
"DomainAdminUsername" = "svc_admin"
}
}

Expand Down
160 changes: 148 additions & 12 deletions powershell/Modules/ModPlatformAD/ModPlatformADCredential.psm1
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
function Get-ModPlatformADCredential {
function Get-ModPlatformADSecret {

<#
.SYNOPSIS
Retrieves a domain account credential that can be used for AD operations
Retrieves domain account secret from SecretsManager
.DESCRIPTION
Using configuration returned from Get-ModPlatformADConfig, this function
optionally assumes a role to access a secret containing the password of the
domain join username. EC2 requires permissions to join the given role,
optionally assumes a role to access a SecretsManager secret containing
domain secrets. EC2 requires permissions to join the given role,
a SSM parameter containing account IDs, and the aws cli.
.PARAMETER ModPlatformADCredential
.PARAMETER ModPlatformADConfig
HashTable as returned from Get-ModPlatformADConfig function
.EXAMPLE
$ADConfig = Get-ModPlatformADConfig
$ADCredential = Get-ModPlatformADCredential $ADConfig
$ADSecret = Get-ModPlatformADJoinCredential $ADConfig
$Password = ConvertTo-SecureString $ADSecret.svc_join_domain
.OUTPUTS
PSCredentialObject
PSCustomObject
#>

[CmdletBinding()]
Expand Down Expand Up @@ -58,15 +59,150 @@ function Get-ModPlatformADCredential {
} else {
$SecretValueRaw = aws secretsmanager get-secret-value --secret-id "${SecretArn}" --query SecretString --output text
}
$SecretValue = "$SecretValueRaw" | ConvertFrom-Json
"$SecretValueRaw" | ConvertFrom-Json
}

function Get-ModPlatformADJoinCredential {

<#
.SYNOPSIS
Retrieves credential that can be used for joining Computers to the domain
.DESCRIPTION
Using configuration returned from Get-ModPlatformADConfig, this function
optionally assumes a role to access a secret containing the password of the
domain join username. EC2 requires permissions to join the given role,
a SSM parameter containing account IDs, and the aws cli.
.PARAMETER ModPlatformADConfig
HashTable as returned from Get-ModPlatformADConfig function
.PARAMETER ModPlatformADSecret
Optional PSCustomObject containing secrets as returned from Get-ModPlatformADSecret
.EXAMPLE
$ADConfig = Get-ModPlatformADConfig
$ADCredential = Get-ModPlatformADJoinCredential $ADConfig
.OUTPUTS
PSCredentialObject
#>

[CmdletBinding()]
param (
[Parameter(Mandatory=$true)][hashtable]$ModPlatformADConfig,
[PSCustomObject]$ModPlatformADSecret
)

$ErrorActionPreference = "Stop"

if ($ModPlatformADSecret -eq $null) {
$ModPlatformADSecret = Get-ModPlatformADSecret -ModPlatformADConfig $ModPlatformADConfig
}
$DomainNameNetbios = $ModPlatformADConfig.DomainNameNetbios
$DomainJoinUsername = $ModPlatformADConfig.DomainJoinUsername
$DomainJoinPassword = $SecretValue.$DomainJoinUsername
$DomainJoinPassword = $ModPlatformADSecret.$DomainJoinUsername
if (-not $DomainJoinPassword) {
Write-Error "Password secret ${SecretArn} does not contain domain join username ${DomainJoinUsername}"
Write-Error "Password secret does not contain domain join username ${DomainJoinUsername}"
}
$DomainJoinPasswordSecureString = ConvertTo-SecureString $SecretValue.$DomainJoinUsername -AsPlainText -Force
$DomainJoinPasswordSecureString = ConvertTo-SecureString $DomainJoinPassword -AsPlainText -Force
New-Object System.Management.Automation.PSCredential ("$DomainNameNetbios\$DomainJoinUsername", $DomainJoinPasswordSecureString)
}

Export-ModuleMember -Function Get-ModPlatformADCredential
function Get-ModPlatformADAdminCredential {

<#
.SYNOPSIS
Retrieves credential that can be used for administrating the domain
.DESCRIPTION
Using configuration returned from Get-ModPlatformADConfig, this function
optionally assumes a role to access a secret containing the password of the
domain join username. EC2 requires permissions to join the given role,
a SSM parameter containing account IDs, and the aws cli.
.PARAMETER ModPlatformADConfig
HashTable as returned from Get-ModPlatformADConfig function
.PARAMETER ModPlatformADSecret
Optional PSCustomObject containing secrets as returned from Get-ModPlatformADSecret
.EXAMPLE
$ADConfig = Get-ModPlatformADConfig
$ADCredential = Get-ModPlatformADAdminCredential $ADConfig
.OUTPUTS
PSCredentialObject
#>

[CmdletBinding()]
param (
[Parameter(Mandatory=$true)][hashtable]$ModPlatformADConfig,
[PSCustomObject]$ModPlatformADSecret
)

$ErrorActionPreference = "Stop"

if ($ModPlatformADSecret -eq $null) {
$ModPlatformADSecret = Get-ModPlatformADSecret -ModPlatformADConfig $ModPlatformADConfig
}
$DomainNameNetbios = $ModPlatformADConfig.DomainNameNetbios
$DomainAdminUsername = $ModPlatformADConfig.DomainAdminUsername
$DomainAdminPassword = $ModPlatformADSecret.$DomainAdminUsername
if (-not $DomainAdminPassword) {
Write-Error "Password secret does not contain domain admin username ${DomainAdminUsername}"
}
$DomainAdminPasswordSecureString = ConvertTo-SecureString $DomainAdminPassword -AsPlainText -Force
New-Object System.Management.Automation.PSCredential ("$DomainNameNetbios\$DomainAdminUsername", $DomainAdminPasswordSecureString)
}

function Get-ModPlatformADSafeModeAdministratorPassword {

<#
.SYNOPSIS
Retrieves credential that can be used for administrating the domain
.DESCRIPTION
Using configuration returned from Get-ModPlatformADConfig, this function
optionally assumes a role to access a secret containing the password of the
domain join username. EC2 requires permissions to join the given role,
a SSM parameter containing account IDs, and the aws cli.
.PARAMETER ModPlatformADConfig
HashTable as returned from Get-ModPlatformADConfig function
.PARAMETER ModPlatformADSecret
Optional PSCustomObject containing secrets as returned from Get-ModPlatformADSecret
.EXAMPLE
$ADConfig = Get-ModPlatformADConfig
$ADCredential = Get-ModPlatformADSafeModeAdministratorPassword $ADConfig
.OUTPUTS
Secure-String
#>

[CmdletBinding()]
param (
[Parameter(Mandatory=$true)][hashtable]$ModPlatformADConfig,
[PSCustomObject]$ModPlatformADSecret
)

$ErrorActionPreference = "Stop"

if ($ModPlatformADSecret -eq $null) {
$ModPlatformADSecret = Get-ModPlatformADSecret -ModPlatformADConfig $ModPlatformADConfig
}
$DomainNameNetbios = $ModPlatformADConfig.DomainNameNetbios
$DomainAdminUsername = $ModPlatformADConfig.DomainAdminUsername
$SafeModeAdministratorPassword = $ModPlatformADSecret.SafeModeAdministratorPassword
if (-not $SafeModeAdministratorPassword) {
Write-Error "Password secret does not contain domain admin username ${SafeModeAdministratorPassword}"
}
ConvertTo-SecureString $SafeModeAdministratorPassword -AsPlainText -Force
}

Export-ModuleMember -Function Get-ModPlatformADSecret
Export-ModuleMember -Function Get-ModPlatformADJoinCredential
Export-ModuleMember -Function Get-ModPlatformADAdminCredential
Export-ModuleMember -Function Get-ModPlatformADSafeModeAdministratorPassword
10 changes: 5 additions & 5 deletions powershell/Modules/ModPlatformAD/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ Provides Active Directory related functions
For example,

```
Get-ModPlatformADConfig - derive AD config from environment
Get-ModPlatformADCredential - lookup domain join secret
Rename-ModPlatformADComputer - rename computer
Add-ModPlatformADComputer - add to domain
Remove-ModPlatformADComputer - remove from domain
Get-ModPlatformADConfig - derive AD config from environment
Get-ModPlatformADJoinCredential - lookup domain join secret
Rename-ModPlatformADComputer - rename computer
Add-ModPlatformADComputer - add to domain
Remove-ModPlatformADComputer - remove from domain
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<#
.SYNOPSIS
Install a Domain Controller from scratch
.DESCRIPTION
By default the script derives the hostname from the Name tag. Or specify NewHostname parameter.
By default derives the AD configuration from EC2 tags (environment-name or domain-name), or specify DomainNameFQDN parameter.
EC2 requires permissions to get tags and the aws cli.
Exits with 3010 if reboot required and script requires re-running. For use in SSM docs
.PARAMETER DomainNameFQDN
Optionally specify the FQDN of the domain name to join
.EXAMPLE
Join-ModPlatformAD
#>

[CmdletBinding()]
param (
[string]$NewHostname = "tag:Name",
[string]$DomainNameFQDN
)

Import-Module ModPlatformAD -Force

$ErrorActionPreference = "Stop"

$ADConfig = Get-ModPlatformADConfig -DomainNameFQDN $DomainNameFQDN
$ADSecret = Get-ModPlatformADSecret -ModPlatformADConfig $ADConfig
$ADJoinCredential = Get-ModPlatformADJoinCredential -ModPlatformADConfig $ADConfig -ModPlatformADSecret $ADSecret
$Renamed = Rename-ModPlatformADComputer -NewHostname $NewHostname -ModPlatformADCredential $ADJoinCredential
if ($Renamed) {
Write-Output "Renamed computer to ${Renamed}"
Exit 3010 # triggers reboot if running from SSM Doc
}
if (Add-ModPlatformADComputer -ModPlatformADConfig $ADConfig -ModPlatformADCredential $ADJoinCredential) {
Exit 3010 # triggers reboot if running from SSM Doc
}

$DFSReplicationStatus = Get-Service "DFS Replication" -ErrorAction SilentlyContinue
if ($DFSReplicationStatus -eq $null) {
$ADAdminCredential = Get-ModPlatformADAdminCredential -ModPlatformADConfig $ADConfig -ModPlatformADSecret $ADSecret
$ADSafeModeAdministratorPassword = Get-ModPlatformADSafeModeAdministratorPassword -ModPlatformADConfig $ADConfig -ModPlatformADSecret $ADSecret
Install-WindowsFeature -Name AD-Domain-Services -IncludeAllSubFeature -IncludeManagementTools
Install-ADDSDomainController -DomainName $ADConfig.DomainNameFQDN -InstallDns:$true -Credential $ADAdminCredential -SafeModeAdministratorPassword $ADSafeModeAdministratorPassword -NoRebootOnCompletion -Force
Exit 3010 # triggers reboot if running from SSM Doc
} else {
$Services='DNS','DFS Replication','Intersite Messaging','Kerberos Key Distribution Center','NetLogon',Active Directory Domain Services
ForEach ($Service in $Services) {Get-Service $Service | Select-Object Name, Status}
}
2 changes: 1 addition & 1 deletion powershell/Scripts/ModPlatformAD/Join-ModPlatformAD.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Import-Module ModPlatformAD -Force
$ErrorActionPreference = "Stop"

$ADConfig = Get-ModPlatformADConfig -DomainNameFQDN $DomainNameFQDN
$ADCredential = Get-ModPlatformADCredential -ModPlatformADConfig $ADConfig
$ADCredential = Get-ModPlatformADJoinCredential -ModPlatformADConfig $ADConfig
$Renamed = Rename-ModPlatformADComputer -NewHostname $NewHostname -ModPlatformADCredential $ADCredential
if ($Renamed) {
Write-Output "Renamed computer to ${Renamed}"
Expand Down
2 changes: 1 addition & 1 deletion powershell/Scripts/ModPlatformAD/Leave-ModPlatformAD.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Import-Module ModPlatformAD -Force
$ErrorActionPreference = "Stop"

$ADConfig = Get-ModPlatformADConfig -DomainNameFQDN $DomainNameFQDN
$ADCredential = Get-ModPlatformADCredential -ModPlatformADConfig $ADConfig
$ADCredential = Get-ModPlatformADJoinCredential -ModPlatformADConfig $ADConfig
if (Remove-ModPlatformADComputer -ModPlatformADCredential $ADCredential) {
Exit 3010 # triggers reboot if running from SSM Doc
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<#
.SYNOPSIS
Install a Domain Controller from scratch
.DESCRIPTION
By default the script derives the hostname from the Name tag. Or specify NewHostname parameter.
By default derives the AD configuration from EC2 tags (environment-name or domain-name), or specify DomainNameFQDN parameter.
EC2 requires permissions to get tags and the aws cli.
Exits with 3010 if reboot required and script requires re-running. For use in SSM docs
Example retrieval of local admin password:
aws ssm get-parameter --name ec2-user_pem --with-decryption --query Parameter.Value --output text --profile hmpps-domain-services-test > tmp.key
aws ec2 get-password-data --instance-id i-0aa02abedd9572e19 --profile core-shared-services-production-ad --priv-launch-key tmp.key
rm tmp.key
.PARAMETER DomainNameFQDN
Optionally specify the FQDN of the domain name to join
.EXAMPLE
Join-ModPlatformAD
#>

[CmdletBinding()]
param (
[string]$NewHostname = "tag:Name",
[string]$DomainNameFQDN
)

Import-Module ModPlatformAD -Force

$ErrorActionPreference = "Stop"

$ADConfig = Get-ModPlatformADConfig -DomainNameFQDN $DomainNameFQDN
$ADSecret = Get-ModPlatformADSecret -ModPlatformADConfig $ADConfig

$DFSReplicationStatus = Get-Service "DFS Replication" -ErrorAction SilentlyContinue
if ($DFSReplicationStatus -ne $null) {
$ADAdminCredential = Get-ModPlatformADAdminCredential -ModPlatformADConfig $ADConfig -ModPlatformADSecret $ADSecret
$ADSafeModeAdministratorPassword = Get-ModPlatformADSafeModeAdministratorPassword -ModPlatformADConfig $ADConfig -ModPlatformADSecret $ADSecret
Uninstall-ADDSDomainController -Credential $ADAdminCredential -NoRebootOnCompletion -Force
Exit 3010 # triggers reboot if running from SSM Doc
}
6 changes: 1 addition & 5 deletions powershell/Scripts/UserDataScripts/DomainController.ps1
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
$ErrorActionPreference = "Stop"

. ../ModPlatformAD/Join-ModPlatformAD.ps1
. ../ModPlatformAD/Install-ModPlatformADDomainController.ps1
if ($LASTEXITCODE -ne 0) {
Exit $LASTEXITCODE
}

Install-WindowsFeature AD-Domain-Services -IncludeAllSubFeature -IncludeManagementTools

0 comments on commit 2edb9e6

Please sign in to comment.