Red Hat Certified Engineer (RHCE) #17 RHCSA 自動化 4: firewall、SELinux、SSH キー

読了 7分

#16 RHCSA 自動化 3: ストレージ (LVM)、ファイルシステム (NFS) でストレージをプレイブックで構成したなら、今回は RHCSA 自動化の最後の領域である セキュリティ構成 を扱います。firewalld でポートを永続的に許可し、SELinux boolean とファイルコンテキストを調整し、ユーザーアカウントに SSH 公開鍵を配布する作業をすべて Ansible で自動化します。

この 3 つは RHCSA で手で覚えた作業です。RHCSA #12 firewalld と SSH 鍵認証firewall-cmd --permanentssh-copy-id を扱い、RHCSA #13 SELinux 深掘りsetsebool -Psemanage fcontextrestorecon を覚えました。RHCE は同じ結果を 冪等性のあるプレイブック で作り出す仕事です。

モジュールが属する collection から #

セキュリティ作業に使うモジュールは大半が ansible.posixcommunity.general collection に入っています。core にデフォルトで含まれていないことがあるので、試験環境でインストールされているかをまず確認します。

作業モジュールcollection
firewalld ルールfirewalldansible.posix
SELinux booleansebooleanansible.posix
SELinux モードselinuxansible.posix
ファイルコンテキストsefcontextcommunity.general
SSH 公開鍵の配布authorized_keyansible.builtin

ansible-doc -l | grep firewalld でモジュールが見えるか確認し、見えなければ ansible-galaxy collection install ansible.posix でインストールします。モジュールの全オプションは、インターネットのない環境で ansible-doc ansible.posix.firewalld で調べる習慣をつけます。

firewalld の自動化 #

RHCSA で firewall-cmd --add-service=http --permanent--reload でやった作業を ansible.posix.firewalld モジュールに移します。このモジュールの核心は、永続適用と即時適用を別々のオプションで制御する という点です。

オプション意味
service または port許可対象。サービス名または ポート/プロトコル
stateenabled で許可、disabled で遮断
permanent: true永続ルール (reboot 後も維持)。--permanent に該当
immediate: trueランタイムにも即時反映。--reload なしですぐ適用
zone適用する zone。省略時はデフォルト zone

--permanent だけを適用すると再起動前までランタイムに反映されないので、試験では permanent: trueimmediate: true を一緒に かけるのが安全です。片方だけかけると「今は開いたが再起動すると閉じる」または「再起動後は開くが今は閉じている」といった部分減点になります。

firewalld 構成プレイブック
---
- name: Configure firewalld
  hosts: webservers
  become: true
  tasks:
    - name: Ensure firewalld is running
      ansible.builtin.service:
        name: firewalld
        state: started
        enabled: true

    - name: Allow http service permanently and immediately
      ansible.posix.firewalld:
        service: http
        state: enabled
        permanent: true
        immediate: true

    - name: Allow https service
      ansible.posix.firewalld:
        service: https
        state: enabled
        permanent: true
        immediate: true

    - name: Allow custom tcp port 8080
      ansible.posix.firewalld:
        port: 8080/tcp
        state: enabled
        permanent: true
        immediate: true

service/usr/lib/firewalld/services に定義された名前を使い、定義のないポートは port: 8080/tcp 形式で直接開きます。複数のサービスを一度に処理するには loop でまとめても構いません。

loop で複数サービス許可
    - name: Allow multiple services
      ansible.posix.firewalld:
        service: "{{ item }}"
        state: enabled
        permanent: true
        immediate: true
      loop:
        - http
        - https
        - cockpit

SELinux の自動化 #

SELinux の作業は 3 つに分かれます。モード設定boolean トグルファイルコンテキスト指定 です。それぞれ別のモジュールを使うので、区別して覚えます。

1) モード設定: selinux モジュール #

ansible.posix.selinux モジュールで enforcing または permissive モードを設定します。state: enforcing がポリシー適用モードで、policy: targeted が標準ポリシーです。

SELinux enforcing 設定
    - name: Ensure SELinux is enforcing
      ansible.posix.selinux:
        state: enforcing
        policy: targeted

