d7301268fa
This is based on previous work [1] and it's what I've been using to test the TLS-everywhere work. This is a convenience tool that will generate an environment file that sets the override in the resource registry as well as the relevant parameters that will be needed in a TLS-everywhere deployment. [1] https://github.com/JAORMX/freeipa-tripleo-incubator bp tls-via-certmonger Change-Id: If3e6cb1dde235b24a0c188eb758f9a2e6a626f69 Depends-On: Iac94b3b047dca1bcabd464ea8eed6f1220c844f1
241 lines
8.9 KiB
Python
Executable File
241 lines
8.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright 2015 Red Hat, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""
|
|
Generate an environment file to enroll the controller nodes to FreeIPA via the
|
|
ExtraConfigPre hook.
|
|
|
|
Please note that this is only used for testing.
|
|
"""
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import collections
|
|
import logging
|
|
import os
|
|
from six.moves import input
|
|
import yaml
|
|
|
|
import tripleo_common.constants as tc_constants
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
autogen_warning = """### DO NOT MODIFY THIS FILE
|
|
### created by the script create_freeipa_enroll_envfile.py
|
|
|
|
"""
|
|
|
|
|
|
TEMPLATE_DEFAULT_PATH = os.path.join(
|
|
tc_constants.DEFAULT_TEMPLATES_PATH,
|
|
'puppet/extraconfig/tls/freeipa-enroll.yaml')
|
|
|
|
|
|
class TemplateDumper(yaml.SafeDumper):
|
|
def represent_ordered_dict(self, data):
|
|
return self.represent_dict(data.items())
|
|
|
|
|
|
TemplateDumper.add_representer(collections.OrderedDict,
|
|
TemplateDumper.represent_ordered_dict)
|
|
|
|
|
|
def write_env_file(output_file, env_dict):
|
|
with open(output_file, 'w') as f:
|
|
f.write(autogen_warning)
|
|
yaml.dump(env_dict, f, TemplateDumper, width=68,
|
|
default_flow_style=False)
|
|
LOG.info("environment file written to %s" % os.path.abspath(output_file))
|
|
|
|
|
|
def get_freeipa_parameter_defaults_dict(password, server, domain,
|
|
dns_servers, ipa_ip):
|
|
parameter_defaults = {
|
|
'FreeIPAOTP': password,
|
|
'FreeIPAServer': server,
|
|
'CloudDomain': domain,
|
|
}
|
|
if dns_servers:
|
|
parameter_defaults['DnsServers'] = dns_servers
|
|
if ipa_ip:
|
|
parameter_defaults['FreeIPAIPAddress'] = ipa_ip
|
|
return parameter_defaults
|
|
|
|
|
|
def get_freeipa_resource_registry_dict(stack):
|
|
resource_registry = {
|
|
'OS::TripleO::NodeTLSCAData': os.path.abspath(stack)
|
|
}
|
|
return resource_registry
|
|
|
|
|
|
def _form_fqdn(name, domain):
|
|
return "%s.%s" % (name, domain)
|
|
|
|
|
|
def get_cloud_names_parameter_defaults_dict(cloud_name,
|
|
cloud_name_internal,
|
|
cloud_name_storage,
|
|
cloud_name_storage_management,
|
|
cloud_name_ctlplane,
|
|
cloud_domain):
|
|
return {
|
|
'CloudName': _form_fqdn(cloud_name, cloud_domain),
|
|
'CloudNameInternal': _form_fqdn(cloud_name_internal, cloud_domain),
|
|
'CloudNameStorage': _form_fqdn(cloud_name_storage, cloud_domain),
|
|
'CloudNameStorageManagement': _form_fqdn(cloud_name_storage_management,
|
|
cloud_domain),
|
|
'CloudNameCtlplane': _form_fqdn(cloud_name_ctlplane, cloud_domain),
|
|
}
|
|
|
|
|
|
def get_freeipa_environment_dict(password, server, domain, dns_servers, ipa_ip,
|
|
stack, cloud_name, cloud_name_internal,
|
|
cloud_name_storage,
|
|
cloud_name_storage_management,
|
|
cloud_name_ctlplane):
|
|
enroll_dict = get_freeipa_parameter_defaults_dict(password, server, domain,
|
|
dns_servers, ipa_ip)
|
|
names_dict = get_cloud_names_parameter_defaults_dict(
|
|
cloud_name,
|
|
cloud_name_internal,
|
|
cloud_name_storage,
|
|
cloud_name_storage_management,
|
|
cloud_name_ctlplane,
|
|
domain)
|
|
enroll_dict.update(names_dict)
|
|
return get_environment_dict(enroll_dict,
|
|
get_freeipa_resource_registry_dict(stack))
|
|
|
|
|
|
def get_environment_dict(parameter_defaults=None, resource_registry=None):
|
|
resulting_dict = collections.OrderedDict()
|
|
if parameter_defaults:
|
|
resulting_dict['parameter_defaults'] = parameter_defaults
|
|
if resource_registry:
|
|
resulting_dict['resource_registry'] = resource_registry
|
|
return resulting_dict
|
|
|
|
|
|
def _confirm(message):
|
|
user_input = input(message)
|
|
return user_input.lower() in ['true', '1', 't', 'y', 'yes']
|
|
|
|
|
|
def _confirmation_if_output_file_exists(output, overwrite):
|
|
if os.path.isfile(output) and not overwrite:
|
|
LOG.warning("%s exists in the filesystem." % output)
|
|
if not _confirm("Do you want to overwrite it? "):
|
|
raise RuntimeError("%s exists and won't be overwritten." % output)
|
|
|
|
|
|
def _assert_stack_file_exists(stack):
|
|
if not os.path.isfile(stack):
|
|
raise IOError("%s file doesn't exist." % stack)
|
|
|
|
|
|
def _assert_not_empty(server, domain):
|
|
if not server or not domain:
|
|
raise RuntimeError(
|
|
"FreeIPA's server and the domain name can't be empty")
|
|
|
|
|
|
def _warn_unmatching_domain(server, domain):
|
|
if not server.endswith(domain):
|
|
LOG.warning(("FreeIPA's server domain doesn't seem to match the given "
|
|
"domain %s ... watch out") % domain)
|
|
|
|
|
|
def _validate_input(args):
|
|
_confirmation_if_output_file_exists(args.output, args.overwrite)
|
|
_assert_stack_file_exists(args.stack)
|
|
_assert_not_empty(args.server, args.domain)
|
|
_warn_unmatching_domain(args.server, args.domain)
|
|
|
|
|
|
def _get_options():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
# Base stack arguments
|
|
parser.add_argument('-w', '--password', required=True,
|
|
help='The OTP that will be used for the nodes.')
|
|
parser.add_argument('-s', '--server', required=True,
|
|
help="The FreeIPA server's fqdn.")
|
|
parser.add_argument('-d', '--domain', required=True,
|
|
help=("The FreeIPA managed domain (must match the "
|
|
"kerberos realm."))
|
|
parser.add_argument('-D', '--dns-server', action='append',
|
|
help=("The DNS server(s) that the overcloud should "
|
|
"have configured."))
|
|
parser.add_argument('-i', '--ipa-ip',
|
|
help="The FreeIPA server's IP address.")
|
|
parser.add_argument('-S', '--stack',
|
|
default=TEMPLATE_DEFAULT_PATH,
|
|
help=("stack template that will be used if not "
|
|
"default."))
|
|
parser.add_argument('-o', '--output',
|
|
default='freeipa-enroll.yaml',
|
|
help=('file that the freeipa-related environment will '
|
|
'be written to.'))
|
|
|
|
# Cloud name environment arguments
|
|
parser.add_argument('--cloud-name',
|
|
default='overcloud',
|
|
help=("The shortname for the overcloud (the domain "
|
|
"will be appended to this)."))
|
|
parser.add_argument('--cloud-name-internal',
|
|
default='overcloud.internalapi',
|
|
help=("The shortname name of the overcloud's internal "
|
|
"API endpoint (the domain will be appended to "
|
|
"this)."))
|
|
parser.add_argument('--cloud-name-storage',
|
|
default='overcloud.storage',
|
|
help=("The shortname name of the overcloud's storage "
|
|
"endpoint (the domain will be appended to "
|
|
"this)."))
|
|
parser.add_argument('--cloud-name-storage-management',
|
|
default='overcloud.storagemgmt',
|
|
help=("The shortname name of the overcloud's storage "
|
|
" management endpoint (the domain will be "
|
|
"appended to this)."))
|
|
parser.add_argument('--cloud-name-ctlplane',
|
|
default='overcloud.ctlplane',
|
|
help=("The shortname name of the overcloud's "
|
|
"ctlplane endpoint (the domain will be "
|
|
"appended to this)."))
|
|
|
|
# Extra
|
|
parser.add_argument('--overwrite', action='store_true',
|
|
help='overwrite the output file if it already exists.')
|
|
return parser.parse_args()
|
|
|
|
|
|
def main():
|
|
args = _get_options()
|
|
_validate_input(args)
|
|
enroll_dict = get_freeipa_environment_dict(
|
|
args.password, args.server, args.domain, args.dns_server, args.ipa_ip,
|
|
args.stack, args.cloud_name, args.cloud_name_internal,
|
|
args.cloud_name_storage, args.cloud_name_storage_management,
|
|
args.cloud_name_ctlplane)
|
|
write_env_file(args.output, enroll_dict)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|