セキュリティ対策
サインイン、権限、シークレット、接続の保護方法
実行場所
AnsibleForms はセルフホスト型で、お客様のインフラストラクチャ上で動作し、データはお客様が運用するデータベースに保存されます。
- AnsibleForms のクラウドサービスやライセンスサーバーはなく、テレメトリや更新チェックもありません。
- インターフェイスはアプリケーション自体が提供し、ほかのサイトから何も読み込みません。
- アプリケーションが接続するのは、管理者が設定したシステムだけです。一覧は 外部への接続 にあります。
構成要素と、それぞれが保持するもの:
| 構成要素 | 役割 | 保持するもの |
|---|---|---|
| アプリケーション | Web インターフェイス、REST API、スケジューラー | 独自のデータはありません。すべてデータベースにあります |
| MySQL または MariaDB | アプリケーションのデータベース | ユーザー、グループ、認証情報 (暗号化済み)、extravars と出力を含むジョブ、監査ログ |
| ランタイム環境 (RTE) | 専用のコンテナーで playbook を実行します | 実行するジョブのファイルと、そのジョブの実行中だけ保持するシークレット |
| 永続フォルダー | 設定、フォーム、playbook、アップロード | フォームと playbook が使うファイル |
全体像は 動作のしくみ を、ランタイム環境については RTE を参照してください。
サインイン
データを読み取ったり変更したりするページと API 呼び出しには、すべてサインインしたユーザーが必要です。サインインなしで利用できる数少ないエンドポイントは、 サインイン自体、バージョン、インスタンスの名前とロゴ、API ドキュメント、初回起動時のデータベースセットアップを提供するもので、 最後のものは ALLOW_SCHEMA_CREATION=0 で閉じられます。
| 方式 | しくみ |
|---|---|
| ローカルアカウント | パスワードは bcrypt でハッシュ化され、 最小の長さ があり、公開されている既定の管理者パスワードは初回サインイン時に変更する必要があります |
| LDAP / Active Directory | ディレクトリがパスワードをチェックし、そのグループがロールに対応付けられます。 LDAP を参照してください |
| OpenID Connect、Entra ID | ID プロバイダーを通じたシングルサインオンで、プロバイダー独自の多要素認証も利用できます。 認証 を参照してください |
- サインインに失敗すると アカウントがロック され、サインインにはレート制限があります。
- サインインすると、30 分間有効な署名付きアクセストークンと、24 時間有効なリフレッシュトークンが返されます。
- トークンは有効期限前に終了させられます。サインアウト、パスワードの変更、ユーザーのブロック、API トークンの取り消しによって、 すべてのノードで同時に終了します。 トークン を参照してください。
- AnsibleForms には独自の多要素認証はありません。必要な場合はシングルサインオンを使用してください。
権限
ユーザーができることは所属グループのロールで決まり、サーバーがリクエストごとにチェックします。
- ロールは config.yaml で定義します。ユーザーに表示されるフォームと、デザイナー、設定ページ、 ほかのユーザーのジョブなど、ユーザーが持つオプションを決めます。
- サーバーは、REST API を通じた起動も含め、すべての起動をフォームのルール (フィールド、その値、ユーザーのアクセス権) に照らしてチェックします。 起動時の検証 を参照してください。
- 管理者ロールは、設計上どの playbook でも実行できます。ほかのロールには付与されたものだけが与えられます。複数のロールを持つユーザーは、 どのロールもそのオプションを拒否していない場合にだけ、そのオプションを得ます。そのため、制限的なロールが 1 つあれば、そのオプションを差し止められます。
保存されたシークレット
パスワード、トークン、鍵は、データベースに書き込まれる前に暗号化されます。
- 認証情報、LDAP のバインドパスワード、ランナーのトークン、シングルサインオンのクライアントシークレット、Webhook の アドレス、API キーなど、保存されるシークレットはすべて、お客様が設定した
ENCRYPTION_SECRETのもとで、 値ごとにランダムな初期化ベクトルを使って AES-256 で暗号化されます。 - 保存されたシークレットを表示する API 呼び出しや設定ページはなく、バックアップにはマスターシークレットが含まれません。
- シークレットを自社の Vault に置いたままにできます。 HashiCorp Vault と CyberArk は、ジョブが必要とするときに読み取られます。
- ジョブのシークレットは、そのトークンから導出した鍵を使って AES-256-GCM で封をされた状態でランタイム環境に届きます。
- 名前がシークレットのように見える extravars はジョブの表示でマスクされ、パスワードフィールドは常にマスクされます。 ジョブのデータ を参照してください。
データベースのそれ以外の部分 (ジョブ、その extravars と出力) はそのまま保存されます。データベース自体の保存時暗号化と アクセス制御で保護してください。 データベース を参照してください。
監査証跡
すべての変更と、拒否されたすべての試行が記録されます。
- インターフェイスまたは API を通じた作成、変更、削除は、それぞれユーザー、そのアドレス、操作、対象、結果とともに 監査ログに書き込まれます。拒否とサインインも、失敗したものを含めて記録されます。
- シークレットのように見える値は、書き込まれる前に伏せられます。
- ログは既定で 365 日間保持され、UDP、TCP、TLS で syslog にコピーできます。
ブラウザー側
インターフェイスは、ページに注入されたコードから保護されています。
- Content-Security-Policy により、アプリケーション自身のスクリプトとフレームだけが許可されます。
- すべての応答には保護用のヘッダーが付きます: nosniff、フレーム保護、HTTPS での HSTS です。
- フォーム、ヘルプテキスト、チャットの回答の HTML はサニタイズされ、ジョブの出力はエスケープされます。
サーバー側
ユーザーの入力を扱うコードは、典型的なインジェクションを回避しています。
- データベースクエリは、値をクエリに連結したテキストとしてではなく、常にパラメーターとして渡します。
- git を含むコマンドは、シェルではなく引数リストから実行されるため、シェルの特殊文字は効果を持ちません。
- サーバー式は 式のサニタイザー を通り、その REST 呼び出しはホストフィルターを通ります。
- MCP サーバー、 チャットアシスタント、メトリクスのエンドポイントは、有効にするまでオフです。
接続
AnsibleForms との間の通信は、エンドツーエンドで暗号化できます。
- アプリケーションは自身で HTTPS を提供するか、リバースプロキシの背後に置かれます。
- ランタイム環境は WebSocket (HTTPS のアドレスでは
wss://) でアプリケーションと通信し、アプリケーションは インバウンドの RTE の証明書をピン留めします。 RTE のモード を参照してください。 - LDAP、シングルサインオン、ランナー、git、シークレットストア、式の REST 呼び出しは、接続先サーバーの証明書を チェックします。ただし、自己署名証明書を使うサーバーに対して管理者がチェックをオフにした場合は除きます。
外部への接続
AnsibleForms が接続するのは、管理者が設定したものだけです。
| 接続先 | 接続するとき |
|---|---|
| LDAP、OpenID Connect、Entra ID (Microsoft のログインと Graph) | そのサインイン方式が設定されているとき |
| AWX / AAP / Ascender、Semaphore、Rundeck、Jenkins | フォームがそのランナーで実行されるとき |
| Git サーバー | リポジトリが設定されているとき |
| メールサーバー、Slack、Teams、Telegram、Webhook | 通知チャネルが設定されているとき |
| HashiCorp Vault、CyberArk | シークレットストアが設定されているとき |
| モデルプロバイダー (Anthropic、OpenAI など) | チャットアシスタント を有効にした場合のみ (既定では無効) |
| フォームで指定されたホストと API | フォームの式や playbook がそれらを呼び出すとき |
| Syslog サーバー | 監査ログやログの転送が設定されているとき |
コンテナー
イメージは、できるだけ少ない権限で実行されるようにビルドされています。
- アプリケーションとランタイム環境は、root ではなく、特権を持たない
nodeユーザーとして実行されます。 - ダイジェストで固定された軽量な Debian イメージをベースにビルドされています。 セキュアな開発 を参照してください。
- アプリケーションが待ち受けるポートは 8000 の 1 つだけです。
新しいインスタンスを保護する手順については、 ハードニング に従ってください。