Merge master into fix/ansible-no-log-sensitive branch

Resolved conflicts by keeping both:
- Added spaces after commas in lookup('env', 'VAR') calls (from master)
- Kept no_log: true directives for sensitive tasks (from our branch)

This ensures proper code formatting while maintaining security improvements.
This commit is contained in:
Dan Guido 2025-08-17 13:24:40 -04:00
commit f516227e56
54 changed files with 336 additions and 145 deletions

View file

@ -28,7 +28,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 1
persist-credentials: false

View file

@ -27,7 +27,7 @@ jobs:
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 1
persist-credentials: false

View file

@ -18,7 +18,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false

View file

@ -26,7 +26,7 @@ jobs:
matrix:
vpn_type: ['wireguard', 'ipsec', 'both']
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
@ -210,7 +210,7 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false

View file

@ -11,7 +11,7 @@ jobs:
name: Ansible linting
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -42,7 +42,7 @@ jobs:
name: YAML linting
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
@ -56,7 +56,7 @@ jobs:
name: Python linting
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -75,7 +75,7 @@ jobs:
name: Shell script linting
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
@ -89,7 +89,7 @@ jobs:
name: PowerShell script linting
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false

View file

@ -18,7 +18,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -37,7 +37,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -59,7 +59,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -87,7 +87,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -113,7 +113,7 @@ jobs:
matrix:
provider: [local, ec2, digitalocean, gce]
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0

View file

@ -23,7 +23,7 @@ jobs:
run_lint: ${{ steps.filter.outputs.lint }}
run_integration: ${{ steps.filter.outputs.integration }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
@ -77,7 +77,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -98,7 +98,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -142,7 +142,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -171,7 +171,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
@ -223,7 +223,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0

View file

@ -17,7 +17,7 @@ jobs:
name: Analyze Test Effectiveness
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: true

1
.gitignore vendored
View file

@ -10,3 +10,4 @@ inventory_users
.ansible/
__pycache__/
*.pyc
algo.egg-info/

View file

@ -82,7 +82,7 @@ def main():
module.fail_json(msg='Python module "botocore" is missing, please install it')
try:
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module)
client = None
try:

View file

