Simplifying SSH Key Management setup with PowerShell

Page content

Simplifying SSH Key Management setup with PowerShell

Introduction

Managing SSH keys effectively is crucial for maintaining secure and efficient access to remote systems. This blog post introduces a PowerShell script designed to configure an SSH-Agent on Windows 11 with keys. I use this method when I first build a new Windows 11. Using SSH-Agent allows me to use forwarding agent requests and allows for using Yubikey certificates acorss an RDP session. The management of SSH keys by automating the key addition, configuration, and cleanup processes.

Overview of the Script

This PowerShell script simplifies SSH key management by:

  1. Ensuring the ssh-agent service is running and set to start automatically.
  2. Copying private key files (.key) from a specified source folder to the .ssh directory.
  3. Adding the private keys to ssh-agent.
  4. Updating the SSH config file with predefined host configurations.
  5. Cleaning up by removing the private key files after adding them to ssh-agent.

How the Script Works

Step 1: Checking Administrative Privileges

The script starts by verifying if it is run with administrative privileges, as managing the ssh-agent service requires elevated rights.

if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Error "This script must be run as an administrator."
    exit 1
}

Step 2: Managing the ssh-agent Service

The script ensures that the ssh-agent service is active and configured to start automatically.

Get-Service ssh-agent | Set-Service -StartupType Automatic -PassThru | Start-Service

Step 3: Copying and Adding Keys

Private keys are copied from the specified source folder to the .ssh directory. After copying, each key is added to the ssh-agent.

Get-ChildItem -Path $sourceFolder -Recurse -Filter "*.key" | ForEach-Object {
    Copy-Item -Path $_.FullName -Destination $destinationFile -Force
    ssh-add $destinationFile
}

Step 4: Cleaning Up Key Files

Once the keys are added to ssh-agent, they are removed from the .ssh directory to enhance security.

Get-ChildItem -Path $destinationFolder -Filter "*.key" | ForEach-Object {
    Remove-Item -Path $_.FullName -Force
}

Step 5: Updating SSH Configurations

The script appends predefined host configurations to the SSH config file, ensuring consistent and secure connection settings.

Add-Content -Path $sshConfigFile -Value $newHostConfig

Customization and Usage

You can customize the source folder path and the SSH host configurations as needed. To run the script, use the following command:

.\ManageSSH.ps1 -sourceFolder "Path\To\Your\Keys"

Complete Script

<#
.SYNOPSIS
    Manages SSH keys by ensuring the ssh-agent is running, copying keys, adding them to the agent, 
    updating the SSH config file, and removing the copied key files after adding them to ssh-agent.

.DESCRIPTION
    This script performs the following tasks:
    - Ensures the ssh-agent service is running and set to start automatically.
    - Recursively copies private key files (.key) from a specified source folder to the .ssh directory.
    - Adds the private keys to the ssh-agent.
    - Updates the SSH config file with specified host configurations.
    - Removes all private key files from the .ssh directory after they are added to ssh-agent.

.PARAMETER sourceFolder
    The path to the folder containing the private key files to be processed.

.EXAMPLE
    .\ManageSSH.ps1 -sourceFolder "G:\Keys"

    This command recursively copies all .key files from "G:\Keys" to the .ssh directory, 
    adds them to the ssh-agent, updates the SSH config, and removes the copied keys.

.NOTES
    Author: Craig
    Date: 2024-11-03
    Version: 1.3
#>

param (
    [string]$sourceFolder
)

# Check for administrative privileges
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Error "This script must be run as an administrator."
    exit 1
}

Write-Output "Starting SSH key management process..."

# Ensure ssh-agent service is set to start automatically and is running
Write-Output "Ensuring ssh-agent service is running..."
Get-Service ssh-agent | Set-Service -StartupType Automatic -PassThru | Start-Service
Write-Output "ssh-agent service is running."

# Define the destination folder as the .ssh directory in the user's profile
$destinationFolder = "$($env:USERPROFILE)\.ssh"

# Create the .ssh folder if it doesn't exist
if (!(Test-Path -Path $destinationFolder)) {
    Write-Output "Creating .ssh directory at $destinationFolder..."
    New-Item -ItemType Directory -Path $destinationFolder | Out-Null
    Write-Output ".ssh directory created."
} else {
    Write-Output ".ssh directory already exists at $destinationFolder."
}

# Process .key files: copy to .ssh, add to ssh-agent
Write-Output "Processing private keys from $sourceFolder..."
Get-ChildItem -Path $sourceFolder -Recurse -Filter "*.key" | ForEach-Object {
    $sourceFile = $_.FullName
    $destinationFile = Join-Path -Path $destinationFolder -ChildPath $_.Name
    
    # Log the file being processed
    Write-Output "Processing file: $sourceFile"

    # Copy the key file to the .ssh directory
    Copy-Item -Path $sourceFile -Destination $destinationFile -Force
    Write-Output "Copied: $sourceFile to $destinationFile"
    
    # Add the key to the ssh-agent
    ssh-add $destinationFile
    Write-Output "Added key to ssh-agent: $destinationFile"
}

Write-Output "All private keys added to ssh-agent."

# Remove all .key files from the .ssh directory
Write-Output "Cleaning up .ssh directory by removing all .key files..."
Get-ChildItem -Path $destinationFolder -Filter "*.key" | ForEach-Object {
    Write-Output "Removing key file: $($_.FullName)"
    Remove-Item -Path $_.FullName -Force
    Write-Output "Removed key file: $($_.FullName)"
}

# Define the path to the SSH config file
$sshConfigFile = Join-Path -Path $destinationFolder -ChildPath "config"

# Check if config file exists, create if it doesn't
if (!(Test-Path -Path $sshConfigFile)) {
    Write-Output "Creating SSH config file at $sshConfigFile..."
    New-Item -ItemType File -Path $sshConfigFile | Out-Null
    Write-Output "SSH config file created."
} else {
    Write-Output "SSH config file already exists at $sshConfigFile."
}

# Define the new host configuration as a string
$newHostConfig = @"
# Default settings for all hosts
Host *
    ForwardAgent yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/id_rsa
    ServerAliveInterval 60
    ServerAliveCountMax 3

# Specific host configuration
Host host-01
    HostName host-01
    User craig
    port 22

"@

# Append the new host configuration to the SSH config file
Write-Output "Appending new host configurations to SSH config file..."
Add-Content -Path $sshConfigFile -Value $newHostConfig
Write-Output "New host configurations added to SSH config."

Write-Output "SSH key management process completed."

Conclusion

This PowerShell script automates the setup task of managing SSH keys, making it easier to maintain secure and organized SSH configurations. By integrating this script into your workflow, you can ensure that your SSH key configuration is efficient and secure.