Files
networkSetup/docs/manuals/azure-artifact-signing/README.md
T
jychoi4andClaude Opus 5.5 7f5540f148 docs: design the EXE installer UI and code signing scope
- Design 14: WiX MSI + Burn with a C# BA host and WebView2 web UI,
  default screen catalog, installer-ui.json and the WebView2 fallback.
- Design 16: Smart App Control checks and what must be signed.
- Manual: beginner guide to Azure Artifact Signing.
- Link the decision from designs 09 and 10 and record it.

Refs #15

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 11:08:50 +09:00

23 KiB

처음 시작하는 Azure 아티팩트 서명(Artifact Signing) 운영 서명

대상: Installer Studio로 만든 MSIX를 사내 시험을 넘어 실제 사용자 PC에 배포하려는 담당자. 자체 서명 테스트 인증서 대신 공인 신뢰 서명을 처음 준비하는 사람 기준으로 쓴다.

확인일: 2026-11-03, 한국 시간. Microsoft Learn 한국어·영어 문서(2026-10-08 갱신판)를 확인해 작성했으며 실제 계정 생성·신원 확인·서명을 수행한 기록은 아니다. 메뉴 이름은 Azure 포털 한국어 화면 기준으로 적고 영문을 괄호로 병기한다. Learn 한국어 페이지는 기계 번역이므로 실제 포털 표기가 약간 다를 수 있다. 2026년에 서비스 이름이 **Trusted Signing → Artifact Signing(아티팩트 서명)**으로 바뀌었다. 포털 검색, 역할 이름, winget 패키지 ID에는 옛 이름이 남아 있으므로 두 이름을 같은 것으로 읽는다.

이 방식이 하는 일

Azure가 인증서 발급·보관·갱신을 모두 맡고, 우리 PC에서는 SignTool이 Azure에 서명 요청만 보낸다. 인증서 개인 키는 Azure HSM 안에 있어 USB 토큰이나 PFX 파일이 없다. 인증서는 3일마다 자동 교체되지만 주체(Subject: CN, O, L, S, C)는 신원 확인 결과로 고정되므로 MSIX의 Publisher가 바뀌지 않는다.

Azure 구독 준비 → 리소스 공급자 등록 → 아티팩트 서명 계정 만들기
→ 조직 ID 유효성 검사(1~20영업일) → 인증서 프로필 만들기 → 역할 할당
→ 서명 PC에 클라이언트 도구 설치 → metadata.json 작성 → az login → signtool로 MSIX 서명
→ 서명 검증 → Installer Studio Publisher를 인증서 주체로 맞춤

용어 대응표

포털 한국어 표기 영어 뜻
아티팩트 서명 계정 Artifact Signing account 서명 서비스의 최상위 리소스
ID 유효성 검사 Identity validation 회사(또는 개인) 신원 확인 요청
인증서 프로필 Certificate profile 실제 인증서가 발급되는 단위
공용 / 프라이빗 Public / Private 공개 배포용 / 사내 전용
액세스 제어(IAM) Access control (IAM) 역할 부여 메뉴
아티팩트 서명 ID 검증 도구 Artifact Signing Identity Verifier 신원 확인 요청 권한
아티팩트 서명 인증서 프로필 서명자 Artifact Signing Certificate Profile Signer 서명 실행 권한
인증서 제목(주체) 미리 보기 Certificate subject preview 인증서에 들어갈 CN·O 문자열

시작 전 확인

항목 내용
지원 국가 공용 신뢰(Public Trust) 인증서는 미국, 캐나다, EU, 영국, 호주, 뉴질랜드, 일본, 한국, 싱가포르, 스위스, 노르웨이, 이스라엘의 조직에 제공한다. 개인 개발자는 미국·캐나다만 가능하다. 한국 법인은 조직으로 진행한다.
Azure 지역 계정은 지원 지역에만 만들 수 있다. Korea Central이 포함되어 있고 엔드포인트는 https://krc.codesigning.azure.net이다.
비용 기본(Basic)은 월 5,000회, 프리미엄(Premium)은 월 100,000회 서명을 포함한다. 금액은 가격 페이지의 계산기에서 확인한다(제3자 자료 기준 월 약 10달러·100달러). 계정을 만든 날부터 과금되고 일할 계산이 없다. 신원 확인이 끝나기 전에도 요금이 나간다.
대상 Windows Windows 10 1809 이상, Windows 11, Windows Server 2016 이상이 루트를 신뢰한다. 더 오래된 PC는 지원 범위에서 제외한다.
SmartScreen 서명해도 즉시 신뢰되지 않는다. 설치 실적이 쌓이기 전에는 경고가 뜰 수 있으며 정상 동작이다.
필요한 사람 Azure 구독 소유자(역할 부여), 회사 대표로 개인 신원 확인을 할 담당자(신분증과 스마트폰), 서명을 실행할 개발자.

