Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secure Key Manager #227

Open
hyeonjaez opened this issue Mar 26, 2024 · 0 comments
Open

Secure Key Manager #227

hyeonjaez opened this issue Mar 26, 2024 · 0 comments
Assignees
Labels
technical 기술 문서 작성

Comments

@hyeonjaez
Copy link
Member

hyeonjaez commented Mar 26, 2024

Secure Key Manager


  • 기밀 데이터(데이터베이스 접속 정보, 앱키, 비밀번호 등), 대칭키, 비대칭키와 같이 애플리케이션 서버에 저장할 경우 보안 위험에 노출될 수 있는 데이터를 중앙 집중적으로 안전하게 관리하고, 인증을 통과한 클라이언트만 접근할 수 있게 제어하는 서비스입니다.

  • 정보보호관리체계(ISMS) 인증 심사의 요구사항인 개인정보 암호화 키를 물리적으로 분리 보관하여야 한다는 요건을 만족시키기 위한 고객사/개발사를 위한 서비스이다.

  • 공개 키 암호 표준 PKCS(Public-Key Cyptography Standard) RSA 시큐리티에서 정한, 공개 키 암호에 대한 사용 방식에 대한 표준 프로토콜을 따르는 서비스

  • Personal Information Exchange Syntax Standard 개인 정보 교환 표준 사용자의 개인키, 인증 등의 저장과 교환을 위한 포맷을 설명하는 파일이다.

  • 확장자는 .p12, .pfx 를 가진다.

구조


  • 루트키와 시스템 키 라는 두개의 암호키를 내부적으로 사용한다.
  • 루트키는 시스템키를 보호하기 위해 사용
  • 시스템키는 사용자 데이터를 보호하기 위해 사용

Image

기능

  • 데이터 관리

    • 기밀 데이터 등록, 관리, 조회
    • 대칭키 생성, 관리, 회전, 데이터 암호화, 복호화, 조회
    • 비대칭키 생성, 관리, 회전, 데이터 서명, 데이터 검증, 조회
  • 데이터 접근 제어

    • 클라이언트 IPv4 주소를 사용한 데이터 접근 제어
    • 클라이언트 MAC 주소를 사용한 데이터 접근 제어
    • 클라이언트 인증서를 사용한 데이터 접근 제어
  • 승인기능

    • 데이터, 데이터 접근 제어의 변경을 승인자, 요청자로 나누어 관리

사용

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/

@hyeonjaez hyeonjaez added the technical 기술 문서 작성 label Mar 26, 2024
@hyeonjaez hyeonjaez self-assigned this Mar 26, 2024
@hyeonjaez hyeonjaez moved this to Done in My-Books-project Mar 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
technical 기술 문서 작성
Projects
Status: Done
Development

No branches or pull requests

1 participant