Skip to content

Commit

Permalink
Merge PR(#9) feature/keymanager - Secret Key Manager
Browse files Browse the repository at this point in the history
  • Loading branch information
woody35545 authored Apr 15, 2024
2 parents ba1e5d4 + c4e2158 commit d746c15
Show file tree
Hide file tree
Showing 12 changed files with 443 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ build/

### VS Code ###
.vscode/

### Key Files ###
*.p12

### yaml ###
application-local.yml
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,12 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;


@ConfigurationPropertiesScan
@SpringBootApplication
@EnableDiscoveryClient
public class AuthenticationApiApplication {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.t3t.authenticationapi.config;

import com.t3t.authenticationapi.keymanager.properties.SecretKeyManagerProperties;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.time.Duration;


@Configuration
public class RestTemplateConfig {

/**
* Secret Key Manager 인증서를 사용하여 요청을 보내기 위한 RestTemplate 빈 등록
* @author woody35545(구건모)
*/
@Bean
@Profile("!local")
public RestTemplate sslRestTemplate(SecretKeyManagerProperties secretKeyManagerProperties)
throws KeyStoreException, IOException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, CertificateException {

KeyStore keyStore = KeyStore.getInstance(secretKeyManagerProperties.getCertKeyType());

keyStore.load(secretKeyManagerProperties.getCertKey().getInputStream(),
secretKeyManagerProperties.getPassword().toCharArray());

RestTemplate sslRestTemplate = new RestTemplateBuilder()
.setConnectTimeout(Duration.ofSeconds(5))
.setConnectTimeout(Duration.ofSeconds(5))
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.build();

sslRestTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClients.custom()
.setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContextBuilder.create()
.loadKeyMaterial(keyStore, secretKeyManagerProperties.getPassword().toCharArray()).build())).build()));

return sslRestTemplate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.t3t.authenticationapi.exception;

