Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible

AnsibleAnsibleBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Ansible is a powerful automation tool that simplifies infrastructure management and configuration. The Ansible script module allows you to execute custom scripts within your playbooks, extending Ansible's functionality beyond its built-in modules. However, users often encounter the 'Permission denied' error when using this module, which can impede automation workflows.

This lab will guide you through understanding and resolving permission-related issues in Ansible's script module. You will learn how to identify the causes of permission errors and implement various solutions to ensure your Ansible scripts run successfully.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ansible(("Ansible")) -.-> ansible/ModuleOperationsGroup(["Module Operations"]) ansible(("Ansible")) -.-> ansible/PlaybookEssentialsGroup(["Playbook Essentials"]) ansible/ModuleOperationsGroup -.-> ansible/apt("Package Manager") ansible/ModuleOperationsGroup -.-> ansible/command("Execute Commands") ansible/ModuleOperationsGroup -.-> ansible/debug("Test Output") ansible/ModuleOperationsGroup -.-> ansible/file("Manage Files/Directories") ansible/ModuleOperationsGroup -.-> ansible/script("Run Scripts") ansible/ModuleOperationsGroup -.-> ansible/shell("Execute Shell Commands") ansible/ModuleOperationsGroup -.-> ansible/stat("File Statistics") ansible/PlaybookEssentialsGroup -.-> ansible/playbook("Execute Playbook") subgraph Lab Skills ansible/apt -.-> lab-415726{{"Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible"}} ansible/command -.-> lab-415726{{"Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible"}} ansible/debug -.-> lab-415726{{"Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible"}} ansible/file -.-> lab-415726{{"Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible"}} ansible/script -.-> lab-415726{{"Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible"}} ansible/shell -.-> lab-415726{{"Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible"}} ansible/stat -.-> lab-415726{{"Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible"}} ansible/playbook -.-> lab-415726{{"Comment résoudre l'erreur 'Permission refusée' dans le module de script Ansible"}} end

Installing Ansible and Setting Up the Environment

Before we can explore permission issues with Ansible scripts, we need to set up our environment. Let's install Ansible and create a basic structure for our test environment.

Installing Ansible

First, let's update the package index and install Ansible:

sudo apt update
sudo apt install -y ansible

Once the installation is complete, verify that Ansible is installed correctly:

ansible --version

You should see output similar to this, showing the Ansible version and configuration details:

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, Mar 01 2023, 12:34:56) [GCC 11.2.0]
  jinja version = 3.0.3
  libyaml = True

Setting Up the Project Structure

Now, let's create a project directory structure for our Ansible playbook and scripts:

mkdir -p ~/project/ansible-lab/{playbooks,scripts}
cd ~/project/ansible-lab

In this structure:

  • playbooks/ will contain our Ansible playbooks
  • scripts/ will contain our shell scripts to be executed by Ansible

Creating a Simple Script

Let's create a simple shell script that we'll use with Ansible. Create a file named hello.sh in the scripts directory:

cd ~/project/ansible-lab/scripts
touch hello.sh

Open the hello.sh file in the editor and add the following content:

#!/bin/bash
echo "Hello from $(hostname)!"
echo "Current time: $(date)"
echo "Current user: $(whoami)"

This script will output the hostname, current time, and the user that executed the script.

Creating an Inventory File

Next, let's create a simple inventory file for Ansible. In Ansible, an inventory file defines the hosts and groups that Ansible will manage:

cd ~/project/ansible-lab
touch inventory.ini

Open the inventory.ini file and add the following:

[local]
localhost ansible_connection=local

This inventory file tells Ansible to run commands on the local machine.

Creating a Basic Playbook

Now, let's create a basic Ansible playbook that uses the script module:

cd ~/project/ansible-lab/playbooks
touch run_script.yml

Open the run_script.yml file and add the following content:

---
- name: Run a script
  hosts: local
  tasks:
    - name: Execute the hello script
      script: ../scripts/hello.sh

This playbook will try to execute our hello.sh script on the local machine.

With this basic setup, we're ready to explore permission issues with Ansible scripts in the next steps.

Encountering the Permission Denied Error

Now that we have set up our environment, let's try to run our Ansible playbook and understand what happens when we encounter a permission denied error.

Running the Playbook

Let's try to run our playbook:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/run_script.yml

You will likely encounter an error message similar to this:

TASK [Execute the hello script] *******************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "failed to execute the script: /bin/sh: 1: /home/labex/.ansible/tmp/ansible-tmp-1234567890.12-123456789012345/AnsiballZ_script.py: Permission denied"}

This is a common permission denied error when using the Ansible script module. The error occurs because our script doesn't have the execute permission, which is required for it to run.

Understanding File Permissions in Linux

In Linux, every file has permissions that determine who can read, write, or execute it. There are three types of permissions:

  1. Read (r): Allows reading the file's contents
  2. Write (w): Allows modifying the file
  3. Execute (x): Allows executing the file as a program

These permissions are assigned to three different user categories:

  1. User (owner): The file's owner
  2. Group: Users who are members of the file's group
  3. Others: All other users