1단계. Azure 구독과 테넌트 준비

  1. Azure 포털에 회사 계정으로 로그인한다. 회사 Microsoft Entra 테넌트가 없으면 먼저 만든다.
  2. **구독(Subscriptions)**이 있어야 한다. 없으면 구독을 만들고 결제 수단을 등록한다. 조직 신원 확인에는 청구 계정 유형 조건이 없다(개인 확인에만 "개인(Individual)" 유형이 필요하다).
  3. 검색 상자에 구독을 입력해 열고 대상 구독을 선택한다. 왼쪽 메뉴 **설정 → 리소스 공급자(Resource providers)**에서 Microsoft.CodeSigning을 찾아 줄임표(…) → **등록(Register)**을 누른다. 상태가 **등록됨(Registered)**으로 바뀌면 된다.

Azure CLI를 쓰면 같은 작업은 다음과 같다.

az login
az account set -s <구독 ID>
az provider register --namespace "Microsoft.CodeSigning"
az extension add --name artifact-signing

2단계. 아티팩트 서명 계정 만들기

  1. 포털 검색 상자에 **아티팩트 서명 계정(Artifact Signing Accounts)**을 입력해 열고 **만들기(Create)**를 누른다.
  2. 입력값
    • 구독(Subscription): 1단계의 구독
    • 리소스 그룹(Resource group): 새로 만들기(Create new). 예: rg-codesigning
    • 계정 이름(Account name): 3~24자 영숫자, 전 세계에서 유일, 문자로 시작. 예: baronsigning
    • 지역(Region): Korea Central
    • 가격 책정(Pricing): 처음에는 기본(Basic)
  3. 검토 + 만들기(Review + create) → 만들기(Create). 완료되면 리소스로 이동(Go to resource).
  4. 계정 개요(Overview) 화면의 **계정 URI(Account URI)**를 적어 둔다. 뒤의 metadata.json에 들어간다.
az group create --name rg-codesigning --location koreacentral
az artifact-signing create -n baronsigning -l koreacentral -g rg-codesigning --sku Basic

3단계. 역할 할당

계정 화면 왼쪽 메뉴 액세스 제어(IAM) → 추가(Add) → 역할 할당 추가(Add role assignment). 역할(Role) 탭의 검색란에 "아티팩트 서명"을 입력하면 두 개의 사용자 지정 역할이 보인다. 역할을 고른 뒤 구성원(Members) 탭에서 사람 또는 앱을 선택하고 **검토 + 할당(Review + assign)**을 누른다.

역할 누구에게 용도
아티팩트 서명 ID 검증 도구 (Artifact Signing Identity Verifier, 구 Trusted Signing Identity Verifier) 신원 확인을 신청할 담당자 4단계 새 ID 버튼 활성화. 구독에 읽기 권한자(Reader) 이상이 함께 있어야 한다
아티팩트 서명 인증서 프로필 서명자 (Artifact Signing Certificate Profile Signer, 구 Trusted Signing Certificate Profile Signer) 서명을 실행할 개발자 계정, 또는 CI용 앱 등록(서비스 주체) 7단계 서명 호출 허용

계정과 인증서 프로필을 만드는 사람에게는 기여자(Contributor) 이상이 필요하다. 구독 **소유자(Owner)**라도 위 두 사용자 지정 역할이 없으면 해당 작업이 막힌다. 역할 반영에 몇 분 걸릴 수 있다.

여러 사람이 함께 서명할 때의 구조

