잊지 않겠습니다.

PKI 시스템

Java 2017.07.13 10:12

PKI

PKI에 대해서 정리할 필요성이 있어서 정리하게 되었습니다.

이론

  • RFC 2459에 정의 (Internet X.509 Public Key Infrastructure)
  • 암호화와 복호화를 위해 서로 다른 키를 사용하는 방식(비대칭 암호화방식)에서 사용되는 key 기반
  • 암호화를 위해 사용되는 Key: Public Key
  • 복호화를 위해 사용되는 Key: Private Key

Message Digest

  • 메세지 축약(message digest) - MD5(128bit), SHA1(160bit), SHA256
  • 아무리 긴 내용이라도 축약시키는 것이 가능

Symmetric Key Algorithm

  • OneKey - Symmetric Key를 이용해서 Encrypt와 Decrypt를 진행
  • 속도가 빠르다.
  • 3DES, AES

Asymmetric Key Algorithm

  • Two Key (PrivateKey, PublicKey)

  • 리만가설에 근거

  • RSA

  • 공개키 암호화/복호화

PlainText --(Public Key)--> EncryptedText
EncryptedText --(Private Key)--> PlainText
  • 서명/확인 (Sign/Verify)
PlainText --(Private Key)--> SignedValue
SignedValue --(Public Key)--> PlainText

PKI

  • Asymmetric Key Algorithm
  • Private Key, Public Key를 이용
  • Private Key는 충분히 보호받고, 외부에 노출되지 않는 상황
  • Public Key는 항시 노출이 가능한 상황
  • PrivateKey를 가진 상대방만 볼 수 있는 내용을 전달하고 싶은 경우에는 암호화/복호화(Encrypt/Decrypt)
  • PrivateKey를 가진 사람이 보낸 내용임을 확인하기 위한 방법이 서명/확인(Sign/Verify)

OpenSSL

OpenSource로 PKI를 지원

Private Key/Public Key 생성

#private key 생성
openssl genrsa -out server.private.pem 2048 

#(option) private key를 사용할 때 필요한 암호 제거
openssl rsa -in server.private.pem -out server.private.pem 

#private key와 쌍이 되는 public key 생성
openssl rsa -in server.private.pem -pubout -out server.public.pem 

Key 파일 형식

  • pem(Privacy Enhanced Mail): byte data를 Base64 HEX String으로 변경시켜서 가독성이 있도록 만든 Format
  • der(Distinguished Encoding Rules): byte data. Browser에서 사용되는 기본 형식
#DER -> PEM (private key)
openssl rsa -inform DER -outform PEM -in server.private.der -out server.private.pem 

#PEM -> DER (private key)
openssl rsa -inform PEM -outform DER -in server.private.pem -out server.private.der 
#DER -> PEM (public key)
openssl rsa -inform DER -outform PEM -pubin -in server.public.der -out server.public.pem 

#PEM -> DER (public key)
openssl rsa -inform PEM -outform DER -pubin -in server.public.pem -out server.public.der 

서버인증서

HTTPS를 지원하기 위해서는 서버에 대한 인증서를 요청해야지 됩니다. 인증된 기간이 요청서를 인증을 하게 되면 그것이 인증서가 됩니다.

1.요청서 작성

#요청서 작성
openssl req -new -days 500 -key server.private.pem -out server.csr 

2.요청서를 CA가 서명

#요청서를 CA가 서명
openssl x509 -req -days 500 -in server.csr -signkey ca.private.pem -out server.crt 

3.(option) PFX 파일

comodo등에서는 pfx파일이 주로 사용됩니다. pfx는 crt와 server.private.pemserver.public.pemca.public.pem이 결합되어 있는 형태입니다.

PFX = 요청서 + 서버PrivateKey + 서버PublicKey + CaPublicKey
#CA 개인키와 요청서와 서버 요청서 결합 (password 연결)
openssl pkcs12 -export -in server.crt -inkey ca.private.pem -out server.pfx 

#PFX 파일에서 server의 private key 추출
openssl pkcs12 -in server.pfx -nocerts -nodes -out server.private.pem 

