Ssh.ps1
function Initialize-Ssh { if (-Not(Get-Command "ssh" -ErrorAction SilentlyContinue)) { Install-Scoop scoop install ssh } } function Connect-Ssh { param( [Parameter(mandatory = $True)] [string] $Ip, [String] $Command ) Initialize-Ssh # if copy-key # scp -o UserKnownHostsFile=/dev/null -o "StrictHostKeyChecking=no " $KEY_PATH $host:/home/box/.ssh/id_ed25519 # ssh -t $host "sed -i 's/\r//' .ssh/id_ed25519 && chmod 600 .ssh/id_ed25519" Write-Host "Connecting to host ${Ip} port 22 ..." do { try { ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR root@$Ip $Command } catch {} } while (-Not $Success) } function Get-SshConfigFile { "${env:USERPROFILE}\.ssh\config" } function Get-SshKey { param( [string] $Type = "ed25519", # or rsa [string] $Name, [switch] $Public ) Initialize-Ssh if (-not(Test-Path -Path $HOME/.ssh -PathType Container)) { New-Item -Path $HOME/.ssh -ItemType Directory | Out-Null } $keyPath = "$global:HOME/.ssh/id_${Type}_box" if (-not(Test-Path -Path $keyPath -PathType Leaf)) { Write-Host("Creando clave ssh '${keyPath}'") # No podem crear una clau sense contrasenya sense preguntar a l'usuari fent servir la opció -N '' perquè a vegades ha de ser '""', però a vegades ha de ser 'xxxxx' mínim 5 caracters i no admet '""'. if ($Type -Eq "ed25519") { ssh-keygen -t ed25519 -f ${keyPath} | Out-Null } else { ssh-keygen -m PEM -t rsa -b 4096 -f ${keyPath} | Out-Null } } if ($Public) { $keyPath = $keyPath + ".pub" } return $keyPath } function Get-ConfigKeyWords { return @("Match", "AddressFamily", "BatchMode", "BindAddress", "ChallengeResponseAuthentication", "CheckHostIP", "Cipher", "Ciphers", "ClearAllForwardings", "Compression", "CompressionLevel", "ConnectionAttempts", "ConnectTimeout", "ControlMaster", "ControlPath", "DynamicForward", "EscapeChar", "ExitOnForwardFailure", "ForwardAgent", "ForwardX11", "ForwardX11Trusted", "GatewayPorts", "GlobalKnownHostsFile", "GSSAPIAuthentication", "GSSAPIKeyExchange", "GSSAPIClientIdentity", "GSSAPIDelegateCredentials", "GSSAPIRenewalForcesRekey", "GSSAPITrustDns", "HashKnownHosts", "HostbasedAuthentication", "HostKeyAlgorithms", "HostKeyAlias", "HostName", "IdentitiesOnly", "IdentityFile", "KbdInteractiveAuthentication", "KbdInteractiveDevices", "LocalCommand", "LocalForward", "LogLevel", "MACs", "NoHostAuthenticationForLocalhost", "PreferredAuthentications", "Protocol", "ProxyCommand", "PubkeyAuthentication", "RemoteForward", "RhostsRSAAuthentication", "RSAAuthentication", "SendEnv", "ServerAliveCountMax", "ServerAliveInterval", "SmartcardDevice", "StrictHostKeyChecking", "TCPKeepAlive", "Tunnel", "TunnelDevice", "UsePrivilegedPort", "User", "UserKnownHostsFile", "VerifyHostKeyDNS", "VisualHostKey") } function Get-ConfigHostList { $hostList = @{} $configFile = Get-SshConfigFile if (-Not(Test-Path -Path $configFile)) { return $hostList } $contents = Get-Content $configFile -Raw # determine line break LF or CR/LF if ($contents -match "^[^\n]+\r\n") { $splitter = "\r\n" } else { $splitter = "\n" } # split by "Host" - when at start of file or has prededing line breaks / whitespaces $splitEntries = "(?i)(^|" + $splitter + "+\s+)host\s" $list = [regex]::Split($contents, $splitEntries) if ($list.Count -le 1) { throw "splitting file $configFilename failed or no content" } # READ lists of hosts foreach ($entry in $list) { # $output += $entry -replace $($splitter+"\s+"), $($joiner+" ") $attributes = [regex]::Split($entry, $splitter) | % { $_.Trim() } $HostName = $null $HostValues = @{} foreach ($attribute in $attributes) { if ($attribute -ne "") { if ($HostName) { # split key/value and normalize key name $kv = [regex]::Split($attribute, "\s+", 1) $keyName = $kv[0] $keyValue = $kv[1] foreach ($keyword in ($keywords | ? { $_ -eq $keyName })) { $keyName = $keyword break } $HostValues[$keyName] = $keyValue } else { # assume first entry to be the host $HostName = $attribute.ToLower() } } } if ($HostName) { if ($hostList.ContainsKey($HostName)) { throw "duplicate Host $HostName" } else { $hostList[$HostName] = $HostValues } } } return $hostList } function Add-ConfigHostToList { param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [hashtable] $hostList, [Parameter(Mandatory = $true)] [string] $HostName, [Parameter(Mandatory = $true)] [hashtable] $HostValues, [switch] $IgnoreExisting ) if (!$IgnoreExisting) { if ($hostList.ContainsKey($HostName.ToLower())) { throw "HostName $HostName already exists" } } $keywords = Get-ConfigKeyWords $hostValuesCleaned = @{} foreach ($kv in $HostValues.GetEnumerator()) { $keyName = $null foreach ($keyword in ($keywords | ? { $_ -eq $kv.Key })) { $keyName = $keyword break } if ($keyName) { $hostValuesCleaned[$keyName] = $kv.Value.Trim() } else { throw "key $($kv.Key) not found in list of keywords" } } if ($HostValuesCleaned) { $hostList[$HostName.ToLower()] = $HostValuesCleaned } return $hostList } function Set-ConfigContents { param ( [Parameter(Mandatory = $true)] [string] $Contents ) $configFilename = Get-SshConfigFile if ($Contents) { $Contents | Set-Content $configFilename } } function Set-ConfigHostList { param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [hashtable] $hostList ) $output = @() foreach ($hostEntry in $hostList.GetEnumerator()) { $hostOutput = "Host " + $hostEntry.Key + $joiner foreach ($kv in $hostEntry.Value.GetEnumerator()) { $hostOutput = $hostOutput + " " + $kv.key + " " + $kv.value + "`n" } $output += $hostOutput } if ($output) { $content = $($output -join "`n") $content | Set-Content (Get-SshConfigFile) } } function Set-SshAcl { param( [string] $Key ) # TODO test $acl = Get-Acl -Path $Key $acl.SetAccessRuleProtection($False, $False) $acl.RemoveAccessRuleAll($_) # icacls.exe $file /c /t /Grant ${env:UserName}:F # Set Ownership to Owner $acl.SetAccessRule((New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList (${env:UserName}) "FullControl" "Allow")) Set-Acl -Path $Key -AclObject $acl } |