SCSKの畑です。8回目の投稿です。 今回は、 初回のエントリ で少しだけ触れた、AWS Amplify が生成した AWS AppSync リソースの手動移行に関する備忘録のような、Tips のような内容になります。如何せんこのような作業が必要となるような案件もといシチュエーション自体が珍しいと思いますので、ニッチな内容になるとは思いますが御覧頂ければ幸いです。 なお、タイトル通り Amplify と AppSync の話題に閉じているのでアーキテクチャ図は載せません。それも何気に今回が初めてですね・・ 前提条件(初回エントリのおさらい含む) お客さんが主体的に管理している AWS 環境上で各種 AWS サービスやリソースの構築・実装を行った、 CloudFormation や AWS CDK、terraform などの使用は原則 NG。AWS マネジメントコンソールの使用を使用した構築が基本。 Amplify についてはお客さんの環境ポリシー上導入 NG だったため、弊社の AWS 環境上で Amplify により作成された各種 AppSync リソースを、お客さんの AWS 環境に手動移行する必要があった。 移行対象はスキーマ、リゾルバ、関数の3つ。 データソースについては上記3つと比較して変更のタイミングが限定的であり、かつリソースとなる DynamoDB のテーブルや Lambda 関数についても申請の上お客さん側で作成頂く必要があるため、設定情報をお客さんに連携して作成頂く形式とした。 以上の内容を踏まえて、いくつかの観点から備忘録替わりに記載していきます。 余分な query や mutation を Amplify に生成させない まずは Amplify スキーマ定義上の工夫から。 @model として定義すると、テーブルだけでなく対応した query なり mutation を自動生成してくれるのが Amplify の便利な点なのですが、アプリケーションから使用しないことが明確なものもあるため、そのような不要なものは生成しないようにすることで移行作業の対象を減らすのが目的です。具体的には、スキーマ定義において生成対象の type を指定することで実現できます。 排他制御の実装例(第一回) で例示した TableInfo において、query は list、mutation は create のみをそれぞれ生成するようにする場合は以下のように定義することで実現できます。 type TableInfo @ model ( queries: { list: "listTableInfos" }, mutations: { create : "createTableInfo" }, ) @ auth ( rules : [ { allow : public, provider : apiKey}, { allow : private, provider : iam}, ]) { name : String! @primaryKey status : TableStatus! editor : String locked_by : String } 手動移行時に設定変更が必要なマッピングテンプレートの整理 次に、実作業についてですが・・こちらは単純に AWS マネジメントコンソールを弊社の AWS 環境とお客さんの AWS 環境で2画面開いて、愚直に手動で移行(もといコピペ)していただけなので、特に内容として取り上げたいものはありません。もっと楽なやり方を採用したかったとは思いますが。。 ただ、AWS 環境が異なる以上、移行時に変更する必要がある項目も幾つかあったためその点には留意しました。特に、リゾルバのリクエストマッピングテンプレートについては VTL を書き換える必要があったため、備忘録として以下に記載しておきます。逆に言うと、注意深く変更する必要があったのはこの項目くらいだったため、移行自体は思っていたほど時間がかからなかったのは幸いでした。 例えば、データソース名はお客さんに作成頂く必要があることもあり、Amplify による生成時の名称から意図的に変更していますが、データソースを意図的に指定する必要があるのは関数やリゾルバ作成時程度なので、あまり気になりませんでした。 下記例の通り、大体コピペのままで行けるのですが以下2点については修正の必要がありました。 authRole, unAuthRole を使用しないため、マッピングテンプレートから削除 adminRoles の AWS アカウント ID をお客さんの AWS 環境のものに変更 ## [Start] Stash resolver specific context.. ** $util.qr($ctx.stash.put("typeName", "<Query or Mutation or Subscription>")) $util.qr($ctx.stash.put("fieldName", "<QueryName or MutationName or SubscriptionName>")) $util.qr($ctx.stash.put("adminRoles", ["arn:aws:sts::<AWS Account ID>:assumed-role"])) {} ## [End] Stash resolver specific context.. ** 手動移行した AppSync リソースの設定チェックにおける工夫 最後に、手動移行後の AppSync 設定確認方法について。 手動で移行したこともあり、環境間で移行したリソース設定をどのように比較チェックするのかがちょっとした課題でした。スキーマは画面からコピペしたものを diff 比較すれば良いとしても、関数/リゾルバのマッピングテンプレートで都度それをやるのはさすがに面倒だし、マッピングテンプレート内の関数実行順などは画面上で比較するしかないということで、どうしたものかと。当初は目視確認もやむなしかと思っていたのですが、案の定設定ミスで動作しなかった mutation が出てしまい、ある程度はちゃんと機械的に比較できる方法を考える必要がありました。 と言っても、先述の通り IaC に該当する仕組みは使用できなかったので、大人しく Python/Boto3 で AppSync の設定を一覧化して S3 に出力するようなコードを書くことにしました。弊社/お客さんの AWS 環境で出力したものを diff 比較するようにすれば、AWS アカウント ID など差異が発生する項目は出るにせよ、画面の目視確認よりは大分マシだろうなと。 なお、順番が前後してしまいますが、現在は Amplify スキーマ更新時などにどこが変更されたのか(=どのリゾルバ/関数を手動移行する必要があるのか)を検出するためにも使用しています。単純な type の追加程度なら何を移行すれば良いのかある程度直感的に分かると思うのですが、変更(更新)とかになるとリゾルバ内のどの関数なりマッピングテンプレートが変更されたか分からないですからね。。 ということで内容は大したことないのですが、以下 Lambda による実装例です。幸い Boto3 にそのものズバリなメソッドが揃っていたため、それらを順次実行した結果を S3 に出力しているだけの簡単仕様ですが、少しだけ補足です。 get_introspection_schema() と list_types() が返す情報はほぼ同義ですが(スキーマ設定により各 type が定義されるので)、一応両方出力するようにしています。 前者は JSON ではなく SDL で出力しているので、streamingBody を read() したものをそのまま出力しています。 list_resolvers() の引数として、リゾルバを実装した type 名を指定する必要があります。Amplify を使用していることもあり、graphql のクエリ言語に対応するものをそのまま直指定しています。 また、出力結果はフォルダごと Winmerge などの diff ツールで比較するような使い方をしていますが、functionID 絡みで比較に支障があった部分については以下のように変換、ソート処理を入れています。 list_functions() の結果がどうやら functionId でソートされて返ってくるようなのですが、ID は当然ながら環境間で異なるためこのままだと有意な比較ができません。よって、 name(関数名)でソートし直したものを出力しています。 リゾルバ内の関数実行定義も functionId による表現となっているため、functionId から name を導出できるような dict を用意の上、定義内容を置換しています。 他にも、マッピングテンプレートや types における definition の出力結果を整形するなど、もうちょっと頑張りどころはありそうなんですが、それらの内容で差分が生じてもそこまで比較に支障が出なさそうだったので、一旦そのまま出力してしまっています。 import json import datetime import boto3 import botocore BUCKET_NAME = '<BUCKET_NAME>' API_ID = '<APPSYNC_API_ID>' appsync = boto3.client('appsync') s3 = boto3.resource('s3') bucket = s3.Bucket(BUCKET_NAME) def put_json_to_S3(obj_key, json_data): obj = bucket.Object(obj_key) obj.put(Body = json.dumps(json_data, indent=4, sort_keys=True, separators=(',', ': '))) def lambda_handler(event, context): obj_key_prefix = f'appsync_setting_dumps/{datetime.datetime.now().strftime("%Y%m%d_%H%M%S")}' # 情報取得(functions) response = appsync.list_functions( apiId=API_ID ) # functionの名前でソート sorted_func_json = sorted(response['functions'], key=lambda x: x['name']) put_json_to_S3(f'{obj_key_prefix}/functions.json', sorted_func_json) # 情報取得(resolvers) id_name_dict = {item['functionId']: item['name'] for item in sorted_func_json} for typename in ['Query', 'Mutation', 'Subscription']: response = appsync.list_resolvers( apiId=API_ID, typeName=typename ) # functions実行定義をIDから名前に変換 converted_resolvers_json = response['resolvers'] for item in converted_resolvers_json: pipeline_config = item["pipelineConfig"] if "functions" in pipeline_config: pipeline_config["functions"] = [id_name_dict[id] for id in pipeline_config["functions"]] put_json_to_S3(f'{obj_key_prefix}/resolvers_{typename}.json', converted_resolvers_json) # 情報取得(types) response = appsync.list_types( apiId=API_ID, format='JSON' ) put_json_to_S3(f'{obj_key_prefix}/types.json', response['types']) # 情報取得(schema) response = appsync.get_introspection_schema( apiId=API_ID, format='SDL' ) obj = bucket.Object(f'{obj_key_prefix}/introspection_schema.json') obj.put(Body = response['schema'].read()) なお、この方向性で AppSync リソースの作成や更新も自動化すればいいじゃんというセルフツッコミが成立しそうなのですが、車輪の再発明感がものすごかったので今回はやめました。もっと対象のリソース数が多かったりしたら検討したかもしれませんが、それよりはお客さんに Amplify の使用許可を貰えるよう交渉を頑張るとか、Amplifyをやめて自前でリゾルバを実装するようにした方が色んな意味で健全かなと思います。。。 余談 Amplify の自動生成が便利とはいえ手動移行に手間をかけるより、自分でリゾルバを書けば良いんじゃないの?と疑問を持たれた方もいるかと思うのですが、その考え自体は正しいと思います。何故それでも Amplify を採用したのかというと、単純に期間や工数との兼ね合いからでした。AppSync を本格的に扱うのが初めてだったということもあるのですが、リゾルバの作成を未経験の言語(VTL or AppSync JS)で頑張るのはちょっと現実的ではなかったです。特に VTL は正直構文とか見てもあまり好きになれず・・ データソースが全て Lambda になるようなアプリケーションであれば、AppSync をやめて API Gateway + Lambda という構成でもよかったのですが、その場合はアプリケーションで使用するDBをどのように用意するか、というのがネックでした。なるべくサーバレスのサービスで構成しようとすると結局一番筋が良さそうなのは DynamoDB になりますが、それなら AppSync 及び Amplify と組み合わせて使った方が筋が良いのではないかと。Aurora Serverless も選択肢ではありましたが、さすがに今回の用途だとオーバースペックでしたし。後は、別エントリで説明した通り AppSync の Subscription をアプリケーション側で活用することを念頭に置いていたという要因も大きいです。 まとめ 本来であればこのような対応を取らないに越したことはないのですが、手動移行したことによりリゾルバや関数の仕組みや実装について理解が深まったことも確かなので、トータルでは良かったのかもしれません。現在もアプリケーションの開発は継続しており、ちょくちょく弊社環境からお客さん環境に AppSync 更新分を移行する機会はあるのですが、これらの取り組みにより移行自体にかかる工数は大分削減できるようになりました。ただ、もし別の案件で同じような対応を迫られた場合は、もっとラクなやり方を検討したいところではあります。。 本記事がどなたかの役に立てば幸いです。
企業ネットワークにおけるクラウドサービス利用のリスク対策として、Cloud Access Security Broker(CASB)の導入が増えています。 CASBは「可視化(Visibility)」「アセスメント(Assessment)」「強制(Enforcement)」「防御(Protection)」の4つのプロセスで説明されます。このうち「強制」では、クラウドサービスの利用許可・拒否等のルールを設定することとなりますが、具体的にどういったルールにするべきか、ご相談をいただくことが多いです。 そこでこの記事では、 実際に設定されることの多いCASBルールの例をご紹介します。 設定はSASEソリューションである「Catoクラウド」のCASB機能に沿ってご紹介しますが、他のCASB製品においてもルール検討のご参考にしていただけましたら幸いです。 なお、CatoクラウドのCASB機能については、以下の記事もご参照ください。 CatoクラウドのCASBについて Catoクラウドのセキュリティオプション CASB について解説します。 blog.usize-tech.com 2023.09.12 Catoクラウドでアプリケーションを制御するには CASB機能のApplication Controlの設定方法や実際にどのような制限ができるのかについて解説していきたいと思います。 blog.usize-tech.com 2023.11.02 CASBではどんな制御ができる? CASBでの制御は、次世代ファイアウォール(L7FW、NGFW)でのアクセス制御とは少し違います。 次世代ファイアウォールでの制御 アプリケーション識別をして、そのアプリケーションへの通信を許可・拒否することができる。 例) X(旧Twitter)へのアクセスを拒否する。閲覧も投稿もできない。 CASBでの制御 アプリケーション識別をして、そのアプリケーションの 特定の 操作を指定して許可・拒否 することができる。 例) X(旧Twitter)の閲覧は許可するが、投稿のみ禁止することができる。 このような違いがあるため、CASBのルール作成においては、許可・拒否するアプリケーションに加えどの操作を許可・拒否するかを検討する必要があって、検討が難しく感じられるのではないかと思います。 なお、Catoクラウドにおいては、CASBはオプション機能となっています。CASBオプションを追加することで、クラウドサービスに対する操作など、詳細な情報が取得できるようになります。 CASBでのよくある制御ルール例 では、CASBを導入されている企業ではどのような制御をされているのでしょうか。SCSKで実際にご相談を受けたり、設定をご案内する中で多い例をご紹介します。 クラウドサービスでの個人アカウント利用の制限 会社で利用するクラウドサービス、具体的にはMicrosoftのM365やGoogle Workspaceについて、 会社のメールアドレスでのログインを許可するが、その他のメールアドレスでのログインを拒否する という設定です。 この設定により、会社の端末から個人のGoogleDriveに業務情報をアップロードするといった操作を抑止できます。 また、同様にChatGPTへの社内情報のアップロードを抑止する目的で、OpenAIへのログインを制御しているご利用例もあります。 Catoクラウドでの設定例 以下は、CatoクラウドのCASB機能であるApplication Controlでの設定例です。それぞれ上の行で会社アドレスでのログインを許可し、下の行でその他のすべてのログインを拒否する設定です。 なお、Catoクラウドではこの他にTenant Restriction(旧名称:Header Injection)機能を利用し、特定のサービスへの通信時にHTTPヘッダを挿入することが可能です。これにより、クラウドサービス側で、アクセス可能なアカウントやテナントを制限するなどの動作が可能です。詳細は下記記事をご参照ください。 Catoでやる「Microsoft 365」のテナント制御~「Header Injection」機能の紹介~ Catoの「Header Injection」機能を使って「Microsoft365」のテナント制御を実施する方法を紹介します。 blog.usize-tech.com 2024.07.12 ファイル共有サービスへのアップロードの制限 Dropbox、boxなどといった、 ファイル共有サービスやオンラインストレージに対し、アップロードのみを拒否する 設定です。 これらのサービスは、取引先等からのファイル送付に利用されることもあるため、アクセス自体を拒否してしまうとやりとりに支障が出てしまいます。このため、以下のようなルールにされる場合が多いです。 自社で契約しているファイル共有サービスは全アクションを許可 それ以外のファイル共有・オンラインストレージは、アップロードのみを拒否 (閲覧・ダウンロードは可能) Catoクラウドでの設定例 Custom Categoriesにて、アップロード拒否対象とするカテゴリを作成し、 Application Controlにて、Dropboxのみ全アクションを許可、その他Custom Categoriesに対するUploadのみを拒否とします。 ※2025年1月現在の仕様で、Application Categoriesに対してはActivitiesが指定できないため、Custom Categoriesを作成しています。 SNS投稿の制限 XやInstagram等の SNSに対し、投稿のみを拒否する 設定です。 情報収集のため閲覧は許可したいが、リスク管理上、社内からの投稿はできないようにしたいという場合に有効です。 Catoクラウドでの設定例 例として、広報担当のみは投稿含めすべての操作を許可し、その他ユーザは投稿を拒否する設定です。 リスクが高いクラウドサービスの利用制限 世の中にはクラウドサービスが無数にあり、利用者がその一つ一つの安全性を判断したり、ルールを設定するのは現実的に不可能です。 この問題への解決策として、各CASBではクラウドサービスに対し独自のリスク判定を行っており、このリスク判定をもとに、利用者がルールを設定することが可能です。 Catoクラウドでの設定例 Catoクラウドでは、クラウドサービスの認定取得やセキュリティ対策状況をもとに、1(低)~10(高)のリスクスコアをつけています。例として、Gmailのリスクスコアは「4」です(2025年1月時点)。 このリスクスコアを元に、 スコア8以上のクラウドサービスはアクセスを拒否する などの設定を行うことで、セキュリティリスクが高いと判定されたサービスの利用を制限することができます。 すべてのクラウドサービスへのアップロードをログに記録 クラウドサービスごとのCASBルールを設定した上で、その他すべてのクラウドサービスに対し、 ファイルのアップロード動作をログに残す設定 です。 万が一情報の持ち出し等があった場合に、ログから追えるようにしたいという目的です。 Catoクラウドでの設定例 すべてのクラウドサービスへのUploadを、許可はするが、Event(ログ)に残すという内容です。 補足 CatoクラウドのCASB機能では、ルールを全体にかけるだけでなく、ユーザやグループを指定して設定することもできるので、例えば個人情報を扱う部署にはより厳しいルールを適用したり、特定のユーザはルールの対象外にしたりといった、細かな設定が可能です。 また、設定例の中にもあるように、指定の動作について、拒否ではなく「許可するがログに残す」「許可するが管理者にメール通知する」といった指定も可能です。 拒否ルールを急に設定すると業務に支障が出る場合もあることから、 まずは「ログに残す」設定でルール適用し、その後ログ状況を見て拒否に変えていく運用がおすすめ です。 最後に 本記事では、実際にCASBで設定されることの多いルールをご紹介しました。CASB導入時のルール検討にご活用いただけますと幸いです。 自社環境に合ったCASB制御を行うには、クラウドサービスの実際の利用状況を定期的に確認し、自社のポリシーと照らし合わせてルールをブラッシュアップしていく必要があります。「可視化(Visibility)」「アセスメント(Assessment)」「強制(Enforcement)」「防御(Protection)」のサイクルの運用です。 SCSKでは、運用経験豊かなエンジニアが多数在籍しており、お客様にあわせたご支援が可能です。お困りごとなどございましたら、ぜひご相談ください。
Amazon Athena と AWS Glue を使用して、Amazon S3 上にある CSV データに対してクエリを実行してみたので、その手順をまとめます。 AWS Glue と は AWS Glueは、Amazon Web Servicesが提供するフルマネージドのETL(抽出、変換、ロード)サービスです。このサービスは、大量のデータを効率的に準備し、変換し、異なるデータストア間で移動させることを目的としています。 Glueを利用するにあたり、登場する用語について簡単に説明します。 ETL(Extract, Transform, Load): データを抽出(Extract)し、変換(Transform)し、ロード(Load)するプロセスを指します。AWS GlueはこのETLプロセスを自動化および簡素化するためのサービスです。 AWS Glue Data Catalog: AWS Glue Data Catalogは、メタデータを管理するための中心的なサービスです。データストアのスキーマ情報、データの場所、その他のメタデータを保持し、データの整理と管理をサポートします。 AWS Glue データベース: AWS Glueデータベースは、Data Catalog内でテーブルをグループ化するための論理的なコンテナです。データベースはスキーマを含んでおり、データの整理とスキーマの一貫性を保つために使用されます。 AWS Glue テーブル: AWS Glueテーブルは、データとその構造に関するメタデータを表します。通常は特定のデータセットのスキーマ情報を含み、データドリブンなアプリケーションで使用されます。 クローラー: クローラーは、自動的にデータソースを探索し、データカタログにメタデータを登録するためのコンポーネントです。クローラーはデータの構造を解析し、テーブル定義を生成または更新します。 AWS Glue ジョブ: AWS Glueジョブは、ETL(抽出、変換、ロード)プロセスを実行するための基本単位です。ジョブを作成して、データを変換し、必要な出力先にロードすることができます。 AWS Glue 接続: AWS Glue接続は、Glueがデータストアにアクセスする際の接続情報を保存します。ホスト名、ポート番号、認証情報などが含まれ、データアクセスを安全かつ効率的に行えます。 Amazon Athena とは Amazon Athenaは、Amazon Web Services(AWS)が提供するサーバーレスのインタラクティブクエリサービスです。Athenaを使用すると、Amazon S3に保存されているデータに対して直接SQLクエリを実行し、複雑なETLプロセスを必要とせずにデータを分析できます。 Amazon Athenaには、以下の特徴があります。: サーバーレス: Athenaは完全にサーバーレスであるため、インフラストラクチャの管理が不要です。ユーザーはクエリの実行に対してのみ料金を支払います。 SQLサポート: Athenaは標準SQLを使用してクエリを記述できるため、SQLに精通したユーザーが簡単に利用できます。 データソースのサポート: 主にAmazon S3に保存されたデータに対してクエリを実行しますが、Athenaを他のデータソースに接続することも可能です。 使いやすさ: ノードやクラスタの管理が不要で、クエリを書くだけでデータ分析を始められます。 統合機能: Amazon QuickSightなどの他のAWSサービスと統合しやすく、ダッシュボードを通じたビジュアル分析が可能です。 データ形式のサポート: AthenaはCSV、JSON、ORC、Avro、Parquetなど、さまざまなデータ形式に対応しています。 これらの特徴により、Amazon Athenaはデータアナリストやデータサイエンティストにとって、スピーディーで効果的なデータ分析ツールとなっています。 やってみた AWS Glue 1.データベースの作成 まずはクローラの出力先となるデータベースを作成します。 ここでは名前のみ指定しました。 2.クローラーの作成 クローラーの名前を入力します。 「Add a data source」からデータソースを指定します。 今回はS3のデータを利用したいので、データを配置したS3のパスを指定します。 また、「Subsequent crawler runs」では、クローラーの再実行時にどのフォルダをクロールするかを選択できます。 今回は、全て再クロールする「Crawl all folders」を選択しました。 データソースを指定できたら「Next」へ進みます。 IAMロールを選択します。 今回は「AWSGlueServiceRole」およびソースデータを配置したS3へのアクセス権限を付与しました。 クローラの出力先を指定します。 「1.データベースの作成」で事前に作成したデータベースを指定します。 設定に問題がなければ「Create crawler」をクリックします。 以上でクローラの作成は完了です! 3.クローラの実行 早速クローラを実行してみます。 作成したクローラの詳細画面から「Run crawler」クリックします。 出力先に設定したデータベースを確認すると、クローラによりS3上のデータが自動で読み取られ、構造化されたインデックスがカタログ(Glue Data Catalog)として保存されています。 Amazon Athena クエリの実行 Athenaでクエリを実行してみます。 Athenaでのクエリ実行時に、データベースにGlue Data Catalogのデータベースを指定することで、データベース内のテーブルやテーブル内の項目名を使うことができます。 データソース欄で「AWSDataCatalog」を指定すると、データベース欄からGlueで作成したデータカタログ内のデータベースが選択できます。 クエリを実行してみました。 select文を実行して、テーブル内の項目を抽出することができました! さいごに S3のデータをGlueでデータベースに格納して、Athena で必要なデータを取得するまでの手順をまとめました。Glueを利用することで簡単にS3上のデータを構造化し、容易に必要な値を取得することができました。 次回はAthenaのデータをQuickSightに連携し、可視化してみたいと思います。
こんにちは。ひるたんぬです。 本年もよろしくお願いいたします。今年は巳年ですね。 小さい頃に「十二支は神様の号令の下、競争して早い順に決まった」と言われた記憶があるのですが、実際に本当に早い順に十二支を並べるとどのようになるのか、ふと気になってしまいました。 調べたところ、すでにこの疑問に対して調査をしてくださっていた記事がありましたので一部を抜粋してご紹介します。 本やネットに速度が出ているものは、それを採用し、それ以外のものは、筆者の経験その他から強引に算出するなどした結果、13匹の動物たちの速度は以下のようになった。 子=鼠:時速10km 丑=牛:時速4km(注1) 寅=虎:時速64km 卯=兎:時速72km 辰=竜:時速360km以上(注2) 巳=蛇:時速16km(注3) 午=馬:時速68km(注4) 未=羊:時速13km(注5) 申=猿:時速30km(注6) 酉=鶏:時速18km(注7) 戌=犬:時速36km(注8) 亥=猪:時速45km 猫:時速48km(注9) 引用:Yahoo! ニュース「 「十二支」の順番がナットクできない。実際の動物のスピードを考えると、どんな順番になるか? 」 上記から、令和版の十二支は「辰卯午寅猫亥戌申酉巳未子」となるようですね。竜が圧勝のようです。 戦略を練って二位に漕ぎ着けていた牛は、スタメンから外れてしまいました。 また、これを元に考えると、今年は亥年ということになりますね。 …さて、今回はIaCというものを少し使いこなせるようになって調子に乗っていた結果、大きな落とし穴にはまってしまったので、自戒の意味も込めてご紹介いたします。 やりたいこと とあるログをEventBridgeを経由してCloudWatch Logsに送ろう!というよくあるものです。 せっかくなのでマネジメントコンソールからではなく、IaC(CloudFormation)を使用して構築しよう!ということになりました。 やったこと マネジメントコンソールではEventBridgeのルール作成とCloudWatch Logsのロググループ作成のみで実施できたので、同じようにCloudFormationを書いてみました。今回は検証のため、EC2に関する任意のイベントをCloudWatch Logsのロググループへ転送することにします。 AWSTemplateFormatVersion: '2010-09-09' Resources: RuleEC2Activity: Type: AWS::Events::Rule Properties: EventPattern: { "source": ["aws.ec2"] } Targets: - Arn: !GetAtt LogEC2Activity.Arn Id: LogGroup LogEC2Activity: Type: AWS::Logs::LogGroup Properties: RetentionInDays: 14 LogGroupName: /aws/events/EC2Activity 上記のファイルのデプロイは問題なく完了しました。 起きたこと ログへ転送がされるかを確認するために、EC2インスタンスを立ち上げました。しかし、待てど暮らせどログは出力されません。 おかしいな…と思い、EventBridgeの当該ルールのモニタリングをチェックすることにしました。すると… EventBridgeのルール自体は動いていたのですが、そのすべての実行が失敗(FailedInvocationsに記録)していたのです。 原因調査 こんなときに役に立つのは、インターネットに広がる知識の海です。調査してみたところ、公式ドキュメントに気になる記載がありました。 CloudWatch Logs がルールのターゲットである場合、EventBridge がログストリームを作成し、CloudWatch Logs がログエントリとしてイベントからテキストを保存します。EventBridge がログストリームを作成してイベントを記録するためには、EventBridge が CloudWatch Logs に書き込むことを可能にするリソースベースポリシーを CloudWatch Logs に含める必要があります。 AWS Management Console を使用して、CloudWatch Logs をルールのターゲットとして追加する場合、リソースベースのポリシーは自動的に作成されます。AWS CLI を使用してターゲットを追加し、ポリシーがまだ存在しない場合は、作成する必要があります。 引用:AWS「 Amazon EventBridge ユーザーガイド:Amazon EventBridge のリソースベースのポリシーを使用する 」 今までの私は前者(マネジメントコンソールでの操作)しか行ったことがなかったので気づかなかったのですが、実はリソースベースポリシーの設定が必要なようですね。言われてみれば、権限も設定していないのに書き込めるのは不思議ですもんね。。。 解決に向けて… リソースベースポリシーをIaCにて設定 後述する参考記事によると、CloudFormationでリソースベースポリシーを設定できるようなので、まずはこちらを試してみます。 下記のテンプレートファイルを作成し、新規でスタックを作成してデプロイします。 PolicyDocument内のアカウントIDやロググループ名などは適宜修正してください。 AWSTemplateFormatVersion: '2010-09-09' Resources: EventBridgeToCWLPolicy: Type: AWS::Logs::ResourcePolicy Properties: PolicyDocument: "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"TrustEventsToStoreLogEvent\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":[\"delivery.logs.amazonaws.com\",\"events.amazonaws.com\"]},\"Action\":[\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Resource\":\"arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/events/*:*\"}]}" PolicyName: TrustEventsToStoreLogEvents これにより、正常にログが転送されました! また、このスタックを削除することによりポリシーがなくなり、ログ転送ができなくなる点も確認できました。 リソースベースポリシーをマネジメントコンソールにて設定 では、マネジメントコンソールでルールを作成した場合はどうなるのでしょうか。 リソースベースポリシーが裏で設定されているとのことだったので、その挙動を中心に確認してみます。 ルールを作成した後にCloudShellにてリソースベースポリシーの有無を確認してみると… 先ほどIaCにて設定したポリシーと同様のものが付与されていました。 知らないところで動かせるようにしてくれていたのですね。 …ここで気になった点がありました。 「このマネジメントコンソールで作ったルールを消したらリソースベースポリシーはどうなっちゃうの問題」です。 実際にやってみる他ありませんね!やってみました。 …残っていました。そのため、 マネジメントコンソールからEventBridgeのルールを一度でも作成している場合、このブログのような症状には出会わない可能性もある ということですね。 おわりに 改めて、AWSの権限に対する考え方を痛感する良いきっかけとなりました。 何事にも許可がいる…現実でもクラウド上でもそんな認識でいるのが大事なのかなと思います。 また、今回の記事は以下を参考に作成いたしました。Web上の皆さまの記事にはいつも助けられてばかりです。。 CloudWatch LogsをターゲットとするEventBridgeルールをCloudFormationで作成するには | DevelopersIO dev.classmethod.jp 上記サイトにも記載がありましたが、このリソースベースポリシーはマネジメントコンソール上から確認することができないようです。(CLIを用いて確認する) あまり需要はないかもしれませんが、これも気軽に確認できるようになるとより良いのかな…と思った次第です。 余談ですが、十二支の昔話はYouTubeでも観れるのですね。
みなさん、Amazon Redshift Serverlessを使ったことはありますか? プロビジョンドタイプと異なり、サーバレスの強みを生かした高可用性、高スケーラビリティ、コストメリット有りと使いやすさ抜群のサーバレスタイプですが、 サーバレス特有のコンピューティングキャパシティの考え方を理解すると、よりメリットを享受することが出来そうです。 今回自分が携わったプロジェクトでRedshift Serverlessを構築したので、その際に分かったこと・試したことを記事にまとめてみました。 ※最新情報についてはAWS公式ドキュメントを参照ください。 Redshiftプロビジョンドタイプとサーバレスタイプの違い まずRedshiftとは、 フルマネージド型のデータウェアハウスサービス です。 高速なリアルタイム分析が得意で、BIツールと連携も可能なため、企業の意思決定に大いに役立つサービスです。 プロビジョンドタイプはクラスタの管理が必要で、クラスタのサイズを手動で設定する必要がありますが、サーバレスタイプは ワークロードに応じて自動でスケーリング します。 後に説明する「ベース容量」から「最大容量」までの範囲で自動でスケーリングがおこなわれるため、コスト効率化、運用負荷削減に有効です。 コンピューティングキャパシティの考え方 Redshift Serverlessでは、コンピューティングキャパシティを RPU(Redshift Processing Unit) という単位で設定します。 1つのRPUは16GBのメモリを提供します。 設定箇所としては「ベース容量」、オプションで「最大容量」、「使用制限」があるので、それぞれワークロードのクエリパフォーマンスや目標コストに応じてRPUを設定していきます。 ベース容量(設定はマスト) クエリの処理に使用するコンピューティングリソースの基本容量をここで設定します。 デフォルト値は128RPUで、8RPU から512RPU まで8単位で調整可能です。 ベース容量を大きく設定することで、クエリのパフォーマンスが向上します。 最大容量(設定はオプション) Redshiftが スケールアップできるRPUの上限 をここで設定します。 クエリ実行開始時は「ベース容量」で設定したRPUで処理が実行されますが、クエリの負荷に応じてこの「最大容量」まで自動でスケーリングされます。 使用制限(設定はオプション) Redshiftの 使用を制限したい場合 はここで設定します。 頻度(毎日/毎週/毎月)、制限RPU数、アクション(ログ出力/アラート/クエリ無効)が設定できます。 Redshiftはクエリの実行に使用されたRPU時間に応じて課金されるため、これ以上コストをかけたくない、という目安がある場合には設定がお勧めです。 ベース容量と最大容量の決め方 ベース容量と最大容量はどのように定めるのが良いでしょうか? また設定後に「容量を変更すべき」という判断の基準をどのように持っておけば良いのでしょうか。 ここからは自分が実際に試してみた設定値決めの方法をご紹介します。 ざっくりとRPU設定値を決める RPUは基本的には、 「データ量」 と 「クエリの複雑さ、頻度」 で考えていきます。 仮で、以下要件の場合のベース容量を考えてみます。 ・Redshiftでの分析の元となるデータ量は3TB程度。 ・分析のために実行するクエリは集計などのSQL文。実行時間は平日の勤務時間内。 「データ量」で考えると、公式ドキュメントで「8、16、24RPU の基本RPU容量は、128TB 未満のデータが必要なワークロードを対象としています。」との記載があり、今回の対象データは3TBであることから、8~24RPUを選択の候補とします。 「クエリの複雑さ、頻度」で考えると、正直どの程度データ分析でRedshiftを使用するかによるため、一旦16RPUを選択し、検証の中で設定値を調整していく形とします。 検証で設定値をチューニングする 上記の形で一旦設定したRPUが適切かどうかを実際の利用シーンを想定してクエリを実行してみることで、設定値の妥当性を判断します。 RPU値をチューニングする時には、以下2点をポイントとしてチェックすると良いです。 ComputeCapacityメトリクス クエリ実行すると様々なメトリクスが取得できますが、その中の[ComputeCapacity]メトリクスをCloudWatchで確認することで、クエリ実行時に使用されているRPUが分かります。 メトリクスの値がベース容量のRPUから最大容量のRPUにスケールアップし、最大容量に近い時間が多い場合は「ベース容量が足りていない」と判断する材料になります。 ただし、クエリについては単一のクエリからの負荷増加に応じたRPUスケールアップはおこなわれず、 同時実行クエリのみがスケールアップの対象 であることを念頭においておくことが必要です。 クエリ実行時間 以下の方法でクエリ実行時間を確認し、 想定内の実行時間であるか を評価する方法も有効です。 SYS_QUERY_HISTORYビュー Redshift内でSQLを実行しビューを表示させ、クエリ実行に関する詳細情報を確認する方法。 例えば「elapsed_time」を表示させると、クエリの実行時に消費した合計時間がわかります。 elapsed_time :クエリの実行が消費した合計時間(マイクロ秒)。 監査ログ 監査ログを有効にし、クエリ実行時間に関する情報を確認する方法。 QueryDuration :クエリを完了するまでの平均時間(マイクロ秒)。 QueryRuntimeBreakdown :クエリステージごとの、クエリが実行された合計時間(ミリ秒)。 まとめ コンピューティングキャパシティの考え方を理解して、パフォーマンス的にもコスト的にも有効に使用できると良いですね。 最後まで読んでいただきありがとうございました! この記事が皆さんのお役に立てれば幸いです。
こんにちは、2024年度入社の秋葉です! 2025年の1月14日を持ちまして、約3ヶ月のクラウド人材研修が終了いたしました。 クラウドは利用しているけど、”クラウド人材研修”って一体何?と疑問に思っているあなたに向けてクラウド人材研修とは何か、その具体的な内容、そして研修によって何を得ることができたのか記載していきます! クラウド人材研修の背景・目的 近年の急速なデジタル化は、市場や社会の変化を激化させており、顧客のDX推進を支援するためには、クラウドネイティブな知識とアジャイルな開発スタイルを備えた、即戦力となる人材が不可欠です。 しかし、経験豊富なクラウドエンジニアは不足しており、育成が急務となっています。特に、アプリケーション開発とインフラ運用、双方の知識とスキルを兼ね備えた「 フルスタック人材 」の育成は喫緊の課題です。 この背景から、SCシステム事業本部では新人育成プログラムとしてクラウド人材研修を実施しています。本研修の目的は、将来的なフルスタック人材育成を視野に入れ、クラウド基盤技術の習得、アジャイル開発手法の実践を通じて、クラウドネイティブな開発スタイルを早期に経験させることです。 技術スタック フルスタックを目的とした技術スタックはAWSを基本に以下のように構成されていました! Javaアプリケーション SpringBoot IaC クラウド(AWS CloudFormation) コンテナ(Docker/Amazon ECR/Amazon ECS) CI / CD イミュータブルインフラストラクチャ ビルド/デプロイ自動化(AWS CodePipeline) ステートレス(Amazon ElastiCache) 負荷分散 / 冗長化 ロードバランサー(Elastic Load Balancing ALB) 監視 / 通知 監視(Amazon CloudWatch Alarm) 通知(Amazon SNS) 研修内容 CNCF Cloud Native Trail Map をベースに構成したLesson0~Lesson9までの全10レッスンのカリキュラムで、クラウドネイティブの基礎から応用までを網羅的に学習してきました! 各Lessonのテーマは以下のようになっています。研修は、2人1チームの計8チームで進められておりチーム内だけでなく各チーム間で協力して研修に取り組んだことで全チームが期間内にすべてのLessonを終えることができました! Lesson Theme Lesson 0 Preparation Lesson 1 Introduction Lesson 2 IaC Level 1 Lesson 3 IaC Level 2 Lesson 4 Redundancy Lesson 5 Containerization and Orchestration Lesson 6 CI/CD Lesson 7 Observability Lesson 8 Operations Automation Lesson 9 Disaster Recovery 全Lessonが終了すると以下のような構成図になります。 この一連のレッスンでは、Spring Bootを用いたWebアプリケーションをAWSクラウド上で構築し、CI/CDパイプラインによる 自動デプロイ と 監視機能 を備えた、 堅牢なシステム の実現を目指します。 Lesson0では、Spring Boot・AWS・Gitなど開発に必要なツールの使い方や学習から始まり、最後の Lesson 9 では、災害などに備えて、システムをより堅牢にするための仕組みを作りました。具体的には、Lesson9ではDNS Failoverを実現することで東京リージョンで障害が発生した場合に備え、Webアプリケーションを自動的に別のリージョン(バージニア北部)に切り替えて、静的なエラー画面を表示する仕組みを構築しました。 このように、この研修を通して、Webアプリケーションの 開発 から 運用 、そして 災害対策 まで、一連の流れを学ぶことができたと思います! 研修を終えた新人たちの声 Kさん 当たり前のことだがコミュニケーションを密に取ることが大切だということを再実感した。また、問題が発生した際に原因の切り分けを行いながらトラブルシューティングを行うスキルが身に染み付いたと思っているので今後の業務に活かしていきたい! Sさん 権限の管理に関して、必要最低限のポリシーをアタッチすることが簡単なようでとても難しかった。必要以上のポリシーを付与してついつい楽をしがちだが、不要なポリシーが無いか確認し同じロールを使いまわさないことを意識して業務に臨みたい。 Tさん エラー発生時に画面共有しながら、ペアプログラミングできた経験はすごく良かったと感じた。今後の案件では研修を通して身に着けた、明確な作業内容報告の実施をチームメンバーに対して心がけていきたい! Oさん 研修を通して一番忍耐力が身についたと思いました。開発中1つエラーを解決したら別のところでまたエラー、エラー三昧になってしまうこともあったけどそれに負けず最後までやり遂げれました。今後の業務にもエラー三味に負けない心で挑みたい! 終わりに 3ヶ月間のクラウド人材研修は、私にとって大きな経験であり、同時に大きな成長の機会となりました。右も左も分からない状態からスタートしましたが、CNCF Cloud Native Trail Mapをベースとした体系的なカリキュラム、そしてチームメンバーや講師の方々のサポートのおかげで、クラウドネイティブ開発の基礎をしっかりと築くことができました。 研修を通して特に印象に残っているのは、実践的な課題を通じて、座学だけでは得られないリアルな経験を積むことができた点です。エラーに遭遇した時の原因究明やトラブルシューティング、チームでの協力作業など、実際の開発現場で直面するであろう課題に取り組むことで、問題解決能力やコミュニケーション能力を向上させることができました。また、Kさんが述べているように、チームメンバーと密にコミュニケーションを取りながら課題に取り組む重要性を改めて認識しました。 最後に、この研修に関わってくださった全ての方々に感謝申し上げます。ありがとうございました!
AWS System Manager (SSM) の Patch Manager 機能を利用すると、OS パッチ適用を自動化できるそうです。 すごく便利だと思ったので、設定手順をまとめてみました。 アーキテクチャ 今回は、下図の構成で実装してみました。 Systems Managerとは、 オンプレミスでもマルチクラウド環境でも、AWS 内のノードを広範囲にわたって一元的に表示、管理、および運用できます。統合コンソールエクスペリエンスのリリースにより、Systems Manager では AWS アカウントとリージョン全体にわたってよく使用するノードタスクを完了できるさまざまなツールが統合されています。 AWS Systems Manager とは – AWS Systems Manager Patch Managerとは、 オペレーティングシステムとアプリケーションの両方にパッチを適用することができます。 AWS Systems Manager Patch Manager – AWS Systems Manager 設定手順 今回は、以下手順でOS「Windows2022」のEC2に、毎月第4月曜日の9:00にパッチ適用する手順をまとめました。 1.パッチベースラインの作成 2.パッチグループの作成 3.メンテナンスウィンドウの作成 4.ターゲットの登録 5.Run Commandタスクの登録 1.パッチベースラインの作成 AWS System Managerの左メニュー「パッチマネージャー」をクリックし、「パッチベースライン」>「パッチベースラインを作成する」をクリックします。 ▼ パッチベースラインの詳細 「名前」欄は、任意のパッチベースライン名を入力します。 「オペレーティングシステム」欄は、パッチ適用対象のインスタンスのOSを選択します。 今回は、windowsを選択しました。 ▼ オペレーティングシステムの承認ルール 「製品」欄は、パッチ適用対象のインスタンスのOSイメージを選択します。 「分類」欄は「CriticalUpdates」、「SecurityUpdates」を選択します。 「重要度」欄は「Critical」、「Important」を選択します。 「コンプライアンスレポート」欄は、「重大」を選択します。 そのほかはデフォルトのままにします。 以下の欄はデフォルトのままにし、「パッチベースラインの作成」をクリックします。 ▼アプリケーションの承認ルール ▼パッチの例外 ▼タグの管理 2.パッチグループの作成 作成したバッチペースラインのIDをクリックし、「アクション」>「パッチグループの変更」をクリックします。 「バッチグループ」欄に任意のパッチグループ名を入力し、「追加」をクリックします。 入力したパッチグループ名が追加されたことを確認後、「閉じる」をクリックします。 3.メンテナンスウィンドウの作成 AWS System Managerの左メニュー「メンテナンスウィンドウ」をクリックし、「メンテナンスウィンドウの作成」をクリックします。 ▼ メンテナンスウィンドウの詳細の入力 「名前」欄は、任意のメンテナンスウィンドウ名を入力します。 そのほかはデフォルトのままにします。 ▼ スケジュール 「次で指定」欄は、「CRON/Rate 式」を選択し、実行させる時間帯をcronで記載します。 ※今回は第4月曜日の9時に実行させたいので、cron(00 09 ? * MON#4 *)で登録してみます。 「期間」欄は、「3」時間を選択します。 「タスクの開始を停止する」欄は、「0」を選択します。 「スケジュールのタイムゾーン」欄は、任意のタイムゾーンを選択します。 ※今回は「(GMT+09:00) Asia/Tokyo」を選択しました。 そのほかはデフォルトのままにします。 ▼ スケジュール デフォルトのままにし、「メンテナンスウィンドウの作成」をクリックします。 4.ターゲットの登録 作成したメンテナンスウィンドウのIDをクリックし、「アクション」>「ターゲットの登録」をクリックします。 ▼ Maintenance window target details 「Target name」欄は、任意のターゲット名を入力します。 そのほかはデフォルトのままにします。 ▼ ターゲット 「ターゲットの選択」欄は、「インスタンスタグを指定」を選択します。 「インスタンスタグを指定」欄は、パッチ適用対象のインスタンスにアタッチしている任意のタグを入力し、「Add」をクリックします。 入力したタグが追加されたことを確認後、「Register target」をクリックします。 5.Run Commandタスクの登録 作成したメンテナンスウィンドウのIDをクリックし、「アクション」>「Run Commandタスクの登録」をクリックします。 ▼ メンテナンスウィンドウタスクの詳細 「名前」欄は、任意のメンテナンスウィンドウタスク名を入力します。 そのほかはデフォルトのままにします。 ▼ コマンドドキュメント 「ドキュメント」欄は、「AWS-RunPatchBaseline」を選択します。 そのほかはデフォルトのままにします。 ▼ ターゲット 「登録済みターゲットグループの選択」を選択し、「4.ターゲットの登録」で設定したターゲットを選択します。 ▼ レート制御 「同時実行数」欄は、「1」ターゲットを選択します。 「エラーのしきい値」欄は、「1」エラーを選択します。 ▼ IAM サービスロール パッチ適用用のIAMロールを選択します。 ▼ 出力オプション 「CloudWatch output」を選択し、任意のロググループ名を入力します。 ※パッチ適用の実行結果がCloudWatch logsに出力されます。 ▼ SNS通知 デフォルトのままにします。 ▼ パラメータ 「Operation」欄は、「Install」を選択します。 「Snapshot Id」欄は、「 {{WINDOW_EXECUTION_ID}} 」を入力します。 そのほかはデフォルトのままにします。 ▼ CloudWatch alarm デフォルトのままにします。 すべての項目を設定後、「Run Commandタスクの登録」をクリックします。 パッチ実行結果確認 パッチ適用結果は以下の方法で確認することができます。 ①「メンテナンスウィンドウ」>「履歴」 ②CloudWatch logsに出力する設定をした場合は、 「ロググループ」>「ロググループ名」>「ログストリーム」 まとめ 今回は、Windowsのパッチ適用を設定するところまでをまとめてみました。 適用結果をSNSで通知させる方法もあるみたいなので、次の記事でご紹介します。 パッチ適用以外にもSSMの機能でいろいろできそうだと思ったので、もう少し調べてみようと思います。
こんにちは、冨岡です。 私は12月までAWSの研修を受けていました。 今では案件に入り、私の社会人生活が始まった気がします。 しかし私が扱うのはAWSではなく、なんと Azure 。 心を入れ替えて頑張ります! はじめに 私が今取り組んでいるのは、アプリ機能の新規開発と既存システムを改修し Azure上へ移設する案件です。 Azure上にVM、ストレージ、ネットワーク等々を構築しています。 これらのサービスは本番環境として東日本リージョン、 災対環境 として西日本リージョンで構成します。 私はこの 災対環境 を担当しております。 私が興味を持ったサービスは Azure Spring Apps です。 オンラインWebアプリケーションを実行する用途で使われるサービスになります。 実はこのAzure Spring Apps、 西日本リージョンで非対応 なのです! 代わりに 東南アジアリージョン に作成しますので、備忘録として記事にまとめます。 災対環境とは 本番環境障害によりシステム継続負荷の際に稼働する環境。 本番環境が構築される東京リージョンの 大規模障害時 において、 西日本・東南アジアリージョンでシステムを構築します。 Azure Spring Apps Azure Spring Appsとは コードを変更せずに、Spring BootアプリケーションをAzureにデプロイできるPaaSのサービス。 私の環境でHello World表示させてみます。 参考: クイックスタート – 初めてのアプリケーションを Azure Spring Apps にデプロイする | Microsoft Learn 対応リージョン 公式ドキュメント見ましたが、やはり西日本リージョンなかったです。 Azure Spring Apps の信頼性 | Microsoft Learn 試用 Microsoft Learnに沿って、Azure Spring Appsでアプリをデプロイしてみたいと思います。 Azure Spring Appsの作成 Azureポータル上でも西日本リージョンがないこと確認 アプリをデプロイ ブラウザからHello Worldにアクセスできること確認 案件ではちゃんとしたシステムにアクセスできるようになると考えると、胸が高まります。 注意 公式ドキュメントに、 廃止 のお知らせがありました。 Azure Container Apps への移行が推奨されていました。 こちらを使うことなったら、また記事にしようと思います。 Azure Spring Apps の提供終了のお知らせ | Microsoft Learn さいごに TechHarmonyにはAzureの記事がAWSと比較して少ないと感じました。 私がたくさん書いてAzureの記事を増やそうと思います。
SCSKの畑です。7回目の投稿です。 今回は小ネタ・・のつもりだったのですがいくつか加筆していたらそれなりの分量になってしまいました。内容は正直タイトルから大体想像付くところだとは思うのですが、ご了承ください。 アーキテクチャ概要 今回はタイトル通り AWS AppSync と AWS Lambda がメインですが、少しだけ Amazon Redshift も話に出てきます。 背景 ほぼ毎回説明しているかもしれませんが、本アプリケーションの主目的(機能)はデータベース/DWH のテーブルデータメンテナンスです。本アーキテクチャ構成上、アプリケーションと Redshift の間でテーブルデータの読み書きをする場合は AppSync 及び Lambda を介するため、対象テーブルのデータサイズ次第で AppSync もしくは Lambda のペイロードサイズに制約を受ける可能性があります。 AppSync は、レスポンス/レスポンス共に最大ペイロードサイズが 5MB です。 厳密には、評価されたマッピングテンプレートの最大サイズが 5MB という解釈が正しいようです。下記 URL における「evaluated resolver, function, or handler template」という表現ですね。 AWS AppSync endpoints and quotas - AWS General Reference The following are the service endpoints and service quotas for this service. To connect programmatically to an AWS servi... docs.aws.amazon.com Lambda は、同期呼び出しにおける最大ペイロードサイズはリクエスト/レスポンス共に 6MB です。 Lambda quotas - AWS Lambda Maximum sizes, limits, and quotas for Lambda functions and API requests. docs.aws.amazon.com よって、今回のアーキテクチャにおいて、AppSync API 実行時の入出力データサイズはいずれも 5MB 未満に抑える必要があります。 なお、ダイレクト Lambda リゾルバを使用した場合は、最大ペイロードサイズが Lambda の値に準拠するようです。(=最大 6MB)ただ、Amplify で @function ディレクティブを使用して Lambda を query なり mutation に紐付けた場合は、マッピングテンプレートを使用する通常の Lambda リゾルバになるようです。gen2 であればオプション等で対応していたりするんでしょうか・・? 今回はダイレクト Lambda リゾルバの使用が必須となるような要件はなかったため、使用していません。 ダイレクト Lambda リゾルバー (VTL) を使用した VTL マッピングテンプレートの無効化 - AWS AppSync ダイレクト Lambda リゾルバーを使用して VTL テンプレートのをバイパスする方法について説明します。 docs.aws.amazon.com もちろん、アーキテクチャ設計時にはこの点は考慮に入れており、以下2点より当面は特に対策しなくても大丈夫だろうと考えていました。 本アプリケーションにおけるメンテナンス対象はいわゆる「マスタテーブル」であるため、データサイズが小さい 「トランザクションテーブル」のようなデータサイズの多いテーブルではない 現時点で一番データ量の大きいテーブルのデータサイズが CSV ファイル形式 で 約 800KB である かつ、今後データサイズが爆発的に増大する可能性が少ない ところが、開発中に同テーブルに対するリクエスト/レスポンスのデータサイズを計測してみたところ、 3MB 程度になってしまっていることが判明しました。上記の通りまだ最大サイズ内ではあるものの、既に半分を超えてしまっていることになるため、慌てて原因を調べることになりました。 データサイズ差異の原因 何故このようなデータサイズの差異が生じてしまったのかですが、原因は AppSync 及び Lambda の入出力におけるテーブルデータのフォーマットにありました。当初、AppSync のスキーマにおけるテーブルデータは、以下のように 文字列の配列 として定義しており、この形式でAppSync/Lambda で入出力を行っていました。 table_data: [String]! 具体的には、以下のような JSON Lines 形式 のデータを行単位でリストに格納していました。 {"id":"001","value":"sample_data_1", "create_day":"2025-01-01 00:00:00","update_day":null,"creater_name":"admin","updater_name":"","delete_flg":"N" } {"id":"002","value":"sample_data_2", "create_day":"2025-01-02 00:00:00","update_day":null,"creater_name":"admin","updater_name":"","delete_flg":"N" } {"id":"003","value":"sample_data_3", "create_day":"2025-01-03 00:00:00","update_day":null,"creater_name":"admin","updater_name":"","delete_flg":"N" } 以下理由よりトータルで一番楽に実装できると判断したため、このようなフォーマットでデータを保持していた訳ですが・・ Redshift ⇔ Lambda 間のデータ読み書きに COPY / UNLOAD 文を使用しており、そのSQL文からそのまま使用できるフォーマットであるため COPY / UNLOAD 文でサポートされているフォーマットは JSON 含めて複数存在するが、JSON にしておけば後述するようにアプリケーションからも容易に使用できる https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/copy-parameters-data-format.html#copy-json https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_UNLOAD.html アプリケーション側で使用しているテーブル表示用のライブラリにおいて、テーブルのデータを JSON 形式で保持する必要がある JSON Lines形式から変換する必要はあるものの、最小限の対応で済む さて、もう既にお分かりかと思いますが、ここまで 黄色アンダーライン でマークした通り、テーブルデータのフォーマットを JSON Lines 形式で持つようにしたことがデータ量増大の原因となっていました。テーブルデータを同形式で持つということは、当然ながら実データだけでなく JSON フォーマットで付加される情報(列名、中括弧、ダブルクォートなど)のデータも各行ごとに含まれます。つまり、テーブルのデータ量が大きいほど、JSON フォーマットで付加される情報が占めるデータサイズも相対的に大きくなってしまうことになります。 厳密には、列数・列名の長さといったメタ情報や、行数の方が要因としてより多くを占めるものと思いますが・・ そこで、改めて対象テーブルにおける実データ以外のデータサイズを改めて計算したところ、 行数:約 10000 行 1行あたりの JSON フォーマット分のデータサイズ:約 220Byte 計算結果:210 B * 10000 ≒ 2.2MB ということで、当然ですがデータサイズの差異分とほぼ一致する結果となり、裏付けが取れてしまった格好になりました。。というか、実データの約 2.5 倍のサイズとなってしまっているんですよね。どう考えてもサイズ効率は劣悪ですし、他のメンテナンス対象テーブルについても同様の傾向にあることが見て取れましたので、根本的な対策を行うこととしました。 解決策 一方で、JSON (Lines) 形式そのものは実装面から変えたくなかったのでちょっと悩んだのですが、今回のように「とりあえずサイズを小さくできればよい」ケースで最も良く使用される手法を用いてあっさり解決しました。そう、 圧縮 です。 ということで、まずスキーマ定義を文字列の配列から文字列に変更しました。 table_data: String! 後は、Lambda と テーブルデータをやり取りする時に、JSON 形式のデータをダンプしてから圧縮/展開してしまえば OK です。以下、Lambda側 で圧縮したテーブルデータを Typescript 側で展開する場合の実装例を示します。 Lambda JSON 形式のテーブルデータを Lambda 側で圧縮する例です。 table_data_json_base64 = base64.b64encode(gzip.compress(json.dumps(table_data_json).encode('utf-8'))).decode('utf-8') 圧縮する以上、lambda コード内でテーブルデータを JSON Lines 形式で扱う必要性がなくなったため、通常の JSON 配列として扱っています。table_data_json が対象の変数です。 Typescript Lambda / AppSync から受け取った圧縮されたテーブルデータを展開して、JSON 配列に変換する例です。 const table_datas = JSON.parse(pako.ungzip(Base64.toUint8Array(table_data_json_base64), { to: 'string' })) table_data_json_base64 変数に圧縮データが格納されている想定です。また、下記サイト様の情報より、gzip/ungzip 用のモジュールとして pako を使用しています。 zlibでGZIP形式で圧縮された文字列のレスポンスデータをJavaScriptで解凍する - Qiita Lambdaで構築されたAPIで返却値が大きいせいでペイロードのデータサイズ制限(6MB以上は制限に引っかかる)に引っかかってしまうとのことで、Lambda側でgzip圧縮されたデータをフロントで解… qiita.com これらの対応により、対象テーブルデータのサイズを 約 160KB に低減することができました。最大サイズ 5MB と比較しても十分に小さいため、この方式を採用して解決と相成りました。JSON 形式のデータフォーマットである以上はある程度圧縮が効くものと見込んでいましたが、データそのものの特性もあり想定以上の圧縮率となりました。 なお、より根本的な対策として、Lambda にテーブルデータを入力する(=アプリケーションからテーブルデータを更新する)場合は、全テーブルデータを渡して truncate + load するのではなく、更新差分のみを渡すという方法もあります。 おおよそのケースでデータサイズを抑えることが可能な半面、差分更新を行うための SQL 文を生成するロジックを実装する必要があるため、実装難易度は上がります。また、更新量によっては truncate + load より処理速度が遅くなる可能性もあります。(Redshift のように、列指向でデータを持つ DWH ではよりその傾向が強くなります) 今回はメンテナンス対象テーブルのデータサイズを鑑みて、差分更新を実装する必要はないと判断しました。 まとめ 言い訳がましいのですが、CSV 形式より JSON 形式の方がトータルでデータサイズが増大すること自体は認識していました。ただ、実データに基づく試算などの定量的な裏取りはしておらず、何となく大丈夫だろう程度の感覚で実装を優先してしまっていたのが今回の根本原因であり、反省点です。。。特に今回は事前に試算することも容易なデータサイズ/データフォーマットであったため、尚更ですね。 なお、本記事を書き終わった後に初めて知ったのですが、実は AppSync 側で API レスポンスの圧縮を行う機能もあることに気づきました。本アプリケーションの実装は変更しない予定ですが、別の機会で試してみても良いかもしれないですね。 AWS AppSync でのサーバー側のキャッシュと API ペイロード圧縮の設定 - AWS AppSync AWS AppSync のサーバー側のデータキャッシュと圧縮機能について学んでください。 docs.aws.amazon.com ただ、実アプリケーションで採用する場合、以下一文が気になるところではありますが・・ AWS AppSync はベストエフォートベースでオブジェクトを 圧縮 します。まれに、AWS AppSync が現在の容量を含むさまざまな要因に基づいて、圧縮をスキップすることがあります。 本記事がどなたかの役に立てば幸いです。
こんにちは、SCSKの茂木です。 昨今、重要なシステムのBCP対策としてマルチリージョンでの冗長化をよく目にします。 障害や災害が発生した際のダウンタイムを最小化 や データを複数の場所に分散することによるシステムの信頼性向上 などを目的としたこの構成ですが、AWS上でどう実装すればいいのか気になりました。 なので、今回はAWS Transit Gatewayを用いてマルチリージョンにおける高可用性方式を実装してみます。 はじめに 本記事では、DRBDでのデータレプリケーションを想定したマルチリージョン構成について解説します。 DRBD(Distributed Replicated Block Device)は、Linuxシステムにおけるストレージレベルのデータレプリケーションソフトウェアで、複数のサーバー間でデータをリアルタイムに同期し、高可用性を実現するために使用されます。 第10回 DRBD × LifeKeeperの高可用性リアルタイムレプリケーションを探る データのリアルタイムレプリケーションを実現するDRBD(Distributed Replicated Block Device)とLifeKeeperの可能性について説明します。 blog.usize-tech.com 2024.10.25 マルチリージョンでの冗長化を図るために、クラスタノードは3台構成とし、 クライアント及びノード間の通信をを効率的に管理するためにAWS Transit Gatewayを採用しております。 クライアント通信は仮想IPアドレスをターゲットに行われます。この仮想IPアドレスは、複数の拠点やデータセンターからの通信を一元的にハンドリングする役割を果たします。 なお、本稿では一般的なAWSサービス(EC2など)の構築手順や基本的な説明については割愛しています。そのため、AWSサービスの基本的な操作方法については、別途AWSの公式ドキュメントなどをご参照ください。 全体構成 構成要素と役割 構成要素 説明 NATインスタンス (LKDRBD-nat,LKDRBD-nat-2) Elastic IPを設定し、Publicなサブネットに配置します。 クラスターノードはNATインスタンス経由でAWSのAPIを使ってルートテーブルを制御の内容を書き換えます。 AWSのAPIを使うにはインターネットにアクセスできることが前提となります。 AWSの新機能のPrivate Linkを使うことでインターネットに出ずにAPIをたたけるようになりましたが、本記事では従来通りのNATインスタンスを使う方式を前提としています。 踏み台Windowsサーバー (LKDRBD-windows) Publicなサブネットに配置します。クラスターノードの設定やメンテナンス作業は全て踏み台サーバー経由で行います。 お手元のPCからRDP接続し、踏み台Windowsサーバーとクラスターノード間はSSHで通信します。 クラスターノード (LKDRBD-1,LKDRBD-2,LKDRBD-3) インターネットにアクセスできる必要が無いので、Privateなサブネットに配置します。 今回の検証環境ではファイルシステムの冗長化を行っています。 仮想IPアドレス 意図的にVPC外のダミーのIPアドレス(20.1.1.1)をクライアントから参照させることでルートテーブルを参照させて、そのルートテーブルに登録されているターゲットのENIにアクセスさせます。 詳しくは過去の記事をご参照ください。 第4回 【LifeKeeper】AWSでは仮想IPアドレスが使えない!?をこうして解決する!! オンプレや仮想環境でHAクラスタを構築する際は仮想IPアドレスを使えましたが、AWSでは仮想IPアドレスの機能が提供されません。この課題をLifeKeeperがどのように解決しているかを解説します。 blog.usize-tech.com 2023.11.29 フェイルオーバーの際には、AWSのAPIをキックしてターゲットを稼動系から待機系にルーティング変更します。この制御により、クライアントは常に稼動系のクラスターノードにアクセスできます。 NWの構成 各サービスのパラメータ 本環境で利用しているNW関連サービスのパラメータを紹介します。 内容が重複するため東京リージョンのリソースのみとします。 ルートテーブル publicとprivateで分けていますがどちらも大阪に抜ける経路は同じとなります。 Transit Gateway 必要に応じてオプション機能を有効化します。 今回は「DNSサポート」のみ有効化しています。 Transit Gatewayアタッチメント 東京側のアタッチメント(tgw-at-tokyo)では東京のpublicとprivateサブネットを関連付けています。 Transit Gatewayルートテーブル アタッチメントごとにルートテーブルを作成して関連付けるイメージです。 ルートアナライザーでの疎通確認 ルートアナライザーを使うと簡易的に疎通確認ができます。 疎通が失敗する場合は原因がどこかを特定しましょう。 仮想IPのルーティングシナリオ 仮想IPアドレスを使ったクライアント通信経路に関して、想定されるルーティングシナリオを3パターンご紹介します。 クラスターノードの稼働状況に応じてAWS側でルーティングを切り替える必要があります。 ここでは仮想IPアドレスを「20.1.1.1」とし、東京1号機(LKDRBD-1)から順に障害によるダウンをしたと仮定します。 例ではTGWアタッチメントをサーバと同じプライベートサブネットに配置していますが、 AWSのベストプラクティスはTGWアタッチメント専用のサブネットを分けることが推奨されています。 Amazon VPC Transit Gateway 設計のベストプラクティス - Amazon VPC Transit Gateway 設計のベストプラクティスについて学ぶ。 docs.aws.amazon.com 東京1号機が稼働機の場合 各ルートテーブルは以下のように設定します。 ※設定不要なルートテーブルは割愛します。 ・rtb-tokyo 送信先 ターゲット 20.1.1.1/32 LKDRBD-1のENI ・tgw-rtb-tokyo 送信先 ターゲット 20.1.1.1/32 tgw-at-tokyo ・tgw-rtb-tokyo-osaka 送信先 ターゲット 20.1.1.1/32 tgw-at-tokyo 東京2号機が稼働機の場合 各ルートテーブルは以下のように設定します。 ※設定不要なルートテーブルは割愛します。 ・rtb-tokyo 送信先 ターゲット 20.1.1.1/32 LKDRBD-2のENI ・tgw-rtb-tokyo 送信先 ターゲット 20.1.1.1/32 tgw-at-tokyo ・tgw-rtb-tokyo-osaka 送信先 ターゲット 20.1.1.1/32 tgw-at-tokyo 大阪1号機が稼働機の場合 各ルートテーブルは以下のように設定します。 ※設定不要なルートテーブルは割愛します。 ・rtb-osaka 送信先 ターゲット 20.1.1.1/32 LKDRBD-3のENI ・tgw-rtb-osaka 送信先 ターゲット 20.1.1.1/32 tgw-at-osaka ・tgw-rtb-osaka-tokyo 送信先 ターゲット 20.1.1.1/32 tgw-at-osaka ルーティング切替の実装方針 上述のルーティングシナリオを実現するためにAWSのAPIを使用することでルーティングの切替を行います。 ざっくりした実装方式は以下を想定しており、別記事でスクリプトや挙動のご紹介を予定しています。 ①障害が発生 ②稼働機に昇格したクラスタノードからスクリプトをキック ③スクリプト内でルートテーブルを差し替えて仮想IPを新稼働機までルーティング ④新稼働機でサービス継続 最後に 以上、駆け足でしたがAWS Transit Gatewayを用いたマルチリージョン構成ができたことになります。 最後までお読みいただき、ありがとうございました。 次回はスクリプトによるルーティング切替の詳細について記事を書こうと思います。
先日初めて、AWS User Notificationsというサービスを利用しました。 AWSからの通知を設定、管理していく際に便利だと感じましたので、 EC2に関するAWS Healthイベントの通知をAWS User Notificationsを利用して実装した検証内容をまとめてみました。 概要 AWS Health イベントとAWS User Notificationsについて簡単に説明します。 詳細についてはリンクをご参照ください。 AWS Health イベント AWS Health イベントとはAWS Healthが送信する通知のことで、AWSの障害情報やアカウントに影響を与える可能性がある変更などについて通知を行います。 とは AWS Health - AWS Health AWS Health Dashboard と を使用して、 AWS リソース、サービス、アカウントの状態を継続的に可視化します AWS Health。 docs.aws.amazon.com AWS User Notifications AWS User Notificationsは、AWSサービスからの通知を一元的に設定および確認できるサービスです。 AWS ユーザー通知 aws.amazon.com 検証内容 今回は、EC2に関するAWS Health イベントの通知をAWS User Notificationsで実装し、Eメールで通知を受け取ってみました。 事前確認 AWS Health APIを利用して、EC2のAWS Health イベントに関する情報を確認します。 今回はAWS CloudShellで実行します。AWS Health APIの詳細は以下リンクをご確認ください。 Actions - AWS Health The following actions are supported: docs.aws.amazon.com 以下を実行することで、どのような内容のEC2のAWS Health イベントが通知されるのかを確認できます。 出力結果は2025/1/8時点の情報であり、出力結果が長いため省略しています。 [cloudshell-user@ip-xx-xx-xx-xx ~]$ aws health describe-event-types --region us-east-1 --filter "services=EC2" --output table ------------------------------------------------------------------------------------------------------- | DescribeEventTypes | +-----------------------------------------------------------------------------------------------------+ || eventTypes || |+---------------------+-----------------------------------------------------------------+-----------+| || category | code | service || |+---------------------+-----------------------------------------------------------------+-----------+| || issue | AWS_EC2_API_ISSUE | EC2 || || accountNotification| AWS_EC2_BILLING_NOTIFICATION | EC2 || || accountNotification| AWS_EC2_BYOIP_ROAS_EXPIRING | EC2 || || accountNotification| AWS_EC2_BYOIP_RPKI_INVALID | EC2 || || accountNotification| AWS_EC2_BYOIP_RPKI_UNKNOWN | EC2 || || issue | AWS_EC2_CAPACITY_BLOCKS_API_ISSUE | EC2 || || issue | AWS_EC2_CAPACITY_BLOCKS_API_LATENCY_ISSUE | EC2 || ・・・(中略)・・・ || accountNotification| AWS_EC2_SIMPLIFIED_AUTO_RECOVERY_SUCCESS | EC2 || || issue | AWS_EC2_SPOT_API_UNAVAILABILITY | EC2 || || scheduledChange | AWS_EC2_ULTRASERVER_CAPACITY_REDUCED | EC2 || || scheduledChange | AWS_EC2_ULTRASERVER_MAINTENANCE_INITIATED | EC2 || || accountNotification| AWS_EC2_ULTRASERVER_RECOVERY_COMPLETED | EC2 || || issue | AWS_EC2_VPC_API_ISSUE | EC2 || || issue | AWS_EC2_VPC_NETWORK_HEALTH_INTERNET_ISSUE | EC2 || || issue | AWS_EC2_VPC_NETWORK_HEALTH_INTER_AZ_ISSUE | EC2 || || issue | AWS_EC2_VPC_NETWORK_HEALTH_INTRA_AZ_ISSUE | EC2 || |+---------------------+-----------------------------------------------------------------+-----------+| (END) AWS User Notificationsの設定 AWS User Notificationsを設定していきます。 Creating your first notification configuration in AWS User Notifications - AWS User Notifications Get started with User Notifications. docs.aws.amazon.com 今回は、以下の流れで設定を実施します。 通知設定 通知ハブの設定 配信チャネルの設定 AWS User Notificationsのマネジメントコンソールには、画面上部の以下マークをクリックすることで遷移できます。 1.通知設定 通知を受け取りたいサービスとイベントルールの設定を行います。 「通知設定を作成」をクリックします。 「クイックセットアップ」と「名前と説明」を設定します。 クイックセットアップを利用することで、迅速に通知設定を作成することができます。 「イベントルール」を設定します。 今回は、EC2に関するAWS Health イベントの通知のみを受け取りたいので、高度なフィルターで以下のjsonを記述しました。 { "source": [ "aws.health" ], "detail-type": [ "AWS Health Event" ], "detail": { "service": [ "EC2" ] } } 「集約設定」と「配信チャネル」を設定します。 集約設定では通知の受信頻度、配信チャネルでは通知の送信先を定義します。 配信チャネルでは、「Eメール」、「AWSコンソールモバイルアプリ」、「チャットチャネル」を選択可能です。 配信チャネルは後述で設定するため、詳細は 3.配信チャネルの設定 をご確認ください。 設定が完了したら、「通知設定を作成」をクリックします。 イベントルールの「リージョン別のステータス」が「アクティブ」になっています。 2.配信ハブの設定 通信ハブでは、通知データの保存や処理、またはレプリケートをする特定のリージョンを選択します。 今回は、東京リージョン(ap-northeast-1)を選択し、「保存して続行」をクリックします。 Asia Pacific (Tokyo)が「アクティブ」になっていることがわかります。 3.配信チャネルの設定 配信チャネルでは通知先を設定します。 今回は通知先にはEメールを選択します。 「Eメールを追加」をクリックします。 受信者にメールアドレス、名前にメールアドレスの所有者がわかるような名前を設定し、「Eメールの追加」をクリックします。 設定したメールアドレス宛にAWSから以下のようなメールが送信されます。 内容を確認の上、「Verify email」をクリックします。 「Eメールが検証されました」と表示されます。 配信チャネルを確認すると、先ほど登録したメールアドレスの検証ステータスが「アクティブ」になっています。 登録した配信チャネルを通知設定に設定します。 通知設定の設定画面にて、「配信チャネル」をクリックします。 追加した配信チャネルを選択し、「通知設定を更新」をクリックします。 配信チャネルが通知設定に追加されています。 AWS User Notificationsの設定は以上です。 まとめ 今回は、AWS Health イベントをEメールで通知できるように設定まで行いました。 テストの方法についても今後まとめられたらと思っております。 EC2のAWS Health イベントをEメールで通知できるように設定しましたが、 UserNotificationsは他にもCloudWatchなどにも対応しているので、運用機能実装時に大変役立つサービスだと思います。 皆様のお役に立ちましたら、嬉しいです。
SCSKの畑です。6回目の投稿です。 今回も引き続きアプリケーションにおける排他制御の話題ですが、よりアプリケーション側の実装にフォーカスしています。 はじめに 第一回 で整理していた排他制御の要件は以下の通りです。 主にデータベース/DWH 上のテーブルデータのメンテナンスを実施するアプリケーション 以下の要件に基づき、アプリケーション側で排他制御(ロック)を実装 テーブルデータ編集時に、テーブル単位での排他制御(ロック)を行う 外部キーを持つテーブルのデータ編集時には、外部キーの参照先テーブルについても合わせて排他制御(ロック)を行う 対象テーブルのステータス(編集状態)は DynamoDB で管理する ステータスの遷移(更新)時に、DynamoDB、Lambda、AppSync を用いて排他制御(ロック)を行う ここ2回のエントリでは主に4点目の内容について記載しましたが、今回は2点目の内容について記載します。 今回の案件事例では、2点目の内容を満たす設計・実装として、具体的には以下のような方式を採りました。 あるテーブルをユーザAが編集中の場合、 ユーザAにはテーブルデータの編集画面を表示する それ以外のユーザにはテーブルデータの参照画面を表示する(編集はできない) この場合、DynamoDB で管理されているテーブルのステータスを元に、ユーザ毎にアプリケーション側で画面を制御したり、ルーティングを変更したりする必要があります。よって、このステータスをどのようにアプリケーション内で扱うかが重要なポイントとなったため、考慮・工夫した点を以下に記載していきたいと思います。 アーキテクチャ概要 こちらも載せておきます。 本投稿で言及するのはほぼアプリケーション(Nuxt.js)部分になりますが、ちょこちょこ AppSync の話も書きます。なお、本投稿では Nuxt.js(Vue)自体の説明は割愛します。ご了承ください。 Amazon DynamoDB テーブルのステータス(編集状態)管理 AWS Lambda 排他制御を考慮したテーブルのステータス更新ロジックの実装 AWS AppSync(AWS Amplify) 上記 Lambda をアプリケーション上から実行するためのスキーマ定義 アプリケーション(Nuxt.js) テーブルのステータスに応じた画面制御 テーブルのステータスをコンポーネント間で共有する 冒頭の繰り返しになりますが、テーブルのステータス(編集状態)をベースにアプリケーション側でルーティングや画面の制御を行う必要があるため、同情報はアプリケーション内の各コンポーネントから参照できることが望ましいです。このような仕組みをどのように実装するかはフレームワークに拠りますが、Nuxt3 の場合は useState を使用すると楽に実装できます。 なお、テーブルのステータス情報を、アプリケーションのライフサイクルにおいて適切なタイミングで初期化することも非常に重要なのですが、その話はまた別のエントリで触れたいと思います。最もハマったポイントの1つだったので・・ 実装にあたっては以下サイト様の内容がとても参考になりました。 Nuxt3入門(第8回) - Nuxt3のuseStateでコンポーネント間で状態を共有する | 豆蔵デベロッパーサイト 前回はNuxt3でプラグイン、ミドルウェアの導入について見てきました。今回はNuxt3が提供する状態管理について見ていきます。Nuxt2では、コンポーネント間で状態を共有するには、Nuxt2にバンドルされているVuexを使うのが一般的でした... developer.mamezou-tech.com 以下実装例です。composable として実装しています。 import * as custom_queries from "@/src/graphql/customQueries"; import * as models from "@/src/API"; export type TableStatus = { status: models.TableStatus, editor: string, locked_by: string, } export const useTableStatus = () => { // stateの定義 const TableStatusDict:Ref<{[key: string]: TableStatus}> = useState('g_TableStatusDict', () => ({})) // stateの更新処理 const updateTableStatusDict = async () => { const client = useNuxtApp().$Amplify.GraphQL.client; const result=await client.graphql({ query: custom_queries.listTablesCustom, }) let master_table_status:{[key: string]: TableStatus} = {} for (let item of result.data.listTableInfos.items) { master_table_status[item.name] = { 'status': item.status, 'editor': item.editor, 'locked_by': item.locked_by, } } TableStatusDict.value = master_table_status; } return { TableStatusDict: readonly(TableStatusDict), updateTableStatusDict: updateTableStatusDict, } } useState() で定義したオブジェクトは Nuxt3(Vue3) における Ref となるため、typescript 内でアクセスする際は .value を付けてアクセスする必要があります。また、export 時は readonly として読み取り専用とし、内容の更新は専用のメソッド「updateTableStatusDict」を通してのみ実行するようにしています。 更新処理自体は、前回のエントリで定義した DynamoDB のテーブルの内容を graphql 経由で取得してきた上で、dict 形式に変換してuseState() で定義したオブジェクトを更新しているだけですね。 テーブルのステータスをアプリケーション側にリアルタイム反映する テーブルのステータスについてはなるべくリアルタイムでアプリケーション側に反映できるとユーザビリティの観点からは望ましいのですが、そのような仕組みを自前で用意するのは実装面でなかなかハードルが高いところです。そこで今回は、AppSync の subscription を使用したプッシュ通知によるリアルタイム更新を採用しました。この仕組みによりステータスの反映処理の大凡を任せることができて実装も楽になったので、正に一石二鳥でした。この仕組みを使いたいが故に今回 AppSync を使用したと言っても過言ではないかもしれません。 subscription については、平野さんが執筆された素晴らしいエントリがありますのでこちらも合わせてご参照ください。私自身も大いに参考にさせて頂きました。 AWS AppSync を使って React アプリからキックした非同期ジョブの結果をプッシュ通知で受け取る 非同期ジョブを実行した後、結果をどう受け取るか?というのは開発者として作り込み甲斐のあるテーマです。今回は React アプリが非同期ジョブを実行した後に、AWS AppSync 経由でジョブ完了のプッシュ通知を受け取る仕組みを紹介します。 blog.usize-tech.com 2022.12.01 以下、schema.graphql ファイルにおける実装例です。 type Subscription { onStatusChangeTableWithLock: ResultTableStatus @aws_subscribe(mutations: ["ChangeTableStatusWithLock"]) @aws_api_key @aws_iam } 今回 subscription を設定したいのは、前回のエントリで作成したステータス更新用の mutation (ChangeTableStatusWithLock) となるので、それを3行目の「mutations:」で指定したリスト内で定義すれば OK です。リスト内に複数の mutation を指定して、単一の subscription に対応させることも可能です。 以下実装例です。こちらは、メンテナンス対象のテーブル一覧を表示するためのメニュー用 component 内のメソッドとして定義しており、onMounted() のタイミングで実行するようにしています。 const subscribeTableList = async () => { varSubscriptionStatus.value = client .graphql({ query: subscriptions.onStatusChangeTableWithLock }) .subscribe({ next: async (data: any) => { await updateTableStatusDict() await updateTableMenu() }, error: (error: any) => console.warn(error) }); } onMounted(async () => { await updateTableMenu(); await subscribeTableList(); }); なお、 subscription の返り値は「mutations:」で指定した mutation と同一でないといけない点に注意してください。 mutation を複数指定する場合も同様です。 よって、今回の実装においてはアプリケーション側でこの subscription によるプッシュ通知を受け取った後に、1つ前のセクションで記載したようなテーブルステータス更新用のメソッドを実行する必要があります。この subscription の役割はあくまでいずれかのテーブルのステータスに更新があったことまでで、各テーブルのステータスは改めて取得する必要があるということですね。 前回及び今回の実装例における改善点があるとすると、この返り値である ResultTableStatus にテーブルステータス更新用のメソッドの返り値と同じような情報も含むようにすれば、AppSync API のコール数が1回減ってより効率的になったというところでしょうか。もちろんその場合は composable の仕様についても見直す必要がありますが。 ほか、メニュー画面にテーブルのステータスを表示している都合上画面も更新する必要があるため、そのための関数「updateTableMenu()」も合わせて実行しています。(同関数の内容については今回触れません) aws-amplify の SSR (Nuxt3)対応 最後に、本筋とは少し異なる話題になりますが触れておこうと思います。 今回は Web アプリケーションフレームワークとして Nuxt3 を使用している関係上、レンダリングモードとして SSR (Server-Side Rendering) を使用しています。このため、厳密には実装次第ではありますが、aws-amplify モジュールの各関数がクライアントサイドだけでなく、サーバサイドでも実行され得ます。しかし、aws-amplify は原則 React や Vue などの SPA (Single-Page Application) で使用することが前提のため、Nuxt3 (Nuxt.js) において SSR 対応させるためには別途準備が必要となります。 なお、Next.js は下記 URL を見る限り、バージョン縛りはあるもののサポートされているようです。 Use Amplify categories APIs from Next.js - Next.js - AWS Amplify Gen 1 Documentation Use Amplify categories APIs from Next.js server-side runtimes. AWS Amplify Documentation docs.amplify.aws 具体的には、Nuxt3 の plugin を使用して、クライアントサイドとサーバサイドで使用する aws-amplify のインターフェース(関数)をそれぞれ分けて定義するような形式になります。ただ、サーバサイドで使用できる機能は限定されているため留意が必要です。詳細は以下 URL を参照ください。 Use Amplify categories APIs from Nuxt 3 - Next.js - AWS Amplify Gen 1 Documentation Use Amplify categories APIs from Nuxt 3 AWS Amplify Documentation docs.amplify.aws なお、1つ目のセクションで示した実装例も、上記の通り plugin 内で初期化した graphql の client を使用しています。このため、コード内で aws-amplify モジュール を import していません。この composable は実装上クライアントサイド/サーバサイド両方で実行され得るため、ここまで記載したような対策が必要となります。 本件は、詳細に踏み込もうとすると aws-amplify モジュールの初期設定にも関連する話になるため、また別のエントリで改めて説明する形にさせて頂こうと思います。内容としては公式 URL をある程度なぞる形にはなりますが。。 まとめ いずれのセクションの内容もアプリケーションの設計・実装上は重要な要素だったと感じています。特に、aws-amplify の SSR 対応についてはアプリケーション開発当初に調べていた内容なのですが、調査の過程でアプリケーションフレームワーク自体の挙動や SPA との差異など、他の重要な知識についてもある程度知ることができたのが今振り返るととても良かったです。 第四回を書くかは現時点では未定ですが、書く場合は Nuxt.js における具体的なルーティングの実装例について幾つか記載してみようと思います。 本記事の内容がどなたかの役に立てば幸いです。
こんにちは、広野です。 React アプリから実行できる Amazon DynamoDB へのデータインポート画面を作成したときの話です。 インプットするデータ量は少ないのですが、データを加工したりデータから AI サービスを使用してさらにデータを作成したりしなければならなかったので、裏で AWS Step Functions ステートマシンを使用します。AWS AppSync から Mutation でインポートデータをステートマシンに渡し、開始させる仕組みを作成しました。そこで AWS AppSync の HTTP リゾルバという設定を使いましたが、少し工夫が必要な面があったので紹介します。 つくったもの 主に、以下の図の 緑色の線 の部分を説明します。 AWS AppSync への命令は Mutation にしましたが、Query でも動くと思います。ただ、データを取得するのが目的ではなかったので Mutation にしました。 HTTP リゾルバから実行するアクションは states:StartExecution を使用します。AWS AppSync はステートマシンを開始させたら一旦役目は終了です。以降、結果は非同期に通知される仕様とします。※本記事では言及しません。 AWS AppSync には主にデータベースと接続するための専用リゾルバが用意されていますが、それ以外の AWS サービスを呼び出すには HTTP リゾルバを使用します。呼び出すのに必要な Sigv4 と呼ばれる署名プロセスも自動で実施してくれます。 AWS AppSync での HTTP リゾルバーの使用 - AWS AppSync AWS AppSync の HTTP リゾルバーのチュートリアル。 docs.aws.amazon.com 以降、必要な設定を紹介します。 AWS AppSync スキーマ 例として、startImportJob という Mutation を作成し、data という string 型のデータをやり取りする簡単な設定にしています。 type ImportData { data: String } type Mutation { startImportJob(data: String!): ImportData } schema { query: Query mutation: Mutation subscription: Subscription } AWS AppSync データソース AWS Step Functions ステートマシンをデータソースと見立てて、設定します。タイプは HTTP にします。このデータソースに関連付ける IAM ロールを別途作成する必要があります。今回は、AWS AppSync が states:StartExecution を実行できる権限さえあれば良いです。 AWS AppSync リゾルバ 今回は JavaScript リゾルバを使用しています。 import { util } from '@aws-appsync/utils'; export function request(ctx) { return { method: 'POST', params: { headers: { 'Content-Type': 'application/x-amz-json-1.0', 'x-amz-target': 'AWSStepFunctions.StartExecution' }, body: { 'stateMachineArn': 'arn:aws:states:ap-northeast-1:231376435333:stateMachine:xxxxxxxxxxx', 'input': JSON.stringify({ "data": ctx.args.data, //アプリから渡された引数 "username": ctx.identity.claims.email //emailアドレスをIDトークンから取得している }) } }, resourcePath: '/' }; } export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type); } return { "data": JSON.stringify({ "statusCode": ctx.result.statusCode, //ステートマシンの実行結果 "result": JSON.parse(ctx.result.body) //結果メッセージ }) } } ステートマシンに渡すパラメータを説明します。 headers の部分はこのままにします。 body.stateMachineArn には呼び出したいステートマシンの ARN を入れます。 body.input に入れたデータが、そのままステートマシンへの input になります。ただし、格納するデータは JSON.stringify で文字列化した JSON データに変換する必要があります。(VTL の場合、$util.toJson を使用します) レスポンスについて説明します。 あらかじめ定義していた data (string 型) 変数を使用してアプリに結果を戻します。そのため、戻りのデータを JSON.stringify で文字列化しています。AWS Step Functions から戻ってきた結果は、ctx.result に入ります。エラーがあると、ctx.result.statusCode が 200 以外になります。エラーの内容は ctx.result.body に入っているのですが、これが JSON オブジェクトではなく文字列化された JSON で格納されているので、ctx.result.body を JSON.parse をかけて JSON オブジェクトとして読み取れる状態に変換しています。そうして statusCode とマージさせた JSON を stringify させて返す、という処理にしています。当初ここで結果を読み取ることができず、苦労しました。 この呼び出し方は、説明は雑でしたが以下の AWS ブログに書いてありました。 Invoking AWS Step Functions short- and long-running workflows from AWS AppSync | Amazon Web Services AWS AppSync is a fully managed GraphQL service allowing developers to easily build GraphQL APIs. AWS AppSync lets develo... aws.amazon.com React React アプリ側の GraphQL コードも書いておきます。 import { generateClient } from 'aws-amplify/api'; import gql from 'graphql-tag'; //create AppSync client const client = generateClient(); //インポートジョブ開始関数 const startImportJob = async (data) => { const mutateImportJob = gql` mutation startImportJob($data: String!) { startImportJob(data: $data) { data } } `; const res = await client.graphql({ query: mutateImportJob, variables: { data: data } }); return JSON.parse(res.data.startImportJob.data); //文字列化されたJSONが返されるのでparseしている }; export { startImportJob }; AWS CloudFormation テンプレート 抜粋ですが、関連する部分のテンプレートを貼っておきます。詳細な設定はこちらをご覧ください。AWS Step Functions は省略しています。検証した AWS AppSync が Amazon Cognito ユーザープールで認証するタイプになっているので、その記述が紛れ込んでいます。 AWSTemplateFormatVersion: 2010-09-09 Description: The CloudFormation template that creates an AppSync API to start a Step Functions state machine and relevant IAM roles. # ------------------------------------------------------------# # Input Parameters # ------------------------------------------------------------# Parameters: SubName: Type: String Description: System sub name that is used for all deployed resources. (e.g. prod or dev) Default: dev MaxLength: 10 MinLength: 1 Resources: # ------------------------------------------------------------# # AppSync # ------------------------------------------------------------# AppSyncApi: Type: AWS::AppSync::GraphQLApi Description: AppSync API for example Properties: Name: !Sub example-${SubName} AuthenticationType: AMAZON_COGNITO_USER_POOLS AdditionalAuthenticationProviders: - AuthenticationType: AWS_IAM UserPoolConfig: UserPoolId: xxxxx //CognitoのユーザープールID を入れる AwsRegion: !Sub ${AWS::Region} DefaultAction: "ALLOW" IntrospectionConfig: DISABLED LogConfig: CloudWatchLogsRoleArn: !GetAtt AppSyncCloudWatchLogsPushRole.Arn ExcludeVerboseContent: true FieldLogLevel: ALL Visibility: GLOBAL XrayEnabled: true Tags: - Key: Cost Value: !Sub example-${SubName} DependsOn: - AppSyncCloudWatchLogsPushRole AppSyncSchema: Type: AWS::AppSync::GraphQLSchema Properties: ApiId: !GetAtt AppSyncApi.ApiId Definition: | schema { query: Query mutation: Mutation subscription: Subscription } type ImportData { data: String } type Mutation { startImportJob(data: String!): ImportData } DependsOn: - AppSyncApi AppSyncDataSourceStateMachines: Type: AWS::AppSync::DataSource Properties: ApiId: !GetAtt AppSyncApi.ApiId Name: !Sub example${SubName}StateMachines Description: AppSync DataSource to call State Machines. Type: HTTP ServiceRoleArn: !GetAtt AppSyncStepFunctionsRole.Arn HttpConfig: Endpoint: !Sub https://states.${AWS::Region}.amazonaws.com/ AuthorizationConfig: AuthorizationType: AWS_IAM AwsIamConfig: SigningRegion: !Ref AWS::Region SigningServiceName: states DependsOn: - AppSyncApi - AppSyncStepFunctionsRole AppSyncResolverStartImportJob: Type: AWS::AppSync::Resolver Properties: ApiId: !GetAtt AppSyncApi.ApiId TypeName: Mutation FieldName: startImportJob DataSourceName: !GetAtt AppSyncDataSourceStateMachines.Name Kind: UNIT Runtime: Name: APPSYNC_JS RuntimeVersion: 1.0.0 Code: | import { util } from '@aws-appsync/utils'; export function request(ctx) { return { method: 'POST', params: { headers: { 'Content-Type': 'application/x-amz-json-1.0', 'x-amz-target': 'AWSStepFunctions.StartExecution' }, body: { 'stateMachineArn': 'arn:aws:states:ap-northeast-1:231376435333:stateMachine:example-xxxxx', 'input': JSON.stringify({ "data": ctx.args.data, "username": ctx.identity.claims.email }) } }, resourcePath: '/' }; } export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type); } return { "data": JSON.stringify({ "statusCode": ctx.result.statusCode, "result": JSON.parse(ctx.result.body) }) } } DependsOn: - AppSyncDataSourceStateMachines # ------------------------------------------------------------# # AppSync CloudWatch Invocation Role (IAM) # ------------------------------------------------------------# AppSyncCloudWatchLogsPushRole: Type: AWS::IAM::Role Properties: RoleName: !Sub example-AppSyncCloudWatchLogsPushRole-${SubName} Description: This role allows AppSync to push logs to CloudWatch Logs. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - appsync.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs # ------------------------------------------------------------# # AppSync Step Functions Invocation Role (IAM) # ------------------------------------------------------------# AppSyncStepFunctionsRole: Type: AWS::IAM::Role Properties: RoleName: !Sub example-AppSyncStepFunctionsRole-${SubName} Description: This role allows AppSync to invoke Step Functions. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - appsync.amazonaws.com Action: - sts:AssumeRole Path: / Policies: - PolicyName: !Sub example-AppSyncStepFunctionsPolicy-${SubName} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "states:StartExecution" Resource: - "arn:aws:states:ap-northeast-1:231376435333:stateMachine:example-xxxxx" まとめ いかがでしたでしょうか? 時間のかかる処理を AWS AppSync の裏側で AWS Step Functions を非同期実行させるのに活用できると思います。もちろん、AWS AppSync のタイムアウト範囲内で終わることが確実な処理であれば同期処理にしてしまってもよいでしょう。 本記事が皆様のお役に立てれば幸いです。
AWS CLIのコマンドを本番環境でのAWSアカウントでは試しにくかったり、お金がかかるため自分のAWSアカウント持っていなくて試せないことがあるのではないのでしょうか。 LocalStackというツールを利用すると、なんとローカル環境にAWSのコマンドを試せる環境が作れちゃいます。 ここまでで興味を持ってくれた方、以降で使い方を紹介するので、ぜひ自分のPC等で試してみてください。 ※無償版(Community)と有償版(Pro)がありますが、今回は無償版(Community)の使い方になります。 LocalStackとは ローカル環境のコンテナ上でAWSをエミュレートして、AWSの開発やテストができるツールです。 LocalStackを使ってみる 環境 OS:Ubuntu 24.04 LTS (自宅のPCのHyper-V上に仮想マシンを作成) Docker:Docker version 26.1.3, build 26.1.3-0ubuntu1~24.04.1 AWS CLI:aws-cli/2.22.12 Python/3.12.6 Linux/6.8.0-49-generic exe/x86_64.ubuntu.24 →アクセスキーは適当な値でも問題ありません。 事前にインストールが必要なもの Docker Ubuntuの場合、Ubuntuのリポジトリからインストールできます。 sudo apt install docker.io 参考: Docker AWS CLI Ubuntuの場合、初期セットアップの際、インストール可否を選択できるため、そこでインストールすると楽です。 追加でインストールする際は公式サイトの手順に従ってインストールしてください。 参考: AWS CLI LocalStackをインストールする 参考: Installation LocalStack CLIをインストールする curl --output localstack-cli-4.0.0-linux-amd64-onefile.tar.gz \ --location https://github.com/localstack/localstack-cli/releases/download/v4.0.0/localstack-cli-4.0.0-linux-amd64-onefile.tar.gz sudo tar xvzf localstack-cli-4.0.0-linux-*-onefile.tar.gz -C /usr/local/bin LocalStackのコンテナを起動する docker run \ --rm -it \ -p 127.0.0.1:4566:4566 \ -p 127.0.0.1:4510-4559:4510-4559 \ -v /var/run/docker.sock:/var/run/docker.sock \ localstack/localstack AWS CLIを実行してみる AWS CLI実行時はエンドポイントを以下で指定する必要があります。 指定するエンドポイント:http://localhost:4566 ■IAMユーザ作成 ※UserIdはマスキングしています user01@localstack:~$ aws iam --endpoint-url=http://localhost:4566 create-user --user-name testuser { "User": { "Path": "/", "UserName": "testuser", "UserId": "**********************", "Arn": "arn:aws:iam::000000000000:user/testuser", "CreateDate": "2024-12-09T15:59:47.345000+00:00" } } user01@localstack:~$ ■S3作成 user01@localstack:~$ aws s3api --endpoint-url=http://localhost:4566 create-bucket --bucket test-bucket001 { "Location": "/test-bucket001" } user01@localstack:~$ user01@localstack:~$ aws s3api --endpoint-url=http://localhost:4566 put-bucket-tagging --bucket test-bucket001 --tagging 'TagSet=[{Key=Name,Value=test-bucket001},{Key=testTag,Value=abcd}]' user01@localstack:~$ aws s3api --endpoint-url=http://localhost:4566 get-bucket-tagging --bucket test-bucket001 { "TagSet": [ { "Key": "Name", "Value": "test-bucket001" }, { "Key": "testTag", "Value": "abcd" } ] } user01@localstack:~$ user01@localstack:~$ aws s3 --endpoint-url=http://localhost:4566 cp /home/user01/test/testfile001 s3://test-bucket001 upload: test/testfile001 to s3://test-bucket001/testfile001 user01@localstack:~$ user01@localstack:~$ aws s3 --endpoint-url=http://localhost:4566 ls s3://test-bucket001 2025-01-03 06:42:16 0 testfile001 user01@localstack:~$ 複数のS3を作成して特定のタグを変更するシェルスクリプトを実行してみる 実機での変更系のコマンドは試しにくいため、タグの変更を実行してみようと思います。 ■タグが変更されるバケット S3バケット:test-bucket001、test-bucket002 タグ:Name=バケット名 タグ: testTag=abcd(変更前) タグ:testKey =XYZ(変更後) ■タグが変更されないバケット S3バケット:test-bucket999 タグ:Name=バケット名 タグ: testTag =noChange ■シェルスクリプト #!/bin/bash ENDPOINT_URL="http://localhost:4566" # S3バケットのリストを取得 BUCKET_NAMES=$(aws s3api list-buckets --query "Buckets[].Name" --output text --endpoint-url $ENDPOINT_URL) for BUCKET_NAME in $BUCKET_NAMES do echo "Checking bucket: $BUCKET_NAME" # 前後比較のファイル名を設定 OLD_TAG_FILE="${BUCKET_NAME}_old_tags.json" NEW_TAG_FILE="${BUCKET_NAME}_new_tags.json" # バケットのタグを取得 aws s3api get-bucket-tagging --bucket $BUCKET_NAME --endpoint-url $ENDPOINT_URL --query "TagSet" --output json 2>/dev/null > $OLD_TAG_FILE # 対象のタグキーとバリューが存在するか確認 if jq -e '.[] | select(.Key == "testTag" and .Value == "abcd")' $OLD_TAG_FILE > /dev/null; then echo "Updating tag for bucket: $BUCKET_NAME" # 古いタグを読み込み、変更 TAGS=$(jq '.[] | if .Key == "testTag" and .Value == "abcd" then .Value = "XYZ" else . end' $OLD_TAG_FILE | jq -s .) NEW_TAGS='{"TagSet":'"$TAGS"'}' # タグを更新 aws s3api put-bucket-tagging --bucket $BUCKET_NAME --tagging "$NEW_TAGS" --endpoint-url $ENDPOINT_URL # 新しいタグを取得 aws s3api get-bucket-tagging --bucket $BUCKET_NAME --endpoint-url $ENDPOINT_URL --query "TagSet" --output json > $NEW_TAG_FILE # 変更前後のタグを比較 echo "=====$BUCKET_NAME=====" diff -y $OLD_TAG_FILE $NEW_TAG_FILE echo "----------------------------------------" else echo "No matching tag 'testTag: abcd' for bucket: $BUCKET_NAME" fi done ■実行結果 test-bucket001、test-bucket002のタグが変更され、test-bucket999のみ変更されませんでした。 AWS CLIを使用したシェルスクリプトも試すことも可能です! user01@localstack:~/test$ ./update-s3-tags.sh Updating tag for bucket: test-bucket001 =====test-bucket001===== [ [ { { "Key": "Name", "Key": "Name", "Value": "test-bucket001" "Value": "test-bucket001" }, }, { { "Key": "testTag", "Key": "testTag", "Value": "abcd" | "Value": "XYZ" }, }, ] ] ---------------------------------------- Updating tag for bucket: test-bucket002 =====test-bucket002===== [ [ { { "Key": "Name", "Key": "Name", "Value": "test-bucket002" "Value": "test-bucket002" }, }, { { "Key": "testTag", "Key": "testTag", "Value": "abcd" | "Value": "XYZ" }, }, ] ] ---------------------------------------- No matching tag 'testTag: abcd' for bucket: test-bucket999 user01@localstack:~/test$ 最後に ネットサーフィンしているときに面白そうなツールだなと思い今回試してみました。 お試しというところで実際に開発に使えるかどうかまでは確認していないため、開発で使用できるかについてはご自身で試して判断してみてください。 また、今回は無償版を使っているため、コンテナが停止するとデータが残らない仕様になっています。 コンテナを再起動するたびに環境構築が必要となりますので、停止時にはご注意ください。 参考 LocalStack: https://www.localstack.cloud/ 使用できるAWSサービス: AWS のサービス機能カバレッジ |ドキュメント
あけましておめでとうございます。SCSK渡辺(大)です。 今回は、 AWS Amplify+AWS CDKで人生初のアプリケーションを作ってみました。 車のハザードランプのマークがAWS Amplifyのロゴに見えてきてしまうくらいには触りました。 3回に分けて掲載予定です。 第1回:AWS Amplifyでデプロイした後にログイン画面をカスタマイズしてみた ←今回 第2回:AWS CDKでAPIを作ってみた 第3回:アプリケーションを構築して動かしてみた 準備 React+Viteをインストールする React+Viteをインストールします。 React:UI構築用のJavaScriptライブラリ。流行っている。 Vite:ビルドツール。高速で動作する。 TypeScript:プログラミング言語。型安全で可読性と保守性が高い。コンパイルするとJavaScriptになる。 SWC:コンパイルとバンドルを高速に行えるツール。 $ npm create vite@latest > npx > create-vite √ Project name: ... test √ Select a framework: » React √ Select a variant: » TypeScript + SWC Scaffolding project in C:\Users\xxxxx\Desktop\VSCODE\test... Done. Now run: cd temp npm install npm run dev 出力されている通りのコマンドを打ちます。 $ cd test #testディレクトリに移動。 $ npm install added 142 packages, and audited 143 packages in 1m 40 packages are looking for funding run `npm fund` for details found 0 vulnerabilities $ npm run dev > test@0.0.0 dev > vite VITE v6.0.7 ready in 644 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose ➜ press h + enter to show help ローカル環境(➜ Local: http://localhost:5173/)のリンクをクリックし、以下の画面が表示されることを確認します。 AWS Amplifyをインストールする AWS Amplifyをインストールします。 $ npm create amplify@latest Need to install the following packages: create-amplify@1.0.7 Ok to proceed? (y) y > test@0.0.0 npx > create-amplify ? Where should we create your project? . Installing devDependencies: - @aws-amplify/backend - @aws-amplify/backend-cli - aws-cdk@^2 - aws-cdk-lib@^2 - constructs@^10.0.0 - typescript@^5.0.0 - tsx - esbuild Installing dependencies: - aws-amplify ✔ DevDependencies installed ✔ Dependencies installed ✔ Template files created Successfully created a new project! Welcome to AWS Amplify! - Get started by running npx ampx sandbox. - Run npx ampx help for a list of available commands. Amplify collects anonymous telemetry data about general usage of the CLI. Participation is optional, and you may opt-out by using npx ampx configure telemetry disable. To learn more about telemetry, visit https://docs.amplify.aws/react/reference/telemetry リモートリポジトリにpushする ローカルリポジトリをリモートリポジトリに反映します。 $ git init $ git add . $ git commit -m "first commit" $ git branch -M main $ git remote add origin https://xxxxxxxxxxxxxx/test.git $ git push -u origin main AWS Amplifyにデプロイする デプロイはとても簡単です。 リモートリポジトリを選択して数回クリックするだけです。 デプロイが開始されると以下の画面に切り替わります。 デプロイが完了したのでアプリを開いてみます。 ローカル環境で確認したものと同じ画面が表示されました。 URLも本番環境のものであることが確認できました。 ログイン画面をカスタマイズする ライブラリのインストール ログイン画面で使用するライブラリをインストールします。 $ npm install -g @aws-amplify/cli@latest npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported added 33 packages in 10s 7 packages are looking for funding run `npm fund` for details $ npm install @aws-amplify/ui-react aws-amplify added 61 packages, and audited 1959 packages in 1m 197 packages are looking for funding run `npm fund` for details found 0 vulnerabilities ついでにページ遷移に便利なReact Router フックをインストールします。 $ npm install react-router-dom up to date, audited 1965 packages in 28s 197 packages are looking for funding run `npm fund` for details found 0 vulnerabilities Amazon Cognitoと連携する AWS CognitoのユーザープールIDとユーザープールクライアントIDを確認します。 マネジメントコンソールから確認しに行っても良いのですが、amplify_outputs.jsonで確認することも可能です。 amplify_outputs.jsonはデプロイの画面からダウンロードできます。 amplify_outputs.jsonは大事に保管するか、参照後はローカル環境から削除しておきましょう。 amplify_outputs.jsonの一番上に記載されています。 { "auth": { "user_pool_id": "[ユーザープールID]", "aws_region": "ap-northeast-1", "user_pool_client_id": "[ユーザープールクライアントID]", ルートディレクトリに.envファイルを作成し環境変数を定義します。 VITE_REACT_APP_USER_POOL_ID=[ユーザープールID] VITE_REACT_APP_USER_POOL_CLIENT_ID=[ユーザープールクライアントID] ログイン画面を作成する プロジェクトの中にあるsrcディレクトリの下に、pagesディレクトリを作り、その中にLogin.tsxファイルを作ります。 そのファイルに以下のように記述します。 import { Authenticator, translations } from "@aws-amplify/ui-react"; import "@aws-amplify/ui-react/styles.css"; import '../App.css' import Page1 from '../App.tsx' import { I18n } from "aws-amplify/utils" import { Amplify } from "aws-amplify"; import { ResourcesConfig } from "@aws-amplify/core"; import { BrowserRouter, Routes, Route } from 'react-router-dom'; const userPoolClientId = import.meta.env.VITE_REACT_APP_USER_POOL_CLIENT_ID; const userPoolId = import.meta.env.VITE_REACT_APP_USER_POOL_ID; const awsConfig: ResourcesConfig = { Auth: { Cognito: { userPoolClientId: userPoolClientId, userPoolId: userPoolId, }, }, }; Amplify.configure(awsConfig); function Login() { return ( <BrowserRouter> <Authenticator> {({ user }) => ( <main> {user && ( <Routes> <Route path="/" element={<Page1 />} /> </Routes> )} </main> )} </Authenticator> </BrowserRouter> ); } I18n.putVocabularies(translations) I18n.setLanguage("ja") export default Login; 解説します。(一部重複コードあります) 以下でログイン画面を作っています。 import { Authenticator, translations } from "@aws-amplify/ui-react"; import "@aws-amplify/ui-react/styles.css"; function Login() { return ( <Authenticator> {({ user }) => ( <main> {user && ( )} </main> )} </Authenticator> ); } export default Login; 以下で日本語化させてます。 import { Authenticator, translations } from "@aws-amplify/ui-react"; import { I18n } from "aws-amplify/utils" I18n.putVocabularies(translations) I18n.setLanguage("ja") 以下で見た目を制御しています。 import "@aws-amplify/ui-react/styles.css"; import '../App.css' 以下でページ遷移を制御しています。 import Page1 from '../App.tsx' import { BrowserRouter, Routes, Route } from 'react-router-dom'; <BrowserRouter> <Routes> <Route path="/" element={<Page1 />} /> </Routes> </BrowserRouter> 以下でAmazon Cognitoと連携をしています。 import { Amplify } from "aws-amplify"; import { ResourcesConfig } from "@aws-amplify/core"; const userPoolClientId = import.meta.env.VITE_REACT_APP_USER_POOL_CLIENT_ID; const userPoolId = import.meta.env.VITE_REACT_APP_USER_POOL_ID; const awsConfig: ResourcesConfig = { Auth: { Cognito: { userPoolClientId: userPoolClientId, userPoolId: userPoolId, }, }, }; Amplify.configure(awsConfig); ログイン後の画面(デフォルト画面)にサインアウトのボタンを配置する APP.tsxを以下の通りに修正します。 import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import './App.css' import { Authenticator } from "@aws-amplify/ui-react"; function App() { return ( <Authenticator> {({ signOut }) => ( <> <div> <a href="https://vite.dev" target="_blank"> <img src={viteLogo} className="logo" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt="React logo" /> </a> </div> <h1>Vite + React</h1> <div className="card"> <button onClick={signOut}>サインアウト</button> <p> Edit <code>src/App.tsx</code> and save to test HMR </p> </div> <p className="read-the-docs"> Click on the Vite and React logos to learn more </p> </> )} </Authenticator> ) } export default App 以下でサインアウトボタンを実装しています。 import { Authenticator } from "@aws-amplify/ui-react"; <Authenticator> {({ signOut }) => ( <button onClick={signOut}>サインアウト</button> </Authenticator> アクセス時にログイン画面が表示されるようにする main.tsxを以下のように修正します。 import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import './index.css' import Login from '../src/pages/Login.tsx' createRoot(document.getElementById('root')!).render( <StrictMode> <Login /> </StrictMode>, ) リモートリポジトリにpushする ローカルリポジトリをリモートリポジトリに反映します。 $ git add . $ git commit -m "second commit" $ git push -u origin main 自動でデプロイされましたので改めて見てみます。 ログイン画面が出ました。 アカウントを作るとAmazon Cognitoにユーザーが作成されました。 作成したユーザーでログインできました。 画像では伝わりませんが、サインアウトも問題なくできました。 まとめ アプリ初心者がいきなりAWS Amplifyを触るのは邪道だったかもしれませんが、先輩方の記事を眺めていると将来的にはAWS Amplifyを触れるようになっておいたほうが良いのかと感じたため、今回の記事執筆に至りました。 アプリ開発したことがなかったので、完全にゼロの状態から調べながら進めました。 時間が掛かった反面、とても勉強になりました。
こんにちは、広野です。 AWS AppSync はレスポンスが速くてサブスクリプションを手軽に作れて便利なのですが、ネイティブに CORS 対応はしていません。CORS が必要になった場合には、現時点では Amazon CloudFront をかぶせて CORS ヘッダーをオーバーライドするのが一番スマートかな、と思います。 と、思ってたら簡単には行かなかったので、気付いたことを残しておきます。 実装したアーキテクチャ 冒頭で説明したように、AWS AppSync はネイティブに CORS をサポートしていません。レスポンスで返ってくる Access-Control-Allow-Origin ヘッダーは “*” 固定になっています。そのため、これを Amazon CloudFront distribution でレスポンスヘッダーを上書きします。 CORS は https:// から始まる宛先への通信をサポートしています。AWS AppSync への Query は https の POST メソッドを使用しているようで、Amazon CloudFront を介して CORS を有効化させられます。ところが Subscription (WebSocket) は wss:// から始まる宛先になるので、ブラウザは CORS をサポートしていません。一般的に、WebSocket で同様のセキュリティ対策をしようと思ったら Origin ヘッダーのチェックをするようです。ということなので、Subscription 通信については Amazon CloudFront を通さずに行きます。他にもそのようにした理由がありますが、細かすぎるので最後の方で補足します。 さて、Query の CORS 有効化に話を戻します。レスポンスヘッダーを上書きするだけじゃん?と思うのですが、今回の構成では AWS AppSync が Amazon Cognito 認証になっています。その場合、リクエストの Authorization ヘッダーに Amazon Cognito から受け取ったトークンを格納して送りますので、Amazon CloudFront が AWS AppSync にそれを転送する必要があります。 ここで気を付けないといけない点があり、Authorization ヘッダーをオリジン (ここでは AWS AppSync) に転送するには、特定の設定方法でしか実装できません。それが以下の AWS ドキュメントに書いてあります。 オリジンリクエストにカスタムヘッダーを追加する - Amazon CloudFront CloudFront からオリジンに送信するリクエストにカスタムヘッダーを追加します。 docs.aws.amazon.com まるっとビューワーヘッダー全体指定で転送するか、キャッシュポリシーに Authorization を明記するか、の大まかに 2 択です。私は今回のケースでは Amazon CloudFront にキャッシュをさせたくなかった (通信をパススルーさせたい) ので、キャッシュポリシーをマネージドの CachingDisabled を選択することにしていました。そのため、まるっとビューワーヘッダー全体指定の転送を選択しています。ただし、それだけでは転送されず、レスポンスヘッダーのオーバーライドで使用予定だった Access-Control-Allow-Headers に Authorization を追加すると転送されるようになりました。 今回の一番の目的である CORS 有効化ですが、この設定自体は簡単です。具体的には後述の設定の章を見て欲しいですが、レスポンスヘッダーポリシーに CORS 用設定があるので、そこに CORS 用のヘッダー情報を入れるだけです。また、オーバーライドする設定を有効にします。ここよりも、他のヘッダー設定の方が苦労しました。 ポリシーを使用して CloudFront レスポンスの HTTP ヘッダーを追加または削除する - Amazon CloudFront レスポンスヘッダーポリシーを使用して、Amazon CloudFront が HTTP レスポンスで追加または削除する HTTP ヘッダーを指定します。 docs.aws.amazon.com React アプリ側は、以下のコードで AWS AppSync を呼び出すクライアントの設定をしています。※値は変えてます Amplify.configure( { Auth: { Cognito: { userPoolId: import.meta.env.VITE_USERPOOLID, userPoolClientId: import.meta.env.VITE_USERPOOLWEBCLIENTID, identityPoolId: import.meta.env.VITE_IDPOOLID } }, API: { GraphQL: { // AppSync の標準のエンドポイント endpoint: 'https://example1234567890000.appsync-api.ap-northeast-1.amazonaws.com/graphql', region: 'ap-northeast-1' defaultAuthMode: 'userPool', // 独自ドメインの CloudFront に置き換えたエンドポイント customEndpoint: 'https://xxx.hironoenterprise.com/graphql', customEndpointRegion: 'ap-northeast-1' } } } ); CORS 有効化のため AWS AppSync に手作りカスタムドメインを追加構築したようなものなので、カスタムドメインの設定を追加したところ Query 通信にはカスタムドメイン (Amazon CloudFront のエンドポイント) に、Subscription 通信は AWS AppSync のエンドポイントにアクセスするようになりました。 Configure Amplify categories - JavaScript - AWS Amplify Gen 1 Documentation Configuring the client. AWS Amplify Documentation docs.amplify.aws さて、、、ここまでで CORS 有効化設定そのものは整いましたが、周辺のアーキテクチャについても次章で説明します。 追加のアーキテクチャ もう 1 回同じ図を再掲します。 AWS AppSync への Query 通信を CORS 有効化できただけでも 1 つの進歩なのですが、まだ少々懸念が残っています。 AWS AppSync に Amazon CloudFront をかぶせただけでは、AWS AppSync にダイレクトにアクセスできる経路が残っている。 つまり、Amazon S3 で言う OAC (Origin Access Control) のようなことをした方が良い。 WebSocket 通信については、CORS 同等の対策ができていない。アクセス元アプリを、ここでは hironoenterprise.com に限定するような設定が必要。Origin ヘッダーをチェックさせたい。 これらについて、完璧ではないですが今時点できることを実装してみます。 AWS AppSync エンドポイントへのダイレクトアクセス拒否 これについては、AWS ブログで方法が紹介されています。原始的と言っては失礼ですが、今できることを他の AWS サービスを駆使して組み上げた感じです。 How to enhance Amazon CloudFront origin security with AWS WAF and AWS Secrets Manager | Amazon Web Services Whether your web applications provide static or dynamic content, you can improve their performance, availability, and se... aws.amazon.com 私の図をベースに説明しますと。 Amazon CloudFront から AWS AppSync にリクエストを転送するときに、「私は許可された CloudFront ですよー」と証明するためのキーをカスタムヘッダーに追加します。 リクエストを受け取った AWS AppSync は、リクエストを AWS WAF にチェックしてもらいます。カスタムヘッダーの値が、あらかじめ口裏合わせしておいたキーと同じであれば、アクセスを許可します。 (今回の私の例には含めていませんが) Amazon CloudFront と AWS WAF に持たせる口裏合わせのキーは AWS Secrets Manager で定期的に自動ローテーションします。 なんちゃって OAC AppSync 版、って感じですが、十分な機能ですね。私は今回はバッドプラクティスですが、キーはベタに書きました。そこは参考にしないでください。 Subscription (WebSocket) 通信の Origin チェック WebSocket は特殊な通信で、今回、AWS WAF のログやブラウザの開発者コンソールを見て、通信の仕組みがよくわからないことがわかりました。目的の Origin チェックは簡単に実装できるのですが、前述の AppSync 通信ダイレクトアクセス拒否が意味を失います。長くなりますが、説明します。 まず、Origin のチェックは AWS WAF Web ACL で、Origin ヘッダーがここでは https://hironoenterprise.com であることをチェックすればよいです。ただし、それは以下のように条件分けする必要があります。 Query 通信はカスタムヘッダーをチェックする。 Subscription 通信は Origin ヘッダーをチェックする。 では、AWS WAF がどの情報で Query か Subscription かを識別するかです。 まず、私は host ヘッダーの利用を考えました。host は通信の宛先の FQDN で、今回のケースですと AWS AppSync のエンドポイントになります。実は AWS AppSync は Query と Subscription でエンドポイントが異なります。 AWS AppSync でのリアルタイム WebSocket クライアントの構築 - AWS AppSync AWS AppSync リアルタイム WebSocket クライアント設定 docs.aws.amazon.com Query 用のエンドポイント (GraphQL エンドポイント) 例:https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql SubScription 用のエンドポイント (リアルタイムエンドポイント) 例:wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql FQDN が異なることが確認できると思います。そのため、AWS WAF に残る host ヘッダーが変わり、それぞれの通信を識別できるだろうと考えました。 結論から言いますが、実際には host 情報がまさかの同じ!だったので、識別できませんでした。 Query 通信も SubScription 通信ともに、AWS WAF のログを見る限り、どちらも GraphQL エンドポイントの FQDN が host ヘッダーに残っていました。それ以外の情報では通信を絶対というレベルで識別できるものは見つけられませんでした。 ログを見ていて、SubScription の通信の動きでわかったことは。 まず、wss:// から始まるリアルタイムエンドポイントに GET の通信をしに行く。 これが AWS WAF には残らない!(WAF を通過しない???) その後、GraphQL エンドポイントに POST の通信をしに行く。これは AWS WAF に残る。でもエンドポイントが Query と同じなので Subscription の通信なのかがわからない。 WebSocket のセッションが張れた後は、 AWS WAF に通信の記録は残らない。 Subscription 用にリアルタイムエンドポイントなるものが用意されてはいるものの、目に見えるのは GraphQL エンドポイントの情報のみなので、いかんともしがたいです。 しかしながら、2 の POST の通信がブロックされると WebSocket セッション確立が失敗するのと、Origin ヘッダーはあったので Origin チェックは意味を成します。 Origin チェックを Subscription 通信限定で行うことができず、AWS WAF を通る全通信を対象にするしかないため、ダイレクトアクセス拒否の設定は意味なくなります。ただし、Subscription 通信を全くしない構成であれば機能します。 さらに補足 他の方法として、CloudFront Functions や Lambda@Edge でヘッダーを書き換える方法も検討しましたが、セキュリティの根幹となるヘッダーを書き換えることはできない仕様だったのであきらめました。(そりゃそうだ、それができたら Amazon CloudFront 使って不正アクセスできるようになりますわw) AWS WAF のログは必ず残しましょう。通信がなぜブロックされたのか、また許可された正常な通信はどのようなヘッダー情報を持っているのか確認できるので。 そもそも Subscription (WebSocket) 通信を Amazon CloudFront 経由に統合しなかったのか?と思われる方もいらっしゃるかもしれません。試しましたが、私はできませんでした。おそらく前述した、WebSocket 通信がトリッキーなことが原因だと思います。wss:// から始まる通信、GET から始まり途中から POST に変わる、そしてエンドポイントも変わる、host は GraphQL エンドポイント、、、などなど、通信仕様が理解できず、Amazon CloudFront にヘッダー処理をうまく組み込めませんでした。AWS AppSync はネイティブにカスタムドメインはサポートしており、それを設定すると AWS 側で管理する Amazon CloudFront distribution が立ち上がります。当然その構成では機能するはずなので、勝手な想像ですが Lambda@Edge 等も活用して通信が正常に通るように作り込んでいるのだと思います。ただし CORS はできませんが。 最後になってしまいましたが気になる AWS AppSync のレスポンスは、Amazon CloudFront を介しても体感的には変わらなかったです。さすがエッジロケーション。どうでもいいですが、使用されたエッジロケーションの所在地を意味するようなヘッダーがあって、xx県xx市からのアクセスだとあそこに誘導されるんだー、って一人で感動してました。 思った以上にアーキテクチャ説明が長くなってしまいました。次章で設定情報を紹介します。 具体的な設定 (AWS CloudFormation テンプレート) すみません、AWS CloudFormation テンプレートで失礼します。インラインで補足をコメントします。 AWS AppSync の設定については説明のテーマではないので割愛します。 AWSTemplateFormatVersion: 2010-09-09 Description: The CloudFormation template that creates S3 Buckets, AppSync API with a Web acl, a CloudFront distribution with CORS and relevant IAM roles. # ------------------------------------------------------------# # Input Parameters # ------------------------------------------------------------# Parameters: SubName: Type: String Description: System sub name that is used for all deployed resources. (e.g. prod or dev) Default: dev MaxLength: 10 MinLength: 1 DomainName: Type: String Description: Domain name for URL. xxxxx.xxx (e.g. hironoenterprise.com) Default: hironoenterprise.com MaxLength: 40 MinLength: 5 AllowedPattern: "[^\\s@]+\\.[^\\s@]+" CertificateId: Type: String Description: ACM certificate ID. CloudFront only supports ACM certificates in us-east-1 region. Default: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx MaxLength: 36 MinLength: 36 CloudFrontOriginVerificationKey: Type: String Description: The random string key that AppSync verifies it is sent from the exact CloudFront. !Bad Practice! Use Secrets Manager instead. Default: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX MaxLength: 256 MinLength: 8 LogRetentionDays: Type: Number Description: The retention period (days) for AWS WAF logs. Enter an integer between 35 to 540. Default: 365 MaxValue: 540 MinValue: 35 Resources: # ------------------------------------------------------------# # S3 # ------------------------------------------------------------# S3BucketWafLogs: Type: AWS::S3::Bucket Properties: BucketName: !Sub aws-waf-logs-hironoenterprise-${SubName} LifecycleConfiguration: Rules: - Id: AutoDelete Status: Enabled ExpirationInDays: !Ref LogRetentionDays OwnershipControls: Rules: - ObjectOwnership: BucketOwnerEnforced PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true Tags: - Key: Cost Value: !Sub hironoenterprise-${SubName} # ------------------------------------------------------------# # AppSync 大部分を省略、Cognito の設定は外部テンプレートを参照しているのでこのままでは動きません # ------------------------------------------------------------# AppSyncApi: Type: AWS::AppSync::GraphQLApi Description: AppSync API for hironoenterprise Properties: Name: !Sub hironoenterprise-${SubName} AuthenticationType: AMAZON_COGNITO_USER_POOLS AdditionalAuthenticationProviders: - AuthenticationType: AWS_IAM UserPoolConfig: UserPoolId: Fn::ImportValue: !Sub CognitoUserPoolID-hironoenterprise-${SubName} AwsRegion: !Sub ${AWS::Region} DefaultAction: "ALLOW" IntrospectionConfig: DISABLED LogConfig: CloudWatchLogsRoleArn: !GetAtt AppSyncCloudWatchLogsPushRole.Arn ExcludeVerboseContent: true FieldLogLevel: ALL Visibility: GLOBAL XrayEnabled: true Tags: - Key: Cost Value: !Sub hironoenterprise-${SubName} DependsOn: - AppSyncCloudWatchLogsPushRole # ------------------------------------------------------------# # AppSync CloudWatch Invocation Role (IAM) # ------------------------------------------------------------# AppSyncCloudWatchLogsPushRole: Type: AWS::IAM::Role Properties: RoleName: !Sub hironoenterprise-AppSyncCloudWatchLogsPushRole-${SubName} Description: This role allows AppSync to push logs to CloudWatch Logs. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - appsync.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs # ------------------------------------------------------------# # WAF Web Acl for AppSync # ------------------------------------------------------------# WebAclAppSync: Type: AWS::WAFv2::WebACL Properties: Name: !Sub hironoenterprise-${SubName}-appsync Description: !Sub WAFv2 WebACL for AppSync hironoenterprise-${SubName} Scope: REGIONAL DefaultAction: Block: {} Rules: # Query 通信はカスタムヘッダーが正しく入っているかチェックする、ただし Origin チェックを併用すると意味はない - Name: !Sub AllowAppSyncGraphqlEndpoint-hironoenterprise-${SubName} Priority: 1 Action: Allow: {} Statement: AndStatement: Statements: - ByteMatchStatement: FieldToMatch: SingleHeader: Name: host PositionalConstraint: EXACTLY # GraphQL エンドポイント宛ての通信であることをチェック SearchString: !GetAtt AppSyncApi.GraphQLDns TextTransformations: - Priority: 0 Type: NONE # x-origin-verify というカスタムヘッダーをチェックする - ByteMatchStatement: FieldToMatch: SingleHeader: Name: x-origin-verify PositionalConstraint: EXACTLY SearchString: !Ref CloudFrontOriginVerificationKey TextTransformations: - Priority: 0 Type: NONE VisibilityConfig: CloudWatchMetricsEnabled: true MetricName: !Sub AllowAppSyncGraphqlEndpoint-hironoenterprise-${SubName} SampledRequestsEnabled: true # Subscription 通信はという条件にしたかったが識別できず、全体に対してチェックしている - Name: !Sub AllowAppSyncRealtimeEndpoint-hironoenterprise-${SubName} Priority: 2 Action: Allow: {} Statement: AndStatement: Statements: - ByteMatchStatement: FieldToMatch: SingleHeader: # React アプリから呼び出したことを条件にしている、無くてもよい Name: x-amz-user-agent PositionalConstraint: STARTS_WITH SearchString: aws-amplify TextTransformations: - Priority: 0 Type: NONE - ByteMatchStatement: FieldToMatch: SingleHeader: # origin ヘッダーをチェックする、ここでは hironoenterprise.com であること Name: origin PositionalConstraint: EXACTLY SearchString: !Sub https://${DomainName} TextTransformations: - Priority: 0 Type: NONE VisibilityConfig: CloudWatchMetricsEnabled: true MetricName: !Sub AllowAppSyncRealtimeEndpoint-hironoenterprise-${SubName} SampledRequestsEnabled: true VisibilityConfig: CloudWatchMetricsEnabled: true MetricName: !Sub hironoenterprise-${SubName}-appsync SampledRequestsEnabled: true Tags: - Key: Cost Value: !Sub hironoenterprise-${SubName} DependsOn: - AppSyncApi WebACLAssociationAppSync: Type: AWS::WAFv2::WebACLAssociation Properties: ResourceArn: !GetAtt AppSyncApi.Arn WebACLArn: !GetAtt WebAclAppSync.Arn DependsOn: - WebAclAppSync WebAclLoggingConfigurationAppSync: Type: AWS::WAFv2::LoggingConfiguration Properties: ResourceArn: !GetAtt WebAclAppSync.Arn LogDestinationConfigs: - !GetAtt S3BucketWafLogs.Arn DependsOn: - S3BucketWafLogs - WebAclAppSync # ------------------------------------------------------------# # CloudFront ログの設定は外部テンプレートを参照しているのでこのままでは動かない # ------------------------------------------------------------# CloudFrontDistributionAppSync: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: Enabled: true Comment: !Sub CloudFront distribution for hironoenterprise-${SubName}-appsync Aliases: - !Sub hironoenterprise-${SubName}-appsync.${DomainName} HttpVersion: http2 IPV6Enabled: true PriceClass: PriceClass_200 Logging: Bucket: Fn::ImportValue: !Sub hironoenterprise-S3BucketDomainName-Logs-${SubName} IncludeCookies: false Prefix: cloudfrontAccesslogAppsync/ DefaultCacheBehavior: TargetOriginId: !Sub AppSyncOrigin-hironoenterprise-${SubName}-https ViewerProtocolPolicy: redirect-to-https # 以下の AllowdMethods と CachedMethods の設定は書き方に制約があるのでこの通りに書く AllowedMethods: - GET - HEAD - OPTIONS - PUT - PATCH - POST - DELETE CachedMethods: - HEAD - GET # キャッシュポリシーはAWSマネージドのキャッシュを全くしないポリシーを指定 CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad OriginRequestPolicyId: !Ref CloudFrontOriginRequestPolicy ResponseHeadersPolicyId: !Ref CloudFrontResponseHeadersPolicy Compress: false SmoothStreaming: false Origins: - Id: !Sub AppSyncOrigin-hironoenterprise-${SubName}-https # オリジンには AppSync の GraphQL エンドポイントを指定、FQDN 形式でないとエラーになる DomainName: !GetAtt AppSyncApi.GraphQLDns CustomOriginConfig: HTTPPort: 80 HTTPSPort: 443 OriginProtocolPolicy: https-only OriginSSLProtocols: - TLSv1.2 # ここで、オリジンに送るカスタムヘッダーを追加している OriginCustomHeaders: - HeaderName: x-origin-verify HeaderValue: !Ref CloudFrontOriginVerificationKey ConnectionAttempts: 3 ConnectionTimeout: 10 ViewerCertificate: AcmCertificateArn: !Sub "arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/${CertificateId}" MinimumProtocolVersion: TLSv1.2_2021 SslSupportMethod: sni-only Tags: - Key: Cost Value: !Sub hironoenterprise-${SubName} DependsOn: - CloudFrontOriginRequestPolicy - CloudFrontResponseHeadersPolicy CloudFrontOriginRequestPolicy: Type: AWS::CloudFront::OriginRequestPolicy Properties: OriginRequestPolicyConfig: Name: !Sub OriginRequestPolicy-hironoenterprise-${SubName}-appsync Comment: !Sub CloudFront Origin Request Policy for hironoenterprise-${SubName}-appsync CookiesConfig: CookieBehavior: none # オリジンに転送するヘッダーは host 以外全てにした HeadersConfig: HeaderBehavior: allExcept Headers: - Host QueryStringsConfig: QueryStringBehavior: all CloudFrontResponseHeadersPolicy: Type: AWS::CloudFront::ResponseHeadersPolicy Properties: ResponseHeadersPolicyConfig: Name: !Sub ResponseHeadersPolicy-hironoenterprise-${SubName}-appsync Comment: !Sub CloudFront Response Headers Policy for hironoenterprise-${SubName}-appsync # CORS の設定は CorsConfig: AccessControlAllowCredentials: false # ここに Authorization を追加しないと動かなかった AccessControlAllowHeaders: Items: - Origin - Content-Type - Authorization - x-amz-user-agent # Query は POST メソッド。プリフライトチェックが行われるので OPTIONS を必ず入れる。 AccessControlAllowMethods: Items: - POST - OPTIONS # アクセスを許可するアプリの URL を入れる。ここでは hironoenterprise.com AccessControlAllowOrigins: Items: - !Sub https://${DomainName} # 必ず CORS ヘッダーをオーバーライドすること。 OriginOverride: true # セキュリティヘッダーはおまけ。一般的な設定。 SecurityHeadersConfig: ContentSecurityPolicy: ContentSecurityPolicy: !Sub "default-src 'self' *.${DomainName} ${DomainName}" Override: true ContentTypeOptions: Override: true FrameOptions: FrameOption: DENY Override: true ReferrerPolicy: Override: true ReferrerPolicy: strict-origin-when-cross-origin StrictTransportSecurity: AccessControlMaxAgeSec: 31536000 IncludeSubdomains: true Override: true Preload: true XSSProtection: ModeBlock: true Override: true Protection: true CustomHeadersConfig: Items: - Header: Cache-Control Value: no-store Override: true # ------------------------------------------------------------# # Route 53 ※独自ドメインを使用するときは CloudFront にエイリアスレコードを登録する # ------------------------------------------------------------# Route53RecordA: Type: AWS::Route53::RecordSet Properties: HostedZoneName: !Sub ${DomainName}. Name: !Sub hironoenterprise-${SubName}-appsync.${DomainName}. Type: A AliasTarget: HostedZoneId: Z2FDTNDATAQYW2 DNSName: !GetAtt CloudFrontDistributionAppSync.DomainName DependsOn: - CloudFrontDistributionAppSync Route53RecordAAAA: Type: AWS::Route53::RecordSet Properties: HostedZoneName: !Sub ${DomainName}. Name: !Sub hironoenterprise-${SubName}-appsync.${DomainName}. Type: AAAA AliasTarget: HostedZoneId: Z2FDTNDATAQYW2 DNSName: !GetAtt CloudFrontDistributionAppSync.DomainName DependsOn: - CloudFrontDistributionAppSync まとめ いかがでしたでしょうか。 いろいろ調べて非常に疲れました。HTTP ヘッダーの勉強になりました。同じ問題で困っている方、もし解決できたようでしたら、世の中に公開してくれると嬉しいです。または、AWS さんが AWS AppSync の CORS サポートを追加してくれればよいのですが。。。 本記事が皆様のお役に立てれば幸いです。
2025年2月以降のCatoクラウドのサービス体系(基本サービス、オプション、マネージドサービス)について解説をしています。 これまで(2025年1月末まで)のサービス体系や変更内容については、以下の記事をご参照ください。 Catoクラウドのサービス体系について(2024年版) Catoクラウド 2025年の価格改定(Pricing Update)について 基本サービス まず最初に、Catoクラウドの基本サービスとしては、以下の基本料金が発生します。 拠点毎のPoP接続帯域、および総帯域 モバイルユーザ Socket(エッジデバイス) 拠点毎のPoP接続帯域、および拠点総帯域 サービスメニューは、Catoクラウドを利用する国により異なります。 Catoクラウドでは、世界各国を大きく2つのグループ( Group1 、 Group2 )に分けられており、その他に、ひとつの単独国で価格設定している Stand-alone Countries に分けられています。Stand-alone Countries は、 中国 、 ベトナム 、 モロッコ の3ヵ国で、それぞれ国毎に価格設定がされているため、全部で以下の5つの料金体系となっています。 ちなみに、日本は、Group2 に所属します。 Group1(北アメリカ、ヨーロッパ) Group2(日本を含むアジア、南アメリカ、メキシコ、オーストラリア、アフリカ) Stand-alone Countries(中国) Stand-alone Countries(ベトナム) Stand-alone Countries(モロッコ) Group1、Group2、Stand-alone Countries を世界地図で表すと以下になります。 Site(サイト)ライセンス 次に、拠点のCatoクラウドへの接続については、” Site(サイト)ライセンス “というものが必要となり、本社、支店、営業所、店舗、データセンターといった物理拠点、または AWS、Azureなどのクラウド拠点に、このライセンスが必要となります。 Group1、Group2 の Siteライセンスは接続帯域毎に以下 10個のメニューが準備されています。 25Mbps(最小) 50Mbps 100Mbps 250Mbps 500Mbps 1,000Mbps 2,000Mbps 3,000Mbps 5,000Mbps 10,000Mbps(最大) 拠点は、契約帯域以上の通信速度は出ません。それ以上の通信はQoS設定に従い優先度の低い通信から破棄(Discard)されます。 Pooled(プールド)ライセンス また、Siteライセンス以外にも、複数接続拠点の総帯域を購入する” Pooled(プールド)ライセンス “があります。 Pooledライセンスは、Siteライセンスとは異なり、10Mbps単位で拠点分割が行え、拠点帯域の増速、減速をお客様が自由に行うことできるライセンスとなります。 Pooledライセンス契約は1,000Mbps以上(初期契約時は100Mbps単位で追加可)、契約後は200Mbps以上での追加となります。 Group1、Group2のグループ毎にPooledライセンスを契約し、グループ内での分配することが可能です。 ひとつのアカウントで、SiteライセンスとPooledライセンスの組み合わせも可能です。 Pooledライセンスは、Siteライセンスの100Mbpsベースの価格設定がされているため、 100Mbps以下の拠点の合計帯域が1,000Mbps以上となる場合は、Pooledライセンスを推奨 しております。特に、25Mbps以下の狭帯域(10M,20M)の拠点が多く存在する場合には、非常にコストメリットがあり、さらに増速・減速の柔軟性も確保することができます。 Stand-alone Countries のライセンス Stand-alone Countries については、Group1、Group2のメニューではなく、国内に閉じた通信(Regional)と国外向け通信(Global)を、それぞれ1Mbps単位で契約を行います。ともに2Mbps以上の契約が必要です。つまり、1拠点 Regional 2M/Global 2M が最小契約です。 Stand-alone Countries(中国、ベトナム、モロッコ)には、Pooledライセンスはございません。 価格としては、安価なのが Group1 で、次に Group2 、最も高額なのが Stand-alone Countries となります。 通常は、 SASEライセンス という後述のSocketの利用を前提としたライセンスになりますが、Socketを利用せずに、他の通信機器を利用したIPsec接続を行う場合には、より安価な SSEライセンス での契約を行うことも可能です。 SASEとSSEライセンスは、拠点毎で選択することが可能です。 モバイルユーザ(ZTNA) モバイルユーザ、ZTNA(Zero Trust Network Access)は、ユーザアカウント数による課金となります。 Group1、Gropup2については、共通の” Generalライセンス “となり、Stand-alone Countries(中国、ベトナム、モロッコ)は、それぞれ国毎のライセンスとなります。 購入したユーザ数以上は、登録が行えません。エラーになります。 モバイルユーザは、10ユーザから購入が可能となり、追加も10ユーザ単位の購入となります。また、Generalライセンス 5ユーザ分が予備で付与されています。 Generalライセンスについては、10~500、501~1,000、1,001~5,000、5,001~10,000、10,001・・・、と契約ユーザ数毎にボリュームディスカウント料金が適応されますが、Stand-alone Countries は、数量によるボリュームディスカウントはありません。 モバイルユーザは、端末にCatoクライアントをインストールしますが、 1ユーザ(アカウント)で3台(デバイス)まで利用することが可能 です。 Socket Catoクラウドの最大の特徴であるエッジデバイス、Socket(ソケット)についてです。Catoクラウドで拠点接続する際の通信機器(ルータ、ファイヤーウォール等)の代わりになるものです。 物理ハードウェアアプライアンスとして、 X1500 、 X1600 、 X1700 の3機種があります。X1500/X1700については、後継版の”B”となっています。 X1500の最大スループットが500Mbps、X1600が1,000Mbps、X1700が10,000Mbpsまでとなっております。 X1600については、通常(ベーシック)モデル以外に、SIMが搭載可能な「LTEモデル」がリリースされており、2025年に「Wi-Fiモデル」「Wi-Fi+LTEモデル」「5Gモデル」などがリリース予定となっています。 物理Socketは利用せず、仮想アプライアンス(vSocket)や、既存の追伸機器(ルータやFirewall)等を用いたIPsec接続のみを利用される場合は、Socketの費用は発生しません。 Socketは、冗長(HA)構成を行うことが可能です。また、コールドスタンバイ(予備機)として手配することも可能ですが、Socketは、購入するのではなく、サブスクリプション(サービス利用課金)となりますので、手配したSocketすべてに費用が発生します。 また、Socketのラックマウントキット、ウォールマウントキットも有り、同じくサブスクリプションで提供されています。 Catoクラウドのサービス終了時には、すべて返却(返送)いただく必要があります。 オプションサービス 2025年1月、現在以下の10個のオプションサービスがあります。 Catoクラウドの標準機能に、 SD-WAN 、 URLフィルタリングを含む SWG(セキュアウェブゲートウェイ) 、 Firewall は含まれています。 No. オプション オプションサービス内容 1 Threat Prevention アンチマルウェア(AM)、次世代型アンチマルウェア(NGAM)、不正侵入防止(IPS)、DNS セキュリティ、Threat Intelligence、インラインAI/ML、アンチフィッシング 2 Advanced Threat Prevention 上記のThreat Preventionに加えて、サンドボックス(Sandbox)、RBI(Remote Browser Isolation)を追加 3 CASB Cloud Access Security Broker シャドーIT、SaaS・アプリケーション利用の可視化/評価/制御 4 DLP Data Loss Prevention 機密情報や重要データの漏洩対策 5 SaaS Security API 外部クラウドサービスのAPIによるセキュリティ検査(アンチマルウェア、DLP) 6 XDR Security Pro Extended Detection and Response 拡張検出と対応 7 Digital Experience Monitoring Digital Experience Monitoring(DEM、デム) エンドユーザー体験監視 8 IoT/OT Security SASEベースの保護を、IoT/OT環境まで拡張し、デバイスの可視化とセキュリティ強化を実現 9 Endpoint Security(EPP) Endpoint Protection Platform エンドポイントプロテクションプラットフォーム 10 Data Log Storage Catoクラウドのデータ保管期間延長オプション Threat Prevention パターンファイルマッチングのアンチマルウェア(Anti-Malware)と、機械学習エンジンを用いた振る舞い検知を含む次世代型アンチマルウェア(Next Generation Anti-Malware)、不正侵入検知システム(IPS)、不正なドメインへのアクセスをブロックする DNS Protection 、不審なアクセスをモニタリングする Suspicious Activity Monitoring(SAM)、Threat Intelligence、インライン AI/ML、アンチフィッシングなどの基本的な脅威対策がすべて含まれているCatoクラウドで最も契約されている基本的なセキュリティオプションとなります。 IPSは、XDR Security Coreにも利用されています。 Advanced Threat Prevention Threat Preventionに加えて、Remote Browser Isolation(RBI)とサンドボックス(Sandbox)が追加されたセキュリティオプションとなります。 RBIは、エンドユーザーのデバイス(PC等)の代わりに、Catoクラウドが、ユーザーのWeb閲覧セッションを代わりに実行し、その画面情報をユーザへ送信することによって、オンラインサイトからの脅威(不正プログラムのダウンロードや実行)を無力化するものです。 RBIは、別のセキュリティオプションとして販売されていましたが、2025年2月以降、単体セキュリティオプションとしての購入できなくなりました。 サンドボックスは、Cato Networks社のこれまでの方針では、昨今の俊敏な企業ニーズには合致しないとし、ゼロデイ脅威対策や、脅威を含む未知ファイルを防ぐための異なるアプローチを取っていましたが、多くのお客様・市場のニーズに応じて、機能提供を開始しました。 サンドボックスは、ファイル(プログラム)を保護・隔離された環境で、システムやデータに影響を与えずに実行し、マルウェア検出やプログラムの動作検証を行うものですが、Catoのサンドボックスは、俊敏性を阻害する事前の予防処理を行うのではなく、処理を並行で実施し、事後にプログラムの動作検証レポートを行うものとなります。 CASB SaaSやクラウドサービスの利用状況を可視化(=シャドーITの可視化)を行います。Cato社で各アプリケーションを独自のセキュリティ・コンプライアンス等の視点で評価した Application Credibility Evaluator(ACE)を利用しており、それを元に管理者が、アプリケーション毎に利用許可(Sanction)を行うことが可能になります。さらにアプリケーションのアクティビティ単位での制御を行うことが可能になります。例えば、DropboxやGmailでダウンロード(download)は許可するが、アップロード(upload)は許可しないなどです。また、Office365の企業テナントのみの利用を許可する(個人利用は許可しない)なども、CASBオプションで実現が可能となります。 DLP トラフィック上のすべてのファイルをスキャンして、機密情報の検出を行い、適切な措置を講じることができます。機密情報の特定には、事前にCato社で定義されたルール(データタイプ)を利用することも可能です。クレジットカードやマイナンバーカードなどは事前にルールが定義されていますが、個別に定義することも可能で、MIP(Microsoft Information Protection)ラベルとの連携も可能になっています。もちろん日本語にも対応しています。 SaaS Security API SaaSアプリケーションに対して、APIを利用してセキュリティ検査(マルウェア検査やDLP)を行う機能です。 Catoクラウド以外から、SaaSやクラウドサービスを利用する場合、つまり社外とのコラボレーションを行う際の脅威を検出するためのセキュリティオプションとなります。 Microsoft Exchange/OneDrive/SharePoint、Google Drive/Gmail、Box、Slack、Salesforce、ServiceNow、GitHub、Workspace(Meta)に対応しております。 XDR Security Pro CatoのXDR Securityは、世界初のSASEベースのXDR(Extended Detection and Response)です。 XDR Securityには、CoreとProの2種類があり、 XDR Security Core は、Catoクラウドをご利用のすべてのお客様が無料でご利用いただけますが、Coreは、IPSを元にセキュリティインシデントの分析をしていますので、Threat Preventionのご利用が前提となります。 また、Microsoft Defender for Endpointと連携が可能で、主要EDR製品(CrowdStrike、SentinelOne)との連携も計画されています。 XDR Security Pro は、セキュリティインシデントに対する対応(SOC通知)が可能なお客様向けに提供される機能で、AIベースの脅威ハンティング(Threat Hunting)、ユーザー行動分析(User Behavioral Analysis)、インシデントライフサイクル管理を追加した有償のオプションとなります。Core同様Threat Preventionの契約が前提となります。 また、後述するCato社のマネージドサービスであるMDRは、このXDR Security Proの契約が前提になります。 Digital Experience Monitoring Digital Experience Monitoring(DEM、デム)は、アプリケーションのユーザー体験を監視するテクノロジーで、エンドユーザーとアプリケーション間のすべてのシステムの健全性を計測し監視します。 DEMは、エンドユーザーのデジタル体験を包括的に監視・分析し、SaaS、クラウド、プライベートアプリケーションのパフォーマンスをリアルタイムに把握することができ、通信経路上のボトルネックや問題の早期発見と迅速な解決が可能となる有償のオプションです。 高度な AI 分析を活用し、インターネット、WAN、カスタムアプリケーション全体のユーザー エクスペリエンスを監視し、最適なパフォーマンスを確保することができます。 アラート機能と高度なトラブルシューティング機能を活用し、エンドポイントの問題を迅速に特定し、課題解決時間を大幅に短縮することができます。 Device Monitoring機能が、エンドユーザのデバイスのパフォーマンスや、利用しているWi-Fiのパフォーマンスを監視し、Synthetic Probe Minitoring機能が、LAN・Socket・インターネットG/W・トンネル・アプリケーションのパフォーマンスを監視し可視化することで、通信経路上のボトルネックをより詳細に特定することが可能になります。 IoT/OT Security IoT/OT Security は、SASEベースの保護を、IoT/OT環境まで拡張し、リアルタイムにデバイスの検出と分類を行い、きめ細かなポリシー適用を行うことで、包括的な脅威防御を提供します。 本オプションは、Site(およびPooled)のみに適用されるオプションです 。 Catoクラウドではこれまで、Site(Pooled)とモバイルユーザは必ずセットでオプション契約が必要でしたが、このオプションについては、Site(およびPooled)にのみ適用されるオプションとなります。 Endpoint Security(EPP) 世界初のSASEベースのエンドポイントセキュリティ(EPP)ソリューションとなります。これまでのSASEのカバレッジ範囲を、ネットワーク層を超えてエンドポイントにまで拡張した製品となり、Cato管理アプリケーション(CMA)に完全に統合管理され、クラウドネイティブな他のセキュリティスタックと連携して動作します。 EPPは、端末にEPPソフトウェアをインストールします。モバイルユーザの利用デバイス数上限と同じく上限は3デバイスとなります。 Data Log Storage(保管期間延長) Catoクラウド上での標準のデータ保管期間は3ヶ月(1時間あたりのイベント数が250万以下)です。 Data Log Storage とは、1時間あたりのイベント出力数(標準は250万イベント/時以下)の上限緩和や、データ保管期間を3ヶ月から6ヶ月または12ヶ月へ延長するオプションとなります。 保管期間の延長を行うと、イベントログだけはなく、トラフィックデータなども保管期間が延長され、過去に遡って確認することが可能となります。 No. ログ数(時間単位) 3ヶ月 6ヶ月 12ヶ月 1 250万イベント以下 0円(標準) ¥ ¥¥ 2 250万イベント ~ 500万イベント以下 ¥ ¥¥ ¥¥¥ 3 500万イベント ~ 750万イベント以下 ¥¥ ¥¥¥ ¥¥¥¥ グローバルIPアドレス(4つ目以上) お客様毎に専用で個別割り当てが可能なグローバルIPアドレスは、Catoクラウドでは標準で3つまではサービスに含まれていますが、4つ目以上は、オプション(追加課金)となります。 オプションの課金体系について Site(Pooled)ライセンスとモバイルユーザは、必ず同じオプションを選択する必要があります(ただし、IoT/OT Serurity除く) つまり、1拠点だけ、モバイルユーザだけオプションを選択しないと言った契約はできません。 Threat Prevention、Advanced Threat Prevention、CASB、DLP、IoT/OT Securityは、PoP接続帯域と同じく 帯域課金 となっております。 IoT/OT Serurityのみが、Site(Pooled)ライセンスにのみ適用されますが、その他のオプションは、モバイルユーザにも課金されます。 SaaS Security API、XDR Security Pro、DEM、EPP、MDRは、 Knowledge Users(ナレッジユーザ)課金 となります。ナレッジユーザとは、企業におけるM365やG-Suiteの契約ユーザ数のことで、同契約ユーザ数での契約が必要となります。 オプションの利用条件について オプションには幾つかの前提条件があります。 DLPは、CASB契約が前提となります。 SaaS Security APIは、DLP契約が前提となります。 SaaS Security APIでマルウェア検査をする場合は、Threat Preventionの契約が前提となります。 Cato社のマネージドサービスであるMDRを契約する場合は、XDR Security Proの契約が前提になります。 マネージドサービス 次に、Cato Networks社自身が提供するマネージドサービスについて紹介します。 No. マネージドサービス サービス内容 1 MDR Managed Detection & Response 専任のセキュリティアナリストによるSOCサービス ※日本語未対応 2 ILMM Intelligent Last Mile Management ラストマイルインターネット回線管理サービス 3 NOCaaS NOC-as-a-Service パートナー向け NOC サービス MDR Cato社にて専任のセキュリティ専門家が、アセスメントから、ゼロデプロイメント、全てのトラフィック常時監視し、継続的な脅威ハンティングをサービス提供します。定期的なレポートとサービスレビュー(オンライン会議)が行われます。 残念ながら、 2025年1月時点においても、MDRは英語対応のみ(レポートおよびオンラインのレビュー会議等)となっており、 日本語は未対応 となっております。 そのため、SCSKでは個別に日本語対応したSOCサービスをご提供しております。 ILMM Cato社のNOC(Network Operations Center)が、ラストマイルのインターネット回線のブラックアウト(回線断)、ブラウンアウト(回線の品質やレスポンスが規定に満たない状況)、パフォーマンス低下やをリアルタイムに監視(検知)します。 NOCが問題を検知し、回線が原因であることを特定すると、Cato社が直接ISPへ(日本国内の場合は日本語で)連絡を行い、問題の解決を図ります。ISPと協力し、ネットワークの問題原因を特定し、問題解決を図り、お客様へ対応内容を適宜ご報告します。 ISPには、事前にお客様の委任状をいただくことで、ISPへの直接問い合わせを代理で実施します。 特に、海外の拠点へ多く展開されており、ご担当者は日本にしか居ない場合は、時差等の問題もあり、ラストマイルのインターネット回線不具合をCato社のNOCが管理を代行することが大きなメリットとなります。 NOC-as-a-Service Cato社のNetwork Operations Centre as a Service (NOCaaS) は、お客様に NOC サービスを提供したい パートナー向けサービス となります(2024年10月販売開始) NOCaaS は、ネットワーク監視およびトラブルシューティングサービスを提供する専門のエンジニアチームを提供し、すべてのお客様のネットワークが最大限の稼働時間とパフォーマンスで最適な状態で稼働するように支援します。NOCaaS には ILMMやハンズフリー管理(Hands-free Management)が含まれています。 ハンズフリー管理(Hands-free Management)は、Cato社またはパートナーのいずれかが、お客様のネットワークの完全なハンズフリー管理を行うサービスです。専門スタッフが、ビジネスや技術要件の変更に伴うネットワークやセキュリティポリシーの変更をすべて行います。お客様、パートナー(またはCato)による、共同管理モデルでもご利用いただけます。 SCSKでは、NOC-as-a-Serviceやハンズフリー管理については、SCSKでは、サービス窓口、監視・障害一次切り分け、変更作業代行、月次報告などの各種マネージドサービスを取り揃えております。 マネージドサービスの課金体系について MDRはナレッジユーザ課金となります。 ILMM、NOCaaSは、お客様の全てのサイトに対し適用されることが前提で、特定サイトのみでのご利用はできません。 料金は、1 サイト単位、またはPooledライセンスの場合は 1 Mbps 単位での提供となりますが、別途最低契約金額の設定が存在します。 契約、課金、最小構成について 契約期間について Catoクラウドの ご契約期間は 1年間(最低) となります。 移行期間や、これまでのWANのリプレースであることから2年以上の複数年契約を行われるお客様も多くいらっしゃいます。 複数年契約を行う場合の注意点としては、Catoクラウドでのライセンス追加(拠点追加、帯域増速、モバイルユーザ追加、あるいはSocketのアップグレード)は、契約期間中であれば、いつでも実施することが可能ですが、ライセンス削減(拠点削減、帯域減速、モバイルユーザ削減、Socketダウングレード)は、契約更新時にしか実施することができませんのでご注意ください。 また、契約期間中のライセンス追加については、契約満了月までの契約となります。 例えば、2025年2月1日契約開始で、2026年1月末契約終了の1年契約の場合、2025年4月に拠点を増速した場合は、ライセンス追加分の契約は、2025年4月から2026年1月の10ヵ月の契約となります。 課金(請求)について SCSKでは、 課金(請求)については、月額課金(請求)、一括請求ともに可能 です。 基本サービスとオプションサービス、マネージドサービスをお客様の要望に応じてご請求が可能ですが、月額課金(請求)のお客様が殆どとなります。 Siteライセンスの増速(例 25Mbps→50Mbps)や、モバイルユーザの追加(例 +10ユーザ)も、追加した月からの追加課金(または残期間の一括課金)となります。 Socketについてもサブスクリプションですので、アップグレードが可能です。X1500からX1600、X1700へのアップグレードを実施した場合は、アップグレード実施月からの追加課金(請求増)となります。 最小構成 Catoクラウドの 最小構成は、1 Siteライセンス、10 モバイル(ZTNA)ユーザ となります。 上記の最小構成は、モバイルユーザ 10名と、拠点しては、クラウド(AWS)としてのSiteライセンス 25Mbps(最小)としています。 モバイルユーザ(日本)については帯域の制限(上限)はありませんが、一部の地域(中国やベトナム等)については上限があります。 AWSのvSocketには料金は発生しません。ただし、AWSの利用量(仮想マシン利用、通信量等)は別途必要です。 最小構成の費用感としては、定価ベースで年間65万以下(月額6万円以下)となりますので、他のSASEソリューション、日本国内のソリューションと比較しても、非常に安価でスモールスタート可能なソリューションです。 見積り・ライセンス発行における注意事項 見積りおよびライセンス発行等の各種手続き、課金(請求)については、Catoクラウドのパートナーにより異なります ので、各種手続きや特にリードタイムを事前にご確認されることを推奨します。 例えば、拠点帯域が逼迫した際、見積りやライセンス発行手続きが遅いと、業務に支障がでる期間が長くなる可能性があります。特にCatoクラウドは、クラウドサービスですので、スモールスタートのお客様が殆どですので、ご契約されるパートナーのリードタイムには十分ご注意ください。 SCSKでは、 ライセンス追加(拠点追加・帯域増速・モバイルユーザ追加)は、15時までの手配(注文書の受領)で、最短で当日中のライセンス発行が可能 です。 SCSKのマネージドサービスについて SCSKでは、2019年よりCatoクラウドの取り扱いを開始し、すでに50社以上のお客様とご契約を行っており、お客様ニーズに応じてこれまで様々なマネージドサービスのご提供を行っておりますので、詳細については以下を参照ください。 Catoクラウドのサービス体系について(2024年最新版) 2024年2月以降のCatoクラウドの新しいサービス体系(基本料金、オプション料金、マネージドサービス)について解説を行っています。 blog.usize-tech.com 2024.01.29 また、これまでの個別サービスメニュー提供に加え、2025年2月からは、新たなサービスメニューも加えた上で、” マネージドサービスパック “をリリースする予定です。 まとめ Cato Networks社 の Catoクラウドのサービス体系、基本サービス、オプションサービス、Cato社のマネージドサービスから、契約・課金(請求)、最小構成、SCSKマネージドサービスについても合わせてご紹介させていただきました。 少しでもCatoクラウドに興味をお持ちになられた方は、遠慮なくSCSKまで お問い合わせ ください。 日本国内でも”SASE(サッシー)”や、Cato Networks、Catoクラウド(Cato Cloud/Cato SASE Cloud)の認知度が徐々に上がって来ておりますが、まだまだ低い状況です。 SCSKでは、2021年からSASEの主要な4ソリューションを一同に紹介を行うオンラインセミナー「 SCSK SASE Solution Summit(通称 S4 エスフォー) 」を定期的に開催しております。これまで15回開催し、述べ2,200名以上の方にご参加いただいております。 また、Catoクラウドは、 デモセミナー(オンライン) 、 ハンズオンセミナー(オフライン) なども定期的に開催しておりますので、ご興味ある方は、ぜひご参加ください。 Catoクラウド イベント・セミナー情報 | よくあるご質問 | Cato Cloud ケイトクラウド - SCSK 定期的にCatoクラウドをご紹介するセミナーを開催しております。・2024年9月26日(木)Catoクラウド ハンズオンセミナー【札幌開催分】 ~全国5都市開催(東京/大阪/名古屋/博多/札幌)~ ... cato-scsk.dga.jp SASEセミナー、Catoクラウドセミナー以外に、Catoクラウドの お客様導入事例 の制作、 FAQサイト運営 、この TechHarmony(技術ブログ) で、Catoクラウドの日本語のお役立ちサイトを目指し、少しでもCatoクラウド、SASEの認知度向上と、皆様のお役に立てればと考えておりますので、今後ともよろしくお願いします。 Catoクラウド エンジニアブログまとめ記事 Catoクラウドのエンジニアブログ(TechHarmony)でのまとめ記事となります。 blog.usize-tech.com 2024.02.27
SCSKの畑です。5回目の投稿です。 第一回 の続きです。今回は、前回説明した排他制御の仕組みをアプリケーションからどのように使用しているかが主な内容となります・・が、それだけだと書くことがほぼなくなってしまうので、使用するための前提条件などを補足しながらにしようと思います。 アーキテクチャ概要、及び排他制御に使用したサービス / コンポーネント 今回はほぼ AppSync & アプリケーションの話ですが、排他制御の仕組みを使用するにあたりメンテナンス対象である Redshift についても補足が必要なため、合わせて言及します。 Amazon DynamoDB テーブルのステータス(編集状態)管理 AWS Lambda 排他制御を考慮したテーブルのステータス更新ロジックの実装 AWS AppSync(AWS Amplify) 上記 Lambda をアプリケーション上から実行するためのスキーマ定義 アプリケーション(Nuxt.js) テーブルのステータスに応じた画面制御 アプリケーションにおける設計・実装 まずは、対象テーブルを通常状態から編集状態に移行する関数「setStatusEditingContent」の実装例を以下に示します。この関数を画面上のフォーム/ボタンに紐付けて実行するイメージです。 import * as mutations from "@/src/graphql/mutations"; import * as models from "@/src/API"; const setStatusEditingContent = async () => { // 編集対象テーブルの引数定義 const input_variables:models.ChangeTableStatusWithLockInput = { table_name: table_name, current_status: models.TableStatus.normal, target_status: models.TableStatus.editing, editor: userinfo['user_name'], } // 編集対象テーブルのFK参照先テーブルの引数定義 const fk_tables = getTableFKList() if (fk_tables.length > 0) { input_variables['fk_table_name'] = fk_tables input_variables['fk_current_status'] = models.TableStatus.normal input_variables['fk_target_status'] = models.TableStatus.locked input_variables['locked_by'] = table_name } // 排他制御を伴うステータス変更(通常状態 -> 編集状態) const result = await client.graphql({ query: mutations.ChangeTableStatusWithLock, variables: { input: input_variables } }) // 編集状態にステータスを変更出来なかった場合 if (result.data.ChangeTableStatusWithLock.lock_result == false) { // 対象テーブルのステータスが変更出来なかった場合 if (result.data.ChangeTableStatusWithLock.current_status === models.TableStatus.editing) { alert('編集モードに移行できませんでした。既に他のユーザが編集中です。') } else if (result.data.ChangeTableStatusWithLock.current_status === models.TableStatus.locked) { alert('編集モードに移行できませんでした。他のユーザが編集中のテーブルのFK参照先テーブルのため、ロックされています。') } // 対象テーブルのFK参照先テーブルのステータスが変更出来なかった場合 else { const lock_failed_tables = [] for(const fk_table_status of result.data.ChangeTableStatusWithLock.fk_current_status){ if (fk_table_status.current_status != models.TableStatus.normal){ lock_failed_tables.push(fk_table_status.table_name) } } alert(`編集モードに移行できませんでした。以下のFK参照先テーブルのロックが取得できませんでした。ロック解放後に再度試行ください。\n[${lock_failed_tables.join(', ')}]`) } } } 内容自体は特に捻りもなく、前回定義した mutation の引数を最初に定義した上で graphql client から mutation を実行し、ステータス変更に失敗した場合は画面上にそのエラーを出力しています。(ステータス変更に成功した場合は画面遷移するため特に出力なし) 状態遷移に関しても、前回定義した状態遷移図に基づき、対象テーブルと FK 参照先テーブルで引数にてそれぞれ (fk_)current_status と (fk_)target_status を指定しています。ただ、FK 参照先テーブルの情報について定義している部分について、そもそもどのように FK 関連の情報を取得してきているのかここまで触れてこなかったので、この点について次のセクションで補足します。 対象 Redshift テーブルの FK 情報取得について 本アプリケーションでは、アーキテクチャ図の通り Redshift のテーブル情報を S3 上で管理しています。具体的には、アプリケーションより対象テーブルのデータ参照/編集画面にアクセスした時点で、Redshift に対して SQL 文を実行してテーブル定義情報及びデータ情報を S3 上に保存し、そのデータをアプリケーションから取得してテーブルデータを表示しています。Redshift については AppSync がネイティブ対応していないこともあり、前回説明した mutation と同じく実処理は Lambda で実装しています。 Lambda 自体は様々な要件なり理由から実装が一番複雑になってしまったこともあり今回説明はしませんが、実行している SQL 文について以下に示します。Redshift は PostgreSQL をベースとしているため、 PostgreSQL のシステムカタログを複数結合して対象テーブルの制約情報を取得しています。 なお、Redshift は DWH サービスである以上、RDBMS である PostgreSQL の機能が全てサポートされている訳ではありません。このため、一部の機能差異については今回アプリケーション側の実装でカバーする必要がありました。そのあたりの話題については、また別のエントリでまとめたいと思います。 Amazon Redshift および PostgreSQL - Amazon Redshift Amazon Redshift と PostgreSQL の設計上の違いについて説明します。 docs.aws.amazon.com SELECT c.conname AS constraint_name, CASE WHEN c.contype = 'p' THEN 'PK' WHEN c.contype = 'u' THEN 'UK' WHEN c.contype = 'f' THEN 'FK' END AS constraint_type, t.relname AS table_name, a.attname AS column_name, CASE WHEN c.contype = 'f' THEN rt.relname ELSE NULL END AS referenced_table_name, CASE WHEN c.contype = 'f' THEN ra.attname ELSE NULL END AS referenced_column_name FROM pg_constraint c JOIN pg_class t ON c.conrelid = t.oid JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey) JOIN pg_namespace nsp ON c.connamespace = nsp.oid LEFT JOIN pg_class rt ON c.confrelid = rt.oid LEFT JOIN pg_attribute ra ON ra.attrelid = rt.oid AND ra.attnum = ANY(c.confkey) WHERE t.relname = '<table_name>' AND nsp.nspname = '<schema_name>' ORDER BY c.conname, column_name; 上記 SQL 文をクエリエディタ経由で実行した例です。対象テーブル「m_country」の制約情報が表示されています。 この内、constraint_type 列が「FK」の行が FK 関連の情報を示しています。 同行における referenced_table_name が FK 参照先テーブル名を示しており、この情報を先述したステータス更新用の mutation を実行する際に使用しています。 そして、アプリケーション上から FK 関連情報を取得するための関数が「getTableFKList()」となります。 まとめ やはり、第一回の最後で危惧していた通り、分量が若干アンバランスになってしまった感があります。。このため第三回として、排他制御関連のトピックとして少し毛色の違う内容を取り上げてみようと思います。 本記事の内容がどなたかの役に立てば幸いです。
本記事は、以下Cato Networks社の記事を日本語へ意訳し、再構成したものとなります。 Cato IoT/OT Security Cato IoT/OTセキュリティについて Cato IoT/OT Security は、2024年12月にリリースされた新機能です。 IoT(Internet of Things) 、 OT(Operational Technology) 環境まで保護を拡張し、リアルタイムにデバイスの検出と分類を行い、きめ細かなポリシー適用を行うことで、包括的な脅威防御を提供します。 Catoクラウド プラットフォームのネイティブ機能として、Cato IoT/OT Securityは、複雑なインテグレーションを一切排除されており、ご契約ですぐに利用が可能で、管理も簡素化することが可能です。 デバイスの即時発見と分類 Cato クラウドプラットフォームにネイティブに組み込まれたCato IoT/OTセキュリティは、構築・インテグレーションの必要が一切なく、IT、IoT、OT環境全体にわたって即座に可視性をお客様へ提供します。専用に構築され、訓練されたAIとML(機械学習)がネットワーク上のデバイスをフィンガープリントし、タイプ、メーカー、バージョンをマッピングします。IoT/OTの盲点をなくすことで、この重要な攻撃対象領域を完全に把握することができ、堅牢なIoT/OTセキュリティ戦略の基盤となります。 きめ細かなポリシー適用 完全なIoT/OTセキュリティ戦略には、可視化以上のものが必要であり、IT部門は、社内外のリソースへのIoT/OTデバイスのアクセスを効率的に制御する能力が必要です。 Cato IoT/OT Securityは、IT部門がこれらを実現できるよう支援します。アクセスポリシーは、特定のデバイスの特性に基づいて設定することも、効率化のためにタイプ、メーカー、モデルによるグループ化に基づいて設定することもできます。IoT/OTネットワークアクセスを制御することで、企業ネットワークの安全性を確保し、攻撃対象領域を劇的に減らすことができます。 総合的な脅威防御の実現 Cato IoT/OT Securityは、ポリシーの実施だけでなく、Cato クラウドプラットフォームの脅威防御機能からもメリットを得られます。 Catoの脅威防御は、IPS、NGAM、DNSセキュリティ、インラインAI/MLなどの複数の高度なセキュリティエンジンを活用し、既知の脅威やゼロデイ脅威からIoT/OTデバイスを保護します。企業は、高度な防御によってリスクを軽減することができます。 管理の簡素化 Cato IoT/OTセキュリティは、Cato Management Application(CMA)のネイティブで統合されています。 すべてのダッシュボードとレポートは、CMAとCatoクラウドプラットフォームの他の機能と一貫しているため、新しいインターフェイスを学習する必要がなく、Time-to-Value(価値を実感するまでにかかる時間)を加速します。 ポリシー、ログ、イベント、およびデバイス、メーカー、モデル、ユーザー、サイトなどのオブジェクトは、CMA全体で一貫して表示されます。この一貫性により、ITチームは、複数のソリューションにまたがる異なるダッシュボード間を移動する必要なく、IoT/OTインシデントを容易に特定して理解することができます。 セキュリティ製品の乱立解消 IoTとOTのセキュリティは、従来、複数のハードウェアとソフトウェアのソリューションの展開と統合を意味していました。このアプローチは、しばしば複雑さをもたらし、セキュリティギャップを作り出し、ネットワークの待ち時間を増やします。 Cato IoT/OT Securityは、Cato SASE Cloud Platformのネイティブな一部であり、セキュリティとネットワーキングを統合し最適化する単一のクラウド提供ソリューションによって、すべてのIoT/OTセキュリティ要件に対応します。この統一されたアプローチにより、従来のソリューションの複雑さが解消され、運用のオーバーヘッドなしに堅牢なセキュリティが提供されます。 まとめ 少しでもCatoクラウドに興味をお持ちになられた方は、遠慮なくSCSKまで お問い合わせ ください。 SASE、Cato Networks、Catoクラウド(Cato Cloud/Cato SASE Cloud)の知名度がまだまだ低い状況です。 SCSKでは、2021年から主要なSASEソリューションを一同に紹介を行うオンラインセミナー「 SCSK SASE Solution Summit(通称S4 エスフォー) 」を定期的に開催しており、これまで15回開催し、述べ2,200名以上の方にご参加いただいております また、Catoクラウドについては、 デモセミナー(オンライン) 、 ハンズオンセミナー(対面) なども無料で開催しておりますので、ご興味ある方は、ぜひご参加ください。 Catoクラウド イベント・セミナー情報 | よくあるご質問 | Cato Cloud ケイトクラウド - SCSK 定期的にCatoクラウドをご紹介するセミナーを開催しております。・2024年9月26日(木)Catoクラウド ハンズオンセミナー【札幌開催分】 ~全国5都市開催(東京/大阪/名古屋/博多/札幌)~ ... cato-scsk.dga.jp SASEセミナー、Catoクラウドセミナー以外に、Catoクラウドのお客様導入事例の制作、 FAQサイト運営 、この TechHarmony(技術ブログ) で、Catoクラウドの日本語のお役立ちサイトを目指し、皆様のお役に立て、少しでもCatoクラウド、SASEの知名度アップに貢献できればと考えておりますので、今後ともよろしくお願いします。 Catoクラウド エンジニアブログまとめ記事 Catoクラウドのエンジニアブログ(TechHarmony)でのまとめ記事となります。 blog.usize-tech.com 2024.02.27
本記事は、以下Cato Networks社の記事を日本語へ意訳し、再構成したものとなります。 Cato Digital Experience Monitoring(DEM) Cato DEMについて Cato DEMは、2024年11月3日にリリースされた新機能で、エンドユーザーエクスペリエンスへのリスクを最小限に抑えながら、IT部門が戦略的なデジタルトランスフォーメーションプロジェクトをサポートできるようにするものです。 エンドユーザーの利用状況を監視、分析を行い、パフォーマンス問題をプロアクティブに特定して解決することで、最適なユーザーエクスペリエンスを確保し、障害やトラブルを事前に減らすことで、IT運用を合理化を促進します。 デプロイ・構築作業が不要で、即座に利用可能 Cato DEMは、Cato Cloud Platformの一つの機能です。 IT部門は、簡単にDEMを有効化し、すぐにその利点を体験することができます。ソリューションアーキテクチャとしては、新たなセンサー配置や、インテグレータ作業は一切不要です。DEMのデータは、Catoクライアント、Cato SD-WAN、Cato PoP、Catoグローバルバックボーンなどの既存Catoクラウドの各センサーから自動的に収集されます。パフォーマンスとエクスペリエンスのベースラインは自動的に計算され、DEM ダッシュボードとレポートで IT部門へ提示されます。 何がユーザーエクスペリエンスを阻害しているかを確認、即座に修正 Cato DEMでユーザーエクスペリエンス問題を迅速に特定することが可能になります。 Cato DEMは、企業ネットワーク全体のユーザーとアプリケーションのパフォーマンスを可視化することで、問題を迅速に特定し、迅速に解決することができます。Cato DEMは、ユーザーやデバイスからWAN、インターネット、SaaS上のアプリケーションまで、詳細な分析とホップ・バイ・ホップの可視性を提供することができます。エクスペリエンスの問題の根本原因が、デバイス、ネットワーク、アプリケーションのいずれにあるかに関わらず、それを迅速に検出・特定できます。IT 部門は迅速かつ効率的に問題に対処できるようになり、ダウンタイムや煩雑な作業、フラストレーションを回避できます。 ユーザーエクスペリエンス問題をプロアクティブに特定し対処可能 ユーザーエクスペリエンスの問題への対応から、積極的なユーザーエクスペリエンスの確保へ。 Cato DEMのAI搭載エンジンを搭載しており、実際のユーザーモニタリングと合成プロービングを相関させ、ユーザー、デバイス、場所に関係なく、ネットワークパスのパフォーマンスを継続的にチェックします。潜在的な問題を事前に特定して対処することで、IT部門は、クラウド移行やグローバル展開などの戦略的プロジェクトにおいて、最適なユーザーエクスペリエンスを確保できます。プロアクティブなアプローチにより、全体的な生産性と満足度が向上します。 インシデント管理の標準化によるIT効率の向上 DEMストーリー(≒インシデント)は、相関する一連のパフォーマンス問題を特定し、CatoのSASEベースのXDRに優先順位付けされたリストとして表示されます。各 DEMストーリーには、調査のための完全な詳細とコンテキストが含まれ、AI と ML(機械学習)の洞察によってデータ駆動型の意思決定が強化され、調査時間の短縮に役立ちます。Cato XDRでセキュリティとネットワークに関する洞察を統合することで、チーム間のコラボレーションが向上し、業務効率が大幅に改善されます。 DEMとSASEのすべてを一枚のガラスで実現 Cato DEMは、Cato Management Application (CMA)のネイティブコンポーネントです。 すべてのダッシュボードやレポートは、CMAやCato Cloudのプラットフォームの他の機能と一貫しているため、長い学習曲線や価値の実現に時間がかかることがありません。ポリシー、ログ、イベント、およびユーザー、サイト、アプリケーションなどのオブジェクトは、プラットフォーム全体で一貫性があり、統一されています。この一貫性により、ITチームは、複数のソリューション間で異なる参照やプレゼンテーションの間でマッピングする必要なく、データポイントを容易に理解し、関連付けることができます。 まとめ 少しでもCatoクラウドに興味をお持ちになられた方は、遠慮なくSCSKまで お問い合わせ ください。 SASE、Cato Networks、Catoクラウド(Cato Cloud/Cato SASE Cloud)の知名度がまだまだ低い状況です。 SCSKでは、2021年から主要なSASEソリューションを一同に紹介を行うオンラインセミナー「 SCSK SASE Solution Summit(通称S4 エスフォー) 」を定期的に開催しており、これまで15回開催し、述べ2,200名以上の方にご参加いただいております また、Catoクラウドについては、 デモセミナー(オンライン) 、 ハンズオンセミナー(対面) なども無料で開催しておりますので、ご興味ある方は、ぜひご参加ください。 Catoクラウド イベント・セミナー情報 | よくあるご質問 | Cato Cloud ケイトクラウド - SCSK 定期的にCatoクラウドをご紹介するセミナーを開催しております。・2024年9月26日(木)Catoクラウド ハンズオンセミナー【札幌開催分】 ~全国5都市開催(東京/大阪/名古屋/博多/札幌)~ ... cato-scsk.dga.jp SASEセミナー、Catoクラウドセミナー以外に、Catoクラウドのお客様導入事例の制作、 FAQサイト運営 、この TechHarmony(技術ブログ) で、Catoクラウドの日本語のお役立ちサイトを目指し、皆様のお役に立て、少しでもCatoクラウド、SASEの知名度アップに貢献できればと考えておりますので、今後ともよろしくお願いします。 Catoクラウド エンジニアブログまとめ記事 Catoクラウドのエンジニアブログ(TechHarmony)でのまとめ記事となります。 blog.usize-tech.com 2024.02.27