IAM을 통한 인증 - Amazon MemoryDB

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

IAM을 통한 인증

개요

IAM 인증을 사용하면 클러스터가 Redis OSS 버전 7 이상을 사용하도록 구성된 경우 AWS IAM ID를 사용하여 MemoryDB에 대한 연결을 인증할 수 있습니다. 그러면 보안 모델이 강화되고 여러 보안 관리 작업이 단순화됩니다. IAM 인증을 사용하면 각 개별 MemoryDB 클러스터 및 MemoryDB 사용자별로 액세스 제어를 세분화해 구성하고 최소 권한 원칙을 고수할 수 있습니다. MemoryDB에 대한 IAM 인증은 Redis OSS 또는 명령에서 수명이 긴 MemoryDB 사용자 암호 대신 수명이 짧은 IAM 인증 토큰을 제공하여 작동합니다. AUTH HELLO IAM 인증 토큰에 대한 자세한 내용은 일반 참조 안내서의 서명 버전 4 서명 프로세스와 아래 코드 예제를 참조하십시오. AWS

IAM ID 및 관련 정책을 사용하여 Redis OSS 액세스를 추가로 제한할 수 있습니다. 페더레이션 자격 증명 공급자로부터 제공받은 사용자에게 바로 MemoryDB 클러스터 액세스를 부여할 수도 있습니다.

AWS IAM을 MemoryDB와 함께 사용하려면 먼저 인증 모드를 IAM으로 설정한 상태에서 MemoryDB 사용자를 생성한 다음 IAM ID를 생성하거나 재사용할 수 있습니다. IAM 자격 증명에 관련 정책이 있어야 MemoryDB 클러스터와 MemoryDB 사용자에게 memorydb:Connect 작업을 부여할 수 있습니다. 구성한 후에는 IAM 사용자 또는 역할의 자격 증명을 사용하여 IAM 인증 토큰을 생성할 수 있습니다. AWS 마지막으로 MemoryDB 클러스터 노드에 연결할 때 Redis OSS 클라이언트에서 수명이 짧은 IAM 인증 토큰을 암호로 제공해야 합니다. 자격 증명 공급자를 지원하는 Redis OSS 클라이언트는 새 연결마다 임시 자격 증명을 자동으로 생성할 수 있습니다. MemoryDB는 IAM가 활성화된 MemoryDB 사용자의 연결 요청에 IAM 인증을 수행하고 IAM과의 연결 요청을 검증합니다.

제한 사항

IAM 데이터베이스 인증을 사용할 때 다음 제한이 적용됩니다.

  • IAM 인증은 Redis OSS 엔진 버전 7.0 이상을 사용할 때 사용할 수 있습니다.

  • IAM 인증 토큰은 15분간 유효합니다. 연결 수명이 긴 경우 자격 증명 공급자 인터페이스를 지원하는 Redis OSS 클라이언트를 사용하는 것이 좋습니다.

  • MemoryDB로의 IAM 인증 연결은 12시간 후에 자동으로 연결이 해제됩니다. AUTH 또는 HELLO 명령과 새 IAM 인증 토큰을 전송하여 연결을 12시간 연장할 수 있습니다.

  • IAM 인증은 MULTI EXEC 명령에서 지원되지 않습니다.

  • 현재 IAM 인증은 모든 전역 조건 컨텍스트 키를 지원하지 않습니다. 전역 조건 컨텍스트 키에 대한 자세한 내용은 IAM 사용 설명서의 AWS 전역 조건 컨텍스트 키를 참조하세요.

설치

