New-xOTP_User.ps1

<#
     .SYNOPSIS
        Creates SecureMFA.com OTP accounts in SQL database.
    .DESCRIPTION
        preloads SecureMFA OTP accounts in SQL database for manual configuration.
        Dependencies:
            * System which executes a script must have Microsoft Framework 4.6.1 and above installed.
            * SecureMFA_SupportTools.dll file must be present in script directory.
            * SecureMFA_SupportTools.json configuration file must be present in script directory.
                                     
            Bellow is a sample of valid Json config file with minimal configuration required for script to work:
                {
                "sql_server": "asqlaol1.adatum.labnet",
                "sql_database": "SecureMfaOTP",
                "ui_input_text": "Please enter user's UPN",
                "ui_environment": "MyCompany",
                "data_encryption_passphrase": "d9GhT=7=Ox8-+LaZ"
                }
 
    .PARAMETER Disable
        Disbales user's OTP account in the database.
 
    .NOTES
        Version: 1.0.1.1
        Author: SecureMfa.com
        Creation Date: 18/08/2020
        Purpose/Change: New
   
    .EXAMPLE
        C:\PS> New-xOTP_User -upn test1@adatum.labnet
 
        This command will import SecureMFA_SupportTools.json file from current directory and creates OTP account for test1 user.
        Command will show secretKey output for user which can be used for manual setup with TOTP Authenticator app.
 
    .EXAMPLE
        C:\PS> New-xOTP_User -upn test1@adatum.labnet -Encrypt
 
        This command will import SecureMFA_SupportTools.json file from current directory and creates OTP account with encrypted secret for test1 user.
        Command will show secretKey output for user which can be used for manual setup with TOTP Authenticator app.
     
#>