서명자 역할을 사람마다 직접 주지 않고 보안 그룹에 한 번만 주고 사람은 그룹에 넣고 뺀다. 서명 PC에는 PFX나 비밀 값이 없으므로, 퇴사·이동 시 그룹에서 빼는 것만으로 서명이 즉시 막히고 인증서를 폐기할 필요가 없다.

  1. Microsoft Entra ID → 그룹(Groups) → 새 그룹(New group). 그룹 유형 보안(Security), 이름 예 sg-codesigning-signers. 멤버십 유형은 할당됨(Assigned).
  2. 3단계의 역할 할당 추가에서 구성원 탭의 액세스 할당 대상을 "사용자, 그룹 또는 서비스 주체"로 두고 그룹을 선택한다. 역할은 아티팩트 서명 인증서 프로필 서명자.
  3. 권한은 세 층으로 나눈다.
층 대상 역할 비고
소유 회사 대표 계정 1~2명 구독 소유자 결제·역할 변경. 평소 서명에 쓰지 않는다
운영 서명 인프라 담당 1~2명 리소스 그룹 기여자 + ID 검증 도구 계정·프로필 생성, 신원 확인 갱신
서명 sg-codesigning-signers 그룹 인증서 프로필 서명자 개발자 전원, CI용 앱 등록. 프로필을 바꾸거나 지울 수 없다
  1. 사람마다 자기 계정으로 az login한다. 한 계정을 여럿이 공유하면 MFA·감사 기록·퇴사 처리가 모두 깨진다. 모든 서명자는 같은 Entra 테넌트에 있어야 하므로 대표 계정이 개인 Microsoft 계정의 기본 디렉터리라면 다른 사람을 게스트 초대해야 하고, 회사 도메인 테넌트가 있다면 그쪽에서 진행하는 것이 맞다.
  2. CI 서버는 **앱 등록(App registrations)**으로 서비스 주체를 만들어 같은 그룹에 넣는다. GitHub Actions·Azure DevOps는 클라이언트 비밀 대신 **페더레이션 자격 증명(워크로드 ID)**을 쓰면 비밀 저장이 없다.
  3. metadata.json은 비밀이 아니므로 저장소에 두고 공유한다. 팀·PC 구분이 필요하면 "CorrelationId": "ci-main"처럼 값을 넣어 서명 기록에서 구분한다.
  4. 서명 횟수는 계정 단위로 합산된다. 기본(Basic) 월 5,000회를 모든 서명자와 CI가 함께 쓴다. CI가 커밋마다 서명하면 빠르게 소진되므로 릴리스 빌드에서만 서명하거나 프리미엄으로 올린다. 기본 계층은 공용 신뢰 프로필을 1개만 만들 수 있다. 같은 회사의 여러 제품은 주체가 같으므로 프로필 1개를 함께 쓰면 된다.
  5. **서명 기록(Signing history)**은 서명자 역할이 볼 수 있고, 역할 변경은 **활동 로그(Activity log)**에 남는다. 역할 할당 변경에 경고 규칙을 걸어 두면 무단 추가를 감지할 수 있다.

4단계. 조직 ID 유효성 검사

가장 오래 걸리는 단계다. 처리 기간은 영업일 기준 1~20일이며 보완 서류 요청이 오면 더 길어진다. 여기서 입력한 회사명·주소가 그대로 인증서 주체가 되고 MSIX Publisher가 된다. 나중에 고치려면 ID 유효성 검사를 새로 해야 하고 앱 계열이 끊어지므로 처음부터 등기 서류와 똑같이 적는다.

  1. 계정 화면 왼쪽 메뉴 **개체(Objects) → ID 유효성 검사(Identity validations)**를 연다.
  2. 상단에서 **조직(Organization)**을 선택하고 **새 ID(New identity) → 공용(Public)**을 누른다.
  3. 새 조직 유효성 검사(New organization validation) 폼 입력값
