Autenticação com o IAM - Amazon MemoryDB para Redis

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 IAM, você pode autenticar uma conexão com o MemoryDB usando identidades IAM da AWS, quando seu cluster estiver configurado para usar a versão 7 ou superior do Redis. Isso possibilita que você fortaleça seu modelo de segurança e simplifique várias tarefas administrativas de segurança. Com a autenticação 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 IAM para MemoryDB Redis fornece um token de autenticação IAM de curta duração em vez de uma senha de usuário MemoryDB de longa duração no comando AUTH ou HELLO do Redis. 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 Redis. 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 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 IAM de curta duração como uma senha no seu cliente Redis ao se conectar ao nó do cluster do MemoryDB. Um cliente Redis 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 IAM está disponível ao usar o mecanismo Redis versão 7.0 ou superior.

  • O token de autenticação do IAM é válido por 15 minutos. Para conexões de longa duração, recomendamos usar um cliente Redis 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 do

    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. Crie 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 Redis. IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userName, clusterName, region); String iamAuthToken = iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.getCredentials()); // Construct Redis 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 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 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 Redis. IAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userName, clusterName, region); // Create a Redis credentials provider using IAM credentials. RedisCredentialsProvider redisCredentialsProvider = new RedisIAMAuthCredentialsProvider( userName, iamAuthTokenRequest, awsCredentialsProvider); // Construct Redis URL with IAM Auth credentials provider RedisURI redisURI = RedisURI.builder() .withHost(host) .withPort(port) .withSsl(ssl) .withAuthentication(redisCredentialsProvider) .build(); // Create a new Lettuce Redis cluster client RedisClusterClient client = RedisClusterClient.create(redisURI); client.connect();

Abaixo está um exemplo de um cliente de cluster do Lettuce Redis 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()); }