Remote API 적용을 위한 SSL 인증서 적용

Posted by

docker 는 API 를 이용하여 외부에서 접속 할 수 있는 기능이 있다.

하지만 그냥 API를 이용하기에는 보안 위험성이 너무 크기 때문에 SSL 인증서를 적용하여 이용 하는 방법을 알아보도록 하자.

이글은 아래 사이트를 참고하여 작성 되었다.

https://docs.docker.com/engine/security/https/

docker 서버에 접속하여 docker 명령으로 tls 인증을 통한 옵션을 한번 살펴보도록 하자

root@docker-02:~# docker
 Usage:  docker [OPTIONS] COMMAND
 A self-sufficient runtime for containers
 Options:
       --config string      Location of client config files (default "/root/snap/docker/384/.docker")
   -D, --debug              Enable debug mode
   -H, --host list          Daemon socket(s) to connect to
   -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
       --tls                Use TLS; implied by --tlsverify
       --tlscacert string   Trust certs signed only by this CA (default "/root/snap/docker/384/.docker/ca.pem")
       --tlscert string     Path to TLS certificate file (default "/root/snap/docker/384/.docker/cert.pem")
       --tlskey string      Path to TLS key file (default "/root/snap/docker/384/.docker/key.pem")
       --tlsverify          Use TLS and verify the remote
   -v, --version            Print version information and quit

위 예제처럼 tls 의 관련 옵션이 존재 하며 기본 경로는 /root/snap/docker/384/.docker 로 되어 있는것을 확인 할 수 있다.(필자는 snap 으로 docker 를 설치하여 위처럼 경로가 설정 됨)

먼저 기본 경로인 /root/snap/docker/384/.docker 로 이동 하자

> cd /root/snap/docker/384/.docker

OpenSSL을 사용하여 CA, 서버 및 클라이언트 키 만들기

CA 개인 키와 공개 키를 생성 해보자

   > openssl genrsa -aes256 -out ca-key.pem 4096
   > openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem 

Common Name 항목에 서버 호스트명을 정확하게 입력하도록 주의하자.

root@docker-02:~/snap/docker/384/.docker# openssl genrsa -aes256 -out ca-key.pem 4096
 Generating RSA private key, 4096 bit long modulus
 …………………………………………………….++
 ……………………………………………++
 e is 65537 (0x010001)
 Enter pass phrase for ca-key.pem:
 Verifying - Enter pass phrase for ca-key.pem:
 root@docker-02:~/snap/docker/384/.docker# openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
 Enter pass phrase for ca-key.pem:
 You are about to be asked to enter information that will be incorporated
 into your certificate request.
 What you are about to enter is what is called a Distinguished Name or a DN.
 There are quite a few fields but you can leave some blank
 For some fields there will be a default value,
 If you enter '.', the field will be left blank.
 Country Name (2 letter code) [AU]:KR  
 State or Province Name (full name) [Some-State]:
 Locality Name (eg, city) []:
 Organization Name (eg, company) [Internet Widgits Pty Ltd]:
 Organizational Unit Name (eg, section) []:
 Common Name (e.g. server FQDN or YOUR name) []:docker-02
 Email Address []:

$HOST 항목에는 호스트 서버의 도메인이나 ip를 입력한다

> openssl genrsa -out server-key.pem 4096 
> openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr 
root@docker-02:~/snap/docker/384/.docker# openssl genrsa -out server-key.pem 4096
 Generating RSA private key, 4096 bit long modulus
 ……………………………………………………………………………………………………………….++
 ………………………..++
 e is 65537 (0x010001)
 root@docker-02:~/snap/docker/384/.docker# openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr

tls 연결은 DNS 와 ip 주소를 통해 이루어 진다. ip와 DNS를 모두 추가하려면 아래와 같이 입력 한다.

 > echo subjectAltName = DNS:$HOST,IP:10.10.10.20,IP:127.0.0.1 >> extfile.cnf 

이제 서명된 인증서를 생성 해보자. CN에 DNS 명도 정확한지 확인하자

 $ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
   -CAcreateserial -out server-cert.pem -extfile extfile.cnf
 Signature ok
 subject=/CN=your.host.com
 Getting CA Private Key Enter pass phrase for ca-key.pem: 

이제부터는 tls 통신을 위한 클라이언트 측 인증서 파일을 만들어 보도록 하자

  > openssl genrsa -out key.pem 4096
  > openssl req -subj '/CN=client' -new -key key.pem -out client.csr
  > echo extendedKeyUsage = clientAuth > extfile-client.cnf 

이제 서명된 인증서를 생성해 보자

> openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile  extfile-client.cnf 

불필요한 인증서 서명 요청파일을 삭제 하자

> rm -v client.csr server.csr extfile.cnf extfile-client.cnf

실수로 인한 인증서 파일 손상을 막기 위해 권한을 변경 하자

> chmod -v 0400 ca-key.pem key.pem server-key.pem
> chmod -v 0444 ca.pem server-cert.pem cert.pem 

이제 인증서 생성작업은 모두 완료 되었다. Docker 서비스를 중지하고 아래 명령으로 실행 해 보자

> service docker stop
> docker daemon --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=0.0.0.0:2376 

필자는 ubuntu 18 버전에 snap 으로 설치해서 조금 다르게 입력해야 동작 한다.

> snap stop docker
> /usr/bin/snap run docker.dockerd --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock

이제 인증서를 클라이언트 서버에 복사 후 아래와 같이 tls 인증을 통한 curl 테스트를 해볼 수 있다.

 curl https://$HOST:2376/images/json \
   --cert ~/.docker/cert.pem \
   --key ~/.docker/key.pem \   --cacert ~/.docker/ca.pem 

Leave a Reply

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다