Search

self-signed-certificate

0. 준비

openssl3
kubernetes(minikube)

1. CA RSA 키 페어 생성

실제 CA가 아니라 우리가 직접 CA를 만들어 TLS 인증하는 과정을 모의로 해본다(self-signed certificate)
$ openssl genrsa -aes256 -out rootCA.key 2048Enter PEM pass phrase:Verifying - Enter PEM pass phrase:$ ll rootCA.key-rw------- 1 hansuk staff 1874 Jan 14 14:30 rootCA.key
Shell
복사
비밀키 분실을 대비하여 AES256으로 암호화 한다. 이때 passphrase를 잘 기억하고 발급할 때 사용하자

2. CA 인증서 발급

$ openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crtEnter pass phrase for rootCA.key:You are about to be asked to enter information that will be incorporatedinto 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 blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [AU]:KRState or Province Name (full name) [Some-State]:RootStateLocality Name (eg, city) []:RootCityOrganization Name (eg, company) [Internet Widgits Pty Ltd]:Root Inc.Organizational Unit Name (eg, section) []:Root CACommon Name (e.g. server FQDN or YOUR name) []:Self-signed Root CAEmail Address []:$ lltotal 16-rw-r--r-- 1 hansuk staff 1033 Jan 14 14:45 rootCA.crt-rw------- 1 hansuk staff 1874 Jan 14 14:30 rootCA.key
Shell
복사
상호작용하는 입력은 대충 해주어도 된다. 키 외에 crt 파일이 생긴걸 확인.

3. localhost(subject) CSR 생성

$ cat << EOF > localhost.csr.cnf> [req]> default_bits = 2048> prompt = no> default_md = sha256> distinguished_name = dn>> [dn]> C=KR> ST=Seoul> L=Seocho-gu> O=Localhost> CN = localhost> EOF$ openssl req -new -sha256 -nodes -out localhost.csr -newkey rsa:2048 -keyout localhost.key -config localhost.csr.cnf...+......+.....+...+.+.........+............+...+..+......+.......+...+...+..+....+.....+.............+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*............+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+..+.+...+......+.....+....+.....+...............+....+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.+............+..+......+.+...+........+...+....+......+..+...+.........+..................+....+...+...+..+...+...+....+......+............+..+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+.+...........+.......+.....+...+....+...+......+..+...+......+......+..................+.+......+.....+....+...+...+.........+....................+.+..+...+...+.......+...+............+..+...............+.+.........+...+........+.+.....+....+............+...+...........+...+......+....+........+...+......+.+...+.........+........+....+...+......+..+.............+......+........+.+..+...+......+...+..........+..+.............+......+.........+......+..+...+.+..............+.........+......+.+.....+...+...+.......+...+.....+..........+...+.........+...+..............+...+................+..+.........+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----$ ll localhost.*-rw-r--r-- 1 hansuk staff 985 Jan 14 14:53 localhost.csr-rw-r--r-- 1 hansuk staff 141 Jan 14 14:52 localhost.csr.cnf-rw------- 1 hansuk staff 1704 Jan 14 14:53 localhost.key
Shell
복사
위에서 CA CSR 발급 시 상호작용으로 입력했던 common name과 같은 입력 값을 파일에 쓰고 인자로 준다.

4. localhost 인증서 생성

$ cat << EOF > v3.ext> authorityKeyIdentifier=keyid,issuer> basicConstraints=CA:FALSE> keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment> subjectAltName = @alt_names>> [alt_names]> DNS.1 = localhost> EOF$ openssl x509 -req -in localhost.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out localhost.pem -days 365 -sha256 -extfile v3.extEnter pass phrase for rootCA.key:$ openssl verify -CAfile rootCA.crt localhost.pemlocalhost.pem: OK
Shell
복사
X509 v3 확장 명세를 정의하고 인증서를 발급한다. alt_names (Subject Alternative Name, SAN)필드에 DNS.n를 추가하면 인증서로 신뢰할 수 있는 도메인을 추가할 수 있다.

5. subject 서버 준비

