장애 조사나 스크립트 리뷰로 고객사의 PowerShell 스크립트를 살펴보면, 상당한 확률로 마주치는 것이 있습니다. $password = "P@ssw0rd123"── 파일 서버 접속, 기간계 시스템의 DB, 메일 발송, Web API 키. 동작시키는 것을 우선한 결과, 비밀번호가 평문으로 스크립트에 박힌 채로 공유 폴더나 Git 저장소에서 몇 년째 살아 있는 것입니다.
까다로운 점은 작성한 본인도 「좋지 않다는 것은 알고 있다」는 것입니다. 그렇다면 대신 무엇이 정답이냐고 물으면, SecureString, Export-Clixml, SecretManagement, 자격 증명 관리자, Azure Key Vault… 하고 선택지가 난립해 있어 각각의 담당 범위와 한계를 알기 어렵습니다. 게다가 「SecureString은 이제 권장되지 않는다」는 이야기까지 들려와서, 무엇을 믿어야 할지 알 수 없게 됩니다. 이 혼란에는 이유가 있고, 정리하면 길은 명확해집니다.
이 글에서는 사내 운영 스크립트나 정기 배치를 관리하는 정보시스템·운영 담당자를 대상으로, 평문 비밀번호의 무엇이 문제인지부터 시작해 PowerShell의 자격 증명 도구를 구조별로 정리하고, 「무인 실행에서는 어떻게 할 것인가」의 현실적인 해법을 판단표로 정리합니다. PowerShell 7.x를 기준으로 하되, Windows PowerShell 5.1 현장에서의 주의점도 함께 적습니다.
1. 먼저 결론
- 평문 비밀번호의 문제는 「파일이 보이는 순간 유출이 확정」된다는 점입니다. Git 이력·공유 폴더·백업·로그 등 스크립트의 사본이 늘어나는 경로 전부가 유출 경로가 됩니다. 평문을 SecureString으로 변환하는 코드(ConvertTo-SecureString -AsPlainText)를 써도, 원래의 평문이 스크립트나 로그에 남아 있다면 해결이 되지 않습니다.12
- 대화형으로 사용하는 스크립트는 Get-Credential로 PSCredential을 받는 것이 기본형입니다. 비밀번호는 화면에 표시되지 않고, 객체로서 각 명령의 -Credential 매개변수에 전달할 수 있습니다.3
- SecureString은 「신규 개발에서는 권장하지 않는다」고 .NET 공식 문서가 명시합니다. 암호화는 Windows에서만 이루어지며, 비-Windows에서는 내부가 암호화되지 않습니다. 한편 PowerShell은 호환성을 위해 SecureString을 계속 사용하고 있어, 표준적인 전달 형식으로서 당분간은 함께 갈 수밖에 없습니다. 과신하지 말고, 자체 보호 체계의 토대로 삼지 마십시오.45
- 무인 실행에서의 자격 증명 파일 저장은 Export-Clixml에 의한 DPAPI 암호화가 최소 구성의 실용적 해법입니다. 저장한 사용자·저장한 머신에서만 복호화할 수 있으므로, 파일 단독으로 유출되어도 열 수 없습니다. 뒤집어 말하면 「작업 스케줄러의 실행 계정 자신이 저장한다」가 필요합니다. 비-Windows에서는 암호화되지 않습니다.6
- 여러 비밀을 다룬다면 SecretManagement+SecretStore로 일원 관리합니다. Set-Secret/Get-Secret의 통일된 인터페이스로, 로컬의 SecretStore부터 Azure Key Vault까지 저장 위치를 바꿔 끼울 수 있습니다. 다만 무인 실행에서는 볼트 비밀번호의 처리가 과제로 남습니다.78
- 최우선으로 검토할 것은 「애초에 자격 증명을 갖지 않는 설계」입니다. 실행 계정(도메인 계정이나 gMSA) 자체에 접속 대상의 권한을 부여하면 스크립트에서 비밀번호가 사라집니다. gMSA라면 비밀번호 관리 자체를 OS에 맡길 수 있습니다.910
- 로그와 트랜스크립트로의 유출을 설계에 포함시킵니다. 스크립트 블록 로그를 활성화하면, 스크립트에서 사용한 자격 증명 등 민감한 데이터가 이벤트 로그에 기록될 수 있다고 공식 문서가 경고합니다. 평문 비밀번호를 명령줄에 입력한 시점에 기록으로 남는다는 전제로 생각합니다.11
2. 평문의 무엇이 문제인가 ── 유출 경로는 사본의 수만큼 있다
먼저 다시 써야 할 대상이 되는 전형적인 패턴을 확인해 둡니다.
# 안티패턴: 둘 다 「평문이 스크립트에 남는다」는 점에서 같다
$password = "P@ssw0rd123"
# SecureString으로 변환해도, 원래의 평문은 1행째에 그대로 적혀 있다.
# PSScriptAnalyzer는 이 -AsPlainText 사용법을 에러로 검출한다
$secure = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('svc-transfer', $secure)
비밀번호를 직접 적는 것이 위험한 이유는 「악의를 가진 침입자에게 읽힐지도 모른다」는 것만이 아닙니다. 스크립트라는 산출물의 성질상, 정상적인 운영을 하는 것만으로도 사본이 증식한다는 점입니다.
| 사본이 생기는 곳 | 무슨 일이 일어나는가 |
|---|---|
| Git 저장소 | 한 번 커밋된 비밀번호는 이력에 영구 보존. 나중에 파일을 고쳐도 이력에는 남는다 |
| 공유 폴더 | 읽기 권한이 있는 모든 사람 + 백업 + 세대별 사본으로 확산 |
| 메일·채팅 | 「이 스크립트 쓰세요」라며 첨부한 순간 통제 불능 |
| 이벤트 로그 | 스크립트 블록 로그가 활성화되어 있으면, 실행된 코드의 내용이 로그에 기록된다11 |
| 트랜스크립트 | Start-Transcript나 조직의 트랜스크립션 설정이, 화면에 흐른 내용을 기록한다11 |
이 구조가 의미하는 것은, 평문 비밀번호의 대책이 「파일을 보이지 않게 한다」로는 달성되지 않는다는 것입니다. 접근 권한을 아무리 좁혀도 Git 이력과 백업까지는 막을 수 없습니다. 비밀번호를 스크립트 밖으로, 암호화된 보관 장소로 꺼내는 것이 본질입니다. 이 사고방식은 .NET 앱의 설정 파일에 대해 「Windows 앱에서 설정 파일에 기밀 정보를 평문으로 저장하지 않기 위한 베스트 프랙티스」에서 쓴 것과 같으며, PowerShell에서도 원칙은 달라지지 않습니다.
또한 평문을 그 자리에서 SecureString으로 변환하는 ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force는 해결책이 아닙니다. PSScriptAnalyzer(공식 정적 분석 도구)는 이 작성법을 에러(Severity: Error)로 검출합니다. 암호화를 우회해 평문을 메모리에 노출시키는 데다, 원래의 평문이 스크립트 안에 계속 남기 때문입니다.1
3. 도구의 실체 ── PSCredential・SecureString과 그 한계
3.1. Get-Credential과 PSCredential
대화형 스크립트의 기본형은 이것뿐입니다.
# 사용자 이름과 비밀번호 입력을 요청하고, PSCredential 객체로 받는다
$cred = Get-Credential -Message '기간계 DB 접속 계정을 입력해 주세요'
# -Credential 매개변수를 가진 명령에 그대로 전달할 수 있다
Invoke-Command -ComputerName APPSV01 -Credential $cred -ScriptBlock { hostname }
Get-Credential은 사용자 이름과 비밀번호 입력을 요청하고, PSCredential 객체를 반환합니다. Windows PowerShell 5.1에서는 대화 상자로, PowerShell 6 이후에서는 콘솔에서 입력을 받습니다.3 비밀번호는 PSCredential 안에서 SecureString으로 유지되며, 화면에는 표시되지 않습니다. 「사람이 그 자리에서 입력한다」는 운영이 허용되는 장면에서는, 이 이상으로 복잡한 일을 할 필요가 없습니다.
자체 함수를 만드는 쪽은 비밀번호를 [string]으로 받지 말고, [PSCredential]의 -Credential 매개변수를 받도록 설계합니다. 작성법의 세부 사항은 공식 해설 「Add Credential support to PowerShell functions」에 정리되어 있습니다.2
3.2. SecureString의 실체 ── 「비권장」을 올바르게 받아들이는 법
SecureString에 대해 알아 두어야 할 사실이 3가지 있습니다.
- .NET 공식은 「신규 개발에서는 사용하지 않을 것을 권장」합니다. 내부 배열의 암호화는 Windows에서만 이루어지며, 비-Windows 플랫폼에서는 내부 저장소가 암호화되지 않습니다. 또한 사용하는 순간에는 결국 평문 표현으로 변환해야 하므로, 노출 시간을 줄이는 효과밖에 없습니다. 권장되는 대안은 「프로세스 외부에 저장된 자격 증명에 대한 불투명한 핸들」, 즉 OS의 자격 증명 저장소나 Key Vault 같은 체계입니다.4
- 그럼에도 PowerShell의 표준 장비는 SecureString을 전제로 합니다. PowerShell은 호환성을 위해 SecureString을 계속 지원하고 있으며, 콘솔이나 로그로의 우발적인 노출을 피하는 용도로 지금도 사용됩니다. 평문 문자열보다는 안전하다는 정도의 위치입니다.5
- 간단히 평문으로 되돌릴 수 있습니다. PowerShell 7에서는
ConvertFrom-SecureString -AsPlainText한 줄로 평문이 됩니다.12 SecureString은 「읽을 수 없는 금고」가 아니라 「무심코 보이지 않기 위한 봉투」 정도로 생각하는 것이 실체에 맞습니다.
실무의 결론은 이렇습니다. SecureString을 이유로 복잡한 자체 암호화로 달려가지 마십시오. PowerShell의 도구(Get-Credential, SecretManagement)가 요구하는 형식으로 사용하고, 보호의 본체는 DPAPI나 볼트 같은 프로세스 외부의 체계에 둡니다.
4. 무인 실행의 정석 ── Export-Clixml의 DPAPI 저장과 「동일 사용자·동일 머신」의 벽
작업 스케줄러에서 동작하는 무인 스크립트는 Get-Credential로 사람에게 물어볼 수 없습니다. 최소 구성의 실용적 해법이 Export-Clixml에 의한 자격 증명 파일입니다.
# --- 준비(1회만, 작업의 실행 계정으로 실행한다) ---
$cred = Get-Credential -Message '연계용 계정'
$cred | Export-Clixml -Path 'D:\Jobs\secrets\transfer.credential'
# --- 실제 스크립트(무인 실행) ---
$cred = Import-Clixml -Path 'D:\Jobs\secrets\transfer.credential'
# 예: 다른 자격 증명이 필요한 공유 접속이나 원격 실행에 사용
Invoke-Command -ComputerName FILESV01 -Credential $cred -ScriptBlock { Get-ChildItem D:\Export }
Export-Clixml은 자격 증명 객체를 Windows의 DPAPI(데이터 보호 API)로 암호화해 저장합니다. 복호화할 수 있는 것은 저장한 사용자 계정이, 저장한 바로 그 컴퓨터에서 열었을 때뿐입니다. 내보낸 파일은 다른 머신이나 다른 사용자에서는 쓸 수 없습니다.613 파일이 반출되어도 열 수 없다는 성질이 무인 실행의 저장 위치로서 유리한 이유입니다.
왜 그렇게 되는지는 구조를 한 단계만 들여다보면 이해가 됩니다. DPAPI는 사용자의 로그온 자격 증명(보통 비밀번호의 해시)에서 유도한 키로 「마스터 키」를 암호화하고, 이를 그 사용자의 프로필 안에 둡니다. 데이터 본체는 그 마스터 키에서 만들어지는 세션 키로 암호화됩니다. 즉 열쇠를 쥐고 있는 것은 「그 사용자로서 로그온할 수 있다는 것」 자체로, 열쇠 파일을 별도로 어딘가에 보관할 필요가 없는 대신 열쇠가 사용자와 머신에 묶이게 됩니다. 공식 문서도 「일반적으로 암호화한 사용자와 같은 로그온 자격 증명을 가진 사용자만 복호화할 수 있으며, 암호화와 복호화는 같은 컴퓨터에서 이루어져야 한다」고 설명합니다.14 이것이 「동일 사용자·동일 머신 한정」의 실체입니다.
다만 이 「동일 사용자·동일 머신 한정」은 보호이면서 동시에 운영상의 함정이기도 합니다.
- 작업 스케줄러의 실행 계정과 맞출 필요가 있습니다. 자신의 계정으로 만든 .credential 파일은 작업이 서비스 계정으로 동작한 순간 복호화할 수 없게 됩니다. 준비 작업은 반드시 「작업의 실행 계정으로서」 수행해야 합니다(그 계정으로 PowerShell을 실행해 저장한다). 작업의 실행 계정과 로그온 종류에 대한 사고방식은 「작업 스케줄러 작업이 실행되지 않는다・0x1로 끝난다 ── 원인 분리와 안전한 운영 설계」에서 자세히 다뤘습니다.
- 서버 교체나 계정 변경 시 반드시 다시 만들어야 합니다. 「마이그레이션했더니 동작하지 않는다」의 단골 원인이므로, 준비 절차를 스크립트화해 저장소에 남겨 둡니다(비밀번호 자체는 물론 포함하지 않습니다).
- 같은 계정으로 동작하는 프로세스에서는 복호화할 수 있습니다. DPAPI는 그 사용자로서 동작하는 코드에는 열려 있기 때문에, 실행 계정에 불필요한 소프트웨어를 함께 두지 않는다, 계정의 권한을 최소로 한다는 주변의 위생 관리는 여전히 필요합니다.
- 비-Windows에서는 암호화되지 않습니다. macOS/Linux에서는 사실상 평문(유니코드 문자 배열)으로 출력된다고 공식 문서에 명시되어 있습니다.6
「그 계정으로 PowerShell을 실행해 저장한다」의 구체적인 절차도 적어 둡니다. 위의 준비 부분(Get-Credential과 Export-Clixml 2줄)을 D:\Jobs\save-credential.ps1로 저장해 두고, 그 계정으로서 PowerShell을 실행해 실행합니다.
# 준비를 작업의 실행 계정으로 수행한다: runas로 그 계정으로서 PowerShell을 실행한다
# 비밀번호는 runas가 대화형으로 묻기 때문에, 명령줄・이력・트랜스크립트에 평문이 남지 않는다
runas /user:CONTOSO\svc-transfer "pwsh.exe -NoProfile -NoExit -File D:\Jobs\save-credential.ps1"
runas는 대화형 로그온에 준하는 권한을 사용하므로, 그 계정에 「로컬 로그온」을 허용하지 않은 환경에서는 실패합니다. 그 경우에는 준비 작업 동안만 로그온을 허용하고, 저장이 끝나면 원래 설정으로 되돌리는 것이 현실적입니다. Get-Credential 입력 자체에 대화형 세션이 필요하므로, 「무인 작업을 하나 만들어 준비한다」는 방법은 쓸 수 없습니다. 또한 실행 계정의 프로필이 한 번도 만들어지지 않은 머신에서는, 최초 로그온으로 프로필이 만들어진 뒤에야 DPAPI의 마스터 키가 배치된다는 점도 이 절차를 거치는 이유 중 하나입니다.
또한 ConvertFrom-SecureString에 -Key를 지정해 AES 암호화하는 방법도 있지만, 이번에는 「키 파일을 어떻게 지킬 것인가」라는 같은 문제가 한 단계 옆으로 이동해 남을 뿐인 경우가 많습니다.12 머신을 넘나들어야 하는 시점에서는 다음 장의 볼트나, 6장의 「갖지 않는 설계」로 나아가야 합니다.
5. 비밀이 늘어나기 시작하면 ── SecretManagement와 SecretStore
접속 대상이 늘고 API 키나 토큰까지 섞이기 시작하면, .credential 파일이 흩어지는 것이 관리의 한계를 맞습니다. 그럴 때 사용하는 것이 SecretManagement 모듈입니다. 이는 비밀의 보관 장소(볼트)에 대한 통일 인터페이스로, 실제 저장은 확장 볼트가 담당합니다. 로컬 저장의 SecretStore(Microsoft 제작) 외에도 Azure Key Vault, KeePass 등의 확장 볼트를 같은 명령으로 다룰 수 있습니다.715
# 최초 1회만: 모듈 도입과 볼트 등록
Install-Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore
Register-SecretVault -Name SecretStore -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault
# 비밀 등록(최초 접근 시 볼트 비밀번호를 설정한다)
Set-Secret -Name TransferJobCred -Secret (Get-Credential)
# 스크립트 쪽: 이름으로 꺼낸다. 저장 위치가 바뀌어도 이 줄은 바뀌지 않는다
$cred = Get-Secret -Name TransferJobCred
비밀 값에는 PSCredential이나 SecureString 외에도 문자열・바이트 배열・해시 테이블도 저장할 수 있으며, 최초 접근 시에는 볼트 자체를 보호하는 비밀번호 설정을 요구받습니다.16 장점은 스크립트에서 「어디에 저장되어 있는가」에 대한 지식이 사라진다는 것입니다. 개발 머신에서는 SecretStore, 프로덕션에서는 Azure Key Vault(Az.KeyVault 모듈이 확장 볼트를 제공)라는 전환이 Register-SecretVault의 구성 변경만으로 끝납니다.177
한편 무인 실행에 도입할 때는 3가지 주의점이 있습니다.
- SecretStore는 기본적으로 대화형으로 볼트 비밀번호를 요구합니다. 그대로 작업 스케줄러에 올리면 프롬프트 대기로 멈춥니다. 공식 문서는 무인 실행을 위해, Interaction을
None으로 하고 DPAPI로 보호된 파일(Export-Clixml)에 대피시킨 볼트 비밀번호를 Unlock-SecretStore로 전달하는 구성을 안내합니다.8 즉 볼트의 열쇠는 결국 DPAPI로 지키게 되며, 앞 장의 동일 사용자·동일 머신 제약을 그대로 물려받습니다. 비밀번호 요구 자체를 비활성화(Authentication None)하는 구성도 가능하지만, 열쇠가 파일 시스템 권한만으로 지켜지게 되므로 강한 보호가 필요한 용도에는 권장되지 않습니다.18 - gMSA 같은 관리되는 계정에서는 동작하지 않습니다. SecretManagement는 프로필($env:LOCALAPPDATA)과 DPAPI에 의존하고 있어, 프로필을 갖지 않는 Windows의 관리되는 계정을 현재는 지원하지 않는다고 명시되어 있습니다.15 gMSA로 동작하는 작업에 비밀을 갖게 하고 싶다면 이 조합은 선택할 수 없습니다(애초에 gMSA라면 비밀을 갖지 않는 설계로 갈 수 있는 경우가 많습니다 ── 다음 장).
- SecretManagement/SecretStore는 기능 완성(feature complete) 취급이며, 적극적인 신규 기능 개발은 종료되었습니다. 보안 수정과 중대 버그 대응은 계속되므로 사용하는 것 자체는 문제없지만, 공식도 「비밀의 성질은 패스워드리스나 연동 자격 증명으로 바뀌어 가고 있다」고 밝히고 있어, 장기 설계에서는 인증 방식 자체의 재검토(Entra ID의 관리 ID 등)도 시야에 넣어야 합니다.7 관리 ID는 Azure상의 리소스에 할당된 ID로 토큰을 얻어, 비밀번호나 키를 갖지 않고 Entra ID 대응 서비스에 인증하는 체계입니다. 다음에 무엇을 읽어야 할지 말하자면, 먼저 개요 페이지에서 시스템 할당과 사용자 할당의 차이를 파악하고,19 PowerShell에서 사용한다면 Az 모듈의
Connect-AzAccount -Identity(관리 ID로 로그인)를 입구로 삼으면 헤매지 않습니다.
Windows의 자격 증명 관리자(Credential Manager)를 볼트로 사용하는 커뮤니티 확장도 존재합니다.7 cmdkey로 등록한 자격 증명이 자동으로 사용되는 구조 등, 자격 증명 관리자 자체의 동작은 「네트워크 드라이브와 UNC 경로의 함정 ── 업무 앱에서 파일 서버(공유 폴더)를 다루는 실무」에서 다룬 대로이며, 이쪽도 사용자 프로필 단위라는 점은 같습니다.
6. 최우선의 현실적 해법 ── 애초에 자격 증명을 갖지 않는다
여기까지 「어떻게 안전하게 저장할 것인가」를 쌓아 왔지만, 사실 무인 실행의 가장 깔끔한 답은 저장 방법의 궁리가 아닙니다. 스크립트가 자격 증명을 가질 필요를 없애는 것입니다.
Windows의 작업이나 서비스는 실행 계정의 보안 컨텍스트로 동작합니다. 접속 대상이 Windows 인증으로 지켜지고 있다면 ── 공유 폴더의 ACL, SQL Server의 Windows 인증, 사내 API의 Windows 통합 인증 ── 실행 계정 자신에게 접속 대상의 권한을 부여하면, 스크립트에는 비밀번호도 Get-Secret도 전혀 등장하지 않습니다. 인증은 Kerberos가 실행 계정의 신원으로 알아서 처리해 줍니다.
이 구성을 뒷받침하는 것이 gMSA(그룹 관리 서비스 계정)입니다. gMSA는 도메인의 관리되는 계정으로, 비밀번호 관리를 Windows OS가 담당합니다.9 비밀번호는 240바이트의 무작위 생성으로 OS가 30일마다 자동으로 변경하기 때문에, 사람은 아무도 비밀번호를 모르고 기한 만료로 인한 정지도 일어나지 않습니다.10 그리고 gMSA는 Windows 서비스뿐만 아니라 작업 스케줄러의 작업에도 사용할 수 있습니다.20
gMSA 도입 절차의 골격도 적어 둡니다. 「쓸 수 있다」로 끝나면 다음에 무엇을 찾아봐야 할지 알 수 없기 때문입니다. 전제 조건으로, 도메인・포리스트의 기능 수준이 Windows Server 2012 이상일 것, 작업 계정이 Domain Admins 상당일 것, 도메인 컨트롤러 이외에서 작업한다면 RSAT(ActiveDirectory 모듈)가 설치되어 있을 것이 필요합니다.20
# 1) 도메인에 1개만: KDS 루트 키를 만든다(이미 있다면 이 절차는 불필요)
# 모든 도메인 컨트롤러로의 복제를 기다려야 하므로, 실제로 gMSA를 만들 수 있기까지 최대 10시간 걸린다
Add-KdsRootKey -EffectiveImmediately
# 2) gMSA를 만든다. PrincipalsAllowedToRetrieveManagedPassword에는
# 비밀번호 취득을 허용할 컴퓨터(를 모은 보안 그룹)를 지정한다
New-ADServiceAccount -Name svc-transfer -DNSHostName svc-transfer.contoso.local `
-PrincipalsAllowedToRetrieveManagedPassword 'gMSA-Hosts'
# 3) 실제로 작업을 동작시킬 서버 측에서: gMSA를 설치하고, 비밀번호를 얻을 수 있는지 확인한다
Install-ADServiceAccount -Identity svc-transfer
Test-ADServiceAccount -Identity svc-transfer
KDS 루트 키 생성은 도메인에서 1회만 하는 작업입니다. 생성 직후에는 복제 사정으로 gMSA를 만들 수 없으므로, 검증 환경에서 기다리고 싶지 않을 때는 -EffectiveTime ((Get-Date).AddHours(-10))로 과거 일시를 지정하는 절차가 공식적으로 안내됩니다(프로덕션에서는 사용하지 마십시오).21 생성 후에는 KDS 서비스의 운영 로그에 이벤트 ID 4004가 기록되어 있는지로 확인할 수 있습니다.20
작업에 대한 할당은, 작업의 실행 계정에 gMSA(CONTOSO\svc-transfer$처럼 끝에 $가 붙는 계정 이름)를 지정합니다. gMSA는 사람이 비밀번호를 모르기 때문에, 「실행 계정의 비밀번호를 입력한다」는 전제의 GUI 절차와는 사정이 다릅니다. 실무에서는 ScheduledTasks 모듈의 New-ScheduledTaskPrincipal과 Register-ScheduledTask로 등록하게 되므로, 이 두 명령의 문서를 다음 조사 대상으로 삼으십시오. 아울러 해당 서버에서 gMSA에 「배치 작업으로 로그온」 권한을 부여하는 설정이 필요해지는 경우가 있습니다.
판단의 우선순위를 정리하면 이렇게 됩니다.
- 접속 대상을 Windows 인증으로 할 수 있다면, 실행 계정(도메인 계정/gMSA)에 대한 권한 부여로 자격 증명을 없앤다. 도메인 환경의 무인 작업은 먼저 이것을 검토합니다.9
- 그것이 불가능한 상대(SQL 인증의 DB, API 키, 워크그룹의 NAS 등)만, 비밀을 저장한다. 단발이라면 Export-Clixml의 DPAPI 저장, 여러 개라면 SecretManagement+SecretStore.68
- 클라우드 리소스로의 접속은, 키 저장보다 관리 ID/연동 자격 증명 이용을 우선한다. 저장할 경우에도 Azure Key Vault 같은 전용 볼트로.177
원격 서버에 대해 자격 증명을 명시적으로 전달해 처리를 실행하는 장면에서는, PowerShell Remoting의 인증 체계도 얽힙니다. 동시 공개한 「PowerShell Remoting/WinRM 입문」을 참조해 주십시오.
7. 로그・트랜스크립트에 비밀을 남기지 않는다
저장을 굳혀도 실행 시의 기록에서 새어 나가면 의미가 없습니다. 짚어 둘 점은 2가지입니다.
첫째, PowerShell은 실행 내용을 기록하는 기능을 여러 개 가지고 있으며, 조직 설정으로 활성화되어 있는 경우가 있습니다. 스크립트 블록 로그를 활성화하면, 처리된 모든 스크립트 블록의 내용이 이벤트 로그에 기록됩니다. 공식 문서는 「스크립트 로그를 활성화하면, 스크립트에서 사용된 자격 증명이나 민감한 데이터가 이벤트 로그에 기록될 수 있다」고 명시적으로 경고하며, 진단 이외의 용도에서는 보호된 이벤트 로그(Protected Event Logging) 병용을 권장합니다.11 보호된 이벤트 로그는 대상 이벤트 로그의 내용을 CMS(암호화 메시지 구문)의 공개 키로 암호화해 기록하고, 개인 키를 가진 별도의 안전한 장소에서만 복호화할 수 있게 하는 체계입니다.11 트랜스크립션(조작 기록)도 마찬가지로, 콘솔에 흐른 내용은 파일로 남습니다.
자신의 환경이 어떻게 되어 있는지는 정책이 기록하는 레지스트리 값으로 확인할 수 있습니다. 보호된 이벤트 로그는 그룹 정책의 「컴퓨터 구성 > 관리 템플릿 > Windows 구성 요소 > 이벤트 로깅(Event Logging)」에 있는 「보호된 이벤트 로그 사용(Enable Protected Event Logging)」으로 설정되며, 대응하는 레지스트리는 다음과 같습니다.22
# 보호된 이벤트 로그가 활성화되어 있는지(정책이 구성되지 않았다면 키 자체가 존재하지 않는다)
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\EventLog\ProtectedEventLogging' `
-Name EnableProtectedEventLogging -ErrorAction SilentlyContinue
# 스크립트 블록 로그 쪽 정책(PowerShell 7 계열)
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\PowerShellCore\ScriptBlockLogging' `
-Name EnableScriptBlockLogging -ErrorAction SilentlyContinue
# Windows PowerShell 5.1 쪽은 다른 키
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' `
-Name EnableScriptBlockLogging -ErrorAction SilentlyContinue
스크립트 블록 로그의 레지스트리 값은 PowerShell 7 계열이 PowerShellCore 아래11, Windows PowerShell 5.1이 Windows\PowerShell 아래23로 나뉩니다. 5.1과 7이 함께 있는 서버에서는 양쪽을 확인하십시오.
확인할 때의 핵심은 스크립트 블록 로그만 활성화되어 있고 보호된 이벤트 로그는 비활성화되어 있는 조합입니다. 이는 「기록은 남기지만 평문으로 쌓아 둔다」는 상태이므로, 자격 증명을 다루는 스크립트를 올리기 전에 파악해 두어야 합니다.
둘째, 그렇기 때문에 「평문이 명령줄이나 화면을 통과하지 않는」 작성법을 철저히 합니다.
- 비밀번호를 인수로 받는 설계로 하지 않습니다.
.\job.ps1 -Password "P@ssw0rd"라고 입력한 시점에, 로그・이력・프로세스 목록에 남는다는 전제로 생각합니다. 받는다면 PSCredential이나 SecureString으로 받습니다.2
# 자체 스크립트의 입력부 작법: 비밀번호를 [string]으로 받지 않는다
[CmdletBinding()]
param(
# 자격 증명은 PSCredential로 받는다. 생략 시에는 Get-Credential로 대화형 취득,
# 무인 실행에서는 Import-Clixml이나 Get-Secret의 결과를 전달한다
[Parameter(Mandatory)]
[System.Management.Automation.PSCredential]$Credential
)
# 비밀을 포함하는 변수는 디버그 출력하지 않는다. 내보내는 것은 사용자 이름까지
Write-Verbose "접속 계정: $($Credential.UserName)"
- 비밀을 포함하는 변수를 Write-Host나 Write-Verbose로 디버그 출력하지 않습니다. 트러블슈팅 시의 「일시적인 셈치고」 한 출력이 트랜스크립트에 영구적으로 남습니다.
- 예외 메시지에 섞여 들어가는 것에 주의합니다. 접속 문자열을 조립한 뒤 오류를 던지면, catch한 로그에 접속 문자열까지 함께 기록되기 쉽습니다. 오류 처리에서 로그에 무엇을 남길지에 대한 설계는 「PowerShell 오류 처리와 재시도 설계」도 함께 참고하십시오.
8. 실무의 정석(판단표)
| 상황 | 권장 | 판단 기준 |
|---|---|---|
| 사람이 그 자리에서 실행한다 | Get-Credential | 저장하지 않는 것이 가장 안전. PSCredential로 받아 -Credential에 전달3 |
| 도메인 내 무인 작업(접속 대상이 Windows 인증) | 실행 계정/gMSA에 대한 권한 부여 | 자격 증명을 갖지 않는 설계를 최우선. gMSA는 작업 스케줄러에서도 사용 가능920 |
| 무인 작업에서 비밀이 1~2개 | Export-Clixml의 DPAPI 저장 | 작업의 실행 계정 자신이 저장. 머신・계정 변경 시 다시 만들어야 함6 |
| 무인 작업에서 비밀이 다수・저장 위치를 장래 바꾸고 싶다 | SecretManagement+SecretStore | 볼트 비밀번호는 DPAPI 저장+Unlock-SecretStore로 공급. gMSA에서는 사용 불가815 |
| 클라우드 리소스・여러 서버에서 공유하는 비밀 | Azure Key Vault(+SecretManagement) | 머신 국소적인 DPAPI로는 공유할 수 없음. 중앙 관리와 감사가 필요해지면17 |
| 스크립트 내 평문+ConvertTo-SecureString | 다시 써야 할 대상 | PSScriptAnalyzer가 에러로 판정하는 나쁜 형태. 위의 것들로 이행한다1 |
망설여진다면 「갖지 않는다 > 머신에 고정해서 갖는다(DPAPI) > 볼트로 갖는다」의 순서로, 위에서부터 검토하십시오.
9. 정리
- 평문 비밀번호의 본질적인 문제는 Git 이력・공유 폴더・로그라는 사본이 증식하는 경로 전부가 유출 경로가 된다는 것입니다. 접근 권한 관리만으로는 지켜낼 수 없습니다.
- 대화형 실행은 Get-Credential+PSCredential로 충분합니다. 비밀번호를 [string]으로 받는 자체 함수는 만들지 마십시오.
- SecureString은 .NET 공식이 신규 개발 비권장으로 하는 한편, PowerShell의 표준적인 전달 형식으로 남아 있습니다. 「무심코 노출을 막는 봉투」로 받아들이고, 보호의 본체는 외부 체계에 둡니다.
- Export-Clixml의 DPAPI 저장은 「동일 사용자・동일 머신 한정」입니다. 작업 스케줄러의 실행 계정 자신이 저장 파일을 만드는 것이 핵심이며, 비-Windows에서는 암호화되지 않습니다.
- SecretManagement+SecretStore는 여러 비밀의 일원 관리에 유효하지만, 무인 실행에서는 볼트 비밀번호의 공급 설계가 필요하며, gMSA에서는 사용할 수 없습니다. 기능 완성 취급이라는 점도 감안해 채택합니다.
- 최우선은 자격 증명을 갖지 않는 설계입니다. Windows 인증+실행 계정(gMSA)에 대한 권한 부여로, 스크립트에서 비밀번호를 없앨 수 없는지를 가장 먼저 검토해 주십시오.
- 스크립트 블록 로그나 트랜스크립트에는 민감한 데이터가 남을 수 있습니다. 평문이 명령줄・화면・예외 메시지를 통과하지 않는 작성법을 철저히 합니다.
관련 글
- Windows 앱에서 설정 파일에 기밀 정보를 평문으로 저장하지 않기 위한 베스트 프랙티스
- 작업 스케줄러 작업이 실행되지 않는다・0x1로 끝난다 ── 원인 분리와 안전한 운영 설계
- 네트워크 드라이브와 UNC 경로의 함정 ── 업무 앱에서 파일 서버(공유 폴더)를 다루는 실무
- PowerShell Remoting(WinRM) 입문 ── 여러 대의 Windows를 일괄 관리하기
- PowerShell의 에러 처리와 재실행 설계 ── try/catch가 먹히지 않는 함정부터 exit code·재시도의 정석까지
- PowerShell 스크립트의 인수 설계와 모듈화 ── 「작동하는 스크립트」에서 「남에게 넘길 수 있는 스크립트」로
관련 상담 영역
합동회사 코무라소프트에서는 운영 스크립트・정기 배치에 박혀 있는 자격 증명의 전수 조사와 안전한 보관으로의 이행, gMSA를 포함한 실행 계정 설계, 무인 실행 작업의 보안 리뷰를 다루고 있습니다. 「동작하고 있으니 손대지 못한다」며 방치된 평문 비밀번호의 정리부터 상담해 주십시오.
참고 링크
-
Microsoft Learn, AvoidUsingConvertToSecureStringWithPlainText. PSScriptAnalyzer가 ConvertTo-SecureString의 -AsPlainText 사용을 에러(Severity: Error)로 검출하는 것, 암호화를 우회해 민감한 정보를 평문으로 메모리에 노출시키는 것, 대안으로 Read-Host -AsSecureString이나 SecretStore 모듈이 제시되는 것에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Add Credential support to PowerShell functions. 자체 함수에 PSCredential 매개변수를 추가하는 방법, 평문 비밀번호가 다양한 로그에 기록되기 때문에 ConvertTo-SecureString -AsPlainText 사용 시 경고되는 이유에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Get-Credential. Get-Credential이 사용자 이름과 비밀번호 입력을 요청해 PSCredential 객체를 반환하는 것, Windows PowerShell 5.1에서는 대화 상자로・PowerShell 6 이후에서는 콘솔에서 입력을 요청하는 것, -Credential 매개변수를 가진 명령에 전달해 사용하는 것에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, SecureString Class. .NET(Core)의 신규 개발에서 SecureString을 사용하지 않을 것이 권장되는 것, 암호화가 Windows에서만 이루어지며 비-Windows에서는 내부 저장소가 암호화되지 않는 것, 사용 시에는 평문 표현으로의 변환이 필요한 것, 권장 대안이 프로세스 외부에 저장된 자격 증명에 대한 불투명한 핸들인 것에 대해. ↩ ↩2
-
Microsoft Learn, Advisory Development Guidelines. .NET이 SecureString의 신규 이용을 권장하지 않는 한편, PowerShell은 하위 호환성을 위해 SecureString을 계속 지원하는 것, 평문 문자열보다는 안전하며 콘솔이나 로그로의 우발적 노출을 피하기 위해 사용되는 것, 쉽게 평문으로 변환할 수 있으므로 주의해서 사용해야 하는 것에 대해. ↩ ↩2
-
Microsoft Learn, Export-Clixml. Export-Clixml이 자격 증명 객체를 Windows의 DPAPI로 암호화해 저장하는 것, 복호화할 수 있는 것이 저장한 사용자 계정・저장한 컴퓨터에서뿐이며 내보낸 파일을 다른 머신・다른 사용자에서 사용할 수 없는 것, 비-Windows(macOS/Linux)에서는 암호화되지 않고 사실상 평문으로 출력되는 것에 대해. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Overview of the SecretManagement and SecretStore modules. SecretManagement가 확장 볼트에 대한 통일 인터페이스인 것, SecretStore가 로컬 파일에 암호화 저장하는 크로스 플랫폼 확장 볼트인 것, Azure Key Vault・KeePass・자격 증명 관리자(CredMan) 등의 확장 볼트가 존재하는 것, Secret 모듈군이 기능 완성 취급이며 적극적인 개발이 종료되고 보안 수정만 계속되는 것에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Use the SecretStore in automation. 무인 실행을 위해 SecretStore의 Interaction을 None으로 구성하는 것, 볼트 비밀번호를 Export-Clixml로 DPAPI 암호화한 파일에 저장하고 Unlock-SecretStore로 잠금을 해제하는 구성, 이것이 Windows 한정의 해결책인 것에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Group Managed Service Accounts overview. gMSA가 자동 비밀번호 관리와 SPN 관리 간소화를 제공하는 관리되는 도메인 계정이며, 비밀번호 관리를 관리자가 아니라 Windows OS가 담당하는 것에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Secure group managed service accounts. gMSA의 비밀번호가 240바이트의 무작위 생성인 것, OS가 30일마다 자동으로 변경하기 때문에 비밀번호 변경 계획이나 서비스 정지가 불필요해지는 것, 온프레미스 서비스의 계정 종류로 gMSA 사용이 권장되는 것에 대해. ↩ ↩2
-
Microsoft Learn, about_Logging_Windows. 스크립트 블록 로그를 활성화하면 PowerShell이 처리하는 모든 스크립트 블록의 내용이 이벤트 로그에 기록되는 것, 로그 수준을 높이면 스크립트에서 사용된 자격 증명 등 민감한 데이터가 로그에 포함될 수 있는 것, PowerShell 7 계열에서 스크립트 블록 로그를 활성화하는 레지스트리 값이
HKLM:\Software\Policies\Microsoft\PowerShellCore\ScriptBlockLogging의EnableScriptBlockLogging인 것, Protected Event Logging이 CMS(암호화 메시지 구문)의 공개 키로 이벤트 로그의 내용을 암호화하고 개인 키를 가진 안전한 장소에서 복호화하는 체계인 것에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 -
Microsoft Learn, ConvertFrom-SecureString. SecureString을 암호화된 표준 문자열로 변환할 수 있는 것, 키를 지정하지 않으면 Windows의 DPAPI가, Key/SecureKey 지정 시에는 AES가 사용되는 것, -AsPlainText로 평문 문자열로 직접 변환할 수 있는 것에 대해. ↩ ↩2
-
Microsoft Learn, Import-Clixml. Import-Clixml로 Export-Clixml이 저장한 자격 증명・보안 문자열을 복원할 수 있는 것, 이를 통해 스크립트 내에 평문 비밀번호를 적는 위험을 피할 수 있는 것에 대해. ↩
-
Microsoft Learn, CryptProtectData function. 일반적으로 암호화한 사용자와 같은 로그온 자격 증명을 가진 사용자만 복호화할 수 있는 것, 암호화와 복호화가 일반적으로 같은 컴퓨터에서 이루어져야 하는 것, 함수가 사용자의 로그온 자격 증명에서 세션 키를 만들어 암호화를 수행하는 것에 대해. ↩
-
Microsoft Learn, Understanding the SecretManagement module. SecretManagement가 등록된 확장 볼트를 통해 비밀을 저장・취득하는 구조인 것, 볼트 등록이 사용자 컨텍스트 단위인 것, $env:LOCALAPPDATA와 DPAPI에 대한 의존으로 인해 Windows의 관리되는 계정(managed accounts)에서는 현재 동작하지 않는 것에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Get started with the SecretStore module. Register-SecretVault를 통한 SecretStore 등록, Set-Secret/Get-Secret/Get-SecretInfo의 기본 조작, 최초 접근 시 볼트 비밀번호 설정을 요구받는 것에 대해. ↩
-
Microsoft Learn, Use Azure Key Vault in automation. Az.KeyVault 3.3.0 이후가 SecretManagement 확장을 포함하는 것, Register-SecretVault로 Azure Key Vault를 SecretManagement의 볼트로 등록해 Get-Secret 등으로 조작할 수 있는 것에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Understanding the security features of SecretManagement and SecretStore. 비밀번호 인증을 완전히 비활성화한 경우, 복호화 키가 파일 시스템 권한만으로 보호되며, 강한 보안 보호가 필요한 시스템에는 권장되지 않는 것에 대해. ↩
-
Microsoft Learn, What are managed identities for Azure resources?. 관리 ID가 Entra ID상의 ID를 사용해 자격 증명을 관리하지 않고 토큰을 얻는 체계인 것, 시스템 할당과 사용자 할당의 2종류와 그 차이에 대해. ↩
-
Microsoft Learn, Manage group Managed Service Accounts. gMSA를 서비스 제어 관리자 구성의 서비스, IIS 애플리케이션 풀, 작업 스케줄러의 작업에서 사용할 수 있는 것, 전제 조건(도메인・포리스트의 기능 수준이 Windows Server 2012 이상, Domain Admins/Enterprise Admins의 멤버십, KDS 루트 키의 존재와 KdsSvc 운영 로그의 이벤트 ID 4004로 확인, 도메인 컨트롤러 이외에서의 작업에 RSAT가 필요한 것), New-ADServiceAccount를 통한 생성 절차와 PrincipalsAllowedToRetrieveManagedPassword 지정, Install-ADServiceAccount/Test-ADServiceAccount를 통한 도입과 확인에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Create the Key Distribution Services KDS Root Key. gMSA의 비밀번호 생성에 KDS 루트 키가 필요한 것, Add-KdsRootKey -EffectiveImmediately를 통한 생성과 모든 도메인 컨트롤러로의 복제 수렴을 위해 최대 10시간 기다려야 하는 사양, 검증 환경용으로 Add-KdsRootKey -EffectiveTime으로 과거 일시를 지정해 대기 시간을 회피하는 절차에 대해. ↩
-
Microsoft Learn, ADMX_EventLogging Policy CSP. EnableProtectedEventLogging 정책이 컴퓨터 구성의 「Windows 구성 요소 > 이벤트 로깅」에 있는 것, 대응하는 레지스트리 키가
Software\Policies\Microsoft\Windows\EventLog\ProtectedEventLogging, 값 이름이EnableProtectedEventLogging인 것에 대해. ↩ -
Microsoft Learn, about_Logging (Windows PowerShell 5.1). Windows PowerShell 5.1에서 스크립트 블록 로그를 활성화하는 레지스트리 값이
HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging의EnableScriptBlockLogging인 것에 대해. ↩
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
PowerShell Remoting(WinRM) 입문 ── 여러 대의 Windows를 일괄 관리하기
PowerShell Remoting(WinRM)으로 여러 대의 Windows를 일괄 관리하는 입문서입니다. 동작 원리와 포트 5985/5986, Enable-PSRemoting으로 일어나는 일, 워크그룹의 TrustedHosts, Invoke-C...
PowerShell의 실행 정책과 스크립트 서명 ── 'Bypass로 덮어버리는' 운영에서 벗어나는 실무 가이드
PowerShell의 실행 정책은 '보안 경계가 아니라 안전장치'입니다. RemoteSigned 등의 차이, 범위의 우선순위, Mark of the Web과 Unblock-File, 스크립트 서명, 사내 배포의 현실적인 운영까지 정리합니다.
PowerShell 스크립트가 느릴 때 살펴볼 곳 ── 배열・파이프라인・대조의 급소
PowerShell 스크립트가 느려지는 대표적인 원인을 정리합니다. 배열의 +=가 O(n^2)이 되는 이유, 파이프라인과 foreach의 차이, 대조의 해시테이블화, 파일 I/O 개선, 그리고 올바른 측정법까지 실무 관점에서 설명합니다.
Write-Host를 그만두다 ── PowerShell의 출력 스트림과 로그 설계
PowerShell 6가지 출력 스트림의 구분 사용법, Write-Host가 안고 있는 문제와 올바른 쓰임새, 함수의 반환값이 오염되는 원인, -Verbose나 -InformationVariable을 통한 호출 측 제어, 구조화 로그를 남기는 방...
PowerShell의 병렬 처리 ── ForEach-Object -Parallel과 작업(Job)의 구분 사용
ForEach-Object -Parallel·Start-ThreadJob·Start-Job의 차이와 구분 사용, $using:와 스레드 안전성, ThrottleLimit을 정하는 법, 오히려 느려지는 경우까지 실무 관점에서 정리합니다.
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- PowerShell 스크립트에 비밀번호를 평문으로 써서는 안 되는 이유는 무엇인가요?
- 스크립트는 복사되고, 공유되고, 이력에 남는 것을 전제로 한 산출물이기 때문입니다. Git에 한 번 커밋하면 이력에서 지우기 어렵고, 공유 폴더에 두면 읽기 권한이 있는 모든 사람에게 보이며, 스크립트 블록 로그나 트랜스크립트에는 명령의 내용이 그대로 기록됩니다. 즉 평문 비밀번호는 「파일이 보이는 순간 유출이 확정」되는 구조를 만들어 버립니다. 유출 경로를 먼저 막는 것이 아니라, 비밀번호를 스크립트 밖의 보호된 장소로 꺼내는 것이 대책의 본질입니다.
- Export-Clixml로 저장한 자격 증명은 어디까지 안전한가요?
- Windows에서는 DPAPI(데이터 보호 API)로 암호화되어, 저장한 사용자 계정이면서 동일한 컴퓨터에서만 복호화할 수 있습니다. 파일이 탈취되더라도 다른 머신·다른 사용자로는 열 수 없기 때문에 무인 실행용 저장소로서는 실용적인 선택지입니다. 다만 같은 계정으로 동작하는 프로세스에서는 복호화할 수 있으므로 만능은 아니며, macOS나 Linux에서는 암호화되지 않고 사실상 평문으로 출력된다는 점에 주의해야 합니다. 작업 스케줄러에서 사용할 경우, 작업의 실행 계정 자신이 저장 파일을 만들어야 합니다.
- SecureString은 지금도 사용해야 하나요?
- .NET 공식 문서는 신규 개발에서 SecureString 사용을 권장하지 않는다고 명시하고 있습니다. 암호화는 Windows에서만 이루어지며, 비-Windows에서는 내부가 암호화되지 않습니다. 또한 사용하는 순간에는 결국 평문으로 되돌려야 합니다. 한편 PowerShell 세계에서는 Get-Credential이나 SecretManagement 같은 표준 도구가 SecureString을 전제로 하고 있어, 평문 문자열로 들고 다니는 것보다는 노출이 줄어들기 때문에, 당분간은 「PowerShell의 표준적인 전달 형식」으로 받아들이는 것이 현실적입니다. 자체 암호화 체계를 만드는 재료로는 삼지 마십시오.
- 작업 스케줄러의 무인 실행에서 SecretStore를 쓰면 비밀번호 입력에서 멈추지 않나요?
- 기본 구성 그대로라면 멈춥니다. SecretStore는 기본적으로 볼트 비밀번호를 요구하며 대화형 프롬프트를 띄우기 때문입니다. 무인 실행에서는 Interaction을 None으로 하고, 볼트 비밀번호를 DPAPI로 보호된 파일(Export-Clixml)에서 읽어와 Unlock-SecretStore로 잠금을 해제하는 구성이 공식 문서에서 안내됩니다. 다만 이는 「볼트의 열쇠를 DPAPI로 지키는」 구성이므로, 결국 DPAPI의 제약(동일 사용자·동일 머신)을 그대로 물려받습니다. 그 앞 단계에서 gMSA나 실행 계정에 대한 권한 부여로 자격 증명 자체를 불필요하게 만들 수 없는지를 먼저 검토하십시오.
- 애초에 자격 증명을 저장하지 않는 방법도 있나요?
- 있습니다. 오히려 그것이 제1선택지입니다. Windows의 작업이나 서비스는 실행 계정의 권한으로 동작하므로, 접속 대상(공유 폴더, SQL Server의 Windows 인증 등)에 실행 계정 자신의 권한을 부여하면 스크립트는 비밀번호를 전혀 갖지 않아도 됩니다. 실행 계정을 gMSA(그룹 관리 서비스 계정)로 하면, 비밀번호는 240바이트의 무작위 값을 OS가 30일마다 자동으로 갱신하여 사람이 아무도 비밀번호를 모르는 상태를 만들 수 있습니다. gMSA는 작업 스케줄러의 작업에도 사용할 수 있습니다.