Add bulk credentials in bulk to Password Vault - powershell

Overview:
I have created a vault that stores sensitive data, you can see my full sample code in this question:
PowerShell Password Vault
Goal:
I am attempting to make a function that would add credentials in bulk. I am not looking for particular method. However, I did attempt to run a loop that would add creds on each new line. But, my logic is off somewhere, meaning that when I attempt to use the following code, it begins to add credentials in an erroneous manner- please see table below. I am very open to new ideas or suggestions as well.
Exact Code:
function Add-BulkCreds{
param(
[string]$ID,
[string]$Key,
[string]$URL
)
$vaultAssembly
do{
Write-Host 'AddCreds)' -ForegroundColor Yellow -NoNewline
$x = Read-Host
$first,$second,$third = $x -split '\s',3
$vault = New-Object Windows.Security.Credentials.PasswordVault
$cred = New-Object Windows.Security.Credentials.PasswordCredential($second, $third, $first)
$vault.Add($cred)
}while($x)
}
Example input:
PS > Add-BulkCreds
AddCreds)test1c1 test1c2 test1c3
test2c1 test2c2 test2c3
test3c1 test3c2 test3c3
AddCreds)
New-Object : Exception calling ".ctor" with "3" argument(s): "The parameter is incorrect.
Cannot create credential"
At C:\Users\getcred.ps1:83 char:13
+ $cred = New-Object Windows.Security.Credentials.PasswordCredential($second, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Output:
ID Key Endpoint
-------- ------ -----------
test1c3... test1c1 test1c2
Closer Look at ID column:
PS > $credexample.id | Where-Object {$_.key -eq 'test1c1'}
test1c3
test2c1 test2c2 test2c3
test3c1 test3c2 test3c3
Observation:
As you can see the following part of my input was added to my ID column:
test1c3
test2c1 test2c2 test2c3
test3c1 test3c2 test3c3
Whereas....
test1c1 was added to Key
test1c2 was added to endpoint
Question:
Given my goal and overview, how can I create a simple, yet efficient function for adding credentials in bulk? And, does my logic work?
Additionally:
I am realizing that the original parameters aren't even needed since I am splitting the variable below with $x.
param(
[string]$ID,
[string]$Key,
[string]$URL
)

Related

PowerShell authenticate and read google calendar events

Using PowerShell, I am trying to authenticate to Google calendar using a service account, and read events. With the help of stack overflow, I was able to install and import the required packages in my PowerShell session.
Newtonsoft.Json
Google.Apis.Core
Google.Apis
Google.Apis.Auth
Google.Apis.Calendar.v3
I then tried to read Google calendar events
# Set the credentials and calendar ID
$credentials = Get-Content "C:\Users\Windows\Desktop\powershell-376318-70973daa61d9.json" | ConvertFrom-Json
$calendarId = "primary"
# Build the calendar service
$service = New-Object Google.Apis.Calendar.v3.CalendarService
$service.Credentials = New-Object Google.Apis.Auth.OAuth2.GoogleCredential($credentials)
# Get the current time
$now = Get-Date
# Get the events for the next hour
$events = $service.Events.List($calendarId)
$events.TimeMin = $now
$events.TimeMax = $now.AddHours(1)
$events.SingleEvents = $true
$events.OrderBy = "startTime"
$events = $events.Execute()
# Print the events
foreach ($event in $events.Items) {
Write-Host "Event: $($event.Summary)"
Write-Host "Start Time: $($event.Start.DateTime)"
Write-Host "End Time: $($event.End.DateTime)"
Write-Host ""
}
But I get this error
New-Object : A constructor was not found. Cannot find an appropriate constructor for type
Google.Apis.Auth.OAuth2.GoogleCredential.
At line:7 char:24
+ ... edentials = New-Object Google.Apis.Auth.OAuth2.GoogleCredential($cred ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : CannotFindAppropriateCtor,Microsoft.PowerShell.Commands.NewObjectCommand
Exception calling "Execute" with "0" argument(s): "The service calendar has thrown an exception. HttpStatusCode is
Forbidden. The request is missing a valid API key."
At line:18 char:1
+ $events = $events.Execute()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : GoogleApiException
Obviously, there's an issue with "Google.Apis.Auth.OAuth2.GoogleCredential". I'm not sure it's even possible to authenticate and read events using a service account, but right now I don't know how to proceed with this.
I want to avoid using OAuth2 client id and client secret for authentication if possible, because I've had issues in the past with token expiries, whereas a service account doesn't expire.
The error message tells you exactly what the problem is:
Cannot find an appropriate constructor for type Google.Apis.Auth.OAuth2.GoogleCredential.
Having a look at the docs shows: There really is no constructor like GoogleCredential(string). But you can use different static methods to create a GoogleCredential object. E. g. FromJson(String):
# Set the credentials and calendar ID
$credentials = Get-Content -Raw -Path "C:\Users\Windows\Desktop\powershell-376318-70973daa61d9.json"
# Build the calendar service
$service = New-Object Google.Apis.Calendar.v3.CalendarService
$service.Credentials = [Google.Apis.Auth.OAuth2.GoogleCredential]::FromJson($credentials)
You can also pass the file directly to GoogleCredential via FromFile:
# Build the calendar service
$service = New-Object Google.Apis.Calendar.v3.CalendarService
$service.Credentials = [Google.Apis.Auth.OAuth2.GoogleCredential]::FromFile('C:\Users\Windows\Desktop\powershell-376318-70973daa61d9.json')

Why does PowerShell reject my secure string and say it cannot convert it to a secure string?

I am working on a script that will run New-RemoteMailbox with a generated string as the password argument. I have specific requirements for generating the password. It should begin with "Welcome" and then include some numbers and a few acceptable symbols. These are OTPs that will be used shortly after creation so I don't need them to be very strong.
Below is the code where I generate the password and convert it to a secure string:
[string]$Prefix = 'Welcome'
$Numbers = -join ((48..57) | Get-Random -Count 3 | % {[char]$_})
$Symbols = -join ((35..38)+(42)+(63..64)+(33) | Get-Random -Count 2 | % {[char]$_})
$Password = $Prefix + $Numbers + $Symbols
Write-Output "Temporary Password: $Password"
$Password = ConvertTo-SecureString -string $Password -AsPlainText -Force
Then here's where I use the variable later:
New-RemoteMailbox -Name "$FullN" -Password $Password -UserPrincipalName $Address -FirstName $FirstN -LastName $LastN -ResetPasswordOnNextLogon $true -SamAccountName $SamName
When I do that, I get the following error:
Cannot process argument transformation on parameter 'Password'. Cannot convert the "System.Security.SecureString" value of type "System.String" to type "System.Security.SecureString".
+ CategoryInfo : InvalidData: (:) [New-RemoteMailbox], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,New-RemoteMailbox
The rest of this script seems to work without issue. This particular problem only showed up once I introduced the custom password generation (the prebuilt password method often recommended online did not suit our needs, as it generates (){}[]-./\|=+;:, potentially needlessly complicating the process for a new user, but the method was not causing this error). I see there have been questions about this particular error before, but the solution to the ones I've seen was using ConvertTo-SecureString, which I have in the code. I also can add Write-Output $Password any time before the conversion and it seems to output what I would expect (example: Welcome267#&).
Any ideas?
As #MathiasR.Jessen said in the replies, the issue was that I declared [String]$Password (not shown in the question), which prevented it from converting to a secure string. Changing the declaration or just using a new variable both seem to work.

PowerShell Error: New-Object : Cannot find an overload for "PlatformParameters" and the argument count: "1"

I am trying to automatically upload a CSV into PowerBi using the Git repository PowerBIPS. I can't seem to get past this error:
New-Object : Cannot find an overload for "PlatformParameters" and the argument count: "1".
With the help of the article linked here (https://powerbi.microsoft.com/en-us/blog/using-a-power-bi-app-to-upload-csv-files-to-a-dataset/), I believe I have found a viable solution to solve this. However, I am running into an error I can't seem to figure out.
I have customized the code from the original article to fit my current situation (outlined in the code below). I am able to run the code up until the "send data to PowerBi comment" where this error is raised.
I have tried referencing the Git documentation to help with this issue, but have found no luck. I have a feeling it has to do with the authentication piece of connecting to PowerBi.
while ($true) {
# Iterate each CSV file and send to PowerBI
Get-ChildItem "$currentPath\CSVData" -Filter "*.csv" | % {
$file = $_
#Import csv and add column with filename
$data = Import-Csv $file.FullName |
select #{Label="File";Expression={$file.Name}}, *
# Send data to PowerBI
$data | Out-PowerBI -DataSetName "CSVSales" -TableName "Sales" -Types #{
"Sales.OrderDate" = "datetime";
"Sales.SalesAmount" = "double";
"Sales.Freight" = "double"
} -BatchSize 300 -Verbose
# Archive the file
Move-Item $file.FullName "$currentPath\CSVData\Archive\" -Force
}
Write-Output "Sleeping..."
Sleep -Seconds 5
}
VERBOSE: Getting the Authentication Token
VERBOSE: Using default authentication flow
New-Object : Cannot find an overload for "PlatformParameters" and the argument
count: "1".
At C:\Program Files\WindowsPowerShell\Modules\PowerBIPS\2.0.3.1\PowerBIPS.psm1:299 char:16
+ ... pltParams = New-Object Microsoft.IdentityModel.Clients.ActiveDirector ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

PowerShell: cannot convert type SMO.server to type SMO.server

Error I'm getting from PowerShell:
Cannot convert argument "srv", with value: "[DBADEV\SQL2008r2]", for "SqlBackup" to type "Microsoft.SqlServer.Management.Smo.Server": "Cannot convert the "[DBADEV\SQL2008r2]" value of type
"Microsoft.SqlServer.Management.Smo.Server" to type "Microsoft.SqlServer.Management.Smo.Server"."
At line:23 char:1
+ $backup.SqlBackup($srv)
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
I'm attempting to write a PowerShell script to restore a database from our Production box and into our DBADEV box. Below is the code I'm using which is then producing the error.
#Clear Screen
cls
#load assemblies
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
$ErrorActionPreference = "Inquire"
# Restore [SQLSRV2k8-0102\SQL2008] instance
$BackupFile = Get-ChildItem "\\NetworkShare\r`$\MSSQL10.SQL2008\MSSQL\Backup\AdventureWorks2008r2" | select -Last 1
$BackupFile
$srv = New-Object Microsoft.SqlServer.Management.Smo.Server("DBADEV\SQL2008r2")
$res = New-Object Microsoft.SqlServer.Management.Smo.Restore
$backup = New-Object Microsoft.SqlServer.Management.Smo.Backup
$Backup.Devices.AddDevice($BackupFile, [Microsoft.SqlServer.Management.Smo.DeviceType]::File)
$Backup.Database = "AdventureWorks2008r2"
$Backup.Action = [Microsoft.SqlServer.Management.Smo.BackupActionType]::Database
$backup.Initialize = $true
$backup.SqlBackup($srv)
$srv.Databases["AdventureWorks2008r2"].Drop()
$res.Devices.AddDevice($BackupFile, [Microsoft.SqlServer.Management.Smo.DeviceType]::File)
$res.Database = "AdventureWorks2008r2"
$res.NoRecovery = $true
$res.SqlRestore($srv)
The error seems a bit cryptic to me (as do most PowerShell errors). Any thoughts on why this is occurring? I'm also getting the error when I use Mike Fal's powershell script here: http://www.mikefal.net/2014/07/22/restoreautomation-powershell-module/
The one thing that seems to get me past this error is by passing "DBADEV\SQL2008r2" directly into SQLRestore,
i.e. $res.SqlRestore("DBADEV\SQL2008r2") instead of $res.SqlRestore($srv)
This now generate an error stating "Restore failed for Server 'DBADEV\SQL2008r2'
Well from my experiences this kind of errors appear because of wrong name/data type in variable.
I would try to escape \ in "DBADEV\SQL2008r2"
or try what I found on MSDN
$srv = new-Object Microsoft.SqlServer.Management.Smo.Server("(local)")
Write-Host $srv.Information.Version
so it could look like
New-Object Microsoft.SqlServer.Management.Smo.Server("(DBADEV\SQL2008r2)")

Binding to a different active directory ldap instance in Powershell

I am trying to connect to some independent LDAP stores (ADAM - Active Directory Application Mode) using a specific set of credentials to bind with, but having trouble working out the best way to do this. Here is an example which I had hoped would work:
$ldapHost = New-Object System.DirectoryServices.DirectoryEntry("LDAP://{serverip}:{port}/dc=acme,dc=com","cn=myuser,dc=acme,dc=com","myPassw0rd")
$ldapQuery = New-Object System.DirectoryServices.DirectorySearcher
$ldapQuery.SearchRoot = $ldapHost
$ldapQuery.Filter = "(objectclass=*)"
$ldapQuery.SearchScope = "Base"
$ldapQuery.FindAll()
This will get me:
Exception calling "FindAll" with "0" argument(s): "A local error has occurred.
"
At line:1 char:19
+ $ldapQuery.FindAll <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
I also tried:
$ldapHost = New-Object System.DirectoryServices.DirectoryEntry("LDAP://{myip}:{port}/dc=acme,dc=com")
$ldapHost.Username = "cn=myuser,dc=acme,dc=com"
which results:
The following exception occurred while retrieving member "Username": "The specified directory service attribute or valu
e does not exist.
"
At line:1 char:11
+ $ldapHost. <<<< Username = "cn=myuser,DC=acme,dc=com"
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
I've tried a few variations with filter etc. Most of the documentation I can find on this just assumes that I'm connecting to ldap from within the same directory/am connecting with the correct user for the query.
If you're familiar with Python's ldap module, this is how I do it in that:
import ldap
ld = ldap.initialize("ldap://{myip}:{port}")
ld.bind_s("cn=myuser,dc=acme,dc=com","Passw0rd")
ld.search_s("dc=acme,dc=com",ldap.SCOPE_BASE,"objectclass=*")
Any pointers on how to approach this? I can definitely connect via the various LDAP clients out there. I might need to explicitly specify authentication, but I'm not sure because there is so little information on querying from outside the domain.
You can try this...I use it to connect to an OpenLDAP instance and it works well. Works against AD also so it should fit your needs. You'll need to update the $basedn variable and the host/username ones.
$hostname = ''
$username = ''
$Null = [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")
#Connects to LDAP
$LDAPConnect = New-Object System.DirectoryServices.Protocols.LdapConnection "$HostName"
#Set session options (SSL + LDAP V3)
$LDAPConnect.SessionOptions.SecureSocketLayer = $true
$LDAPConnect.SessionOptions.ProtocolVersion = 3
# Pick Authentication type:
# Anonymous, Basic, Digest, DPA (Distributed Password Authentication),
# External, Kerberos, Msn, Negotiate, Ntlm, Sicily
$LDAPConnect.AuthType = [System.DirectoryServices.Protocols.AuthType]::Basic
# Gets username and password.
$credentials = new-object "System.Net.NetworkCredential" -ArgumentList $UserName,(Read-Host "Password" -AsSecureString)
# Bind with the network credentials. Depending on the type of server,
# the username will take different forms.
Try {
$ErrorActionPreference = 'Stop'
$LDAPConnect.Bind($credentials)
$ErrorActionPreference = 'Continue'
}
Catch {
Throw "Error binding to ldap - $($_.Exception.Message)"
}
Write-Verbose "Successfully bound to LDAP!" -Verbose
$basedn = "OU=Users and Groups,DC=TEST,DC=NET"
$scope = [System.DirectoryServices.Protocols.SearchScope]::Subtree
#Null returns all available attributes
$attrlist = $null
$filter = "(objectClass=*)"
$ModelQuery = New-Object System.DirectoryServices.Protocols.SearchRequest -ArgumentList $basedn,$filter,$scope,$attrlist
#$ModelRequest is a System.DirectoryServices.Protocols.SearchResponse
Try {
$ErrorActionPreference = 'Stop'
$ModelRequest = $LDAPConnect.SendRequest($ModelQuery)
$ErrorActionPreference = 'Continue'
}
Catch {
Throw "Problem looking up model account - $($_.Exception.Message)"
}
$ModelRequest
Credit for most of this goes here..
http://mikemstech.blogspot.com/2013/03/searching-non-microsoft-ldap.html
This worked for me. Only use this for testing purposes since password is not secured at all.
Add-Type -AssemblyName System.DirectoryServices.Protocols
$server = test.com
$username = "CN=username,OU=users,DC=test,DC=com"
$password = "userpassword"
$Credentials = new-object System.Net.NetworkCredential($username, $password)
$LdapConnection = New-Object System.DirectoryServices.Protocols.LdapConnection $server
# Basic auth, cleartext password using port 389
$LdapConnection.AuthType = [System.DirectoryServices.Protocols.AuthType]::Basic
$LdapConnection.Bind($Credentials)
$LdapConnection.Dispose()