Custom Rules 101: Preventing sensitive information leakage in your Ansible Playbooks
Tags: customrules, security, ansibleplaybooks, ansible
Published: 2023-10-26 15:00:00

As automation takes center stage in modern IT environments, the security of automation scripts, especially Ansible Playbooks, cannot be overstated. One interesting security vulnerability in automation is keeping it compliant with company policies. This blog post will explore how to use [Steampunk Spotter](https://steampunk.si/spotter/)’s custom rules to prevent personally identifiable information leakage vulnerability in Ansible Playbooks. In our use case, we will demonstrate this for full name leakage prevention and be one step closer to GDPR like compliances.

## The Security Risk of Leaking Sensitive Information
In the realm of cybersecurity, safeguarding sensitive information is paramount, especially when it comes to financial institutions like banks. When automating with Ansible, high-quality Ansible Playbooks are essential for efficiency and ensuring that no personal information is inadvertently exposed. Companies can reduce the risk of data leaks by meticulously crafting and maintaining these playbooks and bolstering their security measures. In an age where data breaches are a constant threat, investing in top-notch automation becomes a cornerstone in fortifying various institutions' security infrastructure.

## Why Use Code Analysis Tools like Spotter
Code analysis tools such as Spotter go beyond basic linting to offer valuable insights into the quality of your code. Spotter’s custom rules feature allows you to set specific conditions like specifying allowed modules and collections and limiting required values on specific modules and entities, such as exposed ports and virtual machine sizes. You can also have custom security rules to achieve absolute compliance with internal and external regulations.

### System Requirements and Dependencies
Before you start implementing custom rules in Spotter, make sure you have the following:

* Ansible 2.x or above
* [Spotter CLI tool](https://pypi.org/project/steampunk-spotter/)
* A CI/CD pipeline ([GitLab](https://steampunk.si/blog/spotter-in-gitlab/), [Github Actions](https://steampunk.si/blog/spotter-github-actions/)) where Spotter can be integrated (optional but recommended)

## Step-by-Step Guide to Creating Custom Rules
We will use the example of checking our playbooks if they contain any full names to demonstrate how to use Spotter’s custom rules to prevent sensitive data leaks and decrease security vulnerabilities.

The [Ansible ‘no_log’](https://docs.ansible.com/ansible/latest/reference_appendices/logging.html) parameter, a powerful security feature, will help us protect sensitive data by preventing it from being logged when you save Ansible output to a log file. This is essential for safeguarding confidential information like full names, passwords, and usernames.

Did we set the parameter correctly? Let’s check!

Our starting playbook:

```
--- 

- hosts: all 
  connection: local 
  gather_facts: false 

  tasks: 
    - name: Ensure user Bob is present 
      ansible.windows.win_user: 
        name: MSbob 
        fullname: Bob Something 
        password: "{{ bob_password }}" 
        password_expired: false 
        password_never_expires: true 
        state: present 
        groups:  
          - Users 
      no_log: false 
```

### Step 1: Installing the Spotter CLI Tool
Install the Spotter CLI tool as a Python package using pip to get started.

```
pip install steampunk-spotter  
```

### Step 2: Upload Custom Rules
Spotter supports rules/policies written in accordance with the Open Policy Agent (OPA) engine.

Use the command `spotter set-policies <policies>`. You can upload a single file or a folder with multiple policies.

### Step 3: Defining Your Custom Rule
Example of a Rego file that defines a custom rule to ensure no_log parameter is correctly set to true:

```
package Play 

SpotterPolicy[result] { 
    task := input.tasks[i] 
    task_args := task.task_args 
    task_args[key] 
    task_args[key][sub_key] 
    regex.match("^fullname$", sub_key)

    task_args.no_log = false 
    
    
    result := { 
        "correlation_id": task.task_id, 
        "check_type": "TASK", 
        "subcode": "NoLogFullName", 
        "message": "When using a parameter fullname, ensure that the Ansible task is run with parameter no-log.", 
        "abc": sub_key, 
    } 
} 

SpotterPolicy[result] { 
    task := input.tasks[i] 
    task_args := task.task_args 
    task_args[key][sub_key] 
    regex.match("^fullname$", sub_key) 
    not task_args.no_log 

    result := { 
        "correlation_id": task.task_id, 
        "check_type": "TASK", 
        "subcode": "NoLogFullName", 
        "message": "When using a parameter fullname, ensure that the Ansible task is run with parameter no-log.", 
        "abc": sub_key, 
    } 
} 
```

### Step 4: Scan Results
Once you’ve defined the rule, Spotter will scan your playbooks and alert you if there is any sensitive data according to your custom-written rule, in this case - to prevent showing full names.

This is what Spotter found while scanning our playbook:

```
 > spotter set-policies custom_rule1.rego
    Custom policies successfully set.
     > spotter scan playbook.yml
    Scanning...success. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
    
    Check results:
    playbook.yml:7:7: ERROR: [E2300::NoLogFullName] When using a parameter fullname, ensure that the Ansible task is run with parameter no-log.
    
    Scan summary:
    Spotter took 1.355 s to scan your input.
    It resulted in 1 error(s), 0 warning(s) and 0 hint(s).
    Can rewrite 0 file(s) with 0 change(s).
    Overall status: ERROR
       > 
 ```  

As we can see, it alerted us that we were exposing a full name and that the parameter was not set correctly.

If we fix the playbook according to Spotter’s recommendation, we can see, the alert no longer appears:

```  
 > spotter scan playbook.yml
    Scanning...success. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
    
    Scan summary:
    Spotter took 1.323 s to scan your input.
    It resulted in 0 error(s), 0 warning(s) and 0 hint(s).
    Can rewrite 0 file(s) with 0 change(s).
    Overall status: SUCCESS
     > 
```   

Our finished playbook:
```
--- 
- hosts: all 
  connection: local 
  gather_facts: false 

  tasks: 
    - name: Ensure user Bob is present 
      ansible.windows.win_user: 
        name: MSbob 
        fullname: Bob Something 
        password: "{{ bob_password }}" 
        password_expired: false 
        password_never_expires: true 
        state: present 
        groups:  
          - Users 
      no_log: true 
```

## Best Practices
When implementing custom rules:

* Test the rule on a subset of your playbooks before applying it globally.

* Create one rule per task, do not add multiple checks in one single rule.

* Update Spotter regularly to make use of the latest security features and checks.

## Conclusion
Spotter’s custom rules feature provides a robust mechanism for enhancing the security of your Ansible Playbooks. Creating a custom rule to prevent leaking sensitive information can significantly reduce security risks and ensure compliance with industry regulations, especially in finance, healthcare, and government.

## Additional Resources
For more details on how to create and manage custom rules in Spotter, check out the following resources:

[Custom rules DEMO](https://www.youtube.com/watch?si=60dJa2tT3VzSGE-4&v=8bjzWXZC9_E&feature=youtu.be&ab_channel=XLABSteampunk)

[Custom rules blog post](https://steampunk.si/blog/spotter-custom-policies/)

[Other helpful articles](https://steampunk.si/blog/categories/Steampunk-Spotter/)