disabled から enabled に変える場合のように再起動が必要な変更だと、このモジュールは結果に reboot_required を知らせます。その場合は ansible.builtin.reboot task で再起動につなげるパターンが安全です。

2) boolean トグル: seboolean モジュール #

setsebool -P httpd_can_network_connect on でやった作業が ansible.posix.seboolean モジュールです。persistent: true が RHCSA の -P に該当 し、これを抜かすと再起動後に値が初期化されます。

SELinux boolean の切り替え
    - name: Allow httpd to make network connections
      ansible.posix.seboolean:
        name: httpd_can_network_connect
        state: true
        persistent: true
オプション意味
nameboolean の名前。getsebool -a で確認
statetrue でオン、false でオフ
persistent: true再起動後も維持。setsebool -P に該当

3) ファイルコンテキスト: sefcontext モジュール #

非標準パス (例: /web 配下の Web コンテンツ) を置くと SELinux ラベルが合わず、サービスがアクセスできません。RHCSA では semanage fcontext でポリシーにルールを追加し、restorecon で実際のファイルにラベルを適用しました。

community.general.sefcontext モジュールは ポリシールールの追加だけ を行います。つまり semanage fcontext に該当する作業までしかせず、実際のファイルラベルの適用 (restorecon) は別の task でつなげる必要があります。この 2 つをまとめるのが定石です。

fcontext ルール追加と restorecon
    - name: Add fcontext rule for /web
      community.general.sefcontext:
        target: '/web(/.*)?'
        setype: httpd_sys_content_t
        state: present

    - name: Apply the new context to existing files
      ansible.builtin.command:
        cmd: restorecon -Rv /web

sefcontext だけを実行するとポリシーにはルールが入りますが、すでに存在するファイルのラベルは変わりません。そのため commandrestorecon を一度回さないと実際のファイルに反映されません。command は毎回 changed として扱われ冪等性が少し崩れますが、試験では restorecon が抜けるほうがはるかに大きい減点なので、一緒に置くことをおすすめします。

SSH 公開鍵の配布 #

RHCSA で ssh-copy-id でやった公開鍵の配布を ansible.builtin.authorized_key モジュールで自動化します。特定のユーザーの ~/.ssh/authorized_keys に公開鍵を冪等に追加するモジュールです。

公開鍵の配布
    - name: Deploy public key for deploy user
      ansible.builtin.authorized_key:
        user: deploy
        state: present
        key: "{{ lookup('file', 'files/deploy_id_ed25519.pub') }}"
オプション意味
user対象のユーザーアカウント
key登録する公開鍵の文字列。lookup('file', ...) でファイルから読む
statepresent で追加、absent で削除
exclusive: trueこの鍵だけを残し既存の鍵をすべて削除

key は control node に置いた公開鍵ファイルを lookup('file', ...) で読み込む方式がよくあります。複数のユーザーにそれぞれの鍵を配布するには、変数ディクショナリと loop を組み合わせます。

複数ユーザーへの公開鍵配布
    - name: Deploy keys for multiple users
      ansible.builtin.authorized_key:
        user: "{{ item.name }}"
        state: present
        key: "{{ lookup('file', item.keyfile) }}"
      loop:
        - { name: alice, keyfile: files/alice.pub }
        - { name: bob, keyfile: files/bob.pub }

system role の代替 #

この領域も手でモジュールをかける代わりに、#13 system roles で扱った rhel-system-roles で処理できます。試験で system role を使えと明示されたら必ず role を使い、そうでなければ慣れているほうを選べばよいです。

firewall system role #

redhat.rhel_system_roles.firewall role に変数でルールを宣言します。role の内部が永続適用まで処理するので、オプションを一つ一つ気にする必要が減ります。

firewall role プレイブック
- name: Configure firewall via system role
  hosts: webservers
  become: true
  roles:
    - redhat.rhel_system_roles.firewall
  vars:
    firewall:
      - service: http
        state: enabled
      - service: https
        state: enabled
      - port: 8080/tcp
        state: enabled

