반응형
Private Docker Registry 구축 및 보안 강화
사설 Docker Registry를 구축하고, 보안성을 강화하여 안전한 이미지 저장소를 운영할 수 있도록 한다.
과제 설명
기업 내부에서 사용하는 Docker 이미지를 안전하게 관리하기 위해 Docker Private Registry를 구축하고, TLS(SSL) 인증 및 접근 제어를 적용하여 보안성을 높이는 실습을 진행한다.
활용 툴
- Docker, Docker Compose
- OpenSSL
- htpasswd
- GitLab CI/CD
1. Docker Private Registry 기본 구축*
- registry:2 공식 이미지를 활용하여 로컬 Private Registry 컨테이너 실행
- 볼륨 설정 : 이후에 설정을 변경하는 과정에서 여러번 Registry를 내리고 다시 올리기 때문에 볼륨 설정하여, Docker 레지스트리의 저장소 데이터를 영구적으로 유지
# Registry 데이터를 저장할 디렉터리 생성
mkdir -p ~/docker-registry/data
# Registry 컨테이너 실행
docker run -d \
--name registry \
-p 5000:5000 \
-v ~/docker-registry/data:/var/lib/registry \
--restart=always \
registry:2
insecure-registries
설정 (daemon.json
수정)- Docker Daemon (자체 서명된 인증서를 사용하는 레지스트리 추가 설정)
sudo vi /etc/docker/daemon.json
# 아래처럼 변경
{
"insecure-registries": ["192.168.1.8:5000"]
}
sudo systemctl restart docker
- docker tag 및 docker push 명령어를 사용하여 이미지를 Private Registry에 업로드
- 예시로 'BusyBox' 이미지 사용
- (BusyBox는 리눅스 유틸리티를 하나의 실행 파일로 제공하는 경량화된 소프트웨어)
# BusyBox 이미지 다운로드
docker pull busybox
# 태그 변경 (Private Registry용)
docker tag busybox localhost:5000/busybox
# Private Registry로 Push
docker push localhost:5000/busybox
- docker pull을 통해 저장된 이미지 정상 다운로드 확인
# 이미지를 로컬에서 삭제해도 Registry에 저장된 이미지를 다시 받을 수 있는지 pull 체크
docker rmi busybox
docker pull localhost:5000/busybox
2. Registry 보안 설정 (TLS/SSL 인증 적용)
- OpenSSL을 사용하여 자체 서명된 SSL 인증서 생성
- 참고 : 실습이기 때문에 localhost로 설정해놓았지만, 실제 환경에서는 FQDN을 사용하는 것이 좋다.
- FQDN : 완전한 도메인 이름
mkdir -p ~/docker-registry/certs
cd ~/docker-registry/certs
# 자체 서명된 SSL 인증서 생성
openssl req -newkey rsa:4096 -nodes -sha256 -keyout registry.key -x509 -days 365 -out registry.crt \
-subj "/C=KR/ST=Seoul/L=Seoul/O=MyCompany/OU=IT Department/CN=localhost"
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DockerTest
Organizational Unit Name (eg, section) []:IT Department
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:test@email.com
- 4096비트 RSA 개인키와 해당 키로 서명된, 1년(365일) 동안 유효한 자체 서명된 인증서를 각각 지정된 파일에 저장
- 생성된 인증서 확인하기
# 생성된 인증서 확인
ls -l
- 생성한 인증서를 Registry에 적용하여 HTTPS 기반 통신 구성
- Docker Private Registry를 TLS(SSL) 인증서를 사용하여 보안된 상태로 실행
- 실행 중인 registry 컨테이너를 중지 → SSL 포함[HTTPS]으로 다시 실행
docker stop registry
docker rm registry
docker run -d \
--name registry \
-p 5000:5000 \
-v ~/docker-registry/data:/var/lib/registry \
-v ~/docker-registry/certs:/certs \
-e REGISTRY_HTTP_TLS_ADDR=0.0.0.0:5000 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
--restart=always \
registry:2
- curl을 활용하여 TLS 적용 여부 확인
curl -k https://localhost:5000/v2/_catalog
3. 기본 인증(Basic Authentication) 설정
- htpasswd를 사용하여 사용자 계정을 생성하고 인증 적용
sudo apt install apache2-utils -y
# 사용자 계정 생성 (예: admin)
mkdir -p ~/docker-registry/auth
htpasswd -Bc ~/docker-registry/auth/htpasswd admin
- Registry 컨테이너에 기본 인증 적용
docker stop registry
docker rm registry
docker run -d \
--name registry \
-p 5000:5000 \
-v ~/docker-registry/data:/var/lib/registry \
-v ~/docker-registry/certs:/certs \
-v ~/docker-registry/auth:/auth \
-e REGISTRY_HTTP_TLS_ADDR=0.0.0.0:5000 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
--restart=always \
registry:2
-e REGISTRY_AUTH=htpasswd
: 방식으로 사용자 인증 적용-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm
: 로그인 창에 표시되는 인증 영역의 이름-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
: htpasswd 파일 경로 지정
- docker login 명령어를 활용하여 인증 확인
docker logout localhost:5000
docker login localhost:5000
- 인증 없이 접근 시 차단되는지 테스트
- 인증없이 접근시 "UNAUTHORIZED"가 뜬다.
4. Docker 이미지 서명 및 무결성 검증
Docker Content Trust (DCT) 활성화 및 서명된 이미지 푸시
- DCT 개념 참고
- DCT는 Notary를 사용하여 서명을 관리한다.
- Notary Server 관련 Trouble Shooting
- 계속해서 인증서 오류 발생 (TLS 인증서 만료)
- TLS 인증서가 2023년 4월에 만료되어, 2025년 현재 시점에 접속할 때 인증서 검증에 실패
- 계속해서 인증서 오류 발생 (TLS 인증서 만료)
- 방법 1)
/fixtures/regenerateTestingCerts.sh
스크립트를 실행- https://github.com/notaryproject/notary/issues/1698
- https://github.com/notaryproject/notary/issues/1701
- Go, CFSSL, CFSSLJSON 설치 후에 "/fixtures/regenerateTestingCerts.sh 스크립트를 실행하여 인증서를 재생성했지만
- → 실패
- 방법 2) 수동으로 openssl 명령어를 이용해 새로운 인증서를 생성
- 방법 3) [테스트용] 강제로 클라이언트 시간을 일시적으로 과거로 돌리기
jinho@ubuntu:~/docker-registry$ # NTP 서비스 중지
sudo systemctl stop systemd-timesyncd
# 특정 시간까지 설정하고 싶다면
sudo date -s "2022-03-01 12:00:00"
2022. 03. 01. (화) 12:00:00 UTC
jinho@ubuntu:~/docker-registry$ date
2022. 03. 01. (화) 12:00:01 UTC
- → 실패
- 결론) 지금 인증서에 문제가 있는 것 같음
Hi all, Doug Singer here -- DevSecOps Engineer for Modern Technology Solutions, INC.
In the process of doing some R&D for our dept, I was investigating this project. Ran into the x509 expiration issue and found this thread. Looks like this PR may resolve the issue we're having, so I will keep an eye on it. Thank you, all.
- Private Registry를 사용할 경우 별도의 Notary 서버를 실행
cat << EOF > docker-compose.yml
version: '2'
services:
notary-server:
image: theupdateframework/notary-server:latest
ports:
- "4443:4443"
environment:
- NOTARY_SERVER_STORAGE_BACKEND=memory
restart: always
notary-signer:
image: theupdateframework/notary-signer:latest
environment:
- NOTARY_SIGNER_STORAGE_BACKEND=memory
restart: always
EOF
cat << EOF > config.yml
version: 0.1
storage:
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :4443
headers:
X-Content-Type-Options: [nosniff]
auth:
token:
realm: "https://auth.docker.io/token"
service: "registry.docker.io"
issuer: "auth.docker.io"
rootcertbundle: /root/certs/auth.cert
EOF
- alpine 이미지를 사용해서 DCT를 활성화하고 서명된 이미지를 푸시
- 서명되지 않은 이미지 업로드 시도 및 차단 여부 확인
- 실패
반응형