기밀 데이터(데이터베이스 접속 정보, 앱키, 비밀번호 등), 대칭키, 비대칭키와 같이 애플리케이션 서버에 저장할 경우 보안 위험에 노출될 수 있는 데이터를 중앙 집중적으로 안전하게 관리하고, 인증을 통과한 클라이언트만 접근할 수 있게 제어하는 서비스입니다.
정보보호관리체계(ISMS) 인증 심사의 요구사항인 개인정보 암호화 키를 물리적으로 분리 보관하여야 한다는 요건을 만족시키기 위한 고객사/개발사를 위한 서비스이다.
공개 키 암호 표준 PKCS(Public-Key Cyptography Standard) RSA 시큐리티에서 정한, 공개 키 암호에 대한 사용 방식에 대한 표준 프로토콜을 따르는 서비스
Personal Information Exchange Syntax Standard 개인 정보 교환 표준 사용자의 개인키, 인증 등의 저장과 교환을 위한 포맷을 설명하는 파일이다.
확장자는 .p12, .pfx 를 가진다.
구조
루트키와 시스템 키 라는 두개의 암호키를 내부적으로 사용한다.
루트키는 시스템키를 보호하기 위해 사용
시스템키는 사용자 데이터를 보호하기 위해 사용
기능
데이터 관리
기밀 데이터 등록, 관리, 조회
대칭키 생성, 관리, 회전, 데이터 암호화, 복호화, 조회
비대칭키 생성, 관리, 회전, 데이터 서명, 데이터 검증, 조회
데이터 접근 제어
클라이언트 IPv4 주소를 사용한 데이터 접근 제어
클라이언트 MAC 주소를 사용한 데이터 접근 제어
클라이언트 인증서를 사용한 데이터 접근 제어
승인기능
데이터, 데이터 접근 제어의 변경을 승인자, 요청자로 나누어 관리
사용
1.1 인증서 관리
1.2 인증서 등록
1.3 인증서 파일
인증서는 .p12 파일로 다운로드 된다.
이 파일은 PKCS #12 형식을 사용하는 인증서 입니다.
이 인증서는 프로젝트의 resource 폴더에 위치 시키면 됩니다.
1.4 키 관리
1.5 키 추가
1.6 키 상세 정보
2. 프로젝트 로직 설정
2.1 DTO 클래스
@Getter
public class KeyResponseDto {
private Header header;
private Body body;
@Getter
@NoArgsConstructor
public static class Body {
private String secret;
}
@Getter
@NoArgsConstructor
public static class Header {
private Integer resultCode;
private String resultMessage;
private boolean isSuccessful;
}
}
2.2 API
기밀 데이터 조회 api
조회 코드
@Configuration
public class KeyConfig {
private final KeyProperties keyProperties;
@Autowired
public KeyConfig(KeyProperties keyProperties) {
this.keyProperties = keyProperties;
}
public String keyStore(String keyId) {
try {
KeyStore clientStore = KeyStore.getInstance("PKCS12");
InputStream result = new ClassPathResource("my-books.p12").getInputStream();
clientStore.load(result, keyProperties.getPassword().toCharArray());
SSLContext sslContext = SSLContextBuilder.create()
.setProtocol("TLS")
.loadKeyMaterial(clientStore, keyProperties.getPassword().toCharArray())
.loadTrustMaterial(new TrustSelfSignedStrategy())
.build();
SSLConnectionSocketFactory sslConnectionSocketFactory =
new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
RestTemplate restTemplate = new RestTemplate(requestFactory);
URI uri = UriComponentsBuilder
.fromUriString(keyProperties.getUrl())
.path(keyProperties.getPath())
.encode()
.build()
.expand(keyProperties.getAppKey(), keyId)
.toUri();
return Objects.requireNonNull(restTemplate.exchange(uri,
HttpMethod.GET,
new HttpEntity<>(headers),
KeyResponseDto.class)
.getBody())
.getBody()
.getSecret();
} catch (KeyStoreException | IOException | CertificateException
| NoSuchAlgorithmException
| UnrecoverableKeyException
| KeyManagementException e) {
throw new KeyMangerException(e.getMessage());
}
}
}
2.3 키 복호화 하여 사용
키값을 properties파일에 저장한다
Properties에 있는 키값을 가지고 있는 클래스를 빈으로 등록
keyConfig.keyStore(databaseProperties.getUrl())를 호출하여 실제 값을 복호화 하여 가져온다
@Configuration
public class DatabaseConfig {
private final KeyConfig keyConfig;
private final DatabaseProperties databaseProperties;
@Autowired
public DatabaseConfig(KeyConfig keyConfig, DatabaseProperties databaseProperties) {
this.keyConfig = keyConfig;
this.databaseProperties = databaseProperties;
}
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl(keyConfig.keyStore(databaseProperties.getUrl()));
dataSource.setUsername(keyConfig.keyStore(databaseProperties.getUserName()));
dataSource.setPassword(keyConfig.keyStore(databaseProperties.getPassword()));
dataSource.setInitialSize(databaseProperties.getInitialSize());
dataSource.setMaxTotal(databaseProperties.getMaxTotal());
dataSource.setMinIdle(databaseProperties.getMinIdle());
dataSource.setMaxIdle(databaseProperties.getMaxIdle());
dataSource.setMaxWaitMillis(databaseProperties.getMaxWait());
dataSource.setTestOnBorrow(true);
dataSource.setTestOnReturn(true);
dataSource.setTestWhileIdle(true);
return dataSource;
}
Secure Key Manager
기밀 데이터(데이터베이스 접속 정보, 앱키, 비밀번호 등), 대칭키, 비대칭키와 같이 애플리케이션 서버에 저장할 경우 보안 위험에 노출될 수 있는 데이터를 중앙 집중적으로 안전하게 관리하고, 인증을 통과한 클라이언트만 접근할 수 있게 제어하는 서비스입니다.
정보보호관리체계(ISMS) 인증 심사의 요구사항인 개인정보 암호화 키를 물리적으로 분리 보관하여야 한다는 요건을 만족시키기 위한 고객사/개발사를 위한 서비스이다.
공개 키 암호 표준 PKCS(Public-Key Cyptography Standard) RSA 시큐리티에서 정한, 공개 키 암호에 대한 사용 방식에 대한 표준 프로토콜을 따르는 서비스
Personal Information Exchange Syntax Standard 개인 정보 교환 표준 사용자의 개인키, 인증 등의 저장과 교환을 위한 포맷을 설명하는 파일이다.
확장자는 .p12, .pfx 를 가진다.
구조
기능
데이터 관리
데이터 접근 제어
승인기능
사용
1.1 인증서 관리
1.2 인증서 등록
1.3 인증서 파일
인증서는 .p12 파일로 다운로드 된다. 이 파일은 PKCS #12 형식을 사용하는 인증서 입니다. 이 인증서는 프로젝트의 resource 폴더에 위치 시키면 됩니다.
1.4 키 관리
1.5 키 추가
1.6 키 상세 정보
2. 프로젝트 로직 설정
2.1 DTO 클래스
2.2 API
기밀 데이터 조회 api
조회 코드
2.3 키 복호화 하여 사용
키값을 properties파일에 저장한다
Properties에 있는 키값을 가지고 있는 클래스를 빈으로 등록
keyConfig.keyStore(databaseProperties.getUrl())를 호출하여 실제 값을 복호화 하여 가져온다
Reference
https://docs.nhncloud.com/ko/Security/Secure%20Key%20Manager/ko/overview/