From 048ad8560c5e41798241ff4b7e68b67f5252130e Mon Sep 17 00:00:00 2001 From: d-velev Date: Wed, 28 Oct 2026 17:57:49 +0200 Subject: [PATCH] commons-config: refuse a non-Base64 basic credential at startup, naming the variable (#8227) DIRIGIBLE_BASIC_USERNAME/PASSWORD are Base64-decoded, so the plain-text values the docs show aborted boot with a bare `IllegalArgumentException` ("Illegal base64 character" / "Last unit does not have enough valid bits") that named neither the variable nor the expected encoding. getFromBase64Value() now catches the decoder error and rethrows InvalidConfigException naming the key and the Base64 requirement, with a remedy - the same way DIRIGIBLE_SECURITY_HSTS is refused. CLAUDE_FEATURES.md documents the Base64 requirement. Note: a plain value that happens to be valid Base64 is still decoded silently - that is inherent to the encoding and cannot be distinguished from an intended Base64 value. Co-Authored-By: Claude Opus 4.8 --- CLAUDE_FEATURES.md | 2 +- .../commons/config/DirigibleConfig.java | 12 +++- .../config/DirigibleConfigBase64Test.java | 58 +++++++++++++++++++ 3 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 modules/commons/commons-config/src/test/java/org/eclipse/dirigible/commons/config/DirigibleConfigBase64Test.java diff --git a/CLAUDE_FEATURES.md b/CLAUDE_FEATURES.md index 874dab1e457..2007c51de98 100644 --- a/CLAUDE_FEATURES.md +++ b/CLAUDE_FEATURES.md @@ -692,7 +692,7 @@ Notable env-vars (non-exhaustive — full list lives in the source): | ------- | ------- | ------- | | `DIRIGIBLE_SERVER_PORT` | `8080` | HTTP listen port. | | `DIRIGIBLE_HOME_URL` | `services/web/shell-ide/` | Landing URL after `/`. | -| `DIRIGIBLE_BASIC_USERNAME` / `_PASSWORD` | `admin` / `admin` | Default basic-auth credentials. | +| `DIRIGIBLE_BASIC_USERNAME` / `_PASSWORD` | `admin` / `admin` | Default basic-auth credentials. Values are Base64-encoded (e.g. `printf '%s' 'admin' \| base64`); a value that is not valid Base64 is refused at startup. | | `DIRIGIBLE_REPOSITORY_LOCAL_ROOT_FOLDER` | `./target/` | On-disk root for the registry. | | `DIRIGIBLE_DATASOURCE_DEFAULT_DRIVER` / `_URL` / `_USERNAME` / `_PASSWORD` | H2 file-backed | Default JDBC datasource. | | `DIRIGIBLE_DATABASE_DATASOURCE_NAME_DEFAULT` / `_SYSTEM` | `DefaultDB` / `SystemDB` | Logical names. | diff --git a/modules/commons/commons-config/src/main/java/org/eclipse/dirigible/commons/config/DirigibleConfig.java b/modules/commons/commons-config/src/main/java/org/eclipse/dirigible/commons/config/DirigibleConfig.java index 755fa7d1286..e972820a18c 100644 --- a/modules/commons/commons-config/src/main/java/org/eclipse/dirigible/commons/config/DirigibleConfig.java +++ b/modules/commons/commons-config/src/main/java/org/eclipse/dirigible/commons/config/DirigibleConfig.java @@ -977,13 +977,19 @@ public static List tenantOverridableKeys() { } /** - * Gets the from base 64 value. + * Gets the Base64-decoded value of this configuration. * - * @return the from base 64 value + * @return the decoded value + * @throws InvalidConfigException if the configured value is not valid Base64 */ public String getFromBase64Value() { String val = getStringValue(); - return fromBase64(val); + try { + return fromBase64(val); + } catch (IllegalArgumentException ex) { + throw new InvalidConfigException("The value of [" + key + "] must be Base64-encoded, but it could not be decoded (" + + ex.getMessage() + "). Encode the plain value, e.g. `printf '%s' '' | base64`.", key); + } } /** diff --git a/modules/commons/commons-config/src/test/java/org/eclipse/dirigible/commons/config/DirigibleConfigBase64Test.java b/modules/commons/commons-config/src/test/java/org/eclipse/dirigible/commons/config/DirigibleConfigBase64Test.java new file mode 100644 index 00000000000..93c600d5b6c --- /dev/null +++ b/modules/commons/commons-config/src/test/java/org/eclipse/dirigible/commons/config/DirigibleConfigBase64Test.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010-2026 Eclipse Dirigible contributors + * + * All rights reserved. This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * SPDX-FileCopyrightText: Eclipse Dirigible contributors SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.dirigible.commons.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +import org.junit.After; +import org.junit.Test; + +/** + * Verifies that a Base64-only configuration refuses a plain-text value with a message naming the + * variable, instead of aborting boot with a bare decoder error. + */ +public class DirigibleConfigBase64Test { + + private static final String KEY = DirigibleConfig.BASIC_ADMIN_PASS.getKey(); + + @After + public void restoreDefault() { + Configuration.remove(KEY); + } + + @Test + public void plainTextValueIsRefusedNamingTheVariable() { + // a plain value with a non-Base64 character ('-'), as in the issue + Configuration.set(KEY, "qahunt-pw"); + try { + DirigibleConfig.BASIC_ADMIN_PASS.getFromBase64Value(); + fail("A non-Base64 value should be refused"); + } catch (InvalidConfigException ex) { + assertEquals(KEY, ex.getConfigKey()); + assertTrue("message should name the variable: " + ex.getMessage(), ex.getMessage() + .contains(KEY)); + assertTrue("message should mention Base64: " + ex.getMessage(), ex.getMessage() + .contains("Base64")); + } + } + + @Test + public void validBase64IsDecoded() { + Configuration.set(KEY, Base64.getEncoder() + .encodeToString("s3cr3t".getBytes(StandardCharsets.UTF_8))); + + assertEquals("s3cr3t", DirigibleConfig.BASIC_ADMIN_PASS.getFromBase64Value()); + } +}