본문 바로가기

iOS+

인증서와 프로파일

개요

일반적으로 프로젝트에서 Automatically manage signing(자동 서명 관리)을 이용한다면, 서명 및 프로파일에 큰 신경을 안 써도 된다

 

하지만 Github action 같은 CI/CD 파이프라인을 직접 작성하는 경우, 작업이 돌아가는 머신에서 프로젝트를 빌드하다 보면 자동 서명 관리는 올바르게 동작하지 않는 경우가 있었다

 

자동 서명 관리를 안하고 직접 관리하는 방식으로 스크립트를 작성하다 보니, 서명 및 프로파일에 대해 좀 더 자세히 알아야겠단 생각을 하게 되었고, 이 글을 통해 이를 정리하고자 한다

 

해당 내용들에 대해 정리 이후, 서명은 Keychain에 등록하고, 프로파일은 Xcode가 기본적으로 참고하는 위치에 추가하는 스크립트를 마지막으로 글을 마무리한다

 

  • CSR(Certificate Signing Request)
  • Certificates, Identifiers & Profiles
  • Certificate과 Profile 등록

 

CSR(Certificate Signing Request)

CSR(Certificate Signing Request)은 Apple에서 개발자 인증서(.cer)를 발급받기 위해 필요한 파일이다

Apple은 개발자가 진짜 본인인지 확인하고, 인증서를 특정 Mac과 연결하기 위해 CSR을 요구하는다

 

  • CSR 파일을 만들면 Mac의 Keychain Access에 개인 키(Private Key)가 생성된다
  • CSR 파일에는 개발자의 공개 키(Public Key)와 신원 정보가 들어 있다
  • Apple은 CSR에 포함된 공개 키(Public Key)를 사용하여 개발자 전용 인증서를 만든다

 

그렇다면 이렇게 얻은 인증서는 CSR을 만든 Mac 말고는 사용할 수 없는가? 아니다

 

인증서 파일에 개인키를 같이 하나의 파일로 패키징하여 내보내면 된다

이 패키징은 .p12 파일이며, 다른 Mac에서도 이 파일을 가져오면, 인증서를 사용할 수 있다

단, 보안을 위해 .p12 파일을 생성할 때 비밀번호를 설정하고, 다른 Mac에서 가져올 때 이 비밀번호가 필요하다

 

.cer 파일을 export 시, 다음과 같이 비밀번호 입력을 요구한다

 

Certificates, Identifiers & Profiles

인증서는 실제로 앱 파일에 디지털 서명을 추가하여 무결성을 보장하고,

프로파일은 그 서명이 어떤 환경에서 유효한지 관리하는 설정 파일이다

 

이런 관계를 알고 보면, 각 구성 항목들이 비슷하지만 굳이 서명과 프로파일로 나뉜 이유를 이해하는 데 도움이 될 것이다

 

Certificates(인증서)

Certificates(인증서)는 개발자가 Apple의 보안 체계를 따르는 신뢰할 수 있는 개발자임을 인증하는 역할을 한다

아래 내용에서 알맞은 내용을 선택하고, CSR을 업로드하여 인증서(.cer)를 얻을 수 있다

 

https://developer.apple.com/account/resources/certificates/add

인증서 종류

개발용 인증서는 개발 중인 앱을 실제 기기에서 테스트할 때 필요하며, Xcode에서 개발자 계정을 추가하면 자동으로 생성된다

배포용 인증서는 App Store 내 또는 외부에서 실제로 앱 배포를 위해 사용된다

 

  • 개발용 인증서 (Development Certificate)
    • iOS Development
    • macOS Development…
  • 배포용 인증서 (Distribution Certificate)
    • App Store Distribution
    • Ad-Hoc Distribution
    • Enterprise Distribution
    • Developer ID Installer...
    • Developer ID Application
      • 사용자가 앱을 설치할 때 macOS의 Gatekeeper가 "확인된 개발자의 앱"으로 인식할 수 있도록 해준다

서비스

해당 인증서가 사용할 수 있는 특정 기능(서비스) 의미한다

만약 앱이 특정 Apple 서비스(예: 푸시 알림, Apple Pay 등)를 활용하려면, 해당 서비스에 맞는 인증서를 발급받아야 한다

만약 앱에서 해당 서비스를 이용한다면, .entitlements에 관련 항목을 추가해야 한다

Identifiers(식별자)

Apple의 Identifiers(식별자)는 앱, 서비스, 기기 등을 고유하게 식별하는 값이다

앱을 개발하고 특정 Apple 기능(푸시 알림, iCloud, Game Center 등)을 사용하려면, 올바른 식별자를 생성 및 설정해야 한다

App ID와 Bundle ID

App ID는 앱이 사용하는 특정 서비스들을 설정하는 데 사용되고, Bundle ID는 앱의 고유성을 보장하는 역할이다

