|
|
|
@ -12,14 +12,15 @@ from subprocess import run |
|
|
|
|
|
|
|
|
|
import certbot_config as config |
|
|
|
|
|
|
|
|
|
# Resolve include directive (non-recursive) |
|
|
|
|
# Resolve 'include' directive (non-recursive) |
|
|
|
|
def resolve_include(response, directive): |
|
|
|
|
result = [] |
|
|
|
|
for index in directive['includes']: |
|
|
|
|
# Join parsed included file to result list |
|
|
|
|
result.extend(response['config'][index]['parsed']) |
|
|
|
|
return result |
|
|
|
|
|
|
|
|
|
# Resolve all include directives (recursive) |
|
|
|
|
# Resolve all 'include' directives (recursive) |
|
|
|
|
def resolve_includes(response, directives=None): |
|
|
|
|
# Assume resolve of first file in response if not specified |
|
|
|
|
if directives is None: |
|
|
|
@ -29,10 +30,12 @@ def resolve_includes(response, directives=None): |
|
|
|
|
result = [] |
|
|
|
|
for directive in directives: |
|
|
|
|
if 'includes' in directive: |
|
|
|
|
# Resolve include and recursively resolve includes in included file |
|
|
|
|
result.extend(resolve_includes(response, resolve_include(response, directive))) |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
if 'block' in directive: |
|
|
|
|
# Recursively traverse block statement |
|
|
|
|
directive['block'] = resolve_includes(response, directive['block']) |
|
|
|
|
|
|
|
|
|
result.append(directive) |
|
|
|
@ -45,18 +48,23 @@ def search_directives(directives, fn, recursive=False): |
|
|
|
|
|
|
|
|
|
for directive in directives: |
|
|
|
|
if fn(directive): |
|
|
|
|
# Append directive matched by search function to result list |
|
|
|
|
result.append(directive) |
|
|
|
|
elif recursive and 'block' in directive: |
|
|
|
|
# Recursively search block statement |
|
|
|
|
result.extend(search_directives(directive['block'], fn, True)) |
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
|
|
|
|
|
# Recursive search in directives, steered by matching functions |
|
|
|
|
def resolve_path(directives, fns): |
|
|
|
|
# Pick the first search function in the list and perform a flat search |
|
|
|
|
results = search_directives(directives, fns[0]) |
|
|
|
|
if len(results) > 0 and len(fns) > 1: |
|
|
|
|
# A match for the first path element was found, recurse subtree to find next match |
|
|
|
|
return resolve_path(results[0]['block'], fns[1:]) |
|
|
|
|
else: |
|
|
|
|
# No further matches were found |
|
|
|
|
return results |
|
|
|
|
|
|
|
|
|
# Get all HTTP server directives |
|
|
|
@ -70,24 +78,31 @@ def get_vhosts(directives): |
|
|
|
|
servers = get_servers(directives) |
|
|
|
|
vhosts = [] |
|
|
|
|
for server in servers: |
|
|
|
|
# Retrieve server name directive |
|
|
|
|
server_name = search_directives(server['block'], lambda d: ('directive', 'server_name') in d.items()) |
|
|
|
|
if len(server_name) == 0: |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
for name in server_name[0]['args']: |
|
|
|
|
# Apply server alias to vhosts list |
|
|
|
|
vhosts.append(name) |
|
|
|
|
|
|
|
|
|
return vhosts |
|
|
|
|
|
|
|
|
|
# Parse nginx.conf file with Crossplane |
|
|
|
|
response = crossplane.parse(config.nginx_config_file) |
|
|
|
|
if response['errors']: |
|
|
|
|
pprint.pprint(response['errors']) |
|
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
|
|
# Resolve all includes (combine into to one big config tree) |
|
|
|
|
directives = resolve_includes(response) |
|
|
|
|
|
|
|
|
|
# Retrieve all virtual hostnames |
|
|
|
|
vhosts = [ name for name in get_vhosts(directives) if not name in config.ignored_domains ] |
|
|
|
|
|
|
|
|
|
if config.primary_domain in vhosts: |
|
|
|
|
# Ensure the primary hostname comes first |
|
|
|
|
vhosts.remove(config.primary_domain) |
|
|
|
|
vhosts.insert(0, config.primary_domain) |
|
|
|
|
else: |
|
|
|
@ -100,10 +115,11 @@ for name in vhosts: |
|
|
|
|
print(' {}'.format(name)) |
|
|
|
|
print() |
|
|
|
|
|
|
|
|
|
# Build certbot command line |
|
|
|
|
cmd = config.certbot_command |
|
|
|
|
|
|
|
|
|
for name in vhosts: |
|
|
|
|
cmd.extend(['-d', name]) |
|
|
|
|
|
|
|
|
|
print('Running', ' '.join(cmd)) |
|
|
|
|
print() |
|
|
|
|
run(cmd) |
|
|
|
|