로컬 nginx에 인증서를 설치하여 인증을 테스트해본다. 먼저 인증서를 설치를 위한 시크릿과 설정맵도 만든다. 쿠버네티스는 TLS 타입에 대해 빌트인 시크릿이 정의되어 있다:
$ kubectl create secret tls nginxsecret --key localhost.key --cert localhost.pemsecret/nginxsecret created$ cat << EOF > default.conf> server {> listen 80 default_server;> listen [::]:80 default_server ipv6only=on;>> listen 443 ssl;>> root /usr/share/nginx/html;> index index.html;>> server_name localhost;> ssl_certificate /etc/nginx/ssl/tls.crt;> ssl_certificate_key /etc/nginx/ssl/tls.key;>> location / {> try_files $uri $uri/ =404;> }> }> EOF$ kubectl create configmap nginxconfmap --from-file=default.confconfigmap/nginxconfmap created
Shell
복사
만든 인증서를 설치할 nginx 컨테이너를 up 한다:
apiVersion: v1kind: Servicemetadata: name: nginx-cert labels: app: nginx-certspec: type: NodePort ports: - port: 80 protocol: TCP name: http nodePort: 30080 - port: 443 protocol: TCP name: https nodePort: 30443 selector: app: nginx-cert---apiVersion: apps/v1kind: Deploymentmetadata: labels: run: nginx-cert name: nginx-certspec: replicas: 1 selector: matchLabels: app: nginx-cert template: metadata: labels: app: nginx-cert spec: volumes: - name: secret-volume secret: secretName: nginxsecret - name: configmap-volume configMap: name: nginxconfmap containers: - image: nginx name: nginx ports: - containerPort: 80 - containerPort: 443 volumeMounts: - mountPath: /etc/nginx/ssl name: secret-volume - mountPath: /etc/nginx/conf.d name: configmap-volume
YAML
복사

6. SSL 요청