항목(한국어 / 영어) 적는 내용
조직 이름 / Organization Name 법인 등기상의 정식 명칭. 영문 표기는 사업자등록증·영문 등기부의 표기와 일치
웹 사이트 URL / Website url 회사가 소유한 도메인의 웹사이트
기본 이메일 / Primary Email 회사 도메인의 실제 수신 가능한 메일. 확인 링크가 오며 7일 안에 열어야 한다
보조 이메일 / Secondary Email 기본과 다른 같은 도메인 메일. 메일 그룹 가능
비즈니스 식별자 / Business Identifier 사업자등록번호 또는 법인등록번호
판매자 ID / Seller ID Microsoft Store 판매자만. 없으면 비움
도로명, 도시, 국가/지역, 주/도, 우편번호 법인 사업장 주소
이름 / First Name, 성 / Last Name 회사를 대표해 개인 신원 확인을 할 담당자. 여권 등 신분증 표기와 똑같이 적는다
  1. **인증서 제목 미리 보기(Certificate subject preview)**로 인증서에 들어갈 문자열을 미리 본다. 이 값이 나중의 Publisher다.
  2. 만들기(Create). 상태가 **진행 중(In Progress)**이 된다.
  3. 상태가 **작업 필요(Action Required)**로 바뀌면 담당자 개인 확인 차례다. 기본 이메일로도 링크가 온다.
    1. 요청에 적은 이메일로 로그인해 링크를 연다.
    2. **신뢰할 수 있는 ID 검증 도구를 통해 여기에서 확인 받기(Get verified here through our trusted ID-verifiers)**를 누르면 외부 확인 업체(AU10TIX) 화면으로 간다.
    3. 이메일 PIN 확인 → 전화번호 입력 → 시작(Start) → 노트북 화면의 QR 코드를 스마트폰으로 스캔.
    4. 스마트폰에서 여권·운전면허증·신분증 촬영과 안면 확인을 진행한다. 플래시 없이, 평평한 곳에서, 잘리지 않게 찍는다.
    5. **인증자 열기(Open Authenticator)**로 Microsoft Authenticator 앱에 확인된 ID(Verified ID)를 **추가(Add)**하고, 다시 브라우저 QR 코드를 스캔해 **공유(Share)**한다.
    6. 브라우저에 **확인 성공(Verification Successful)**이 뜨면 포털 상태가 몇 분 뒤 진행 중으로 돌아가 조직 확인이 이어진다.
  4. 서류 보완 메일이 오면 포털에서 업로드한다. 업로드 기회는 3번이다. 12개월 이내 발급, 만료가 2개월 이상 남은 서류여야 한다. 사업자등록증·법인등기부등본과 도메인 등록 증빙(회사명·도메인이 함께 적힌 것)을 준비해 둔다.
  5. 상태가 **완료(Completed)**가 되면 다음 단계로 간다. **실패(Failed)**면 사유 메일을 확인하고 새 요청을 만든다.

5단계. 인증서 프로필 만들기

  1. 계정 화면 **개체 → 인증서 프로필(Certificate profiles) → 만들기(Create)**에서 **공용 신뢰(Public Trust)**를 고른다.
  2. 인증서 프로필 이름(Certificate Profile Name): 5~100자. 예: baron-public-trust
  3. **인증서 유형(Certificate Type)**은 자동 입력, **프로그램 유형(Program Type)**은 없음(None) 그대로 둔다.
  4. **유효성 검사된 CN 및 O(Verified CN and O)**에서 4단계에서 완료된 ID 유효성 검사를 선택한다. 거리 주소 포함(Include street address), **우편 번호 포함(Include postal code)**은 선택 사항이며 기본은 끈다.
  5. **인증서 제목 미리 보기(Certificate Subject Preview)**에 최종 주체가 보인다. 이 문자열을 그대로 복사해 보관한다. 예: CN=Baron Software Co., Ltd., O=Baron Software Co., Ltd., L=Seoul, S=Seoul, C=KR
  6. 만들기(Create).

CLI로는 ID 유효성 검사 화면에서 ID 유효성 검사 ID를 복사한 뒤 다음을 실행한다.

az artifact-signing certificate-profile create -g rg-codesigning --account-name baronsigning -n baron-public-trust --profile-type PublicTrust --identity-validation-id <ID 유효성 검사 ID>

6단계. 서명 PC 준비

