mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
bc4ef99533
* openstack: standardize tls params * tower: tower_verify_ssl->validate_certs * docker: use standard tls config params - cacert_path -> ca_cert - cert_path -> client_cert - key_path -> client_key - tls_verify -> validate_certs * k8s: standardize tls connection params - verify_ssl -> validate_certs - ssl_ca_cert -> ca_cert - cert_file -> client_cert - key_file -> client_key * ingate: verify_ssl -> validate_certs * manageiq: standardize tls params - verify_ssl -> validate_certs - ca_bundle_path -> ca_cert * mysql: standardize tls params - ssl_ca -> ca_cert - ssl_cert -> client_cert - ssl_key -> client_key * nios: ssl_verify -> validate_certs * postgresql: ssl_rootcert -> ca_cert * rabbitmq: standardize tls params - cacert -> ca_cert - cert -> client_cert - key -> client_key * rackspace: verify_ssl -> validate_certs * vca: verify_certs -> validate_certs * kubevirt_cdi_upload: upload_host_verify_ssl -> upload_host_validate_certs * lxd: standardize tls params - key_file -> client_key - cert_file -> client_cert * get_certificate: ca_certs -> ca_cert * get_certificate.py: clarify one or more certs in a file Co-Authored-By: jamescassell <code@james.cassell.me> * zabbix: tls_issuer -> ca_cert * bigip_device_auth_ldap: standardize tls params - ssl_check_peer -> validate_certs - ssl_client_cert -> client_cert - ssl_client_key -> client_key - ssl_ca_cert -> ca_cert * vdirect: vdirect_validate_certs -> validate_certs * mqtt: standardize tls params - ca_certs -> ca_cert - certfile -> client_cert - keyfile -> client_key * pulp_repo: standardize tls params remove `importer_ssl` prefix * rhn_register: sslcacert -> ca_cert * yum_repository: standardize tls params The fix for yum_repository is not straightforward since this module is only a thin wrapper for the underlying commands and config. In this case, we add the new values as aliases, keeping the old as primary, only due to the internal structure of the module. Aliases added: - sslcacert -> ca_cert - sslclientcert -> client_cert - sslclientkey -> client_key - sslverify -> validate_certs * gitlab_hook: enable_ssl_verification -> hook_validate_certs * Adjust arguments for docker_swarm inventory plugin. * foreman callback: standardize tls params - ssl_cert -> client_cert - ssl_key -> client_key * grafana_annotations: validate_grafana_certs -> validate_certs * nrdp callback: validate_nrdp_certs -> validate_certs * kubectl connection: standardize tls params - kubectl_cert_file -> client_cert - kubectl_key_file -> client_key - kubectl_ssl_ca_cert -> ca_cert - kubectl_verify_ssl -> validate_certs * oc connection: standardize tls params - oc_cert_file -> client_cert - oc_key_file -> client_key - oc_ssl_ca_cert -> ca_cert - oc_verify_ssl -> validate_certs * psrp connection: cert_trust_path -> ca_cert TODO: cert_validation -> validate_certs (multi-valued vs bool) * k8s inventory: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * openshift inventory: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * tower inventory: verify_ssl -> validate_certs * hashi_vault lookup: cacert -> ca_cert * k8s lookup: standardize tls params - cert_file -> client_cert - key_file -> client_key - ca_cert -> ca_cert - verify_ssl -> validate_certs * laps_passord lookup: cacert_file -> ca_cert * changelog for TLS parameter standardization
204 lines
8.9 KiB
Python
204 lines
8.9 KiB
Python
# Copyright (c) 2018 Ansible Project
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
from __future__ import (absolute_import, division, print_function)
|
|
|
|
__metaclass__ = type
|
|
|
|
DOCUMENTATION = '''
|
|
name: tower
|
|
plugin_type: inventory
|
|
author:
|
|
- Matthew Jones (@matburt)
|
|
- Yunfan Zhang (@YunfanZhang42)
|
|
short_description: Ansible dynamic inventory plugin for Ansible Tower.
|
|
version_added: "2.7"
|
|
description:
|
|
- Reads inventories from Ansible Tower.
|
|
- Supports reading configuration from both YAML config file and environment variables.
|
|
- If reading from the YAML file, the file name must end with tower.(yml|yaml) or tower_inventory.(yml|yaml),
|
|
the path in the command would be /path/to/tower_inventory.(yml|yaml). If some arguments in the config file
|
|
are missing, this plugin will try to fill in missing arguments by reading from environment variables.
|
|
- If reading configurations from environment variables, the path in the command must be @tower_inventory.
|
|
options:
|
|
plugin:
|
|
description: the name of this plugin, it should always be set to 'tower'
|
|
for this plugin to recognize it as it's own.
|
|
env:
|
|
- name: ANSIBLE_INVENTORY_ENABLED
|
|
required: True
|
|
choices: ['tower']
|
|
host:
|
|
description: The network address of your Ansible Tower host.
|
|
type: string
|
|
env:
|
|
- name: TOWER_HOST
|
|
required: True
|
|
username:
|
|
description: The user that you plan to use to access inventories on Ansible Tower.
|
|
type: string
|
|
env:
|
|
- name: TOWER_USERNAME
|
|
required: True
|
|
password:
|
|
description: The password for your Ansible Tower user.
|
|
type: string
|
|
env:
|
|
- name: TOWER_PASSWORD
|
|
required: True
|
|
inventory_id:
|
|
description: The ID of the Ansible Tower inventory that you wish to import.
|
|
type: string
|
|
env:
|
|
- name: TOWER_INVENTORY
|
|
required: True
|
|
validate_certs:
|
|
description: Specify whether Ansible should verify the SSL certificate of Ansible Tower host.
|
|
type: bool
|
|
default: True
|
|
env:
|
|
- name: TOWER_VERIFY_SSL
|
|
required: False
|
|
aliases: [ verify_ssl ]
|
|
include_metadata:
|
|
description: Make extra requests to provide all group vars with metadata about the source Ansible Tower host.
|
|
type: bool
|
|
default: False
|
|
version_added: "2.8"
|
|
'''
|
|
|
|
EXAMPLES = '''
|
|
# Before you execute the following commands, you should make sure this file is in your plugin path,
|
|
# and you enabled this plugin.
|
|
|
|
# Example for using tower_inventory.yml file
|
|
|
|
plugin: tower
|
|
host: your_ansible_tower_server_network_address
|
|
username: your_ansible_tower_username
|
|
password: your_ansible_tower_password
|
|
inventory_id: the_ID_of_targeted_ansible_tower_inventory
|
|
# Then you can run the following command.
|
|
# If some of the arguments are missing, Ansible will attempt to read them from environment variables.
|
|
# ansible-inventory -i /path/to/tower_inventory.yml --list
|
|
|
|
# Example for reading from environment variables:
|
|
|
|
# Set environment variables:
|
|
# export TOWER_HOST=YOUR_TOWER_HOST_ADDRESS
|
|
# export TOWER_USERNAME=YOUR_TOWER_USERNAME
|
|
# export TOWER_PASSWORD=YOUR_TOWER_PASSWORD
|
|
# export TOWER_INVENTORY=THE_ID_OF_TARGETED_INVENTORY
|
|
# Read the inventory specified in TOWER_INVENTORY from Ansible Tower, and list them.
|
|
# The inventory path must always be @tower_inventory if you are reading all settings from environment variables.
|
|
# ansible-inventory -i @tower_inventory --list
|
|
'''
|
|
|
|
import re
|
|
import os
|
|
import json
|
|
from ansible.module_utils import six
|
|
from ansible.module_utils.urls import Request, urllib_error, ConnectionError, socket, httplib
|
|
from ansible.module_utils._text import to_native
|
|
from ansible.errors import AnsibleParserError
|
|
from ansible.plugins.inventory import BaseInventoryPlugin
|
|
|
|
# Python 2/3 Compatibility
|
|
try:
|
|
from urlparse import urljoin
|
|
except ImportError:
|
|
from urllib.parse import urljoin
|
|
|
|
|
|
class InventoryModule(BaseInventoryPlugin):
|
|
NAME = 'tower'
|
|
# Stays backward compatible with tower inventory script.
|
|
# If the user supplies '@tower_inventory' as path, the plugin will read from environment variables.
|
|
no_config_file_supplied = False
|
|
|
|
def make_request(self, request_handler, tower_url):
|
|
"""Makes the request to given URL, handles errors, returns JSON
|
|
"""
|
|
try:
|
|
response = request_handler.get(tower_url)
|
|
except (ConnectionError, urllib_error.URLError, socket.error, httplib.HTTPException) as e:
|
|
error_msg = 'Connection to remote host failed: {err}'.format(err=e)
|
|
# If Tower gives a readable error message, display that message to the user.
|
|
if callable(getattr(e, 'read', None)):
|
|
error_msg += ' with message: {err_msg}'.format(err_msg=e.read())
|
|
raise AnsibleParserError(to_native(error_msg))
|
|
|
|
# Attempt to parse JSON.
|
|
try:
|
|
return json.loads(response.read())
|
|
except (ValueError, TypeError) as e:
|
|
# If the JSON parse fails, print the ValueError
|
|
raise AnsibleParserError(to_native('Failed to parse json from host: {err}'.format(err=e)))
|
|
|
|
def verify_file(self, path):
|
|
if path.endswith('@tower_inventory'):
|
|
self.no_config_file_supplied = True
|
|
return True
|
|
elif super(InventoryModule, self).verify_file(path):
|
|
return path.endswith(('tower_inventory.yml', 'tower_inventory.yaml', 'tower.yml', 'tower.yaml'))
|
|
else:
|
|
return False
|
|
|
|
def parse(self, inventory, loader, path, cache=True):
|
|
super(InventoryModule, self).parse(inventory, loader, path)
|
|
if not self.no_config_file_supplied and os.path.isfile(path):
|
|
self._read_config_data(path)
|
|
# Read inventory from tower server.
|
|
# Note the environment variables will be handled automatically by InventoryManager.
|
|
tower_host = self.get_option('host')
|
|
if not re.match('(?:http|https)://', tower_host):
|
|
tower_host = 'https://{tower_host}'.format(tower_host=tower_host)
|
|
|
|
request_handler = Request(url_username=self.get_option('username'),
|
|
url_password=self.get_option('password'),
|
|
force_basic_auth=True,
|
|
validate_certs=self.get_option('validate_certs'))
|
|
|
|
inventory_id = self.get_option('inventory_id').replace('/', '')
|
|
inventory_url = '/api/v2/inventories/{inv_id}/script/?hostvars=1&towervars=1&all=1'.format(inv_id=inventory_id)
|
|
inventory_url = urljoin(tower_host, inventory_url)
|
|
|
|
inventory = self.make_request(request_handler, inventory_url)
|
|
# To start with, create all the groups.
|
|
for group_name in inventory:
|
|
if group_name != '_meta':
|
|
self.inventory.add_group(group_name)
|
|
|
|
# Then, create all hosts and add the host vars.
|
|
all_hosts = inventory['_meta']['hostvars']
|
|
for host_name, host_vars in six.iteritems(all_hosts):
|
|
self.inventory.add_host(host_name)
|
|
for var_name, var_value in six.iteritems(host_vars):
|
|
self.inventory.set_variable(host_name, var_name, var_value)
|
|
|
|
# Lastly, create to group-host and group-group relationships, and set group vars.
|
|
for group_name, group_content in six.iteritems(inventory):
|
|
if group_name != 'all' and group_name != '_meta':
|
|
# First add hosts to groups
|
|
for host_name in group_content.get('hosts', []):
|
|
self.inventory.add_host(host_name, group_name)
|
|
# Then add the parent-children group relationships.
|
|
for child_group_name in group_content.get('children', []):
|
|
self.inventory.add_child(group_name, child_group_name)
|
|
# Set the group vars. Note we should set group var for 'all', but not '_meta'.
|
|
if group_name != '_meta':
|
|
for var_name, var_value in six.iteritems(group_content.get('vars', {})):
|
|
self.inventory.set_variable(group_name, var_name, var_value)
|
|
|
|
# Fetch extra variables if told to do so
|
|
if self.get_option('include_metadata'):
|
|
config_url = urljoin(tower_host, '/api/v2/config/')
|
|
config_data = self.make_request(request_handler, config_url)
|
|
server_data = {}
|
|
server_data['license_type'] = config_data.get('license_info', {}).get('license_type', 'unknown')
|
|
for key in ('version', 'ansible_version'):
|
|
server_data[key] = config_data.get(key, 'unknown')
|
|
self.inventory.set_variable('all', 'tower_metadata', server_data)
|
|
|
|
# Clean up the inventory.
|
|
self.inventory.reconcile_inventory()
|