This is an automated email from the ASF dual-hosted git repository.
jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/karaf.git
The following commit(s) were added to refs/heads/main by this push:
new 54dd45ad05 fix(config): restrict config:install to the admin role
(#2861)
54dd45ad05 is described below
commit 54dd45ad059168f22f83754abeea5adaa2fc5253
Author: JB Onofré <[email protected]>
AuthorDate: Fri Sep 11 14:48:03 2026 +0200
fix(config): restrict config:install to the admin role (#2861)
config:install writes a file fetched from an arbitrary URL into
${karaf.etc}, which also holds users.properties, keys.properties and the
*.acl.* files. The command had no entry in the
org.apache.karaf.command.acl.config
ACL, and the command guard treats an unmatched command as allowed, so any
authenticated shell user could run it.
Add "install = admin" to the config command ACL, consistent with
config:delete and with bundle:install / feature:install / kar:install.
---
.../features/standard/src/main/feature/feature.xml | 6 +++++
.../etc/org.apache.karaf.command.acl.config.cfg | 6 +++++
.../src/test/filtered-resources/etc/feature.xml | 6 +++++
.../itests/ssh/ConfigSshCommandSecurityTest.java | 29 ++++++++++++++++++++++
manual/src/main/asciidoc/user-guide/security.adoc | 3 ++-
5 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/assemblies/features/standard/src/main/feature/feature.xml
b/assemblies/features/standard/src/main/feature/feature.xml
index 220592b484..d1c7f086dc 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -612,6 +612,12 @@ edit = manager
edit[/.*jmx[.]acl.*/] = admin
edit[/.*org[.]apache[.]karaf[.]command[.]acl[.].+/] = admin
edit[/.*org[.]apache[.]karaf[.]service[.]acl[.].+/] = admin
+#
+# 'install' writes an arbitrary file (fetched from a URL) into ${karaf.etc},
which
+# includes the users, keys and *.acl.* configuration files. It is restricted to
+# 'admin', consistent with bundle:install, feature:install and kar:install.
+#
+install = admin
property-append = manager
property-append[/.*jmx[.]acl.*/] = admin
property-append[/.*org[.]apache[.]karaf[.]command[.]acl[.].+/] = admin
diff --git
a/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.command.acl.config.cfg
b/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.command.acl.config.cfg
index 1cbc8b5cd8..89336fd4f1 100644
---
a/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.command.acl.config.cfg
+++
b/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.command.acl.config.cfg
@@ -29,6 +29,12 @@ edit = manager
edit[/.*jmx[.]acl.*/] = admin
edit[/.*org[.]apache[.]karaf[.]command[.]acl[.].+/] = admin
edit[/.*org[.]apache[.]karaf[.]service[.]acl[.].+/] = admin
+#
+# 'install' writes an arbitrary file (fetched from a URL) into ${karaf.etc},
which
+# includes the users, keys and *.acl.* configuration files. It is restricted to
+# 'admin', consistent with bundle:install, feature:install and kar:install.
+#
+install = admin
property-append = manager
property-append[/.*jmx[.]acl.*/] = admin
property-append[/.*org[.]apache[.]karaf[.]command[.]acl[.].+/] = admin
diff --git a/itests/test/src/test/filtered-resources/etc/feature.xml
b/itests/test/src/test/filtered-resources/etc/feature.xml
index 31c9fff502..ec36a8c8d6 100644
--- a/itests/test/src/test/filtered-resources/etc/feature.xml
+++ b/itests/test/src/test/filtered-resources/etc/feature.xml
@@ -408,6 +408,12 @@
edit[/.*jmx[.]acl.*/] = admin
edit[/.*org[.]apache[.]karaf[.]command[.]acl[.].+/] = admin
edit[/.*org[.]apache[.]karaf[.]service[.]acl[.].+/] = admin
+ #
+ # 'install' writes an arbitrary file (fetched from a URL) into
${karaf.etc}, which
+ # includes the users, keys and *.acl.* configuration files. It
is restricted to
+ # 'admin', consistent with bundle:install, feature:install and
kar:install.
+ #
+ install = admin
property-append = manager
property-append[/.*jmx[.]acl.*/] = admin
property-append[/.*org[.]apache[.]karaf[.]command[.]acl[.].+/]
= admin
diff --git
a/itests/test/src/test/java/org/apache/karaf/itests/ssh/ConfigSshCommandSecurityTest.java
b/itests/test/src/test/java/org/apache/karaf/itests/ssh/ConfigSshCommandSecurityTest.java
index 97695cc094..cd5f2de890 100644
---
a/itests/test/src/test/java/org/apache/karaf/itests/ssh/ConfigSshCommandSecurityTest.java
+++
b/itests/test/src/test/java/org/apache/karaf/itests/ssh/ConfigSshCommandSecurityTest.java
@@ -13,6 +13,8 @@
*/
package org.apache.karaf.itests.ssh;
+import java.io.File;
+
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,6 +59,33 @@ public class ConfigSshCommandSecurityTest extends
SshCommandTestBase {
testConfigEdits("karaf", Result.OK,
"org.apache.karaf.service.acl.test_" + counter++, true);
}
+ @Test
+ public void testConfigInstallCommandSecurityViaSsh() throws Exception {
+ // Skip on Windows where PTY output can be garbled,
+ // when upgrading to Junit5, this can be replaced with
@DisabledOnOs(OS.WINDOWS)
+ // TODO: remove this once we have a better solution for PTY output on
Windows
+ Assume.assumeFalse(System.getProperty("os.name",
"").toLowerCase().contains("win"));
+
+ String manageruser = "man" + System.nanoTime() + "_" + counter++;
+ String vieweruser = "view" + System.nanoTime() + "_" + counter++;
+
+ addUsers(manageruser, vieweruser);
+
+ String sourceUrl = new File(System.getProperty("karaf.etc"),
"system.properties").toURI().toURL().toString();
+
+ // config:install writes an arbitrary file under ${karaf.etc}, so it
is restricted to admin.
+ // A viewer and a manager must not even see the command.
+ assertCommand(vieweruser, "config:install " + sourceUrl + " itest-" +
counter++ + ".cfg", Result.NOT_FOUND);
+ assertCommand(manageruser, "config:install " + sourceUrl + " itest-" +
counter++ + ".cfg", Result.NOT_FOUND);
+
+ // The admin user can run it: the first install succeeds, a second one
without --override
+ // reports that the file already exists, which proves the file was
written.
+ String target = "itest-installed-" + counter++ + ".cfg";
+ assertCommand("karaf", "config:install " + sourceUrl + " " + target,
Result.OK);
+ assertContains("already exists",
+ assertCommand("karaf", "config:install " + sourceUrl + " " +
target, Result.OK));
+ }
+
private void testConfigEdits(String user, Result expectedEditResult,
String pid, boolean isAdmin) throws Exception {
assertCommand(user, "config:edit " + pid + "\n" +
"config:property-set x y\n" +
diff --git a/manual/src/main/asciidoc/user-guide/security.adoc
b/manual/src/main/asciidoc/user-guide/security.adoc
index a3365778f2..a542b88994 100644
--- a/manual/src/main/asciidoc/user-guide/security.adoc
+++ b/manual/src/main/asciidoc/user-guide/security.adoc
@@ -489,7 +489,8 @@ By default, Apache Karaf defines the following commands
ACLs:
* `etc/org.apache.karaf.command.acl.config.cfg` configuration file defines the
ACL for `config:*` commands.
This ACL limits the execution of `config:*` commands with `jmx.acl.*`,
`org.apache.karaf.command.acl.*`, and
`org.apache.karaf.service.acl.*` configuration PID to the users with `admin`
role. For the other configuration PID,
- the users with the `manager` role can execute `config:*` commands.
+ the users with the `manager` role can execute `config:*` commands. As
`config:install` writes an arbitrary file into
+ the `etc` folder, it is restricted to the users with the `admin` role.
* `etc/org.apache.karaf.command.acl.feature.cfg` configuration file defines
the ACL for `feature:*` commands.
Only the users with `admin` role can execute `feature:install`,
`feature:uninstall`,`feature:start`, `feature:stop` and `feature:update`
commands. The other `feature:*`
commands can be executed by any user.