mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-21 00:01:08 +00:00
etcd3 lookup - improve HTTPS connection handling and docs (#11861)
* etcd3 lookup - improve HTTPS connection handling and documentation Improve user experience when connecting to HTTPS etcd3 endpoints: - Strip URL scheme from host option when present, with a warning - Warn when HTTPS endpoint is specified but ca_cert is not provided - Document that ca_cert is required to enable TLS - Add HTTPS connection example - Fix minor doc markup issue in notes section Fixes #1664 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add changelog fragment for PR 11861 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
6
changelogs/fragments/11861-etcd3-lookup-https.yml
Normal file
6
changelogs/fragments/11861-etcd3-lookup-https.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
bugfixes:
|
||||
- >-
|
||||
etcd3 lookup plugin - improve HTTPS endpoint handling by stripping URL schemes from the ``host`` option
|
||||
and warning when ``ca_cert`` is not provided for HTTPS endpoints
|
||||
(https://github.com/ansible-collections/community.general/issues/1664,
|
||||
https://github.com/ansible-collections/community.general/pull/11861).
|
||||
@@ -34,6 +34,8 @@ options:
|
||||
V(https://hostname:2379), or V(<host>:<port>) form.
|
||||
- The V(host) part is overwritten by O(host) option, if defined.
|
||||
- The V(port) part is overwritten by O(port) option, if defined.
|
||||
- Note that specifying V(https://) in the endpoint URL does not by itself enable TLS. To connect to an HTTPS etcd3
|
||||
endpoint, you must provide O(ca_cert) (and optionally O(cert_cert) and O(cert_key)).
|
||||
env:
|
||||
- name: ETCDCTL_ENDPOINTS
|
||||
default: '127.0.0.1:2379'
|
||||
@@ -42,6 +44,8 @@ options:
|
||||
description:
|
||||
- Etcd3 listening client host.
|
||||
- Takes precedence over O(endpoints).
|
||||
- Must be a bare hostname or IP address without a URL scheme. If a V(https://) or V(http://) prefix is present,
|
||||
it will be stripped automatically.
|
||||
type: str
|
||||
port:
|
||||
description:
|
||||
@@ -51,6 +55,7 @@ options:
|
||||
ca_cert:
|
||||
description:
|
||||
- Etcd3 CA authority.
|
||||
- Required to enable TLS when connecting to an HTTPS etcd3 endpoint.
|
||||
env:
|
||||
- name: ETCDCTL_CACERT
|
||||
type: str
|
||||
@@ -87,9 +92,11 @@ options:
|
||||
type: str
|
||||
|
||||
notes:
|
||||
- O(host) and O(port) options take precedence over (endpoints) option.
|
||||
- O(host) and O(port) options take precedence over O(endpoints) option.
|
||||
- The recommended way to connect to etcd3 server is using E(ETCDCTL_ENDPOINT) environment variable and keep O(endpoints),
|
||||
O(host), and O(port) unused.
|
||||
- To connect to an HTTPS etcd3 endpoint, the O(ca_cert) option must be provided. Merely specifying V(https://) in
|
||||
O(endpoints) is not sufficient to enable TLS.
|
||||
seealso:
|
||||
- module: community.general.etcd3
|
||||
- plugin: community.general.etcd
|
||||
@@ -115,6 +122,10 @@ EXAMPLES = r"""
|
||||
- name: "connect to etcd3 with a client certificate"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ lookup('community.general.etcd3', 'foo/bar', cert_cert='/etc/ssl/etcd/client.pem', cert_key='/etc/ssl/etcd/client.key') }}"
|
||||
|
||||
- name: "connect to etcd3 over HTTPS"
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ lookup('community.general.etcd3', 'foo/bar', endpoints='https://etcd.example.com:2379', ca_cert='/etc/ssl/etcd/ca.pem') }}"
|
||||
"""
|
||||
|
||||
RETURN = r"""
|
||||
@@ -185,19 +196,42 @@ class LookupModule(LookupBase):
|
||||
# etcd3 class expects host and port as connection parameters, so endpoints
|
||||
# must be mangled a bit to fit in this scheme.
|
||||
# so here we use a regex to extract server and port
|
||||
is_https = False
|
||||
match = re.compile(
|
||||
r"^(https?://)?(?P<host>(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|([-_\d\w\.]+))(:(?P<port>\d{1,5}))?/?$"
|
||||
r"^(?P<scheme>https?://)?(?P<host>(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|([-_\d\w\.]+))(:(?P<port>\d{1,5}))?/?$"
|
||||
).match(self.get_option("endpoints"))
|
||||
if match:
|
||||
if match.group("host"):
|
||||
client_params["host"] = match.group("host")
|
||||
if match.group("port"):
|
||||
client_params["port"] = match.group("port")
|
||||
if match.group("scheme") and match.group("scheme").startswith("https"):
|
||||
is_https = True
|
||||
|
||||
for opt in etcd3_cnx_opts:
|
||||
if self.get_option(opt):
|
||||
client_params[opt] = self.get_option(opt)
|
||||
|
||||
# strip URL scheme from host if present
|
||||
if "host" in client_params:
|
||||
host_match = re.match(r"^(?P<scheme>https?://)(?P<host>.+)$", client_params["host"])
|
||||
if host_match:
|
||||
display.warning(
|
||||
f"The host option contained a URL scheme '{host_match.group('scheme')}' which has been removed. "
|
||||
"Use a bare hostname or IP address for the host option. "
|
||||
"To enable TLS, provide the ca_cert option."
|
||||
)
|
||||
client_params["host"] = host_match.group("host")
|
||||
if host_match.group("scheme").startswith("https"):
|
||||
is_https = True
|
||||
|
||||
if is_https and not self.get_option("ca_cert"):
|
||||
display.warning(
|
||||
"An HTTPS endpoint was specified but ca_cert was not provided. "
|
||||
"The connection will be attempted without TLS. "
|
||||
"To enable TLS, provide the ca_cert option."
|
||||
)
|
||||
|
||||
cnx_log = dict(client_params)
|
||||
if "password" in cnx_log:
|
||||
cnx_log["password"] = "<redacted>"
|
||||
|
||||
Reference in New Issue
Block a user