Ansible モジュールをコピーして - 権限が拒否されました

Ansible モジュールをコピーして - 権限が拒否されました

localhostフォルダを別の場所にコピーするためにAnsibleスクリプトを実行しています。しかし、

- name: Copy Network
  become: yes
  become_user: root
  copy:
    src: /d/
    dest: "/dest/d/"
    mode: 0644
  tags: [network]

が表示されています[Errno 13] Permission denied: b'd/f1'。このコマンドが root として実行されることを期待していましたがbecome_user、動作しませんでした。このファイルの権限は です0600(root:root)

このファイルにアクセスして、Ansible を使用してコピーするためのヒントを教えていただけますか?

注記:

  • sudo ansible-playbook p.ymlsudo完璧に動作しますが、必要でない場合や Ansible にそのためのトリックがある場合は、Ansible コマンドで使用したくありません。

  • command: cp -r /d/ /dest/d/sudoansible コマンド ( ) に追加しなくても動作します。ただし、べき等性とモジュールにタスクに必要なオプションがあるため、できればansible-playbook p.yml使用したくありません。commandcopymode

答え1

更新: ローカルホストマスターで権限をルートに昇格できる場合、解決策は次のようになりますremote_src: true(credit @ivandov)

- copy:
    src: /d/
    dest: /dest/d/
    mode: '0644'
    remote_src: true
  become: true
  become_user: root

以下は、ローカルホストでルートに昇格できない場合の詳細です。ローカルホスト上のファイルの場合

shell> ll /tmp/test/d/f1
-rw-r----- 1 root root 0 Aug 25 23:23 /tmp/test/d/f1

モジュールコピー期待通りに動作する

- copy:
    src: /tmp/test/d/
    dest: /tmp/test/dest/
  become: true
  become_user: root

まず、ファイルを読み込もうとして失敗する

致命的: [localhost]: 失敗しました! => メッセージ: 'ファイル ''/tmp/test/d/f1'' の読み取り中にエラーが発生しました: [Errno 13] 権限が拒否されました: b''/tmp/test/d/f1''。 [Errno 13] 権限が拒否されました: b''/tmp/test/d/f1'''

デフォルトでは、モジュールコピーファイルをコピーするソース(リモートサーバーにコピーするファイルへのローカルパス)目的地(ファイルをコピーするリモートの絶対パス)。この場合、become: trueAnsible はリモート ホストで権限を昇格しますが、ローカルホストのマスターでは昇格しません。タスクがローカルホストで実行されているにもかかわらず、つまりマスターとリモート ホストの両方がローカルホストであるにもかかわらず、remote_src: true設定がないbecome: trueと、ファイルの書き込みにのみ適用され、読み取りには適用されません。ローカルホスト設定でルートに昇格できない場合は、remote_src: true

- copy:
    src: /tmp/test/d/
    dest: /tmp/test/dest/
    remote_src: true
  become: true
  become_user: root

失敗する

fatal: [localhost]: 失敗しました! => changed=false ansible_facts: discovered_interpreter_python: /usr/bin/python3 module_stderr: |- sudo: パスワードが必要です module_stdout: '' msg: |- モジュール障害 正確なエラーについては stdout/stderr を参照してください rc: 1


質問:「回避策はありますか?」

A: ルートへのエスカレーションがなければ回避策はありません。ファイルの所有権と権限に違反することになります。たとえば、コントローラのファイルが

shell> ll f1
-rw-rw---- 1 root root 0 Sep 13 18:17 f1

以下のプレイブックは権限のないユーザーによって開始されました

shell> cat playbook.yml
- hosts: test_01
  become: true
  tasks:
    - copy:
        src: f1
        dest: /tmp

クラッシュする

TASK [copy] ****
fatal: [test_01]: FAILED! => 
  msg: 'an error occurred while trying to read the file ''/scratch/f1'':
       [Errno 13] Permission denied: b''/scratch/f1'''

ローカルホスト マスターでルートにエスカレートできない場合は、プレイブックを実行しているユーザーがファイルを読み取り可能にすることが解決策です。

答え2

Vladimir の回答を基にすると、実は簡単な回避策があります。

以下のコメント(太字で強調した部分)が鍵でした。

モジュールコピーでは、become: yesはファイルの書き込みにのみ適用されます。読まない

remote_src: trueファイルをローカルにコピーする場合でも、を使用します。これにより、 はリモート マシンとして扱い、権限の昇格を適切に適用するため、ローカル マシンからファイル/ディレクトリをbecome読み取るときに権限が正しく昇格されます。srcsrc

- name: Copy Network
  become: yes
  become_user: root
  copy:
    src: /d/
    dest: "/dest/d/"
    remote_src: true  # this allows become to work as expected
    mode: 0644
  tags: [network]

答え3

tl;dr - Ansible は、become: rootプレイブックを実行している Ansible ホストではなく、ターゲット マシンに適用されます。回避策は可能です。

答えを書きましたここroot単一ファイルでこの問題に対処するには、プレイブックを実行している Ansible ホストは、で自身の権限を に上げませんbecome: root。これはターゲット マシンにのみ適用されます。元の質問では両方とも ですが、この動作は依然として適用されると思います。これは、権限のない「ソース」と権限のあるターゲットlocalhostとして考えてください。rootroot

このソリューションdelegate_to: localhostでは、slurp必要なファイルをメモリに保存します。これにより、ローカルでその魔法が動作し、保存されたファイルをターゲット マシンに書き出すdelegate_to:ことができます。become: root

元の質問では、ディレクトリに対してこれを行うことについて尋ねていますが、slurpディレクトリについても議論されています。こここれは、ファイルごとのソリューションと組み合わせると適切な出発点となるはずですslurp。特に、ファイルごとの回避策を使用する前にファイルのリストを作成することに関する、その回答に対する @guzmonne のコメントに注意してくださいslurp(これは優れた方法ではありませんが、ファイル/ディレクトリのアクセス許可を変更するよりも好ましい場合があります)。

関連情報