From 21e8c5aeeba27f832a894cce84e88b0837ab5ac2 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 18 Oct 2017 08:51:15 +0000 Subject: [PATCH] Remove password expiry from unison user This change ensures that any password expiry has been removed from the user that runs unison to synchronize data. The fix is entirely in charm-helpers so this patch is a simple sync. Change-Id: I75d6ac0e9be19a87efe16a1095b1afd44f41dc17 Closes-Bug: #1686085 --- charmhelpers/contrib/openstack/ha/utils.py | 11 ++-- charmhelpers/contrib/openstack/neutron.py | 61 +++---------------- .../openstack/templates/section-oslo-cache | 6 ++ charmhelpers/contrib/unison/__init__.py | 3 + charmhelpers/core/hookenv.py | 18 ++++++ charmhelpers/core/host.py | 43 +++++++++++++ tests/charmhelpers/core/hookenv.py | 18 ++++++ tests/charmhelpers/core/host.py | 43 +++++++++++++ 8 files changed, 148 insertions(+), 55 deletions(-) create mode 100644 charmhelpers/contrib/openstack/templates/section-oslo-cache diff --git a/charmhelpers/contrib/openstack/ha/utils.py b/charmhelpers/contrib/openstack/ha/utils.py index 254a90e7..9a4d79c1 100644 --- a/charmhelpers/contrib/openstack/ha/utils.py +++ b/charmhelpers/contrib/openstack/ha/utils.py @@ -82,15 +82,18 @@ def update_dns_ha_resource_params(resources, resource_params, continue m = re.search('os-(.+?)-hostname', setting) if m: - networkspace = m.group(1) + endpoint_type = m.group(1) + # resolve_address's ADDRESS_MAP uses 'int' not 'internal' + if endpoint_type == 'internal': + endpoint_type = 'int' else: msg = ('Unexpected DNS hostname setting: {}. ' - 'Cannot determine network space name' + 'Cannot determine endpoint_type name' ''.format(setting)) status_set('blocked', msg) raise DNSHAException(msg) - hostname_key = 'res_{}_{}_hostname'.format(charm_name(), networkspace) + hostname_key = 'res_{}_{}_hostname'.format(charm_name(), endpoint_type) if hostname_key in hostname_group: log('DNS HA: Resource {}: {} already exists in ' 'hostname group - skipping'.format(hostname_key, hostname), @@ -101,7 +104,7 @@ def update_dns_ha_resource_params(resources, resource_params, resources[hostname_key] = crm_ocf resource_params[hostname_key] = ( 'params fqdn="{}" ip_address="{}" ' - ''.format(hostname, resolve_address(endpoint_type=networkspace, + ''.format(hostname, resolve_address(endpoint_type=endpoint_type, override=False))) if len(hostname_group) >= 1: diff --git a/charmhelpers/contrib/openstack/neutron.py b/charmhelpers/contrib/openstack/neutron.py index 37fa0eb0..0f847f56 100644 --- a/charmhelpers/contrib/openstack/neutron.py +++ b/charmhelpers/contrib/openstack/neutron.py @@ -59,18 +59,13 @@ def determine_dkms_package(): def quantum_plugins(): - from charmhelpers.contrib.openstack import context return { 'ovs': { 'config': '/etc/quantum/plugins/openvswitch/' 'ovs_quantum_plugin.ini', 'driver': 'quantum.plugins.openvswitch.ovs_quantum_plugin.' 'OVSQuantumPluginV2', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=QUANTUM_CONF_DIR)], + 'contexts': [], 'services': ['quantum-plugin-openvswitch-agent'], 'packages': [determine_dkms_package(), ['quantum-plugin-openvswitch-agent']], @@ -82,11 +77,7 @@ def quantum_plugins(): 'config': '/etc/quantum/plugins/nicira/nvp.ini', 'driver': 'quantum.plugins.nicira.nicira_nvp_plugin.' 'QuantumPlugin.NvpPluginV2', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=QUANTUM_CONF_DIR)], + 'contexts': [], 'services': [], 'packages': [], 'server_packages': ['quantum-server', @@ -100,7 +91,6 @@ NEUTRON_CONF_DIR = '/etc/neutron' def neutron_plugins(): - from charmhelpers.contrib.openstack import context release = os_release('nova-common') plugins = { 'ovs': { @@ -108,11 +98,7 @@ def neutron_plugins(): 'ovs_neutron_plugin.ini', 'driver': 'neutron.plugins.openvswitch.ovs_neutron_plugin.' 'OVSNeutronPluginV2', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=NEUTRON_CONF_DIR)], + 'contexts': [], 'services': ['neutron-plugin-openvswitch-agent'], 'packages': [determine_dkms_package(), ['neutron-plugin-openvswitch-agent']], @@ -124,11 +110,7 @@ def neutron_plugins(): 'config': '/etc/neutron/plugins/nicira/nvp.ini', 'driver': 'neutron.plugins.nicira.nicira_nvp_plugin.' 'NeutronPlugin.NvpPluginV2', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=NEUTRON_CONF_DIR)], + 'contexts': [], 'services': [], 'packages': [], 'server_packages': ['neutron-server', @@ -138,11 +120,7 @@ def neutron_plugins(): 'nsx': { 'config': '/etc/neutron/plugins/vmware/nsx.ini', 'driver': 'vmware', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=NEUTRON_CONF_DIR)], + 'contexts': [], 'services': [], 'packages': [], 'server_packages': ['neutron-server', @@ -152,11 +130,7 @@ def neutron_plugins(): 'n1kv': { 'config': '/etc/neutron/plugins/cisco/cisco_plugins.ini', 'driver': 'neutron.plugins.cisco.network_plugin.PluginV2', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=NEUTRON_CONF_DIR)], + 'contexts': [], 'services': [], 'packages': [determine_dkms_package(), ['neutron-plugin-cisco']], @@ -167,11 +141,7 @@ def neutron_plugins(): 'Calico': { 'config': '/etc/neutron/plugins/ml2/ml2_conf.ini', 'driver': 'neutron.plugins.ml2.plugin.Ml2Plugin', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=NEUTRON_CONF_DIR)], + 'contexts': [], 'services': ['calico-felix', 'bird', 'neutron-dhcp-agent', @@ -189,11 +159,7 @@ def neutron_plugins(): 'vsp': { 'config': '/etc/neutron/plugins/nuage/nuage_plugin.ini', 'driver': 'neutron.plugins.nuage.plugin.NuagePlugin', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=NEUTRON_CONF_DIR)], + 'contexts': [], 'services': [], 'packages': [], 'server_packages': ['neutron-server', 'neutron-plugin-nuage'], @@ -203,10 +169,7 @@ def neutron_plugins(): 'config': '/etc/neutron/plugins/plumgrid/plumgrid.ini', 'driver': ('neutron.plugins.plumgrid.plumgrid_plugin' '.plumgrid_plugin.NeutronPluginPLUMgridV2'), - 'contexts': [ - context.SharedDBContext(user=config('database-user'), - database=config('database'), - ssl_dir=NEUTRON_CONF_DIR)], + 'contexts': [], 'services': [], 'packages': ['plumgrid-lxc', 'iovisor-dkms'], @@ -217,11 +180,7 @@ def neutron_plugins(): 'midonet': { 'config': '/etc/neutron/plugins/midonet/midonet.ini', 'driver': 'midonet.neutron.plugin.MidonetPluginV2', - 'contexts': [ - context.SharedDBContext(user=config('neutron-database-user'), - database=config('neutron-database'), - relation_prefix='neutron', - ssl_dir=NEUTRON_CONF_DIR)], + 'contexts': [], 'services': [], 'packages': [determine_dkms_package()], 'server_packages': ['neutron-server', diff --git a/charmhelpers/contrib/openstack/templates/section-oslo-cache b/charmhelpers/contrib/openstack/templates/section-oslo-cache new file mode 100644 index 00000000..e056a32a --- /dev/null +++ b/charmhelpers/contrib/openstack/templates/section-oslo-cache @@ -0,0 +1,6 @@ +[cache] +{% if memcache_url %} +enabled = true +backend = oslo_cache.memcache_pool +memcache_servers = {{ memcache_url }} +{% endif %} diff --git a/charmhelpers/contrib/unison/__init__.py b/charmhelpers/contrib/unison/__init__.py index cef0be27..83108883 100644 --- a/charmhelpers/contrib/unison/__init__.py +++ b/charmhelpers/contrib/unison/__init__.py @@ -69,6 +69,7 @@ from charmhelpers.core.host import ( adduser, add_user_to_group, pwgen, + remove_password_expiry, ) from charmhelpers.core.hookenv import ( @@ -177,6 +178,8 @@ def ensure_user(user, group=None): adduser(user, pwgen()) if group: add_user_to_group(user, group) + # Remove password expiry (Bug #1686085) + remove_password_expiry(user) def ssh_authorized_peers(peer_interface, user, group=None, diff --git a/charmhelpers/core/hookenv.py b/charmhelpers/core/hookenv.py index 622987d1..fb96f2dd 100644 --- a/charmhelpers/core/hookenv.py +++ b/charmhelpers/core/hookenv.py @@ -1093,6 +1093,24 @@ def network_get_primary_address(binding): return subprocess.check_output(cmd).decode('UTF-8').strip() +@translate_exc(from_exc=OSError, to_exc=NotImplementedError) +def network_get(endpoint, relation_id=None): + """ + Retrieve the network details for a relation endpoint + + :param endpoint: string. The name of a relation endpoint + :param relation_id: int. The ID of the relation for the current context. + :return: dict. The loaded YAML output of the network-get query. + :raise: NotImplementedError if run on Juju < 2.0 + """ + cmd = ['network-get', endpoint, '--format', 'yaml'] + if relation_id: + cmd.append('-r') + cmd.append(relation_id) + response = subprocess.check_output(cmd).decode('UTF-8').strip() + return yaml.safe_load(response) + + def add_metric(*args, **kwargs): """Add metric values. Values may be expressed with keyword arguments. For metric names containing dashes, these may be expressed as one or more diff --git a/charmhelpers/core/host.py b/charmhelpers/core/host.py index 2ac94e04..5cc5c86b 100644 --- a/charmhelpers/core/host.py +++ b/charmhelpers/core/host.py @@ -441,6 +441,49 @@ def add_user_to_group(username, group): subprocess.check_call(cmd) +def chage(username, lastday=None, expiredate=None, inactive=None, + mindays=None, maxdays=None, root=None, warndays=None): + """Change user password expiry information + + :param str username: User to update + :param str lastday: Set when password was changed in YYYY-MM-DD format + :param str expiredate: Set when user's account will no longer be + accessible in YYYY-MM-DD format. + -1 will remove an account expiration date. + :param str inactive: Set the number of days of inactivity after a password + has expired before the account is locked. + -1 will remove an account's inactivity. + :param str mindays: Set the minimum number of days between password + changes to MIN_DAYS. + 0 indicates the password can be changed anytime. + :param str maxdays: Set the maximum number of days during which a + password is valid. + -1 as MAX_DAYS will remove checking maxdays + :param str root: Apply changes in the CHROOT_DIR directory + :param str warndays: Set the number of days of warning before a password + change is required + :raises subprocess.CalledProcessError: if call to chage fails + """ + cmd = ['chage'] + if root: + cmd.extend(['--root', root]) + if lastday: + cmd.extend(['--lastday', lastday]) + if expiredate: + cmd.extend(['--expiredate', expiredate]) + if inactive: + cmd.extend(['--inactive', inactive]) + if mindays: + cmd.extend(['--mindays', mindays]) + if maxdays: + cmd.extend(['--maxdays', maxdays]) + if warndays: + cmd.extend(['--warndays', warndays]) + cmd.append(username) + subprocess.check_call(cmd) + +remove_password_expiry = functools.partial(chage, expiredate='-1', inactive='-1', mindays='0', maxdays='-1') + def rsync(from_path, to_path, flags='-r', options=None, timeout=None): """Replicate the contents of a path""" options = options or ['--delete', '--executability'] diff --git a/tests/charmhelpers/core/hookenv.py b/tests/charmhelpers/core/hookenv.py index 622987d1..fb96f2dd 100644 --- a/tests/charmhelpers/core/hookenv.py +++ b/tests/charmhelpers/core/hookenv.py @@ -1093,6 +1093,24 @@ def network_get_primary_address(binding): return subprocess.check_output(cmd).decode('UTF-8').strip() +@translate_exc(from_exc=OSError, to_exc=NotImplementedError) +def network_get(endpoint, relation_id=None): + """ + Retrieve the network details for a relation endpoint + + :param endpoint: string. The name of a relation endpoint + :param relation_id: int. The ID of the relation for the current context. + :return: dict. The loaded YAML output of the network-get query. + :raise: NotImplementedError if run on Juju < 2.0 + """ + cmd = ['network-get', endpoint, '--format', 'yaml'] + if relation_id: + cmd.append('-r') + cmd.append(relation_id) + response = subprocess.check_output(cmd).decode('UTF-8').strip() + return yaml.safe_load(response) + + def add_metric(*args, **kwargs): """Add metric values. Values may be expressed with keyword arguments. For metric names containing dashes, these may be expressed as one or more diff --git a/tests/charmhelpers/core/host.py b/tests/charmhelpers/core/host.py index 2ac94e04..5cc5c86b 100644 --- a/tests/charmhelpers/core/host.py +++ b/tests/charmhelpers/core/host.py @@ -441,6 +441,49 @@ def add_user_to_group(username, group): subprocess.check_call(cmd) +def chage(username, lastday=None, expiredate=None, inactive=None, + mindays=None, maxdays=None, root=None, warndays=None): + """Change user password expiry information + + :param str username: User to update + :param str lastday: Set when password was changed in YYYY-MM-DD format + :param str expiredate: Set when user's account will no longer be + accessible in YYYY-MM-DD format. + -1 will remove an account expiration date. + :param str inactive: Set the number of days of inactivity after a password + has expired before the account is locked. + -1 will remove an account's inactivity. + :param str mindays: Set the minimum number of days between password + changes to MIN_DAYS. + 0 indicates the password can be changed anytime. + :param str maxdays: Set the maximum number of days during which a + password is valid. + -1 as MAX_DAYS will remove checking maxdays + :param str root: Apply changes in the CHROOT_DIR directory + :param str warndays: Set the number of days of warning before a password + change is required + :raises subprocess.CalledProcessError: if call to chage fails + """ + cmd = ['chage'] + if root: + cmd.extend(['--root', root]) + if lastday: + cmd.extend(['--lastday', lastday]) + if expiredate: + cmd.extend(['--expiredate', expiredate]) + if inactive: + cmd.extend(['--inactive', inactive]) + if mindays: + cmd.extend(['--mindays', mindays]) + if maxdays: + cmd.extend(['--maxdays', maxdays]) + if warndays: + cmd.extend(['--warndays', warndays]) + cmd.append(username) + subprocess.check_call(cmd) + +remove_password_expiry = functools.partial(chage, expiredate='-1', inactive='-1', mindays='0', maxdays='-1') + def rsync(from_path, to_path, flags='-r', options=None, timeout=None): """Replicate the contents of a path""" options = options or ['--delete', '--executability']