selinux system role #

redhat.rhel_system_roles.selinux role でモードと boolean、ファイルコンテキストを一度に宣言します。role がコンテキストの適用まで一緒に処理するので、restorecon を別に呼ばなくても済みます。

selinux role プレイブック
- name: Configure SELinux via system role
  hosts: webservers
  become: true
  roles:
    - redhat.rhel_system_roles.selinux
  vars:
    selinux_state: enforcing
    selinux_booleans:
      - name: httpd_can_network_connect
        state: true
        persistent: true
    selinux_fcontexts:
      - target: '/web(/.*)?'
        setype: httpd_sys_content_t
        state: present
    selinux_restore_dirs:
      - /web

統合例 #

3 つの領域を 1 つのプレイブックにまとめると、試験のセキュリティ自動化問題に近い形になります。firewalld でポートを開け、SELinux boolean をオンにし、SSH 鍵を配布する流れです。

セキュリティ統合プレイブック
---
- name: Secure web hosts
  hosts: webservers
  become: true
  tasks:
    - name: Open http and https permanently
      ansible.posix.firewalld:
        service: "{{ item }}"
        state: enabled
        permanent: true
        immediate: true
      loop:
        - http
        - https

    - name: Enforce SELinux
      ansible.posix.selinux:
        state: enforcing
        policy: targeted

    - name: Enable httpd network boolean
      ansible.posix.seboolean:
        name: httpd_can_network_connect
        state: true
        persistent: true

    - name: Add fcontext for content dir
      community.general.sefcontext:
        target: '/web(/.*)?'
        setype: httpd_sys_content_t
        state: present

    - name: Restore context on content dir
      ansible.builtin.command:
        cmd: restorecon -Rv /web

    - name: Deploy admin public key
      ansible.builtin.authorized_key:
        user: deploy
        state: present
        key: "{{ lookup('file', 'files/deploy.pub') }}"

試験のポイント #

  • firewalld は permanent: trueimmediate: true を一緒に かけるのが安全です。片方だけかけると再起動の前後で状態が食い違い、部分減点になります。
  • seboolean は persistent: true を必ず 入れます。RHCSA の setsebool -P に該当し、抜けると再起動後に初期化されます。
  • sefcontext はルールの追加だけ を行います。実際のファイルへの適用は restorecon を別の task でつなげないとラベルが反映されません。
  • selinux モジュールは再起動が必要な変更 (disabled から enabled) だと reboot_required を知らせます。必要なら reboot task につなげます。
  • authorized_key の keylookup('file', ...) で control node の公開鍵を読み込みます。exclusive: true は既存の鍵を消すので、意図するときだけ使います。
  • モジュールが見えなければ、ansible-galaxy collection install ansible.posixcommunity.general をまず確認します。

まとめ #

この記事で押さえたこと:

  • firewalldansible.posix.firewalld で service と port を permanent: true + immediate: true で永続許可
  • SELinux モードansible.posix.selinux で enforcing/targeted を設定。必要に応じて再起動
  • SELinux booleanansible.posix.seboolean でトグル。persistent: true で永続適用
  • SELinux コンテキストcommunity.general.sefcontext でルールを追加後 restorecon で適用
  • SSH 鍵ansible.builtin.authorized_key でユーザーごとの公開鍵を配布
  • system role の代替。firewall と selinux role で同じ作業を変数宣言で処理

これで #14 から続いた RHCSA 自動化の 4 編が終わりました。ユーザー・パッケージ、サービス・時刻・ログ、ストレージ、セキュリティまで、RHCSA の手作業をすべてプレイブックに移しました。試験比重の半分を占める領域なので、各モジュールの永続適用オプションを手に覚えることが合格ラインを超える近道です。

次へ: 試験のコツ #

自動化の領域をすべて扱ったので、次は 4 時間を実際にどう運用するかを整理する番です。

#18 試験のコツと時間管理 では、ansible-doc の活用法、冪等性検証の習慣、永続適用の点検チェックリスト、そして時間配分の戦略まで、試験会場ですぐ使える実戦的なコツを整理します。

X