当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 通过 10 个步骤保护 WinRM for Ansible(证书)[操作方法]

作者:精品下载站 日期:2024-12-14 13:01:32 浏览:14 分类:玩电脑

通过 10 个步骤保护 WinRM for Ansible(证书)[操作方法]


Ansible 正在成为当今最常用的配置管理工具之一(如果不是)。 Ansible 是一个方便的(在大多数情况下是免费的)工具,允许 DevOps 工程师和系统工程师/管理员以幂等、基础设施即代码的方式跨所有环境构建和维护基础设施。但是,将其配置为通过 WinRM for Ansible 与 Windows 对话可能是一个挑战。

与许多其他基础设施组件一样,Ansible 可以跨 Windows 主机部署和维护配置状态。 Ansible 通过 WinRM 连接到这些 Windows 主机,尽管他们正在试验 SSH。

当您为 Ansible 配置 WinRm 时,您有一些不同的选项,从易于设置到安全隐患。很多人选择简单的方法;使用 HTTP 的基本身份验证。尽管您放弃了涉及证书的额外工作,但除非必要,否则通过网络发送未加密的数据绝不是一个好主意。

在本文中,您将学习如何使用自签名证书使用基于证书的身份验证为 Ansible 设置 WinRm,以便 Ansible 可以与它们通信。

您将在本教程中学习的设置不仅仅适用于 Ansible 作为客户端。这种基于证书的身份验证可以同样适用于其他 WinRm 客户端,如其他 Windows 主机。

假设

本文将是基于教程的演练。如果您打算按照此处介绍的步骤为 Ansible 配置 WinRm,本教程将假设:

  • 您已经在 Linux 主机上安装了 Ansible。
  • 您已根据 Windows 主机设置了 Ansible 清单。
  • 您需要管理 Windows Server 2016 或更高版本。本教程中使用的某些 cmdlet 不适用于旧版本的 Windows。
  • Windows 主机不在域中。尽管这些示例是在未加入域的主机上执行的,但此配置应该也适用于加入域的主机。
  • 您具有对 Windows 主机的 RDP 或控制台访问权限,并以本地管理员身份登录。
  • 您熟悉 PowerShell。几乎所有示例都将使用 PowerShell 代码在 Windows 主机上进行更改。

每个部分都将使用依赖于最后一个部分的代码片段。一些片段将引用之前定义的变量。如果您打算完全遵循此代码,请务必在复制/粘贴此代码时保持控制台打开。

如果您只想要代码而不需要所有解释,请随时下载此 GitHub gist。

为 Ansible 的 WinRm 启用 PowerShell 远程处理

尽管所有 Windows Server 2016 或更高版本的服务器都启用了 PowerShell 远程处理,但确认这一点始终是个好主意。

在要管理的 Windows 主机上,以管理员身份打开 PowerShell 控制台并运行以下代码片段。此代码片段确保 WinRm 服务启动并设置为在系统启动时自动启动。

Set-Service -Name "WinRM" -StartupType Automatic
Start-Service -Name "WinRM"

接下来,首先检查是否有任何活动的会话配置,以确保 PowerShell 远程处理已启用。如果没有,请确保它没有任何可用的侦听器。 Ansible 的 WinRm 必须至少有一个侦听器。如果这些情况之一没有返回,请运行 Enable-PSRemoting

if (-not (Get-PSSessionConfiguration) -or (-not (Get-ChildItem WSMan:\localhost\Listener))) {
    ## Use SkipNetworkProfileCheck to make available even on Windows Firewall public profiles
    ## Use Force to not be prompted if we're sure or not.
    Enable-PSRemoting -SkipNetworkProfileCheck -Force
}

[玩转系统] 通过 10 个步骤保护 WinRM for Ansible(证书)[操作方法]

启用基于证书的身份验证

默认情况下,WinRM 未配置为基于证书的身份验证。您必须通过配置 WSMan 来启用它,如下所示。

#region Enable cert-based auth
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true
#endregion

创建本地用户帐户

要使用基于证书的 WinRM 进行 Ansible 身份验证,必须将本地用户帐户“映射”到证书。您可以使用本地管理员帐户来执行此操作,但创建特定帐户以使管理更轻松始终是一个好主意。

