This is an automated email from the ASF dual-hosted git repository.

ramackri pushed a commit to branch RANGER-5723-spiffe-audit-destination-2.10
in repository https://gitbox.apache.org/repos/asf/ranger.git

commit 2b78958ce89bab97b0dc9249025bcc0a9d574f68
Author: ramk <[email protected]>
AuthorDate: Mon Nov 2 08:32:24 2026 +0530

    RANGER-5723: Backport SPIFFE outbound auth for audit-server destination 
(2.10)
    
    Cherry-pick/adapt master 8e7716cd for ranger-2.10: PluginHeaderAuthConfig,
    RangerRESTClient trusted headers (Jersey 1.x ClientFilter), and audit 
destination wiring.
    Preserves JWT DefaultTokenSupplier on 2.10.
---
 agents-audit/dest-auditserver/pom.xml              |   6 +
 .../destination/RangerAuditServerDestination.java  |  11 ++
 .../RangerAuditServerDestinationTest.java          |  56 +++++++
 .../ranger/plugin/util/RangerRESTClient.java       |  35 +++++
 .../ranger/plugin/util/TestRangerRESTClient.java   |  43 ++++++
 .../ranger/plugin/util/PluginHeaderAuthConfig.java | 166 +++++++++++++++++++++
 .../plugin/util/PluginHeaderAuthConfigTest.java    |  92 ++++++++++++
 7 files changed, 409 insertions(+)