minikube 서비스 IP를 알아내어 openssl로 먼저 요청해본다:
$ minikube service --url nginx-cert -n certhttp://192.168.64.2:30080http://192.168.64.2:30443$ openssl s_client -CAfile rootCA.crt -connect 192.168.64.2:30443 2>/dev/null < /dev/nullCONNECTED(00000003)---Certificate chain 0 s:C = KR, ST = Seoul, L = Seocho-gu, O = Localhost, CN = localhost i:C = KR, ST = RootState, L = RootCity, O = Root Inc., OU = Root CA, CN = Self-signed Root CA a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Jan 17 03:37:15 2022 GMT; NotAfter: Jan 17 03:37:15 2023 GMT---Server certificate-----BEGIN CERTIFICATE-----MIIDzzCCAregAwIBAgIUYMe6nRgsZwq9UPMKFgj9dt9z9FIwDQYJKoZIhvcNAQELBQAweDELMAkGA1UEBhMCS1IxEjAQBgNVBAgMCVJvb3RTdGF0ZTERMA8GA1UEBwwIUm9vdENpdHkxEjAQBgNVBAoMCVJvb3QgSW5jLjEQMA4GA1UECwwHUm9vdCBDQTEcMBoGA1UEAwwTU2VsZi1zaWduZWQgUm9vdCBDQTAeFw0yMjAxMTcwMzM3MTVaFw0yMzAxMTcwMzM3MTVaMFkxCzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVTZW91bDESMBAGA1UEBwwJU2VvY2hvLWd1MRIwEAYDVQQKDAlMb2NhbGhvc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALc9retjBorwRKbuyC1SNx1U9L5LJPPbBkBh4kg98saQxtRX0Wqs5mgswWMZYL3E6yRl0gfwBkdqt8GVQ49dgg0QO5MbG9ylfCLS9xR3WWjAgxaDJ0W96PyvTzmg295aqqHFKPSaG/nMJyZgFJDuGoRRgwoWNqZ1pRCDLMIENDx4qgjOnQch529pM9ZRwFQSswKpn4BVkY00/u8jIvax67kFOg70QGY16paGEg7YfSNle7BFZY0VJ8rIiBoqwRmPH6hbF/djxe5byzkI9eqts9bqw8eDLC28S36x62FxkdqkK8pI/rzWAKSV43TWML1zq4vM2bI+vp0ka06GhSsS1bUCAwEAAaNwMG4wHwYDVR0jBBgwFoAUURHNpOE9zTgXgVYAGvLt94YmP+8wCQYDVR0TBAIwADALBgNVHQ8EBAMCBPAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MB0GA1UdDgQWBBSS1ZHHT6OHTomYIRsmhz6hMJLGnDANBgkqhkiG9w0BAQsFAAOCAQEAWA23pCdAXtAbdSRy/p8XURCjUDdhkp3MYA+1gIDeGAQBKNipU/KEo5wO+aVkAG6FryPZLOiwiP8nYAebUxOAqKG3fNbgT9t95BEGCip7Cxjp96KNYt73Kl/OTPjJKZUkHQ7MXN4vc5gmca8q+OqwCCQ/daMkzLabPQWNk3R/Hzo/mT42v8ht9/nVh1Mlu3Dow5QPp8LESrJABLIRyRs0+Tfp+WodgekgDX5hnkkSk77+oXB49r2tZUeG/CVvFg8PuUNi+DWpdxX8fE/gIbSzSsamOf29+0sCIoJEPvk7lEVLt9ca0SoJ7rKn/ai4HxwTiYo9pNcoLwhH3xdXjvbuGA==-----END CERTIFICATE-----subject=C = KR, ST = Seoul, L = Seocho-gu, O = Localhost, CN = localhostissuer=C = KR, ST = RootState, L = RootCity, O = Root Inc., OU = Root CA, CN = Self-signed Root CA---No client certificate CA names sentPeer signing digest: SHA256Peer signature type: RSA-PSSServer Temp Key: X25519, 253 bits---SSL handshake has read 1620 bytes and written 390 bytesVerification: OK---New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384Server public key is 2048 bitSecure Renegotiation IS supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 00C994177DCF3DA424433CD0EDB33FF54C1198D0DE2C08D61BBD155D85890F20 Session-ID-ctx: Master-Key: B88A94A3556F9A595B3B395E0F4701290D3837BC49CA125CA25E0351261E7C59F0DF0928B4A12E33509B38B2F2684711 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: 0000 - 5d 96 c8 cf 8f 9c 9f c4-15 25 b9 57 56 13 ec 9d ]........%.WV... 0010 - 2a 26 f8 e5 09 e4 01 11-fa 59 25 a1 6c e7 ba 94 *&.......Y%.l... 0020 - 85 b2 6c 49 b1 1f 78 6c-4c b1 ed b1 af 1b ce 46 ..lI..xlL......F 0030 - c6 f1 bd f8 36 da b0 c4-31 ce ba 62 72 4b 76 a1 ....6...1..brKv. 0040 - 2d d4 b6 8d cb c3 39 ee-8f 05 77 48 9e 61 3e 4a -.....9...wH.a>J 0050 - 2c 6b f4 19 59 f4 93 cf-bd d7 16 76 ce af 48 b5 ,k..Y......v..H. 0060 - b7 cc c2 aa 9b 36 44 b5-93 4e 1e 8a 96 6c e7 96 .....6D..N...l.. 0070 - b5 0e 04 96 77 d7 df 2a-ef 70 ad c1 7b 82 a9 3a ....w..*.p..{..: 0080 - 5c 9b 4a 94 fb ea dc de-15 11 fa 3b e1 af dd cf \.J........;.... 0090 - 57 48 98 ed c8 d7 6b 5d-00 c3 84 5f 86 0c a8 b5 WH....k]..._.... 00a0 - 18 66 52 14 c4 9c b0 ff-0b 39 12 b6 0a 78 49 4d .fR......9...xIM Start Time: 1644478485 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: yes---
Shell
복사
브라우저에서도 확인해본다. openssl 요청 시 CAfile 옵션으로 CA 인증서를 넘겨 주었지만, 브라우저 요청에 적용하기 위해선 맥 시스템 키체인에 추가해야한다. 신뢰 탭을 펼쳐 이 인증서 사용 시
항상 신뢰
로 변경하자:
2
쿠버네티스 공식 문서에도 self-signed certificate를 설명하는 글이 있다. CKA를 준비하며 알게 된것인데, 쿠버네티스는 클러스터 사용자 인증에 TLS 인증을 사용한다. 인증서 요청 승인, 발급 등의 과정은 kubectl로 더 간단하게 할 수 있지만 CSR 생성은 위와 같은 방법으로도 하고, openssl이 아닌 다른 도구를 쓰기도 한다.
아무튼 나는 openssl로 self-signed certificate 해본 것이 CKA 시험 보는데에도 큰 도움이 됐다.
openssl 뿐만 아니라 인증서 발급할 수 있는 다른 여러 도구가 있다. 하지만 openssl로 연습해보길 잘했다. 가장 기초가 되는 도구 같다.
nginx 설정하다가 오타가 생겨 헤맸는데 스택오버플로에서 도움을 받아 해결했다: https://stackoverflow.com/questions/70830744/nginx-pod-responds-with-its-listening-port-in-self-signed-certificate-examples

참고