Swift proxy is currently rejecting valid v3 tokens because it is failing to validate them due to its credentials being in the v2 format and missing domain information. This change examines the version of the API keystone has advertised down the identity-service relation and configures the proxy conf appropriately Change-Id: Id2215168ffbad1caf0e7203ded26c41913181306 Closes-Bug: 1624304
229 lines
7.9 KiB
Python
229 lines
7.9 KiB
Python
import os
|
|
import uuid
|
|
|
|
from charmhelpers.core.hookenv import (
|
|
config,
|
|
log,
|
|
relation_ids,
|
|
related_units,
|
|
relation_get,
|
|
unit_get,
|
|
service_name,
|
|
)
|
|
from charmhelpers.contrib.openstack.context import (
|
|
OSContextGenerator,
|
|
ApacheSSLContext as SSLContext,
|
|
context_complete,
|
|
IdentityServiceContext,
|
|
)
|
|
from charmhelpers.contrib.hahelpers.cluster import (
|
|
determine_api_port,
|
|
determine_apache_port,
|
|
)
|
|
from charmhelpers.contrib.network.ip import (
|
|
format_ipv6_addr,
|
|
get_ipv6_addr,
|
|
)
|
|
from charmhelpers.contrib.openstack.utils import get_host_ip
|
|
|
|
|
|
SWIFT_HASH_FILE = '/var/lib/juju/swift-hash-path.conf'
|
|
WWW_DIR = '/var/www/swift-rings'
|
|
|
|
|
|
class HAProxyContext(OSContextGenerator):
|
|
interfaces = ['cluster']
|
|
|
|
def __call__(self):
|
|
"""Extends the main charmhelpers HAProxyContext with a port mapping
|
|
specific to this charm.
|
|
Also used to extend cinder.conf context with correct api_listening_port
|
|
"""
|
|
haproxy_port = config('bind-port')
|
|
api_port = determine_apache_port(config('bind-port'),
|
|
singlenode_mode=True)
|
|
|
|
ctxt = {
|
|
'service_ports': {'swift_api': [haproxy_port, api_port]},
|
|
}
|
|
return ctxt
|
|
|
|
|
|
class ApacheSSLContext(SSLContext):
|
|
interfaces = ['https']
|
|
service_namespace = 'swift'
|
|
|
|
# We make this a property so that we avoid import-time
|
|
# dependencies on config()
|
|
|
|
@property
|
|
def external_ports(self):
|
|
return [config('bind-port')]
|
|
|
|
|
|
class SwiftRingContext(OSContextGenerator):
|
|
|
|
def __call__(self):
|
|
allowed_hosts = []
|
|
for relid in relation_ids('swift-storage'):
|
|
for unit in related_units(relid):
|
|
host = relation_get('private-address', unit, relid)
|
|
if config('prefer-ipv6'):
|
|
host_ip = get_ipv6_addr(exc_list=[config('vip')])[0]
|
|
else:
|
|
host_ip = get_host_ip(host)
|
|
|
|
allowed_hosts.append(host_ip)
|
|
|
|
ctxt = {
|
|
'www_dir': WWW_DIR,
|
|
'allowed_hosts': allowed_hosts
|
|
}
|
|
return ctxt
|
|
|
|
|
|
class SwiftIdentityContext(OSContextGenerator):
|
|
interfaces = ['identity-service']
|
|
|
|
def __call__(self):
|
|
bind_port = config('bind-port')
|
|
workers = config('workers')
|
|
if workers == 0:
|
|
import multiprocessing
|
|
workers = multiprocessing.cpu_count()
|
|
if config('prefer-ipv6'):
|
|
proxy_ip = '[%s]' % get_ipv6_addr(exc_list=[config('vip')])[0]
|
|
memcached_ip = 'ip6-localhost'
|
|
else:
|
|
proxy_ip = get_host_ip(unit_get('private-address'))
|
|
memcached_ip = get_host_ip(unit_get('private-address'))
|
|
|
|
ctxt = {
|
|
'proxy_ip': proxy_ip,
|
|
'memcached_ip': memcached_ip,
|
|
'bind_port': determine_api_port(bind_port, singlenode_mode=True),
|
|
'workers': workers,
|
|
'operator_roles': config('operator-roles'),
|
|
'delay_auth_decision': config('delay-auth-decision'),
|
|
'node_timeout': config('node-timeout'),
|
|
'recoverable_node_timeout': config('recoverable-node-timeout'),
|
|
'log_headers': config('log-headers')
|
|
}
|
|
|
|
if config('debug'):
|
|
ctxt['log_level'] = 'DEBUG'
|
|
else:
|
|
ctxt['log_level'] = 'INFO'
|
|
|
|
# Instead of duplicating code lets use charm-helpers to set signing_dir
|
|
# TODO(hopem): refactor this context handler to use charm-helpers
|
|
# code.
|
|
_ctxt = IdentityServiceContext(service='swift', service_user='swift')()
|
|
signing_dir = _ctxt.get('signing_dir')
|
|
if signing_dir:
|
|
ctxt['signing_dir'] = signing_dir
|
|
|
|
ctxt['ssl'] = False
|
|
|
|
auth_type = config('auth-type')
|
|
auth_host = config('keystone-auth-host')
|
|
admin_user = config('keystone-admin-user')
|
|
admin_password = config('keystone-admin-user')
|
|
if (auth_type == 'keystone' and auth_host and
|
|
admin_user and admin_password):
|
|
log('Using user-specified Keystone configuration.')
|
|
ks_auth = {
|
|
'auth_type': 'keystone',
|
|
'auth_protocol': config('keystone-auth-protocol'),
|
|
'keystone_host': auth_host,
|
|
'auth_port': config('keystone-auth-port'),
|
|
'service_user': admin_user,
|
|
'service_password': admin_password,
|
|
'service_tenant': config('keystone-admin-tenant-name'),
|
|
}
|
|
ctxt.update(ks_auth)
|
|
|
|
for relid in relation_ids('identity-service'):
|
|
log('Using Keystone configuration from identity-service.')
|
|
for unit in related_units(relid):
|
|
ks_auth = {
|
|
'auth_type': 'keystone',
|
|
'auth_protocol': relation_get('auth_protocol',
|
|
unit, relid) or 'http',
|
|
'service_protocol': relation_get('service_protocol',
|
|
unit, relid) or 'http',
|
|
'keystone_host': relation_get('auth_host',
|
|
unit, relid),
|
|
'service_host': relation_get('service_host',
|
|
unit, relid),
|
|
'auth_port': relation_get('auth_port',
|
|
unit, relid),
|
|
'service_user': relation_get('service_username',
|
|
unit, relid),
|
|
'service_password': relation_get('service_password',
|
|
unit, relid),
|
|
'service_tenant': relation_get('service_tenant',
|
|
unit, relid),
|
|
'service_port': relation_get('service_port',
|
|
unit, relid),
|
|
'admin_token': relation_get('admin_token',
|
|
unit, relid),
|
|
'api_version': relation_get('api_version',
|
|
unit, relid) or '2',
|
|
}
|
|
if ks_auth['api_version'] == '3':
|
|
ks_auth['admin_domain_id'] = relation_get(
|
|
'admin_domain_id', unit, relid)
|
|
ks_auth['service_tenant_id'] = relation_get(
|
|
'service_tenant_id', unit, relid)
|
|
if context_complete(ks_auth):
|
|
ctxt.update(ks_auth)
|
|
|
|
if config('prefer-ipv6'):
|
|
for key in ['keystone_host', 'service_host']:
|
|
host = ctxt.get(key)
|
|
if host:
|
|
ctxt[key] = format_ipv6_addr(host)
|
|
|
|
return ctxt
|
|
|
|
|
|
class MemcachedContext(OSContextGenerator):
|
|
|
|
def __call__(self):
|
|
ctxt = {}
|
|
if config('prefer-ipv6'):
|
|
ctxt['memcached_ip'] = 'ip6-localhost'
|
|
else:
|
|
ctxt['memcached_ip'] = get_host_ip(unit_get('private-address'))
|
|
|
|
return ctxt
|
|
|
|
|
|
def get_swift_hash():
|
|
if os.path.isfile(SWIFT_HASH_FILE):
|
|
with open(SWIFT_HASH_FILE, 'r') as hashfile:
|
|
swift_hash = hashfile.read().strip()
|
|
elif config('swift-hash'):
|
|
swift_hash = config('swift-hash')
|
|
with open(SWIFT_HASH_FILE, 'w') as hashfile:
|
|
hashfile.write(swift_hash)
|
|
else:
|
|
model_uuid = os.environ.get("JUJU_ENV_UUID",
|
|
os.environ.get("JUJU_MODEL_UUID"))
|
|
swift_hash = str(uuid.uuid3(uuid.UUID(model_uuid),
|
|
service_name()))
|
|
with open(SWIFT_HASH_FILE, 'w') as hashfile:
|
|
hashfile.write(swift_hash)
|
|
|
|
return swift_hash
|
|
|
|
|
|
class SwiftHashContext(OSContextGenerator):
|
|
|
|
def __call__(self):
|
|
ctxt = {
|
|
'swift_hash': get_swift_hash()
|
|
}
|
|
return ctxt
|