Do It with AmazonQでアプリケーションを構成する①ユーザが知るべき価値と責任
はじめに
こんにちは。AWSについて記事を作成していきたいと思います。
近年、生成AIの登場を受けてSaaSもIaaSもセキュリティもデータ分析もどこもかしこもLLM、GenAIが活用できることを強くアピールしています。AWSについても BedrockとAmazonQを中心に生成AIサービスと利用事例がre:Inventやサミットでも目立ちます。
実際イベントやデモ/勉強会など多く触れる場面がこの1,2年で皆さん多くあったのではないでしょうか?こうした生成AIの利用はAWSでの開発/構築に大きなメリットをもたらしてくれそうではあります。
しかし、どこまで活用できるのか、何に気をつけておかないといけないのかはまだ事例待ち、PoC中というのが実情に思われます。現在出来ることと出来ないこと、新しい責任共有モデルについてアプリケーション開発をテーマに本ブログで触れていきたいと思います。Do It with yourself(DIY)からDo It with AI(DIAI)でアプリケーションを構成することを目指します。
本記事の対象とする方
・AWSやパブリッククラウドについて基礎知識がある方
・生成AIについて基礎知識がある方
・AWSにアプリケーションを構成されている or される予定の方
・AWSのセキュリティ、統制に興味のある方
・DevOps/DevSecOpsに興味がある、活用されている方
※私がバックエンド寄りの人間なのでフロントエンド部分については申し訳ないですが言及しておりませんので悪しからず・・・。
アプリケーション開発/インフラ構築における生成AIの価値
生成AIはチャットベースでのやり取りまたはメディア(テキスト,画像,音声,動画)生成での使われ方が一般的に多いかと思います。特に調べごとの補助や文章の要約などで日頃使われている方が多いのではないでしょうか?また、アプリケーション開発でツールに制限のない方や生成AI利用を業務で許可されている方はGithub CopilotやGitLab Duo、Cursorなどの生成AIにリクエストを投げられるサービスやツールを利用されている方もいると思います。
業務ではPoCや個人タスクの改善として生成AIを活用しております。例として実際にAmazonQのプラグインをVisual Studioに導入してCloudFromationのyamlを生成してみました。
※Visual Studio上で試したCloudFormation
#s3-bucket-template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudFormation template to create an S3 bucket'
Resources:
MyS3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: !Sub '${AWS::StackName}-bucket'
VersioningConfiguration:
Status: Enabled
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
自分で一生懸命調べながら作成したり、Former2を使ってAWSリソースから作成していたテンプレートがものの1-2分でファイルとして作成されてしまいました・・・。
これはサンプルで非常に単純なもののため、そこまでのものではありません。しかし、プロンプトでリクエストを追加したり、そもそも注意すべきポイントを聞く事も出来ます。
※Visual Studio上でさらにベストプラクティスに沿うようリクエスト
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS CloudFormation Template for creating a secure S3 bucket following Well-Architected Framework best practices'
Parameters:
BucketName:
Type: String
Description: Name of the S3 bucket to create
AccessLogBucketName:
Type: String
Description: Name of the S3 bucket to store access logs
Resources:
SecureS3Bucket:
Type: 'AWS::S3::Bucket'
DeletionPolicy: Retain
Properties:
BucketName: !Ref BucketName
# Enable versioning for data protection and recovery
VersioningConfiguration:
Status: Enabled
# Enable server-side encryption by default
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: 'aws:kms'
KMSMasterKeyID: !GetAtt BucketKey.Arn
# Configure access logging
LoggingConfiguration:
DestinationBucketName: !Ref AccessLogBucketName
LogFilePrefix: 'logs/'
# Enable public access blocking
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
# Enable object lifecycle rules
LifecycleConfiguration:
Rules:
- Id: TransitionToIA
Status: Enabled
Transitions:
- StorageClass: STANDARD_IA
TransitionInDays: 90
- Id: TransitionToGlacier
Status: Enabled
Transitions:
- StorageClass: GLACIER
TransitionInDays: 180
# Enable bucket inventory
InventoryConfigurations:
- Id: EntireBucketInventory
Enabled: true
IncludedObjectVersions: All
Schedule:
Frequency: Weekly
Destination:
BucketArn: !Sub 'arn:aws:s3:::${AccessLogBucketName}'
Format: CSV
BucketKey:
Type: 'AWS::KMS::Key'
Properties:
Description: 'KMS key for S3 bucket encryption'
EnableKeyRotation: true
KeyPolicy:
Version: '2012-10-17'
Statement:
- Sid: Enable IAM User Permissions
Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
Action: 'kms:*'
Resource: '*'
BucketKeyAlias:
Type: 'AWS::KMS::Alias'
Properties:
AliasName: !Sub 'alias/${BucketName}-key'
TargetKeyId: !Ref BucketKey
BucketPolicy:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket: !Ref SecureS3Bucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: EnforceTLSRequestsOnly
Effect: Deny
Principal: '*'
Action: 's3:*'
Resource:
- !Sub '${SecureS3Bucket.Arn}/*'
- !GetAtt SecureS3Bucket.Arn
Condition:
Bool:
'aws:SecureTransport': false
- Sid: DenyUnencryptedObjectUploads
Effect: Deny
Principal: '*'
Action: 's3:PutObject'
Resource: !Sub '${SecureS3Bucket.Arn}/*'
Condition:
StringNotEquals:
's3:x-amz-server-side-encryption': 'aws:kms'
Outputs:
BucketName:
Description: Name of the created S3 bucket
Value: !Ref SecureS3Bucket
BucketARN:
Description: ARN of the created S3 bucket
Value: !GetAtt SecureS3Bucket.Arn
KMSKeyARN:
Description: ARN of the KMS key used for bucket encryption
Value: !GetAtt BucketKey.Arn
ロギング、ライフサイクル管理、バケットポリシー、暗号化キーに関わる設定が追加されています。プロンプトに少し詳細を加えたり、追加でリクエストを投げるなどいわゆるプロンプトエンジニアリングによって内容をより拡充されたのが分かります。
インターネットで検索する、専門の書籍で調べる、実際に試したり、OSSならGitでソースコードを確認する、StackOverflowなどで同じ悩みを持つ人の投稿を確認する。こうした事を時間をかけて行なってきた経験からすると革新的に思えます。
出来ることと出来ないこと
アプリケーション開発/インフラ構築において生成AIは万能なのでしょうか?当然答えはNoです。技術的な理由と品質管理の面、セキュリティで許容できない点があるためです。このあたりはよく言われているので簡単に触れたいと思います。
生成AIの課題と出来ない事
ハルシネーション
生成AIは適切で最もらしい確率の単語の組み合わせを選別し文章やメディアを作成するので、自信満々に嘘をつくことがあります。学習したデータにその情報がない場合でも時に回答してしまいます。まだ、無知の知までではないということですね。一部のモデルでは知らないことを知らないと回答できるものも出てきていますが、回答の妥当性や真偽はまだ人間が判定するしかありません。
※AWSが提供しているBedrockハンズオンデモで十万石まんじゅうを尋ねた時の嘘(群馬ではなく埼玉)
何かを新しく生み出す、課題を解決することは出来ない
何か問題に直面したり、新しく何かを始めるときに提案までは行なってくれますが創造性という点では過去学んだ結果からだけでは難しいです。学んだ知識を組み合わせて、今までにない革新的な組み合わせだったとかはありそうですが、ビジネスや倫理的に妥当かまでの判断は難しいです。
※質問者(私)が悪いだけな気もする酷いリクエスト、当然出来ないと回答
背景を詳しく理解することは難しい
大規模言語モデルを中心に生成AIの学習元はインターネット上の膨大なデータであるため、非公開の機密情報(社外秘、個人情報、学術情報)を知る由はありません。また、細かい背景ではなく確率の高い一般論での回答に留まってしまいます。RAGやファインチューニングを通じて非公開情報や背景を追加は出来るものの、いわゆる行間を読み取る、複雑に絡んだ内容を加味するのはまだ不完全な部分があります。
※100万PVでセキュアで稼働率の高いサービスという曖昧かつ無茶な指示に対して、健気に大量リクエストを捌けるFlaskのアプリケーションを生成しだす
学んだことをアウトプットするのみ
あくまで学んだ結果をアウトプットするだけなので、モデル自体が何か外部に対してアクションをすることはありません。また、当然ながら自発的にモデルが何か行動をすることもありません。いわゆるAgent型のサービスではその限りではありませんが、モデルだけでは何も出来ません。
※外部の予約サイトに調べにいくようなことは出来ない
新しい責任共有モデル
生成AIが行えることと行えないことについて触れてきましたが、**大事なのは責任をどこまでユーザが持つかという事です。**仮に生成AIが脆弱性を含むコードを生成し、それが実際にリリースされた場合、誰の責任になるのでしょうか?
モデルが学んだデータの所有者なのか、モデルの開発元なのか、モデルの提供元なのか、それともモデルを利用したユーザなのか。その答えとなりえるのがWebアプリケーションのセキュリティ標準化団体が出しているOWASP Top 10による内容です。
OWASP Top10 for LLM 2025
これを参考にモデルのSOWと新しい責任共有モデルを構成してみます。BedrockとAmazon QではPaaS,SaaSの違いがあるため分けて記入しています。IaaSでの推論基盤構成はBedrockとあまり変わらないため読み替え可能です。
(凡例: ◯責任を負う、△部分的に責任を負う、×責任の対象外、※条件次第では責任を負う)
Top10内容 | ユーザ | Bedrock(PaaS) | Amazon Q(SaaS) |
---|---|---|---|
LLM01: Prompt Injection | 〇生成AIへの指示の内容と渡すデータについて責任を負う | × | × |
LLM02: Sensitive Information Disclosure | 〇RAGやAgentでモデルがセンシティブなデータにアクセスする制御の責任を負う | ◯他のユーザからリクエストで投げられたデータを再学習などし漏らさないようにする責任を負う | ◯他のユーザからリクエストで投げられたデータを再学習などし漏らさないようにする責任を負う |
LLM03: Supply Chain | ※Bedrockのみ:ファインチューニング、外部モデルを調達する場合に限り責任を負う | △提供モデルがAWS製にもよるが、モデルの安全性、トレーサビリティを担保する必要がある | ◯モデルの安全性、トレーサビリティを担保する必要がある |
LLM04: Data and Model Poisoning | ※Bedrockのみ:ファインチューニング、外部モデルを調達する場合に限り責任を負う | △提供モデルがAWS製なのかにもよるが、モデルの安全性、トレーサビリティを担保する必要がある | ◯モデルの安全性、トレーサビリティを担保する必要がある |
LLM05: Improper Output Handling | ◯モデルからのアウトプットについてフィルタリング、処理する責任を負う | × | △倫理、コンプライアンス的に問題のあるアウトプットをフィルタリングする責任を部分的に負う |
LLM06: Excessive Agency | 〇Agent型のサービス実装時にモデルが閲覧、操作出来る権限制御の責任を負う | × | × |
LLM07: System Prompt Leakage | ※Bedrockのみ:モデル起動時の初期プロンプトの管理責任を負う | × | ◯モデル起動時の初期プロンプトの管理責任を負う |
LLM08: Vector and Embedding Weakness | 〇RAGのためのベクトルDBやRAGのデータ管理について責任を負う | × | △Agentサービスで外部データをRAGにする場合、その管理責任を負うが、外部データ管理はユーザー責 |
LLM09: Misinformation | 〇誤情報が出力されたとしてもその取り扱い責任を負う | × | × |
LLM10: Unbounded Consumption | 〇必要以上に推論されないように保護する責任を負う | × | × |
基本的にIaaS/PaaS/SaaSの責任共有モデルと構成は同じですが、セキュリティリスクについてほぼユーザーが負う必要があるのが特徴です。何故なら生成AI自体に不完全さがあるためであり、その不完全さを見抜けるのはエンドユーザーになるためです。また、RAGやファインチューニング、Agent対応によって精度を上げたり、アクションを行えたとしても根本が不完全なので補助としてしか見なされません。
こうした結果をまとめると以下のような新しい責任共有モデルがまとめられます。
AWSは提供するモデルの安全性やそのモデルを稼働させる推論基盤について責任を負います。一方、それ以外のインプットもアウトプットもモデルに対するいかなるチューニングや補助もユーザ責任となります。
アプリケーション開発/インフラ構築で期待されることと難しいこと
では、これらの特性を元にアプリケーション開発に何が活かせて、何が厳しいのかを考察を交えながら整理していきます。ただし、要件定義や設計はケースバイケースのためPoCやデモレベルでは行える場合もありますし、RAGやファインチューニングによるモデルの精度向上、Agent型サービスのモデルが動的にアクションできるなど一部解消できる余地もありますのであくまで一例です。
工程 | 期待できること | 難しいと思われること |
---|---|---|
要件定義 | ・必要な要素や観点、やり方の提案、与えられた情報の整理、要約 | ・ヒアリングを通じた要件定義そのもの |
基本/詳細設計 | ・必要な要素や観点、やり方の提案、与えられた情報からの文章化 | ・個別の要件に合わせた設計を行うこと |
コーディング | ・フレームワークに基づいた関数、クラス、変数定義、繰り返し処理や入出力に対するデータ処理定義 | ・複雑なネストを含むような処理定義、既存のクラス/関数やコンポーネントと連携する処理 |
デバッグ/レビュー | ・コード内のバグ検出、与えられた情報を基にしたレビュー | ・動的なデバッグ、機能/非機能要件に基づく俯瞰的なレビュー |
コミット/マージリクエスト | ・コミット時の実装の要約、変更箇所、差分の説明 | ・実際にコミット/MRする |
単体テスト | ・テストケースの観点提案、テストコードの生成 | ・テストケースそのものの考案、テストカバレッジの提示 |
SAST/SCA | ・コード内の脆弱な書き方の抽出 | ・最新のCVE情報に即した検出 |
ビルド | ・ビルドに必要な設定ファイル生成、ビルドに必要なCLIやツールの扱い方 | ・実際にビルドする |
ドキュメント化 | ・実装した単一のコードの要約と説明 | ・複数クラス/関数、コンポーネント間の連携を含めた説明 |
インフラ構築 | ・必要な要素や観点、やり方の提案、設定内容、ベストプラクティスの提示 | ・実際の構築作業、アプリケーションと連動した細かいコンポーネントの提示(Web,DB等) |
デプロイ | ・デプロイに必要な設定ファイル生成、デプロイ手法の提案 | ・実際のデプロイ作業、最適なデプロイ方法/ロールバック提示 |
結合テスト | ・テストケースの観点提案、テスト手法の提示 | ・実際のテスト実行 |
運用/監視 | ・運用監視手法の提示 | ・監視を実際に行い異常を検出する、運用効率化/改善化のための分析/提案 |
DAST | ・手法やツールの提示 | ・実際のDAST検出 |
チーム管理/コミュニケーション | ・必要な要素、やり方の提案 | ・進捗管理、課題管理 |
最後に
今回の記事では生成AI活用によってアプリケーションを構成する事で期待できることと難しいと思われることをメインに触れていきました。
生成AIの特性とそれを補うために注力すべき事について次回以降詳しく見ていきます。
Discussion