Public/Import-SshId.ps1

function Import-SshId {
    <#
    .SYNOPSIS
        Imports SSH public keys published by an online identity into a local
        authorized_keys file, PowerShell-native re-implementation of the
        classic `ssh-import-id` tool.
 
    .DESCRIPTION
        Fetches public keys published at a well-known URL for a given
        '<prefix>:<username>' identity (built-in: gh, gl, lp - see
        Get-SshImportIdSource for custom prefixes) and appends any keys not
        already present to the target authorized_keys file. Each imported
        key is tagged with a trailing comment identifying its source, and
        duplicate keys already on file are skipped.
 
        After a successful import, NTFS permissions on the authorized_keys
        file and its parent .ssh directory are locked down so the Windows
        OpenSSH server will accept the file.
 
    .PARAMETER UserId
        One or more identities in '<prefix>:<username>' form, e.g.
        'gh:octocat', 'gl:someone', 'lp:someone'.
 
    .PARAMETER AuthorizedKeysPath
        Path to the authorized_keys file to update. Defaults to
        '$HOME\.ssh\authorized_keys', or to the Windows OpenSSH
        administrators_authorized_keys path when -ForAdministrators is set.
 
    .PARAMETER ForAdministrators
        Target Windows OpenSSH's shared
        '%ProgramData%\ssh\administrators_authorized_keys' file instead of
        the per-user authorized_keys file. On Windows, sshd routes members
        of the local Administrators group to this file regardless of their
        own '.ssh\authorized_keys', and requires it to grant access to only
        SYSTEM and Administrators (not even the admin's own account may
        hold an explicit ACE). Writing to it requires an elevated (Run as
        Administrator) session, and the '%ProgramData%\ssh' directory must
        already exist (created by installing the OpenSSH Server Windows
        feature) - this command will not create it, nor will it touch that
        directory's own permissions.
 
    .PARAMETER PassThru
        Emit a result object per identity describing how many keys were
        added/skipped.
 
    .EXAMPLE
        Import-SshId gh:octocat
 
        Imports all public keys published on octocat's GitHub profile.
 
    .EXAMPLE
        'gh:octocat', 'lp:someone' | Import-SshId -Verbose
 
        Imports keys for multiple identities piped in, with verbose logging.
 
    .EXAMPLE
        ssh-import-id gh:octocat -WhatIf
 
        Uses the ssh-import-id alias and previews the change without writing.
 
    .EXAMPLE
        Import-SshId gh:octocat -ForAdministrators
 
        Imports into '%ProgramData%\ssh\administrators_authorized_keys' for
        an account that logs in as a member of Administrators. Must be run
        elevated.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('Id')]
        [string[]] $UserId,

        [string] $AuthorizedKeysPath,

        [switch] $ForAdministrators,

        [switch] $PassThru
    )

    begin {
        if (-not $PSBoundParameters.ContainsKey('AuthorizedKeysPath')) {
            $AuthorizedKeysPath = Get-SshImportIdDefaultAuthorizedKeysPath -ForAdministrators:$ForAdministrators
        }
    }

    process {
        foreach ($uid in $UserId) {
            try {
                $resolved = Resolve-SshImportIdUrl -UserId $uid

                if (-not $PSCmdlet.ShouldProcess($AuthorizedKeysPath, "Import SSH keys for '$uid'")) {
                    continue
                }

                $isAdminKeyFile = Test-SshImportIdAdministratorsAuthorizedKeysPath -Path $AuthorizedKeysPath
                if ($isAdminKeyFile) {
                    if (-not (Test-SshImportIdElevated)) {
                        throw "Writing to '$AuthorizedKeysPath' requires an elevated (Run as Administrator) PowerShell session."
                    }
                    $parentDir = Split-Path -Parent $AuthorizedKeysPath
                    if (-not (Test-Path -Path $parentDir -PathType Container)) {
                        throw "'$parentDir' does not exist. Install the OpenSSH Server Windows feature before importing keys for administrators."
                    }
                }

                Write-Verbose "Fetching keys for '$uid' from $($resolved.Url)"
                $lines = Invoke-SshImportIdFetch -Url $resolved.Url
                $validLines = @($lines | Where-Object { $_ -match '^(ssh-|ecdsa-|sk-)' })

                if (-not $validLines) {
                    Write-Warning "No valid SSH public keys found for '$uid'."
                    continue
                }

                $result = Add-SshImportIdAuthorizedKey -Path $AuthorizedKeysPath -KeyLine $validLines -Tag $uid

                if ($result.Added.Count -gt 0) {
                    if (-not $isAdminKeyFile) {
                        # %ProgramData%\ssh is shared by sshd (host keys,
                        # sshd_config, ...); only the file itself is ours to
                        # lock down, never its parent directory.
                        Set-SshImportIdPermission -Path (Split-Path -Parent $AuthorizedKeysPath)
                    }
                    Set-SshImportIdPermission -Path $AuthorizedKeysPath
                }

                foreach ($key in $result.Added) {
                    $preview = if ($key.Length -gt 60) { $key.Substring(0, 60) + '...' } else { $key }
                    Write-Host "[+] $uid : $preview" -ForegroundColor Green
                }
                foreach ($key in $result.Skipped) {
                    Write-Verbose "Skipped duplicate key for '$uid': $key"
                }

                $obj = [pscustomobject]@{
                    UserId  = $uid
                    Source  = $resolved.Prefix
                    Added   = $result.Added.Count
                    Skipped = $result.Skipped.Count
                    Path    = $AuthorizedKeysPath
                }

                if ($PassThru) {
                    $obj
                }
            } catch {
                Write-Error "Failed to import '$uid': $($_.Exception.Message)"
            }
        }
    }
}

Set-Alias -Name ssh-import-id -Value Import-SshId