function Start-CaiwuDeploymentAuth { param([string]$Server, [string]$SshUser, [string]$KeyPath, [Security.SecureString]$Password, [switch]$UpdatePassword) if ($Server -notmatch '^[A-Za-z0-9][A-Za-z0-9.-]*$' -or $SshUser -notmatch '^[A-Za-z_][A-Za-z0-9_-]*$') { throw '服务器地址或登录用户名格式无效。' } $options = @('-o', 'StrictHostKeyChecking=accept-new', '-o', 'ConnectTimeout=10') if (-not [string]::IsNullOrWhiteSpace($KeyPath)) { return @{ Options = $options + @('-i', (Resolve-Path -LiteralPath $KeyPath).Path, '-o', 'BatchMode=yes'); Directory = $null; Saved = @{} } } $directory = Join-Path ([Environment]::GetFolderPath('LocalApplicationData')) "CaiWuXiTong/deploy-credentials/${SshUser}@${Server}" [IO.Directory]::CreateDirectory($directory) | Out-Null $session = @{ Directory = $directory; Saved = @{}; Options = $options + @('-o', 'BatchMode=no', '-o', 'PreferredAuthentications=password', '-o', 'PubkeyAuthentication=no', '-o', 'NumberOfPasswordPrompts=1') } try { $acl = [Security.AccessControl.DirectorySecurity]::new() $acl.SetAccessRuleProtection($true, $false) $owner = [Security.Principal.WindowsIdentity]::GetCurrent().User $acl.SetOwner($owner) $acl.AddAccessRule([Security.AccessControl.FileSystemAccessRule]::new($owner, 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow')) [IO.FileSystemAclExtensions]::SetAccessControl([IO.DirectoryInfo]::new($directory), $acl) $values = @{ SSH_ASKPASS = (Join-Path $PSScriptRoot 'deploy-password-prompt.cmd') SSH_ASKPASS_REQUIRE = 'force' DISPLAY = 'caiwu-deploy' CAIWU_DEPLOY_LOGIN = "${SshUser}@${Server}" CAIWU_DEPLOY_PASSWORD_CACHE = (Join-Path $directory 'password.dpapi') CAIWU_DEPLOY_PASSWORD_UPDATE = $(if ($UpdatePassword) { '1' } else { $null }) } foreach ($name in $values.Keys) { $session.Saved[$name] = [Environment]::GetEnvironmentVariable($name, 'Process') [Environment]::SetEnvironmentVariable($name, $values[$name], 'Process') } if ($Password) { $Password | ConvertFrom-SecureString | Set-Content -LiteralPath $env:CAIWU_DEPLOY_PASSWORD_CACHE -Encoding ASCII $env:CAIWU_DEPLOY_PASSWORD_UPDATE = $null } if (Test-Path -LiteralPath $env:CAIWU_DEPLOY_PASSWORD_CACHE) { Write-Host '正在使用本机已保存的部署登录信息。' } else { Write-Host '首次部署:请在本机窗口输入服务器密码。此后自动使用已保存的登录信息。' } return $session } catch { Stop-CaiwuDeploymentAuth $session throw } } function Stop-CaiwuDeploymentAuth { param($Session) if (-not $Session) { return } foreach ($name in $Session.Saved.Keys) { [Environment]::SetEnvironmentVariable($name, $Session.Saved[$name], 'Process') } }