kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Moto を使って Cognito の cognito-idp API をローカル環境で試す

Amazon Cognito を操作するコード/テストを実装するときに LocalStack を使いたいな〜と思うけど,Amazon Cognito は LocalStack Pro Edition でサポートされていて,LocalStack Community Edition では使えないと言う課題がある.

docs.localstack.cloud

もちろん LocalStack Pro Edition を契約して使うという選択肢もありつつ,単純に Amazon Cognito の基本的な API を実行できれば良いのであれば Moto を使うという選択肢もある❗️

github.com

例えば Amazon Cognito の cognito-idp API だと以下のようなカバレッジになっていて,Amazon Cognito User Pools の操作など主要な API はサポートされているかな〜という感じ👏

docs.getmoto.org

LocalStack と Moto

ちなみに LocalStack と Moto の関係性については Moto のドキュメントに以下のように書いてある📝 LocalStack は Moto よりも高度な機能を持っていると書いてあるけど,実際に LocalStack の内部で Moto に依存しているところも多く,Moto は LocalStack の重要な「コア部分」と言えると思う.

LocalStack is Moto’s bigger brother with more advanced features, such as EC2 VM’s that you can SSH into and Dockerized RDS-installations that you can connect to.

docs.getmoto.org

Moto: Server Mode

Moto は Python ライブラリとして使えるように実装されているけど,実は Server Mode という機能もあって LocalStack とほとんど同じ体験で使えるため,個人的には Moto の Server Mode が使いやすいかな〜と思う \( 'ω')/

docs.getmoto.org

前に Testcontainers for Python と pytest を組み合わせて Moto を自動テストに活用するという記事を書いたときも Server Mode を使っている👌

kakakakakku.hatenablog.com

Moto の Server Mode を起動する場合は以下のようにする❗️

👇️コンテナとして起動する例

$ docker run --rm -p 5000:5000 --name moto motoserver/moto

$ aws sts get-caller-identity \
    --endpoint http://127.0.0.1:5000
{
    "UserId": "AKIAIOSFODNN7EXAMPLE",
    "Account": "123456789012",
    "Arn": "arn:aws:sts::123456789012:user/moto"
}

👇️ Python ライブラリから起動する例

$ pip install 'moto[server]'
$ moto_server

👇️ uv と uvx で起動する例

$ uvx --from 'moto[server]' moto_server

AWS CLI で試す

今回は AWS CLI で Moto の基本的な cognito-idp API を試してみた❗️AWS CLI は同じでエンドポイントを --endpoint http://127.0.0.1:5000 のようにすれば OK👌

  • aws cognito-idp list-user-pools
  • aws cognito-idp create-user-pool
  • aws cognito-idp create-user-pool-client
  • aws cognito-idp list-user-pool-clients
  • aws cognito-idp admin-create-user
  • aws cognito-idp list-users
  • aws cognito-idp admin-delete-user

aws cognito-idp list-user-pools

$ aws cognito-idp list-user-pools \
    --max-results 2 \
    --endpoint http://127.0.0.1:5000
{
    "UserPools": []
}

awscli.amazonaws.com

aws cognito-idp create-user-pool

$ aws cognito-idp create-user-pool \
    --pool-name sandbox \
    --endpoint http://127.0.0.1:5000

$ aws cognito-idp list-user-pools \
    --max-results 2 \
    --endpoint http://127.0.0.1:5000
{
    "UserPools": [
        {
            "Id": "ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e",
            "Name": "sandbox",
            "LambdaConfig": {},
            "LastModifiedDate": "2024-11-07T23:00:00+09:00",
            "CreationDate": "2024-11-07T23:00:00+09:00"
        }
    ]
}

awscli.amazonaws.com

aws cognito-idp create-user-pool-client

$ aws cognito-idp create-user-pool-client \
    --user-pool-id ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e \
    --client-name sandbox \
    --endpoint http://127.0.0.1:5000
{
    "UserPoolClient": {
        "UserPoolId": "ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e",
        "ClientName": "sandbox",
        "ClientId": "9ujfbc613ayfsozlg5ar8v20ag",
        "RefreshTokenValidity": 30,
        "AllowedOAuthFlowsUserPoolClient": false,
        "EnableTokenRevocation": true,
        "EnablePropagateAdditionalUserContextData": false,
        "AuthSessionValidity": 3
    }
}

awscli.amazonaws.com

aws cognito-idp list-user-pool-clients

$ aws cognito-idp list-user-pool-clients \
    --user-pool-id ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e \
    --endpoint http://127.0.0.1:5000
{
    "UserPoolClients": [
        {
            "ClientId": "9ujfbc613ayfsozlg5ar8v20ag",
            "UserPoolId": "ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e",
            "ClientName": "sandbox"
        }
    ]
}

awscli.amazonaws.com

aws cognito-idp admin-create-user

$ aws cognito-idp admin-create-user \
    --user-pool-id ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e \
    --username kakakakakku \
    --endpoint http://127.0.0.1:5000
{
    "User": {
        "Username": "kakakakakku",
        "Attributes": [
            {
                "Name": "sub",
                "Value": "1ce4bba2-35e0-4adc-8357-e5bb594538b0"
            }
        ],
        "UserCreateDate": "2024-11-07T23:00:00+09:00",
        "UserLastModifiedDate": "2024-11-07T23:00:00+09:00",
        "Enabled": true,
        "UserStatus": "FORCE_CHANGE_PASSWORD",
        "MFAOptions": []
    }
}

awscli.amazonaws.com

aws cognito-idp list-users

$ aws cognito-idp list-users \
    --user-pool-id ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e \
    --endpoint http://127.0.0.1:5000
{
    "Users": [
        {
            "Username": "kakakakakku",
            "Attributes": [
                {
                    "Name": "sub",
                    "Value": "1ce4bba2-35e0-4adc-8357-e5bb594538b0"
                }
            ],
            "UserCreateDate": "2024-11-07T23:00:00+09:00",
            "UserLastModifiedDate": "2024-11-07T23:00:00+09:00",
            "Enabled": true,
            "UserStatus": "FORCE_CHANGE_PASSWORD",
            "MFAOptions": []
        }
    ]
}

awscli.amazonaws.com

aws cognito-idp admin-delete-user

$ aws cognito-idp admin-delete-user \
    --user-pool-id ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e \
    --username kakakakakku \
    --endpoint http://127.0.0.1:5000

$ aws cognito-idp list-users \
    --user-pool-id ap-northeast-1_a709065b9e7c4161b45b83cdbf0b313e \
    --endpoint http://127.0.0.1:5000
{
    "Users": []
}

awscli.amazonaws.com