GitLab CI/CD에서 SSH 키 사용하기

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

GitLab은 현재 빌드 환경(즉, GitLab Runner가 실행되는 곳)에서 SSH 키를 관리하는 기본 지원을 제공하지 않습니다.

SSH 키를 사용하는 경우:

  • 내부 서브모듈을 체크아웃합니다.
  • 패키지 관리자를 사용하여 비공개 패키지를 다운로드합니다. 예: Bundler.
  • 응용 프로그램을 자체 서버 또는 예를 들어 Heroku에 배포합니다.
  • 빌드 환경에서 원격 서버로 SSH 명령을 실행합니다.
  • 빌드 환경에서 파일을 원격 서버로 Rsync합니다.

위의 사항 중 어느 것이라도 해당된다면, 아마도 SSH 키가 필요할 것입니다.

가장 널리 지원되는 방법은 .gitlab-ci.yml을 확장하여 빌드 환경에 SSH 키를 삽입하는 것이며, 이 방법은 Docker 또는 쉘과 같은 executor와 함께 작동합니다.

SSH 키 생성 및 사용

GitLab CI/CD에서 SSH 키를 생성하고 사용하려면 다음을 수행합니다:

  1. ssh-keygen을 사용하여 로컬에서 새 SSH 키 쌍을 생성합니다.
  2. 프로젝트에 대한 파일 형식 CI/CD 변수로서의 비공개 키를 추가합니다. 변수 값은 새 줄(LF 문자)로 끝나야 합니다. 줄을 추가하려면 SSH 키의 마지막 줄 뒤에 Enter 또는 Return을 누릅니다.
  3. 작업에서 ssh-agent를 실행하여 비공개 키를 로드합니다.
  4. 원하는 서버에 공개 키를 복사합니다(일반적으로 ~/.ssh/authorized_keys에 위치) 또는 배포 키로 추가합니다(비공개 GitLab 리포지터리에 액세스하는 경우).

Docker executor를 사용할 때 SSH 키

CI/CD 작업이 Docker 컨테이너 내에서 실행되고 비공개 서버에 코드를 배포해야 하는 경우 SSH 키 쌍을 사용해야 합니다.

  1. 먼저 SSH 키 쌍을 생성해야 합니다. 자세한 내용은 SSH 키 생성 안내를 따릅니다. SSH 키에 암호를 추가하지 마세요, 그렇지 않으면 before_script에서 이를 요청합니다.
  2. 파일 형식 CI/CD 변수를 생성합니다.
    • Key 필드에 SSH_PRIVATE_KEY를 입력합니다.
    • Value 필드에 이전에 생성한 키 쌍의 비공개 키 내용을 붙여넣습니다. 파일은 새 줄로 끝나야 합니다. 줄을 추가하려면 변경 사항을 저장하기 전에 SSH 키의 마지막 줄 뒤에 Enter 또는 Return을 누릅니다.
  3. .gitlab-ci.ymlbefore_script 작업으로 수정합니다. 아래 예에서는 Debian 기반 이미지를 가정했습니다. 필요에 맞게 편집합니다:

    before_script:
      ##
      ## apt-get을 사용하는 경우, ssh-agent가 이미 설치되어 있지 않다면 설치합니다.
      ##
      - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
         
      ##
      ## ssh-agent를 실행합니다(빌드 환경 내).
      ##
      - eval $(ssh-agent -s)
         
      ##
      ## 올바른 권한을 부여합니다. 그렇지 않으면 ssh-add가 파일을 추가하지 않습니다.
      ## CI/CD에 저장된 SSH_PRIVATE_KEY 파일 형식 CI/CD 변수에 SSH 키를 에이전트 리포지터리에 추가합니다.
      ##
      - chmod 400 "$SSH_PRIVATE_KEY"
      - ssh-add "$SSH_PRIVATE_KEY"
         
      ##
      ## SSH 디렉터리를 만들고 올바른 권한을 부여합니다.
      ##
      - mkdir -p ~/.ssh
      - chmod 700 ~/.ssh
         
      ##
      ## Git 명령을 사용할 경우 사용자 이름과 이메일을 설정합니다(선택 사항).
      ##
      # - git config --global user.email "user@example.com"
      # - git config --global user.name "User name"
    

    before_script는 기본값 또는 작업별로 설정할 수 있습니다.

  4. 비공개 서버의 SSH 호스트 키가 확인된지 확인합니다.
  5. 마지막 단계로, 처음에 생성한 공개 키를 빌드 환경 내부에서 액세스하려는 서비스에 추가합니다. 비공개 GitLab 리포지터리에 액세스하는 경우, 배포 키로 추가해야 합니다.

Shell executor를 사용할 때 SSH 키

Shell executor를 사용하고 있다면 Docker가 아니라 SSH 키를 설정하는 것이 더 쉽습니다.

