AIコーディングエージェントを使うと、Webアプリや小規模な業務システムを短期間で形にできます。
一方、ローカル環境で画面が動くことと、業務で安全に使い続けられることは別です。本番環境には認証、権限管理、秘密情報の保護、バックアップ、監視、障害時の復旧手順も必要です。
この記事では、AI駆動開発(AIDD: AI-Driven Development)を始める前の準備から、本番公開までに人が確認したい項目を整理します。
きっかけは、実際に構築中の環境を確認していて、次のような問題に遭遇したことです。
- 構成管理・IaCツールでサーバーを構築する過程で、機密情報が外部へ漏れかねない状態になった
- 内部APIと公開APIが同じコードに実装され、設定を誤ると内部APIまで外部公開される構成になった
- 画面や主要機能は動いていたが、クリックジャッキングなどへの対策が残っていた
いずれも、アプリが動くかどうかだけを確認していたら見落としかねない問題でした。個別の実装ミスというより、秘密情報、公開範囲、セキュリティ要件を最初に分けて定義していなかったことが共通の原因でした。
AI駆動開発は「AIに全部任せること」ではない
AI駆動開発は、要件整理、実装、テスト、レビュー、修正をAIと人が分担し、短いサイクルで進める開発方法です。
AIは実装や調査、テストコードの作成を速められます。しかし、次の判断は人が担当する必要があります。
- 誰が何のために利用するのか
- どの情報を保存してよいのか
- 誰にどこまで操作を許可するのか
- どのリスクまで許容するのか
- 障害や漏えいが起きたときにどう対応するのか
- AIの変更を本番へ反映してよいか
基本原則は、AIの出力をそのまま正解とせず、変更履歴を残し、テストし、人が確認してから反映することです。
1. 開発前に準備する
目的と利用者を一文で書く
最初に「誰が、何のために、何をするアプリなのか」を一文で書きます。
例えば「営業担当者が、顧客からの問い合わせと対応状況を共有する社内アプリ」のように、利用者と最初の目的を限定します。最初から巨大なシステムを目指すより、一つの業務を完了できる範囲から始めた方が確認しやすくなります。
完成条件を画面以外も含めて決める
- 入力項目と入力規則
- 一般利用者、管理者、閲覧者などの権限
- 誤入力や通信失敗時の動作
- 保存するデータと保存期間
- データの削除方法
- 操作履歴や監査ログの要否
曖昧なまま「顧客管理アプリを作って」と依頼すると、AIは不足部分を推測します。その推測が業務要件と一致する保証はありません。
最低限の開発基盤
| 項目 | 目的 |
|---|---|
| Gitリポジトリ | 変更理由を追跡し、問題のある変更を戻せるようにする |
| README | 目的、起動方法、環境変数、テスト方法を残す |
| 課題管理 | 仕様、不具合、保留事項をチャット以外にも残す |
| 開発環境 | 言語やランタイム、パッケージのバージョンを揃える |
| ブランチ運用 | 未確認の変更が直接本番用ブランチへ入ることを防ぐ |
本番がLinuxなら、開発環境もLinux、macOS、またはWSLへ近づけると、パスや権限、改行コードの差による不具合を減らせます。
2. AIには確認できる単位で依頼する
アプリ全体を一度に作らせると変更範囲が広くなり、レビューしにくくなります。「ログイン」「顧客の登録」「一覧表示」「権限判定」のように動作確認できる単位へ分け、テストと検証結果も一緒に依頼します。
顧客情報を登録する機能を実装してください。
- 入力値をサーバー側でも検証する
- 未認証の場合は処理を拒否する
- 一般利用者と管理者の権限を区別する
- 正常系、境界値、未認証、権限不足のテストを追加する
- 型チェックとテストを実行し、結果を報告する
- 関係のないファイルは変更しない
AIが「完了しました」と回答しても、差分、テストの実行結果、ログを確認します。テスト自体が誤っている可能性もあるため、重要な業務処理は人間による動作確認も必要です。
3. 認証と権限を分けて考える
認証は「誰であるかを確認すること」、認可は「その人が何を操作できるかを判断すること」です。
ログイン画面があっても、サーバー側が権限を確認していなければ、URLやリクエストを直接操作される可能性があります。画面上でボタンを隠すだけでは権限制御になりません。
- 管理者、一般利用者、閲覧専用などの役割を定義する
- APIやサーバー処理でも毎回権限を確認する
- 他人のIDへ変更してもデータを閲覧・更新できないことを試す
- 管理者アカウントには多要素認証を設定する
- 退職者や不要なアカウントを無効化できるようにする
- セッションやCookieへ適切な有効期限と属性を設定する
4. 秘密情報をコードとAIの会話へ入れない
APIキー、DBパスワード、秘密鍵、アクセストークンをソースコードへ直接書かず、AIとの会話にも貼り付けません。
ローカルでは環境変数を利用し、.envをGitの管理対象から外します。本番ではクラウドのシークレット管理機能か、アクセス権を制限した環境変数として渡します。
- 開発環境と本番環境で認証情報を分ける
- アプリへ管理者権限を与えない
- トークンには必要最小限の権限と有効期限を設定する
- 漏えい時に失効・再発行できるようにする
- ログやエラー画面に秘密情報を表示しない
秘密情報をGitへコミットした場合、後からファイルを削除するだけでは履歴に残ります。まず認証情報を失効・再発行し、その後で履歴を処理します。
構成管理コードも確認する
構成管理・IaCツールを使っていても、それだけで秘密情報が安全になるわけではありません。変数ファイル、テンプレート、状態ファイル、実行ログ、生成された設定ファイルに認証情報が残ることがあります。
私がサーバー設定を構築したときも、機密情報が外部へ漏れかねない状態になりました。構成管理コードをGitで管理できていることと、そこに書かれた値を公開してよいことは別です。秘密情報は暗号化された保管先から実行時に渡し、ログへの出力、配置先の権限、Gitの追跡対象を確認します。
5. データとDB変更を管理する
データベース、アップロードファイル、ログ、秘密情報は保存先を分けて考えます。
- 顧客や申請などの構造化データ: PostgreSQLやMySQL
- 画像や添付ファイル: オブジェクトストレージ
- アプリケーションログ: ログ管理基盤
- APIキーやパスワード: シークレット管理
DBの構造変更はマイグレーションとしてGitへ保存します。本番DBだけを手作業で変更し続けると、環境差や変更内容が分からなくなる原因になります。
適用済みのマイグレーションは書き換えず、修正は新しいマイグレーションとして追加します。AIやツールが生成したSQLも、本番へ適用する前に確認します。
6. 本番環境は開発PCの延長にしない
本番では、公開Web、社内限定アプリ、管理経路、データベースを分けて考えます。
公開範囲
- インターネットから到達できるポートを必要最小限にする
- DB、SSH、管理画面を原則として直接公開しない
- 社内限定機能にはZTNAやVPNなどのアクセス制御を使う
- HTTPSを設定し、HTTPからHTTPSへ転送する
- 管理者のアクセス元と権限を制限する
内部APIと公開APIが同じアプリに実装されている場合、ルーティングやリバースプロキシの設定ミス一つで、内部用のエンドポイントまで外部から到達できる可能性があります。実際にこの構成へ遭遇し、コード上での認証・認可と、ネットワーク上の公開範囲の両方を確認する必要があると分かりました。
「内部用」という名前や設計だけでは保護になりません。外部ネットワークから到達できないことを実際に試し、仮に到達してもサーバー側で拒否されるようにします。可能なら、内部APIと公開APIはルート、デプロイ単位、またはネットワーク境界を分けます。
ブラウザ向けの防御
主要機能が動作していても、クリックジャッキングなど、通常の操作確認では気づきにくい脆弱性が残ることがあります。
-
Content-Security-Policyのframe-ancestorsなどで、意図しないサイトからの埋め込みを制限する - Cookieへ
Secure、HttpOnly、適切なSameSite属性を設定する - 本番環境でデバッグ表示や詳細なエラーを無効にする
- セキュリティヘッダーと依存パッケージを自動・手動の両方で確認する
診断ツールの結果だけで安全と判断せず、認証や重要操作の仕様と合わせてレビューします。
データベース
- アプリと同じプライベートネットワークから接続する
- 接続元を制限する
- アプリ用DBユーザーには必要最小限の権限だけを与える
- 管理者用とアプリ用の認証情報を分ける
デプロイ
- 誰が、どのコミットを、いつ反映したか追跡できる
- 型チェック、Lint、テストに合格した成果物だけを配置する
- 問題発生時に一つ前の状態へ戻せる
- DB変更の適用順序と復旧方法を確認する
7. 公開した日から監視とバックアップが必要
本番では、アプリ停止だけでなく、ディスク容量不足、inode枯渇、証明書期限切れ、DB容量不足、バックアップ失敗なども起こります。
最初に監視したい項目は次のとおりです。
- サーバーの死活
- CPU、メモリ、ディスク容量、inode
- WebアプリのHTTP応答
- データベースの容量と接続状況
- 最終バックアップ日時
- 監視基盤自体の死活
- クラウド利用額と請求アラート
監視はグラフを表示するだけでなく、異常時にSlack、Teams、メールなどへ通知し、誰が判断するかまで決めます。
バックアップも「有効にした」で終わらせず、対象、保存先、保存期間、暗号化、削除権限、復元方法、復元時間を確認します。ランサムウェアや管理者アカウントの侵害に備えるなら、本番とは独立した保存先や、保存期間中に削除・上書きできない保管方式も検討します。
本番公開前チェックリスト
コードと秘密情報
- 本番へ反映するコミットと変更内容を確認した
- 型チェック、Lint、自動テストが成功している
- APIキー、パスワード、秘密鍵がGit履歴に含まれていない
- 開発用のデバッグ機能とテストアカウントを無効化した
- 依存パッケージの既知の脆弱性を確認した
認証と公開範囲
- 管理者アカウントに多要素認証を設定した
- 一般利用者と管理者の権限をサーバー側で分離した
- HTTPSを設定し、HTTPから転送される
- 不要なポートを公開していない
- DB、SSH、管理画面をインターネットへ直接公開していない
- 内部APIへ外部ネットワークから到達できないことを確認した
- 内部APIへ到達した場合も、サーバー側の認証・認可で拒否される
- クリックジャッキングを防ぐレスポンスヘッダーを設定した
-
Cookieに
Secure、HttpOnly、適切なSameSite属性を設定した
データと運用
- 自動バックアップの保存先と保存期間を確認した
- バックアップから復元する手順を確認した
- 死活、CPU、メモリ、ディスク、HTTP応答を監視している
- 異常通知を実際に受け取れることを試した
- 障害時の連絡先、調査担当、復旧判断者を決めた
- クラウドの請求アラートを設定した
まとめ
AI駆動開発では、実装速度が上がった分だけ、要件、テスト、権限、公開範囲、運用を意識して確認する工程が重要になります。
すべてを最初から満たせない場合は、対象者を限定した検証環境として始める方法もあります。未確認のまま全面公開せず、利用範囲を制限し、監視と復旧手段を整えてから本番へ移行します。
AIでコードを作るところをゴールにせず、安全に公開し、異常に気づき、元へ戻せるところまでを開発の範囲に含めることが大切です。
より詳しい構成例は以下にもまとめています。