서명을 실행할 PC(개발 PC 또는 빌드 서버)에서 한다. Windows 10 1809 이상이어야 한다.

  1. 관리자 PowerShell에서 클라이언트 도구를 설치한다. SignTool, .NET 8 런타임, 서명 플러그인(dlib)이 함께 들어온다.
winget install -e --id Microsoft.Azure.ArtifactSigningClientTools

winget이 없는 서버는 MSI를 직접 받는다.

$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -Uri "https://download.microsoft.com/download/70ad2c3b-761f-4aa9-a9de-e7405aa2b4c1/ArtifactSigningClientTools.msi" -OutFile .\ArtifactSigningClientTools.msi
Start-Process msiexec.exe -Wait -ArgumentList '/I ArtifactSigningClientTools.msi /quiet'
Remove-Item .\ArtifactSigningClientTools.msi
  1. Windows SDK의 일반 SignTool은 이 플러그인과 호환되지 않는 버전일 수 있다. 설치된 도구 폴더의 SignTool을 쓴다. 기본 경로는 C:\Program Files (x86)\Microsoft\ArtifactSigningClientTools\bin이다.
  2. metadata.json을 만든다. Endpoint는 2단계의 계정 URI와 같아야 하며 지역이 다르면 403 오류가 난다.
{
  "Endpoint": "https://krc.codesigning.azure.net",
  "CodeSigningAccountName": "baronsigning",
  "CertificateProfileName": "baron-public-trust"
}
  1. Azure CLI를 설치하고 서명자 역할이 있는 계정으로 로그인한다. 사람이 서명하는 PC에서는 이것으로 충분하다.
az login

빌드 서버에서는 **Microsoft Entra ID → 앱 등록(App registrations)**에서 앱을 만들어 3단계의 서명자 역할을 주고 환경 변수로 인증한다. 비밀 값은 소스나 프로젝트 파일에 넣지 않는다.

$env:AZURE_TENANT_ID = "<테넌트 ID>"
$env:AZURE_CLIENT_ID = "<앱 등록 클라이언트 ID>"
$env:AZURE_CLIENT_SECRET = "<클라이언트 비밀>"

7단계. MSIX 서명

서명 전에 패키지의 Publisher가 5단계의 주체와 글자 단위로 같아야 한다. 다르면 SignTool이 0x8007000B로 거부한다.

& "C:\Program Files (x86)\Microsoft\ArtifactSigningClientTools\bin\signtool.exe" sign /v /fd SHA256 `
  /tr "http://timestamp.acs.microsoft.com" /td SHA256 `
  /dlib "C:\Program Files (x86)\Microsoft\ArtifactSigningClientTools\bin\x64\Azure.CodeSigning.Dlib.dll" `
  /dmdf .\metadata.json `
  .\package.msix
  • /tr과 /td의 타임스탬프는 반드시 넣는다. 인증서가 3일 뒤 만료되므로 타임스탬프가 없으면 그 뒤 서명 검증이 실패한다.
  • 실패하면 /debug를 추가해 인증·인증서 체인 메시지를 본다.
  • dlib 경로는 설치 버전에 따라 bin\x64\ 또는 bin\ 바로 아래일 수 있다. 폴더에서 Azure.CodeSigning.Dlib.dll 위치를 확인한다. 32비트 SignTool에는 x86 dlib를 쓴다.

서명 결과 확인:

signtool verify /pa /v .\package.msix
Get-AuthenticodeSignature .\package.msix | Format-List Status, SignerCertificate, TimeStamperCertificate

Status가 Valid이고 SignerCertificate의 Subject가 5단계 값과 같으면 된다. 이 PC에 자체 서명 테스트 인증서를 신뢰 등록한 적이 있어도 운영 서명 검증과는 무관하다.

8단계. Installer Studio에 반영

  1. 앱 정보 탭 패키지 identity → Publisher에 5단계에서 복사한 주체를 그대로 붙인다. 쉼표 뒤 공백까지 같아야 한다.
  2. Identity Name은 바꾸지 않는다. Publisher가 바뀌면 PackageFamilyName이 달라져 기존 테스트 설치본과는 다른 앱이 된다. 테스트용 자체 서명본을 설치한 PC에서는 먼저 제거한다.
  3. 현재 Installer Studio의 서명 모드는 unsigned와 development(자체 서명)만 있다. 운영 서명은 미서명 모드로 빌드한 뒤 7단계 명령을 수동으로 실행하는 방식으로 진행한다. 제작기 안에서 /dlib 호출을 지원하는 운영 서명 프로필은 백로그 BL-03 후속 작업이다.
  4. 서명본은 제작기의 releases/<id> 폴더를 덮어쓰지 말고 별도 출력 폴더에 두고, 서명 로그와 signtool verify 결과를 함께 보관한다.

