ADLAB PowerShell source file: buildup-ca.ps1

(C) Ondrej Sevecek, 2019 - www.sevecek.com, ondrej@sevecek.com



#$global:outClass = 'main'

$libDir = Split-Path -parent $MyInvocation.MyCommand.Definition
& "$libDir\lib-common.ps1" -defaultConfig -rootDir $libDir -outFile caLib
& "$libDir\lib-modifyActions.ps1"
& "$libDir\lib-buildup.ps1"

$vmName = $args[0]

DBG ("AD CS Installation library")
Redirect-TempToOutput
Load-VMConfig

Find-MarkedVolumes

$appTag = 'ca'
$appConfig = $vmConfig.$appTag
$firstAppHost = Get-FirstAppHostInInstance $appTag $appConfig.instance 'waitParams'
$firstAppHostInInstance = Check-FirstAppHostInInstance $appTag $appConfig.instance


#====================
#====================



#=========================
DBG ("Copying CAPOLICY.INF")
Copy-Item -Path "$global:rootDir\AD-CS\capolicy.inf" -Destination "$env:SystemRoot" -Force -EV er -EA SilentlyContinue
DBGER $MyInvocation.MyCommand.Name $er


#=========================
DBG ("Going to install AD CS with: {0} | CN={1},{2} | {3} | {4} | {5} | {6}" -f $appConfig.pkitype, $appConfig.instance, $appConfig.dn, $appConfig.provider, $appConfig.algo, $appConfig.keyLength, $appConfig.validity)

