
CloudFormationでAmazon MemoryDB for Redisのリソースを管理する
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
コンサル部のとばち(@toda_kk)です。
2021年8月に発表された新サービスであるAmazon MemoryDB for Redisについて、CloudFormationを使ってリソース管理できるようになりました。
Amazon MemoryDB for Redisは、高速なインメモリデータベースでありつつデータの永続化をサポートしているRedis互換のマネージドサービスです。詳細は下記ページをご参照ください。
なお、2021年10月からは東京リージョンでも利用可能になっています。
Amazon MemoryDB for RedisのCloudFormationリソースタイプ
公式ドキュメントが公開されたので、早速眺めてみます。
2021年11月2日現在、サポートされているCloudFormationのリソースタイプは下記の通りです。
- AWS::MemoryDB::ACL
- AWS::MemoryDB::Cluster
- AWS::MemoryDB::ParameterGroup
- AWS::MemoryDB::SubnetGroup
- AWS::MemoryDB::User
Cluster、ParameterGroup、SubnetGroup
MemoryDB for Redisは、ElastiCache for Redisと同様にVPC内に配置されるリソースであり、サブネットグループによって配置するAvailability Zoneやサブネットを指定し、パラメーターグループによってRedisエンジンのパラメーターを設定します。
また、クラスターモードのみがサポートされており、シャード数(NumShards)やレプリカ数(NumReplicasPerShard)を指定する必要があります。レプリカ数を1以上で設定する場合は、指定するサブネットグループに複数のAZが含まれている必要があります。
ACL
MemoryDB for Redisではセキュリティグループをサポートしていますが、それとは別にアクセスコントロールリスト(ACL)という形でユーザー毎のアクセス制御を設定できます。
このACLは、Redisバージョン6にて標準でサポートされている機能です。Redis ACLコマンドを通じて、ユーザーやユーザーグループを作成し、実行可能なコマンドやデータのアクセス制御を設定することができます。
ただし、MemoryDB for RedisにおいてはACLコマンドの機能は一部制限されており、ユーザーの作成や権限の変更といった書き込みベースの処理がサポートされていません。そのため、ユーザー作成といった操作を実行したいときは、MemoryDB for Redisの機能としてマネジメントコンソールやCLIやCloudFormationから行う必要があります。
redis-cliでRedisに接続した後、ACL HELPを実行することでサポートされているコマンドを確認できます。まずは、Redisバージョン6のコンテナイメージを引っ張ってきてローカル環境などで起動した上で、素のRedisでサポートされているコマンドを確認してみます。
$ sudo docker pull redis:6 $ sudo docker run -d -p 6379:6379 redis:6 $ redis-cli -h localhost localhost:6379> ACL HELP 1) ACL <subcommand> [<arg> [value] [opt] ...]. Subcommands are: 2) CAT [<category>] 3) List all commands that belong to <category>, or all command categories 4) when no category is specified. 5) DELUSER <username> [<username> ...] 6) Delete a list of users. 7) GETUSER <username> 8) Get the user's details. 9) GENPASS [<bits>] 10) Generate a secure 256-bit user password. The optional `bits` argument can 11) be used to specify a different size. 12) LIST 13) Show users details in config file format. 14) LOAD 15) Reload users from the ACL file. 16) LOG [<count> | RESET] 17) Show the ACL log entries. 18) SAVE 19) Save the current config to the ACL file. 20) SETUSER <username> <attribute> [<attribute> ...] 21) Create or modify a user with the specified attributes. 22) USERS 23) List all the registered usernames. 24) WHOAMI 25) Return the current connection username. 26) HELP 27) Prints this help.
次に、MemoryDB for Redisに接続して確認してみます。ちなみに、クラスターの設定でTLS接続を有効にしている場合は--tlsオプションが必要になります。また、クラスターモードで接続したい場合は-cオプションを付与します。
$ redis-cli -h xxxxxx.cluster-name.xxxxxx.memorydb.ap-northeast-1.amazonaws.com --tls -c xxxxxx.cluster-name.xxxxxx.memorydb.ap-northeast-1.amazonaws.com:6379> ACL HELP 1) ACL <subcommand> [<arg> [value] [opt] ...]. Subcommands are: 2) LIST -- Show user details in config file format. 3) USERS -- List all the registered usernames. 4) GETUSER <username> -- Get the user details. 5) CAT -- List available categories. 6) CAT <category> -- List commands inside category. 7) GENPASS [<bits>] -- Generate a secure user password. 8) WHOAMI -- Return the current connection username. 9) LOG [<count> | RESET] -- Show the ACL log entries. 10) HELP 11) Prints this help.
素のRedisと比べて、MemoryDB for Redisではサポートされているコマンドが少ないことがわかります。
これはElastiCache for Redisでも同様です。Redis標準ではAUTHコマンドによるユーザー認証がサポートされていますが、より柔軟な権限制御の方法としてRBAC(Role-Based Access Control)という形でRedis ACLをサポートしています。
- Authenticating users with the Redis AUTH command - Amazon ElastiCache for Redis
- Authenticating users with Role-Based Access Control (RBAC) - Amazon ElastiCache for Redis
Redisでは当初からAUTHコマンドによる認証がサポートされていたのですが、バージョン6からAUTHの拡張と共にACLが追加され、より柔軟な権限制御を実現できるようになったという背景があります。ElastiCache for RedisではRedisエンジンのバージョン6をサポートするにあたり、RBACという形でRedis ACLを提供するようになりました。
これを受けて、MemoryDB for RedisではCloudFormationのリソースタイプにもあるようにACLとUserをAWSリソースとして管理できるようにサポートしているようです。デフォルトではopen-accessという名前のACLが作成されており、defaultユーザーが登録されています。
User
上述のACLで管理するユーザーを作成するリソースタイプです。形式は下記のようになっています。
Type: AWS::MemoryDB::User
Properties:
AccessString:
String
AuthenticationMode: Json
Tags:
- Tag
UserName: String
AccessStringは、ユーザーに許可する操作権限を指定するパラメーターです。on ~* &* +@allといった形式で記述します。詳細は前掲の MemoryDB for Redisのドキュメント もしくは Redisの公式ドキュメント をご参照ください。
AuthenticationModeはJSON形式で指定します。MemoryDBにおけるアクションCreateUserのAPIリファレンスによると、TypeとPasswordsを指定する必要がありそうです。
ここで、上述のdefaultユーザーの設定値をAWS CLIから確認してみます。すると、Authentication.Typeがno-passwordとなっていることがわかります。
これはつまり、パスワードなしでRedisに接続できるユーザーということになります。ElastiCache for Redisの場合でも、AUTH認証やRBACのことを特に意識していない状態で利用していれば、このdefaultユーザーを使ってアクセスしていることになります。
$ aws memorydb describe-users
{
"Users": [
{
"Name": "default",
"Status": "active",
"AccessString": "on ~* &* +@all",
"ACLNames": [
"open-access"
],
"MinimumEngineVersion": "6.0",
"Authentication": {
"Type": "no-password"
},
"ARN": "arn:aws:memorydb:ap-northeast-1:123456789012:user/default"
}
]
}
しかし、データタイプAuthenticationModeのリファレンスを参照すると、次のような記載があります。
Indicates whether the user requires a password to authenticate. All newly-created users require a password.
つまり、新たにユーザーを作成する場合はパスワードが必要になり、no-passwordは実態としてはdefaultユーザーでしか利用できないようです。
CloudFormationからリソース作成してみる
必要なリソースタイプがわかったので、CloudFormationを使って一通りのリソースを作成してみます。以下は、簡単なサンプルとしてご利用いただければと思います。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
SampleCluster:
Type: AWS::MemoryDB::Cluster
Properties:
ClusterName: sample-cluster
ACLName: !Ref SampleACL
NodeType: db.r6g.large
NumReplicasPerShard: 1
NumShards: 1
ParameterGroupName: !Ref SampleParameterGroup
SecurityGroupIds:
- sg-xxxxxxxxxxxxxxxxx
- sg-yyyyyyyyyyyyyyyyy
SubnetGroupName: !Ref SampleSubnetGroup
TLSEnabled: true
SampleSubnetGroup:
Type: AWS::MemoryDB::SubnetGroup
Properties:
SubnetGroupName: sample-subnet-group
SubnetIds:
- subnet-xxxxxxxxxxxxxxxxx
- subnet-yyyyyyyyyyyyyyyyy
- subnet-zzzzzzzzzzzzzzzzz
SampleParameterGroup:
Type: AWS::MemoryDB::ParameterGroup
Properties:
ParameterGroupName: sample-parameter-group
Family: memorydb_redis6
SampleACL:
Type: AWS::MemoryDB::ACL
Properties:
ACLName: sample-acl
UserNames:
- !Ref SampleUser
SampleUser:
Type: AWS::MemoryDB::User
Properties:
UserName: sample-user
AccessString:
on ~* &* +@all
AuthenticationMode: {
Type: password,
Passwords: [xxxxxxxxxxXXXXX!]
}
意図した通りにリソースが作成されていました。
以上、コンサル部のとばち(@toda_kk)でした。








