[{"data":1,"prerenderedAt":46},["ShallowReactive",2],{"snippet-lambda-function-connect-memorydb-iam":3},{"id":4,"title":5,"contributors":6,"description":8,"extension":9,"gitHub":10,"introBox":13,"languages":17,"meta":20,"resources":21,"services":22,"snippets":25,"stem":42,"tags":43,"type":44,"__hash__":45},"snippets\u002Fsnippets\u002Flambda-function-connect-memorydb-iam.json","Connect to Amazon MemoryDB for Redis from AWS Lambda",[7],"content\u002Fcontributors\u002Fjosh-kahn.json","This snippet demonstrates how to conenct to an Amazon MemoryDB for Redis cluster from an AWS Lambda function with IAM authentication. This snippet is valid for Redis engine version 7.0+.","json",{"template":11},{"repoURL":12},"https:\u002F\u002Fgithub.com\u002Faws-samples\u002Fserverless-snippets\u002Ftree\u002Fmain\u002Flambda-function-connect-memorydb-iam",{"headline":14,"text":15},"How it works",[16],"Amazon MemoryDB for Redis is a durable database with microsecond reads, low single-digit millisecond writes, scalability, and enterprise security. Connect to a MemoryDB cluster using IAM authentication.",[18,19],"TypeScript","Java",{},null,[23,24],"lambda-event-functions","memorydb",[26],{"title":27,"codeTabs":28},"Runtimes",[29,36],{"id":18,"title":30,"description":31,"snippets":32},"Copy the code into your Lambda function","Follow the AWS Lambda instructions for packaging with dependencies and uploading in .zip format. This snippet uses the ioredis library.",[33],{"language":34,"code":35},"ts","\u002F\u002F Snippet uses the ioredis library, but other redis clients will also work\nimport { Cluster } from 'ioredis';\nimport { SignatureV4 } from '@aws-sdk\u002Fsignature-v4';\nimport { Sha256 } from '@aws-crypto\u002Fsha256-js';\nimport { formatUrl } from '@aws-sdk\u002Futil-format-url';\nimport { fromNodeProviderChain } from '@aws-sdk\u002Fcredential-providers';\n\nlet redisClient: Cluster;\n\n\u002F**\n * MemoryDB (and Elasticache) with Redis v7.0+ offer IAM authentication. In this mode, pass\n * the username with a presigned URL as the password. This function generates the presigned\n * URL, which acts as an authentication token. Note that this token expires after 15 minutes\n * and will need to be refreshed.\n * \n * Snippet assumes that cache parameters are included as environment variables. Note that\n * cache cluster name is distinct from endpoint.\n *\u002F\n\nconst getAuthToken = async(): Promise&#60;string&#62; =&#62; {\n    const signer = new SignatureV4({\n      service: 'memorydb',\n      region: process.env['AWS_REGION'],\n      credentials: fromNodeProviderChain(),\n      sha256: Sha256\n    });\n  \n    const protocol = 'https';\n  \n    const presigned = await signer.presign({\n      method: 'GET',\n      protocol,\n      hostname: process.env['CACHE_CLUSTER_NAME'],\n      path: '\u002F',\n      query: {\n        Action: 'connect',\n        User: process.env['CACHE_USERNAME']\n      },\n      headers: {\n        host: process.env['CACHE_CLUSTER_NAME']\n      }\n    }, { expiresIn: 900 });\n  \n    const token = formatUrl(presigned).replace(`${protocol}:\u002F\u002F`, '');\n  \n    return token;\n  };\n\n  redisClient = new Cluster(\n    [\n      {\n        host: process.env['CACHE_ENDPOINT'],\n        port: parseInt(process.env['CACHE_PORT']), \u002F\u002F usually 6379\n      }\n    ],\n    {\n      \u002F\u002F dnsLookup resolves an issue with TLS encryption and MemoryDB clusters\n      \u002F\u002F see https:\u002F\u002Fgithub.com\u002Fredis\u002Fioredis#special-note-aws-elasticache-clusters-with-tls\n      dnsLookup: (address, callback) =&#62; callback(null, address),\n      redisOptions: {\n        username: process.env['CACHE_USERNAME'],\n        password: await getAuthToken(),\n        tls: {}\n      }\n    }\n  );\n}\n\n\u002F\u002F set a value in the cache, see ioredis docs for other options\nawait redisClient.set(\"foo\", \"bar\");\n\n\u002F\u002F get the value back\nconst result = redisClient.get(\"foo\");",{"id":19,"title":30,"description":37,"snippets":38},"Follow the AWS Lambda instructions for packaging with dependencies and uploading in .zip format. This snippet uses the lettuce library.",[39],{"language":40,"code":41},"java","package example;\n\nimport software.amazon.awssdk.auth.credentials.AwsCredentials;\nimport software.amazon.awssdk.auth.signer.Aws4Signer;\nimport software.amazon.awssdk.auth.signer.params.Aws4PresignerParams;\nimport software.amazon.awssdk.http.SdkHttpFullRequest;\nimport software.amazon.awssdk.http.SdkHttpMethod;\nimport software.amazon.awssdk.regions.Region;\n\nimport java.net.URISyntaxException;\nimport java.time.Duration;\nimport java.time.Instant;\nimport java.net.URI;\n\npublic class IAMAuthTokenRequest {\n    private static final SdkHttpMethod REQUEST_METHOD = SdkHttpMethod.GET;\n    private static final String REQUEST_PROTOCOL = \"https:\u002F\u002F\";\n    private static final String PARAM_ACTION = \"Action\";\n    private static final String PARAM_USER = \"User\";\n    private static final String ACTION_NAME = \"connect\";\n    private static final String SERVICE_NAME = \"memorydb\";\n    private static final Duration TOKEN_EXPIRY_SECONDS = Duration.ofSeconds(900);\n\n    private final String userName;\n    private final String clusterName;\n    private final String region;\n\n    public IAMAuthTokenRequest(String userName, String clusterName, String region) {\n        this.userName = userName;\n        this.clusterName = clusterName;\n        this.region = region;\n    }\n\n    public String toSignedRequestUri(AwsCredentials credentials) {\n        SdkHttpFullRequest request = getSignableRequest();\n        SdkHttpFullRequest signedRequest = sign(request, credentials);\n\n        return signedRequest.getUri().toString().replace(REQUEST_PROTOCOL, \"\");\n    }\n\n    private SdkHttpFullRequest getSignableRequest() {\n        return SdkHttpFullRequest.builder()\n                .method(REQUEST_METHOD)\n                .uri(getRequestUri())\n                .appendRawQueryParameter(PARAM_ACTION, ACTION_NAME)\n                .appendRawQueryParameter(PARAM_USER, userName)\n                .build();\n    }\n\n    private URI getRequestUri() {\n        return URI.create(String.format(\"%s%s\u002F\", REQUEST_PROTOCOL, clusterName));\n    }\n\n    private SdkHttpFullRequest sign(SdkHttpFullRequest request, AwsCredentials credentials) {\n        Instant expiresAt = Instant.now().plus(TOKEN_EXPIRY_SECONDS);\n\n        Aws4Signer signer = Aws4Signer.create();\n\n        Aws4PresignerParams params = Aws4PresignerParams.builder()\n                .signingRegion(Region.of(region))\n                .awsCredentials(credentials)\n                .signingName(SERVICE_NAME)\n                .expirationTime(expiresAt)\n                .build();\n\n        return signer.presign(request, params);\n    }\n}\n\nRedisClusterClient client;\nRedisAdvancedClusterCommands&#60;String, String&#62; redisCommands;\n\nString userName = System.getenv(\"CACHE_USERNAME\");\nString clusterName = System.getenv(\"CACHE_CLUSTER_NAME\");\nString endpoint = System.getenv(\"CACHE_ENDPOINT\");\nString region = System.getenv(\"AWS_REGION\");\n\nAwsCredentialsProvider awsCredentialsProvider = DefaultCredentialsProvider.create();\n\n\u002F\u002F Create an IAM authentication token request and signed it using the AWS credentials.\n\u002F\u002F The pre-signed request URL is used as an IAM authentication token for MemoryDB Redis.\nIAMAuthTokenRequest iamAuthTokenRequest = new IAMAuthTokenRequest(userName, clusterName, region);\nString iamAuthToken = iamAuthTokenRequest.toSignedRequestUri(awsCredentialsProvider.resolveCredentials());\n\n\u002F\u002F Construct Redis URL with IAM Auth credentials provider\nRedisURI redisURI = RedisURI.builder()\n        .withHost(endpoint)\n        .withPort(6379)\n        .withSsl(true)\n        .withAuthentication(userName, iamAuthToken)\n        .build();\n\nclient = RedisClusterClient.create(redisURI);\nredisCommands = client.connect().sync();","snippets\u002Flambda-function-connect-memorydb-iam",[],"Integration","Hjzx6d4jJMpfB5o7wD4oBe4IhaHLOlAfoB_COln-zdg",1792578864397]