#PFX 파일에서 server 요청서 추출
openssl pkcs12 -in server.pfx -clcerts -nokeys -out server.crt 

4.(option) JKS(java key store)

JKS 파일은 pfx를 통해서 얻어낼 수 있으며, server.private.pem과 server.public.pem을 모두 얻어낼 수 있습니다. java의 keytool을 이용합니다.

keytool -importkeystore -srckeystore server.pfx -srcstoretype pkcs12 -destkeystore server.jks -deststoretype jks


저작자 표시 동일 조건 변경 허락
신고
Posted by xyzlast Y2K
TAG PKI

nodejs + pm2 application을 구성한 dockfile을 구성하는 방법에 대해서 알아보도록 하겠습니다.

먼저 code를 어떤 방법으로 배포할지에 대한 process를 정하는 것이 중요합니다. 이는 Dockerfile을 어떻게 만들지에 대한 방향이 결정나게 됩니다.

배포 Process

제가 구성한 Docker를 이용한 배포 process는 다음과 같습니다.

  1. nvm 설치
  2. nvm을 이용한 node 설치
  3. pm2 설치
  4. ssh 인증 + git clone 을 통한 code download
  5. npm install
  6. .pm2/logs 위치에 따른 host 파일 공유
  7. docker run의 parameter pass를 통한 pm2 start json 파일 전송

1. nvm 설치 & node 설치 & pm2 설치

ubuntu image를 기본으로 하여 구성을 하도록 하겠습니다. nodejs application은 npm install을 통해서 node_modules을 다운로드 받아서 compile되는 환경이기 때문에 build환경역시 갖추는 것이 중요합니다.

FROM ubuntu # 빌드 환경 구성 RUN apt-get update RUN apt-get install -y wget build-essential keychain git python # NVM_DIR, NODE_VERSION에 따른 ENV 설정 ENV NVM_DIR /usr/local/nvm ENV NODE_VERSION 7.3.0 # NVM 다운로드 & 설치 RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash # Shell 변경 (sh -> bash) SHELL ["/bin/bash", "-c"] # nvm 구성 & node install RUN source $NVM_DIR/nvm.sh; \ nvm install $NODE_VERSION; \ nvm use --delete-prefix $NODE_VERSION; ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH # PM2 설치 RUN npm install -g pm2

2. ssh 인증 구성

ssh 인증을 위해서 private key를 image안에 COPY할 필요가 있습니다. 그리고 $(ssh-agent)값을 지정해줄 필요가 있습니다. 그런데, eval을 이용한 값 설정의 경우, Dockerfile에서 할 수 없습니다. 따라서 do-ssh.sh 실행 파일을 구성해서 처리할 image 내부에서 실행할 필요가 있습니다.

다음은 do-ssh.sh파일의 내용입니다.

eval "$(ssh-agent)" && ssh-agent -s ssh-add /root/.ssh/id_rsa
# .ssh Folder작성 & private key Copy RUN mkdir /root/.ssh COPY [ "id_rsa", "/root/.ssh/id_rsa" ] # SSH Key 권한 설정 - 권한이 600이 아닌경우, id_rsa key를 얻어내지 못합니다. RUN chmod 600 /root/.ssh/id_rsa # do-ssh.sh 파일 COPY COPY [ "do-ssh.sh", "/root/do-ssh.sh" ] # 실행권한 설정 RUN chmod 777 /root/do-ssh.sh # SHELL 변경 (bash -> sh) SHELL ["/bin/sh", "-c"] # do-ssh.sh RUN RUN /root/do-ssh.sh # SSH 접근 check. -o StrictHostKeyChecking=no option이 없으면 docker container에서 실행되지 않습니다. RUN ssh -T -v git@10.1.95.184 -o StrictHostKeyChecking=no

3. git code download & npm install

nodejs Application이 위치될 folder를 만들어주고, git clone을 통해서 code를 받고, npm install을 하는 구성입니다.