IAM 인증을 설정하려면:

  1. 클러스터 생성

    aws memorydb create-cluster \ --cluster-name cluster-01 \ --description "MemoryDB IAM auth application" --node-type db.r6g.large \ --engine-version 7.0 \ --acl-name open-access
  2. 아래에서와 같이, 역할에 IAM 신뢰 정책 문서를 생성하여 계정이 새 역할을 수임할 수 있도록 합니다. 정책을 trust-policy.json 파일에 저장합니다.

    { "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "sts:AssumeRole" } }
  3. 아래에서와 같이, IAM 정책 문서를 생성합니다. 정책을 policy.json 파일에 저장합니다.

    { "Version": "2012-10-17", "Statement": [ { "Effect" : "Allow", "Action" : [ "memorydb:connect" ], "Resource" : [ "arn:aws:memorydb:us-east-1:123456789012:cluster/cluster-01", "arn:aws:memorydb:us-east-1:123456789012:user/iam-user-01" ] } ] }
  4. IAM 역할을 생성합니다.

    aws iam create-role \ --role-name "memorydb-iam-auth-app" \ --assume-role-policy-document file://trust-policy.json
  5. IAM 정책을 생성합니다.

    aws iam create-policy \ --policy-name "memorydb-allow-all" \ --policy-document file://policy.json
  6. IAM 정책을 역할에 연결합니다.

    aws iam attach-role-policy \ --role-name "memorydb-iam-auth-app" \ --policy-arn "arn:aws:iam::123456789012:policy/memorydb-allow-all"
  7. IAM가 활성화된 사용자를 새로 생성합니다.

    aws memorydb create-user \ --user-name iam-user-01 \ --authentication-mode Type=iam \ --access-string "on ~* +@all"
  8. ACL을 생성하고 사용자를 연결합니다.

    aws memorydb create-acl \ --acl-name iam-acl-01 \ --user-names iam-user-01 aws memorydb update-cluster \ --cluster-name cluster-01 \ --acl-name iam-acl-01

Connecting

토큰을 암호로 연결

먼저 AWS SigV4 사전 서명된 요청을 사용하여 단수명 IAM 인증 토큰을 생성해야 합니다. 그런 다음, MemoryDB 클러스터에 연결할 때 아래 예제에서와 같이 IAM 인증 토큰을 암호로 제공합니다.

String userName = "insert user name" String clusterName = "insert cluster name" String region = "insert region" // Create a default AWS Credentials provider. // This will look for AWS credentials defined in environment variables or system properties. AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain(); // Create an IAM authentication token request and signed it using the AWS credentials. // The pre-signed request URL is used as an IAM authentication token for MemoryDB. IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userName, clusterName, region); String iamAuthToken = iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.getCredentials()); // Construct Redis OSS URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(userName, iamAuthToken) .build(); // Create a new Lettuce Redis OSS client RedisClusterClient client = RedisClusterClient.create(redisURI); client.connect();

아래는 IAMAuthTokenRequest의 정의입니다.

public class IAMAuthTokenRequest { private static final HttpMethodName REQUEST_METHOD = HttpMethodName.GET; private static final String REQUEST_PROTOCOL = "http://"; private static final String PARAM_ACTION = "Action"; private static final String PARAM_USER = "User"; private static final String ACTION_NAME = "connect"; private static final String SERVICE_NAME = "memorydb"; private static final long TOKEN_EXPIRY_SECONDS = 900; private final String userName; private final String clusterName; private final String region; public IAMAuthTokenRequest(String userName, String clusterName, String region) { this.userName = userName; this.clusterName = clusterName; this.region = region; } public String toSignedRequestUri(AWSCredentials credentials) throws URISyntaxException { Request<Void> request = getSignableRequest(); sign(request, credentials); return new URIBuilder(request.getEndpoint()) .addParameters(toNamedValuePair(request.getParameters())) .build() .toString() .replace(REQUEST_PROTOCOL, ""); } private <T> Request<T> getSignableRequest() { Request<T> request = new DefaultRequest<>(SERVICE_NAME); request.setHttpMethod(REQUEST_METHOD); request.setEndpoint(getRequestUri()); request.addParameters(PARAM_ACTION, Collections.singletonList(ACTION_NAME)); request.addParameters(PARAM_USER, Collections.singletonList(userName)); return request; } private URI getRequestUri() { return URI.create(String.format("%s%s/", REQUEST_PROTOCOL, clusterName)); } private <T> void sign(SignableRequest<T> request, AWSCredentials credentials) { AWS4Signer signer = new AWS4Signer(); signer.setRegionName(region); signer.setServiceName(SERVICE_NAME); DateTime dateTime = DateTime.now(); dateTime = dateTime.plus(Duration.standardSeconds(TOKEN_EXPIRY_SECONDS)); signer.presignRequest(request, credentials, dateTime.toDate()); } private static List<NameValuePair> toNamedValuePair(Map<String, List<String>> in) { return in.entrySet().stream() .map(e -> new BasicNameValuePair(e.getKey(), e.getValue().get(0))) .collect(Collectors.toList()); } }

보안 인증 정보 공급자와 연결

아래 코드는 IAM 인증 보안 인증 정보 공급자를 사용하여 MemoryDB로 인증하는 방법을 보여줍니다.

String userName = "insert user name" String clusterName = "insert cluster name" String region = "insert region" // Create a default AWS Credentials provider. // This will look for AWS credentials defined in environment variables or system properties. AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain(); // Create an IAM authentication token request. Once this request is signed it can be used as an // IAM authentication token for MemoryDB. IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userName, clusterName, region); // Create a Redis OSS credentials provider using IAM credentials. RedisCredentialsProvider redisCredentialsProvider = new RedisIAMAuthCredentialsProvider( userName, iamAuthTokenRequest, awsCredentialsProvider); // Construct Redis OSS URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(redisCredentialsProvider) .build(); // Create a new Lettuce Redis OSS cluster client RedisClusterClient client = RedisClusterClient.create(redisURI); client.connect();

다음은 AuthTokenRequest IAM을 자격 증명 공급자에 래핑하여 필요할 때 임시 자격 증명을 자동 생성하는 Lettuce Redis OSS 클러스터 클라이언트의 예입니다.

public class RedisIAMAuthCredentialsProvider implements RedisCredentialsProvider { private static final long TOKEN_EXPIRY_SECONDS = 900; private final AWSCredentialsProvider awsCredentialsProvider; private final String userName; private final IAMAuthTokenRequest iamAuthTokenRequest; private final Supplier<String> iamAuthTokenSupplier; public RedisIAMAuthCredentialsProvider(String userName, IAMAuthTokenRequest iamAuthTokenRequest, AWSCredentialsProvider awsCredentialsProvider) { this.userName = userName; this.awsCredentialsProvider = awsCredentialsProvider; this.iamAuthTokenRequest = iamAuthTokenRequest; this.iamAuthTokenSupplier = Suppliers.memoizeWithExpiration(this::getIamAuthToken, TOKEN_EXPIRY_SECONDS, TimeUnit.SECONDS); } @Override public Mono<RedisCredentials> resolveCredentials() { return Mono.just(RedisCredentials.just(userName, iamAuthTokenSupplier.get())); } private String getIamAuthToken() { return iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.getCredentials()); }