以下の内容はhttps://zaki-hmkc.hatenablog.com/entry/2025/04/29/231328より取得しました。


[Ansible] 別ユーザー(非root)権限でのタスクの実行 (become)

Ansibleでroot権限でタスクを実行したい場合はbecomeキーワードを使えばいいが、本質的にはこの仕組みは任意のユーザー権限でタスクを実行するもの。
root権限で処理されるのは、いくつかの関連パラメタを省略するとデフォルトでroot権限で動くようになっているため。

本記事では、多くの場合に省略されるパラメタをきっちり指定するとrootではない他ユーザー権限でタスクを処理できる点についてまとめておく。

LinuxCLIに慣れてる人向けに補足すると、becomeだけ使うのはsudoを素で実行するとroot権限がデフォルト動作になるのと同じ。
本記事ではsudo-uで指定するユーザーの権限でタスクを実行するのと同様のことを行う。

基本的なタスクの書き方

例として「ユーザーを新たに作成し、そのユーザー権限で実行する必要があるタスク」というケース。 ここではyu_takasakiユーザーを作成(パスワードはerabenaiyo)し、ホームディレクトリへでPython仮想環境を作成する、というもの。

- hosts: all
  gather_facts: false
  vars:
    username: yu_takasaki
    password: erabenaiyo

  tasks:
  - name: create user
    ansible.builtin.user:
      name: "{{ username }}"
      password: "{{ password | password_hash('sha512') }}"
      shell: /bin/bash
      home: "/home/{{ username }}"
    become: true

  - name: create venv
    ansible.builtin.pip:
      name:
      - pip
      - ansible-core==2.18.5
      virtualenv: "/home/{{ username }}/python-env"
      virtualenv_command: python3 -m venv
    become: true
    become_user: "{{ username }}"
    become_method: sudo
    vars:
      ansible_become_password: "{{ password }}"

タスク「create user」は本記事では触れないが、「create venv」について、becometrueにしつつ、become_userでユーザー名を指定することで、このユーザー権限でタスクを実行する記述になる。
ただbecome系のキーワードには「becomeのためのパスワードを指定」する専門の設定項目がなぜかないため、vars.ansible_become_passwordに指定ユーザーのパスワードをセットする。
(言い換えると、become_passwordはAnsibleにはないんで、varsを使って変数でセットする、ということ)

権限エラーの場合の原因と対処方法4選

環境によっては以下のようなエラーが発生する場合がある(ansible-playbookの実行に-v付与)

fatal: [node]: FAILED! => 
    msg: |-
        Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 1, err: OpenSSH_9.9p1, OpenSSL 3.2.4 11 Feb 2025
        debug1: Reading configuration data /home/zaki/.ssh/config
        debug1: /home/zaki/.ssh/config line 1: Applying options for *
        debug1: Reading configuration data /etc/ssh/ssh_config
        debug1: Reading configuration data /etc/ssh/ssh_config.d/20-systemd-ssh-proxy.conf
        debug1: Reading configuration data /etc/ssh/ssh_config.d/50-redhat.conf
        debug1: Reading configuration data /etc/crypto-policies/back-ends/openssh.config
        debug1: configuration requests final Match pass
        debug1: re-parsing configuration
        debug1: Reading configuration data /home/zaki/.ssh/config
        debug1: /home/zaki/.ssh/config line 1: Applying options for *
        debug1: Reading configuration data /etc/ssh/ssh_config
        debug1: Reading configuration data /etc/ssh/ssh_config.d/20-systemd-ssh-proxy.conf
        debug1: Reading configuration data /etc/ssh/ssh_config.d/50-redhat.conf
        debug1: Reading configuration data /etc/crypto-policies/back-ends/openssh.config
        debug1: auto-mux: Trying existing master at '/home/zaki/.ansible/cp/7c19651577'
        debug1: mux_client_request_session: master session id: 2
        chmod: invalid mode: ‘A+user:yu_takasaki:rx:allow’
        Try 'chmod --help' for more information.
        }). For information on working around this, see https://docs.ansible.com/ansible-core/2.18/playbook_guide/playbooks_privilege_escalation.html#risks-of-becoming-an-unprivileged-user

