PowerShell 함수에 자격 증명 지원 추가

참고 항목

현재 문서의 원본 버전@joshduffney가 작성한 블로그에 있습니다. 이 문서는 이 사이트에 포함하기 위해 편집되었습니다. PowerShell 팀은 이 콘텐츠를 공유해 주신 Josh에게 감사드립니다. duffney.io 자신의 블로그를 검사.

이 문서에서는 PowerShell 함수에 자격 증명 매개 변수를 추가하는 방법과 원하는 이유를 보여 줍니다. 자격 증명 매개 변수는 함수 또는 cmdlet을 다른 사용자로 실행할 수 있도록 하는 것입니다. 가장 일반적인 용도는 상승된 사용자 계정으로 함수 또는 cmdlet을 실행하는 것입니다.

예를 들어 cmdlet New-ADUser 에는 do기본 관리자 자격 증명을 제공하여 할 일기본 계정을 만들 수 있는 자격 증명 매개 변수가 있습니다. PowerShell 세션을 실행하는 일반 계정에 아직 이 액세스 권한이 없는 것으로 가정합니다.

자격 증명 개체 만들기

PSCredential 개체는 사용자 이름 및 암호와 같은 보안 자격 증명 집합을 나타냅니다. 해당 자격 증명 개체에서 사용자 계정으로 실행되는 함수에 매개 변수로 개체를 전달할 수 있습니다. 자격 증명 개체를 만들 수 있는 몇 가지 방법이 있습니다. 자격 증명 개체를 만드는 첫 번째 방법은 PowerShell cmdlet Get-Credential을 사용하는 것입니다. 매개 변수 없이 실행하면 사용자 이름과 암호를 묻는 메시지가 표시됩니다. 또는 일부 선택적 매개 변수를 사용하여 cmdlet을 호출할 수 있습니다.

do기본 이름 및 사용자 이름을 미리 지정하려면 Credential 또는 UserName 매개 변수를 사용할 수 있습니다. UserName 매개 변수를 사용하는 경우 메시지 값도 제공해야 합니다. 아래 코드에서는 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

AsPlainTextForce 매개 변수가 모두 필요합니다. 이러한 매개 변수가 없으면 일반 텍스트를 보안 문자열에 전달해서는 안 된다는 메시지가 표시됩니다. 일반 텍스트 암호가 다양한 로그에 기록되기 때문에 PowerShell은 이 경고를 반환합니다. 보안 문자열을 만든 후에는 자격 증명 개체를 PSCredential() 만들려면 메서드에 전달해야 합니다. 다음 예제에서 변수 $password 는 자격 증명 개체를 포함하는 보안 문자열 $Cred 을 포함합니다.

$password = ConvertTo-SecureString "MyPlainTextPassword" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ("username", $password)

자격 증명 개체를 만드는 방법을 알게 되었으므로 이제 PowerShell 함수에 자격 증명 매개 변수를 추가할 수 있습니다.

자격 증명 매개 변수 추가