if ($thisOSVersion -like '5.2.*') {

  DBG ("Doing 5.2 installation of Certificate Services by using SYSOCMGR.")

  $sysocmgrFile = Get-DataFileApp 'certsrvSetup' $null '.ini'
  # Note: CADistinguishedName, nor other variants such as Locality, State, Country etc. are supported on 2k3
  $argReplacement = 'CAType${0}|Name$"{1}"|CADistinguishedName$"{2}"|CSPProvider$"{3}"|HashAlgorithm${4}|KeyLength${5}|ValidityPeriod${6}' -f (Escape-ForMultiValue $appConfig.pkitype, $appConfig.instance, $appConfig.dn, $appConfig.provider, $appConfig.algo, $appConfig.keyLength, $appConfig.validity)
  Replace-ArgumentsInFile "$global:rootDir\AD-CS\install-CertSrv.ini" $argReplacement $sysocmgrFile ASCII

  Run-Process "sysocmgr" "/i:`"$env:SystemRoot\inf\sysoc.inf`" /u:`"$sysocmgrFile`" /r /q"

} elseif ($global:thisOSVersionNumber -ge 6.2) {

  DBG ("Doing 6.2+ installation of AD CS by using the powershell cmdlet")

  Install-AdcsCertificationAuthority -AllowAdministratorInteraction:$false -CACommonName $appConfig.instance -CADistinguishedNameSuffix $appConfig.dn -CAType ('{0}CA' -f $appConfig.pkitype) -CryptoProviderName $appConfig.provider -HashAlgorithmName $appConfig.algo -IgnoreUnicode:$false -KeyLength $appConfig.keyLength -OverwriteExistingCAinDS -OverwriteExistingDatabase -OverwriteExistingKey:$false -ValidityPeriod Years -ValidityPeriodUnits $appConfig.validity -Confirm:$false -EV er -EA SilentlyContinue
  DBGER $MyInvocation.MyCommand.Name $er

} else {

  DBG ("Doing 6.0 and 6.1 installation of AD CS by using .VBS script.")

  switch ($appConfig.pkitype)
  {
    "EnterpriseRoot" { $typeSwitch = '/IE' }
    "StandaloneRoot" { $typeSwitch = '/IS' }
    "EnterpriseSubordinate" { $typeSwitch = '/IF' }
    "StandaloneSubordinate" { $typeSwitch = '/IT' }
    default { $typeSwitch = '/IE' }
  }

  $scriptParams = "//NoLogo `"$global:rootDir\AD-CS\install-AD-CS.vbs`" /SP `"$($appConfig.provider)`" /SK `"$($appConfig.keyLength)`" /SA `"$($appConfig.algo)`" /SN `"$($appConfig.instance)`" /DN `"$($appConfig.dn)`" /SV `"$($appConfig.validity)`" $typeSwitch"
  DBG ('Will install the CA with the following script: {0}' -f $scriptParams)

#  if ($global:thisOSVersionNumber -eq 6.0) { Read-Host DOITMANUALLY }
  
  if ($global:thisOSVersionNumber -eq 6.0) {

    # On Windows 2008 RTM there is the hang/deadlock if we assume the output to come back - it hangs on the g_oCASetup.Install() call
    Run-Process 'cscript' $scriptParams -doNotRedirOut $true
  
  } else {

    Run-Process 'cscript' $scriptParams
  }
}


$caBaseRegKey = 'HKLM:\System\CurrentControlSet\Services\CertSvc\Configuration\{0}' -f $appConfig.instance
DBG ('CA base registry key: {0}' -f $caBaseRegKey)


#=========================
DBG ("Default CA config")

DBG ("Setting default CERSRV registry parameters")
Run-Process 'CERTUTIL' '-setreg Policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2'
Run-Process 'CERTUTIL' '-setreg CA\ValidityPeriodUnits 7'
Run-Process 'CERTUTIL' '-setreg Policy\EditFlags +EDITF_ENABLELDAPREFERRALS'

if ($global:thisOSVersionNumber -ge 6.1) {

  Run-Process 'CERTUTIL' '-setreg DBFlags +DBFLAGS_ENABLEVOLATILEREQUESTS'
}

Run-Process 'CERTUTIL' '-setreg CA\AuditFilter 127'
Enable-Auditing 'Object Access' 'Certification Services' -verify


DBG ('Should we change the CNGHashAlgorithm: {0} | {1}' -f (Is-ValidString $appConfig.cngHash), $appConfig.cngHash)
if (Is-ValidString $appConfig.cngHash) {

  DBGSTART
  [string] $currentCngHash = (Get-ItemProperty -Path (Join-Path $caBaseRegKey CSP) -Name CNGHashAlgorithm).CNGHashAlgorithm
  DBGER $MyInvocation.MyCommand.Name $error
  DBGEND

  DBG ('Current CNG hash algo: {0}' -f $currentCngHash)
  DBGIF $MyInvocation.MyCommand.Name { Is-Null $currentCngHash }

  DBG ('Changing CNG hash algo: {0} | {1}' -f $currentCngHash, $appConfig.cngHash)
  DBGSTART
  Set-ItemProperty -Path (Join-Path $caBaseRegKey CSP) -Name CNGHashAlgorithm -Value $appConfig.cngHash
  DBGER $MyInvocation.MyCommand.Name $error
  DBGEND
}


if ($thisOSVersion -like '6.0.*') {
  
  # Note: this shity OS doesn't allow Administrators full control to the registry keys
  #       TrustedInstaller is owner and Administrators are granted only Read permission
  
  Take-RegOwnership 'Software\Classes\AppId\{D99E6E74-FC88-11D0-B498-00A0C90312F3}'
  Set-RegPermissions 'Software\Classes\AppId\{D99E6E74-FC88-11D0-B498-00A0C90312F3}' "Administrators"
}


DBG ('Adjust static DCOM port: {0}' -f (Is-ValidString $appConfig.staticPort))
if (Is-ValidString $appConfig.staticPort) {

  Run-Process 'CERTUTIL' '-setreg CA\InterfaceFlags +IF_NORPCICERTREQUEST'
  Set-RegistryValue 'HKLM:\Software\Classes\AppID\{D99E6E74-FC88-11D0-B498-00A0C90312F3}' EndPoints ('ncacn_ip_tcp,0,{0}' -f $appConfig.staticPort) MultiString
}


# This can only be set if all the clients are at least Vista/2008
#Run-Process 'CERTUTIL' '-setreg CA\CSP\AlternateSignatureAlgorithm 1'
#Run-Process 'CERTUTIL' '-setreg CA\EncryptionCSP\CNGEncryptionAlgorithm AES'
#Run-Process 'CERTUTIL' '-setreg CA\EncryptionCSP\SymmetricKeySize 128'
#Run-Process 'CERTUTIL' '-setreg CA\EncryptionCSP\CNGPublicKeyAlorithm ECDH_P256'
#Run-Process 'CERTUTIL' '-setreg CA\EncryptionCSP\KeySize 256'


if (($thisOSVersionNumber -ge 6) -and ($appConfig.pkitype -like 'Standalone*')) {

  # Note: this is not necessary for enterprise CAs that use certificate templates
  #       The logic is that the CA checks the template OR the EditFlags for presence of this attribute
  #       and if at least one says to omit CRL/AIA paths, it does as instructed
  Run-Process 'CERTUTIL' '-setreg Policy\EditFlags +EDITF_ENABLEOCSPREVNOCHECK'
}


Set-RegistrySD ($caBaseRegKey) 'Security' ('O:BAG:BAD:AI(A;OICI;0x200;;;AU)(A;OICI;CC;;;{0}\{1})(A;OICI;DC;;;{0}\{1})S:(AU;SAFA;0xFFFF;;;WD)(AU;SAFA;0xFFFF;;;AN)' -f $appConfig.app.iDomain, $appConfig.app.aGroup)

[System.Collections.ArrayList] $deList = @()
$rootDSE = Get-DE 'RootDSE' ([ref] $deList)
$configDN = GDES $rootDSE configurationNamingContext

DBG ("Importing Autoenrollment rights GUID")
# Note: you cannot use #configurationNamingContext with Windows 2003 LDIFDE
Run-Process 'LDIFDE' "-i -f `"$global:rootDir\AD-CS\autoenrollment-rights-guid.ldf`" -c `"cn=configuration,dc=x`" `"$configDN`"" -ignoreExitCodes @(5010)


#====================
DBG ("Importing OIDs")
Run-Process 'LDIFDE' "-i -f `"$global:rootDir\AD-CS\cert-templates-oids.ldf`" -c `"cn=configuration,dc=x`" `"$configDN`""



#====================
DBG ('Updating macros in templates.LDF')
$templatesLDF = Get-DataFileApp 'templates' $null '.ldf'
$argReplacement = 'namePrefix${0}' -f (Escape-ForMultiValue $appConfig.templateNamePrefix)
Replace-ArgumentsInFile (Join-Path $global:rootDir 'AD-CS\templates.ldf') $argReplacement $templatesLDF ASCII

DBG ('Importing templates')
Run-Process 'LDIFDE' ('-i -f "{0}" -c "cn=configuration,dc=x" "{1}"' -f $templatesLDF, $configDN)



#====================
DBG ("Going to set CRL and AIA paths")
$certEnrollPath = "$env:SystemRoot\system32\CertSrv\CertEnroll"

#$publicDNS = Strip-ValueFlags ([string] $appConfig.SelectSingleNode('./fs[@appTag="target"]/@dns').'#text')
[string] $publicDNS =  Get-ServiceOrMachineDnsFQDNs $appConfig -assertSingleName $true
[string] $virtDir = Strip-ValueFlags ([string] $appConfig.SelectSingleNode('./fs[@appTag="target"]/@iis').'#text')

if (Is-ValidString $publicDNS) {

  DBG ("Will publish on public DNS: {0} / {1}" -f $publicDNS, $virtDir)
  $crlPublicDNSURL = '6:http://{0}/{1}/%3%8%9.crl\n' -f $publicDNS, $virtDir
  $aiaPublicDNSURL = '2:http://{0}/{1}/%3%4.crt\n' -f $publicDNS, $virtDir

} else {

  DBG ('No public DNS for CRL')
}

if (-not (Parse-BoolSafe $appConfig.noLDAPpaths)) {

  DBG ('Should add LDAP paths for CRL')
  $ldapCRL = '79:ldap:///CN=%7%8,CN=%2,CN=CDP,CN=Public Key Services,CN=Services,%6%10\n'
  $ldapAIA = '3:ldap:///CN=%7,CN=AIA,CN=Public Key Services,CN=Services,%6%11\n'

} else {

  DBG ('No LDAP paths for CRL')
  $ldapCRL = ''
  $ldapAIA = ''
}

Run-Process 'CERTUTIL' ('-setreg CA\CRLPublicationURLs "65:{0}\%3%8%9.crl\n{1}{2}"' -f  $certEnrollPath, $crlPublicDNSURL, $ldapCRL)
Run-Process 'CERTUTIL' ('-setreg CA\CACertPublicationURLs "1:{0}\%3%4.crt\n{1}{2}"' -f $certEnrollPath, $aiaPublicDNSURL, $ldapAIA)

#DBG ("Copying the original CA .CRT name")
#Rename-Item -Path ("$env:SystemRoot\System32\CertSrv\CertEnroll\{0}.{1}_{2}.crt" -f $thisComputerHost, $thisComputerDomain, $appConfig.instance) -NewName ('{0}.crt' -f $appConfig.instance) -EV er -EA SilentlyContinue
#DBGSTART
#$cmdOutput = & "$global:rootDir\AD-CS\sevecek-publish-AIA-CDP.ps1" "$env:SystemRoot\System32\CertSrv\CertEnroll" $appConfig.instance
#DBGER $MyInvocation.MyCommand.Name $er
#DBG ('Copy AIA .CRT result: {0}' -f ($cmdOutput | Out-String))


DBG ('Sometimes the CertSvc is not yet fully initialized, so give it some time')

Wait-Service CertSvc
Wait-CertSvc



if ($global:thisOSVersionNumber -ge 6) {

  DBG ("Setting AD CS to Delayed AutoStart on Win6.x")
  Run-Process 'SC' 'config CertSvc start= delayed-auto'
}



#=========================
#=========================
DBG ("Delegating CA forest administration to: {0}" -f $appConfig.app.aGroup)

$pkiDN = 'CN=Public Key Services,CN=Services,{0}' -f $configDN

$templatesDN = 'CN=Certificate Templates,{0}' -f $pkiDN
$oidsDN = 'CN=OID,{0}' -f $pkiDN
$aiaDN = 'CN=AIA,{0}' -f $pkiDN
$cdpDN = 'CN={1},CN=CDP,{0}' -f $pkiDN, $global:thisComputerNetBIOS
$esDN = 'CN=Enrollment Services,{0}' -f $pkiDN

# /P:Y - mark protected
# /N - replace ACL instead of editing
# /I:T - inherit to all childs
# /G - grant
# /R - revoke

$caMachineLogin = Get-SAMLogin ('{0}$' -f $global:thisComputerNetBIOS) $global:thisComputerDomain

Run-Process 'DSACLS' ('"{0}" /P:Y /N /G "{1}:GA" "SYSTEM:GA" "Authenticated Users:GR"' -f $templatesDN, $appConfig.app.aGroup)
Run-Process 'DSACLS' ('"{0}" /P:Y /N /I:T /G "{1}:GA" "SYSTEM:GA" "Authenticated Users:GR"' -f $oidsDN, $appConfig.app.aGroup)
Run-Process 'DSACLS' ('"{0}" /P:Y /N /I:T /G "{1}:GA" "SYSTEM:GA" "Authenticated Users:GR"' -f $aiaDN, $appConfig.app.aGroup)
Run-Process 'DSACLS' ('"{0}" /P:Y /N /I:T /G "{1}:GA" "SYSTEM:GA" "Authenticated Users:GR" "{2}:GA"' -f $cdpDN, $appConfig.app.aGroup, $caMachineLogin)
Run-Process 'DSACLS' ('"{0}" /P:Y /N /I:T /G "{1}:GA" "SYSTEM:GA" "Authenticated Users:GR"' -f $esDN, $appConfig.app.aGroup)


#=========================
DBG ("Searching for certificate TEMPLATES")
$searchRes = Get-ADSearch $templatesDN 'oneLevel' '(objectClass=pKICertificateTemplate)'

if ($searchRes.found) {
  
  #$searchRes[1] = $searchRes[0].FindAll()
  $searchRes.result | % { 

    $oneDN = GSRS $_ distinguishedName
    DBG ("Securing template for default PKI admins group: {0}" -f $oneDN)
    Run-Process 'DSACLS' ('"{0}" /P:Y /R "Enterprise Admins" "Domain Admins" "SYSTEM" /G "Authenticated Users:GR" "{1}:GWWOWD"' -f $oneDN, $appConfig.app.aGroup)
  }
}

Dispose-ADSearch ([ref] $searchRes)

#=========================
DBG ("Searching for OIDs")
$searchRes = Get-ADSearch $oidsDN 'oneLevel' '(objectClass=msPKI-Enterprise-OID)'
#DBGIF $MyInvocation.MyCommand.Name { Is-Null $searchRes[0] }

if ($searchRes.found) {
  
  #$searchRes[1] = $searchRes[0].FindAll()
  $searchRes.result | % { 

    $oneDN = GSRS $_ distinguishedName
    DBG ("Securing OID: {0}" -f $oneDN)
    Run-Process 'DSACLS' ('"{0}" /P:Y /R "Enterprise Admins" "Domain Admins" /G "Authenticated Users:GR" "{1}:GA"' -f $oneDN, $appConfig.app.aGroup)
  }
}

Dispose-ADSearch ([ref] $searchRes)


Dispose-List ([ref] $deList)



#=========================
DBG ("Finishing AD CS installation by cleaning up and restarting the service and publishing CRL")

Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Cryptography\CertificateTemplateCache' -Name 'Timestamp' -EA SilentlyContinue -EV er
DBGER $MyInvocation.MyCommand.Name $er

Remove-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Cryptography\CertificateTemplateCache' -Name 'Timestamp' -EA SilentlyContinue -EV er
DBGER $MyInvocation.MyCommand.Name $er

Run-Process 'certutil' '-silent -repairstore my *'

# Note: this produces unnecessary "Access denied" errors on some Microsoft root CAs which do not have private keys anyway
#Run-Process 'certutil' '-silent -repairstore root *'

Restart-Service -Name CertSvc -EV er -EA SilentlyContinue
DBGER $MyInvocation.MyCommand.Name $er

Wait-Service CertSvc
Wait-CertSvc

Run-Process 'CERTUTIL' '-crl'


DBG ("Enabling default certificate templates")
Run-Process 'CERTUTIL' '-SetCATemplates KerberosAuthentication'


$publishingScript = 'sevecek-PKI-publish-AIA-CDP'


#=========================
$cdpSvcNode = $appConfig.SelectSingleNode('./svc[@appTag="jobs"]')
#$cdpFsJobNode = $appConfig.SelectSingleNode('./fs[@instance="local" and @appTag="jobs"]')
$cdpFsShareNode = $appConfig.SelectSingleNode('./fs[@appTag="target"]')
#DBG ('Install CRL/CRT/AIA/CDP publishing script: {0}' -f ((Is-ValidString $cdpSvcNode.login) -and (Is-ValidString $cdpFsJobNode.instance) -and (Is-ValidString $cdpFsShareNode.instance)))
DBG ('Install CRL/CRT/AIA/CDP publishing script: {0}' -f ((Is-ValidString $cdpSvcNode.login) -and (Is-ValidString $cdpFsShareNode.instance)))

#if ((Is-ValidString $cdpSvcNode.login) -and (Is-ValidString $cdpFsJobNode.instance) -and (Is-ValidString $cdpFsShareNode.instance)) {
if ((Is-ValidString $cdpSvcNode.login) -and (Is-ValidString $cdpFsShareNode.instance)) {

  $targetFSPath = Resolve-ClientFsPath $cdpFsShareNode
  
  if ($targetFSPath -like '\\*') {

    $targetShareTokens = ($targetFSPath).Split('\')

    #DBG ('Prepare CDP/AIA publishing script to a shared folder: {0}' -f $targetFSPath)
    #$cdpScriptTemp = Get-DataFileApp $publishingScript $null '.bat'
    $argReplacement = 'caName${0}|fsServer${1}|fsShare${2}|publishUser${3}@{4}|publishPwd${5}' -f (Escape-ForMultiValue $appConfig.instance, $targetShareTokens[2], $targetShareTokens[3], $cdpSvcNode.login, $cdpSvcNode.domain, $cdpSvcNode.pwd)
    #Replace-ArgumentsInFile "$global:rootDir\AD-CS\$publishingScript.bat" $argReplacement $cdpScriptTemp ASCII
  
  } else {

    #DBG ('Prepare CDP/AIA publishing script to publish to a local folder: {0}' -f $targetFSPath)
    #$cdpScriptTemp = Get-DataFileApp $publishingScript $null '.bat'
    $argReplacement = 'caName${0}|fsServer${1}|fsShare${2}|publishUser${3}@{4}|publishPwd${5}' -f (Escape-ForMultiValue $appConfig.instance, $null, $targetFSPath, $cdpSvcNode.login, $cdpSvcNode.domain, $cdpSvcNode.pwd)
    #Replace-ArgumentsInFile "$global:rootDir\AD-CS\$publishingScript.bat" $argReplacement $cdpScriptTemp ASCII
  }


<#
  $cdpScript = Join-Path (Resolve-ClientFsPath $cdpFsJobNode) "$publishingScript.bat"

  DBG ('Copy CDP script: {0} | {1}' -f $cdpScriptTemp, $cdpScript)
  Copy-Item -Path $cdpScriptTemp -Destination $cdpScript -Force -EV er -EA SilentlyContinue | Out-Null
  DBGER $MyInvocation.MyCommand.Name $er 

  
  $aiaRenameScriptSrc = "$global:rootDir\AD-CS\$publishingScript.ps1"
  $aiaRenameScriptDst = Join-Path (Resolve-ClientFsPath $cdpFsJobNode) "$publishingScript.ps1"

  DBG ('Copy AIA script: {0} | {1}' -f $aiaRenameScriptSrc, $aiaRenameScriptDst)
  Copy-Item -Path $aiaRenameScriptSrc -Destination $aiaRenameScriptDst -Force -EV er -EA SilentlyContinue | Out-Null
  DBGER $MyInvocation.MyCommand.Name $er 
#>
  $cdpScript = Install-ScheduledJob -vmConfig $vmConfig -appTag ca -sourceScriptName $publishingScript -sourceFolder AD-CS -argReplacement $argReplacement

  
  if ($global:thisOSVersionNumber -ge 6) {

    DBG ('Build scheduled task for event 4872')
    Schedule-Task $publishingScript $cdpScript 'NT AUTHORITY\System' $null 'ONEVENT /EC Security /MO "*[System/EventID=4872 or System/EventID=4895]"' $true
  
  } else {

    Schedule-Task $publishingScript $cdpScript $null $null 'SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA "Win32_NTLogEvent" AND TargetInstance.LogFile = "Security" AND (TargetInstance.EventCode = "776" OR TargetInstance.EventCode = "784")' $true
  }
}



DBG ('Finally publish CRL again to test the copy-script execution')
# Note: the script does not wait for the FS instance to finish
#       so don't rely on this too much
Run-Process 'CERTUTIL' '-crl'



#=========================
# Just a matter of debugging info obtained

if ($global:thisOSVersionNumber -ge 6.1) {

  Run-Process 'CERTUTIL' '-ADTemplate'

} else {

  Run-Process 'CERTUTIL' '-Template'
}



#=========================
#=========================


$certTemplApps = $xmlConfig.SelectNodes('./VMs/MACHINE[vm/@do="true"]//cert[translate(@instance,"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz")="{0}"]' -f $appConfig.instance.ToLower())
DBG ('Application requested certificate templates: {0}' -f (Get-CountSafe $certTemplApps))

foreach ($oneCertApp in $certTemplApps) {

  DBG ('Application asks for a template: {0} | {1}' -f $oneCertApp.template, $oneCertApp.who)

  $oneAppTemplate = $oneCertApp.template.Replace('$namePrefix$', $appConfig.templateNamePrefix)

  DBG ('Enabling certificate template: {0}' -f $oneAppTemplate)
  Run-Process 'CERTUTIL' ('-SetCATemplates +{0}' -f $oneAppTemplate)

  $appTemplateDN = 'CN={0},{1}' -f $oneAppTemplate, $templatesDN

  foreach ($oneWho in (Split-MultiValue $oneCertApp.who)) {

    DBG ('Ellow Enroll permission for one: {0}' -f $oneWho)

    $appEnrolleeBase = Strip-ValueFlags $oneWho
    
    if ($appEnrolleeBase -eq $global:emptyValueMarker) {
    
      $appEnrollee = Get-MachineSAMLogin $oneCertApp
    
    } else {

      $appEnrollee = Get-SAMLogin $appEnrolleeBase
    }

    DBGIF ('Did not find enrollee account: {0}' -f $oneWho) { Is-EmptyString $appEnrollee }

    if (Is-ValidString $appEnrollee) {

      #DBGSTART
      #$appEnrolleSID = (New-Object Security.Principal.NTAccount $appEnrollee).Translate([Security.Principal.SecurityIdentifier]).Value
      #DBGER $MyInvocation.MyCommand.Name $Error
      #DBGEND

      #DBG ('Secure template for enrollee: {0} | {1}' -f $appEnrollee, $appEnrolleSID)
      #DBGIF $MyInvocation.MyCommand.Name { Is-EmptyString $appEnrolleSID }

      Assert-AccountExists $appEnrollee 'Secure template for enrollee'
      Run-Process 'DSACLS' ('"{0}" /G "{1}:CA;Enroll"' -f $appTemplateDN, $appEnrollee)

      if (Has-ValueFlags $oneWho 'A') {

        Run-Process 'DSACLS' ('"{0}" /G "{1}:CA;AutoEnrollment"' -f $appTemplateDN, $appEnrollee)
      }
    }
  }
}



# SIG # Begin signature block
# MIIc/QYJKoZIhvcNAQcCoIIc7jCCHOoCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBHI3u+5iig3Crv
# 8NewbFK5UrRppDWTKyaguxLv8rk4I6CCGAQwggTlMIIDzaADAgECAhA5vUKe0oFu
# utW8yQO0umXnMA0GCSqGSIb3DQEBCwUAMHUxCzAJBgNVBAYTAklMMRYwFAYDVQQK
# Ew1TdGFydENvbSBMdGQuMSkwJwYDVQQLEyBTdGFydENvbSBDZXJ0aWZpY2F0aW9u
# IEF1dGhvcml0eTEjMCEGA1UEAxMaU3RhcnRDb20gQ2xhc3MgMiBPYmplY3QgQ0Ew
# HhcNMTYxMjAxMTU1MTEzWhcNMTgxMjAxMTU1MTEzWjBRMQswCQYDVQQGEwJDWjEa
# MBgGA1UECAwRSmlob21vcmF2c2t5IEtyYWoxDTALBgNVBAcMBEJybm8xFzAVBgNV
# BAMMDk9uZHJlaiBTZXZlY2VrMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
# AQEAr9E9hNj06bash9JX97kpsqK9Z/ciOBC6trI4nvlW9CPwhKBTb5wArhxLYZBG
# 9jWPWrdy1nL/cm5qMqBb/mogYwMwvEYWMvsIOOVn6HD9lVhNAovD6PHz0ziBBKIs
# zXTjyUPQaoIlIELovz967m78HJdUZJGxqhluAsS9o9/fEzA7XXUhUuqRKsetuZV/
# Asfh5sOveeoRsbeW4daTWvtz3TJuULL0w43LNVYJkd6LL8cegvLPVZUe1N7skvid
# EvntdlowQsJlqFdrH3SGKIPKA6ObcY8SZWkEQSbVBF8Kum1UT+jN0gm+84FwOg5W
# qKx+VvTK2ljVWnPrCD0Zzu2oIQIDAQABo4IBkzCCAY8wDgYDVR0PAQH/BAQDAgeA
# MBMGA1UdJQQMMAoGCCsGAQUFBwMDMAkGA1UdEwQCMAAwHQYDVR0OBBYEFG2vSo3N
# hQWILeUs0oN9XzHTejcfMB8GA1UdIwQYMBaAFD5ik5rXxxnuPo9JEIVVFSDjlIQc
# MG0GCCsGAQUFBwEBBGEwXzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Auc3RhcnRz
# c2wuY29tMDcGCCsGAQUFBzAChitodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0
# cy9zY2EuY29kZTIuY3J0MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwuc3Rh
# cnRzc2wuY29tL3NjYS1jb2RlMi5jcmwwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5z
# dGFydHNzbC5jb20vMFEGA1UdIARKMEgwCAYGZ4EMAQQBMDwGCysGAQQBgbU3AQIF
# MC0wKwYIKwYBBQUHAgEWH2h0dHBzOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kw
# DQYJKoZIhvcNAQELBQADggEBAJuRiEvHtIYSpsmMkPhTz4QOOShN3p5KWdf8vm71
# A33CR9fds10d8D2B2aE+vjmHJ69GY0bbfg5oZY2Lsq2euL7Da5/hS8+6T3MEtD4h
# njfHV7mxmoSfFuy/KDipoV6uwhI+ksqchXYdUH+5uCQO0MOO8ITjAgzUQsnZ4UIB
# HBGeP+e+3ljxSYSXWdPIrgxdR971P/HhWSVfKNlmBgEKMQM5Jy0aAd4jxSl/AzdY
# t0+6pliFJ1peGhdFni2Fm8fu5oN68aTIrNtc5WY7Lzgf+sRTVeWORWS37+1zAD0m
# jzd8gyfBLxRuaRSfjYxny0rLXelAwfiA3ze2DU2Bfg9/rfcwggXYMIIDwKADAgEC
# AhBsO9J+3TyUnpWOKKmzx1egMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAklM
# MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRh
# bCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBTdGFydENvbSBDZXJ0aWZp
# Y2F0aW9uIEF1dGhvcml0eTAeFw0xNTEyMTYwMTAwMDVaFw0zMDEyMTYwMTAwMDVa
# MHUxCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSkwJwYDVQQL
# EyBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEjMCEGA1UEAxMaU3Rh
# cnRDb20gQ2xhc3MgMiBPYmplY3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
# ggEKAoIBAQC5FARY97LFhiwIMmCtCCbAgXe5aBnZFSsdGGnk2hqWBZcuZHkaqT1R
# M1rQd2r0ApNBw466cBur2Ht0b5jo17mpPmh2pImgIqwX1in4u7hhn9IH0GYOMEcg
# K3ACHv5zCRxxNLXifqmsqKfxjjpABnaSyvd4bO9YBXN9f4NQ6aJVAuMArpanxsJk
# e+P4WECVLk17v92CAN5JVaczI+baT/lgo5NVcTEkloCViSbIfU6ILeyhOSQZvpom
# MYk8eJqI0nimOTJJfmXangNDsrX8np+3lXD0+6rCZisXRWIaeffyTMHZ31Qj1D50
# WYdRtX5yev4WgaXoKJQN3lkgXUcytvyHAgMBAAGjggFaMIIBVjAOBgNVHQ8BAf8E
# BAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAy
# BgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0c3NsLmNvbS9zZnNjYS5j
# cmwwZgYIKwYBBQUHAQEEWjBYMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5zdGFy
# dHNzbC5jb20wMAYIKwYBBQUHMAKGJGh0dHA6Ly9haWEuc3RhcnRzc2wuY29tL2Nl
# cnRzL2NhLmNydDAdBgNVHQ4EFgQUPmKTmtfHGe4+j0kQhVUVIOOUhBwwHwYDVR0j
# BBgwFoAUTgvvGqRAW6UXaYcwyjRoQ9BBrvIwPwYDVR0gBDgwNjA0BgRVHSAAMCww
# KgYIKwYBBQUHAgEWHmh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeTANBgkq
# hkiG9w0BAQsFAAOCAgEAY6U81bNtJyjY67pTrzAL6kpdEtX5mspw+kxjjNdNVH5G
# 6lLnhaEkIxqdpvY/Wdw+UdNtExs+N8efKPSwh2m/BxXj2fSeLMwXcwHFookScEER
# 8ez0quCNzioqNHac7LCXPEnQzbtG2FHlePKNDWh8eU6KxiAzNzIrIxPthinHGgLT
# BOACHQM2YTlD8YoU5oN3dLmBOqtH0BDMZoLcjEIoEW1zC+TnVb3yU1G0xub6gnN7
# lP50vbAiHJYrnywQiXaloBV8B9YYfe6ZgvjqxwufwFcMVyE3UmCuDTsOpjqDEKpJ
# 25s+FUdkie5VqCS1aaudLo31X+9UvP45pfgyRqzyfUnVEhH4ZXxlBWZMzj2Xov5+
# m/+H3kxYuFA5xdqdshj/Zx00S7PkCSF+8M1NCcvFgQwjIw61bZAjDBl3P3a8xNTX
# sb2CjFdiNKbT3LD6IGeIf0b/EbPf0FXdvBrxm0ofMOhnngdPolPYCtoOGtZPAVe/
# xeu+/ZyKv6TSHlshaUO0iYfsmbXnZ51vvt/kkjwms9/qPFxSuE0fjEfF7aQazwRE
# Df2hiVPR0pAhvShtM3oU4XreEFEUWEYHs25fYV4WMmxkUKSgmSmwRq45tvtGH4LT
# b5+cd+iLqK8rBQL0E6xaUjjGfsYx7bueIvqTvCkrQvoxMbn/qDHCiypowDVq6TAw
# ggZqMIIFUqADAgECAhADAZoCOv9YsWvW1ermF/BmMA0GCSqGSIb3DQEBBQUAMGIx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IEFzc3VyZWQgSUQgQ0Et
# MTAeFw0xNDEwMjIwMDAwMDBaFw0yNDEwMjIwMDAwMDBaMEcxCzAJBgNVBAYTAlVT
# MREwDwYDVQQKEwhEaWdpQ2VydDElMCMGA1UEAxMcRGlnaUNlcnQgVGltZXN0YW1w
# IFJlc3BvbmRlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKNkXfx8
# s+CCNeDg9sYq5kl1O8xu4FOpnx9kWeZ8a39rjJ1V+JLjntVaY1sCSVDZg85vZu7d
# y4XpX6X51Id0iEQ7Gcnl9ZGfxhQ5rCTqqEsskYnMXij0ZLZQt/USs3OWCmejvmGf
# rvP9Enh1DqZbFP1FI46GRFV9GIYFjFWHeUhG98oOjafeTl/iqLYtWQJhiGFyGGi5
# uHzu5uc0LzF3gTAfuzYBje8n4/ea8EwxZI3j6/oZh6h+z+yMDDZbesF6uHjHyQYu
# RhDIjegEYNu8c3T6Ttj+qkDxss5wRoPp2kChWTrZFQlXmVYwk/PJYczQCMxr7GJC
# kawCwO+k8IkRj3cCAwEAAaOCAzUwggMxMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB
# Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMIIBvwYDVR0gBIIBtjCCAbIw
# ggGhBglghkgBhv1sBwEwggGSMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdp
# Y2VydC5jb20vQ1BTMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4AeQAgAHUAcwBl
# ACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBu
# AHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0
# AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAAYQBuAGQAIAB0
# AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcAcgBlAGUAbQBl
# AG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5
# ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkACAAaABl
# AHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMAsGCWCGSAGG/WwD
# FTAfBgNVHSMEGDAWgBQVABIrE5iymQftHt+ivlcNK2cCzTAdBgNVHQ4EFgQUYVpN
# JLZJMp1KKnkag0v0HonByn0wfQYDVR0fBHYwdDA4oDagNIYyaHR0cDovL2NybDMu
# ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEQ0EtMS5jcmwwOKA2oDSGMmh0
# dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENBLTEuY3Js
# MHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl
# cnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRBc3N1cmVkSURDQS0xLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAnSV+
# GzNNsiaBXJuGziMgD4CH5Yj//7HUaiwx7ToXGXEXzakbvFoWOQCd42yE5FpA+94G
# AYw3+puxnSR+/iCkV61bt5qwYCbqaVchXTQvH3Gwg5QZBWs1kBCge5fH9j/n4hFB
# pr1i2fAnPTgdKG86Ugnw7HBi02JLsOBzppLA044x2C/jbRcTBu7kA7YUq/OPQ6dx
# nSHdFMoVXZJB2vkPgdGZdA0mxA5/G7X1oPHGdwYoFenYk+VVFvC7Cqsc21xIJ2bI
# o4sKHOWV2q7ELlmgYd3a822iYemKC23sEhi991VUQAOSK2vCUcIKSK+w1G7g9BQK
# Ohvjjz3Kr2qNe9zYRDCCBs0wggW1oAMCAQICEAb9+QOWA63qAArrPye7uhswDQYJ
# KoZIhvcNAQEFBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu
# YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQg
# QXNzdXJlZCBJRCBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTIxMTExMDAwMDAw
# MFowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UE
# CxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgQXNzdXJlZCBJ
# RCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6IItmfnKwkKV
# pYBzQHDSnlZUXKnE0kEGj8kz/E1FkVyBn+0snPgWWd+etSQVwpi5tHdJ3InECtqv
# y15r7a2wcTHrzzpADEZNk+yLejYIA6sMNP4YSYL+x8cxSIB8HqIPkg5QycaH6zY/
# 2DDD/6b3+6LNb3Mj/qxWBZDwMiEWicZwiPkFl32jx0PdAug7Pe2xQaPtP77blUjE
# 7h6z8rwMK5nQxl0SQoHhg26Ccz8mSxSQrllmCsSNvtLOBq6thG9IhJtPQLnxTPKv
# mPv2zkBdXPao8S+v7Iki8msYZbHBc63X8djPHgp0XEK4aH631XcKJ1Z8D2KkPzIU
# YJX9BwSiCQIDAQABo4IDejCCA3YwDgYDVR0PAQH/BAQDAgGGMDsGA1UdJQQ0MDIG
# CCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcD
# CDCCAdIGA1UdIASCAckwggHFMIIBtAYKYIZIAYb9bAABBDCCAaQwOgYIKwYBBQUH
# AgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5o
# dG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0
# AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1
# AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABp
# AGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBl
# AGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBo
# AGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAg
# AGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAg
# AGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJYIZIAYb9bAMVMBIGA1UdEwEB
# /wQIMAYBAf8CAQAweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8v
# b2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6
# MHgwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy
# ZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwHQYDVR0OBBYEFBUAEisTmLKZB+0e
# 36K+Vw0rZwLNMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqG
# SIb3DQEBBQUAA4IBAQBGUD7Jtygkpzgdtlspr1LPUukxR6tWXHvVDQtBs+/sdR90
# OPKyXGGinJXDUOSCuSPRujqGcq04eKx1XRcXNHJHhZRW0eu7NoR3zCSl8wQZVann
# 4+erYs37iy2QwsDStZS9Xk+xBdIOPRqpFFumhjFiqKgz5Js5p8T1zh14dpQlc+Qq
# q8+cdkvtX8JLFuRLcEwAiR78xXm8TBJX/l/hHrwCXaj++wc4Tw3GXZG5D2dFzdaD
# 7eeSDY2xaYxP+1ngIw/Sqq4AfO6cQg7PkdcntxbuD8O9fAqg7iwIVYUiuOsYGk38
# KiGtSTGDR5V3cdyxG0tLHBCcdxTBnU8vWpUIKRAmMYIETzCCBEsCAQEwgYkwdTEL
# MAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKTAnBgNVBAsTIFN0
# YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSMwIQYDVQQDExpTdGFydENv
# bSBDbGFzcyAyIE9iamVjdCBDQQIQOb1CntKBbrrVvMkDtLpl5zANBglghkgBZQME
# AgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEM
# BgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqG
# SIb3DQEJBDEiBCCYEvT04HmTNacN8tE1fnRJVTu11z2Vp+a6Fkmws8PVnDANBgkq
# hkiG9w0BAQEFAASCAQBP9ZCjMyi6bJ+BV8JZbFjeaKXF5HEfY4r1Z0rQ+m04nrf/
# 52oUUYhEvhxE1wnpYnT6brdG41m7Z1E3/GnV1B5gJJoHazrhGFuYhmp6wyEUCEGz
# kwWfjZEIE9K9HRDUKF5ZEuMFMBHTg0aFnQOmaLDKqpRtU4hK3p7B2PfBwApUSsUa
# D96b/ZO5w5rwZ5YG2h9o5T3MINt1tkrdJZ9U+hg6qKmgQH13yvUTJBiFHEGOOmHm
# ZneQQIkP0kl+V40FHS1updwepVJZv0krbqqV08h/waCjOcZgNF+v/aCVQ8eE+ZOx
# mpgLp1DocDmYkDnd7PceaRkssikMz73e9gufBh0uoYICDzCCAgsGCSqGSIb3DQEJ
# BjGCAfwwggH4AgEBMHYwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0
# IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNl
# cnQgQXNzdXJlZCBJRCBDQS0xAhADAZoCOv9YsWvW1ermF/BmMAkGBSsOAwIaBQCg
# XTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xODA4
# MjExNjM5MDNaMCMGCSqGSIb3DQEJBDEWBBQhr/2IQS+C/aGpcZD3+sba3L202zAN
# BgkqhkiG9w0BAQEFAASCAQCgi7ceZ8MippaUjd1MfMQjX6qlbBQa7oSIn8Z+EfG2
# YaeGqEvpbhUl7KCa7LRe0r8yItNZCfHslRuB8cC6n997eUTdLc94Tmy3cJkPnhb3
# jIXVm1m6B0J5PAhRoHlJziPaQ+mvy0IfU33m1AeckYTqDw9395dBJvYdoWUCYrKS
# pkAJlZ4jr1PVDcK9VJod4qfRoFZPaL1DjJieD1otKAFI2Y9N1p7UvScVOcDWvyJb
# YKt5ncFOcI8grYctCXzQzidKATTZZMIticxwU95MwYoDdIW8A5AkL1jHtWq6wS6V
# 4YX1TJ9g1BaBpTxtaR2WiqGKsMGqVe9tdvrB4QkrEG4u
# SIG # End signature block