def configure_ca(self): from keystone_utils import ( SSH_USER, get_ca, ensure_permissions, is_ssl_cert_master, ) if not is_cert_provided_in_config() and not is_ssl_cert_master(): log( "Not ssl-cert-master - skipping apache ca config until " "master is elected", level=INFO) return ca_cert = config('ssl_ca') if ca_cert is None: ca = get_ca(user=SSH_USER) ca_cert = ca.get_ca_bundle() else: ca_cert = b64decode(ca_cert) # Ensure accessible by keystone ssh user and group (unison) install_ca_cert(ca_cert) ensure_permissions(CA_CERT_PATH, user=SSH_USER, group='keystone', perms=0o0644)
def configure_cert(self, cn): from keystone_utils import ( SSH_USER, get_ca, ensure_permissions, is_ssl_cert_master, KEYSTONE_USER, ) # Ensure ssl dir exists whether master or not perms = 0o775 mkdir(path=self.ssl_dir, owner=SSH_USER, group=KEYSTONE_USER, perms=perms) # Ensure accessible by keystone ssh user and group (for sync) ensure_permissions(self.ssl_dir, user=SSH_USER, group=KEYSTONE_USER, perms=perms) if not is_cert_provided_in_config() and not is_ssl_cert_master(): log( "Not ssl-cert-master - skipping apache cert config until " "master is elected", level=INFO) return log("Creating apache ssl certs in %s" % (self.ssl_dir), level=INFO) cert = config('ssl_cert') key = config('ssl_key') if not (cert and key): ca = get_ca(user=SSH_USER) cert, key = ca.get_cert_and_key(common_name=cn) else: cert = b64decode(cert) key = b64decode(key) write_file(path=os.path.join(self.ssl_dir, 'cert_{}'.format(cn)), content=cert, owner=SSH_USER, group=KEYSTONE_USER, perms=0o640) write_file(path=os.path.join(self.ssl_dir, 'key_{}'.format(cn)), content=key, owner=SSH_USER, group=KEYSTONE_USER, perms=0o640)
def configure_cert(self, cn): from keystone_utils import ( SSH_USER, get_ca, ensure_permissions, is_ssl_cert_master, ) # Ensure ssl dir exists whether master or not ssl_dir = os.path.join('/etc/apache2/ssl/', self.service_namespace) perms = 0o755 mkdir(path=ssl_dir, owner=SSH_USER, group='keystone', perms=perms) # Ensure accessible by keystone ssh user and group (for sync) ensure_permissions(ssl_dir, user=SSH_USER, group='keystone', perms=perms) if not is_cert_provided_in_config() and not is_ssl_cert_master(): log("Not ssl-cert-master - skipping apache cert config until " "master is elected", level=INFO) return log("Creating apache ssl certs in %s" % (ssl_dir), level=INFO) cert = config('ssl_cert') key = config('ssl_key') if not (cert and key): ca = get_ca(user=SSH_USER) cert, key = ca.get_cert_and_key(common_name=cn) else: cert = b64decode(cert) key = b64decode(key) write_file(path=os.path.join(ssl_dir, 'cert_{}'.format(cn)), content=cert, owner=SSH_USER, group='keystone', perms=0o644) write_file(path=os.path.join(ssl_dir, 'key_{}'.format(cn)), content=key, owner=SSH_USER, group='keystone', perms=0o644)
def configure_ca(self): from keystone_utils import ( SSH_USER, get_ca, ensure_permissions, is_ssl_cert_master, KEYSTONE_USER, ) if not is_cert_provided_in_config() and not is_ssl_cert_master(): log( "Not ssl-cert-master - skipping apache ca config until " "master is elected", level=INFO) return cert = config('ssl_cert') key = config('ssl_key') ca_cert = config('ssl_ca') if ca_cert: ca_cert = b64decode(ca_cert) elif not (cert and key): # NOTE(hopem): if a cert and key are provided as config we don't # mandate that a CA is also provided since it isn't necessarily # needed. As a result we only generate a custom CA if we are also # generating cert and key. ca = get_ca(user=SSH_USER) ca_cert = ca.get_ca_bundle() if ca_cert: # Ensure accessible by keystone ssh user and group (unison) install_ca_cert(ca_cert) ensure_permissions(CA_CERT_PATH, user=SSH_USER, group=KEYSTONE_USER, perms=0o0644)
def configure_ca(self): from keystone_utils import ( SSH_USER, get_ca, ensure_permissions, is_ssl_cert_master, ) if not is_cert_provided_in_config() and not is_ssl_cert_master(): log("Not ssl-cert-master - skipping apache ca config until " "master is elected", level=INFO) return ca_cert = config('ssl_ca') if ca_cert is None: ca = get_ca(user=SSH_USER) ca_cert = ca.get_ca_bundle() else: ca_cert = b64decode(ca_cert) # Ensure accessible by keystone ssh user and group (unison) install_ca_cert(ca_cert) ensure_permissions(CA_CERT_PATH, user=SSH_USER, group='keystone', perms=0o0644)
def identity_changed(relation_id=None, remote_unit=None): """ A service has advertised its API endpoints, create an entry in the service catalog. Optionally allow this hook to be re-fired for an existing relation+unit, for context see see db_changed(). """ if not cluster.eligible_leader(CLUSTER_RES): utils.juju_log('INFO', 'Deferring identity_changed() to service leader.') return settings = utils.relation_get_dict(relation_id=relation_id, remote_unit=remote_unit) # the minimum settings needed per endpoint single = set(['service', 'region', 'public_url', 'admin_url', 'internal_url']) if single.issubset(settings): # other end of relation advertised only one endpoint if 'None' in [v for k, v in settings.iteritems()]: # Some backend services advertise no endpoint but require a # hook execution to update auth strategy. relation_data = {} # Check if clustered and use vip + haproxy ports if so if cluster.is_clustered(): relation_data["auth_host"] = config['vip'] relation_data["service_host"] = config['vip'] else: relation_data["auth_host"] = config['hostname'] relation_data["service_host"] = config['hostname'] relation_data["auth_port"] = config['admin-port'] relation_data["service_port"] = config['service-port'] if config['https-service-endpoints'] in ['True', 'true']: # Pass CA cert as client will need it to # verify https connections ca = get_ca(user=SSH_USER) ca_bundle = ca.get_ca_bundle() relation_data['https_keystone'] = 'True' relation_data['ca_cert'] = b64encode(ca_bundle) if relation_id: relation_data['rid'] = relation_id # Allow the remote service to request creation of any additional # roles. Currently used by Horizon for role in get_requested_roles(settings): utils.juju_log('INFO', "Creating requested role: %s" % role) create_role(role) utils.relation_set(**relation_data) return else: ensure_valid_service(settings['service']) add_endpoint(region=settings['region'], service=settings['service'], publicurl=settings['public_url'], adminurl=settings['admin_url'], internalurl=settings['internal_url']) service_username = settings['service'] https_cn = urlparse.urlparse(settings['internal_url']) https_cn = https_cn.hostname else: # assemble multiple endpoints from relation data. service name # should be prepended to setting name, ie: # realtion-set ec2_service=$foo ec2_region=$foo ec2_public_url=$foo # relation-set nova_service=$foo nova_region=$foo nova_public_url=$foo # Results in a dict that looks like: # { 'ec2': { # 'service': $foo # 'region': $foo # 'public_url': $foo # } # 'nova': { # 'service': $foo # 'region': $foo # 'public_url': $foo # } # } endpoints = {} for k, v in settings.iteritems(): ep = k.split('_')[0] x = '_'.join(k.split('_')[1:]) if ep not in endpoints: endpoints[ep] = {} endpoints[ep][x] = v services = [] https_cn = None for ep in endpoints: # weed out any unrelated relation stuff Juju might have added # by ensuring each possible endpiont has appropriate fields # ['service', 'region', 'public_url', 'admin_url', 'internal_url'] if single.issubset(endpoints[ep]): ep = endpoints[ep] ensure_valid_service(ep['service']) add_endpoint(region=ep['region'], service=ep['service'], publicurl=ep['public_url'], adminurl=ep['admin_url'], internalurl=ep['internal_url']) services.append(ep['service']) if not https_cn: https_cn = urlparse.urlparse(ep['internal_url']) https_cn = https_cn.hostname service_username = '******'.join(services) if 'None' in [v for k, v in settings.iteritems()]: return if not service_username: return token = get_admin_token() utils.juju_log('INFO', "Creating service credentials for '%s'" % service_username) service_password = get_service_password(service_username) create_user(service_username, service_password, config['service-tenant']) grant_role(service_username, config['admin-role'], config['service-tenant']) # Allow the remote service to request creation of any additional roles. # Currently used by Swift and Ceilometer. for role in get_requested_roles(settings): utils.juju_log('INFO', "Creating requested role: %s" % role) create_role(role, service_username, config['service-tenant']) # As of https://review.openstack.org/#change,4675, all nodes hosting # an endpoint(s) needs a service username and password assigned to # the service tenant and granted admin role. # note: config['service-tenant'] is created in utils.ensure_initial_admin() # we return a token, information about our API endpoints, and the generated # service credentials relation_data = { "admin_token": token, "service_host": config["hostname"], "service_port": config["service-port"], "auth_host": config["hostname"], "auth_port": config["admin-port"], "service_username": service_username, "service_password": service_password, "service_tenant": config['service-tenant'], "https_keystone": "False", "ssl_cert": "", "ssl_key": "", "ca_cert": "" } if relation_id: relation_data['rid'] = relation_id # Check if clustered and use vip + haproxy ports if so if cluster.is_clustered(): relation_data["auth_host"] = config['vip'] relation_data["service_host"] = config['vip'] # generate or get a new cert/key for service if set to manage certs. if config['https-service-endpoints'] in ['True', 'true']: ca = get_ca(user=SSH_USER) cert, key = ca.get_cert_and_key(common_name=https_cn) ca_bundle = ca.get_ca_bundle() relation_data['ssl_cert'] = b64encode(cert) relation_data['ssl_key'] = b64encode(key) relation_data['ca_cert'] = b64encode(ca_bundle) relation_data['https_keystone'] = 'True' unison.sync_to_peers(peer_interface='cluster', paths=[SSL_DIR], user=SSH_USER, verbose=True) utils.relation_set(**relation_data) synchronize_service_credentials()