@ -8,7 +8,7 @@ description = "Set up a personal IPSEC VPN in the cloud"
version = "2.0.0-beta"
requires-python = ">=3.11"
dependencies = [
"ansible==11.8.0",
"ansible==11.9.0",
"jinja2>=3.1.6",
"netaddr==1.3.0",
"pyyaml>=6.0.2",

View file

@ -161,5 +161,31 @@
include_tasks: aip/main.yml
when: alternative_ingress_ip
- name: Ubuntu 22.04+ | Use iptables-legacy for compatibility
block:
- name: Install iptables packages
apt:
name:
- iptables
- iptables-persistent
state: present
update_cache: true
- name: Configure iptables-legacy as default
alternatives:
name: "{{ item }}"
path: "/usr/sbin/{{ item }}-legacy"
with_items:
- iptables
- ip6tables
- iptables-save
- iptables-restore
- ip6tables-save
- ip6tables-restore
when:
- ansible_distribution == "Ubuntu"
- ansible_distribution_version is version('22.04', '>=')
tags: iptables
- include_tasks: iptables.yml
tags: iptables

View file

@ -2,6 +2,13 @@
- name: Set OS specific facts
set_fact:
strongswan_additional_plugins: []
- name: Ubuntu | Ensure af_key kernel module is loaded
modprobe:
name: af_key
state: present
persistent: present
- name: Ubuntu | Install strongSwan (individual)
apt:
name: strongswan

View file

@ -0,0 +1,157 @@
#!/usr/bin/env python
"""
Test for AWS Lightsail boto3 parameter fix.
Verifies that get_aws_connection_info() works without the deprecated boto3 parameter.
Addresses issue #14822.
"""
import importlib.util
import os
import sys
import unittest
from unittest.mock import MagicMock, patch
# Add the library directory to the path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../library'))
class TestLightsailBoto3Fix(unittest.TestCase):
"""Test that lightsail_region_facts.py works without boto3 parameter."""
def setUp(self):
"""Set up test fixtures."""
# Mock the ansible module_utils since we're testing outside of Ansible
self.mock_modules = {
'ansible.module_utils.basic': MagicMock(),
'ansible.module_utils.ec2': MagicMock(),
'ansible.module_utils.aws.core': MagicMock(),
}
# Apply mocks
self.patches = []
for module_name, mock_module in self.mock_modules.items():
patcher = patch.dict('sys.modules', {module_name: mock_module})
patcher.start()
self.patches.append(patcher)
def tearDown(self):
"""Clean up patches."""
for patcher in self.patches:
patcher.stop()
def test_lightsail_region_facts_imports(self):
"""Test that lightsail_region_facts can be imported."""
try:
# Import the module
spec = importlib.util.spec_from_file_location(
"lightsail_region_facts",
os.path.join(os.path.dirname(__file__), '../../library/lightsail_region_facts.py')
)
module = importlib.util.module_from_spec(spec)
# This should not raise an error
spec.loader.exec_module(module)
# Verify the module loaded
self.assertIsNotNone(module)
self.assertTrue(hasattr(module, 'main'))
except Exception as e:
self.fail(f"Failed to import lightsail_region_facts: {e}")
def test_get_aws_connection_info_called_without_boto3(self):
"""Test that get_aws_connection_info is called without boto3 parameter."""
# Mock get_aws_connection_info to track calls
mock_get_aws_connection_info = MagicMock(
return_value=('us-west-2', None, {})
)
with patch('ansible.module_utils.ec2.get_aws_connection_info', mock_get_aws_connection_info):
# Import the module
spec = importlib.util.spec_from_file_location(
"lightsail_region_facts",
os.path.join(os.path.dirname(__file__), '../../library/lightsail_region_facts.py')
)
module = importlib.util.module_from_spec(spec)
# Mock AnsibleModule
mock_ansible_module = MagicMock()
mock_ansible_module.params = {}
mock_ansible_module.check_mode = False
with patch('ansible.module_utils.basic.AnsibleModule', return_value=mock_ansible_module):
# Execute the module
try:
spec.loader.exec_module(module)
module.main()
except SystemExit:
# Module calls exit_json or fail_json which raises SystemExit
pass
except Exception:
# We expect some exceptions since we're mocking, but we want to check the call
pass
# Verify get_aws_connection_info was called
if mock_get_aws_connection_info.called:
# Get the call arguments
call_args = mock_get_aws_connection_info.call_args
# Ensure boto3=True is NOT in the arguments
if call_args:
# Check positional arguments
if call_args[0]: # args
self.assertTrue(len(call_args[0]) <= 1,
"get_aws_connection_info should be called with at most 1 positional arg (module)")
# Check keyword arguments
if call_args[1]: # kwargs
self.assertNotIn('boto3', call_args[1],
"get_aws_connection_info should not be called with boto3 parameter")
def test_no_boto3_parameter_in_source(self):
"""Verify that boto3 parameter is not present in the source code."""
lightsail_path = os.path.join(os.path.dirname(__file__), '../../library/lightsail_region_facts.py')
with open(lightsail_path) as f:
content = f.read()
# Check that boto3=True is not in the file
self.assertNotIn('boto3=True', content,
"boto3=True parameter should not be present in lightsail_region_facts.py")
# Check that boto3 parameter is not used with get_aws_connection_info
self.assertNotIn('get_aws_connection_info(module, boto3', content,
"get_aws_connection_info should not be called with boto3 parameter")
def test_regression_issue_14822(self):
"""
Regression test for issue #14822.
Ensures that the deprecated boto3 parameter is not used.
"""
# This test documents the specific issue that was fixed
# The boto3 parameter was deprecated and removed in amazon.aws collection
# that comes with Ansible 11.x
lightsail_path = os.path.join(os.path.dirname(__file__), '../../library/lightsail_region_facts.py')
with open(lightsail_path) as f:
lines = f.readlines()
# Find the line that calls get_aws_connection_info
for line_num, line in enumerate(lines, 1):
if 'get_aws_connection_info' in line and 'region' in line:
# This should be around line 85
# Verify it doesn't have boto3=True
self.assertNotIn('boto3', line,
f"Line {line_num} should not contain boto3 parameter")
# Verify the correct format
self.assertIn('get_aws_connection_info(module)', line,
f"Line {line_num} should call get_aws_connection_info(module) without boto3")
break
else:
self.fail("Could not find get_aws_connection_info call in lightsail_region_facts.py")
if __name__ == '__main__':
unittest.main()

14
uv.lock generated
View file

@ -68,7 +68,7 @@ dev = [
[package.metadata]
requires-dist = [
{ name = "ansible", specifier = "==11.8.0" },
{ name = "ansible", specifier = "==11.9.0" },
{ name = "azure-identity", marker = "extra == 'azure'", specifier = ">=1.15.0" },
{ name = "azure-mgmt-compute", marker = "extra == 'azure'", specifier = ">=30.0.0" },
{ name = "azure-mgmt-network", marker = "extra == 'azure'", specifier = ">=25.0.0" },
@ -99,19 +99,19 @@ dev = [
[[package]]
name = "ansible"
version = "11.8.0"
version = "11.9.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "ansible-core" },
]
sdist = { url = "https://files.pythonhosted.org/packages/82/74/b86d14d2c458edf27ddb56d42bf6d07335a0ccfc713f040fb0cbffd30017/ansible-11.8.0.tar.gz", hash = "sha256:28ea032c77f344bb8ea4d7d39f9a5d4e935e6c8b60836c8c8a28b9cf6c9adb1a", size = 44286995, upload-time = "2025-07-16T15:13:22.91Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e8/b3/01564da36375f35907c2ec6626d68f4d59e39e566c4b3f874f01d0d2ca19/ansible-11.9.0.tar.gz", hash = "sha256:528ca5a408f11cf1fea00daea7570e68d40e167be38b90c119a7cb45729e4921", size = 44589149, upload-time = "2025-08-12T16:03:31.912Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/47/47/23fe9f6d9cd533ce4d54f4925cb0b7fdcfd3500b226421aad6166d9aa11c/ansible-11.8.0-py3-none-any.whl", hash = "sha256:a2cd44c0d2c03972f5d676d1b024d09dd3d3edbd418fb0426f4dd356fca9e5b1", size = 56046023, upload-time = "2025-07-16T15:13:17.557Z" },
{ url = "https://files.pythonhosted.org/packages/84/fd/093dfe1f7f9f1058c0efa10b685f6049b676aa2c0ecd6f99c8664cafad6a/ansible-11.9.0-py3-none-any.whl", hash = "sha256:79b087ef38105b93e0e092e7013a0f840e154a6a8ce9b5fddd1b47593adc542a", size = 56340779, upload-time = "2025-08-12T16:03:26.18Z" },
]
[[package]]
name = "ansible-core"
version = "2.18.7"
version = "2.18.8"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cryptography" },
@ -120,9 +120,9 @@ dependencies = [
{ name = "pyyaml" },
{ name = "resolvelib" },
]
sdist = { url = "https://files.pythonhosted.org/packages/29/33/cd25e1af669941fbb5c3d7ac4494cf4a288cb11f53225648d552f8bd8e54/ansible_core-2.18.7.tar.gz", hash = "sha256:1a129bf9fcd5dca2b17e83ce77147ee2fbc3c51a4958970152897cc5b6d0aae7", size = 3090256, upload-time = "2025-07-15T17:49:24.074Z" }
sdist = { url = "https://files.pythonhosted.org/packages/9b/78/8b8680eaf7b1990a8d4c26f25cdf2b2eabaae764a3d8e5299b1d61c7c385/ansible_core-2.18.8.tar.gz", hash = "sha256:b0766215a96a47ce39933d27e1e996ca2beb54cf1b3907c742d35c913b1f78cd", size = 3088636, upload-time = "2025-08-11T19:03:12.495Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7e/a7/568e51c20f49c9e76a555a876ed641ecc59df29e93868f24cdf8c3289f6a/ansible_core-2.18.7-py3-none-any.whl", hash = "sha256:ac42ecb480fb98890d338072f7298cd462fb2117da6700d989c7ae688962ba69", size = 2209456, upload-time = "2025-07-15T17:49:22.549Z" },
{ url = "https://files.pythonhosted.org/packages/a8/59/aa2c1918224b054c9a0d93812c0b446fa8ddba155dc96c855189fae9c82b/ansible_core-2.18.8-py3-none-any.whl", hash = "sha256:b60bc23b2f11fd0559a79d10ac152b52f58a18ca1b7be0a620dfe87f34ced689", size = 2218673, upload-time = "2025-08-11T19:03:04.75Z" },
]
[[package]]