자주 막히는 곳

증상 확인할 것
새 ID 버튼이 흐림 3단계 ID 검증 도구 역할이 없거나 구독 읽기 권한자가 없다
신원 확인 메일이 안 옴 기본 이메일이 외부 발신 링크를 받는지, 7일이 지나지 않았는지. 지났으면 새 요청
403 Forbidden / SignerSign() 실패 metadata.json의 Endpoint 지역이 계정 지역과 다르거나 서명자 역할이 없다
0x8007000B Publisher와 인증서 주체 불일치
dlib 로드 실패 SDK 기본 SignTool을 쓴 경우. 클라이언트 도구 폴더의 SignTool 사용
서명 3일 뒤 검증 실패 타임스탬프 없이 서명함. 다시 서명
설치 PC에서 "신뢰할 수 없는 게시자" Windows 10 1809 미만, 또는 루트 업데이트가 없는 격리 PC
요금이 나가는데 아직 못 씀 정상. 계정 생성일부터 과금되므로 신원 확인 서류를 먼저 모은 뒤 계정을 만든다

Key Vault + 공인 CA 방식 (대안)

아티팩트 서명을 쓸 수 없거나 특정 CA 인증서가 필요할 때의 방법이다. 비용은 CA 인증서 가격이 더해지고, 설정도 더 많다.

  1. **키 자격 증명 모음(Key Vault)**을 프리미엄(Premium) 가격 책정 계층으로 만들고 **개체 → 인증서(Certificates) → 생성/가져오기(Generate/Import)**에서 **인증서 발급 방법(Method of Certificate Creation)**을 "생성", **인증 기관 유형(Type of Certificate Authority)**을 "통합되지 않은 CA에서 발급한 인증서(Certificate issued by a non-integrated CA)"로 고른다. 고급 정책에서 키 종류 RSA-HSM, 키 크기 3072 이상, 내보내기 가능한 프라이빗 키는 아니오, 확장 키 사용(EKU)에 코드 서명 1.3.6.1.5.5.7.3.3을 넣는다.
  2. 생성된 인증서 항목에서 **인증서 작업(Certificate Operation) → CSR 다운로드(Download CSR)**로 요청 파일을 받아 CA(DigiCert, Sectigo, GlobalSign 등)에 OV 코드 서명 인증서로 신청한다. CA가 조직 확인을 한다. CA가 Azure Key Vault 키 증명을 받아 주는지 먼저 문의한다. 2023년 이후 규정으로 HSM 보관 증명이 필요하다.
  3. 발급된 인증서를 **서명된 요청 병합(Merge Signed Request)**으로 합친다.
  4. 서명 계정에 **액세스 제어(IAM)**에서 **Key Vault 암호화 사용자(Key Vault Crypto User)**와 Key Vault 인증서 사용자(Key Vault Certificate User) 역할을 준다.
  5. 서명 PC에 dotnet tool install --global AzureSignTool을 설치하고 서명한다.
azuresigntool sign --azure-key-vault-url https://<vault>.vault.azure.net `
  --azure-key-vault-certificate <인증서 이름> --azure-key-vault-managed-identity `
  --timestamp-rfc3161 http://timestamp.digicert.com --timestamp-digest sha256 --file-digest sha256 `
  .\package.msix

사람이 서명할 때는 --azure-key-vault-managed-identity 대신 az login 뒤 --azure-key-vault-tenant-id, --azure-key-vault-client-id, --azure-key-vault-client-secret(앱 등록) 조합을 쓴다. 6. 인증서 주체를 Publisher에 복사하는 8단계는 동일하다. 갱신 때 CA·회사 정보 표기를 바꾸지 않아야 주체가 유지된다.

근거