summaryrefslogtreecommitdiff
path: root/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java
blob: 4140c9c12c5cd2ef96346d562ea27367c97d3a04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/*
 *
 * 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;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.management.plugin.HttpManagement;
import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.Plugin;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.security.access.FileAccessControlProviderConstants;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
import org.apache.qpid.test.utils.TestFileUtils;

public class AccessControlProviderRestTest extends QpidRestTestCase
{
    private static final String ALLOWED_USER = "allowed";
    private static final String DENIED_USER = "denied";
    private static final String OTHER_USER = "other";

    private String  _aclFileContent1 =
                          "ACL ALLOW-LOG " + ALLOWED_USER + " ACCESS MANAGEMENT\n" +
                          "ACL ALLOW-LOG " + ALLOWED_USER + " CONFIGURE BROKER\n" +
                          "ACL DENY-LOG ALL ALL";

    private String  _aclFileContent2 =
                          "ACL ALLOW-LOG " + ALLOWED_USER + " ACCESS MANAGEMENT\n" +
                          "ACL ALLOW-LOG " + OTHER_USER + " ACCESS MANAGEMENT\n" +
                          "ACL ALLOW-LOG " + ALLOWED_USER + " CONFIGURE BROKER\n" +
                          "ACL DENY-LOG ALL ALL";

    @Override
    protected void customizeConfiguration() throws IOException
    {
        super.customizeConfiguration();
        getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER);

        getBrokerConfiguration().setObjectAttribute(Plugin.class, TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT,
                HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, true);
    }

    public void testCreateAccessControlProvider() throws Exception
    {
        String accessControlProviderName = getTestName();

        //verify that the access control provider doesn't exist, and
        //in doing so implicitly verify that the 'denied' user can
        //actually currently connect because no ACL is in effect yet
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertAccessControlProviderExistence(accessControlProviderName, false);

        //create the access control provider using the 'allowed' user
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        int responseCode = createAccessControlProvider(accessControlProviderName, _aclFileContent1);
        assertEquals("Access control provider creation should be allowed", 201, responseCode);

        //verify it exists with the 'allowed' user
        assertAccessControlProviderExistence(accessControlProviderName, true);

        //verify the 'denied' user can no longer access the management interface
        //due to the just-created ACL file now preventing it
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertCanAccessManagementInterface(accessControlProviderName, false);
    }

    public void testRemoveAccessControlProvider() throws Exception
    {
        String accessControlProviderName = getTestName();

        //verify that the access control provider doesn't exist, and
        //in doing so implicitly verify that the 'denied' user can
        //actually currently connect because no ACL is in effect yet
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertAccessControlProviderExistence(accessControlProviderName, false);

        //create the access control provider using the 'allowed' user
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        int responseCode = createAccessControlProvider(accessControlProviderName, _aclFileContent1);
        assertEquals("Access control provider creation should be allowed", 201, responseCode);

        //verify it exists with the 'allowed' user
        assertAccessControlProviderExistence(accessControlProviderName, true);

        //verify the 'denied' user can no longer access the management interface
        //due to the just-created ACL file now preventing it
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertCanAccessManagementInterface(accessControlProviderName, false);

        //remove the access control provider using the 'allowed' user
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);

        responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "DELETE");
        assertEquals("Access control provider deletion should be allowed", 200, responseCode);
        assertAccessControlProviderExistence(accessControlProviderName, false);

        //verify it is gone again, using the 'denied' user to implicitly confirm it is
        //now able to connect to the management interface again because the ACL was removed.
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertAccessControlProviderExistence(accessControlProviderName, false);
    }

    public void testReplaceAccessControlProvider() throws Exception
    {
        String accessControlProviderName1 = getTestName() + "1";

        //verify that the access control provider doesn't exist, and
        //in doing so implicitly verify that the 'denied' user can
        //actually currently connect because no ACL is in effect yet
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertAccessControlProviderExistence(accessControlProviderName1, false);

        //create the access control provider using the 'allowed' user
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        int responseCode = createAccessControlProvider(accessControlProviderName1, _aclFileContent1);
        assertEquals("Access control provider creation should be allowed", 201, responseCode);

        //verify it exists with the 'allowed' user
        assertAccessControlProviderExistence(accessControlProviderName1, true);

        //verify the 'denied' and 'other' user can no longer access the management
        //interface due to the just-created ACL file now preventing them
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertCanAccessManagementInterface(accessControlProviderName1, false);
        getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
        assertCanAccessManagementInterface(accessControlProviderName1, false);

        //create the replacement access control provider using the 'allowed' user.
        String accessControlProviderName2 = getTestName() + "2";
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        responseCode = createAccessControlProvider(accessControlProviderName2, _aclFileContent2);
        assertEquals("Access control provider creation should be allowed", 201, responseCode);

        //Verify that it took effect immediately, replacing the first access control provider

        //verify the 'denied' user still can't access the management interface, but the 'other' user now CAN.
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, false);
        getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, true);

        //remove the original access control provider using the 'allowed' user
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName1, "DELETE");
        assertEquals("Access control provider deletion should be allowed", 200, responseCode);
        assertAccessControlProviderExistence(accessControlProviderName1, false);

        //verify the 'denied' user still can't access the management interface, the 'other' user still can, thus
        //confirming that the second access control provider is still in effect
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, false);
        getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, true);
    }


    public void testAddAndRemoveSecondAccessControlProviderReinstatesOriginal() throws Exception
    {
        String accessControlProviderName1 = getTestName() + "1";

        //verify that the access control provider doesn't exist, and
        //in doing so implicitly verify that the 'denied' user can
        //actually currently connect because no ACL is in effect yet
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertAccessControlProviderExistence(accessControlProviderName1, false);

        //create the access control provider using the 'allowed' user
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        int responseCode = createAccessControlProvider(accessControlProviderName1, _aclFileContent1);
        assertEquals("Access control provider creation should be allowed", 201, responseCode);

        //verify it exists with the 'allowed' user
        assertAccessControlProviderExistence(accessControlProviderName1, true);

        //verify the 'denied' and 'other' user can no longer access the management
        //interface due to the just-created ACL file now preventing them
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertCanAccessManagementInterface(accessControlProviderName1, false);
        getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
        assertCanAccessManagementInterface(accessControlProviderName1, false);

        //create the replacement access control provider using the 'allowed' user.
        String accessControlProviderName2 = getTestName() + "2";
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        responseCode = createAccessControlProvider(accessControlProviderName2, _aclFileContent2);
        assertEquals("Access control provider creation should be allowed", 201, responseCode);

        //Verify that it took effect immediately, replacing the first access control provider

        //verify the 'denied' user still can't access the management interface, but the 'other' user now CAN.
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, false);
        getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, true);

        //remove the second access control provider using the 'allowed' user
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName2, "DELETE");
        assertEquals("Access control provider deletion should be allowed", 200, responseCode);
        assertAccessControlProviderExistence(accessControlProviderName2, false);

        //verify the 'denied' user still can't access the management interface, the
        //'other' now CANT again, the 'allowed' still can, thus confirming that the
        //first access control provider is now in effect once again
        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, false);
        getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, false);
        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
        assertCanAccessManagementInterface(accessControlProviderName2, true);
    }

    public void testRemovalOfAccessControlProviderInErrorStateUsingManagementMode() throws Exception
    {
        stopBroker();

        File file = new File(TMP_FOLDER, getTestName());
        if (file.exists())
        {
            file.delete();
        }
        assertFalse("ACL file should not exist", file.exists());
        UUID id = getBrokerConfiguration().addAclFileConfiguration(file.getAbsolutePath());
        getBrokerConfiguration().setSaved(false);
        startBroker(0, true);

        getRestTestHelper().setUsernameAndPassword(BrokerOptions.MANAGEMENT_MODE_USER_NAME, MANAGEMENT_MODE_PASSWORD);

        Map<String, Object> acl = getRestTestHelper().getJsonAsSingletonList("accesscontrolprovider/" + TestBrokerConfiguration.ENTRY_NAME_ACL_FILE);
        assertEquals("Unexpected id", id.toString(), acl.get(AccessControlProvider.ID));
        assertEquals("Unexpected path", file.getAbsolutePath() , acl.get(FileAccessControlProviderConstants.PATH));
        assertEquals("Unexpected state", State.ERRORED.name() , acl.get(AccessControlProvider.STATE));

        int status = getRestTestHelper().submitRequest("accesscontrolprovider/" + TestBrokerConfiguration.ENTRY_NAME_ACL_FILE, "DELETE");
        assertEquals("ACL was not deleted", 200, status);

        List<Map<String, Object>> acls = getRestTestHelper().getJsonAsList("accesscontrolprovider/" + TestBrokerConfiguration.ENTRY_NAME_ACL_FILE);
        assertEquals("ACL exists", 0, acls.size());
    }

    private void assertCanAccessManagementInterface(String accessControlProviderName, boolean canAccess) throws Exception
    {
        int expected = canAccess ? 200 : 403;
        int responseCode = getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "GET");
        assertEquals("Unexpected response code", expected, responseCode);
    }

    private void assertAccessControlProviderExistence(String accessControlProviderName, boolean exists) throws Exception
    {
        String path = "accesscontrolprovider/" + accessControlProviderName;
        List<Map<String, Object>> providers = getRestTestHelper().getJsonAsList(path);
        assertEquals("Unexpected result", exists, !providers.isEmpty());
    }

    private int createAccessControlProvider(String accessControlProviderName, String content) throws Exception
    {
        File file = TestFileUtils.createTempFile(this, ".acl", content);
        Map<String, Object> attributes = new HashMap<String, Object>();
        attributes.put(AccessControlProvider.NAME, accessControlProviderName);
        attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
        attributes.put(FileAccessControlProviderConstants.PATH, file.getAbsoluteFile());

        return getRestTestHelper().submitRequest("accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
    }
}