CDOT: PowerShell Connections and Secure Credentials Manager Function - Part 2/2

PS: Apologies in advance about the formatting on this blog. Copy and paste as text only into say NotePad++, and the script should look much more sensible!

#### START OF SCRIPT ####

######################################################################
## TITLE: PowerShell Connect and Credentials Manager Function for   ##
##   Clustered ONTAP - rev. 6 (cot.ps1)                             ##
##                            COMMENTS: See end of script!          ##
##                              AUTHOR: vCosonok of www.cosonok.com ##
######################################################################

### START OF FUNCTION COT ###
function cot {

       # GENERAL SECTION: Set Error Pref and DOT Toolkit
       $ErrorActionPreference = 'SilentlyContinue' # Default is 'Continue'
       if (!(Get-Module DataONTAP)){Import-Module DataONTAP}
       if (!(Get-Module DataONTAP)){return "ERROR: Cannot load DataONTAP PowerShell Toolkit!"}
      
       # Current working directory, current username, and the credentials file
       $cotCurrentWorkingPath = (pwd).path     
       $cotWhoAmI = $env:username
       $cotCredsFile = $cotCurrentWorkingPath + "\PS_creds_" + $cotWhoAmI + ".txt"

       # ARGUMENTS: Store the original args
       $cotA0 = $args[0]
       $cotA1 = $args[1]
       $cotA2 = $args[2]
       $cotA3 = $args[3]

       # NO ARG0: COT
       if (!$cotA0){
              $cotOut = cotFnGet
              return $cotOut }

       # ARG0 = ?/HELP: COT ?/HELP
       if (($cotA0 -eq "?") -or ($cotA0 -eq "HELP")){
              $cotQOut = cotFnHelp
              # Use function here simply to place help contents at end of script!
              return $cotQOut}
             
       # ARG0 = CLEAR: COT CLEAR
       if ($cotA0 -eq "CLEAR"){
              $global:CurrentNcController = $null
              return $null}
             
       # ARG0 = CRED: COT CRED   
       if ($cotA0 -eq "CRED"){
              $cotFileCheck = Test-Path $cotCredsFile
              if (!$cotFileCheck){
                     return "ERROR: Creds file $cotCredsFile non-existent!"}
              $cotCredsFileContent = Get-Content $cotCredsFile
              $cotRowsInCredsFile = $cotCredsFileContent.count
              if ($cotRowsInCredsFile -lt 3){
                     return "ERROR: Creds file $cotCredsFile missing content!"}
              $cotCredsOutHash = @{}
              $cotCount = 0
              do {
                     $cotCredsOutHash += @{($cotCredsFileContent[$cotCount]) = ($cotCredsFileContent[$cotCount+1])}
                     $cotCount = $cotCount + 3
              } until ($cotCount -ge  $cotRowsInCredsFile - 2)
              return $cotCredsOutHash}

       # ARG0 = RCRED: COT RCRED IP/DNS (& USER)
       if ($cotA0 -eq "RCRED"){
              if (!$cotA1){return "ERROR: Need more parameters!"}
              $cotFileCheck = Test-Path $cotCredsFile
              if (!$cotFileCheck){
                     return "ERROR: Creds file $cotCredsFile non-existent!"}
              $cotCredsFileContent = Get-Content $cotCredsFile
              $cotRowsInCredsFile = $cotCredsFileContent.count
              if ($cotRowsInCredsFile -lt 3){
                     return "ERROR: Creds file $cotCredsFile missing content!"}          
              $cotCount = 0
              $cotCredFileNew = @()
              do {
                     if ($cotA1 -ne ($cotCredsFileContent[$cotCount])){
                           if (($cotA2 -ne ($cotCredsFileContent[$cotCount+1])) -or (!$cotA2)){
                                  $cotCredFileNew += $cotCredsFileContent[$cotCount]
                                  $cotCredFileNew += $cotCredsFileContent[$cotCount+1]
                                  $cotCredFileNew += $cotCredsFileContent[$cotCount+2]}}
                     $cotCount = $cotCount + 3
              } until ($cotCount -ge  $cotRowsInCredsFile - 2)
              if ($cotCredFileNew){
                     $cotCredFileNew | Set-Content $cotCredsFile
                     return $null}
              if (!$cotCredFileNew){
                     # If remove last cred set-content won't work for $null file!
                     $cotNewFile = New-Item $cotCredsFile -Type file -Force
                     return $null}}
             
       # ARG0 = ADD: COT ADD
       $cotAdding = $null
       if ($cotA0 -eq "ADD"){
              if (!$cotA1){return "ERROR: Need more parameters!"}
              # Flag we want to add controllers, and remove ADD argument!
              $cotAdding = "YES"
              $cotA0 = $cotA1
              $cotA1 = $cotA2
              $cotA2 = $cotA3}
             
       # ARG0 = RETURN: COT REMOVE
       if ($cotA0 -eq "REMOVE"){
              if (!$cotA1){return "ERROR: Need more parameters!"}
              $cotCCount = $global:currentnccontroller.count
              if ($cotCCount -eq 0){return "ERROR: No connected controllers!"}
              $cotConnections = $global:CurrentNcController
              $global:CurrentNcController = $null
              $cotAdding = "YES"
              foreach ($cotConnection in $cotConnections){
                     $cotCName = $cotConnection.Name
                     $cotCAddr = $cotConnection.Address.IPAddressToString
                     $cotCUser = $cotConnection.Credentials.Username
                     if (($cotCName -ne $cotA1) -and ($cotCAddr -ne $cotA1)){
                           if ($cotCName -eq $cotCAddr){
                           $cotFindCred = cotFnFindCred2 $cotCAddr $cotCUser
                           $cotConnected = cotFnConnectSecure $cotCAddr $cotCUser $cotFindCred}
                           if ($cotCName -ne $cotCAddr){
                                  $cotFindCred = cotFnFindCred2 $cotCName $cotCUser
                                  $cotConnected = cotFnConnectSecure $cotCName $cotCUser $cotFindCred}}}
              return $null}

       # ARG0 = IP (and no 2nd arg): COT 10.10.10.10
       if (!$cotA1){
              $cotCredsFileCheck = cotFnFileCheck
              $cotFindCred = @()
              $cotFindCred = cotFnFindCred1 $cotA0
              if ($cotFindCred){
                     $cotUser = $cotFindCred[0]
                     $cotPass = $cotFindCred[1]
                     $cotConnected = cotFnConnectSecure $cotA0 $cotUser $cotPass
                     if (!$cotConnected){
                           return "ERROR: Failed to connect!"}                   
                     return $null}
              return "ERROR: Could not find credentials for $cotA0."}
             
       # ARG0,1 = IP,USER (and no 3nd arg): COT 10.10.10.10 USER
       if (!$cotA2){
              $cotCredsFileCheck = cotFnFileCheck
              $cotFindCred = @()
              $cotFindCred = cotFnFindCred2 $cotA0 $cotA1
              if ($cotFindCred){
                     $cotConnected = cotFnConnectSecure $cotA0 $cotA1 $cotFindCred
                     if (!$cotConnected){
                           return "ERROR: Failed to connect!"}                   
                     return $null}
              return "ERROR: Could not find credentials for $cotA0 adn user $cotA1."}
             
       # ARG0,1,2: COT IP/DNS USER PASS
       if ($cotA0 -and $cotA1 -and $cotA2){
              $cotConnected = cotFnConnect $cotA0 $cotA1 $cotA2
              if (!$cotConnected){
                     return "ERROR: Failed to connect!"}
              $cotCredsFileCheck = cotFnFileCheck
              $cotCredStored = cotFnCredStore $cotA0 $cotA1 $cotA2
              return $null}
             
       # END OF FUNCTION: Should never happen - nothing got caught!
       return "SYNTAX ERROR - NO ARGS CAUGHT!"

} ### END OF FUNCTION COT ###