You can view a file's permissions using the ls -l command:

ls -l ~/project/ansible-lab/scripts/hello.sh

You might see output like this:

-rw-rw-r-- 1 labex labex 95 Jun 10 12:34 /home/labex/project/ansible-lab/scripts/hello.sh

In this output, the first set of characters (-rw-rw-r--) represents the file's permissions:

  • The first character (-) indicates this is a regular file
  • The next three characters (rw-) are the owner's permissions (read, write, no execute)
  • The next three (rw-) are the group's permissions
  • The final three (r--) are permissions for others

Notice that the execute permission (x) is missing for all user categories, which is why we're getting the permission denied error.

Checking the Current Permissions

Let's examine the current permissions of our script:

ls -l ~/project/ansible-lab/scripts/hello.sh

You'll see that the script is missing the execute permission, which is needed for Ansible to run it.

In the next step, we'll learn how to fix this permission issue and successfully run our Ansible playbook.

Fixing Permission Issues with chmod

The most common way to fix the "Permission denied" error is to add execute permissions to the script file. We can do this using the chmod command.

Understanding the chmod Command

The chmod command is used to change the permissions of files or directories in Linux. The command has several ways to specify permissions:

  1. Symbolic mode: Uses letters (r, w, x) to represent permissions
  2. Numeric mode: Uses numbers (4, 2, 1) to represent permissions

For our purpose, we'll use the symbolic mode to add execute permissions.

Adding Execute Permissions to the Script

Let's add execute permissions to our script:

chmod +x ~/project/ansible-lab/scripts/hello.sh

The +x option adds execute permission for all user categories (user, group, and others).

Let's verify that the permissions have been updated:

ls -l ~/project/ansible-lab/scripts/hello.sh

You should now see output similar to this:

-rwxrwxr-x 1 labex labex 95 Jun 10 12:34 /home/labex/project/ansible-lab/scripts/hello.sh

Notice the x in the permissions string, indicating that the execute permission has been added.

Running the Playbook Again

Now that we've added execute permissions to our script, let's run the Ansible playbook again:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/run_script.yml

This time, the playbook should execute successfully:

PLAY [Run a script] ******************************************

TASK [Gathering Facts] ***************************************
ok: [localhost]

TASK [Execute the hello script] *****************************
changed: [localhost]

PLAY RECAP *************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Viewing the Script Output

Let's check the output of our script. Ansible captures the script's output and includes it in the task results. To see the detailed output, let's modify our playbook to register and display the output:

cd ~/project/ansible-lab/playbooks

Edit the run_script.yml file to include the register and debug tasks:

---
- name: Run a script
  hosts: local
  tasks:
    - name: Execute the hello script
      script: ../scripts/hello.sh
      register: script_output

    - name: Display script output
      debug:
        var: script_output.stdout_lines

Now let's run the playbook again:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/run_script.yml

You should see output like this:

PLAY [Run a script] ******************************************

TASK [Gathering Facts] ***************************************
ok: [localhost]

TASK [Execute the hello script] *****************************
changed: [localhost]

TASK [Display script output] ********************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "Hello from localhost!",
        "Current time: Wed Jun 10 12:34:56 UTC 2023",
        "Current user: labex"
    ]
}

PLAY RECAP *************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Now you can see the full output of our script. The script ran as the labex user, which is our current user.

By adding execute permissions with chmod +x, we've successfully fixed the "Permission denied" error and can now run our script through Ansible.

Using Become for Privilege Escalation

Sometimes, you need to run scripts with elevated privileges, such as running commands that require root access. In these cases, simply adding execute permissions to the script might not be enough. Ansible provides the become directive to run tasks with privilege escalation.

Understanding the Become Directive

The become directive in Ansible allows you to execute tasks as a different user, typically with elevated privileges. This is similar to using sudo in the command line.

Key options for the become directive include:

  • become: yes: Enables privilege escalation
  • become_user: <username>: Specifies which user to become (default is root)
  • become_method: <method>: Specifies how to become the user (default is sudo)

Creating a Script That Requires Root Privileges

Let's create a script that requires root privileges to execute successfully:

cd ~/project/ansible-lab/scripts
touch system_info.sh

Add the following content to the system_info.sh file:

#!/bin/bash
echo "System information - requires root privileges"
echo "Hostname: $(hostname)"
echo "Kernel version: $(uname -r)"
echo "Available disk space:"
df -h /
echo "User executing the script: $(whoami)"

Make the script executable:

chmod +x ~/project/ansible-lab/scripts/system_info.sh

Creating a Playbook with Become

Now, let's create a playbook that uses the become directive:

cd ~/project/ansible-lab/playbooks
touch root_script.yml

Add the following content to the root_script.yml file:

---
- name: Run a script as root
  hosts: local
  tasks:
    - name: Execute the system info script
      script: ../scripts/system_info.sh
      become: yes
      register: script_output

    - name: Display script output
      debug:
        var: script_output.stdout_lines

The become: yes directive tells Ansible to run the script with elevated privileges.

