diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 57018759..ce246fc4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - test pull_request: branches: - main + - test workflow_dispatch: inputs: @@ -20,6 +22,7 @@ on: env: S3_BUCKET_NAME: wingle-ci-bucket + TEST_S3_BUCKET_NAME: wingle-test-ci-bucket CODE_DEPLOY_APPLICATION_NAME: wingle-codedeploy-app CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: wingle-codedeploy-group @@ -46,13 +49,24 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - - name: make main application.yml + - name: πŸš€ PROD - make main application.yml + if: github.ref == 'refs/heads/main' run: | sudo mkdir -p ./wingle/src/main/resources sudo chmod 777 ./wingle/src/main/resources cd ./wingle/src/main/resources touch ./application.yml echo "${{ secrets.MAIN_YML }}" > ./application.yml + + - name: πŸ‘€ TEST - make stage application.yml + if: github.ref == 'refs/heads/test' + run: | + sudo mkdir -p ./wingle/src/main/resources + sudo chmod 777 ./wingle/src/main/resources + cd ./wingle/src/main/resources + touch ./application.yml + echo "${{ secrets.STAGE_YML }}" > ./application.yml + # 파일 μ—†μœΌλ©΄ λΉŒλ“œ μ—λŸ¬ - uses: actions/upload-artifact@v3 with: @@ -104,20 +118,20 @@ jobs: shell: bash - name: Make zip file - if: contains(github.ref, 'main') +# if: contains(github.ref, 'main') run: zip -r ./$GITHUB_SHA.zip . shell: bash - - name: Configure AWS credentials - if: contains(github.ref, 'main') + - name: πŸš€ PROD - Configure AWS credentials + if: github.ref == 'refs/heads/main' uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ secrets.AWS_REGION }} - - name: Upload to AWS S3 - if: contains(github.ref, 'main') + - name: πŸš€ PROD - Upload to AWS S3 + if: github.ref == 'refs/heads/main' run: | cd ./wingle aws deploy push \ @@ -127,11 +141,40 @@ jobs: --source . # S3 버킷에 μžˆλŠ” νŒŒμΌμ„ λŒ€μƒμœΌλ‘œ CodeDeploy μ‹€ν–‰ - - name: Deploy to AWS EC2 from S3 - if: contains(github.ref, 'main') + - name: πŸš€ PROD - Deploy to AWS EC2 from S3 + if: github.ref == 'refs/heads/main' run: | aws deploy create-deployment \ --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ --deployment-config-name CodeDeployDefault.AllAtOnce \ --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ --s3-location bucket=$S3_BUCKET_NAME,key=build/$GITHUB_SHA.zip,bundleType=zip + + + - name: πŸ‘€ TEST - Configure AWS credentials + if: github.ref == 'refs/heads/test' + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.TEST_AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.TEST_AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: πŸ‘€ TEST - Upload to AWS S3 + if: github.ref == 'refs/heads/test' + run: | + cd ./wingle + aws deploy push \ + --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + --ignore-hidden-files \ + --s3-location s3://$TEST_S3_BUCKET_NAME/build/$GITHUB_SHA.zip \ + --source . + + # S3 버킷에 μžˆλŠ” νŒŒμΌμ„ λŒ€μƒμœΌλ‘œ CodeDeploy μ‹€ν–‰ + - name: πŸ‘€ TEST - Deploy to AWS EC2 from S3 + if: github.ref == 'refs/heads/test' + run: | + aws deploy create-deployment \ + --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + --deployment-config-name CodeDeployDefault.AllAtOnce \ + --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ + --s3-location bucket=$TEST_S3_BUCKET_NAME,key=build/$GITHUB_SHA.zip,bundleType=zip diff --git a/wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java b/wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java index 068aca1b..7a5acf28 100644 --- a/wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java +++ b/wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java @@ -1,13 +1,16 @@ package kr.co.wingle.common.util; -import java.io.UnsupportedEncodingException; -import java.security.GeneralSecurityException; -import java.security.Key; - import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import kr.co.wingle.common.constants.ErrorCode; @@ -15,45 +18,62 @@ @Component public class AES256Util { - //initial vector μ„€μ • - private static String iv = "0000000000000001"; - private static Key keySpec; - - public AES256Util() throws UnsupportedEncodingException { - iv = iv.substring(0, 16); - byte[] keyBytes = new byte[16]; - byte[] b = iv.getBytes("UTF-8"); - int len = b.length; - if (len > keyBytes.length) { - len = keyBytes.length; - } - System.arraycopy(b, 0, keyBytes, 0, len); - SecretKeySpec _keySpec = new SecretKeySpec(keyBytes, "AES"); - keySpec = _keySpec; + + private static String KEY; + private static byte[] SALT; + private static String IV; + + @Value("${aes256.key}") + public void setKEY(String KEY) { + AES256Util.KEY = KEY; + } + + @Value("${aes256.salt}") + public void setSALT(String SALT) throws DecoderException { + AES256Util.SALT = Hex.decodeHex(SALT.toCharArray()); + } + + @Value("${aes256.iv}") + public void setIV(String IV) { + AES256Util.IV = IV; } - //μ•”ν˜Έν™” public static String encrypt(String str) { try { - Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); - c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec((iv.getBytes()))); - byte[] encrypted = c.doFinal(str.getBytes("UTF-8")); - // String enStr = new String(Base64.encodeBase64(encrypted)); - return new java.math.BigInteger(encrypted).toString(16); - } catch (GeneralSecurityException | UnsupportedEncodingException e) { + SecretKey key = generateKey(KEY); + byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, IV, str.getBytes("UTF-8")); + return encodeHex(encrypted); + } catch (Exception e) { + throw new InternalServerErrorException(ErrorCode.ENCRYPT_FAIL); + } + } + + public static String encrypt(String str, String salt) { + try { + SecretKey key = generateKey(KEY, salt); + byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, IV, str.getBytes("UTF-8")); + return encodeHex(encrypted); + } catch (Exception e) { throw new InternalServerErrorException(ErrorCode.ENCRYPT_FAIL); } } - //λ³΅ν˜Έν™” public static String decrypt(String str) { try { - Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); - c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes())); - // byte[] byteStr = Base64.decodeBase64(str.getBytes()); - byte[] byteStr = new java.math.BigInteger(str, 16).toByteArray(); - return new String(c.doFinal(byteStr), "UTF-8"); - } catch (GeneralSecurityException | UnsupportedEncodingException e) { + SecretKey key = generateKey(KEY); + byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, IV, decodeBase64(str)); + return new String(decrypted, "UTF-8"); + } catch (Exception e) { + throw new InternalServerErrorException(ErrorCode.DECRYPT_FAIL); + } + } + + public static String decrypt(String str, String salt) { + try { + SecretKey key = generateKey(KEY, salt); + byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, IV, decodeBase64(str)); + return new String(decrypted, "UTF-8"); + } catch (Exception e) { throw new InternalServerErrorException(ErrorCode.DECRYPT_FAIL); } } @@ -61,4 +81,48 @@ public static String decrypt(String str) { public static Long userIdDecrypt(String userId) { return Long.parseLong(decrypt(userId)); } + + private static byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) throws Exception { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(encryptMode, key, new IvParameterSpec(decodeHex(iv))); + return cipher.doFinal(bytes); + } + + private static SecretKey generateKey(String passPhrase) throws Exception { + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + + // generate key with salt + PBEKeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT, 3000, 256); + SecretKey key = new SecretKeySpec(factory.generateSecret(keySpec).getEncoded(), "AES"); + + return key; + } + + private static SecretKey generateKey(String passPhrase, String salt) throws Exception { + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + + // generate custom salt + PBEKeySpec saltSpec = new PBEKeySpec(salt.toCharArray(), SALT, 3000, 128); + SecretKey saltKey = new SecretKeySpec(factory.generateSecret(saltSpec).getEncoded(), "AES"); + + // generate key with custom salt + PBEKeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), saltKey.toString().getBytes(), 3000, 256); + SecretKey key = new SecretKeySpec(factory.generateSecret(keySpec).getEncoded(), "AES"); + + return key; + } + + private static String encodeHex(byte[] bytes) { + return Hex.encodeHexString(bytes); + } + + private static byte[] decodeHex(String str) throws Exception { + return Hex.decodeHex(str.toCharArray()); + } + + private static byte[] decodeBase64(String str) { + byte[] decodeByte = Base64.decodeBase64(str); + return Base64.decodeBase64(decodeByte); + } + }