## FUNCTION: cotFnGet
function cotFnGet{
       $cotCurrentCtrs = $global:CurrentNcController
       if($cotCurrentCtrs){
                     # Gcnc = global current nc controller
                     $cotGcncTemplate = @{Expression={$_.Name};Label="Name";width=25},@{Expression={$_.Address};Label="Address";width=25},@{Expression={$_.Vserver};Label="Vserver";width=25},@{Expression={$_.Credentials.UserName};Label="UserName";width=25}
                     $cotGcncOutHash = $cotCurrentCtrs | Format-Table $cotGcncTemplate   
                     return $cotGcncOutHash}
       return $null}

## FUNCTION: cotFnConnect
function cotFnConnect{
       $cotIPAddress = $args[0]
       $cotUsername = $args[1]
       $cotPassword = $args[2]
       $cotSecPass = $cotPassword | ConvertTo-SecureString  -AsPlainText -Force
       $cotCredential = New-Object System.Management.Automation.PsCredential($cotUsername, $cotSecPass)
       if (!$cotAdding){$cotConnect = Connect-NcController $cotIPAddress -Credential $cotCredential}
       if ($cotAdding){$cotConnect = Connect-NcController $cotIPAddress -Credential $cotCredential -Add}
       if ($cotConnect){return "CONNECTED!"}
       if (!$cotConnect){return $null}}
      
## FUNCTION: cotFnConnectSecure
function cotFnConnectSecure{
       $cotIPAddress = $args[0]
       $cotUsername = $args[1]
       $cotPassword = $args[2]
       $cotSecPass = $cotPassword | ConvertTo-SecureString
       $cotCredential = New-Object System.Management.Automation.PsCredential($cotUsername, $cotSecPass)
       if (!$cotAdding){$cotConnect = Connect-NcController $cotIPAddress -Credential $cotCredential}
       if ($cotAdding){$cotConnect = Connect-NcController $cotIPAddress -Credential $cotCredential -Add}
       if ($cotConnect){return "CONNECTED!"}
       if (!$cotConnect){return $null}} 
      
