diff --git a/RHEL-193739-fence_vmware_rest-add-token-based-authentication.patch b/RHEL-193739-fence_vmware_rest-add-token-based-authentication.patch new file mode 100644 index 0000000..824e5d8 --- /dev/null +++ b/RHEL-193739-fence_vmware_rest-add-token-based-authentication.patch @@ -0,0 +1,171 @@ +From 1a943d5c131ae65b01bdd44a816f3903cb878b87 Mon Sep 17 00:00:00 2001 +From: Arslan Ahmad +Date: Wed, 8 Jul 2026 21:51:53 +0530 +Subject: [PATCH] fence_vmware_rest: add token-based authentication support + +This introduces `--token` and `--token-script` parameters to allow secure, +passwordless authentication with the vCenter REST API. This avoids the +need to store static passwords or short-lived session IDs in the cluster +configuration. + + - Adds dynamic bypass of core credential validation when a token is used. + - Adds a `fail_usage` check if neither authentication method is provided. + - Streamlines `connect()` to cleanly handle both token and credential +workflows. + +Signed-off-by: Arslan Ahmad +--- + agents/vmware_rest/fence_vmware_rest.py | 49 ++++++++++++++++++----- + tests/data/metadata/fence_vmware_rest.xml | 14 ++++++- + 2 files changed, 51 insertions(+), 12 deletions(-) + +diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py +index 9dc9a12f4..fb9d42861 100644 +--- a/agents/vmware_rest/fence_vmware_rest.py ++++ b/agents/vmware_rest/fence_vmware_rest.py +@@ -6,7 +6,7 @@ + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") + from fencing import * +-from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS ++from fencing import fail, fail_usage, run_command, run_delay, EC_LOGIN_DENIED, EC_STATUS + + if sys.version_info[0] > 2: import urllib.parse as urllib + else: import urllib +@@ -69,6 +69,8 @@ def get_list(conn, options): + return outlets + + def connect(opt): ++ if "--token" not in opt and ("--username" not in opt or "--password" not in opt): ++ fail_usage("Failed: You must provide either a token, a token-script, or a username/password.") + conn = pycurl.Curl() + + ## setup correct URL +@@ -88,9 +90,6 @@ def connect(opt): + "Accept: application/json", + ]) + +- conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC) +- conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"]) +- + conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"])) + + if "--ssl-secure" in opt: +@@ -100,16 +99,22 @@ def connect(opt): + conn.setopt(pycurl.SSL_VERIFYPEER, 0) + conn.setopt(pycurl.SSL_VERIFYHOST, 0) + +- try: +- result = send_command(conn, "com/vmware/cis/session", "POST") +- except Exception as e: +- logging.debug("Failed: {}".format(e)) +- fail(EC_LOGIN_DENIED) ++ if "--token" not in opt: ++ conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC) ++ conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"]) ++ ++ try: ++ result = send_command(conn, "com/vmware/cis/session", "POST") ++ except Exception as e: ++ logging.debug("Failed: {}".format(e)) ++ fail(EC_LOGIN_DENIED) ++ ++ conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_NONE) + + # set session id for later requests + conn.setopt(pycurl.HTTPHEADER, [ + "Accept: application/json", +- "vmware-api-session-id: {}".format(result["value"]), ++ "vmware-api-session-id: {}".format(opt["--token"] if "--token" in opt else result["value"]), + ]) + + return conn +@@ -182,6 +187,20 @@ def define_new_opts(): + "shortdesc" : "Filter to only return relevant VMs. It can be used to avoid " + "the agent failing when more than 1000 VMs should be returned.", + "order" : 2} ++ all_opt["token"] = { ++ "getopt" : ":", ++ "longopt" : "token", ++ "help" : "--token=[token] API Token", ++ "required" : "0", ++ "shortdesc" : "API Token", ++ "order" : 2} ++ all_opt["token_script"] = { ++ "getopt" : ":", ++ "longopt" : "token-script", ++ "help" : "--token-script=[script] Script to retrieve a token", ++ "required" : "0", ++ "shortdesc" : "Script to retrieve a token", ++ "order" : 2} + + + def main(): +@@ -190,11 +209,15 @@ def main(): + "api_path", + "login", + "passwd", ++ "no_login", ++ "no_password", + "ssl", + "notls", + "web", + "port", + "filter", ++ "token", ++ "token_script", + ] + + atexit.register(atexit_handler) +@@ -204,6 +227,12 @@ def main(): + all_opt["power_wait"]["default"] = "1" + + options = check_input(device_opt, process_input(device_opt)) ++ if "--token-script" in options: ++ try: ++ options["--token"] = run_command(options, options["--token-script"])[1].strip() ++ except Exception as e: ++ logging.error("Failed to execute token script: {}".format(e)) ++ sys.exit(EC_LOGIN_DENIED) + + docs = {} + docs["shortdesc"] = "Fence agent for VMware REST API" +diff --git a/tests/data/metadata/fence_vmware_rest.xml b/tests/data/metadata/fence_vmware_rest.xml +index 672769d99..72fc22533 100644 +--- a/tests/data/metadata/fence_vmware_rest.xml ++++ b/tests/data/metadata/fence_vmware_rest.xml +@@ -25,7 +25,7 @@ NOTE: If there's more than 1000 VMs there is a filter parameter to work around t + + TCP/UDP port to use for connection with device + +- ++ + + + Login name +@@ -80,7 +80,7 @@ NOTE: If there's more than 1000 VMs there is a filter parameter to work around t + + Use SSL connection with verifying certificate + +- ++ + + + Login name +@@ -94,6 +94,16 @@ NOTE: If there's more than 1000 VMs there is a filter parameter to work around t + + Filter to only return relevant VMs. It can be used to avoid the agent failing when more than 1000 VMs should be returned. + ++ ++ ++ ++ API Token ++ ++ ++ ++ ++ Script to retrieve a token ++ + + + diff --git a/fence-agents.spec b/fence-agents.spec index a452fee..7117fbc 100644 --- a/fence-agents.spec +++ b/fence-agents.spec @@ -47,7 +47,7 @@ Name: fence-agents Summary: Set of unified programs capable of host isolation ("fencing") Version: 4.10.0 -Release: 116%{?alphatag:.%{alphatag}}%{?dist} +Release: 117%{?alphatag:.%{alphatag}}%{?dist} License: GPLv2+ and LGPLv2+ URL: https://github.com/ClusterLabs/fence-agents Source0: https://fedorahosted.org/releases/f/e/fence-agents/%{name}-%{version}.tar.gz @@ -221,6 +221,7 @@ Patch76: RHEL-145088-fence_ibm_vpc-fix-missing-statuses.patch Patch77: RHEL-146216-fence_kubevirt-report-Succeeded-and-Failed-as-OFF.patch Patch78: RHEL-183892-fence_ibm_vpc-set-proxy-when-token-is-expired-as-well.patch Patch79: RHEL-154985-fence_openstack-fix-list-action-to-avoid-timeout-with-large-number-of-VMs.patch +Patch80: RHEL-193739-fence_vmware_rest-add-token-based-authentication.patch ### HA support libs/utils ### # all archs @@ -424,6 +425,7 @@ BuildRequires: %{systemd_units} %patch -p1 -P 77 %patch -p1 -P 78 %patch -p1 -P 79 +%patch -p1 -P 80 # prevent compilation of something that won't get used anyway sed -i.orig 's|FENCE_ZVM=1|FENCE_ZVM=0|' configure.ac @@ -1522,6 +1524,10 @@ are located on corosync cluster nodes. %endif %changelog +* Thu Jul 09 2026 Arslan Ahmad - 4.10.0-117 +- fence_vmware_rest: add token-based authentication + Resolves: RHEL-193739 + * Wed Jun 17 2026 Arslan Ahmad - 4.10.0-116 - fence_openstack: fix list-action to avoid timeout when there are 100+ VMs on the hypervisor