/* * Licensed 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.karaf.itests; import java.io.IOException; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerClass; /** * This test exercises the Shell Command ACL for the config scope commands as defined in * /framework/src/main/resources/resources/etc/org.apache.karaf.command.acl.config.cfg */ @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) public class ConfigSshCommandSecurityTest extends SshCommandTestBase { private static int counter = 0; @Test public void testConfigCommandSecurityViaSsh() throws Exception { String manageruser = "man" + System.nanoTime() + "_" + counter++; String vieweruser = "view" + System.nanoTime() + "_" + counter++; addUsers(manageruser, vieweruser); // A viewer cannot do anything to ConfigAdmin assertCommand(vieweruser, "config:edit cfg." + vieweruser, Result.NOT_FOUND); assertCommand(vieweruser, "config:delete cfg." + vieweruser, Result.NOT_FOUND); testConfigEdits(manageruser, Result.OK, "cfg." + manageruser, false); testConfigEdits(manageruser, Result.NO_CREDENTIALS, "jmx.acl.test_" + counter++, false); testConfigEdits(manageruser, Result.NO_CREDENTIALS, "org.apache.karaf.command.acl.test_" + counter++, false); testConfigEdits(manageruser, Result.NO_CREDENTIALS, "org.apache.karaf.service.acl.test_" + counter++, false); testConfigEdits("karaf", Result.OK, "cfg.karaf_" + counter++, true); testConfigEdits("karaf", Result.OK, "jmx.acl.test_" + counter++, true); testConfigEdits("karaf", Result.OK, "org.apache.karaf.command.acl.test_" + counter++, true); testConfigEdits("karaf", Result.OK, "org.apache.karaf.service.acl.test_" + counter++, true); } private void testConfigEdits(String user, Result expectedEditResult, String pid, boolean isAdmin) throws Exception, IOException { assertCommand(user, "config:edit " + pid + "\n" + "config:property-set x y\n" + "config:property-set a b\n" + "config:property-append x z\n" + "config:update", expectedEditResult); if (expectedEditResult != Result.OK) // If we're expecting failure, don't continue any further... return; String result = assertCommand(user, "config:edit " + pid + "\n" + "config:property-list\n" + "config:cancel", Result.OK); Assert.assertTrue(result.contains("x = yz")); Assert.assertTrue(result.contains("a = b")); String result2 = assertCommand(user, "config:edit " + pid + "\n" + "config:property-delete a\n" + "config:property-list\n" + "config:update", Result.OK); Assert.assertTrue(result2.contains("x = yz")); Assert.assertFalse(result2.contains("a = b")); if (isAdmin) { assertCommand(user, "config:delete " + pid, Result.OK); String result3 = assertCommand(user, "config:edit " + pid + "\n" + "config:property-list", Result.OK); Assert.assertFalse(result3.contains("x = yz")); Assert.assertFalse(result3.contains("a = b")); } else { assertCommand(user, "config:delete " + pid, Result.NOT_FOUND); String result3 = assertCommand(user, "config:edit " + pid + "\n" + "config:property-list", Result.OK); Assert.assertTrue("The delete command should have had no effect", result3.contains("x = yz")); Assert.assertFalse(result3.contains("a = b")); } } @Test public void testConfigCommandSecurityWithoutEditSessionViaSsh() throws Exception { String manageruser = "man" + System.nanoTime() + "_" + counter++; String vieweruser = "view" + System.nanoTime() + "_" + counter++; addUsers(manageruser, vieweruser); // Test the viewer user. Since the viewer cannot modify anything wrt Config Admin // the commands should not even be found... testConfigEditsNoSession(vieweruser, Result.NOT_FOUND, "cfg." + vieweruser); testConfigEditsNoSession(vieweruser, Result.NOT_FOUND, "jmx.acl.test_" + counter++); testConfigEditsNoSession(vieweruser, Result.NOT_FOUND, "org.apache.karaf.command.acl.test_" + counter++); testConfigEditsNoSession(vieweruser, Result.NOT_FOUND, "org.apache.karaf.service.acl.test_" + counter++); // Test the manager user. The manager can modify some properties, but not the ones associated with security // Therefore the config: commands will be found, but in some cases the manager is denied access testConfigEditsNoSession(manageruser, Result.OK, "cfg." + manageruser); testConfigEditsNoSession(manageruser, Result.NO_CREDENTIALS, "jmx.acl.test_" + counter++); testConfigEditsNoSession(manageruser, Result.NO_CREDENTIALS, "org.apache.karaf.command.acl.test_" + counter++); testConfigEditsNoSession(manageruser, Result.NO_CREDENTIALS, "org.apache.karaf.service.acl.test_" + counter++); // The admin user can modify everything. testConfigEditsNoSession("karaf", Result.OK, "cfg.karaf.test_" + counter++); testConfigEditsNoSession("karaf", Result.OK, "jmx.acl.test_" + counter++); testConfigEditsNoSession("karaf", Result.OK, "org.apache.karaf.command.acl.test_" + counter++); testConfigEditsNoSession("karaf", Result.OK, "org.apache.karaf.service.acl.test_" + counter++); } private void testConfigEditsNoSession(String user, Result expectedResult, String pid) throws Exception, IOException { assertCommand(user, "config:property-set -p " + pid + " a.b.c d.e.f", expectedResult); assertCommand(user, "config:property-append -p " + pid + " a.b.c .g.h", expectedResult); if (expectedResult == Result.OK) { Assert.assertTrue(assertCommand(user, "config:property-list -p " + pid, Result.OK).contains("a.b.c = d.e.f.g.h")); } assertCommand(user, "config:property-delete -p " + pid + " a.b.c", expectedResult); if (expectedResult == Result.OK) { Assert.assertFalse(assertCommand(user, "config:property-list -p " + pid, Result.OK).contains("a.b.c")); } } }