カテゴリー: aws

AWSの情報をまとめる

  • Cognito 認証情報を活用した AWS Lambda の効果的なユーザー管理

    Cognito 認証情報を活用した AWS Lambda の効果的なユーザー管理

    導入

    現代のビジネス環境において、アプリケーションのセキュリティとユーザー管理は重要な柱です。AWS Lambda と Amazon Cognito を組み合わせることで、高度にスケーラブルでセキュアなサービスを効率よく構築できます。本記事では、Amazon Cognito で認証されたユーザーの情報を AWS Lambda で取得し、ビジネスプロセスに統合する方法に焦点を当てます。

    ビジネスの利点

    Amazon Cognito と AWS Lambda の組み合わせは、以下のビジネス上の利点を提供します。

    • セキュリティの強化: ユーザー認証情報を適切に処理することで、不正アクセスを防ぎます。
    • コスト効率: サーバーレスアーキテクチャを利用することで、リソースの利用に応じて課金され、余分なコストを削減します。
    • 拡張性: 需要に応じて自動的にスケールします。これにより、ビジネスが拡大してもパフォーマンスが維持されます。

    実装

    以下は、AWS Lambda 関数で Cognito の認証が通ったユーザーからメールアドレスを取得するステップバイステップのガイドです。

    ステップ1: IDトークンの取得

    まず、AWS Lambda 関数で HTTP リクエストのヘッダーから ID トークンを取得します。これは、Amazon Cognito によって発行された JWT(JSON Web Token)です。

    id_token = request.headers.get("x-amzn-oidc-data", "")

    ステップ2: トークンのデコード

    次に、JWT のペイロード部分をデコードします。JWT は3つの部分(ヘッダー、ペイロード、署名)で構成されており、ペイロードにはユーザー情報が含まれています。

    token_parts = id_token.split('.')
    payload_encoded = token_parts[1]
    padding_needed = 4 - len(payload_encoded) % 4
    payload_encoded += "=" * padding_needed
    payload_decoded = base64.b64decode(payload_encoded)
    payload_json = json.loads(payload_decoded.decode("utf-8"))

    ステップ3: メールアドレスの抽出

    最後に、デコードされたペイロードからメールアドレスを抽出します。

    email = payload_json['email']

    まとめ

    Amazon CognitoとAWS Lambdaを組み合わせることで、セキュアでスケーラブルなユーザー管理を実現し、ビジネスプロセスを効率化することができます。ユーザー認証情報の適切な処理は、アプリケーションのセキュリティを強化し、顧客の信頼を築く上で不可欠です。

    今回解説した方法を使用すると、簡潔にユーザーのメールアドレスを取得でき、これをビジネスロジックやユーザー通知など、さまざまな用途で活用することができます。

  • タイトル: S3バケットに関連付けられたLambda関数をAWS CLIで調査する

    タイトル: S3バケットに関連付けられたLambda関数をAWS CLIで調査する

    はじめに

    Amazon S3バケットにファイルがアップロードされたときにAWS Lambda関数を自動的にトリガーするのは、一般的な使用例です。しかし、プロジェクトが大規模になると、どのLambda関数が特定のS3バケットと関連付けられているのかを把握するのが難しくなることがあります。この記事では、AWS CLIを使用して、S3バケットに関連付けられたLambda関数を調査する方法について解説します。

    手順

    1. AWS CLIのインストールと設定

    AWS CLIがまだインストールされていない場合は、公式ドキュメントに従ってインストールしてください。次に、aws configureコマンドを使用してAWSアカウントの認証情報を設定します。

    2. S3バケットの通知設定を確認

    次に、以下のコマンドを使用してS3バケットの通知設定を取得します。このコマンドはバケットの名前を指定する必要があります。

    aws s3api get-bucket-notification-configuration --bucket YOUR_BUCKET_NAME

    このコマンドを実行すると、バケットに関連付けられた通知設定がJSON形式で表示されます。

    3. 結果の解析

    出力されたJSONの中で、LambdaFunctionConfigurations セクションに注目します。このセクションには、関連付けられたLambda関数のリストが含まれています。それぞれの項目では、Lambda関数のARN (Amazon Resource Name)、トリガーされるS3イベント、および任意のフィルタルールに関する情報が表示されます。

    実例

    以下は、実際の出力の例です(固有情報はマスクされています):

    {
    "LambdaFunctionConfigurations": [
    {
    "Id": "example-trigger-1",
    "LambdaFunctionArn": "arn:aws:lambda:region:account-id:function:example-function-1",
    "Events": [
    "s3:ObjectCreated:Put",
    "s3:ObjectCreated:Post"
    ],
    "Filter": {
    "Key": {
    "FilterRules": [
    {
    "Name": "Suffix",
    "Value": ".csv"
    }
    ]
    }
    }
    },
    {
    "Id": "example-trigger-2",
    "LambdaFunctionArn": "arn:aws:lambda:region:account-id:function:example-function-2",
    "Events": [
    "s3:ObjectCreated:Put",
    "s3:ObjectCreated:Post"
    ],
    "Filter": {
    "Key": {
    "FilterRules": [
    {
    "Name": "Suffix",
    "Value": ".txt"
    }
    ]
    }
    }
    }
    ]
    }

    この例では、2つのLambda関数がS3バケットに関連付けられています。

    それぞれが異なるファイルタイプ(.csvおよび.txt)のアップロード時にトリガーされます。

    まとめ

    AWS CLIを使用して、簡単にS3バケットに関連付けられているLambda関数の情報を取得することができます。これにより、システムの動作を理解し、必要に応じて設定を調整することが可能になります。

  • Flaskにおける特定のルートのログ出力の無効化について: AWS EC2/ECS

    Flaskにおける特定のルートのログ出力の無効化について: AWS EC2/ECS

    FlaskはPythonで開発された軽量なWebフレームワークで、そのシンプルさと拡張性から多くの開発者に利用されています。

    今回は、特にAWSのEC2やECSでFlaskを使用している開発者の皆様向けに、ある一般的な問題とその解決策について共有させていただきます。

    サーバーのヘルスチェックは重要な部分であり、私たちはそのためのエンドポイント/healthzを定期的にポーリングしています。

    しかし、これがもたらすログ出力の多さが問題となり、重要な情報が見づらくなることがあります。

    そこで、ヘルスチェックのエンドポイントに関するログだけを無効にする方法について考察しました。

    解決策:特定のルートのログ出力をフィルタリングする

    この問題に対する答えの一つとして、PythonのloggingモジュールのFilterクラスを用いる方法があります。このクラスを継承し、カスタムフィルタクラスを作成します。このフィルタをロガーに追加することで、特定のログメッセージをフィルタリングできます。

    import logging

    class HealthCheckFilter(logging.Filter):
    def filter(self, record):
    return "/healthz" not in record.getMessage()

    ここで定義したHealthCheckFilterクラスは、ログメッセージに/healthzが含まれていない場合にのみTrueを返します。

    したがって、/healthzがメッセージに含まれるログエントリはフィルタリングされ、出力されません。

    そして、このフィルタを適用したいロガーに追加します:

    logger = Logger().getLogger('default')
    logger.addFilter(HealthCheckFilter())

    これにより、ヘルスチェックに関するログ出力が無効化され、ログの可読性が向上します。

    注意点

    この解決策は、特定のロガーに対してのみ適用されます。全体のロガーへの適用はされません。

    例えば、Flaskは内部的にWerkzeugサーバーを利用しており、そのサーバーは自己のロガー(‘werkzeug’)を持っています。

    そのため、もしWerkzeugサーバーからのログもフィルタリングしたい場合は、同様にフィルタを追加する必要があります。

    この記事がAWSのEC2やECSで大規模なFlaskアプリケーションを運用している皆様の一助になれば幸いです。

    特定のエンドポイントのログ出力を制御することで、ログの可読性が向上し、重要な情報へのアクセスが容易になります。

    私たちはまだ学び続けており、他の解決策や改善点があれば、ぜひ共有いただければと思います。

  • AWS CLIでエスケープなしのJSONを送信する

    AWS CLIでエスケープなしのJSONを送信する

    AWS CLIを使って作業を行うとき、しばしばJSON文字列を引数として渡す必要があります。しかし、これが難しい場合もあります。特に文字列内にエスケープが必要な文字(バックスラッシュなど)が含まれている場合です。

    今回は、エスケープなしのJSON文字列をAWS CLIに直接渡す方法を紹介します。

    ヒアドキュメントの使用

    ヒアドキュメント(Here Document)は、シェルスクリプトのリダイレクトの一種で、複数行のテキストを直接スクリプト内に記述するための方法です。

    ヒアドキュメント内部では、一部のエスケープシーケンスが解釈されずバックスラッシュがただの文字として扱われます。

    これを利用すると、バックスラッシュを含む文字列をエスケープせずに直接AWS CLIに渡すことが可能になります。

    具体的には、以下のようにします:

    aws sqs send-message --profile your-profile --queue-url "your-queue-url" --message-group-id "your-message-group-id" --message-body "$(cat <<EOF
    {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
    }
    EOF
    )
    "

    ここで、

    $(cat <<EOF ... EOF)

    がヒアドキュメントの部分で、これが完全に展開された後で

    aws sqs send-message

    コマンドが実行されます。ヒアドキュメント内のJSON文字列はエスケープなしでそのまま扱われるため、特殊文字を含むパスでも問題なくAWS CLIに渡すことができます。

    まとめ

    AWS CLIでエスケープが必要な文字を含むJSONを扱う際には、ヒアドキュメントが非常に便利です。ヒアドキュメントを使うと、エスケープなしで文字列をそのまま扱うことができるので、コマンドラインでの作業が少し楽になります。

  • 「AWSではじめるデータレイク」を読んだ

    「AWSではじめるデータレイク」は、AWSを使ってデータレイクを構築する方法について詳しく解説された書籍である。本書は、AWSのデータレイクについて初心者から中級者までのユーザーに向けて、豊富な事例や具体的な手順を示しながら、データレイクの概念や構成要素、設計方法などについて詳細に解説している。

    本書の特徴の一つは、AWSのデータレイクを利用するメリットや機能面の解説が非常に丁寧であることだ。また、AWSのサービスを組み合わせて、スケーラブルで堅牢なデータレイクを構築するためのベストプラクティスについても解説されている。さらに、実際のビジネスケースを通じて、データレイクがどのように活用されるかもわかりやすく説明されている。

    本書で取り上げられたデータレイクの構成要素は、ストレージ層、処理層、分析層、セキュリティ層の4つである。それぞれの層の機能や使い方について、AWSのサービスを活用した実践的な手順が解説されている。例えば、ストレージ層では、S3やGlacierなどのAWSのストレージサービスを使って、データの保管やアクセス方法について詳しく解説されている。

    処理層では、EMRやLambdaなどのAWSのサービスを使って、データの加工や変換方法について解説されている。分析層では、RedshiftやAthenaなどのAWSのデータ分析サービスを使って、データの分析や可視化方法について解説されている。また、セキュリティ層では、IAMやKMSなどのAWSのセキュリティサービスを使って、データの保護やアクセス制御方法について詳しく解説されている。

    本書の内容は非常に実践的であり、データレイクの構築に必要なスキルや知識を習得する上で非常に役立つ。AWSのサービスを組み合わせることで、大量のデータを効率的に扱うことができるため、データ分析やビジネスインテリジェンスの分野での活用において、非常に有用な知識となる。また、本書で紹介されたベストプラクティスを活用することで、スケーラビリティや可用性など、データレイクを構築する上での課題に対しても十分な対応が可能となる。

    さらに、本書ではAWS以外のデータレイクの構築方法やツールについても言及されており、AWS以外の環境でもデータレイクを構築する際に役立つ情報が得られる。また、データレイクの構築におけるトラブルシューティングやパフォーマンスチューニングのポイントについても詳しく解説されているため、実際の運用においても非常に参考になる。

    一方で、本書はAWSを利用する上での基本的な知識があることが前提となっており、AWSの初心者にとっては難易度が高い可能性がある。また、本書で紹介されたAWSのサービスや機能が、新しいバージョンにアップデートされた場合には情報が古くなる可能性もあるため、最新の情報を得るためにはAWSのドキュメントや公式の情報源を参照する必要がある。

    総じて、本書はAWSを使ったデータレイクの構築に興味がある方や、既にAWSを利用している方にとって非常に有用な一冊である。豊富な実践的な事例や手順が示されており、AWSのデータレイクを効果的に活用するためのノウハウが詳しく解説されているため、データ分析やビジネスインテリジェンスの分野での活用を目指す方には、必読の書と言える。

  • n日以降に ECR に push された image を調べる

    今後もつかそうなのでメモ

    aws ecr describe-images --repository-name $REPOSITORY  --query "reverse(sort_by(imageDetails[*], &imagePushedAt))" | jq '.[] | select(.imagePushedAt > "2022-12-01T00:00:00+09:00")'
    

    REPOSITORY に pushされた image を取得することができる

  • ECR の全リポジトリ名を取得する

    よく使うので tips として書き留めておく。

    以下のコマンドで取得可能

    aws ecr describe-repositories --output json | jq -re ".repositories[].repositoryName"
    

    結果は、ECR のリポジトリが表示される

    ecr-test-repo1
    ecr-test-repo2
    
  • ElasticIP を使わず EC2 instance へsshする

    コンテナが広く使われるようになり、
    EC2 instanceは徐々に使わなくなってきたが、それでもEC2 instance を使っているところはまだまだ多い。

    EC2 instance に接続するには ElasticIP を使ってssh を使うのが一般的だが、
    ElasticIP は便利なために、長年運用している間に気がつけばだんだん増えていってしまいがちである。

    踏み台サーバのような ssh しか使わないサーバであれば、極力 ElasticIP を使わずいけるようにしたい。

    接続先のAWS EC2 側の設定と、接続元のMac に設定をまとめた。

    接続先のAWS EC2 側の設定

    Linux 側に SSM agent をインストールする

    sudo yum install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm
    
    

    ap-northeast-1 の場合は上記の通りだが、
    他のリーションを使うことになれば上記よしなに変更する

    IAM の設定

    EC2 インスタンスに Attach している IAM role に
    SSM のロールを Attach する。

    AmazonSSMManagedInstanceCore

    という AWS管理のポリシーがあるので、これを Attach

    Mac の設定

    直に aws コマンドをインストールしてもよいが、ローカル環境が汚れるのが嫌なので(これは完全に趣向性)
    自分はaws コマンドを叩くと、aws cli のコンテナが動くようにしている。
    公式のaws cli のコンテナは何のプラグインも入ってないプレーンな状態なので、
    session-manager-plugin をインストールした。

    vi Dockerfile

    FROM amazon/aws-cli
    
    RUN curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/linux_64bit/session-manager-plugin.rpm" -o "session-manager-plugin.rpm" && \
        yum install -y ./session-manager-plugin.rpm
    
    

    docker image build -t ssm/aws-cli:latest .

    .ssh/config に以下の通り設定を入れる

    host bastion
        User ec2-user
        ProxyCommand sh -c "docker run --rm -i -v ~/.aws:/root/.aws -v $(pwd):/aws --env AWS_PAGER="" ssm/aws-cli ssm --profile staging start-session --target i-08afxxxxxxxxxx --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
        IdentityFile ~/.ssh/ec2-user
    
    

    他のサーバに対して同様の設定をする際は
    インスタンスID i-08afxxxxxxxxxx
    や User, IdentityFileを変更すれば良い

    また、今回は接続先が BT 環境のため --profile staging としたが、他の環境に接続する際はここを適宜変更する。

    動作確認

    今まで ElasticIP を使って接続していたことと同様に接続できることを確認できた。

    % ssh bastion                  
    Last login: Mon May  9 10:31:34 2022 from localhost
    
           __|  __|_  )
           _|  (     /   Amazon Linux 2 AMI
          ___|\___|___|
    
    https://aws.amazon.com/amazon-linux-2/
    [ec2-user@bastion ~]$
    
    
  • About the concept of S3 directories

    Introduction

    Most of the tasks in aws can be operated with aws commands. The only command I couldn’t find in the official documentation was “create folder,” which should be on the screen.

    The concept of a folder in S3

    In fact, the concept of folders does not exist in S3. https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/UsingMetadata.html

    The data model of Amazon S3 is a flat structure. Buckets are created and objects are stored in those buckets. There is no hierarchy of sub-buckets or sub-folders. However, a logical hierarchy can be implied by using key name prefixes and delimiters, such as those used in the Amazon S3 console.

    So, for one bucket, there are no folders in it, and it is an image of a large number of files.

    So what do we do?

    I don’t have a directory, but I’ll just dump it in directly!

    aws s3 cp sample.txt s3://test/sample-folder/


    This will create a sample-folder in the test bucket. Copy the sample.txt file into it. Reference: Breaking the illusion of “folder” in Amazon S3 and revealing its reality https://dev.classmethod.jp/cloud/aws/amazon-s3-folders/

    If multiple environments are registered in the .aws directory, it is possible to specify the profile to be loaded with -profile role-a-profile.

    If you want to copy the whole directory, use

    --recursive
    option to copy the entire directory recursively.

  • kms:ViaService の考え方について

    kms:ViaService を利用して、CMK を呼び出していない時」というポリシーの書き方をすることができる

                    "Null": {
                        "kms:ViaService": "true"
                    },
    

    この部分は Classmethod さんのブログが非常にわかりやすい

    https://dev.classmethod.jp/articles/ebs-kms-sourceip/

    kms:ViaServiceは、CMKの使用を指定のAWSサービスからのリクエストに制限する条件キーであり、

    Nullは、条件キーの存在を確認する条件演算子を指す。

    Nullで {"kms:ViaService": "true"}と指定すると、「kms:ViaServiceが存在しない(≒CMKを呼び出していない)」という条件になる。

    これを接続元IPアドレスを制限する条件に追加することで、「CMKを呼び出していない かつ 接続元IPを制限する」という条件になる。