TLS 인증 구성하기

개요

필요한 경우 사설 TLS 인증서를 발급하여 해당 TLS 인증서를 가진 클라이언트만 ETCD3 클러스터에 접근하여 데이터 CRUD를 수행하도록 강제할 수 있다.

인증서 생성

필요한 Tool 설치

cfssl, cfssljson 설치

#!/bin/bash
CFSSL_VERSION=1.6.5
CFSSL_PATH=/usr/local/bin
ARCH=amd64

curl -L "https://github.com/cloudflare/cfssl/releases/download/v${CFSSL_VERSION}/cfssl_${CFSSL_VERSION}_linux_${ARCH}" -o cfssl
curl -L "https://github.com/cloudflare/cfssl/releases/download/v${CFSSL_VERSION}/cfssljson_${CFSSL_VERSION}_linux_${ARCH}" -o cfssljson
curl -L "https://github.com/cloudflare/cfssl/releases/download/v${CFSSL_VERSION}/cfssl-certinfo_${CFSSL_VERSION}_linux_${ARCH}" -o cfssl-certinfo

chmod +x cfssl cfssljson cfssl-certinfo
sudo cp cfssl cfssljson cfssl-certinfo ${CFSSL_PATH}/

인증서 발급하기

참고

ETCD3 클러스터를 위한 인증서 발급 예시를 참조한다.

https://github.com/etcd-io/etcd/tree/main/hack/tls-setup

Makefile을 필요에 따라 아래와 같이 수정한다.

  • 해당 예시의 경우, 파일 관리 편의성을 위해 cfssljson 명령어로 export 하여 생성하는 .pem 파일의 이름 템플릿을 변경하였다.

$ vim Makefile
.PHONY: cfssl ca req clean

CFSSL   = @env PATH=$(GOPATH)/bin:$(PATH) cfssl
JSON    = env PATH=$(GOPATH)/bin:$(PATH) cfssljson

all:  ca req

cfssl:
        HTTPS_PROXY=127.0.0.1:12639 go get -u -tags nopkcs11 github.com/cloudflare/cfssl/cmd/cfssl
        HTTPS_PROXY=127.0.0.1:12639 go get -u github.com/cloudflare/cfssl/cmd/cfssljson
        HTTPS_PROXY=127.0.0.1:12639 go get -u github.com/mattn/goreman

ca:
        mkdir -p certs
        $(CFSSL) gencert -initca config/ca-csr.json | $(JSON) -bare certs/etcd-ca

req:
        $(CFSSL) gencert \
          -ca certs/etcd-ca.pem \
          -ca-key certs/etcd-ca-key.pem \
          -config config/ca-config.json \
          config/req-csr.json | $(JSON) -bare certs/${infra0}
        $(CFSSL) gencert \
          -ca certs/etcd-ca.pem \
          -ca-key certs/etcd-ca-key.pem \
          -config config/ca-config.json \
          config/req-csr.json | $(JSON) -bare certs/${infra1}
        $(CFSSL) gencert \
          -ca certs/etcd-ca.pem \
          -ca-key certs/etcd-ca-key.pem \
          -config config/ca-config.json \
          config/req-csr.json | $(JSON) -bare certs/${infra2}
        $(CFSSL) gencert \
          -ca certs/etcd-ca.pem \
          -ca-key certs/etcd-ca-key.pem \
          -config config/ca-config.json \
          config/req-csr.json | $(JSON) -bare certs/${infra0}-peer
        $(CFSSL) gencert \
          -ca certs/etcd-ca.pem \
          -ca-key certs/etcd-ca-key.pem \
          -config config/ca-config.json \
          config/req-csr.json | $(JSON) -bare certs/${infra1}-peer
        $(CFSSL) gencert \
          -ca certs/etcd-ca.pem \
          -ca-key certs/etcd-ca-key.pem \
          -config config/ca-config.json \
          config/req-csr.json | $(JSON) -bare certs/${infra2}-peer

clean:
        rm -rf certs

인증서 CSR (Certificate Signing Request) 를 필요에 따라 아래와 같이 수정한다.

  • “CN” 항목은 삭제한다. 현 Patroni에서 ETCD에 접근하기 위해 클라이언트로 이용하는 Python gRPC gateway가 TLS Common Name이 적용된 인증서를 지원하지 않는다.

  • host 항목에 구성할 ETCD 클러스터의 IP 주소 및 호스트 이름 (필요시) 을 배열로 입력한다.

$ vim config/req-csr.json
{
  "CN": "etcd",               # Patroni -> etcd 연결을 암호화한 구성인 경우 삭제
  "hosts": [
    "localhost",
    "127.0.0.1",
    "node1",
    "node2",
    "node3",
    "172.176.0.2",
    "172.176.0.3",
    "172.176.0.4"
  ],
  "key": {
    "algo": "ecdsa",
    "size": 384
  },
  "names": [
    {
      "O": "autogenerated",
      "OU": "etcd cluster",
      "L": "the internet"
    }
  ]
}

인증기관 (CA) CSR 을 필요에 따라 아래와 같이 수정한다.

  • “CN” 항목은 삭제한다.

  • 필요에 따라 names 항목을 아래와 같이 수정한다.

