Powershell对脚本有安全机制,默认情况下,脚本必须签名后才正常运行无提示否则会报错:
✘
xxx: 无法加载文件 xxx.ps1。未对文件 xxx.ps1 进行数字签名。无法在当前系统上运行该脚本。有关
运行脚本和设置执行策略的详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
所在位
+ ~~~~~~置 行:1 字符: 1
+ resize
+ CategoryInfo : SecurityError: (:) [],PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
当然,我们可以用管理员运行 Powershell ,然后运行以下指令,设置安全策略为对远程脚本才进行签名验证:
Set-ExecutionPolicy RemoteSigned
但这样我们会损失安全特性,因为病毒、恶意软件等,可以通过在本地生成脚本的形式然后运行,就不会有安全警告了。我们可以用以下指令,强制系统运行的所有脚本,都需要数字签名才能运行:
Set-ExecutionPolicy AllSigned
为了能自己签名,可以可以按如下方式进行,在Powershell中依次运行指令,记得把对应的数据更改为相应的内容,下面的操作只需要做一次即可:
# 生成用于代码签名的自签名根证书
New-SelfSignedCertificate -DnsName <你的DnsName例如admin@www.abc.com> -CertStoreLocation Cert:\CurrentUser\My\ -FriendlyName "你的证书名字" -NotAfter (Get-Date).AddYears(99) -KeyLength 4096 -Type Codesigning
# 列出当前用户的个人存储中的证书
Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
# 记录对应证书的Thumbprint指纹,然后继续导出该证书
Export-Certificate -Cert Cert:\CurrentUser\My\<证书指纹,例如C9D463CDA04D7583221FE14C32D7B7570537905A> -FilePath cert.cer
# 然后以管理员省份运行Powershell并导入证书到受信任根证书颁发机构和受信任发布者这两个目录:
Import-Certificate -CertStoreLocation Cert:\LocalMachine\AuthRoot -FilePath cert.cer
Import-Certificate -CertStoreLocation Cert:\LocalMachine\TrustedPublisher -FilePath cert.cer
此后就可以用这个证书对ps1脚本签名了:
Set-AuthenticodeSignature -FilePath C:\test.ps1 -Certificate (Get-ChildItem -Path Cert:\CurrentUser\My\<你的证书指纹,例如C9D463CDA04D7583221FE14C32D7B7570537905A>)
签名完成后,你的脚本文件(.ps1)的末尾,会多出一段签名信息,例如:
# SIG # Begin signature block
# MIIIfQYJKoZIhvcNAQcCoIIIbjCCCGoCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# ...
# SIG # End signature block
一旦签名后,ps1文件就不能再做任何修改,否则运行 ps1 文件会提示错误:
✘
xxx: 无法加载文件 xxx.ps1。未授权的用户或进程可能更改了文件 xxx.ps1 的内容,因为该文件的哈
希与数字签名中存储的哈希不匹配。无法在指定的系统上运行该脚本。有关详细信息,请运行 Get-Help about_Signing。。
所在位置
+ ~~~~~~
+ CategoryInfo : SecurityError: (:) [],PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess行:1 字符: 1
+ xxx
你可以重新签名消除警告。