diff --git a/agents-audit/dest-auditserver/pom.xml 
b/agents-audit/dest-auditserver/pom.xml
index 8ae78d940..0b42f4594 100644
--- a/agents-audit/dest-auditserver/pom.xml
+++ b/agents-audit/dest-auditserver/pom.xml
@@ -54,6 +54,12 @@
         </dependency>
 
         <!-- Test -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>${junit.jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>log4j-over-slf4j</artifactId>
diff --git 
a/agents-audit/dest-auditserver/src/main/java/org/apache/ranger/audit/destination/RangerAuditServerDestination.java
 
b/agents-audit/dest-auditserver/src/main/java/org/apache/ranger/audit/destination/RangerAuditServerDestination.java
index a46f8f5c7..93a75f7a3 100644
--- 
a/agents-audit/dest-auditserver/src/main/java/org/apache/ranger/audit/destination/RangerAuditServerDestination.java
+++ 
b/agents-audit/dest-auditserver/src/main/java/org/apache/ranger/audit/destination/RangerAuditServerDestination.java
@@ -29,6 +29,7 @@
 import org.apache.ranger.audit.model.AuthzAuditEvent;
 import org.apache.ranger.audit.provider.MiscUtil;
 import org.apache.ranger.plugin.authn.DefaultTokenSupplier;
+import org.apache.ranger.plugin.util.PluginHeaderAuthConfig;
 import org.apache.ranger.plugin.util.RangerRESTClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -98,6 +99,16 @@ public void init(Properties props, String propPrefix) {
         this.restClient.setMaxRetryAttempts(maxRetryAttempts);
         this.restClient.setRetryIntervalMs(retryIntervalMs);
 
+        // Trusted header auth is orthogonal to authn.type 
(JWT/Basic/Kerberos): when enabled,
+        // trusted headers are added in addition to whatever authType 
configured above.
+        Map<String, String> trustedHeaders = 
PluginHeaderAuthConfig.buildTrustedAuthHeaders(props, propPrefix);
+
+        if (!trustedHeaders.isEmpty()) {
+            this.restClient.setTrustedAuthHeaders(trustedHeaders);
+
+            LOG.debug("Trusted authentication headers added for audit-server 
destination");
+        }
+
         LOG.info("<== RangerAuditServerDestination:init()");
     }
 
diff --git 
a/agents-audit/dest-auditserver/src/test/java/org/apache/ranger/audit/destination/RangerAuditServerDestinationTest.java
 
b/agents-audit/dest-auditserver/src/test/java/org/apache/ranger/audit/destination/RangerAuditServerDestinationTest.java
new file mode 100644
index 000000000..4ba059e3f
--- /dev/null
+++ 
b/agents-audit/dest-auditserver/src/test/java/org/apache/ranger/audit/destination/RangerAuditServerDestinationTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.audit.destination;
+
+import org.apache.ranger.plugin.util.PluginHeaderAuthConfig;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+import java.util.Properties;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class RangerAuditServerDestinationTest {
+    private static final String AUDIT_DEST_PREFIX = 
"xasecure.audit.destination.auditserver";
+
+    @Test
+    public void buildTrustedAuthHeadersUsesAuditDestinationPrefix() {
+        Properties props = new Properties();
+
+        props.setProperty(AUDIT_DEST_PREFIX + ".authn.header.enabled", "true");
+        props.setProperty(AUDIT_DEST_PREFIX + ".authn.header.X-Spiffe-Id", 
"spiffe://prod-cluster.k8s.example.com/ns/ranger/sa/hive");
+
+        Map<String, String> headers = 
PluginHeaderAuthConfig.buildTrustedAuthHeaders(props, AUDIT_DEST_PREFIX);
+
+        assertEquals(1, headers.size());
+        
assertEquals("spiffe://prod-cluster.k8s.example.com/ns/ranger/sa/hive", 
headers.get("X-Spiffe-Id"));
+    }
+
+    @Test
+    public void buildTrustedAuthHeadersEmptyWhenAuditDestinationDisabled() {
+        Properties props = new Properties();
+
+        props.setProperty(AUDIT_DEST_PREFIX + ".authn.header.enabled", 
"false");
+        props.setProperty(AUDIT_DEST_PREFIX + ".authn.header.X-Spiffe-Id", 
"spiffe://prod-cluster.k8s.example.com/ns/ranger/sa/hive");
+
+        Map<String, String> headers = 
PluginHeaderAuthConfig.buildTrustedAuthHeaders(props, AUDIT_DEST_PREFIX);
+
+        assertTrue(headers.isEmpty());
+    }
+}
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
index 4830bbfed..4438e87e8 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java
@@ -33,6 +33,8 @@
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
 import java.util.Base64;
+import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
@@ -122,7 +124,9 @@ public class RangerRESTClient {
        private volatile Supplier<String> tokenSupplier;
        private          ClientFilter jwtAuthFilter;
        private          ClientFilter basicAuthFilter;
+       private          ClientFilter trustedAuthFilter;
        private volatile String       basicAuthHeader;
+       private volatile Map<String, String> trustedAuthHeaders = 
Collections.emptyMap();
 
        public RangerRESTClient(String url, String sslConfigFileName, 
Configuration config) {
                this(url, sslConfigFileName, config, getPropertyPrefix(config));
@@ -187,6 +191,33 @@ public void setRestClientReadTimeOutMs(int 
mRestClientReadTimeOutMs) {
 
        public void setRetryIntervalMs(int retryIntervalMs) { 
this.retryIntervalMs = retryIntervalMs; }
 
+       /**
+        * Trusted HTTP headers for SPIFFE or other header-based auth.
+        * Applied to every REST request from this client.
+        */
+       public void setTrustedAuthHeaders(Map<String, String> headers) {
+               if (headers == null || headers.isEmpty()) {
+                       trustedAuthHeaders = Collections.emptyMap();
+                       trustedAuthFilter  = null;
+               } else {
+                       trustedAuthHeaders = Collections.unmodifiableMap(new 
LinkedHashMap<>(headers));
+
+                       final Map<String, String> headersToSend = 
trustedAuthHeaders;
+
+                       trustedAuthFilter = new ClientFilter() {
+                               @Override
+                               public ClientResponse handle(ClientRequest 
clientRequest) throws ClientHandlerException {
+                                       for (Map.Entry<String, String> entry : 
headersToSend.entrySet()) {
+                                               
clientRequest.getHeaders().add(entry.getKey(), entry.getValue());
+                                       }
+
+                                       return getNext().handle(clientRequest);
+                               }
+                       };
+               }
+               resetClient();
+       }
+
        public void setBasicAuthInfo(String username, String password) {
                mUsername = username;
                mPassword = password;
@@ -293,6 +324,10 @@ private Client buildClient() {
                        client.addFilter(authFilter);
                }
 
+               if (trustedAuthFilter != null && 
!client.isFilterPresent(trustedAuthFilter)) {
+                       client.addFilter(trustedAuthFilter);
+               }
+
                // Set Connection Timeout and ReadTime for the PolicyRefresh
                client.setConnectTimeout(mRestClientConnTimeOutMs);
                client.setReadTimeout(mRestClientReadTimeOutMs);
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/util/TestRangerRESTClient.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/util/TestRangerRESTClient.java
index 2ab5b7eb5..12eab693f 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/util/TestRangerRESTClient.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/util/TestRangerRESTClient.java
@@ -29,7 +29,9 @@
 
 import java.net.InetSocketAddress;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Supplier;
 
@@ -43,6 +45,7 @@ public class TestRangerRESTClient {
     private static final String SERVICE_NAME = "test-service";
     private static final String APP_ID = "test-app";
     private static final String ERR_MESSAGE = "Ranger URL is null or empty.";
+    private static final String VALID_SPIFFE  = 
"spiffe://example.org/ns/default/sa/default";
 
     @Test
     public void testPluginInit_WithNoUrl_ThrowsException() {
@@ -71,6 +74,46 @@ public void tokenSupplierWithoutTokenFallsBackToBasicAuth() 
throws Exception {
         assertEquals("Basic dXNlcjE6cGFzc3dvcmQx", captureAuthHeader(() -> 
null, "user1", "password1"));
     }
 
+    @Test
+    public void setTrustedAuthHeadersAddsHeaderToOutboundRequest() throws 
Exception {
+        AtomicReference<String> capturedSpiffeHeader = new AtomicReference<>();
+        HttpServer              httpServer           = HttpServer.create(new 
InetSocketAddress(0), 0);
+
+        httpServer.createContext("/", exchange -> {
+            List<String> values = 
exchange.getRequestHeaders().get("X-Spiffe-Id");
+
+            if (values != null && !values.isEmpty()) {
+                capturedSpiffeHeader.set(values.get(0));
+            }
+
+            exchange.sendResponseHeaders(200, -1);
+            exchange.close();
+        });
+
+        httpServer.start();
+
+        try {
+            String              serverUrl = "http://localhost:"; + 
httpServer.getAddress().getPort();
+            Configuration       conf      = new Configuration();
+            RangerRESTClient    client    = new RangerRESTClient(serverUrl, 
null, conf);
+            Map<String, String> headers   = new LinkedHashMap<>();
+
+            headers.put("X-Spiffe-Id", VALID_SPIFFE);
+            client.setTrustedAuthHeaders(headers);
+
+            ClientResponse response = client.get("/test", 
Collections.emptyMap());
+            try {
+                assertEquals(200, response.getStatus());
+            } finally {
+                response.close();
+            }
+
+            assertEquals(VALID_SPIFFE, capturedSpiffeHeader.get());
+        } finally {
+            httpServer.stop(0);
+        }
+    }
+
     private String captureAuthHeader(Supplier<String> tokenSupplier, String 
username, String password) throws Exception {
         AtomicReference<String> capturedAuthHeader = new AtomicReference<>();
         HttpServer              httpServer         = HttpServer.create(new 
InetSocketAddress(0), 0);
diff --git 
a/common-utils/src/main/java/org/apache/ranger/plugin/util/PluginHeaderAuthConfig.java
 
b/common-utils/src/main/java/org/apache/ranger/plugin/util/PluginHeaderAuthConfig.java
new file mode 100644
index 000000000..a96a81fa9
--- /dev/null
+++ 
b/common-utils/src/main/java/org/apache/ranger/plugin/util/PluginHeaderAuthConfig.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Outbound trusted-header auth for audit-server and other REST clients.
+ *
+ * <p>When {@code authn.header.enabled=true}, trusted HTTP headers are added 
to every
+ * outbound REST request. Each header is configured as a property whose name 
is the
+ * HTTP header name under {@code authn.header} (audit destination example):
+ * <pre>
+ * xasecure.audit.destination.auditserver.authn.header.enabled=true
+ * 
xasecure.audit.destination.auditserver.authn.header.X-Spiffe-Id=file:/path/to/spiffe-id.file
+ * # valid value specs:
+ * #   file:/path/to/spiffe-id.file
+ * #   env:SPIFFE_ID
+ * #   spiffe://trust-domain/ns/.../sa/...  (literal string)
+ * </pre>
+ */
+public final class PluginHeaderAuthConfig {
+    private static final Logger LOG = 
LoggerFactory.getLogger(PluginHeaderAuthConfig.class);
+
+    public static final String PROP_HEADER_PREFIX       = "authn.header.";
+    public static final String PROP_HEADER_AUTH_ENABLED = PROP_HEADER_PREFIX + 
"enabled";
+
+    private static final String VALUE_PREFIX_FILE = "file:";
+    private static final String VALUE_PREFIX_ENV  = "env:";
+
+    private PluginHeaderAuthConfig() {
+        // to block instantiation
+    }
+
+    /**
+     * Returns whether trusted header auth is enabled for the given config 
prefix.
+     *
+     * @param props        plugin or site configuration properties
+     * @param configPrefix property prefix for header-auth settings
+     * @return {@code true} when header auth is enabled
+     */
+    public static boolean isHeaderAuthEnabled(final Properties props, final 
String configPrefix) {
+        return props != null && StringUtils.isNotBlank(configPrefix) && 
Boolean.parseBoolean(props.getProperty(configPrefix + "." + 
PROP_HEADER_AUTH_ENABLED, "false"));
+    }
+
+    /**
+     * Builds trusted HTTP headers for outbound REST calls when header auth is 
enabled.
+     *
+     * @param props        plugin or site configuration properties
+     * @param configPrefix prefix such as {@code 
xasecure.audit.destination.auditserver}
+     * @return immutable header map; empty when auth is disabled or 
misconfigured
+     */
+    public static Map<String, String> buildTrustedAuthHeaders(final Properties 
props, final String configPrefix) {
+        final Map<String, String> ret;
+
+        if (isHeaderAuthEnabled(props, configPrefix)) {
+            String              propertyPrefix = configPrefix + "." + 
PROP_HEADER_PREFIX;
+            Map<String, String> headers        = new LinkedHashMap<>();
+
+            for (String propertyName : props.stringPropertyNames()) {
+                if (!propertyName.startsWith(propertyPrefix)) {
+                    continue;
+                }
+
+                String headerName = 
propertyName.substring(propertyPrefix.length());
+
+                if (StringUtils.isBlank(headerName) || 
"enabled".equals(headerName)) {
+                    continue;
+                }
+
+                String headerValue = 
resolveConfiguredValue(props.getProperty(propertyName));
+
+                addConfiguredHeader(headers, configPrefix, headerName, 
headerValue);
+            }
+
+            if (headers.isEmpty()) {
+                LOG.warn("Plugin header auth enabled for {} but no trusted 
headers could be resolved", configPrefix);
+            }
+
+            ret = Collections.unmodifiableMap(headers);
+        } else {
+            ret = Collections.emptyMap();
+        }
+
+        return ret;
+    }
+
+    private static void addConfiguredHeader(final Map<String, String> headers, 
final String configPrefix, final String headerName, final String headerValue) {
+        if (StringUtils.isBlank(headerValue)) {
+            LOG.warn("Plugin header auth enabled for {} but trusted header {} 
has no resolvable value", configPrefix, headerName);
+        } else {
+            headers.put(headerName, headerValue);
+        }
+    }
+
+    private static String resolveConfiguredValue(final String valueSpec) {
+        final String ret;
+
+        if (StringUtils.isBlank(valueSpec)) {
+            ret = null;
+        } else if (valueSpec.startsWith(VALUE_PREFIX_FILE)) {
+            ret = 
readFirstNonBlankLine(valueSpec.substring(VALUE_PREFIX_FILE.length()));
+        } else if (valueSpec.startsWith(VALUE_PREFIX_ENV)) {
+            ret = 
StringUtils.trimToNull(System.getenv(valueSpec.substring(VALUE_PREFIX_ENV.length())));
+        } else {
+            ret = StringUtils.trimToNull(valueSpec);
+        }
+
+        return ret;
+    }
+
+    private static String readFirstNonBlankLine(final String filePath) {
+        String ret = null;
+
+        if (StringUtils.isNotBlank(filePath)) {
+            try {
+                Path path = Paths.get(filePath.trim());
+
+                if (Files.isRegularFile(path)) {
+                    for (String line : Files.readAllLines(path, 
StandardCharsets.UTF_8)) {
+                        String trimmed = StringUtils.trimToNull(line);
+
+                        if (trimmed != null) {
+                            ret = trimmed;
+
+                            break;
+                        }
+                    }
+                }
+            } catch (IOException ex) {
+                LOG.debug("Unable to read trusted header value from file {}", 
filePath, ex);
+            }
+        }
+
+        return ret;
+    }
+}
diff --git 
a/common-utils/src/test/java/org/apache/ranger/plugin/util/PluginHeaderAuthConfigTest.java
 
b/common-utils/src/test/java/org/apache/ranger/plugin/util/PluginHeaderAuthConfigTest.java
new file mode 100644
index 000000000..9cc892a2e
--- /dev/null
+++ 
b/common-utils/src/test/java/org/apache/ranger/plugin/util/PluginHeaderAuthConfigTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ranger.plugin.util;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class PluginHeaderAuthConfigTest {
+    private static final String VALID_SPIFFE =
+            "spiffe://prod-cluster.k8s.example.com/ns/ranger/sa/om";
+
+    @Test
+    public void buildTrustedAuthHeadersUsesLiteralHeaderValue() {
+        Properties props = new Properties();
+        props.setProperty("ranger.ozone.authn.header.enabled", "true");
+        props.setProperty("ranger.ozone.authn.header.X-Spiffe-Id", 
VALID_SPIFFE);
+
+        Map<String, String> headers = 
PluginHeaderAuthConfig.buildTrustedAuthHeaders(props, "ranger.ozone");
+
+        assertEquals(VALID_SPIFFE, headers.get("X-Spiffe-Id"));
+    }
+
+    @Test
+    public void buildTrustedAuthHeadersUsesFileValueSpec(@TempDir Path 
tempDir) throws Exception {
+        Path spiffeFile = tempDir.resolve("spiffe");
+        Files.write(spiffeFile, (VALID_SPIFFE + 
"\n").getBytes(StandardCharsets.UTF_8));
+
+        Properties props = new Properties();
+        props.setProperty("ranger.ozone.authn.header.enabled", "true");
+        props.setProperty("ranger.ozone.authn.header.X-Spiffe-Id", "file:" + 
spiffeFile);
+
+        Map<String, String> headers = 
PluginHeaderAuthConfig.buildTrustedAuthHeaders(props, "ranger.ozone");
+
+        assertEquals(VALID_SPIFFE, headers.get("X-Spiffe-Id"));
+    }
+
+    @Test
+    public void buildTrustedAuthHeadersEmptyWhenDisabled() {
+        Properties props = new Properties();
+        props.setProperty("ranger.ozone.authn.header.enabled", "false");
+        props.setProperty("ranger.ozone.authn.header.X-Spiffe-Id", 
VALID_SPIFFE);
+
+        assertTrue(PluginHeaderAuthConfig.buildTrustedAuthHeaders(props, 
"ranger.ozone").isEmpty());
+    }
+
+    @Test
+    public void isHeaderAuthEnabledFalseForMissingPrefix() {
+        assertFalse(PluginHeaderAuthConfig.isHeaderAuthEnabled(new 
Properties(), "ranger.ozone"));
+    }
+
+    @Test
+    public void buildTrustedAuthHeadersEmptyWhenNoHeadersConfigured() {
+        Properties props = new Properties();
+        props.setProperty("ranger.ozone.authn.header.enabled", "true");
+
+        assertTrue(PluginHeaderAuthConfig.buildTrustedAuthHeaders(props, 
"ranger.ozone").isEmpty());
+    }
+
+    @Test
+    public void buildTrustedAuthHeadersEmptyWhenSpiffeIdUnresolved() {
+        Properties props = new Properties();
+        props.setProperty("ranger.ozone.authn.header.enabled", "true");
+        props.setProperty("ranger.ozone.authn.header.X-Spiffe-Id", 
"env:UNSET_SPIFFE_ID_VAR");
+
+        assertTrue(PluginHeaderAuthConfig.buildTrustedAuthHeaders(props, 
"ranger.ozone").isEmpty());
+    }
+}

Reply via email to