以下代码片段为 WinRm for Ansible 创建一个名为 ansibletestuser 的本地用户帐户,密码为 p@$$w0rd12(如果不存在)。为了确保它始终保持活动状态,该帐户的密码永远不会过期。

$testUserAccountName = 'ansibletestuser'
$testUserAccountPassword = (ConvertTo-SecureString -String 'p@$$w0rd12' -AsPlainText -Force)
if (-not (Get-LocalUser -Name $testUserAccountName -ErrorAction Ignore)) {
    $newUserParams = @{
        Name                 = $testUserAccountName
        AccountNeverExpires  = $true
        PasswordNeverExpires = $true
        Password             = $testUserAccountPassword
    }
    $null = New-LocalUser @newUserParams
}

创建客户端证书

WinRm for Ansible(安全地)必须有两个证书;客户端证书和服务器证书。

您可以对客户端/服务器使用相同的证书,但我在这种方法中遇到了问题。在 Ansible 文档和许多其他来源中,您将找到通过 PowerShell 的 New-SelfSignedCert cmdlet 生成客户端证书的说明。虽然这个方法可能有效,但我无法轻松实现它。

要为 Ansible 的 WinRM 创建客户端证书,您必须创建私钥和公钥。首先通过 SSH 连接到 Ansible 主机并运行以下 openssl 命令。此命令在名为 cert_key.pem 的文件中创建一个名为 cert_key.pem 的私钥,并创建一个名为 cert.pem 的公钥。密钥用途将用于客户端身份验证(1.3.6.1.4.1.1)。 311.20.2.3) “映射”到您之前创建的名为 ansibletestuser 的本地用户帐户。

## This is the public key generated from the Ansible server using:
cat > openssl.conf << EOL
distinguished_name = req_distinguished_name
[req_distinguished_name]
[v3_req_client]
extendedKeyUsage = clientAuth
subjectAltName = otherName:1.3.6.1.4.1.311.20.2.3;UTF8:ansibletestuser@localhost
EOL
export OPENSSL_CONF=openssl.conf
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -out cert.pem -outform PEM -keyout cert_key.pem -subj "/CN=ansibletestuser" -extensions v3_req_client
rm openssl.conf 

离 Ansible WinRM 身份验证又近了一步!

导入客户端证书

为 Ansible 上的 WinRm 创建客户端证书后,您必须将其导入 Windows 主机上的两个证书存储中,以便 Ansible 上的 WinRm 正常工作。为此,首先将 cert.pem 公钥传输到 Windows 主机。下面的示例假设密钥存在于C:\cert.pem

在 Windows 主机上拥有公共证书后,使用 Import-Certificate 将其导入受信任的根证书颁发机构受信任的人员证书存储区如下所示。

$pubKeyFilePath = 'C:\cert.pem'

## Import the public key into Trusted Root Certification Authorities and Trusted People
$null = Import-Certificate -FilePath $pubKeyFilePath -CertStoreLocation 'Cert:\LocalMachine\Root'
$null = Import-Certificate -FilePath $pubKeyFilePath -CertStoreLocation 'Cert:\LocalMachine\TrustedPeople'

创建服务器证书

WinRM for Ansible 需要使用密钥用途定义的证书进行服务器身份验证。该证书将存储在 Windows 主机的 LocalMachine\My 证书存储中。使用下面的代码片段创建自签名证书。

$hostname = hostname
$serverCert = New-SelfSignedCertificate -DnsName $hostName -CertStoreLocation 'Cert:\LocalMachine\My'

创建 Ansible WinRm 监听器

创建两个证书后,您现在必须在 Windows 主机上创建 WinRm 侦听器。此侦听器开始在端口 5986 上侦听传入连接。创建后,此侦听器接受传入连接,并尝试使用上面创建的服务器证书加密数据。

一旦进行身份验证,PowerShell 远程处理就会使用此 WinRM 侦听器作为传输。

在下面的代码片段中,您可以看到检查现有 HTTPS 侦听器的一个很好的示例。如果使用上面创建的服务器证书找不到侦听器,它将创建一个新的侦听器。

## Find all HTTPS listners
$httpsListeners = Get-ChildItem -Path WSMan:\localhost\Listener\ | where-object { $_.Keys -match 'Transport=HTTPS' }

