Skip to content

Commit

Permalink
Merge pull request ComplianceAsCode#12014 from mildas/ansible_shell_diff
Browse files Browse the repository at this point in the history
Github Action Ansible `shell` module changes check
  • Loading branch information
matusmarhefka authored May 29, 2024
2 parents 3d569bc + 78f77a5 commit 731dde4
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/compare-ds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,35 @@ jobs:
type: delete
comment_id: ${{ steps.fc.outputs.comment-id }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Compare Ansible playbook shell commands
if: ${{ steps.ctf.outputs.CTF_OUTPUT_SIZE != '0' }}
run: utils/ansible_shell_diff.py ssg-${{steps.product.outputs.prop}}-ds.xml build/ssg-${{steps.product.outputs.prop}}-ds.xml | tee diff.log
env:
PYTHONPATH: ${{ github.workspace }}
- name: Test if there are Ansible shell module changes
if: ${{ steps.ctf.outputs.CTF_OUTPUT_SIZE != '0' }}
run: echo "SHELL_DIFF_OUTPUT_SIZE=$(stat --printf="%s" diff.log)" >> $GITHUB_OUTPUT
id: ansible_shell_diff
- name: Find Comment
uses: peter-evans/find-comment@v3
id: shell_diff
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: Change in Ansible 'shell' module found.
- name: Create comment
if: ${{ steps.ansible_shell_diff.outputs.SHELL_DIFF_OUTPUT_SIZE != '0' && steps.shell_diff.outputs.comment-id == 0 }}
uses: peter-evans/create-or-update-comment@v4
with:
issue-number: ${{ github.event.pull_request.number }}
body: |
Change in Ansible `shell` module found.
Please consider using more suitable Ansible module than `shell` if possible.
- name: Delete existing comment in case new commits trigger no changes in Ansible shell module
if: ${{ (steps.ansible_shell_diff.outputs.SHELL_DIFF_OUTPUT_SIZE == '0' || steps.ctf.outputs.CTF_OUTPUT_SIZE == '0') && steps.shell_diff.outputs.comment-id != 0 }}
uses: jungwinter/comment@v1
with:
type: delete
comment_id: ${{ steps.shell_diff.outputs.comment-id }}
token: ${{ secrets.GITHUB_TOKEN }}
61 changes: 61 additions & 0 deletions utils/ansible_shell_diff.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/python3

import yaml
import argparse
import subprocess
from pathlib import Path


def parse_args():
parser = argparse.ArgumentParser(
description="Check for changes in 'shell' module usage in two datastreams"
)
parser.add_argument('old', metavar='OLD_DS_PATH', help="Path to old datastream")
parser.add_argument('new', metavar='NEW_DS_PATH', help="Path to new datastream")
return parser.parse_args()


def get_shell_tasks(tasks):
"""
Find all shell/command module tasks.
Module can be as FQCN or just short name.
Both forms, free form and 'cmd:' parameter, are supported.
"""
shell_tasks = []
for task in tasks:
for task_name in ['shell', 'ansible.builtin.shell', 'command', 'ansible.builtin.command']:
if task_name in task:
if type(task[task_name]) is dict and 'cmd' in task[task_name]:
shell_tasks.append(task[task_name]['cmd'])
else:
shell_tasks.append(task[task_name])
# Search also blocks
if 'block' in task:
tasks = get_shell_tasks(task['block'])
if tasks:
shell_tasks.extend(tasks)
return shell_tasks


if __name__ == '__main__':
args = parse_args()
# Generate old and new playbooks for all rules in datastream
cmd = ['oscap', 'xccdf', 'generate', 'fix', '--profile', '(all)', '--fix-type', 'ansible']
subprocess.run(cmd + ['--output', 'old.yml', args.old], check=True)
subprocess.run(cmd + ['--output', 'new.yml', args.new], check=True)

with open('old.yml', 'r') as old_yaml, open('new.yml', 'r') as new_yaml:
old_playbook = yaml.safe_load(old_yaml)
new_playbook = yaml.safe_load(new_yaml)
# Get only shell commands
old_shell_modules = get_shell_tasks(old_playbook[0]['tasks'])
new_shell_modules = get_shell_tasks(new_playbook[0]['tasks'])

diff = set(new_shell_modules) - set(old_shell_modules)
if diff:
print(f"Changes in Ansible shell module have been found:")
print("\n".join(diff))

Path.unlink('old.yml')
Path.unlink('new.yml')
exit(0)

0 comments on commit 731dde4

Please sign in to comment.