# apps folder 작성 RUN mkdir /apps # Shell 변경 (sh -> bash) SHELL ["/bin/bash", "-c"] WORKDIR /apps RUN git clone git@10.1.95.184:/home/git/repo/fms-api-v2.git -o StrictHostKeyChecking=no WORKDIR /apps/fms-api-v2 # npm 설치 RUN npm install

npm install을 통해서 필요한 node module들을 모두 받아주고 build과정을 거치게 됩니다.

4. PORT 공유 & PM2 Log volume 구성

제가 만든 application은 5000, 8000번 port를 open시켜서 사용합니다. 사용되는 PORT를 EXPOSE 시켜주는 과정이 필요하게 됩니다. 그리고 pm2의 log 파일을 host에 기록하도록 volume을 추가합니다.

# expose 5000, 8000 port EXPOSE 8000 EXPOSE 5000 # VOLUME 설정 pm2 log folder VOLUME /root/.pm2/logs

5. 뒷처리과정

매우매우 위험한 파일을 container에 넣어둔것을 기억하고 있어야지됩니다. private key가 바로 그것이지요. 꼭 이 파일을 지워주는 과정이 필요합니다. 마지막으로pm2 실행에 대한 ENTRYPOINT와 CMD 설정이 필요합니다. 제가 만든 application은 설정 json파일에 따라서 동작환경이 변경되게 됩니다. 설정 json파일을 외부에서 parameter로 넣어줄 수 있도록 설정해주는 것이 필요합니다.

# Private Key 삭제 RUN rm /root/.ssh/id_rsa # ENTRYPOINT 설정 docker container에서 pm2를 실행시킬때는 pm2-docker를 통해서 실행합니다. ENTRYPOINT [ "pm2-docker" ] # CMD 설정 - parameter가 없는 경우, default 값을 지정하게 됩니다. CMD ["pm2/dev-system.json"]

6. build image & docker run

image를 만들기 위해서, docker build를 다음과 같이 구성합니다.

docker build -t nodejs-pm2-application .

이제 process가 진행되면 nodejs-pm2-application으로 image가 만들어지게 됩니다.

만들어진 image를 이용해서 container를 배포하는 명령어는 다음과 같습니다.

docker run -it --name node-app -p 5000:5000 -p 8000:8000 -v /logs/pm2:/root/.pm2/logs -t nodejs-pm2-application pm2/api-system1.json
  • -p option으로 5000, 8000번 port를 host에 연결합니다.
  • -v options으로 /root/.pm2/logs folder를 host의 /logs/pm2로 mount 시킵니다.
  • 마지막에 command로 /pm2/api-system1.json을 넣어 container의 COMMAND를 pm2-docker pm2/api-system1.json으로 변경시킵니다.

SUMMARY

Dockerfile을 구성하는 것은 Application의 형태에 따라, 개발환경에 따라 많은 차이를 가지고 오게 됩니다. nodejspythonruby와 같이 외부 library를 받아 compile하는 과정을 가지게 된다면 image내부에서 code를 직접 git으로 받아올 필요가 있습니다. 그러나, JAVAC#GO와 같이 universal compile이 되는 경우, Docker image를 만들때, compile시켜 ADD를 통해서 실행파일을 image안에 넣는것이 더 좋을것 같습니다.

다음은 전체 Dockerfile입니다.

