My-Books-projects / etc

0 stars 1 forks source link

Secure Key Manager #227

Open hyeonjaez opened 5 months ago

hyeonjaez commented 5 months ago

Secure Key Manager


구조


Image

기능

사용

1.1 인증서 관리

Image

1.2 인증서 등록

Image

1.3 인증서 파일

인증서는 .p12 파일로 다운로드 된다. 이 파일은 PKCS #12 형식을 사용하는 인증서 입니다. 이 인증서는 프로젝트의 resource 폴더에 위치 시키면 됩니다.

Image

1.4 키 관리

Image

1.5 키 추가

Image

1.6 키 상세 정보

Image

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

Image

조회 코드

@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파일에 저장한다

Image

Properties에 있는 키값을 가지고 있는 클래스를 빈으로 등록

Image

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;
    }

Reference

https://docs.nhncloud.com/ko/Security/Secure%20Key%20Manager/ko/overview/