/**
* Secret Key Manager API 요청이 실패한 경우 발생하는 예외
*/
public class SecretKeyManagerApiRequestFailedException extends RuntimeException{
public SecretKeyManagerApiRequestFailedException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.t3t.authenticationapi.keymanager.model.response;

import lombok.Getter;

/**
* Secret Key Manager API의 응답 형식을 정의한 클래스
* @author woody35545(구건모)
*/
@Getter
public class SecretKeyManagerResponse {
private SecretKeyManagerResponseHeaderPartDto header;
private SecretKeyManagerResponseBodyPartDto body;

@Getter
public static class SecretKeyManagerResponseHeaderPartDto {
private int resultCode;
private String resultMessage;
private String isSuccessful;
}

@Getter
public static class SecretKeyManagerResponseBodyPartDto {
private String secret;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.t3t.authenticationapi.keymanager.properties;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.Resource;

/**
* Secret Key Manager 에서 사용될 속성을 저장하는 프로퍼티 클래스
* @author woody35545(구건모)
*/
@Getter
@Setter
@Profile("!local")
@ConfigurationProperties(prefix = "t3t.secret-key-manager")
public class SecretKeyManagerProperties {
private String appKey;
private String password;
private String certKeyType;
private String certKeyPath;
@Value("${t3t.secretKeyManager.certKeyPath}")
private Resource certKey;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.t3t.authenticationapi.keymanager.properties;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

/**
* Secret Key Manager 에 등록된 기밀 데이터의 key id를 저장하는 프로퍼티 클래스
* @author woody35545(구건모)
*/
@Profile("!local")
@Getter
@Component
public class SecretKeyProperties {
@Value("${t3t.secretKeyManager.secrets.databaseServerIpAddress.keyId}")
private String databaseIpAddressKeyId;
@Value("${t3t.secretKeyManager.secrets.databaseServerPort.keyId}")
private String databasePortKeyId;
@Value("${t3t.secretKeyManager.secrets.databaseServerUsername.keyId}")
private String databaseNameKeyId;
@Value("${t3t.secretKeyManager.secrets.databaseName.keyId}")
private String databaseUsernameKeyId;
@Value("${t3t.secretKeyManager.secrets.databaseServerPassword.keyId}")
private String databasePasswordKeyId;
@Value("${t3t.secretKeyManager.secrets.jwtSecretKey.keyId}")
private String jwtSecretKeyId;
@Value("${t3t.secretKeyManager.secrets.redisServerIpAddress.keyId}")
private String redisIpAddressKeyId;
@Value("${t3t.secretKeyManager.secrets.redisServerPort.keyId}")
private String redisPortKeyId;
@Value("${t3t.secretKeyManager.secrets.redisServerPassword.keyId}")
private String redisPasswordKeyId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.t3t.authenticationapi.keymanager.service;

import com.t3t.authenticationapi.exception.SecretKeyManagerApiRequestFailedException;
import com.t3t.authenticationapi.keymanager.model.response.SecretKeyManagerResponse;
import com.t3t.authenticationapi.keymanager.properties.SecretKeyManagerProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Profile;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

/**
* Secret Key Manager 에 등록된 Secret 값을 가져오기 위한 서비스 클래스
*
* @author woody35545(구건모)
*/
@Profile("!local")
@Slf4j
@Service
@RequiredArgsConstructor
public class SecretKeyManagerService {
private final RestTemplate sslRestTemplate;
private final SecretKeyManagerProperties secretKeyManagerProperties;

private static final ParameterizedTypeReference<SecretKeyManagerResponse> secretKeyManagerResponseTypeReference
= new ParameterizedTypeReference<SecretKeyManagerResponse>() {
};

/**
* Secret Key Manager 에서 Secret 값 조회
*
* @param keyId 조회할 Key ID(Secret Key Manager 에 등록된 기밀 데이터의 Key ID)
* @return Secret Key Manager 에서 조회한 Secret 값을 String 형태로 반환
* @author woody35545(구건모)
*/
public String getSecretValue(String keyId) {

HttpEntity<SecretKeyManagerResponse> response =
sslRestTemplate.exchange("https://api-keymanager.nhncloudservice.com/keymanager/v1.0/appkey/{appKey}/secrets/{keyId}",
HttpMethod.GET, null, SecretKeyManagerResponse.class,
secretKeyManagerProperties.getAppKey(), keyId);

SecretKeyManagerResponse responseBody = response.getBody();

if (responseBody == null) {
throw new SecretKeyManagerApiRequestFailedException("Response body is null.");
}

if (responseBody.getHeader() == null || responseBody.getBody() == null || !responseBody.getHeader().getIsSuccessful().equals("true") || responseBody.getBody().getSecret() == null) {
log.error("Secret Key Manager API response: {}", responseBody);
throw new SecretKeyManagerApiRequestFailedException(new StringBuilder().append("Fail to request Secret Key Manager API (Key ID:").append(keyId).append(")").toString());
}

return responseBody.getBody().getSecret();
}
}
29 changes: 28 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,31 @@ spring:

logging:
level:
org.hibernate.SQL: debug
org.hibernate.SQL: debug

t3t:
secretKeyManager:
certKeyPath: ${secretKeyManagerCertKeyPath}
certKeyType: ${secretKeyManagerCertKeyType}
appKey: ${secretKeyManagerAppKey}
password: ${secretKeyManagerPassword}

secrets:
databaseName:
keyId: "e3203972cbf04433b90c752f695d5736"
databaseServerIpAddress:
keyId: "62911d2c30064812b2b2c97a8dd90782"
databaseServerPort:
keyId: "48e191996aa748938a1edb62652336f4"
databaseServerUsername:
keyId: "f008c1d3f87f4f88ae57bd03871eb10d"
databaseServerPassword:
keyId: "8a65684780224384a681c3e9035ca7d6"
jwtSecretKey:
keyId: "e4f4d4a87ccd49e594f03dffee9fa58d"
redisServerIpAddress:
keyId: "10ee8b6140cc49ffa9e7a7c8a2924a3e"
redisServerPort:
keyId: "0582f8b117604b7d86e9f3ff26931cde"
redisServerPassword:
keyId: "ec1eb8e0706e402cbec8487cbcb86564"
Loading

0 comments on commit d746c15

Please sign in to comment.