FROM ubuntu # 빌드 환경 구성 RUN apt-get update RUN apt-get install -y wget build-essential keychain git python # NVM_DIR, NODE_VERSION에 따른 ENV 설정 ENV NVM_DIR /usr/local/nvm ENV NODE_VERSION 7.3.0 # NVM 다운로드 & 설치 RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash # Shell 변경 (sh -> bash) SHELL ["/bin/bash", "-c"] # nvm 구성 & node install RUN source $NVM_DIR/nvm.sh; \ nvm install $NODE_VERSION; \ nvm use --delete-prefix $NODE_VERSION; ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH # PM2 설치 RUN npm install -g pm2 # .ssh Folder작성 & private key Copy RUN mkdir /root/.ssh COPY [ "id_rsa", "/root/.ssh/id_rsa" ] # SSH Key 권한 설정 - 권한이 600이 아닌경우, id_rsa key를 얻어내지 못합니다. RUN chmod 600 /root/.ssh/id_rsa # do-ssh.sh 파일 COPY COPY [ "do-ssh.sh", "/root/do-ssh.sh" ] # 실행권한 설정 RUN chmod 777 /root/do-ssh.sh # SHELL 변경 (bash -> sh) SHELL ["/bin/sh", "-c"] # do-ssh.sh RUN RUN /root/do-ssh.sh # SSH 접근 check. -o StrictHostKeyChecking=no option이 없으면 docker container에서 실행되지 않습니다. RUN ssh -T -v git@10.1.95.184 -o StrictHostKeyChecking=no # apps folder 작성 RUN mkdir /apps # Shell 변경 (sh -> bash) SHELL ["/bin/bash", "-c"] WORKDIR /apps RUN git clone git@10.1.95.184:/home/git/repo/fms-api-v2.git -o StrictHostKeyChecking=no WORKDIR /apps/fms-api-v2 # npm 설치 RUN npm install # expose 5000, 8000 port EXPOSE 8000 EXPOSE 5000 # VOLUME 설정 pm2 log folder VOLUME /root/.pm2/logs # Private Key 삭제 RUN rm /root/.ssh/id_rsa # ENTRYPOINT 설정 docker container에서 pm2를 실행시킬때는 pm2-docker를 통해서 실행합니다. ENTRYPOINT [ "pm2-docker" ] # CMD 설정 - parameter가 없는 경우, default 값을 지정하게 됩니다. CMD ["pm2/dev-system.json"]

Happy Coding~

저작자 표시 동일 조건 변경 허락
신고
Posted by xyzlast Y2K

queryDSL이 4.x대로 변경이 되면서 package명에 큰 변화가 생겼습니다. 기존 com.mysema.querydsl 에서 com.querydsl로 package명이 바뀌어서 간략화 되었지요.

기존 querydsl 처리 부분에 대한 build.gradle을 변경한다면 다음과 같습니다.


dependencies {
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile 'com.graphql-java:graphql-java:2.1.0'
compile("org.springframework.boot:spring-boot-starter-jetty")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile("junit:junit")
testCompile("org.springframework.boot:spring-boot-starter-test")
compile 'com.querydsl:querydsl-apt:4.1.4'
compile 'com.querydsl:querydsl-jpa:4.1.4'
compile 'org.springframework.data:spring-data-jpa:1.10.4.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.2.3.Final'
compile "org.hibernate:hibernate-entitymanager:5.2.3.Final"
compile 'com.h2database:h2:1.4.187'
compile group: 'org.aspectj', name: 'aspectjrt', version: '1.8.9'
compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.8.9'
compileOnly "org.projectlombok:lombok:1.16.12"
}


sourceSets {
main {
java {
srcDirs 'src/main/java', 'src/main/generated'
}
}
}

task generateQueryDSL(type: JavaCompile, group: 'build', description: 'Generates the QueryDSL query types') {
file(new File(projectDir, "/src/main/generated")).deleteDir()
file(new File(projectDir, "/src/main/generated")).mkdirs()
source = sourceSets.main.java
classpath = configurations.compile + configurations.compileOnly
options.compilerArgs = [
"-proc:only",
"-processor", "com.querydsl.apt.jpa.JPAAnnotationProcessor"
]
destinationDir = file('src/main/generated')
}

compileJava {
dependsOn generateQueryDSL
}

clean.doLast {
file(new File(projectDir, "/src/main/generated")).deleteDir()
}


기존의 generateQueryDSL task를 유지할 필요 없이, java compile option으로 QClass 생성을 넣어주는것으로 script를 간략화시키는것이 가능합니다. 또한 Q class가 존재할 때, 기존 Q Class를 지워주지 않으면 compile 시에 에러를 발생하게 되기 때문에 지워주는 작업역시 doFirst에 같이 실행하고 있습니다.

기존의 build.gradle보다 간략해보여서 전 개인적으로 맘에 드네요.

저작자 표시 동일 조건 변경 허락
신고
Posted by xyzlast Y2K
TAG gradle, java, JPA


티스토리 툴바