เพิ่มการสนับสนุนข้อมูลรับรองให้กับฟังก์ชัน PowerShell
บันทึก
ต้นฉบับของบทความนี้ปรากฏบนบล็อกที่เขียนโดย @joshduffney บทความนี้ได้รับการแก้ไขเพื่อรวมไว้ในไซต์นี้ ทีม PowerShell ขอขอบคุณ Josh สำหรับการแบ่งปันเนื้อหานี้กับเรา โปรดตรวจสอบบล็อกของเขาที่ duffney.io
บทความนี้จะแสดงวิธีเพิ่มพารามิเตอร์ข้อมูลประจำตัวให้กับฟังก์ชัน PowerShell และเหตุผลที่คุณต้องการ พารามิเตอร์ข้อมูลรับรองคือการอนุญาตให้คุณเรียกใช้ฟังก์ชันหรือ cmdlet ในฐานะผู้ใช้อื่น การใช้งานทั่วไปมากที่สุดคือการเรียกใช้ฟังก์ชันหรือ cmdlet เป็นบัญชีผู้ใช้ที่มีการยกระดับ
ตัวอย่างเช่น cmdlet New-ADUser มีพารามิเตอร์ ข้อมูลรับรอง ซึ่งคุณสามารถระบุข้อมูลรับรองผู้ดูแลระบบโดเมนเพื่อสร้างบัญชีในโดเมนได้ สมมติว่าบัญชีปกติของคุณที่ใช้งานเซสชัน PowerShell ไม่มีสิทธิ์เข้าถึงนั้น
การสร้างวัตถุหนังสือรับรอง
ออบเจ็กต์ PSCredential แสดงถึงชุดข้อมูลรับรองความปลอดภัย เช่น ชื่อผู้ใช้และรหัสผ่าน วัตถุสามารถส่งผ่านเป็นพารามิเตอร์ไปยังฟังก์ชันที่ทำงานเป็นบัญชีผู้ใช้ในวัตถุข้อมูลประจำตัวนั้น คุณสามารถสร้างออบเจ็กต์หนังสือรับรองได้หลายวิธี วิธีแรกในการสร้างออบเจ็กต์ข้อมูลประจำตัวคือการใช้ PowerShell cmdlet Get-Credential เมื่อคุณทำงานโดยไม่มีพารามิเตอร์ ระบบจะขอให้คุณระบุชื่อผู้ใช้และรหัสผ่าน หรือคุณสามารถเรียก cmdlet ด้วยพารามิเตอร์ทางเลือกบางอย่างได้
หากต้องการระบุชื่อโดเมนและชื่อผู้ใช้ล่วงหน้า คุณสามารถใช้พารามิเตอร์ ข้อมูลประจำตัว หรือ ชื่อผู้ใช้ เมื่อคุณใช้พารามิเตอร์ ชื่อผู้ใช้ คุณจะต้องระบุค่า ข้อความ ด้วย รหัสด้านล่างสาธิตการใช้ cmdlet คุณยังสามารถจัดเก็บออบเจ็กต์หนังสือรับรองในตัวแปรเพื่อให้คุณสามารถใช้ข้อมูลรับรองได้หลายครั้ง ในตัวอย่างด้านล่าง ออบเจ็กต์ข้อมูลรับรองจะถูกจัดเก็บไว้ในตัวแปร $Cred
$Cred = Get-Credential
$Cred = Get-Credential -Credential domain\user
$Cred = Get-Credential -UserName domain\user -Message 'Enter Password'
บางครั้ง คุณไม่สามารถใช้วิธีการโต้ตอบในการสร้างออบเจ็กต์ข้อมูลรับรองที่แสดงในตัวอย่างก่อนหน้านี้ได้ เครื่องมืออัตโนมัติส่วนใหญ่ต้องการวิธีการแบบไม่โต้ตอบ หากต้องการสร้างข้อมูลรับรองโดยไม่ต้องโต้ตอบกับผู้ใช้ ให้สร้างสตริงที่ปลอดภัยที่มีรหัสผ่าน จากนั้นส่งสตริงที่ปลอดภัยและชื่อผู้ใช้ไปยังเมธอด System.Management.Automation.PSCredential()
ใช้คำสั่งต่อไปนี้เพื่อสร้างสตริงที่ปลอดภัยที่มีรหัสผ่าน:
ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
ต้องใช้ทั้งพารามิเตอร์ AsPlainText และ Force หากไม่มีพารามิเตอร์เหล่านั้น คุณจะได้รับข้อความเตือนว่าคุณไม่ควรส่งข้อความธรรมดาไปยังสตริงที่ปลอดภัย PowerShell ส่งคืนคำเตือนนี้เนื่องจากรหัสผ่านข้อความธรรมดาได้รับการบันทึกในบันทึกต่างๆ เมื่อคุณสร้างสตริงที่ปลอดภัยแล้ว คุณจะต้องส่งผ่านไปยังเมธอด PSCredential() เพื่อสร้างออบเจ็กต์ข้อมูลรับรอง ในตัวอย่างต่อไปนี้ ตัวแปร $password มีสตริงที่ปลอดภัย $Cred มีวัตถุหนังสือรับรอง
$password = ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("username", $password)
ตอนนี้คุณรู้วิธีสร้างออบเจ็กต์หนังสือรับรองแล้ว คุณสามารถเพิ่มพารามิเตอร์หนังสือรับรองให้กับฟังก์ชัน PowerShell ของคุณได้
การเพิ่มพารามิเตอร์ข้อมูลรับรอง
เช่นเดียวกับพารามิเตอร์อื่นๆ คุณเริ่มต้นด้วยการเพิ่มลงในบล็อก param ของฟังก์ชันของคุณ ขอแนะนำให้คุณตั้งชื่อพารามิเตอร์ $Credential เนื่องจากนั่นคือสิ่งที่ PowerShell cmdlets ที่มีอยู่ใช้ ประเภทของพารามิเตอร์ควรเป็น [System.Management.Automation.PSCredential]
ตัวอย่างต่อไปนี้แสดงบล็อกพารามิเตอร์สำหรับฟังก์ชันที่เรียกว่า Get-Something มีพารามิเตอร์สองตัว: $Name และ $Credential
function Get-Something {
param(
$Name,
[System.Management.Automation.PSCredential]$Credential
)
โค้ดในตัวอย่างนี้เพียงพอที่จะมีพารามิเตอร์ข้อมูลประจำตัวที่ใช้งานได้ อย่างไรก็ตาม มีบางสิ่งที่คุณสามารถเพิ่มเพื่อให้มีประสิทธิภาพมากขึ้น
เพิ่มแอตทริบิวต์การตรวจสอบ
[ValidateNotNull()]เพื่อตรวจสอบว่าค่าถูกส่งไปที่ ข้อมูลรับรอง หากค่าพารามิเตอร์เป็น null แอ็ตทริบิวต์นี้จะป้องกันไม่ให้ฟังก์ชันดำเนินการด้วยข้อมูลรับรองที่ไม่ถูกต้องเพิ่ม
[System.Management.Automation.Credential()]วิธีนี้ช่วยให้คุณสามารถส่งชื่อผู้ใช้เป็นสตริงและมีพร้อมท์โต้ตอบสำหรับรหัสผ่าน-
ตั้งค่าเริ่มต้นสำหรับพารามิเตอร์
$Credentialเป็น[System.Management.Automation.PSCredential]::Emptyฟังก์ชันของคุณที่คุณอาจส่งผ่านออบเจ็กต์$Credentialนี้ไปยัง PowerShell cmdlets ที่มีอยู่ การระบุค่า Null ให้กับ cmdlet ที่ถูกเรียกภายในฟังก์ชันของคุณทำให้เกิดข้อผิดพลาด การระบุออบเจ็กต์ข้อมูลรับรองที่ว่างเปล่าจะหลีกเลี่ยงข้อผิดพลาดนี้
คำแนะนำที่เป็นประโยชน์
cmdlet บางตัวที่ยอมรับพารามิเตอร์ข้อมูลประจำตัวไม่สนับสนุน [System.Management.Automation.PSCredential]::Empty ตามที่ควร ดูส่วนการจัดการกับ Cmdlets ดั้งเดิมสำหรับวิธีแก้ปัญหา
การใช้พารามิเตอร์หนังสือรับรอง
ตัวอย่างต่อไปนี้สาธิตวิธีการใช้พารามิเตอร์ข้อมูลรับรอง ตัวอย่างนี้แสดงฟังก์ชันชื่อ Set-RemoteRegistryValue ซึ่งไม่ได้อยู่ใน The Pester Book ฟังก์ชันนี้กำหนดพารามิเตอร์ข้อมูลรับรองโดยใช้เทคนิคที่อธิบายไว้ในส่วนก่อนหน้า ฟังก์ชันเรียกใช้ Invive-Command โดยใช้ตัวแปร $Credential ที่สร้างโดยฟังก์ชัน ซึ่งช่วยให้คุณสามารถเปลี่ยนผู้ใช้ที่กำลังเรียกใช้ Inrigg-Command เนื่องจากค่าเริ่มต้นของ $Credential เป็นข้อมูลประจำตัวที่ว่างเปล่า ฟังก์ชันจึงสามารถทำงานได้โดยไม่ต้องระบุข้อมูลประจำตัว
function Set-RemoteRegistryValue {
param(
$ComputerName,
$Path,
$Name,
$Value,
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
$null = Invoke-Command -ComputerName $ComputerName -ScriptBlock {
Set-ItemProperty -Path $using:Path -Name $using:Name -Value $using:Value
} -Credential $Credential
}
ส่วนต่อไปนี้แสดงวิธีการต่างๆ ในการให้ข้อมูลประจำตัวแก่ Set-RemoteRegistryValue
แจ้งขอหนังสือรับรอง
การใช้ Get-Credential ในวงเล็บ () ในขณะรันไทม์จะทำให้ Get-credential รันก่อน คุณได้รับพร้อมท์ให้ใส่ชื่อผู้ใช้และรหัสผ่าน คุณสามารถใช้พารามิเตอร์ ข้อมูลรับรอง หรือ ชื่อผู้ใช้ ของ Get-credential เพื่อเติมชื่อผู้ใช้และโดเมนล่วงหน้า ตัวอย่างต่อไปนี้ใช้เทคนิคที่เรียกว่า splatting เพื่อส่งพารามิเตอร์ไปยังฟังก์ชัน Set-RemoteRegistryValue สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Splatting โปรดดูบทความ about_Splatting
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams -Credential (Get-Credential)
การใช้ (Get-Credential) ดูยุ่งยาก โดยปกติ เมื่อคุณใช้พารามิเตอร์ ข้อมูลประจำตัว กับชื่อผู้ใช้เท่านั้น cmdlet จะถามรหัสผ่านโดยอัตโนมัติ แอตทริบิวต์ [System.Management.Automation.Credential()] เปิดใช้งานลักษณะการทำงานนี้
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams -Credential duffney
บันทึก
หากต้องการตั้งค่ารีจิสทรีที่แสดง ตัวอย่างเหล่านี้จะถือว่าคุณได้ติดตั้งคุณลักษณะ เว็บเซิร์ฟเวอร์ ของ Windows แล้ว เรียกใช้ Install-WindowsFeature Web-Server และ Install-WindowsFeature web-mgmt-tools หากจำเป็น
ระบุข้อมูลรับรองในตัวแปร
คุณยังสามารถเติมตัวแปรข้อมูลรับรองล่วงหน้าและส่งผ่านไปยังพารามิเตอร์ ข้อมูลรับรอง ของฟังก์ชัน Set-RemoteRegistryValue ใช้วิธีนี้กับเครื่องมือการผสานรวมอย่างต่อเนื่อง/การปรับใช้อย่างต่อเนื่อง (CI/CD) เช่น Jenkins, TeamCity และ Octopus Deploy สำหรับตัวอย่างการใช้ Jenkins โปรดดูบล็อกโพสต์ของ Hodge การทำอัตโนมัติด้วย Jenkins และ PowerShell บน Windows - ตอนที่ 2
ตัวอย่างนี้ใช้เมธอด .NET เพื่อสร้างออบเจ็กต์หนังสือรับรองและสตริงที่ปลอดภัยเพื่อส่งผ่านรหัสผ่าน
$password = ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("duffney", $password)
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams -Credential $Cred
สำหรับตัวอย่างนี้ สตริงที่ปลอดภัยจะถูกสร้างขึ้นโดยใช้รหัสผ่านข้อความที่ชัดเจน CI/CD ที่กล่าวถึงก่อนหน้านี้ทั้งหมดมีวิธีการที่ปลอดภัยในการระบุรหัสผ่านนั้นในขณะดำเนินการ เมื่อใช้เครื่องมือเหล่านั้น ให้แทนที่รหัสผ่านข้อความธรรมดาด้วยตัวแปรที่กำหนดไว้ภายในเครื่องมือ CI/CD ที่คุณใช้
ดำเนินการโดยไม่มีหนังสือรับรอง
เนื่องจาก $Credential มีค่าเริ่มต้นเป็นออบเจ็กต์ข้อมูลรับรองที่ว่างเปล่า คุณจึงสามารถรันคำสั่งได้โดยไม่ต้องมีข้อมูลรับรอง ดังที่แสดงในตัวอย่างนี้:
$remoteKeyParams = @{
ComputerName = $env:COMPUTERNAME
Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
Name = 'EnableRemoteManagement'
Value = '1'
}
Set-RemoteRegistryValue @remoteKeyParams
การจัดการกับ cmdlets ดั้งเดิม
cmdlet ของทั้งหมดไม่สนับสนุนวัตถุข้อมูลประจำตัวหรืออนุญาตให้ข้อมูลประจำตัวว่างเปล่า cmdlet ต้องการพารามิเตอร์ชื่อผู้ใช้และรหัสผ่านเป็นสตริงแทน มีหลายวิธีในการแก้ไขข้อจำกัดนี้
การใช้ if-else เพื่อจัดการข้อมูลประจำตัวที่ว่างเปล่า
ในสถานการณ์สมมตินี้ cmdlet ที่คุณต้องการเรียกใช้ไม่ยอมรับวัตถุข้อมูลประจำตัวที่ว่างเปล่า ตัวอย่างนี้เพิ่มพารามิเตอร์ ข้อมูลประจำตัว ให้กับ Inrigger-Command เฉพาะในกรณีที่ไม่ว่างเปล่า มิฉะนั้น จะรัน Inrigger-Command โดยไม่มีพารามิเตอร์ Credential
function Set-RemoteRegistryValue {
param(
$ComputerName,
$Path,
$Name,
$Value,
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
if($Credential -ne [System.Management.Automation.PSCredential]::Empty) {
Invoke-Command -ComputerName:$ComputerName -Credential:$Credential {
Set-ItemProperty -Path $using:Path -Name $using:Name -Value $using:Value
}
} else {
Invoke-Command -ComputerName:$ComputerName {
Set-ItemProperty -Path $using:Path -Name $using:Name -Value $using:Value
}
}
}
การใช้ splatting เพื่อจัดการข้อมูลประจำตัวที่ว่างเปล่า
ตัวอย่างนี้ใช้การแบ่งพารามิเตอร์เพื่อเรียก cmdlet ดั้งเดิม ออบเจ็กต์ $Credential จะถูกเพิ่มอย่างมีเงื่อนไขไปยังตารางแฮชเพื่อการแบ่งแยก และหลีกเลี่ยงความจำเป็นในการบล็อกสคริปต์ Inrigger-Command ซ้ำ หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการแบ่งส่วนภายในฟังก์ชัน โปรดดูโพสต์บล็อกการแบ่งส่วนพารามิเตอร์ภายในฟังก์ชันขั้นสูง
function Set-RemoteRegistryValue {
param(
$ComputerName,
$Path,
$Name,
$Value,
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
$Splat = @{
ComputerName = $ComputerName
}
if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) {
$Splat['Credential'] = $Credential
}
$null = Invoke-Command -ScriptBlock {
Set-ItemProperty -Path $using:Path -Name $using:Name -Value $using:Value
} @splat
}
การทำงานกับรหัสผ่านสตริง
Invoke-Sqlcmd cmdlet เป็นตัวอย่างของ cmdlet ที่ยอมรับสตริงเป็นรหัสผ่าน Invivo-Sqlcmd ช่วยให้คุณสามารถเรียกใช้คำสั่ง SQL แทรก อัปเดต และลบคำสั่งง่ายๆ ได้ Invivo-Sqlcmd ต้องใช้ชื่อผู้ใช้และรหัสผ่านที่เป็นข้อความที่ชัดเจน แทนที่จะเป็นวัตถุข้อมูลรับรองที่ปลอดภัยกว่า ตัวอย่างนี้แสดงวิธีแยกชื่อผู้ใช้และรหัสผ่านจากออบเจ็กต์ข้อมูลรับรอง
ฟังก์ชัน Get-AllSQLDatabases ในตัวอย่างนี้เรียก cmdlet Invoke-Sqlcmd เพื่อสอบถามเซิร์ฟเวอร์ SQL สำหรับฐานข้อมูลทั้งหมด ฟังก์ชันนี้จะกำหนดพารามิเตอร์ ข้อมูลรับรอง ด้วยแอตทริบิวต์เดียวกันกับที่ใช้ในตัวอย่างก่อนหน้านี้ เนื่องจากชื่อผู้ใช้และรหัสผ่านมีอยู่ในตัวแปร $Credential คุณจึงสามารถแยกค่าเหล่านั้นเพื่อใช้กับ Intake-Sqlcmd ได้
ชื่อผู้ใช้สามารถดูได้จากคุณสมบัติ ชื่อผู้ใช้ ของตัวแปร $Credential หากต้องการรับรหัสผ่าน คุณต้องใช้เมธอด GetNetworkCredential() ของออบเจ็กต์ $Credential ค่าจะถูกแยกออกเป็นตัวแปรที่เพิ่มลงในตารางแฮชที่ใช้สำหรับการแบ่งพารามิเตอร์เป็น Intake-Sqlcmd
function Get-AllSQLDatabases {
param(
$SQLServer,
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
$UserName = $Credential.UserName
$Password = $Credential.GetNetworkCredential().Password
$splat = @{
UserName = $UserName
Password = $Password
ServerInstance = 'SQLServer'
Query = "Select * from Sys.Databases"
}
Invoke-Sqlcmd @splat
}
$credSplat = @{
TypeName = 'System.Management.Automation.PSCredential'
ArgumentList = 'duffney',('P@ssw0rd' | ConvertTo-SecureString -AsPlainText -Force)
}
$Credential = New-Object @credSplat
Get-AllSQLDatabases -SQLServer SQL01 -Credential $Credential
การจัดการข้อมูลรับรองการเรียนรู้อย่างต่อเนื่อง
การสร้างและจัดเก็บออบเจ็กต์หนังสือรับรองอย่างปลอดภัยอาจเป็นเรื่องยาก แหล่งข้อมูลต่อไปนี้สามารถช่วยคุณรักษาข้อมูลประจำตัวของ PowerShell ได้
- BetterCredentials
- Azure Key Vault
- โครงการห้องนิรภัย
- โมดูลการจัดการความลับ