Running the Playbook with Become

Let's run our new playbook:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/root_script.yml

The playbook should execute successfully, and you should see output similar to this:

PLAY [Run a script as root] *********************************

TASK [Gathering Facts] **************************************
ok: [localhost]

TASK [Execute the system info script] **********************
changed: [localhost]

TASK [Display script output] *******************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "System information - requires root privileges",
        "Hostname: localhost",
        "Kernel version: 5.15.0-1015-aws",
        "Available disk space:",
        "Filesystem      Size  Used Avail Use% Mounted on",
        "/dev/root        59G   17G   42G  29% /",
        "User executing the script: root"
    ]
}

PLAY RECAP ************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Notice that in the script output, the "User executing the script" is now root, not labex. This shows that our script ran with elevated privileges due to the become: yes directive.

Understanding When to Use Become

You should use the become directive in the following situations:

  1. When the script needs to access system files or directories that require root privileges
  2. When the script needs to install packages or modify system configurations
  3. When the script needs to run commands that would normally require sudo in the command line

By using the become directive appropriately, you can ensure that your scripts have the necessary permissions to execute successfully, avoiding permission denied errors.

Best Practices for Avoiding Permission Issues

Now that we understand how to fix permission issues using chmod and become, let's explore some best practices to prevent permission issues from occurring in the first place.

1. Always Make Scripts Executable Before Using Them

Before using a script in Ansible, always ensure it has the execute permission:

chmod +x path/to/script.sh

It is good practice to do this as part of your script creation process.

2. Use Version Control with Proper File Modes

If you're using Git or another version control system, make sure it preserves file modes (permissions). In Git, you can configure this with:

git config core.fileMode true

For existing repositories, you might need to update the file modes:

git update-index --chmod=+x path/to/script.sh

3. Create a Script to Check and Fix Permissions

Let's create a utility script that checks and fixes permissions for all scripts in our project:

cd ~/project/ansible-lab
touch fix_permissions.sh

Add the following content to the fix_permissions.sh file:

#!/bin/bash
echo "Fixing permissions for scripts in ansible-lab"

## Find all .sh files and make them executable
find ~/project/ansible-lab -name "*.sh" -type f -exec chmod +x {} \;

echo "Done. All script files now have execute permissions."

Make the script executable:

chmod +x ~/project/ansible-lab/fix_permissions.sh

Run the script to ensure all scripts in your project have execute permissions:

./fix_permissions.sh

4. Use Ansible's File Module to Set Permissions

You can also use Ansible's file module to ensure script files have the correct permissions. Let's create a playbook that does this:

cd ~/project/ansible-lab/playbooks
touch set_permissions.yml

Add the following content to the set_permissions.yml file:

---
- name: Set correct permissions for scripts
  hosts: local
  tasks:
    - name: Find all script files
      find:
        paths: /home/labex/project/ansible-lab
        patterns: "*.sh"
        recurse: yes
      register: script_files

    - name: Make script files executable
      file:
        path: "{{ item.path }}"
        mode: "0755"
      loop: "{{ script_files.files }}"

Run this playbook to ensure all scripts have the correct permissions:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/set_permissions.yml

5. Create a Pre-flight Check Playbook

Finally, let's create a pre-flight check playbook that runs before your main playbooks to verify everything is set up correctly:

cd ~/project/ansible-lab/playbooks
touch preflight_check.yml

Add the following content to the preflight_check.yml file:

---
- name: Pre-flight checks
  hosts: local
  tasks:
    - name: Check if scripts are executable
      find:
        paths: /home/labex/project/ansible-lab
        patterns: "*.sh"
        recurse: yes
      register: script_files

    - name: Verify script permissions
      stat:
        path: "{{ item.path }}"
      register: stat_results
      loop: "{{ script_files.files }}"
      failed_when: not stat_results.stat.executable
      ignore_errors: yes

This playbook checks if all .sh files are executable and reports any that are not.

Let's run the pre-flight check:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/preflight_check.yml

If all your scripts have the correct permissions, the playbook should complete without errors. If any scripts are missing execute permissions, you'll see a notification.

By following these best practices, you can avoid permission denied errors in your Ansible scripts and ensure that your automation runs smoothly.

Summary

In this lab, you have learned how to identify and resolve 'Permission denied' errors when using the Ansible script module.

Key takeaways from this lab include:

  1. Understanding the importance of file permissions in Linux and how they affect script execution in Ansible
  2. Using the chmod command to add execute permissions to script files
  3. Utilizing Ansible's become directive for privilege escalation when running scripts that require root access
  4. Implementing best practices to prevent permission issues, including:
    • Making scripts executable before using them
    • Maintaining proper file modes in version control
    • Creating utility scripts to check and fix permissions
    • Using Ansible's file module to set permissions
    • Implementing pre-flight checks to verify your environment

By applying these techniques, you can ensure that your Ansible scripts run smoothly without permission errors, enhancing the reliability of your automation workflows.

The skills you've learned in this lab are fundamental to working effectively with Ansible and can be applied to a wide range of automation scenarios.