GitLab Runner가 설치된 서버에서 SSH 키를 생성하고, 이 키를 이 서버에서 실행되는 모든 프로젝트에 사용합니다.

  1. 먼저 작업을 실행하는 서버에 로그인합니다.
  2. 그런 다음 터미널에서 gitlab-runner 사용자로 로그인합니다:

    sudo su - gitlab-runner
    
  3. SSH 키 생성 안내에 설명된대로 SSH 키 쌍을 생성합니다. SSH 키에 암호를 추가하지 마세요, 그렇지 않으면 before_script에서 이를 요청합니다.
  4. 생성한 키의 공개 키를 이전에 만든 서비스에 추가하여 빌드 환경 내부에서 액세스하려는 서비스에 추가합니다. 비공개 GitLab 리포지터리에 액세스하는 경우, 배포 키로 추가해야 합니다.

키를 생성한 후, 원격 서버에 로그인하여 지문을 수락합니다:

ssh example.com

GitLab.com의 리포지터리에 액세스하려면 git@gitlab.com을 사용합니다.

SSH 호스트 키 확인

개인 서버의 공개 키를 확인하여 중간자 공격을 방지하는 좋은 습관입니다. 의심스러운 일이 발생하면 작업이 실패합니다(공개 키가 일치하지 않을 때 SSH 연결이 실패하기 때문에 발견됩니다).

서버의 호스트 키를 확인하려면 신뢰할 수 있는 네트워크(이상적으로는 개인 서버 자체)에서 ssh-keyscan 명령을 실행하세요:

## 도메인 네임 사용
ssh-keyscan example.com

## 또는 IP 사용
ssh-keyscan 10.0.2.2

SSH_KNOWN_HOSTS를 “키”로 하고 ssh-keyscan의 출력을 “값”으로 하는 파일 형식 CI/CD 변수를 생성하세요. 파일의 끝이 줄바꿈으로 끝나도록 해야 합니다. 줄바꿈을 추가하려면 SSH 키의 마지막 줄 다음에 Enter 또는 Return을 누르세요.

여러 서버에 연결해야 하는 경우 에 모든 서버 호스트 키를 한 줄에 하나씩 모아야 합니다.

note
.gitlab-ci.yml 내에서 ssh-keyscan 대신에 파일 형식 CI/CD 변수를 사용하면, 호스트 도메인 이름이 어떤 이유로든 변경되더라도 .gitlab-ci.yml을 변경할 필요가 없습니다. 또한, 값은 사용자가 미리 정의하므로 호스트 키가 갑자기 변경되더라도 CI/CD 작업이 실패하지 않으므로 서버나 네트워크에 문제가 있는 것을 알 수 있습니다.

SSH_KNOWN_HOSTS 변수를 생성했다면, .gitlab-ci.yml의 내용에 추가로 다음을 추가해야 합니다:

before_script:
  ##
  ## SSH_KNOWN_HOSTS 파일 형식 CI/CD 변수를 생성했다고 가정하며, 다음 두 줄을 주석 해제하세요.
  ##
  - cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts
  
  ##
  ## 또 다른 방법으로, 개인 서버의 키를 스캔하기 위해 ssh-keyscan을 사용할 수 있습니다.
  ## example.com을 자신의 개인 서버 도메인 이름으로 바꿔주고, 연결해야 하는 서버가 여러 개인 경우 해당 명령을 반복하세요.
  ##
  # - ssh-keyscan example.com >> ~/.ssh/known_hosts
  # - chmod 644 ~/.ssh/known_hosts
  
  ##
  ## 선택적으로 호스트 키 확인을 비활성화할 수 있습니다. 이를 추가하면 중간자 공격에 노출될 수 있음을 주의하세요.
  ## 경고: Docker 실행기와 함께 사용하려면 이것만 사용하고, shell과 함께 사용하면 사용자의 SSH 구성이 덮어쓰여집니다.
  ##
  # - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'

파일 형식 CI/CD 변수를 사용하지 않는 SSH 키 사용

만일 파일 형식 CI/CD 변수를 사용하고 싶지 않다면, 예시 SSH 프로젝트에서 다른 방법을 확인할 수 있습니다. 이 방법은 파일 형식 변수 대신에 일반 CI/CD 변수를 사용합니다.

문제 해결

Error loading key "/builds/path/SSH_PRIVATE_KEY": error in libcrypto 메시지

이 메시지는 SSH 키의 형식 오류가 있는 경우 반환될 수 있습니다.

파일 형식 CI/CD 변수로 SSH 키를 저장할 때, 값은 반드시 줄바꿈(LF 문자)으로 끝나야 합니다. 변수를 저장하기 전에 SSH 키의 -----END OPENSSH PRIVATE KEY----- 줄 끝에 Enter 또는 Return을 눌러야 합니다.