本記事は以下2部構成で作成しています。
- [Ansible]Cloudflare Zero Trust配下のAAP設定をGitLabで管理①~Playbook作成~(本記事)
- [Ansible]Cloudflare Zero Trust配下のAAP設定をGitLabで管理②~Cloudflare・GitLab設定~
はじめに
皆様は、Ansible Automation Platform(AAP)・AWXのジョブテンプレート設定などはコードで管理していますか?
筆者にも言えることですがAAP内で利用するPlaybook自体のコードはGitで管理していてもAAP側の設定はGUIが備わっているので手作業でやることが多いです。
しかし、検証・本番Playbookを管理したり複数チームが入ってくるとAAPの設定はカオスになって手作業で管理することは難しくなります。
そこで今回は、AAPの設定パラメータをGitLabで管理して設定内容を自動で機器に設定するようにしてみたのでその内容を紹介します。
ここまでの内容としてはn番煎じの内容なので、AAPをCloudflare Zero Trust(以降Cloudflareという)配下に置き、GitLabからのアクセスのみを通すようにしました。
全体の構成は以下の通りです。
本記事では、AAPのPlaybook作成部分(図の①)のみとし、
Cloudflare Zero Trustを使ってGitLabからセキュアにWebhookを利用する部分(図の②、③)は別記事として投稿します。
環境
- Ansible Automation Platform: 2.2
- ansible.controller collection: 4.4.0
構築
①AAP設定Playbook・Job Template作成
AAPに設定を行うためのPlaybook作成とそれを動かすJob Templateを作成します。
Playbook作成
AAP設定を行うコレクションはansible.controllerコレクションを使用します。
こちらのコレクションはAAPサブスクリプションがないと見れないですが、同様の仕様としてawx.awxコレクションがあるのでそちらも参照ください。
当初、GitLab RunnerからAnsibleを直接動かしてAAP設定を行おうとしていましたが、Cloudflareを含めて使おうとしたときに技術的にポリシーを通すことが出来ませんでした。
そのため、GitLab RunnerはAAPにWebhookを送ってAAP側でJob Templateを実行するようにしました。
設定対象は運用で変更が多いであろう以下オブジェクトにしています。
- Inventory
- Inventory Sources
- Projects
- Execution Environments
- Job Templates
- Workflow Job Templates
設定対象のデータはモジュール説明を見て以下のようなvarsとして定義します。
かなり面倒なのでansible.controller.export
モジュールを使って必要部分だけ取り込み、dictの順番を変更して使いました。
---
projects:
- name: PJ_DEV
description: Develop Project
organization: Default
credential: GitLab SCM
scm_url: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
scm_branch: develop
scm_update_on_launch: true
- name: PJ_PRD
description: Production Project
organization: Default
credential: GitLab SCM
scm_url: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
scm_branch: main
scm_update_on_launch: true
Playbookは以下の通りで、先程定義したデータを読み込んでloopでオブジェクトを作成します。
---
- name: Configure AAP
hosts: localhost
gather_facts: false
vars_files:
- vars/projects.yml
- vars/inventory.yml
- vars/inventory_sources.yml
- vars/execution_environments.yml
- vars/job_templates.yml
- vars/workflow_job_templates.yml
tasks:
- name: Configure projects
ansible.controller.project:
state: present
name: "{{ item.name }}"
description: "{{ item.description | default(omit) }}"
organization: "{{ item.organization | default(omit) }}"
credential: "{{ item.credential | default(omit) }}"
default_environment: "{{ item.default_environment | default(omit) }}"
scm_type: "{{ item.scm_type | default(omit} }"
scm_url: "{{ item.scm_url | default(omit) }}"
scm_branch: "{{ item.scm_branch | default(omit) }}"
scm_refspec: "{{ item.scm_refspec | default(omit) }}"
scm_update_on_launch: "{{ item.scm_update_on_launch | default(omit) }}"
scm_clean: "{{ item.scm_clean | default(omit) }}"
scm_delete_on_update: "{{ item.scm_delete_on_update | default(omit) }}"
scm_track_submodules: "{{ item.scm_track_submodules | default(omit) }}"
scm_update_cache_timeout: "{{ item.scm_update_cache_timeout | default(omit) }}"
loop: "{{ projects }}"
- name: Configure EE
ansible.controller.execution_environment:
・・・
Job Template作成
次にAAP側でPlaybookを実行できるようにJob Templateを作成します。
まず、AAPを操作するためのトークンを以下手順で作成します。
次に作成したトークンをJob Templateで使えるように認証情報タイプを作成し、環境変数経由でトークン認証できるようにします。
fields:
- id: CONTROLLER_HOST
type: string
label: Controller Host URL
- id: CONTROLLER_OAUTH_TOKEN
type: string
label: Controller API Token
secret: true
- id: CONTROLLER_VERIFY_SSL
type: boolean
label: Verify SSL
required:
- CONTROLLER_HOST
- CONTROLLER_OAUTH_TOKEN
- CONTROLLER_VERIFY_SSL
env:
CONTROLLER_HOST: '{{ CONTROLLER_HOST }}'
CONTROLLER_VERIFY_SSL: '{{ CONTROLLER_VERIFY_SSL }}'
CONTROLLER_OAUTH_TOKEN: '{{ CONTROLLER_OAUTH_TOKEN }}'
あとは、適当なインベントリと合わせてJob Templateを作成します。
Webhook待ち受け設定
最後にAAPのWebhookからJob Templateを実行できるようにします。
Webhookの設定は、オプションのWebhookの有効化
チェックボックスをつけることで待ち受け可能になります。
Webhookサービスは、GitHub
とGitLab
の2パターンがありますので今回はGitLab
を選択します。
認証情報を入力することで実行完了後にGitLab側に結果通知を出来ますが、今回のやり方の場合GitLabの純粋なWebhookを使わないためそのままにします。
これでWebhookが使えるようになったのでcurlを使い、Job Template作成時に出てきたWebhook URL
とWebhookキー
を含めて実行します
curl <Webhook URL> -X POST \
-H "Content-Type: application/json" \
-H "X-Gitlab-Token: <Webhookキー>" \
-d "{\"test\": \"test\"}"
結果に以下が出ればWebhook成功です。
{"message":"Job queued."}
Webhookはキューとして受け付けただけを返すのみで、Job実行結果はAAP側を見る必要があります。
AAP側でJob結果で成功
であればOKです。
これでサーベイや複雑なワークフローを含んだWorkflow Templateを作成することが出来ました。
次に2回目実行しようとしましたが、以下ワーニングが出て実行されませんでした。
{"message":"Webhook previously received, aborting."}
これは、AAP側にてWebhookが複数回実行しないようにリクエストボディーをハッシュ化してGUIDとして管理しているからです。
そのため、curlでPOSTするときはリクエストボディーにランダムなJSONを入力する必要があります。
GitLabで実行する際は、コミットハッシュをつけるのが適当かと思います。
おわりに
AAPの自動構築Playbook・Job Templateを使ってみて、パラメータをコピペして検証環境・本番環境を簡単に作ることができるのはかなり実用的でした。
Job TemplateのWebhook機能も初めて使いましたが、Webhookキーによる簡易認可機能もあり外部公開しても問題なさそうに思いました。
しかし、AAPの役割を考えると脆弱性を突かれたときのリスクがあるためそのまま公開するのは避けたほうがよさそうです。
この辺りは、次回のCloudflare Zero Trustを使って解決します。
一方、Webhookは対象サービスがGitHubとGitLabしかないため、汎用的に使う場合はAPIでジョブ制御したほうが良いとも感じました。
特に、ボディのリクエストを毎回変える必要があることと、実行ジョブの結果を確認できないのは引っ掛かりポイントでした。
参考リンク
-
https://docs.ansible.com/automation-controller/4.0.0/html_ja/userguide/webhooks.html
- AAP Webhook説明ページ
-
https://console.redhat.com/ansible/automation-hub/repo/published/ansible/controller
- ansible.controllerコレクションのページ(要Red Hatアカウントログイン)
-
https://docs.ansible.com/ansible/latest/collections/awx/awx/index.html
- awx.awxコレクション説明ページ
-
https://github.com/ansible/awx/blob/2a1dffd36346e31a5eb9bd9e5770a3ea12827c4f/awx/api/views/webhooks.py#L200
- webhookでGUID計算しているソースコード部分