Autenticação com o IAM - Amazon MemoryDB

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Autenticação com o IAM

Visão geral

Com a autenticação do IAM, você pode autenticar uma conexão com o MemoryDB usando identidades do AWS IAM, quando o cluster estiver configurado para usar a versão 7 ou posterior do Valkey ou Redis OSS. Isso possibilita que você fortaleça seu modelo de segurança e simplifique várias tarefas administrativas de segurança. Com a autenticação do IAM, é possível configurar o controle de acesso refinado para cada cluster e usuário individual do MemoryDB e seguir os princípios de permissões de privilégio mínimo. A autenticação do IAM para MemoryDB fornece um token de autenticação do IAM de curta duração em vez de uma senha de usuário do MemoryDB de longa duração no comando AUTH ou HELLO. Para obter mais informações sobre o token de autenticação do IAM, consulte o processo de assinatura do Signature versão 4 no Guia de referência geral do AWS e no exemplo de código abaixo.

Você pode usar as identidades do IAM e suas políticas associadas para restringir ainda mais o acesso ao Valkey ou Redis OSS. Você também pode conceder acesso aos usuários de seus provedores de identidade federados diretamente aos clusters do MemoryDB.

Para usar o IAM com o MemoryDB da AWS, primeiro é necessário criar um usuário do MemoryDB com o modo de autenticação definido como IAM e, em seguida, criar ou reutilizar uma identidade do IAM. A identidade do IAM precisa de uma política associada para conceder a ação memorydb:Connect ao cluster do MemoryDB e ao usuário do MemoryDB. Depois de configurado, você pode criar um token de autenticação do IAM usando as credenciais da AWS do usuário ou do perfil do IAM. Por fim, você precisa fornecer o token de autenticação do IAM de curta duração como uma senha no cliente do Valkey ou Redis OSS ao se conectar ao nó do cluster do MemoryDB. Um cliente com suporte para provedor de credenciais pode gerar automaticamente as credenciais temporárias para cada nova conexão. O MemoryDB executará a autenticação do IAM para solicitações de conexão de usuários do MemoryDB habilitados para o IAM e validará as solicitações de conexão com o IAM.

Limitações

Ao usar a autenticação do IAM, as seguintes limitações se aplicam:

  • A autenticação do IAM está disponível ao usar o mecanismo Valkey ou Redis OSS versão 7.0 ou posterior.

  • O token de autenticação do IAM é válido por 15 minutos. Para conexões de longa duração, recomendamos usar um cliente do Redis OSS que ofereça suporte a uma interface de provedor de credenciais.

  • Uma conexão autenticada pelo IAM com o MemoryDB será automaticamente desconectada após 12 horas. A conexão pode ser prolongada por 12 horas enviando um comando AUTH ou HELLO com um novo token de autenticação do IAM.

  • A autenticação do IAM não tem suporte em comandos MULTI EXEC.

  • Atualmente, a autenticação do IAM não oferece suporte a todas as chaves de contexto de condição global. Para obter mais informações sobre chaves de contexto de condição global, consulte Chaves de contexto de condição global da AWS no Guia do usuário do IAM.

Configuração

Como configurar a autenticação do IAM

  1. Criar um cluster

    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. Crie um documento de política de confiança do IAM, conforme mostrado abaixo, para o perfil que permita que sua conta assuma o novo perfil. Salve a política em um arquivo chamado trust-policy.json.

    { "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "sts:AssumeRole" } }
  3. Crie um documento de política do IAM, conforme mostrado abaixo. Salve a política em um arquivo chamado 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. Criar um perfil do IAM.

    aws iam create-role \ --role-name "memorydb-iam-auth-app" \ --assume-role-policy-document file://trust-policy.json
  5. Crie a política do IAM.

    aws iam create-policy \ --policy-name "memorydb-allow-all" \ --policy-document file://policy.json
  6. Anexe a política do IAM à função.

    aws iam attach-role-policy \ --role-name "memorydb-iam-auth-app" \ --policy-arn "arn:aws:iam::123456789012:policy/memorydb-allow-all"
  7. Crie um novo usuário habilitado para o IAM.

    aws memorydb create-user \ --user-name iam-user-01 \ --authentication-mode Type=iam \ --access-string "on ~* +@all"
  8. Crie uma ACL e inclua o usuário.

    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

Conexão

Conectar com token como senha

Primeiro, é necessário gerar o token de autenticação do IAM de curta duração usando uma solicitação pré-assinada do AWS SigV4. Depois disso, forneça o token de autenticação do IAM como senha ao se conectar a um cluster do MemoryDB, conforme mostrado no exemplo abaixo.

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 URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(userName, iamAuthToken) .build(); // Create a new Lettuce client RedisClusterClient client = RedisClusterClient.create(redisURI); client.connect();

Veja abaixo a definição de 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()); } }

Conectar com o provedor de credenciais

O código abaixo mostra como se autenticar no MemoryDB usando o provedor de credenciais de autenticação do 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. 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 credentials provider using IAM credentials. RedisCredentialsProvider redisCredentialsProvider = new RedisIAMAuthCredentialsProvider( userName, iamAuthTokenRequest, awsCredentialsProvider); // Construct URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(redisCredentialsProvider) .build(); // Create a new Lettuce cluster client RedisClusterClient client = RedisClusterClient.create(redisURI); client.connect();

Veja abaixo um exemplo de um cliente de cluster do Lettuce que envolve o IAMAuthTokenRequest em um provedor de credenciais para gerar automaticamente credenciais temporárias quando necessário.

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