π GitHubμ λΉλ°λ²νΈκ° μ¬λΌκ°λ€λ©΄? νκ²½ λ³μλ‘ ν΄κ²°νκΈ°
π± μ΄λ° κ²½ν μμΌμ κ°μ?
# application.yml
spring:
datasource:
password: myRealPassword123! # π¨ μ΄κ±° κ·Έλλ‘ GitHubμ...?
μ½λλ₯Ό μμ±νλ€ λ³΄λ©΄ DB λΉλ°λ²νΈ, API ν€, μΈμ¦μ λΉλ°λ²νΈ λ± λ―Όκ°ν μ 보λ₯Ό μ€μ νμΌμ λ£μ΄μΌ ν λκ° μμ΅λλ€.
νμ§λ§ μ΄λλ‘ GitHubμ μ¬λ¦¬λ©΄? π₯ 보μ μ¬κ³ μ§νμ λλ€.
π‘ ν΄κ²°μ± : νκ²½ λ³μ(Environment Variable) μΉν
Spring Bootλ ${νκ²½λ³μλͺ
:κΈ°λ³Έκ°} λ¬Έλ²μΌλ‘ νκ²½ λ³μλ₯Ό μλμΌλ‘ μΉνν΄μ€λλ€.
μλ μ리
password: ${MY_SECRET_PASSWORD:defaultPassword}
-
μ΄μ체μ νκ²½λ³μ
MY_SECRET_PASSWORDκ° μμΌλ©΄ β κ·Έ κ° μ¬μ© -
μμΌλ©΄ β κΈ°λ³Έκ°
defaultPasswordμ¬μ©
μ΄λ κ² νλ©΄:
- β μμ€μ½λμλ μ§μ§ λΉλ°λ²νΈκ° μμ
- β GitHubμ μ¬λ €λ μμ
- β μλ²λ§λ€ λ€λ₯Έ λΉλ°λ²νΈ μ¬μ© κ°λ₯
π Step 1: application.yml μ€μ
IRC μλ²μ SSL μΈμ¦μ λΉλ°λ²νΈλ₯Ό νκ²½ λ³μλ‘ κ΄λ¦¬ν΄λ΄ μλ€.
irc:
ssl:
keystore-path: classpath:keystone.p12
keystore-password: ${IRC_KEYSTORE_PASSWORD:password} # π ν΅μ¬!
keystore-type: PKCS12
π μ½λ μ€λͺ
-
IRC_KEYSTORE_PASSWORD: μ΄μ체μ νκ²½λ³μ μ΄λ¦ -
password: λ‘컬 κ°λ°μ© κΈ°λ³Έκ° (μ΄μ νκ²½μμλ μ λ μ¬μ© μ λ¨)
π Step 2: Java μ½λ μμ± (SslConfig.java)
νκ²½ λ³μλ‘ λ°μ κ°μ μ€μ λ‘ μ¬μ©νλ μ½λμ λλ€.
package com.ircproject.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.InputStream;
import java.security.KeyStore;
@Configuration
public class SslConfig {
@Value("${irc.ssl.keystore-path}")
private String keystorePath;
@Value("${irc.ssl.keystore-password}") // π νκ²½λ³μ μλ μ£Όμ
private String keystorePassword;
@Value("${irc.ssl.keystore-type}")
private String keystoreType;
private final ResourceLoader resourceLoader;
public SslConfig(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Bean
public SSLContext sslContext() throws Exception {
// 1. Keystore λ‘λ (JAR λ΄λΆ νμΌλ μ½μ μ μλλ‘ ResourceLoader μ¬μ©)
KeyStore keyStore = KeyStore.getInstance(keystoreType);
Resource resource = resourceLoader.getResource(keystorePath);
try (InputStream stream = resource.getInputStream()) {
keyStore.load(stream, keystorePassword.toCharArray());
}
// 2. KeyManager μ΄κΈ°ν (μλ² μ λΆμ¦)
KeyManagerFactory kmf = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm()
);
kmf.init(keyStore, keystorePassword.toCharArray());
// 3. TrustManager μ΄κΈ°ν (ν΄λΌμ΄μΈνΈ κ²μ¦)
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm()
);
tmf.init(keyStore);
// 4. SSLContext μμ±
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return sslContext;
}
}
π‘ μ ResourceLoaderλ₯Ό μ¬μ©νλμ?
μΌλ° File ν΄λμ€λ JARλ‘ ν¨ν€μ§νλ©΄ μλνμ§ μμ΅λλ€.
ResourceLoaderλ₯Ό μ¬μ©νλ©΄ JAR λ΄λΆμ νμΌλ μ μμ μΌλ‘ μ½μ μ μμ΅λλ€.
π₯οΈ Step 3: λ‘컬μμ μ€ννκΈ°
λ°©λ² A: IntelliJ IDEA
- Run/Debug Configurations ν΄λ¦
-
Environment variables μ
λ ₯μ°½μ μΆκ°:
IRC_KEYSTORE_PASSWORD=mySecretPassword123 - Apply β Run
![IntelliJ νκ²½λ³μ μ€μ μμ]
λ°©λ² B: ν°λ―Έλ (Mac/Linux)
# νκ²½λ³μ μ€μ ν μ€ν
export IRC_KEYSTORE_PASSWORD=mySecretPassword123
./gradlew bootRun
λλ ν μ€λ‘:
# μΌνμ± νκ²½λ³μ μ€μ
IRC_KEYSTORE_PASSWORD=mySecretPassword123 ./gradlew bootRun
λ°©λ² C: ν°λ―Έλ (Windows)
set IRC_KEYSTORE_PASSWORD=mySecretPassword123
gradlew.bat bootRun
βοΈ Step 4: AWS/μ΄μ νκ²½μμ μ€ννκΈ°
AWS EC2 μμ
# ~/.bashrc λλ ~/.profileμ μΆκ°
export IRC_KEYSTORE_PASSWORD=μ΄μνκ²½_μ§μ§_λΉλ°λ²νΈ
# μλ² μ€ν
java -jar irc-server.jar
Docker μμ
# Dockerfile
FROM openjdk:17-jdk-slim
COPY build/libs/irc-server.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
# μ€ν μ νκ²½λ³μ μ£Όμ
docker run -e IRC_KEYSTORE_PASSWORD=μ΄μλΉλ°λ²νΈ my-irc-server
Kubernetes μμ
# deployment.yaml
apiVersion: v1
kind: Secret
metadata:
name: irc-secrets
type: Opaque
stringData:
keystorePassword: "μ΄μλΉλ°λ²νΈ"
---
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: irc-server
env:
- name: IRC_KEYSTORE_PASSWORD
valueFrom:
secretKeyRef:
name: irc-secrets
key: keystorePassword
β μ΄λ κ² νλ©΄ μ»λ 3κ°μ§ μ΄μ
| νλͺ© | μ€λͺ |
|---|---|
| π 보μ | GitHubμ λΉλ°λ²νΈκ° μ λ λ ΈμΆλμ§ μμ |
| π οΈ μ μ§λ³΄μμ± | νκ²½λ³λ‘ λ€λ₯Έ μ€μ μ½κ² μ μ© κ°λ₯ |
| π λ°°ν¬ μμ μ± | JAR ν¨ν€μ§ μμλ μ μ μλ |
π‘ μΆκ° ν
1οΈβ£ .gitignoreμ μΈμ¦μ νμΌ μΆκ°
# Security / Secrets
*.p12
*.jks
*.key
*.pem
src/main/resources/keystone.p12
2οΈβ£ μ¬λ¬ νκ²½λ³μ νλ²μ μ€μ
# .env νμΌ μμ± (Gitμλ μ¬λ¦¬μ§ λ§ κ²!)
IRC_KEYSTORE_PASSWORD=myPassword
DB_PASSWORD=dbPassword
API_KEY=myApiKey
# νκ²½λ³μ λ‘λ ν μ€ν
export $(cat .env | xargs) && ./gradlew bootRun
3οΈβ£ Spring Profileλ³λ‘ λ€λ₯Έ νκ²½λ³μ μ¬μ©
# application-dev.yml
irc:
ssl:
keystore-password: ${IRC_KEYSTORE_PASSWORD:devPassword}
# application-prod.yml
irc:
ssl:
keystore-password: ${IRC_KEYSTORE_PASSWORD} # κΈ°λ³Έκ° μμ (νμ!)
β οΈ μ£Όμμ¬ν
-
κΈ°λ³Έκ°μ λ무 μ½κ² λ§λ€μ§ λ§μΈμ
-
password,1234κ°μ κΈ°λ³Έκ°μ μνν©λλ€ - κ°λ° νκ²½μ©μΌλ‘λ§ μ¬μ©νκ³ , μ΄μμμλ λ°λμ νκ²½λ³μ μ€μ
-
-
νκ²½λ³μ μ΄λ¦μ λͺ
ννκ²
- β
PASSWORD(λ무 μΌλ°μ ) - β
IRC_KEYSTORE_PASSWORD(λͺ νν¨)
- β
-
λ―Όκ°ν μ 보λ μ λ λ‘κ·Έμ λ¨κΈ°μ§ λ§μΈμ
// β μν log.info("Password: {}", keystorePassword); // β μμ log.info("SSL Context initialized successfully");
π― λ§λ¬΄λ¦¬
νκ²½ λ³μ μΉν κΈ°λ₯μ νμ 보μ ν¨ν΄μ λλ€.
μ§κΈ λΉμ₯ νλ‘μ νΈμ application.ymlμ νμΈν΄λ³΄μΈμ.
λΉλ°λ²νΈκ° νλμ½λ©λμ΄ μλ€λ©΄, μ΄ κΈμ μ°Έκ³ ν΄μ λ°λ‘ μμ νμκΈΈ λ°λλλ€! π