DynamoDB 属性レベル制御とちょっとだけ項目レベル制御

具体的によく知らなかったので調べた。

最近のデバイスはハイスぺなんで、一部の項目だけに絞ってサイズを小さくするってこともあんまりないし、特定アイテム(レコード)内でのデータの可視範囲を制御したいならそのデータはDynamoDBの外部に置いておく方が安全だし、あんまり使いどころがわからん。

あーでも実際にはアプリからのリクエスト時には(普通なら) API Gateway とか AppSync 経由でするように設計するんで API 開発はしやすいかもしれない。あとたぶんデータ転送量も抑えられるのでめちゃでかいシステムなら恩恵あるかも???

というのは個人的な貧相な経験からの感想だが、よくよく考えてみると、「DynamoDBのテーブル数は少ない方がよい。優れた設計はテーブル1つだ!」といった思想があった気がする。テーブル一つなら属性レベル制御絶対に必要だよね。

とりま試験のための勉強なんで概要だけをさらっと。

項目レベル制御と属性レベル制御

docs.aws.amazon.com

項目レベル制御: 項目レベルでアクセス可能・不可を制御。

属性レベル制御:属性レベルでアクセス可能・不可(可視・不可視)を制御。

利用イメージ(属性レベル制御)

docs.aws.amazon.com

docs.aws.amazon.com

GetItem, Query, Scan オペレーション実行時にプロジェクション式(projection expression)を指定することで特定の属性のみに絞ることができる。

例えば、以下の項目があったとする。★の部分のみが欲しい。

{
    "Id": 123,
    "Title": "Bicycle 123",
    "Description": "123 description",・・・★
    "BicycleType": "Hybrid",
    "Brand": "Brand-Company C",
    "Price": 500,
    "Color": ["Red", "Black"],
    "ProductCategory": "Bicycle",
    "InStock": true,
    "QuantityOnHand": null,
    "RelatedItems": [
        341,・・・★
        472,
        649
    ],
    "Pictures": {
        "FrontView": "http://example.com/products/123_front.jpg",
        "RearView": "http://example.com/products/123_rear.jpg",
        "SideView": "http://example.com/products/123_left_side.jpg"
    },
    "ProductReviews": {
        "FiveStar": [・・・★
                "Excellent! Can't recommend it highly enough! Buy it!",
                "Do yourself a favor and buy this."
        ],
        "OneStar": [
                "Terrible product! Do not buy this."
        ]
    },
    "Comment": "This product sells out quickly during the summer",
    "Safety.Warning": "Always wear a helmet"
 }

CLIで、--projection-expression を指定して実行する。

aws dynamodb get-item \
    --table-name ProductCatalog \
    --key file://key.json \
    --projection-expression "Description, RelatedItems[0], ProductReviews.FiveStar"

★の部分のみ取得できる。

{
    "Item": {
        "Description": {
            "S": "123 description"
        },
        "ProductReviews": {
            "M": {
                "FiveStar": {
                    "L": [
                        {
                            "S": "Excellent! Can't recommend it highly enough! Buy it!"
                        },
                        {
                            "S": "Do yourself a favor and buy this."
                        }
                    ]
                }
            }
        },
        "RelatedItems": {
            "L": [
                {
                    "N": "341"
                }
            ]
        }
    }
}

権限制御に使う(属性レベル制御)

repost.aws

こんなテーブルがあったとする。※上の例とは違うので注意。

GameScoresテーブルの情報がここしかなかった。ドキュメントやサポート回答で利用されるテーブル情報がまとまってるなら欲しい。。。

docs.aws.amazon.com

以下のポリシーでは、WinsLosses は見れないようになっている。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "LimitAccessToSpecificAttributes",
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:Query",
                "dynamodb:BatchGetItem",
                "dynamodb:Scan",
                "dynamodb:TransactGetItems"
            ],
            "Resource": [
                "arn:aws:dynamodb:eu-west-1:123456789012:table/GameScores"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:Attributes": [
                        "TopScoreDateTime",
                        "TopScore",
                        "UserId",
                        "GameTitle"
                    ]
                },
                "StringEquals": {
                    "dynamodb:Select": "SPECIFIC_ATTRIBUTES"
                }
            }
        }
    ]
}

CLIの例は以下。