原因はリンクに書かれている通りで、ざっくりいうと「Ansibleはリモートマシンに処理のためのスクリプトを転送してそれをリモートで実行するが、対象サーバーに接続してるユーザーとbecomeで切り替えるユーザーが異なる場合、ユーザー間でスクリプトのアクセス権限が共有できる状態にある必要がある」というもの(rootの場合は正常に動作する)

リモートサーバーにsetfaclを入れる

順当な対処法としてはこれ。たぶん。
OSコマンドとしてsetfaclが使用可能だと、スクリプトの実行・読み取り権限を内部でよしなにしてくれる(説明が雑)。
dnfおよびaptともに、aclパッケージをインストールすれば使用可能になる。

debian系なら以下のタスクを事前に仕込んでおけばOK

- name: install acl
  ansible.builtin.apt:
    name:
    - acl
    update_cache: true
  become: true

観測範囲だと、AWSのAmazonLinux2023はデフォルトでこれが入っているため、特に小細工なしでbecome_userで他ユーザー権限の処理が可能。

common_remote_group (変数名ansible_common_remote_group)

これにグループ名をセットすることで転送するスクリプトファイルの(ownerでなく)groupをそのグループにするというもの。
接続ユーザーと実行ユーザーで同一のOSグループ設定を追加しておき、かつこの設定で読み取り権をグループに付与することでユーザーを切り替えてもスクリプトを実行できるようにする。(ANSIBLE_KEEP_REMOTE_FILES=trueでスクリプトファイルを確認した限りでは770になる)

前述のユーザー作成タスク含めてcommon_remote_groupを使用する構成に改良すると以下の通りで、Ansible実行時に接続するユーザーもnijigasakiグループに所属していればOK

  - name: create user
    ansible.builtin.user:
      name: "{{ username }}"
      password: "{{ password | password_hash('sha512') }}"
      shell: /bin/bash
      home: "/home/{{ username }}"
      groups:
      - nijigasaki
    become: true

  - name: create venv
    ansible.builtin.pip:
      name:
      - pip
      - ansible-core==2.18.5
      virtualenv: "/home/{{ username }}/python-env"
      virtualenv_command: python3 -m venv
    become: true
    become_user: "{{ username }}"
    become_method: sudo
    vars:
      ansible_become_password: "{{ password }}"
      ansible_common_remote_group: nijigasaki

docs.ansible.com

world_readable_temp (変数名ansible_shell_allow_world_readable_temp)

雑だけど簡単で確実な案。
リモートに作成・実行するためのスクリプトファイルの権限をall readableにする(ANSIBLE_KEEP_REMOTE_FILES=trueでスクリプトファイルを確認した限りでは755になる / デフォルトは700)
タスク実行に関するスクリプトがOSのファイルシステム上で誰からもアクセスされても問題ないのであれば楽。

変数指定する場合は名称が(他に比べると大きく)異なるのでその点だけ注意。(world_readable_temp -> ansible_shell_allow_world_readable_temp)

    become: true
    become_user: "{{ username }}"
    become_method: sudo
    vars:
      ansible_become_password: "{{ password }}"
      ansible_shell_allow_world_readable_temp: true

docs.ansible.com

リモートからSSH認証可能なのであれば接続しなおす

becomeを使ったタスク内での権限変更でなく、SSH接続が可能であれば接続ユーザーを変更して実行しても回避できる。

    remote_user: "{{ username }}"
    vars:
      ansible_password: "{{ password }}"

ユーザー作成直後とかだとSSH接続可能な条件がそろっていない可能性は高い(公開鍵認証の可否など)が、可能であればこれはこれで簡単。

参考情報

docs.ansible.com

github.com

www.slideshare.net


copyモジュールなどのファイル配置系の処理であれば標準でファイルのowner/groupを指定可能なので小難しい処理なしで「root権限で処理しつつ的確なファイルの所有権設定」をセットすれば多くの場合は問題ないが、owner/groupの設定ができないモジュールを使う場合はそうもいかないので、対処できる方法についてまとめてみた。

これ以外に「いやそんな小細工しなくてもこれで一撃でできるが?」な情報があればぜひ教えてください。


www.youtube.com




以上の内容はhttps://zaki-hmkc.hatenablog.com/entry/2025/04/29/231328より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14