105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
# Copyright The IETF Trust 2024, All Rights Reserved
|
|
#
|
|
# Uses only Python standard lib
|
|
#
|
|
|
|
import argparse
|
|
import datetime
|
|
import json
|
|
import shutil
|
|
import stat
|
|
import sys
|
|
|
|
from pathlib import Path
|
|
from tempfile import TemporaryDirectory
|
|
|
|
# Default options
|
|
POSTCONFIRM_PATH = "/a/postconfirm/wrapper"
|
|
VDOMAIN = "virtual.ietf.org"
|
|
|
|
# Map from domain label to dns domain
|
|
ADOMAINS = {
|
|
"ietf": "ietf.org",
|
|
"irtf": "irtf.org",
|
|
"iab": "iab.org",
|
|
}
|
|
|
|
|
|
def generate_files(records, adest, vdest, postconfirm, vdomain):
|
|
"""Generate files from an iterable of records
|
|
|
|
If adest or vdest exists as a file, it will be overwritten. If it is a directory, files
|
|
with the default names (draft-aliases and draft-virtual) will be created, but existing
|
|
files _will not_ be overwritten!
|
|
"""
|
|
with TemporaryDirectory() as tmpdir:
|
|
tmppath = Path(tmpdir)
|
|
apath = tmppath / "aliases"
|
|
vpath = tmppath / "virtual"
|
|
|
|
with apath.open("w") as afile, vpath.open("w") as vfile:
|
|
date = datetime.datetime.now(datetime.timezone.utc)
|
|
signature = f"# Generated by {Path(__file__).absolute()} at {date}\n"
|
|
afile.write(signature)
|
|
vfile.write(signature)
|
|
vfile.write(f"{vdomain} anything\n")
|
|
|
|
for item in records:
|
|
alias = item["alias"]
|
|
domains = item["domains"]
|
|
address_list = item["addresses"]
|
|
filtername = f"xfilter-{alias}"
|
|
afile.write(f'{filtername + ":":64s} "|{postconfirm} filter expand-{alias} {vdomain}"\n')
|
|
for dom in domains:
|
|
vfile.write(f"{f'{alias}@{ADOMAINS[dom]}':64s} {filtername}\n")
|
|
vfile.write(f"{f'expand-{alias}@{vdomain}':64s} {', '.join(sorted(address_list))}\n")
|
|
|
|
perms = stat.S_IWUSR | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH
|
|
apath.chmod(perms)
|
|
vpath.chmod(perms)
|
|
shutil.move(apath, adest)
|
|
shutil.move(vpath, vdest)
|
|
|
|
|
|
def directory_path(val):
|
|
p = Path(val)
|
|
if p.is_dir():
|
|
return p
|
|
else:
|
|
raise argparse.ArgumentTypeError(f"{p} is not a directory")
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(
|
|
description="Convert a JSON stream of draft alias definitions into alias / virtual alias files."
|
|
)
|
|
parser.add_argument(
|
|
"--prefix",
|
|
required=True,
|
|
help="Prefix for output files. Files will be named <prefix>-aliases and <prefix>-virtual."
|
|
)
|
|
parser.add_argument(
|
|
"--output-dir",
|
|
default="./",
|
|
type=directory_path,
|
|
help="Destination for output files.",
|
|
)
|
|
parser.add_argument(
|
|
"--postconfirm",
|
|
default=POSTCONFIRM_PATH,
|
|
help=f"Full path to postconfirm executable (defaults to {POSTCONFIRM_PATH}",
|
|
)
|
|
parser.add_argument(
|
|
"--vdomain",
|
|
default=VDOMAIN,
|
|
help=f"Virtual domain (defaults to {VDOMAIN}_",
|
|
)
|
|
args = parser.parse_args()
|
|
data = json.load(sys.stdin)
|
|
generate_files(
|
|
data["aliases"],
|
|
adest=args.output_dir / f"{args.prefix}-aliases",
|
|
vdest=args.output_dir / f"{args.prefix}-virtual",
|
|
postconfirm=args.postconfirm,
|
|
vdomain=args.vdomain,
|
|
)
|