diff options
| author | Alex Rudyy <orudyy@apache.org> | 2013-09-19 10:46:27 +0000 |
|---|---|---|
| committer | Alex Rudyy <orudyy@apache.org> | 2013-09-19 10:46:27 +0000 |
| commit | 578564d5a5787848d8795afa01a5d77264370957 (patch) | |
| tree | 89dde7aec45774f159e9fa0c3c5ffd0f3b734bcd /qpid/java | |
| parent | cab8fae524dd8eb9bd4f3d1f9ee160813b39863e (diff) | |
| download | qpid-python-578564d5a5787848d8795afa01a5d77264370957.tar.gz | |
QPID-5138: Protect user preferences operations with ACL
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1524684 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java')
10 files changed, 402 insertions, 1 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java index 7bcfcbc7f7..bf2a88a2c1 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java @@ -1,3 +1,24 @@ +/* + * + * 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.qpid.server.management.plugin.servlet.rest; import java.io.IOException; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java index 3fc0a76efb..808e3210dd 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java @@ -1,3 +1,24 @@ +/* + * + * 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.qpid.server.management.plugin.servlet.rest; import java.io.IOException; @@ -18,6 +39,7 @@ import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.User; +import org.apache.qpid.server.security.access.Operation; public class UserPreferencesServlet extends AbstractServlet { @@ -46,6 +68,11 @@ public class UserPreferencesServlet extends AbstractServlet private void getUserPreferences(String authenticationProviderName, String userId, HttpServletResponse response) throws IOException { + if (!userPreferencesOperationAuthorized(userId)) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Vieweing of preferences is not allowed"); + return; + } Map<String, Object> preferences = null; PreferencesProvider preferencesProvider = getPreferencesProvider(authenticationProviderName); if (preferencesProvider == null) @@ -132,7 +159,7 @@ public class UserPreferencesServlet extends AbstractServlet * removes preferences */ @Override - protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException { final List<String[]> userData = new ArrayList<String[]>(); for (String name : request.getParameterValues("user")) @@ -165,6 +192,11 @@ public class UserPreferencesServlet extends AbstractServlet Set<String> usernames = preferencesProvider.listUserIDs(); if (usernames.contains(userId)) { + if (!userPreferencesOperationAuthorized(userId)) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Deletion of preferences is not allowed"); + return; + } preferencesProvider.deletePreferences(userId); } } @@ -175,4 +207,9 @@ public class UserPreferencesServlet extends AbstractServlet } } + + private boolean userPreferencesOperationAuthorized(String userId) + { + return getBroker().getSecurityManager().authoriseUserOperation(Operation.UPDATE, userId); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java index 5914b8d8d2..f7560a0dfa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java @@ -1,3 +1,24 @@ +/* + * + * 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.qpid.server.model.adapter; import java.io.ByteArrayOutputStream; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactory.java index 218ecc1c53..32ee910973 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactory.java @@ -1,3 +1,24 @@ +/* + * + * 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.qpid.server.model.adapter; import java.util.Map; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecovererTest.java index aba9e1e5fa..8c316b5f53 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecovererTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecovererTest.java @@ -1,3 +1,24 @@ +/* + * + * 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.qpid.server.configuration.startup; import static org.mockito.Mockito.mock; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactoryTest.java index fcfb1dd0ea..64dfad94c3 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactoryTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactoryTest.java @@ -1,3 +1,24 @@ +/* + * + * 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.qpid.server.model.adapter; import static org.mockito.Mockito.mock; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java index bb64241ff0..0eab93541f 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java @@ -1,3 +1,23 @@ +/* + * + * 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.qpid.server.model.adapter; import static org.mockito.Mockito.mock; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java index 591ced2ddf..7f604bada7 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java @@ -1,3 +1,24 @@ +/* + * + * 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.qpid.systest.rest; import java.io.File; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java index db6d513855..7c0883ec84 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java @@ -1,3 +1,24 @@ +/* + * + * 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.qpid.systest.rest; import java.io.File; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java new file mode 100644 index 0000000000..6ed84ac95a --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java @@ -0,0 +1,197 @@ +/* + * + * 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.qpid.systest.rest.acl; + +import java.io.File; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.management.plugin.HttpManagement; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; +import org.apache.qpid.systest.rest.QpidRestTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; + +public class UserPreferencesRestACLTest extends QpidRestTestCase +{ + + private static final String REST_USER_PREFERENCES_BASE_URL = "/rest/userpreferences"; + private static final String ALLOWED_USER = "webadmin"; + private static final String DENIED_USER = "admin"; + private static final String TEST_USER_PREFERENCES_GET_URL = REST_USER_PREFERENCES_BASE_URL + "/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/%s"; + + private File _preferencesProviderFile; + + public void setUp() throws Exception + { + _preferencesProviderFile = TestFileUtils.createTempFile(this, ".prefs.json", + "{\"webadmin\":{\"language\": \"en\", \"saveTabs\":true}," + " \"admin\":{\"language\": \"fr\", \"saveTabs\":false}" + + "}"); + super.setUp(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_preferencesProviderFile != null) + { + _preferencesProviderFile.delete(); + } + } + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER); + + AbstractACLTestCase.writeACLFileUtil(this, null, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", "ACL ALLOW-LOG " + ALLOWED_USER + + " UPDATE USER", "ACL DENY-LOG " + DENIED_USER + " UPDATE USER", "ACL DENY-LOG ALL ALL"); + + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + brokerConfiguration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, + HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, true); + + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PreferencesProvider.NAME, "test"); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.PROVIDER_TYPE); + attributes.put(FileSystemPreferencesProvider.PATH, _preferencesProviderFile.getAbsolutePath()); + brokerConfiguration + .addPreferencesProviderConfiguration(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, attributes); + } + + public void testListUsersWithPreferencesAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList(REST_USER_PREFERENCES_BASE_URL); + assertUsers(users); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + users = getRestTestHelper().getJsonAsList(REST_USER_PREFERENCES_BASE_URL); + assertUsers(users); + } + + public void testViewOtherUserPreferencesAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String userPreferencesUrl = String.format(TEST_USER_PREFERENCES_GET_URL, DENIED_USER); + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "fr", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", false, preferences.get("saveTabs")); + } + + public void testViewOtherUserPreferencesDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + int responseCode = getRestTestHelper().submitRequest( + "/rest/userpreferences?user=" + + URLEncoder.encode(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + ALLOWED_USER, "UTF-8"), + "DELETE", null); + assertEquals("Preferences deletion should be denied", 403, responseCode); + } + + public void testDeleteOtherUserPreferencesAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String userPreferencesUrl = String.format(TEST_USER_PREFERENCES_GET_URL, DENIED_USER); + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "fr", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", false, preferences.get("saveTabs")); + + int responseCode = getRestTestHelper().submitRequest( + "/rest/userpreferences?user=" + + URLEncoder.encode(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + DENIED_USER, "UTF-8"), + "DELETE", null); + assertEquals("Preferences deletion should be allowed", 200, responseCode); + + preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences after deletion", 0, preferences.size()); + } + + public void testDeleteOtherUserPreferencesDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String userPreferencesUrl = String.format(TEST_USER_PREFERENCES_GET_URL, ALLOWED_USER); + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "en", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", true, preferences.get("saveTabs")); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + int responseCode = getRestTestHelper().submitRequest( + "/rest/userpreferences?user=" + + URLEncoder.encode(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + ALLOWED_USER, "UTF-8"), + "DELETE", null); + assertEquals("Preferences deletion should be denied", 403, responseCode); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences after deletion", 2, preferences.size()); + } + + + private void assertUsers(List<Map<String, Object>> users) + { + assertEquals("Unexpected number of users", 2, users.size()); + Map<String, Object> webadmin = findUser("webadmin", users); + assertEquals("Unexpected name", "webadmin", webadmin.get("name")); + assertEquals("Unexpected authentication provider", TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, webadmin.get("authenticationProvider")); + Map<String, Object> admin = findUser("admin", users); + assertEquals("Unexpected name", "admin", admin.get("name")); + assertEquals("Unexpected authentication provider", TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, admin.get("authenticationProvider")); + } + + private Map<String, Object> findUser(String name, List<Map<String, Object>> users) + { + for (Map<String, Object> user : users) + { + if (name.equals(user.get("name"))) + { + return user; + } + } + return null; + } +} |