App ID 형식은 Team ID+Bundle ID

  • App ID는 Apple Developer 계정에서 설정하는 고유 식별자로, 앱을 Apple 생태계에서 고유하게 구별하는 값 → Apple 시스템(푸시 알림, iCloud 등)에서 앱을 고유하게 식별하고, 해당 기능을 사용할 수 있게 허용
  • Bundle ID는 Xcode에서 각각의 앱을 고유하게 식별하는 값, Info.plist 파일에 설정 → 실제 앱이 설치되는 기기나 시스템에서 앱을 구별하는 데 사용

Services ID

서비스 기능을 활용하려면 해당 기능에 맞는 서비스 식별자를 생성하여, 앱이 Apple의 해당 기능을 정확히 활용할 수 있도록 한다

Profiles(프로파일)

Profiles(프로파일)은 앱을 실행하고 배포하는 데 필요한 설정 파일로, 앱이 특정 환경에서 정상적으로 작동하도록 돕는 역할을 한다

 

https://developer.apple.com/account/resources/profiles/add

프로파일 종류

서명과 마찬가지로 개발용 프로파일배포용 프로파일로 나뉘어서 존재한다

 

  • 개발용 프로파일(Development Profile)
    • iOS Development
    • macOS Development…
  • 배포용 프로파일(Distribution Profile)
    • App Store Distribution
    • Ad-Hoc Distribution
    • Enterprise Distribution
    • Developer ID Installer
    • Developer ID Application...

 

Certificate과 Profile 등록

다음과 같은 작업들을 수행하면, Github action을 통해 작업이 수행되는 머신에 개발자 서명과 프로파일을 등록하여 이용할 수 있다

 

1. 인증서 발급(with CSR)

2. Keychain에 인증서 등록 후, 추출 → .p12

3. 프로파일 발급

4. 인증서(.p12)와 프로파일(.provision)Base64 인코딩 → Github repo secrets에 등록(인증서 추출 시, 등록한 비밀번호도 같이 등록)

5. 작업 머신에 서명과 프로파일 등록(<- secrets을 Base64 디코딩)

 

인증서 및 프로파일 발급은 위에서 언급했고, 인코딩과 등록과정은 다음과 같다

Base64 인코딩

내용을 문자열로 담아 Github repo에 비밀 변수로 등록하는데, 오류가 없게 하기위해 인코딩을 진행해야 한다

사용 시, 다시 디코딩을 통해 원래 데이터를 얻을 수 있다

로컬에서 인증서와 프로파일은 다음과 같이 base64 명령어를 통해 인코딩한다

 

base64 -i [INPUT_FILE] -o [OUTPUT_FILE]

인증서와 프로파일 등록

우선, Github repo에 secrets를 통해 등록한 값을 얻고, 이를 다시 디코딩한다

 

머신에 인증서를 등록하려면, 임시적으로 현재 머신에 Keychain을 만들어야 하고, 비밀번호 설정도 필요하다

그리고 인증서를 Keychain에 등록할 때는 인증서를 내보낼 때 만든 비밀번호를 사용한다

 

프로파일은 Xcode 빌드 시, 참조되는 기본 위치에 복사하여 이들을 사용할 준비를 마친다(~/Library/MobileDevice/Provisioning\ Profiles/)

 

.....
- name: Install Apple certificate and provisioning profile
  env:
    BUILD_CERTIFICATE_BASE64: ${{ secrets.CERTIFICATE_BASE64 }}
    P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
    BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.PROVISIONING_PROFILE_BASE64 }}
    WIDGET_PROVISION_PROFILE_BASE64: ${{ secrets.WIDGET_PROVISIONING_PROFILE_BASE64 }}
    KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
  run: |
    # Create variables
    CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
    PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
    WIDGET_PP_PATH=$RUNNER_TEMP/widget_pp.mobileprovision
    KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db

    # Import certificate and provisioning profile
    echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
    echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
    echo -n "$WIDGET_PROVISION_PROFILE_BASE64" | base64 --decode -o $WIDGET_PP_PATH

    # Create temporary keychain
    security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
    security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
    security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH

    # Import certificate to keychain
    security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
    security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
    security list-keychain -d user -s $KEYCHAIN_PATH

    # Apply provisioning profile
    mkdir -p ~/Library/MobileDevice/Provisioning\\ Profiles
    cp $PP_PATH ~/Library/MobileDevice/Provisioning\\ Profiles/
    cp $WIDGET_PP_PATH ~/Library/MobileDevice/Provisioning\\ Profiles/

 

CSR을 사용하지 않은 Mac이라도, 위와같이 Keychain에 .p12 파일을 등록하여 인증서를 사용할 수 있다

 

마무리

그동안 자동 서명 기능을 사용하면서 인증서나 프로파일에 대한 개념을 깊이 이해하지 못했지만, 직접 파이프라인을 구성하면서 그 중요성을 깨닫게 되었다

'iOS+' 카테고리의 다른 글

Share Extension  (0) 2025.03.16
On-Device AI with CoreML(feat. DeepSeek-R1)  (0) 2025.02.09
#Preview를 위한 환경 구분 방법  (2) 2024.12.29
Xcode Cloud와 Sparkle framework  (2) 2024.09.29
Objective-C  (2) 2024.09.22