다른 매개 변수와 마찬가지로 함수 블록에 param 추가하여 시작합니다. 기존 PowerShell cmdlet에서 사용되므로 매개 변수 이름을 $Credential로 지정하는 것이 좋습니다. 매개 변수 형식은 [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 cmdlet에 전달할 수 있습니다. 함수 내에서 호출된 cmdlet에 null 값을 제공하면 오류가 발생합니다. 빈 자격 증명 개체를 제공하면 이 오류가 발생하지 않습니다.

자격 증명 매개 변수를 허용하는 일부 cmdlet은 예상과 달리 [System.Management.Automation.PSCredential]::Empty를 지원하지 않습니다. 해결 방법은 레거시 Cmdlet 처리 섹션을 참조하세요.

자격 증명 매개 변수 사용

다음 예제에서는 자격 증명 매개 변수를 사용하는 방법을 보여 줍니다. 이 예제에서는 Pester Book에서 제외된 함수를 Set-RemoteRegistryValue보여 있습니다. 이 함수는 이전 섹션에서 설명하는 기술을 사용하여 자격 증명 매개 변수를 정의합니다. 함수는 함수에서 만든 변수를 $Credential 사용하여 호출 Invoke-Command 합니다. 이렇게 하면 실행 중인 사용자를 변경할 수 있습니다 Invoke-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-credentialCredential 또는 UserName 매개 변수를 사용하여 사용자 이름과 도메인을 미리 채울 수 있습니다. 다음 예제에서는 스플래팅이라는 기술을 사용하여 함수에 매개 변수를 Set-RemoteRegistryValue 전달합니다. 스플래팅에 대한 자세한 내용은 about_Splatting 문서를 참조하세요.

$remoteKeyParams = @{
    ComputerName = $env:COMPUTERNAME
    Path = 'HKLM:\SOFTWARE\Microsoft\WebManagement\Server'
    Name = 'EnableRemoteManagement'
    Value = '1'
}

Set-RemoteRegistryValue @remoteKeyParams -Credential (Get-Credential)

런타임에 자격 증명 가져오기

(Get-Credential) 사용은 번거로워 보입니다. 일반적으로 사용자 이름만으로 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-ServerInstall-WindowsFeature web-mgmt-tools를 실행하세요.

변수에서 자격 증명 제공

미리 자격 증명 변수를 채우고 Set-RemoteRegistryValue 함수의 Credential 매개 변수에 전달할 수도 있습니다. Jenkins, TeamCity 및 Octopus Deploy와 같은 CI/CD(연속 통합/연속 배포) 도구에서 이 메서드를 사용합니다. Jenkins를 사용하는 예제의 경우 Windows에서 Jenkins 및 PowerShell을 사용하여 자동화하는 Hodge의 블로그 게시물인 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

레거시 cmdlet 처리

모든 cmdlet이 자격 증명 개체를 지원하거나 빈 자격 증명을 허용하는 것은 아닙니다. 대신 cmdlet은 사용자 이름 및 암호 매개 변수가 문자열이기를 원합니다. 이 제한 사항은 몇 가지 방법으로 해결할 수 있습니다.

if-else를 사용하여 빈 자격 증명 처리

이 시나리오에서 실행할 cmdlet은 빈 자격 증명 개체를 허용하지 않습니다. 다음은 비어 있지 않은 경우에만 자격 증명 매개 변수를 Invoke-Command 추가하는 예제입니다. 그렇지 않으면 자격 증명 매개 변수 없이 실행됩니다Invoke-Command.

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
        }
    }
}

스플래팅을 사용하여 빈 자격 증명 처리

이 예제는 매개 변수 스플래팅을 사용하여 레거시 cmdlet을 호출합니다. 개체는 $Credential 스플래팅을 위해 해시 테이블에 조건부로 추가되며 스크립트 블록을 반복 Invoke-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의 예입니다. Invoke-Sqlcmd 를 사용하면 간단한 SQL 삽입, 업데이트 및 삭제 문을 실행할 수 있습니다. Invoke-Sqlcmd 에는 보다 안전한 자격 증명 개체가 아닌 명확한 텍스트 사용자 이름 및 암호가 필요합니다. 이 예제는 자격 증명 개체에서 사용자 이름 및 암호를 추출하는 방법을 보여 줍니다.

이 예제의 함수는 Get-AllSQLDatabases cmdlet을 Invoke-Sqlcmd 호출하여 모든 데이터베이스에 대해 SQL Server를 쿼리합니다. 이 함수는 이전 예제에서 사용된 것과 동일한 특성을 사용하여 자격 증명 매개 변수를 정의합니다. 사용자 이름 및 암호는 변수 내에 $Credential 있으므로 해당 값을 추출하여 사용할 Invoke-Sqlcmd수 있습니다.

사용자 이름은 변수의 UserName 속성 $Credential 에서 사용할 수 있습니다. 암호를 가져오려면 개체의 $Credential 메서드를 GetNetworkCredential() 사용해야 합니다. 값은 매개 변수를 스플래팅하는 데 사용되는 해시 테이블에 추가되는 변수로 Invoke-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 자격 증명을 기본 수 있습니다.