Create_SecureMFA_OTP_AD_attributes.ps1
#THIS ONLY REQUIRES IF YOU PLAN TO RUN SecureMFA OTP Provider in AD MODE. #You need to execute this script on Read-Write domain controller with AD account which is member of Schema Admins group. #SecureMFA OTP provider when operates in AD mode ("auth_mode": "AD") it requires custom Active Directory (AD) attributes to be created to store OTP data for the user. #This action cannot be undone and needs to be tested in your TEST domain first before moving into PRODUCTION. #New AD Schema Attributes will be added into custom SecureMFA Auxiliary Class and that Class will be added into Existing User Class as AD Schema best practices suggest. #OID numbers for custom attributes are from SecureMFA Private Enterprise range assigned by iana.org . Which do not overlap with other vendors OIDs numbers used to create custom AD attributes. function ADDADSchemaAttributetoClass($SchemaAttribute) { [bool]$reset = $true $attempts=30 $sleepInSeconds=180 do { try { $reset = $true Write-Host "Adding $SchemaAttribute into SecureMFA Auxiliary Class.($attempts)" -ForegroundColor Green #Get AD Schema details $dse = Get-ADRootDSE $schemaPath = $dse.schemaNamingContext $type = 'attributeSchema' #ADD AD Schema Attribute To SecureMFA Class $Schema = Get-ADObject -SearchBase $schemaPath -Filter "name -eq `'SecureMFA`'" $Schema | Set-ADObject -Add @{mayContain = $SchemaAttribute} -ErrorAction stop } catch [Exception] { Write-Host "Waiting for AD schema attribute refresh ... Please note this action can take a few minutes to complete." -ForegroundColor Yellow $reset = $false } $attempts-- if ($attempts -gt 0 -and $reset -eq $false) { sleep $sleepInSeconds } } until ($attempts -le 0 -or $reset -eq $true) return $reset } function ADDADAttribute{ Param( [parameter(Mandatory)] [String]$Name, [Parameter(Mandatory)] [String]$Description, [parameter(Mandatory)] [String]$AttributeID, [Parameter(Mandatory)] [ValidateSet('String','Int','Time','Boolean')] [String]$AttributeType, [Parameter()] [Boolean]$IsSingleValued = $True ) #Attribute values by type https://technet.microsoft.com/en-us/library/cc961740.aspx switch ($AttributeType) { 'String' {$attributeSyntax = '2.5.5.4'; $omSyntax = 20} 'Int' {$attributeSyntax = '2.5.5.9'; $omSyntax = 2} 'Time' {$attributeSyntax = '2.5.5.11'; $omSyntax = 24} 'Boolean' {$attributeSyntax = '2.5.5.8'; $omSyntax = 1} Default {} } #AD atribute params------- $attributes = @{ lDAPDisplayName = $Name; attributeId = $AttributeID; oMSyntax = $omSyntax; attributeSyntax = $attributeSyntax; isSingleValued = $IsSingleValued; adminDescription = $Description; searchflags = 0 } #If AD Attribute doesn't exist create one. if(!(Get-ADObject -SearchBase "$((Get-ADRootDSE).SchemaNamingContext)" -Filter {lDAPDisplayName -eq $Name})) { New-ADObject -Name $Name -Type $type -Path $schemapath -OtherAttributes $attributes Write-host "AD attribute $Name has been created." -ForegroundColor Green } Else {Write-host "AD attribute $Name allready exist in AD." -ForegroundColor yellow} } #START Script #Get AD Schema details $dse = Get-ADRootDSE $schemaPath = $dse.schemaNamingContext $type = 'attributeSchema' #Create a New AD Schema Auxiliary Class for SecureMFA $Name = 'SecureMFA' $attributes = @{ governsId = '1.3.6.1.4.1.54153.2.1000' adminDescription = 'SecureMFA Class to host OTP attributes' objectClass = 'classSchema' ldapDisplayName = $Name adminDisplayName = $Name objectClassCategory = 3 systemOnly = $FALSE # subclassOf: top subclassOf = "2.5.6.0" # rdnAttId: cn rdnAttId = "2.5.4.3" } #If Schema Auxiliary Class for SecureMFA doesn't exist create one. if(!(Get-ADObject -SearchBase (Get-ADRootDSE).SchemaNamingContext -Filter {name -like "SecureMFA"})) { New-ADObject -Name $Name -Type 'classSchema' -Path $schemapath -OtherAttributes $attributes Write-host "A New AD Schema Auxiliary Class SecureMFA has been created." -ForegroundColor Green } Else {Write-host "Auxiliary Class SecureMFA allready exist in AD." -ForegroundColor Yellow} #Add AD Schema SecureMFA Auxiliary Class To default User Class $auxClass = Get-ADObject -SearchBase $schemaPath -Filter "name -eq `'$Name`'" -Properties governsID $classToAddTo = Get-ADObject -SearchBase $schemaPath -Filter "name -eq `'user`'" $classToAddTo | Set-ADObject -Add @{auxiliaryClass = $($auxClass.governsID)} #START Creating AD attributes ADDADAttribute -Name 'sMFA-OTP-secret' -Description 'User Secret attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00001' -AttributeType String -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-logon' -Description 'User logon status attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00002' -AttributeType Int -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-lastlogon' -Description 'User laslogon attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00003' -AttributeType Time -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-logoncount' -Description 'User logoncount attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00004' -AttributeType Int -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-failedlogoncount' -Description 'User failedlogoncount attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00005' -AttributeType Int -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-failedlastlogon' -Description 'User failedlastlogon attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00006' -AttributeType Time -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-failedcode' -Description 'User failedcode attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00007' -AttributeType String -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-logonip' -Description 'User logonip attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00008' -AttributeType String -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-useragent' -Description 'User useragent attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00009' -AttributeType String -IsSingleValued $true ADDADAttribute -Name 'sMFA-OTP-interval' -Description 'User interval attribute' -AttributeID '1.3.6.1.4.1.54153.2.1000.00010' -AttributeType Int -IsSingleValued $false #Refresh AD schema $dse.schemaUpdateNow = $true Write-host "Refreshing AD Schema." -ForegroundColor Green [bool]$reset = $false #START Adding AD Schema Attributes to User Class: @("sMFA-OTP-secret","sMFA-OTP-logon","sMFA-OTP-lastlogon","sMFA-OTP-logoncount","sMFA-OTP-failedlogoncount","sMFA-OTP-failedlastlogon","sMFA-OTP-failedcode","sMFA-OTP-logonip","sMFA-OTP-useragent","sMFA-OTP-interval") | foreach { $SchemaAttribute = $_.trim() $reset = ADDADSchemaAttributetoClass $SchemaAttribute if($reset) {Write-host "AD attribute $SchemaAttribute have been added into SecureMFA Auxiliary Class." -ForegroundColor Green} else {Write-host "AD attribute $SchemaAttribute has failed to add into SecureMFA Auxiliary Class. Please try again later when AD replication for attributes is completed across your environment." -ForegroundColor red} } #Refresh AD schema $dse.schemaUpdateNow = $true write-host "Custom sMFA attributes have been created. Please note that depending on AD replication policies it may take a while to show a new custom attribute for user object in AD when using GUI tools." -ForegroundColor Cyan pause |