Files
ansible-testing/methodologies/ansible/scripts/build-secrets.py
T

92 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Assemble individual GitLab CI/CD variables into a temporary Ansible vars file.
Reads a fixed allowlist of environment variables (injected by GitLab from
masked CI/CD variables), maps them to their Ansible names, and writes them to a
YAML vars file for ``--extra-vars @<file>``. An optional private key is written
to a separate 0600 file for ``--private-key``.
Values never appear on the process command line or in this script's output.
Only the allowlisted variable names are consumed; everything else is ignored.
"""
import argparse
import os
import stat
from pathlib import Path
import yaml
# GitLab variable name -> Ansible variable name. Extend this mapping when a new
# connection variable needs to be supplied per environment.
VAR_MAP = {
"ANSIBLE_USER": "ansible_user",
"ANSIBLE_PASSWORD": "ansible_password",
"ANSIBLE_BECOME_PASSWORD": "ansible_become_password",
"VCENTER_HOSTNAME": "vcenter_hostname",
"VCENTER_USERNAME": "vcenter_username",
"VCENTER_PASSWORD": "vcenter_password",
}
PRIVATE_KEY_ENV = "ANSIBLE_PRIVATE_KEY"
VARS_FILENAME = "ansible-vars.yml"
KEY_FILENAME = "ansible-private-key"
def write_secret_file(path: Path, data: bytes) -> None:
path.write_bytes(data)
path.chmod(stat.S_IRUSR | stat.S_IWUSR)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"--out-dir",
type=Path,
required=True,
help="Directory for the generated vars file and private key",
)
args = parser.parse_args()
args.out_dir.mkdir(parents=True, exist_ok=True)
os.chmod(args.out_dir, stat.S_IRWXU)
variables = {
ansible_name: os.environ[gitlab_name]
for gitlab_name, ansible_name in VAR_MAP.items()
if os.environ.get(gitlab_name)
}
private_key = os.environ.get(PRIVATE_KEY_ENV)
if not variables and not private_key:
raise SystemExit(
"no Ansible secrets were provided. Define at least one of "
+ ", ".join(VAR_MAP)
+ f" or {PRIVATE_KEY_ENV} as an environment-scoped CI/CD variable."
)
vars_file = args.out_dir / VARS_FILENAME
write_secret_file(
vars_file,
yaml.safe_dump(variables, sort_keys=True, default_flow_style=False).encode(
"utf-8"
),
)
print(f"Wrote Ansible variables to {vars_file}")
if private_key:
key_data = (
Path(private_key).read_bytes()
if os.path.isfile(private_key)
else private_key.encode("utf-8")
)
key_file = args.out_dir / KEY_FILENAME
write_secret_file(key_file, key_data)
print(f"Wrote private key to {key_file}")
return 0
if __name__ == "__main__":
raise SystemExit(main())