기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
AWS Secrets Manager를 사용한 보안 인증 정보 관리
작성자: Durga Prasad Cheepuri(AWS)
요약
이 패턴은 AWS Secrets Manager를 사용하여 Java Spring 애플리케이션의 데이터베이스 보안 인증 정보를 동적으로 가져오는 과정을 안내합니다.
과거에는 데이터베이스에서 정보를 검색하는 사용자 지정 애플리케이션을 생성하면 일반적으로 데이터에 액세스하기 위한 보안 인증 정보(보안 암호)을 애플리케이션에 직접 포함시켜야 했습니다. 보안 인증 정보를 교체할 때는 시간을 투자하여 새 보안 인증 정보를 사용하도록 애플리케이션을 업데이트한 다음, 업데이트된 애플리케이션을 배포해야 했습니다. 보안 인증 정보를 공유하는 애플리케이션이 여러 개 있는데 이 중 하나를 업데이트하지 못한 경우 해당 애플리케이션이 침해를 당할 수 있었습니다. 이러한 위험 때문에 많은 고객들은 정기적으로 보안 인증 정보를 교체하지 않기로 결정하며, 이 위험 대신 다른 위험에 직면하게 됩니다.
Secrets Manager는 코드의 암호를 포함해 하드 코딩된 보안 인증 정보를 프로그래밍 방식으로 보안 암호를 검색하도록 하는 API 직접 호출로 바꿀 수 있습니다. 이렇게 하면 보안 암호가 해당 위치에 있지 않기 때문에 여러분의 코드를 검사하는 누군가에 의해 보안 암호가 손상되지 않도록 방지할 수 있습니다. 또한 사용자가 지정한 일정에 따라 Secrets Manager가 자동으로 보안 암호를 교체하도록 구성할 수 있습니다. 따라서 단기 보안 암호로 장기 보안 암호를 교체할 수 있어 손상 위험이 크게 줄어듭니다. 자세한 내용은 AWS Secrets Manager 설명서를 참조하세요.
사전 조건 및 제한 사항
사전 조건
Secrets Manager에 대한 액세스 권한이 있는 AWS 계정
Java Spring 애플리케이션
아키텍처
소스 기술 스택
application.properties 파일에서 관리되는 DB 보안 인증 정보를 사용하여 데이터베이스에 액세스하는 코드를 포함하는 Java Spring 애플리케이션입니다.
대상 기술 스택
Secrets Manager에서 관리되는 DB 보안 인증 정보를 사용하여 데이터베이스에 액세스하는 코드를 포함하는 Java Spring 애플리케이션입니다. application.properties 파일에 Secrets Manager의 비밀이 보관되어 있습니다.
Secrets Manager를 애플리케이션과 통합

도구
Secrets Manager – AWS Secrets Manager는 비밀을 보다 쉽게 관리할 수 있게 해주는 AWS 서비스입니다. 보안 암호는 데이터베이스 보안 인증 정보, 암호, 타사 API 키 및 임의 텍스트가 될 수 있습니다. Secrets Manager 콘솔, Secrets Manager 명령줄 인터페이스(CLI) 또는 Secrets Manager API 및 SDK를 사용하여 중앙에서 이러한 암호를 저장하고 해당 암호에 대한 액세스를 제어할 수 있습니다.
에픽
작업 | 설명 | 필요한 기술 |
---|---|---|
DB 보안 인증 정보를 Secrets Manager에 암호로 저장합니다. | Secrets Manager 설명서의 암호 생성에 나와 있는 단계에 따라 Secrets Manager에 Amazon Relational Database Service(RDS) 또는 기타 DB 보안 인증 정보를 암호로 저장하세요. | 시스템 관리자 |
Spring 애플리케이션이 Secrets Manager에 액세스할 수 있도록 권한을 설정합니다. | Java Spring 애플리케이션이 Secrets Manager를 사용하는 방식에 따라 적절한 권한을 설정합니다. 비밀에 대한 액세스를 제어하려면 Secrets Manager 설명서의 ID 기반 정책(IAM 정책) 및 Secrets Manager용 ABAC 사용 및 Secrets Manager의 리소스 기반 정책 사용 섹션에 제공된 정보를 기반으로 정책을 생성하세요. Secrets Manager 설명서의 암호 값 검색 섹션의 단계를 따르세요. | 시스템 관리자 |
작업 | 설명 | 필요한 기술 |
---|---|---|
Secrets Manager를 사용하려면 JAR 종속성을 추가하세요. | 자세한 내용은 추가 정보 섹션을 참조하세요. | Java 개발자 |
Spring 애플리케이션에 암호의 세부 정보를 추가합니다. | application.properties 파일을 비밀 이름, 엔드포인트, AWS 리전으로 업데이트합니다. 예제를 보려면 추가 정보 섹션을 참조하세요. | Java 개발자 |
Java에서 DB 보안 인증 정보 검색 코드를 업데이트하세요. | 애플리케이션에서 DB 보안 인증 정보를 가져오는 Java 코드를 업데이트하여 Secrets Manager에서 해당 세부 정보를 가져옵니다. 예제 코드는 추가 정보 섹션을 참조하세요. | Java 개발자 |
관련 리소스
추가 정보
Secrets Manager 사용을 위한 JAR 종속성 추가
Maven:
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-secretsmanager</artifactId>
<version>1.11. 355 </version>
Gradle:
compile group: 'com.amazonaws', name: 'aws-java-sdk-secretsmanager', version: '1.11.355'
application.properties 파일에 암호의 세부 정보 업데이트
spring.aws.secretsmanager.secretName=postgres-local
spring.aws.secretsmanager.endpoint=secretsmanager.us-east-1.amazonaws.com
spring.aws.secretsmanager.region=us-east-1
Java에서 DB 보안 인증 정보 검색 코드 업데이트
String secretName = env.getProperty("spring.aws.secretsmanager.secretName");
String endpoints = env.getProperty("spring.aws.secretsmanager.endpoint");
String AWS Region = env.getProperty("spring.aws.secretsmanager.region");
AwsClientBuilder.EndpointConfiguration config = new AwsClientBuilder.EndpointConfiguration(endpoints, AWS Region);
AWSSecretsManagerClientBuilder clientBuilder = AWSSecretsManagerClientBuilder.standard();
clientBuilder.setEndpointConfiguration(config);
AWSSecretsManager client = clientBuilder.build();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode secretsJson = null;
ByteBuffer binarySecretData;
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest().withSecretId(secretName);
GetSecretValueResult getSecretValueResponse = null;
try {
getSecretValueResponse = client.getSecretValue(getSecretValueRequest);
}
catch (ResourceNotFoundException e) {
log.error("The requested secret " + secretName + " was not found");
}
catch (InvalidRequestException e) {
log.error("The request was invalid due to: " + e.getMessage());
}
catch (InvalidParameterException e) {
log.error("The request had invalid params: " + e.getMessage());
}
if (getSecretValueResponse == null) {
return null;
} // Decrypted secret using the associated KMS key // Depending on whether the secret was a string or binary, one of these fields will be populated
String secret = getSecretValueResponse.getSecretString();
if (secret != null) {
try {
secretsJson = objectMapper.readTree(secret);
}
catch (IOException e) {
log.error("Exception while retrieving secret values: " + e.getMessage());
}
}
else {
log.error("The Secret String returned is null");
return null;
}
String host = secretsJson.get("host").textValue();
String port = secretsJson.get("port").textValue();
String dbname = secretsJson.get("dbname").textValue();
String username = secretsJson.get("username").textValue();
String password = secretsJson.get("password").textValue();
}