Active Roles PowerShell Login Function

I like to wrap my login scripts into functions.  I'm having a strange result with Active Roles attempting to connect the AR Proxy.

##ActiveRoles
function Login-QADService{
param(
[string]$passwordfile = "$([Environment]::GetFolderPath("MyDocuments"))\domainpassword.txt",
[string]$username = 'DOMAIN\admin',
[string]$service = 'ARServerService'
)
#Encrypt Password
if(-not $(Test-Path -Path $passwordfile)){(get-credential).password | ConvertFrom-SecureString | set-content $passwordfile}

$password = Get-Content $passwordfile | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential("$username",$password)
Connect-QADService -Proxy -Service $service -Credential $credential
}

If I try to run the function, it connects, but it's like it isn't using the credentials in the function.  I know this because I have an 'regular' and 'admin' account and the regular account only has access to a single domain.  I seem to be only getting the data for the single domain.

If I run the commands within the function I connect with my admin creds and data is returned as expected from all domains.  

Can anyone see something wrong with my script?  

Parents
  • Definitely second Aidar's reply. There are two ways that I routinely use to work around that problem:

    1. Use an AES encryption key file: ConvertTo-SecureString -Key AESEncryptionKey. Key can be generated with:
      $Key = New-Object Byte[] 32
      [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
      $Key | out-file C:\aes.key

      This suffers from having to securely share the keyfile ("c:\aes.key" in the above example) with all people/computers/services that need to decrypt.
    2. Use a PKI cert that is applied to the user or computer on which the decryption is occurring. This is the best option - it can be decrypted anywhere so long as you have the cert installed. Down side is that it is technically more complex to implement.
  • I'm just trying to debug why my function lines work individually but not together.

  • I'm wondering if, because you're encapsulating this in a function, that the connection you've established exists only within the scope of the function. When you return to the main body of your code, my guess is that you're losing the privileged session that you established inside the function and establishing a new connection using your non-privileged credentials.

    I didn't test it, but perhaps you could try something like this:

    function Login-QADService{
    param(
    [string]$passwordfile = "$([Environment]::GetFolderPath("MyDocuments"))\domainpassword.txt",
    [string]$username = 'DOMAIN\admin',
    [string]$service = 'ARServerService'
    )
    #Encrypt Password
    if(-not $(Test-Path -Path $passwordfile)){(get-credential).password | ConvertFrom-SecureString | set-content $passwordfile}
    
    $password = Get-Content $passwordfile | ConvertTo-SecureString
    $credential = New-Object System.Management.Automation.PsCredential("$username",$password)
    $connection = Connect-QADService -Proxy -Service $service -Credential $credential
    return ,$connection
    }
    
    $connection = Login-QADService
    Get-QADUser -Connection $connection

  • That definitely worked.  I didn't even realize there was a connection switch.  Now to figure out how to go about wrapping it up if I can.  I have this parked in the PowerShell profile for easy use.  I'd love to avoid having to use the connection string.

Reply Children
  • I ended up doing this:

    function Login-QADService{
    param(
    [string]$passwordfile = "$([Environment]::GetFolderPath("MyDocuments"))\domainpassword.txt",
    [string]$username = 'DOMAIN\admin',
    [string]$service = 'ARServerService'
    )
    #Encrypt Password
    if(-not $(Test-Path -Path $passwordfile)){(get-credential).password | ConvertFrom-SecureString | set-content $passwordfile}

    $password = Get-Content $passwordfile | ConvertTo-SecureString
    $credential = New-Object System.Management.Automation.PsCredential("$username",$password)
    $connection = Connect-QADService -Proxy -Service $service -Credential $credential
    return $connection
    }

    Connect-QADService -Connection $(Login-QADService)

    Thanks again for the details.

  • Awesome!

    It occurred to me later, that another simple way to solve your problem would be:

    function Login-QADService{
    param(
    [string]$passwordfile = "$([Environment]::GetFolderPath("MyDocuments"))\domainpassword.txt",
    [string]$username = 'DOMAIN\admin',
    [string]$service = 'ARServerService'
    )
    #Encrypt Password
    if(-not $(Test-Path -Path $passwordfile)){(get-credential).password | ConvertFrom-SecureString | set-content $passwordfile}
    
    $password = Get-Content $passwordfile | ConvertTo-SecureString
    $credential = New-Object System.Management.Automation.PsCredential("$username",$password)
    $connection = Connect-QADService -Proxy -Service $service -Credential $credential
    return $connection
    }
    
    . Login-QADService
    Connect-QADService -Connection $connection

    The period before the call to the function means that the function should execute within the current scope. Either way, glad it's working!

  • Ah nice solution also.  I had also thought about making the connection string a global scope.  I wanted to get rid of the extra line needed.