Hardened System Packages 사용하기
Hardened System Packages 사용하기
Docker가 소스에서 직접 빌드한 Hardened System Packages의 개념과, 이미지에 이를 추가하고 패키지 매니저를 구성하며, 서명·provenance를 검증하는 방법을 알아봐요.
출처: 문서
본문
Docker Hardened System Packages는 Docker가 소스에서 직접 빌드해요. 이는 잠재적으로 손상된 공개 패키지의 위험을 제거함으로써 전체 이미지 스택 전반의 공급망 무결성을 보장해요.
강화된 패키지에 대한 접근은 구독에 따라 달라져요.
- DHI Community: 베이스 이미지에 강화된 패키지를 포함. 자체 커스텀 이미지에서 동일한 패키지에 접근하려면 공개 패키지 저장소를 구성할 수 있음.
- DHI Select: 모든 Community 패키지에 더해 추가 컴플라이언스 전용 패키지(예: FIPS 변형)와 이미지 커스터마이즈 UI를 통한 Docker 패치 패키지에 대한 접근을 포함.
- DHI Enterprise: 모든 Select 패키지에 더해 자체 이미지에서 엔터프라이즈 패키지 저장소를 직접 구성해 컴플라이언스·보안 패치 패키지에 대한 전체 접근 권한을 얻을 수 있음.
Docker의 공개 강화 패키지 저장소에서 현재 사용 가능한 패키지를 탐색하려면 다음 인덱스를 봐요.
Docker는 계속 새 강화 패키지를 추가하고 있어요. 필요한 패키지가 아직 없다면 DHI 카탈로그 저장소에서 요청할 수 있어요.
내장 패키지
지원되는 Docker Hardened Images(DHI) 배포판은 강화된 시스템 패키지를 자동으로 포함해요. 추가 구성이 필요하지 않아요. 평소처럼 이미지를 풀·사용하기만 하면 돼요.
이 이미지의 모든 패키지는 Docker가 소스에서 빌드해, 베이스 이미지 자체와 동일한 보안 표준을 유지해요.
이미지에 강화된 패키지 추가
강화된 패키지를 자체 이미지에 추가하는 방법은 두 가지가 있어요.
이미지 커스터마이즈를 통해 패키지 추가
DHI Select 또는 DHI Enterprise로 Docker Hardened Images를 커스터마이즈할 때 커스터마이즈 인터페이스를 통해 Alpine 기반 이미지용 강화 패키지를 추가할 수 있어요. 이미지 커스터마이즈 만들기 단계를 따라 커스터마이즈 과정에서 강화 패키지를 선택해요.
패키지 매니저 구성
Docker의 강화 패키지 저장소에서 풀하도록 패키지 매니저를 구성할 수 있어요. 이렇게 하면 자체 이미지에 강화된 패키지를 설치할 수 있어요.
공개 저장소
자체 이미지에서 Docker의 공개 강화 패키지 저장소를 사용하려면 Dockerfile에서 DHI 서명 키를 설치하고 DHI 저장소를 추가하도록 패키지 매니저를 구성해요.
구성 프로세스는 세 단계로 진행돼요.
- 서명 키 설치
- 패키지 저장소 구성
- 패키지 업데이트 및 설치
Alpine
다음 예시는 Dockerfile에서 Alpine 패키지 매니저를 Docker의 공개 강화 패키지 저장소를 사용하도록 구성하는 방법을 보여줘요.
FROM alpine:3.23
# Install the signing key
RUN cd /etc/apk/keys && \
wget https://dhi.io/keyring/[email protected]
# Replace the default repositories with the hardened package repository
RUN echo "https://dhi.io/apk/alpine/v3.23/main" > /etc/apk/repositories
# Update and install packages
RUN apk update && \
apk add libpng
베이스 이미지 태그와 저장소 URL 둘 다에서 3.23을 Alpine 버전으로 바꿔요. 지원되는 버전에는 Alpine 3.23과 3.24가 포함돼요.
구성을 검증하려면 이미지를 빌드·실행해요.
$ docker build -t myapp:latest .
$ docker run -it myapp:latest sh
컨테이너 내부에서 구성된 저장소를 확인해요.
/ # cat /etc/apk/repositories
https://dhi.io/apk/alpine/v3.23/main
이렇게 하면 모든 패키지가 Docker의 강화 저장소에서 설치되도록 보장해요.
Debian
다음 예시는 Dockerfile에서 Debian 패키지 매니저를 Docker의 공개 강화 패키지 저장소를 사용하도록 구성하는 방법을 보여줘요.
FROM debian:trixie-slim
# Install the signing key
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates curl gnupg \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://dhi.io/keyring/dhi-deb-gpg.D46852F6925E9F71.key \
| gpg --dearmor -o /usr/share/keyrings/dhi-deb.gpg
# Add the hardened package repository
RUN echo "deb [signed-by=/usr/share/keyrings/dhi-deb.gpg] https://dhi.io/deb/debian/main trixie main" \
> /etc/apt/sources.list.d/dhi.list
# Update and install packages
RUN apt-get update && apt-get install -y jq \
&& rm -rf /var/lib/apt/lists/*
구성을 검증하려면 이미지를 빌드·실행해요.
$ docker build -t myapp:latest .
$ docker run -it myapp:latest bash
컨테이너 내부에서 구성된 저장소를 확인해요.
root@myapp:/# cat /etc/apt/sources.list.d/dhi.list
deb [signed-by=/usr/share/keyrings/dhi-deb.gpg] https://dhi.io/deb/debian/main trixie main
DHI 저장소에 패키지의 강화 버전이 있으면 apt가 업스트림 Debian 버전보다 자동으로 이를 우선시해요. apt-cache policy <package>로 확인할 수 있는데, https://dhi.io/deb/debian/main에서 +dhi 또는 dhi 버전 접미사가 있는 후보를 보여줘요.
모든 Debian 패키지가 강화 시스템 패키지로 제공되는 것은 아니에요. 패키지가 DHI 저장소에 없으면 apt가 베이스 이미지에 구성된 업스트림 Debian 미러로 투명하게 폴백해요.
Docker Hardened Images 저장소에서 설치된 모든 패키지는 Docker가 소스에서 빌드하며 완전한 provenance를 포함해요.
엔터프라이즈 저장소
DHI Enterprise가 있으면 FIPS 같은 컴플라이언스 변형의 강화 패키지와 추가 보안 패치를 포함하는 추가 패키지 저장소에 접근할 수 있어요.
구성 프로세스는 다섯 단계로 진행돼요.
- 서명 키 설치
- 베이스 패키지 저장소 구성
- 엔터프라이즈 보안 저장소 추가
- 인증과 함께 패키지 설치 구성
- DHI CLI를 사용해 자격 증명을 시크릿으로 전달하며 이미지 빌드
Alpine
다음 예시는 Dockerfile에서 Alpine 패키지 매니저를 Docker의 엔터프라이즈 강화 패키지 저장소를 사용하도록 구성하는 방법을 보여줘요.
FROM alpine:3.23
# Install the signing key
RUN cd /etc/apk/keys && \
wget https://dhi.io/keyring/[email protected]
# Replace the default repositories with the hardened package repository
RUN echo "https://dhi.io/apk/alpine/v3.23/main" > /etc/apk/repositories
# Update and install the enterprise configuration package to add the security repository
RUN apk update && \
apk add dhi-enterprise-conf
# Install packages from the security repository with authentication
RUN --mount=type=secret,id=http_auth \
HTTP_AUTH="$(cat /run/secrets/http_auth)" \
apk update && \
apk add openssl-fips
인증을 빌드 시크릿으로 안전하게 전달하며 이미지를 빌드해요.
$ docker dhi auth apk > http_auth.txt
$ docker build --secret id=http_auth,src=http_auth.txt -t myapp-enterprise:latest .
$ rm http_auth.txt
--secret 플래그는 빌드 중 인증 자격 증명을 이미지 레이어나 메타데이터에 저장하지 않고 안전하게 마운트해요.
Debian
다음 예시는 Dockerfile에서 Debian 패키지 매니저를 Docker의 엔터프라이즈 강화 패키지 저장소를 사용하도록 구성하는 방법을 보여줘요. 자격 증명을 /etc/apt/auth.conf.d/dhi.conf에 마운트해요. apt는 모드가 0600일 때 /etc/apt/auth.conf.d/의 파일을 자동으로 읽어요.
FROM debian:trixie-slim
# Install the signing keys
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates curl gnupg \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://dhi.io/keyring/dhi-deb-gpg.D46852F6925E9F71.key \
| gpg --dearmor -o /usr/share/keyrings/dhi-deb.gpg
RUN curl -fsSL https://dhi.io/keyring/dhi-deb-sec-gpg.D46852F6925E9F71.key \
| gpg --dearmor -o /usr/share/keyrings/dhi-deb-sec.gpg
# Add the hardened package repository and the enterprise security repository
RUN echo "deb [signed-by=/usr/share/keyrings/dhi-deb.gpg] https://dhi.io/deb/debian/main trixie main" \
> /etc/apt/sources.list.d/dhi.list
RUN echo "deb [signed-by=/usr/share/keyrings/dhi-deb-sec.gpg] https://dhi.io/deb/debian/security trixie main" \
> /etc/apt/sources.list.d/dhi-sec.list
# Install packages from the security repository with authentication
RUN --mount=type=secret,id=netrc,target=/etc/apt/auth.conf.d/dhi.conf,mode=0600 \
apt-get update && apt-get install -y openssl \
&& rm -rf /var/lib/apt/lists/*
환경 변수를 통해 자격 증명을 빌드 시크릿으로 안전하게 전달하며 이미지를 빌드해요.
$ NETRC=$(docker dhi auth deb) docker build \
--secret id=netrc,env=NETRC \
-t myapp-enterprise:latest .
--secret id=netrc,env=NETRC 형식은 빌드 중 인증 자격 증명을 이미지 레이어나 메타데이터에 저장하지 않고 안전하게 마운트해요.
패키지 검증
모든 강화 패키지는 암호화 서명되며 provenance와 빌드 무결성을 증명하는 메타데이터를 포함해요. 서명을 검증하고 메타데이터를 확인해 패키지가 Docker의 신뢰할 수 있는 빌드 인프라에서 왔음을 보장할 수 있어요.
패키지 메타데이터 보기
강화 패키지에 대한 정보를 보려면:
Alpine
$ apk info -L <package-name>
Debian
$ dpkg -L <package-name>
이 명령은 패키지에 포함된 파일과 그 메타데이터를 보여줘요.
패키지 서명 검증
강화 패키지는 Docker가 암호화 서명해요. 이전에 설명한 대로 서명 키를 설치하고 패키지 매니저를 구성하면, 패키지 매니저가 설치 중 서명을 자동으로 검증해요.
패키지가 서명 검증에 실패하면 패키지 매니저가 설치를 거부해, 변조되거나 손상된 패키지로부터 보호해줘요.
빌드 provenance와 암호화 검증
Docker 강화 패키지는 Docker의 신뢰할 수 있는 인프라로 빌드되며 검증 가능한 메타데이터와 암호화 서명을 포함해요.
설치된 패키지의 이 메타데이터를 보려면:
Alpine
$ apk info -a <package-name>
Debian
$ apt-cache show <package-name>
또는 설치 전 패키지 메타데이터를 보려면:
Alpine
$ apk fetch --stdout <package-name> | tar -xzO .PKGINFO
Debian
$ apt-get download <package-name>
$ dpkg-deb -I <package-name>_*.deb
패키지 서명 키는 패키지가 빌드된 후 변조되지 않았음을 보장해요. 서명 키를 설치하고 패키지 매니저를 구성하면 모든 패키지가 설치 전에 자동으로 검증돼요.
패키지 attestation
각 강화 패키지는 이미지 attestation과 유사한 자체 attestation을 포함해요. 이 attestation은 개별 패키지의 provenance와 빌드 정보를 제공해, 공급망을 패키지 수준까지 추적할 수 있게 해줘요.
먼저 이미지의 SLSA provenance에서 패키지 정보를 추출한 다음, 패키지 digest로 그 attestation에 접근해 패키지 attestation을 가져올 수 있어요.
이미지 attestation에서 패키지 정보 추출
이미지의 SLSA provenance attestation에서 특정 패키지의 provenance 정보를 얻으려면 먼저 이미지의 provenance를 가져온 다음 관심 있는 특정 패키지로 필터링해야 해요.
SLSA provenance attestation에는 패키지를 포함한 모든 빌드 입력을 나열하는 materials 배열이 포함돼요. jq로 이 배열을 특정 패키지로 필터링할 수 있어요.
$ docker scout attest get dhi.io/golang:1.26-alpine3.23 \
--predicate-type https://slsa.dev/provenance/v0.2 | \
jq '.predicate.materials[] | select( .uri == "https://dhi.io/apk/alpine/v3.23/main/aarch64/golang-1.26-1.26.0-r0.apk" )'
select() 필터의 패키지 URI를 찾는 특정 패키지로 바꿔요. 먼저 select() 필터 없이 명령을 실행해 모든 materials를 확인하면 사용 가능한 패키지를 찾을 수 있어요.
이 명령은 패키지 URI와 SHA-256 digest를 반환해요.
{
"uri": "https://dhi.io/apk/alpine/v3.23/main/aarch64/golang-1.26-1.26.0-r0.apk",
"digest": {
"sha256": "4082a2500abc2e7b8435f9398d3514d760044fa52ca3d10cf80015469124a838"
}
}
패키지의 attestation 나열
이전 섹션의 패키지 digest를 사용해 해당 패키지의 모든 사용 가능한 attestation을 나열할 수 있어요.
$ curl -s https://dhi.io/apk/alpine/v3.23/main/sha256:4082a2500abc2e7b8435f9398d3514d760044fa52ca3d10cf80015469124a838/attestations/list | jq .
이 명령은 패키지와 사용 가능한 attestation에 대한 정보를 반환해요.
{
"subject": {
"name": "pkg:apk/alpine/[email protected]?os_name=&os_version=",
"digest": {
"sha256": "4082a2500abc2e7b8435f9398d3514d760044fa52ca3d10cf80015469124a838"
}
},
"attestations": [
{
"predicate_type": "https://slsa.dev/provenance/v1",
"digest": {
"sha256": "97c919cf0edb27087739bbabeea4c1ef88d069cd41791476ba64b69280d63a32"
},
"url": "https://dhi.io/apk/alpine/v3.23/main/sha256:4082a2500abc2e7b8435f9398d3514d760044fa52ca3d10cf80015469124a838/attestations/sha256:97c919cf0edb27087739bbabeea4c1ef88d069cd41791476ba64b69280d63a32"
}
]
}
패키지 attestation 가져오기
실제 attestation 내용을 가져오려면 attestation 목록에 제공된 URL을 사용해요.
$ curl -s https://dhi.io/apk/alpine/v3.23/main/sha256:4082a2500abc2e7b8435f9398d3514d760044fa52ca3d10cf80015469124a838/attestations/sha256:97c919cf0edb27087739bbabeea4c1ef88d069cd41791476ba64b69280d63a32 | jq .
이 명령은 패키지의 전체 SLSA provenance attestation을 반환하며, 패키지가 어떻게 빌드되었는지, 그 의존성, 기타 빌드 재료에 대한 정보를 포함해요.
이 프로세스를 재귀적으로 계속해 패키지를 만드는 데 사용된 컴파일러와 기타 빌드 도구까지 공급망을 끝까지 추적할 수 있어요.