#>
Function New-xOTP_User {
Param
(
    [Parameter(Mandatory=$true,ParameterSetName="Default")]
    [String]$upn = $null,
    [Parameter(Mandatory=$false, ParameterSetName="Default")]
    [Switch]$Encrypt,
    [Switch]$Force
)

DynamicParam
{
    # create a dictionary to return, and collection of parameters
    $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
    $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
 
    # create a new [string] parameter for all parameter sets, and decorate with a [ValidateSet]
    $dynParam = New-Object -Type System.Management.Automation.RuntimeDefinedParameter("Profile", [String], $attributeCollection)
    $attributes = New-Object System.Management.Automation.ParameterAttribute
    $fname = "Profiles.json"
    $paramOptions = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList (ConvertFrom-Json (Get-Content (join-path $PSScriptRoot $fname) -Raw))
 
    $attributeCollection.Add($attributes)
    $attributeCollection.Add($paramOptions)
    $paramDictionary.Add("Profile", $dynParam)
 
    return $paramDictionary
}

Process
{
    #Static Parameters
    $Event_Source = "SecureMFA_SupportTools"
    [Int16]$UserStatus = 0;
    $ConfirmPreference="high"
    $decision_Validation = $null

    $message  = "Please confirm if you want to create OTP account for user [$upn]"            
    $question = 'Please confirm?'
    $choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]
    $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes'))
    $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No'))

    #Confirmation for before creating new OTP account
    if(!($Force)) { $decision_Validation = $Host.UI.PromptForChoice($message, $question, $choices, 0) ; if ($decision_Validation -eq 1 ) {break} }

    #Checking Dependencies
    #EventLog source dependency
    $ErrMsg = "Set OTP User EventLog source is missing. Please execute following PS command 'New-EventLog -Source SecureMFA_SupportTools -LogName Application' on the system before using the app."
    if (((Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Application).pschildname | where { $_ -eq $Event_Source} | measure).Count -eq 0) 
    {write-host $ErrMsg -ForegroundColor red; pause; break}
    #Config file dependency
    if ( $PSBoundParameters.Keys.Contains("Profile") )
    {
        $configfile = (Join-Path -Path $PSScriptRoot -ChildPath ($PSBoundParameters.Profile + '_SecureMFA_SupportTools.json'))
    }
    else {$configfile = (Join-Path -Path $PSScriptRoot -ChildPath SecureMFA_SupportTools.json)}
    #Test config file path.
    $ErrMsg = "$configfile file is missing. Please copy a file to script directory and try again."
    if (!(Test-Path $configfile)) { write-host $ErrMsg -ForegroundColor red; pause; break }
    #DLL file dependency
    $dllpath = (Join-Path -Path $PSScriptRoot -ChildPath SecureMFA_SupportTools.dll)
    $ErrMsg = "$configfile file is missing. Please copy a file to script directory and try again."
    if (!(Test-Path $dllpath)) { write-host $ErrMsg -ForegroundColor red; pause; break }

    #Read JSON file Configuration
    $json = Get-Content -Raw $configfile | ConvertFrom-Json
    $sqlinstance = $json.sqlserver
    $sqldbname = $json.sqldbname
    $sqlintegratedsecurity = $json.sqlintegratedsecurity
    $sqluseraccount = $json.sqluseraccount
    $sqluserpassword = $json.sqluserpassword
    $input_text = $json.ui_input_text
    $environment = $json.ui_environment
    $data_encryption_passphrase = $json.data_encryption_passphrase;
    $sqlConnectString = "server=" + $sqlinstance + ";initial catalog=" + $sqldbname + ";integrated security=" + $sqlintegratedsecurity + ";User ID=" + $sqluseraccount + ";Password=" + $sqluserpassword;

    #Get user's input if required
    write-host " -- New OTP User utility for $environment --" -ForegroundColor Green -NoNewline
    write-host " [New OTP User] " -ForegroundColor yellow
    if ($upn -eq $null) { Do { $upn = read-host $input_text} while ($upn -eq "")}

    Try {

        [System.Reflection.Assembly]::LoadFile($dllpath) | Out-Null 
    
        if ([SecureMFA_SupportTools.OTP]::isUserExist($upn, $sqlConnectString, [ref] $UserStatus)) 
            {
        
            switch($UserStatus){
                   0 {$UserStatusValue = "Never logged in."}
                   1 {$UserStatusValue = "Enabled."}
                   2 {$UserStatusValue = "Disabled."}
            }        
            write-host "New OTP account cannot be created because user $upn exist with status: $UserStatusValue `nPlease hardreset user to delete all OTP data before progressing with a new OTP account creation." -ForegroundColor Cyan   
            
            } 
        
        else 
            {
            [String]$sekretKey = "";
            if($Encrypt) {$isSuccess = [SecureMFA_SupportTools.OTP]::NewUser($upn, $sqlConnectString, $true , $data_encryption_passphrase, $env:username, $env:computername, [ref] $sekretKey)}
            else {$isSuccess = [SecureMFA_SupportTools.OTP]::NewUser($upn, $sqlConnectString, $false , $data_encryption_passphrase, $env:username, $env:computername , [ref] $sekretKey)}
            if ($isSuccess) {                
                write-host "OTP account for user: $upn has been created by: $env:username from computer: $env:computername"
                write-host "$upn secretKey: $sekretKey" -ForegroundColor Cyan
                write-host "NOTE: Above secretkey is displayed only once. To recover it you will need to hardreset OTP account and create a new one again." -ForegroundColor yellow   
            
                write-host "`n--- SET UP THE AUTHENTICATOR APP ---`n"
                write-host "1) Install TOTP Authenticator app on your iOS or Android device. `nThis can Microsoft Authenticator , Google Authenticator, Symantec VIP etc . Any OTP authentication app which is compatible with Time-Based One-Time Password algorithm defined in RFC6238."
                write-host "2) In the Authenticator app enter a setup-key/code manually. `nProcess may be slightly different for various authenticators"
                write-host "3) When prompted, enter following details and click Continue. `n a) A name for the account (for example UPN value) `n b) The secret key provided displayed on the screen."
                write-host "4) At this point Authenticator app should start generating OTP codes on your mobile device."
                } 

            }
        }

    #On error acction
    catch [System.Exception] { 
            $completed = get-date
            $line = $_.InvocationInfo.ScriptLineNumber
            $msg = $_.Exception.Message 

            Write-Host -ForegroundColor Red "Error: $msg"
            Write-EventLog –LogName Application –Source $Event_Source –EntryType Error –EventID 5559 –Message “$msg Executed by: $env:username Computer: $env:computername Line: $line”                 
            }    

    }
}