|
#!/usr/bin/env python |
|
# Copyright (C) 2017 Luca Filipozz <luca.filipozzi@gmail.com> |
|
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. |
|
# |
|
# use this deployment script with acmetool |
|
|
|
import addict |
|
import click |
|
import f5.bigip |
|
import f5.bigip.contexts |
|
import requests |
|
import yaml |
|
|
|
def do_common(cfg, cn): |
|
cfg.ssl.name = cfg.formats.ssl.name.format(cn) |
|
cfg.ssl.defaultsFrom = cfg.formats.ssl.defaultsFrom.format(cn) |
|
cfg.ssl.partition = cfg.formats.ssl.partition.format(cn) |
|
cfg.ssl.exists = cfg.mr.tm.ltm.profile.client_ssls.client_ssl.exists(partition=cfg.ssl.partition, name=cfg.ssl.name) |
|
cfg.key.name = cfg.formats.key.name.format(cn) |
|
cfg.key.path = cfg.formats.key.path.format(cn) |
|
cfg.key.exists = cfg.mr.tm.sys.file.ssl_keys.ssl_key.exists(name=cfg.key.name) |
|
cfg.crt.name = cfg.formats.crt.name.format(cn) |
|
cfg.crt.path = cfg.formats.crt.path.format(cn) |
|
cfg.crt.exists = cfg.mr.tm.sys.file.ssl_certs.ssl_cert.exists(name=cfg.crt.name) |
|
cfg.chn.name = cfg.formats.chn.name.format(cn) |
|
cfg.chn.path = cfg.formats.chn.path.format(cn) |
|
cfg.chn.exists = cfg.mr.tm.sys.file.ssl_certs.ssl_cert.exists(name=cfg.chn.name) |
|
cfg.tx = cfg.mr.tm.transactions.transaction |
|
|
|
def do_deploy(cfg): |
|
with f5.bigip.contexts.TransactionContextManager(cfg.tx) as api: |
|
if cfg.key.exists: |
|
api.tm.sys.file.ssl_keys.ssl_key.load(name=cfg.key.name).update() |
|
else: |
|
api.tm.sys.file.ssl_keys.ssl_key.create(name=cfg.key.name, sourcePath=cfg.key.path) |
|
if cfg.crt.exists: |
|
api.tm.sys.file.ssl_certs.ssl_cert.load(name=cfg.crt.name).update() |
|
else: |
|
api.tm.sys.file.ssl_certs.ssl_cert.create(name=cfg.crt.name, sourcePath=cfg.crt.path) |
|
if cfg.chn.exists: |
|
api.tm.sys.file.ssl_certs.ssl_cert.load(name=cfg.chn.name).update() |
|
else: |
|
api.tm.sys.file.ssl_certs.ssl_cert.create(name=cfg.chn.name, sourcePath=cfg.chn.path) |
|
if not cfg.ssl.exists: |
|
cfg.mr.tm.ltm.profile.client_ssls.client_ssl.create(partition=cfg.ssl.partition, name=cfg.ssl.name, |
|
key=cfg.key.name, cert=cfg.crt.name, chain=cfg.chn.name, defaultsFrom=cfg.ssl.defaultsFrom) |
|
|
|
def do_remove(cfg): |
|
if not cfg.ssl.exists and not cfg.key.exists and not cfg.crt.exists and not cfg.chn.exists: |
|
return |
|
with f5.bigip.contexts.TransactionContextManager(cfg.tx) as api: |
|
if cfg.ssl.exists: |
|
cfg.mr.tm.ltm.profile.client_ssls.client_ssl.load(partition=cfg.ssl.partition, name=cfg.ssl.name).delete() |
|
if cfg.key.exists: |
|
api.tm.sys.file.ssl_keys.ssl_key.load(name=cfg.key.name).delete() |
|
if cfg.crt.exists: |
|
api.tm.sys.file.ssl_certs.ssl_cert.load(name=cfg.crt.name).delete() |
|
if cfg.chn.exists: |
|
api.tm.sys.file.ssl_certs.ssl_cert.load(name=cfg.chn.name).delete() |
|
|
|
@click.group() |
|
@click.option('--insecure', is_flag=True, |
|
help='Disable insecure request warning.') |
|
@click.option('--cfgfile', metavar='<CFGFILE>', type=click.File(), |
|
help='Specify configuration file.', default='config.yaml') |
|
@click.pass_context |
|
def cli(ctx, insecure, cfgfile): |
|
""" hook script to deploy x509 certificates onto an F5 BIG-IP """ |
|
if insecure: |
|
warning = requests.packages.urllib3.exceptions.InsecureRequestWarning |
|
requests.packages.urllib3.disable_warnings(warning) |
|
ctx.obj = addict.Dict(yaml.load(cfgfile)) |
|
|
|
@cli.command(name='live-updated') |
|
@click.argument('cns', metavar='<CN [CN] [CN]>', nargs=-1) |
|
@click.pass_obj |
|
def live_updated(cfg, cns): |
|
""" deploy multiple x509 certificates """ |
|
cfg.mr = f5.bigip.ManagementRoot(cfg.f5lb.hostname, cfg.f5lb.username, cfg.f5lb.password) |
|
for cn in cns: |
|
do_common(cfg, cn) |
|
do_deploy(cfg) |
|
|
|
@cli.command() |
|
@click.argument('cn', metavar='<CN>', nargs=1) |
|
@click.pass_obj |
|
def deploy(cfg, cn): |
|
""" deploy a single x509 certificate """ |
|
cfg.mr = f5.bigip.ManagementRoot(cfg.f5lb.hostname, cfg.f5lb.username, cfg.f5lb.password) |
|
do_common(cfg, cn) |
|
do_deploy(cfg) |
|
|
|
@cli.command() |
|
@click.argument('cn', metavar='<CN>', nargs=1) |
|
@click.pass_obj |
|
def remove(cfg, cn): |
|
""" remove a single x509 certificate """ |
|
cfg.mr = f5.bigip.ManagementRoot(cfg.f5lb.hostname, cfg.f5lb.username, cfg.f5lb.password) |
|
do_common(cfg, cn) |
|
do_remove(cfg) |
|
|
|
if __name__ == '__main__': |
|
cli(obj=None) |