General

Use Powershell To Create Local User Account, Generate Password and Store in KeePass Database

(Note i believe a  PoshKeePass module has been created by Jason Fossen over on GitHub – I recommend to use that going forward)

When you take over a large estate where the same username and password has been used for the local admin – the first thing that comes to mind was how can I automate this?

We were still in the process of trialing LastPass for Enterprise and therefore was still using KeePass.  I come across a great script which I slightly tweaked which allows you to:

  • Define local user account
  • Add account to local admins group
  • Generate random 20 character password
  • Sets password to never expire (depending on compliance of course)
  • Saves information into KeePass

The script is below:


#Specifiy Local admin account name
$user = "localuseradmin"

Add-Type -Assembly System.Web
$pass=[Web.Security.Membership]::GeneratePassword(20,0)
NET USER $user "$pass" /ADD /y
#Add user to local admin group
NET LOCALGROUP "Administrators" "$user" /add
#set password to never expire
WMIC USERACCOUNT WHERE "Name='$user'" SET PasswordExpires=FALSE

Write-Host "Username: $user" -foregroundcolor green -backgroundcolor black
Write-Host "Password: $pass" -foregroundcolor green -backgroundcolor black
Write-host "Server: $env:computername" -foregroundcolor green -backgroundcolor black

# Load the classes from KeePass.exe:
cd "\\path\to\keepass\KeePass-2.34" | out-null
(Get-ChildItem -recurse $script:myinvocation.mycommand.path | Where-Object {($_.Extension -EQ ".dll") -or ($_.Extension -eq ".exe")} | ForEach-Object { $AssemblyName=$_.FullName; Try {[Reflection.Assembly]::LoadFile($AssemblyName) } Catch{ }} ) | out-null

# To open a KeePass database, the decryption key is required, and this key
# may be a constructed from a password, key file, Windows user account,
# and/or other information sources.

# $CompositeKey represents a key, possibly constructed from multiple sources of data.
# The other key-related objects are added to this composite key.
$CompositeKey = New-Object -TypeName KeePassLib.Keys.CompositeKey #From KeePass.exe

# The currently logged-on Windows user account can be added to a composite key.
#$KcpUserAccount = New-Object -TypeName KeePassLib.Keys.KcpUserAccount #From KeePass.exe

#load VB Assembly
[void][System.Reflection.Assembly]::LoadWithPartialName(
"Microsoft.VisualBasic")

# A password can be added to a composite key.
$Password = [Microsoft.VisualBasic.Interaction]::InputBox("Please enter the Password for Keypass", "Password")
$KcpPassword = New-Object -TypeName KeePassLib.Keys.KcpPassword($Password)

# Add the Windows user account key to the $CompositeKey, if necessary:
#$CompositeKey.AddUserKey( $KcpUserAccount )
$CompositeKey.AddUserKey( $KcpPassword )
#$CompositeKey.AddUserKey( $KcpKeyFile )

###########################################################################
#
# To open a KeePass database, the path to the .KDBX file is required.
#
###########################################################################

$IOConnectionInfo = New-Object KeePassLib.Serialization.IOConnectionInfo
$IOConnectionInfo.Path = '\\\\path\to\keepass\KeePass-2.34\IT Infrastructure.kdbx'

###########################################################################
#
# To open a KeePass database, an object is needed to record status info.
# In this case, the progress status information is ignored.
#
###########################################################################

$StatusLogger = New-Object KeePassLib.Interfaces.NullStatusLogger

###########################################################################
#
# Open the KeePass database with key, path and logger objects.
# $PwDatabase represents a KeePass database.
#
###########################################################################

$PwDatabase = New-Object -TypeName KeePassLib.PwDatabase #From KeePass.exe
$PwDatabase.Open($IOConnectionInfo, $CompositeKey, $StatusLogger)

###########################################################################
#
# List groups. A group is shown as a folder name in the KeePass GUI.
#
###########################################################################

#$PwDatabase.RootGroup.Groups
#$PwDatabase.RootGroup.Groups | Format-Table Name,LastModificationTime,Groups -AutoSize

###########################################################################
#
# Function to add an entry to a KeePass database.
#
###########################################################################

function New-KeePassEntry
{

[CmdletBinding(DefaultParametersetName="Plain")]
Param
(
[Parameter(Mandatory=$true)] [KeePassLib.PwDatabase] $PwDatabase,
[Parameter(Mandatory=$true)] [String] $TopLevelGroupName,
[Parameter(Mandatory=$true)] [String] $Title,
[Parameter(ParameterSetName="Plain")] [String] $UserName,
[Parameter(ParameterSetName="Plain")] [String] $Password,
[Parameter(ParameterSetName="Cred")] [System.Management.Automation.PSCredential] $PSCredential,
[String] $URL,
[String] $Notes
)
# This only works for a top-level group, not a nested subgroup:
$PwGroup = @( $PwDatabase.RootGroup.Groups | where { $_.name -eq $TopLevelGroupName } )

# Confirm that one and only one matching group was found
if ($PwGroup.Count -eq 0) { throw "ERROR: $TopLevelGroupName group not found" ; return }
elseif ($PwGroup.Count -gt 1) { throw "ERROR: Multiple groups named $TopLevelGroupName" ; return }

# Use PSCredential, if provided, for username and password:
if ($PSCredential)
{
$UserName = $PSCredential.UserName
$Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($PSCredential.Password))
}

# The $True arguments allow new UUID and timestamps to be created automatically:
$PwEntry = New-Object -TypeName KeePassLib.PwEntry( $PwGroup[0], $True, $True )

# Protected strings are encrypted in memory:
$pTitle = New-Object KeePassLib.Security.ProtectedString($True, $Title)
$pUser = New-Object KeePassLib.Security.ProtectedString($True, $UserName)
$pPW = New-Object KeePassLib.Security.ProtectedString($True, $Password)
$pURL = New-Object KeePassLib.Security.ProtectedString($True, $URL)
$pNotes = New-Object KeePassLib.Security.ProtectedString($True, $Notes)

$PwEntry.Strings.Set("Title", $pTitle)
$PwEntry.Strings.Set("UserName", $pUser)
$PwEntry.Strings.Set("Password", $pPW)
$PwEntry.Strings.Set("URL", $pURL)
$PwEntry.Strings.Set("Notes", $pNotes)

$PwGroup[0].AddEntry($PwEntry, $True)

# Notice that the database is automatically saved here!
$StatusLogger = New-Object KeePassLib.Interfaces.NullStatusLogger
$PwDatabase.Save($StatusLogger)

}
New-KeePassEntry -PwDatabase $PwDatabase -TopLevelGroupName 'Windows' -Title "$env:computername Local Administrator" -UserName "$user" -Password "$pass" -URL "N/A" -Notes "N/A"

#Close the open database.
$PwDatabase.Close()