# 全部の属性を取得しようとするため AccessDeniedException
aws dynamodb query --table-name GameScores --key-condition-expression "UserId = :useridval" --expression-attribute-values '{":useridval":{"S":"stefano_123"}}'
# Query 成功
aws dynamodb query --table-name GameScores --key-condition-expression "UserId = :useridval" --expression-attribute-values '{":useridval":{"S":"stefano_123"}}' --projection-expression "TopScore, TopScoreDateTime, GameTitle"
# GetItem 成功
aws dynamodb get-item --table-name GameScores --key '{"UserId":{"S":"stefano_123"},"GameTitle":{"S":"Game Zero"}}' --projection-expression "UserId, GameTitle, TopScore, TopScoreDateTime"

ユースケース

で、どんな時にこんな使い方できるのかな?とちょっと考えてみた。たぶん、「ゲームランキング一覧生成のために全員分のデータを取得する必要はあるが詳細な情報は取得しないようにしたい」みたいなケースかな。

となると、項目レベルの制御で「自分のレコードは全部読めるけど、他人のレコードは概要情報だけ」みたいな制御がしたくなってくる。

項目レベルの制御はここら辺に詳しく書いてあるが、詳細は必要になったら読もう。

docs.aws.amazon.com

docs.aws.amazon.com

タイピング記録 2023/5/2

ITエンジニアなのにタイピング激遅なのでなんとかしたい。

タイピング練習を始めてから1カ月、やっとベスト更新しました。

基本常用語 XJ 52.372 通算回数 763

今までタイピング記録を付けてなかったのでe-typingのも貼っておく。

e-typingは学生時代にちょこっとやってて、1カ月前くらいにまたちょこっとやった。

Private Link がようやっとわかりました(憔悴)

勉強する前

Private Link ってサードパーティーのVPCにいい感じに接続できる仕組みでしょ?インターフェイス型エンドポイントとの違いがよくわかんねいや。

Private Link とは

めちゃわかる。ありがとうございます。おかいき!!(誤用)

dev.classmethod.jp

公式。まあまあわかる。ありがとうございます。

docs.aws.amazon.com

Private Link は以下のアーキテクチャー図で示される概念。

サービスプロバイダ側では VPCエンドポイントサービス を作る。プロバイダは自分であることもあるし、サードパーティーであることもあるし、AWSサービスであることもある(AWSサービス統合)。

コンシューマー側は エンドポイントサービス へ向けた VPCエンドポイント(インターフェイス型) を作る。

エンドポイントサービス 。。。Azure の サービスエンドポイントとこんがらがって頭おかしくなる。。。

とゆーことで全体的にはこんなイメージではないかと。※自分以外に通じるかわからんが、まあこのブログ自体便所の落書きみたいなもんだからね。

ネット記事とか解説とかでは 「VPCエンドポイントにはゲートウェイ型とインターフェイス型があってね~~~。あ、Private Link ってのもあるよ。」って説明の仕方だが、そのせいでだいぶ混乱していた。

実際のところは「VPCエンドポイントにはゲートウェイ型とインターフェイス型があってね~~~。あ、インターフェイス型VPCエンドポイントは Private Link の仕組みの中で利用されるものだよ。AWSサービスが統合されてるからゲートウェイ型と似たような用途で使えるよ。」ってのが正しい理解な気がする。知らんけど。

みんなわかってて書いてんのかなー?(知らないのは僕だけでした)。

AWS CLF 受かった(あたりまえ体操)

試験は1問〇点みたいなのじゃなくて、難易度毎に調整が入る方式だと思う(項目応答理論的な)。

なので単純計算はできないが、仮に単純計算したら、65問中5問も間違えてる計算。

何が駄目だったんだろう。昔はなかった持続可能性周りの範囲でやらかしたのかな。

とりま、SAA目指して頑張りますん(5年くらい前に1回取ったけどとっくの昔に有効期限切れてる)。

Import XXX could not be resolved from sourcePylance

書きたいネタはあるが整理する時間がないので今直面した小ネタを。

VSCode から WSL 2 につないでる状態で、python ライブラリをうまく検知できてなくてワーニングが出た。

これで解決。

maasaablog.com

$ python -c "import site; print (site.getsitepackages())"
['/home/talkeyboid/anaconda3/lib/python3.9/site-packages']