Properties are read under a caller-supplied prefix (audit destination example): + *
+ * xasecure.audit.destination.auditserver.authn.header.enabled=true + * xasecure.audit.destination.auditserver.authn.header.spiffe=X-Spiffe-Id + *+ * SPIFFE ID value is resolved via {@link SpiffeIdentityResolver} under the same + * prefix (explicit value, identity file, or {@code SPIFFE_ID} environment variable). + */ +public final class PluginHeaderAuthConfig { + public static final String PROP_HEADER_AUTH_ENABLED = "authn.header.enabled"; + public static final String PROP_HEADER_SPIFFE = "authn.header.spiffe"; + public static final String DEFAULT_SPIFFE_HEADER_NAME = "X-Spiffe-Id"; + + private static final Logger LOG = + LoggerFactory.getLogger(PluginHeaderAuthConfig.class); + + 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) { + if (props == null || StringUtils.isBlank(configPrefix)) { + return false; + } + + return Boolean.parseBoolean( + props.getProperty(configPrefix + "." + PROP_HEADER_AUTH_ENABLED, + "false")); + } + + /** + * Builds SPIFFE header(s) 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
Resolution order: explicit {@code authn.spiffe.value}, identity file
+ * ({@code authn.spiffe.file} or the default SPIRE path), then {@code SPIFFE_ID}
+ * environment variable.
+ */
+public final class SpiffeIdentityResolver {
+ public static final String PROP_SPIFFE_VALUE = "authn.spiffe.value";
+ public static final String PROP_SPIFFE_FILE = "authn.spiffe.file";
+ public static final String ENV_SPIFFE_ID = "SPIFFE_ID";
+ public static final String DEFAULT_SPIFFE_IDENTITY_FILE =
+ "/var/run/secrets/spiffe.io/identity/spiffe";
+
+ private static final Logger LOG =
+ LoggerFactory.getLogger(SpiffeIdentityResolver.class);
+
+ private SpiffeIdentityResolver() {
+ // to block instantiation
+ }
+
+ /**
+ * Resolves the SPIFFE ID for the given config prefix.
+ *
+ * @param props plugin or site configuration properties
+ * @param configPrefix prefix such as {@code ranger.hive}
+ * @return the resolved SPIFFE ID, or {@code null} when unavailable
+ */
+ public static String resolve(final Properties props, final String configPrefix) {
+ if (props == null || StringUtils.isBlank(configPrefix)) {
+ return null;
+ }
+
+ String value = StringUtils.trimToNull(
+ props.getProperty(configPrefix + "." + PROP_SPIFFE_VALUE));
+
+ if (value != null) {
+ return value;
+ }
+
+ String filePath = StringUtils.trimToNull(
+ props.getProperty(configPrefix + "." + PROP_SPIFFE_FILE));
+
+ if (filePath == null) {
+ filePath = DEFAULT_SPIFFE_IDENTITY_FILE;
+ }
+
+ value = readFirstLine(filePath);
+
+ if (value != null) {
+ return value;
+ }
+
+ return StringUtils.trimToNull(System.getenv(ENV_SPIFFE_ID));
+ }
+
+ private static String readFirstLine(final String filePath) {
+ if (StringUtils.isBlank(filePath)) {
+ return null;
+ }
+
+ try {
+ Path path = Paths.get(filePath.trim());
+
+ if (!Files.isRegularFile(path)) {
+ return null;
+ }
+
+ List