## FUNCTION: cotFnFileCheck
function cotFnFileCheck {
       $cotFileCheck = Test-Path $cotCredsFile
       if ($cotFileCheck){return "EXISTED!"}
       if (!$cotFileCheck){
              $cotNewFile = New-Item $cotCredsFile -Type file
              return $null}}

## FUNCTION: cotFnCredStore
function cotFnCredStore{
       $cotIPAddress = $args[0]
       $cotUsername = $args[1]
       $cotPassword = $args[2]
       $cotSecurePass = $cotPassword | ConvertTo-SecureString -AsPlainText -Force
       $cotSecurePassString = $cotSecurePass | ConvertFrom-SecureString    
       $cotCredsFileContent = Get-Content $cotCredsFile
       $cotRowsInCredsFile = $cotCredsFileContent.count
       if ($cotCredsFileContent){
              $cotCount = 0
              do {
                     if(($cotCredsFileContent[$cotCount] -eq $cotIPAddress) -and
                           ($cotCredsFileContent[$cotCount+1] -eq $cotUsername)){
                           $cotCredsFileContent[$cotCount+2] = $cotSecurePassString
                           return $null}
                     $cotCount = $cotCount + 3
              } until ($cotCount -ge  $cotRowsInCredsFile - 2)}
       $cotCredsFileContent += @($cotIPAddress,$cotUsername,$cotSecurePassString)
       $cotCredsFileContent | Set-Content $cotCredsFile
       return $null}

## FUNCTION: cotFnFindCred1
function cotFnFindCred1{
       $cotIPAddress = $args[0]
       $cotCredsFileContent = Get-Content $cotCredsFile
       $cotRowsInCredsFile = $cotCredsFileContent.count
       if ($cotCredsFileContent){
              $cotCount = 0
              do {
                     if($cotCredsFileContent[$cotCount] -eq $cotIPAddress){
                           $cotReturnUserPass = @()
                           $cotReturnUserPass += $cotCredsFileContent[$cotCount+1]
                           $cotReturnUserPass += $cotCredsFileContent[$cotCount+2]
                           return $cotReturnUserPass}
                     $cotCount = $cotCount + 3
              } until ($cotCount -ge  $cotRowsInCredsFile - 2)}
       return $null}

## FUNCTION: cotFnFindCred2
function cotFnFindCred2{
       $cotIPAddress = $args[0]
       $cotUsername = $args[1]
       $cotCredsFileContent = Get-Content $cotCredsFile
       $cotRowsInCredsFile = $cotCredsFileContent.count
       if ($cotCredsFileContent){
              $cotCount = 0
              do {
                     if(($cotCredsFileContent[$cotCount] -eq $cotIPAddress) -and
                           ($cotCredsFileContent[$cotCount+1] -eq $cotUsername)){
                           $cotReturnPass = $cotCredsFileContent[$cotCount+2]
                           return $cotReturnPass}    
                     $cotCount = $cotCount + 3
              } until ($cotCount -ge  $cotRowsInCredsFile - 2)}
       return $null}

## FUNCTION: cotFnHelp
function cotFnHelp{
       return "
       cot = Returns currently connected to controllers.
       cot ? = List of commands and description.
       cot help = List of commands and description.
       cot clear = Clears current connections.
       cot cred = List credentials - IP/DNS and user.
       Note: Current users credential file path = $cotCredsFile
       cot rcred {IP/DNS} = Removes credentials for specified IP/DNS.
       cot rcred {IP/DNS} {USER} = Removes credentials for specified pair.
       cot {IP/DNS} = Connects with specified arg (or fails to).
       cot {IP/DNS} {USER} = Connects with specified args (or fails to).
       cot {IP/DNS} {USER} {PASSWORD} = Connects with specified args (or fails to).
       cot add {IP/DNS} = Creates an additional connection as specified.
       cot add {IP/DNS} {USER} = Creates an additional connection as specified.  
       cot add {IP/DNS} {USER} {PASSWORD} = Creates an additional connection as specified.
       cot remove {IP/DNS} = Removes the specified connection.
       cot remove {IP/DNS} {USER} = Removes the specified connection.
       "
}

<# CHANGELOG

r1: Was an experimental fling and completely re-written for V2.
r2: This was the first version that worked 100% with the three arguments CLUSTERIP, USERNAME, PASSWORD.
r3: Here we introduced the args CLEAR and ADD, started introducing REMOVE until decided it was too complicated to achieve within the current format.
r4: Completely rewritten using additional functions outside the main one. Got REMOVE working. And the credentials file now is named (so each user that logs in can have their own credentials), and contains multiple credentials (rather than a credential file per IP.)
r5: Minor change - added cot cred (to see creds) and cot rcred (to remove a cred)...
r6: Minor change - added ?/help outputs

#>

#### END OF SCRIPT ####

Image: The obligatory image for the mobile version of blogger!

Comments