프로젝트 철수하는 주에 갑자기 고객사에서 인터페이스 테스트가 안된다는 연락을 받았다..
이유는.. 기존에 api 는 http 호출이었는데
갑자기 https 호출을 한다는것 ..!
Https는 데이터 전송에 암호화가 걸리는 것이기 때문에 생각보다 고려해야할 게 너무 많아서 오래 걸렸다..
간단하게 작업을 나열하자면
(.key 파일 없고 .pem 파일만 있을 때)
A. .key파일 생성
openssl rsa -in key.pem -out cert.key
B. 도메인에 대하여 인증서 등록
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./tls/project-https-secret/tls.key -out ./tls/project-https-secret/tls.crt -subj 도메인명
C. k8s 에서 인증서를 사용할 수 있도록 생성
kubectl -n project명 create secret tls twinreader-https --key ./tls/project-https-secret/tls.key --cert ./tls/project-https-secret/tls.crt
D. nginx.yaml 에서 사용할 https port 선언(예시) 및 재기동
spec:
type: NodePort
externalIPs:
- IP입력
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 80
- name: https
port: 443
protocol: TCP
targetPort: 443
E. ingress.yaml 설정
가지고 있는 ingress 폴더에 하위에 생성한 secret 선언
A. 인터페이스 SSL/TLS 설정
Keystore.p12생성
tls 디렉토리 접근 후
openssl pkcs12 -export -in /home/agilesoda/install/config/nginx/tls/twinreader-https-secret/tls.crt -inkey /home/agilesoda/install/config/nginx/tls/twinreader-https-secret/tls.key -out keystore.p12 -name tomcat
생성된 keystore.p12를 인터페이스에 적용
<application.properties>
server.ssl.key-store=/keystore.p12
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=패스워드
그리고 나는 도커로 말아서 올릴거니까
Dockerfile 에
ADD /install/keystore.p12 keystore.p12
이거 추가
그리고그리고 Kubernetes 클러스터에 배포하기 위한 deployment.yaml 수정
ports:
- name: https
protocol: TCP
#appProtocol: https
port: 443
targetPort: 9000
- name: http
protocol: TCP
port: 9100
targetPort: 9100
B. 개발 소스 수정
org.apache.coyote.http11.Http11NioProtocol"을 사용하여 HTTP/1.1 NIO 프로토콜을 지정하고 커넥터가 사용하는 포트를 9100 으로 설정..
@Configuration
public class TomcatConfig {
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(9100);
return connector;
}
}
C. Ingress 설정
클러스터 외부에서 내부 서비스로 HTTP 및 HTTPS 경로를 라우팅하는 규칙을 설정
<project-pension-ingress.yaml>
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: project
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
#nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/cors-allow-methods: "GET,POST"
spec:
tls:
- hosts:
- "도메인명"
secretName: twinreader-https
rules:
- host: "도메인명"
http:
paths:
- path: /api/v1/aiocrSyncLoad(/|$)(.*)
backend:
serviceName: project
servicePort: 443
yaml 파일 수정후 반영(kubectl delete, apply..)
처음엔 인증서만 받아서 보안포트 사용하면 되는거겟지~ 했는데
우선 인증서 발급과 반영에 대해 무지해서 도움을 많이 받았다.
인증서 적용 후 내 인터페이스의 POST 방식의 호출만 호출이 안되어서 그부분도 확인해보니 redirect 가 이상한 곳으로 가길래 ingress.yaml 의 rewrite 부분을 그냥 주석 해버렸더니 해결 되었었다.
해당 에러는
Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
이렇게 생겼었고
#logging.level.org.springframework=debug
#logging.level.org.springframework.web=debug
#logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG
해당 설정값을 추가해 자세히 로그를 보니 알 수 있었다.
다음으론 인터페이스 내부였다..
인터페이스 내부에는 회사 제품을 호출하고 결과를 받아서 그결과를 보정한 후 전달하게 되는데
https로 들어와서 제품 호출하고 제품에서 http 로 다시 인터페이스를 콜백하는데 그 통신이 안되는것이었다..
그래서 인터페이스 deployment.yaml 을 보면 https 와 http 포트를 구분지어서 통신에따라 다르게 들어오게 처리 해줬다!
이런식으로 port 가 두개!
그.. k8s 버전도 중요.. 꼭 버전에 맞는걸로 테스트 해보시길.. 버전마다 안되는 설정값이 있어서 이것도 애먹었다...
이제 앞으로는 처음 개발 시에 통신에 대해 정하고 시작하기로 다짐했다.
물론 당연히 데이터가 주고받는일에 단순히 내부통신이라고 보안을 생각못한 내잘 못도 있지만..
같이 테스트 하고 컨펌해줬으면서 갑자기 바꾸는 갈대 같은 고객사는... 어쩔 수 없지 뭐....
아직도 서버는 잘 모르겠지만...이렇게 틈틈이 접하다보면 괜찮아지겟지?
크