## If not listeners are defined at all or no listener is configured to work with
## the server cert created, create a new one with a Subject of the computer's host name
## and bound to the server certificate.
if ((-not $httpsListeners) -or -not (@($httpsListeners).where( { $_.CertificateThumbprint -ne $serverCert.Thumbprint }))) {
    $newWsmanParams = @{
        ResourceUri = 'winrm/config/Listener'
        SelectorSet = @{ Transport = "HTTPS"; Address = "*" }
        ValueSet    = @{ Hostname = $hostName; CertificateThumbprint = $serverCert.Thumbprint }
        # UseSSL = $true
    }
    $null = New-WSManInstance @newWsmanParams
}

将客户端证书“映射”到本地用户帐户

下一步是确保当 Ansible 使用服务器证书连接到 Windows 主机时,它将以本地用户身份执行所有指令。在这种情况下,WinRm for Ansible 执行的所有活动都将使用本地用户帐户 ansibletestuser。

$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $testUserAccountName, $testUserAccountPassword

## Find the cert thumbprint for the client certificate created on the Ansible host
$ansibleCert = Get-ChildItem -Path 'Cert:\LocalMachine\Root' | Where-Object {$_.Subject -eq 'CN=ansibletestuser'}

$params = @{
	Path = 'WSMan:\localhost\ClientCertificate'
	Subject = "$testUserAccountName@localhost"
	URI = '*'
	Issuer = $ansibleCert.Thumbprint
  Credential = $credential
	Force = $true
}
New-Item @params

允许 WinRm 用于具有用户帐户控制 (UAC) 的 Ansible

如果使用本地帐户将证书映射到,您还必须将 LocalAccountTokenFilterPolicy 设置为 1 以确保 UAC 不会妨碍。 LocalAccountTokenFilterPolicy 适用于所有本地帐户(非域帐户),并使您的网络登录成为令牌的受限部分。这将阻止它登录,因为 Windows 不会将其视为管理员,并且 WinRM 默认情况下要求用户是本地管理员。

通过设置 LocalAccountTokenFilterPolicy ,您可以告诉 Windows 不要为本地帐户的网络登录创建有限令牌并使用其完整令牌。

$newItemParams = @{
    Path         = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
    Name         = 'LocalAccountTokenFilterPolicy'
    Value        = 1
    PropertyType = 'DWORD'
    Force        = $true
}
$null = New-ItemProperty @newItemParams

在 Windows 防火墙上打开端口 5986

WinRm over HTTPS 使用端口 5986。如果启用了 Windows 防火墙,则必须打开此端口。您可以通过运行以下 PowerShell 代码片段来执行此操作。该代码片段过于宽松,允许所有计算机使用它。如果您想进一步锁定它,请务必使用 LocalAddress 参数并指定 Ansible 的 IP。

#region Ensure WinRM 5986 is open on the firewall
 $ruleDisplayName = 'Windows Remote Management (HTTPS-In)'
 if (-not (Get-NetFirewallRule -DisplayName $ruleDisplayName -ErrorAction Ignore)) {
     $newRuleParams = @{
         DisplayName   = $ruleDisplayName
         Direction     = 'Inbound'
         LocalPort     = 5986
         RemoteAddress = 'Any'
         Protocol      = 'TCP'
         Action        = 'Allow'
         Enabled       = 'True'
         Group         = 'Windows Remote Management'
     }
     $null = New-NetFirewallRule @newRuleParams
 }
 #endregion

将本地用户添加到管理员组

您可能会问为什么本教程不直接将本地用户添加到管理员组中。原因是,由于某种未知原因,当您尝试将客户端证书映射到用户时,该用户帐户不能是本地管理员。

运行以下代码片段将 ansibletestuser 本地用户帐户添加到管理员组。

## Add the local user to the administrators group. If this step isn't doing, Ansible sees an "AccessDenied" error
Get-LocalUser -Name $testUserAccountName | Add-LocalGroupMember -Group 'Administrators'

结论

如果您已按照所示步骤操作,那么您现在应该能够对 Windows 主机执行 Ansible 命令。使用 win_shell 模块来执行测试。如果此模块成功,则您已成功配置 WinRM 以进行 Ansible 和基于证书的身份验证!

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