$ vim config/ca-csr.json
{
  "CN": "Autogenerated CA",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "O": "TmaxTibero",
      "OU": "OpenSQL",
      "L": "Seongnam-si",
      "ST": "Gyeonggi-do",
      "C": "KR"
    }
  ]
}

make 를 실행하여 인증서를 생성한다.

  • 설정한 infra0, infra1, infra2 환경변수 값은 생성된 .pem 인증서의 파일 이름으로 사용된다.

$ infra0=node1 infra1=node2 infra2=node3 make
$ ls -l
total 84
-rw-r--r-- 1 yhyjeon yhyjeon  985  1월  6 18:10 etcd-ca.csr
-rw------- 1 yhyjeon yhyjeon 1679  1월  6 18:10 etcd-ca-key.pem
-rw-rw-r-- 1 yhyjeon yhyjeon 1281  1월  6 18:10 etcd-ca.pem
-rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node1.csr
-rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node1-key.pem
-rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node1.pem
-rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node2.csr
-rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node2-key.pem
-rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node2.pem
-rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node3.csr
-rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node3-key.pem
-rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node3.pem
-rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node1-peer.csr
-rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node1-peer-key.pem
-rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node1-peer.pem
-rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node2-peer.csr
-rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node2-peer-key.pem
-rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node2-peer.pem
-rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node3-peer.csr
-rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node3-peer-key.pem
-rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node3-peer.pem


ETCD 연동

  • ETCD 실행 시 환경변수 파일 /etc/etcd/etcd.env 혹은 명령줄 인자를 통해 https 연결과 인증서 설정한다.

    • 생성한 인증기관 (CA) 인증서 etcd-ca, etcd-ca-key 를 이용해 서명된 인증서를 가지고 있는 클라이언트만 이 ETCD 인스턴스에 접근할 수 있다.

$ vim /etc/etcd/etcd.env
#/etc/etcd/etcd.env
## 아래 내용을 추가하여 허용할 인증서의 인증기관과 공개키 - 사설키를 각각 등록한다.
## 위치한 .pem 인증서는 etcd 프로세스를 시작할 사용자가 읽기 권한을 가진 파일이어야 한다.
#Cert
ETCD_TRUSTED_CA_FILE=/etc/etcd/pki/etcd-ca.pem
ETCD_CERT_FILE=/etc/etcd/pki/node3.pem
ETCD_KEY_FILE=/etc/etcd/pki/node3-key.pem
ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/pki/etcd-ca.pem
ETCD_PEER_CERT_FILE=/etc/etcd/pki/node3-peer.pem
ETCD_PEER_KEY_FILE=/etc/etcd/pki/node3-peer-key.pem

/etc/etcd/etcd.env 파일 혹은 ETCD 실행 시 명령줄 인자를 통해 ADVERTISE_CLIENT_URLS, LISTEN_CLIENT_URLS 변경

  • http://127.0.0.1:2379 는 Local 환경에서의 사용을 위한 것으로 불필요하면 삭제 가능하다.

  • #Certs 항목은 위 과정을 통해 발급한 인증서들을 등록한다. peer 는 Client, 나머지는 Server 사이드 TLS 인증서로 활용된다.

    • ETCD_TRUSTED_CA_FILE : 서버가 신뢰할 TLS 인증서의 인증 기관 (CA) 인증서 경로. 유효한 인증서가 구성된 경우 ETCD 서버는 모든 클라이언트의 인증서를 검증하게 된다. 별도 인증 기관을 설정하지 않고 클라이언트 인증을 활용하는 경우 ETCD_CLIENT_CERT_AUTH=true 옵션을 활용해야 한다.

    • ETCD_CERT_FILE : Client - Sever 통신에 사용할 TLS 인증서 경로이다.

    • ETCD_KEY_FILE : Client - Server 통신에 사용할 TLS Key 경로이다.

    • ETCD_PEER_TRUSTED_CA_FILE : ETCD Peer간 통신에 사용할 TLS 인증서의 인증 기관 (CA) 인증서 경로이다.

    • ETCD_PEER_CERT_FILE : ETCD Peer간 통신에 사용할 TLS 인증서 경로이다.

    • ETCD_PEER_KEY_FILE : ETCD Peer간 통신에 사용할 TLS Key 경로이다.

#/etc/etcd/etcd.env
# ...
ETCD_ADVERTISE_CLIENT_URLS=https://172.18.0.2:2379
ETCD_LISTEN_CLIENT_URLS=https://172.18.0.2:2379,http://127.0.0.1:2379
# ...
#Certs
ETCD_TRUSTED_CA_FILE=/etc/etcd/pki/etcd-ca.pem
ETCD_CERT_FILE=/etc/etcd/pki/node1.pem
ETCD_KEY_FILE=/etc/etcd/pki/node1-key.pem
ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/pki/etcd-ca.pem
ETCD_PEER_CERT_FILE=/etc/etcd/pki/node1-peer.pem
ETCD_PEER_KEY_FILE=/etc/etcd/pki/node1-peer-key.pem

Last updated