92 lines
2.7 KiB
Python
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())
|