blob: 096d4ff3d80fa0035898dc8e9e2d7e2b2a165c04 [file] [log] [blame]
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.hadoop.ozone.security.acl;
import org.apache.hadoop.hdds.client.StandaloneReplicationConfig;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.server.OzoneAdmins;
import org.apache.hadoop.ozone.om.BucketManager;
import org.apache.hadoop.ozone.om.KeyManager;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OmTestManagers;
import org.apache.hadoop.ozone.om.PrefixManager;
import org.apache.hadoop.ozone.om.VolumeManager;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
import org.apache.hadoop.ozone.om.helpers.OzoneAclUtil;
import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
import org.apache.hadoop.ozone.om.request.OMRequestTestUtils;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.ozone.test.GenericTestUtils;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.apache.hadoop.hdds.HddsConfigKeys.OZONE_METADATA_DIRS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_AUTHORIZER_CLASS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_AUTHORIZER_CLASS_NATIVE;
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.ALL;
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.CREATE;
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.NONE;
/**
* Test Ozone owner check from OzoneNativeAuthorizer.
*/
public class TestVolumeOwner {
private static OzoneConfiguration ozoneConfig;
private static OzoneNativeAuthorizer nativeAuthorizer;
private static KeyManager keyManager;
private static VolumeManager volumeManager;
private static BucketManager bucketManager;
private static PrefixManager prefixManager;
private static OMMetadataManager metadataManager;
private static UserGroupInformation testUgi;
private static OzoneManagerProtocol writeClient;
@BeforeClass
public static void setup() throws IOException, AuthenticationException {
ozoneConfig = new OzoneConfiguration();
ozoneConfig.set(OZONE_ACL_AUTHORIZER_CLASS,
OZONE_ACL_AUTHORIZER_CLASS_NATIVE);
File dir = GenericTestUtils.getRandomizedTestDir();
ozoneConfig.set(OZONE_METADATA_DIRS, dir.toString());
OmTestManagers omTestManagers =
new OmTestManagers(ozoneConfig);
metadataManager = omTestManagers.getMetadataManager();
volumeManager = omTestManagers.getVolumeManager();
bucketManager = omTestManagers.getBucketManager();
keyManager = omTestManagers.getKeyManager();
prefixManager = omTestManagers.getPrefixManager();
writeClient = omTestManagers.getWriteClient();
nativeAuthorizer = new OzoneNativeAuthorizer(volumeManager, bucketManager,
keyManager, prefixManager,
new OzoneAdmins(Collections.singletonList("om")));
testUgi = UserGroupInformation.createUserForTesting("testuser",
new String[]{"test"});
prepareTestVols();
prepareTestBuckets();
prepareTestKeys();
}
// create 2 volumes
private static void prepareTestVols() throws IOException {
for (int i = 0; i < 2; i++) {
OmVolumeArgs volumeArgs = OmVolumeArgs.newBuilder()
.setVolume(getTestVolumeName(i))
.setAdminName("om")
.setOwnerName(getTestVolOwnerName(i))
.build();
OMRequestTestUtils.addVolumeToOM(metadataManager, volumeArgs);
}
}
// create 2 buckets under each volume
private static void prepareTestBuckets() throws IOException {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
OmBucketInfo bucketInfo = OmBucketInfo.newBuilder()
.setVolumeName(getTestVolumeName(i))
.setBucketName(getTestBucketName(j))
.build();
OMRequestTestUtils.addBucketToOM(metadataManager, bucketInfo);
}
}
}
// create 2 keys under each test buckets
private static void prepareTestKeys() throws IOException {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
OmKeyArgs.Builder keyArgsBuilder = new OmKeyArgs.Builder()
.setVolumeName(getTestVolumeName(i))
.setBucketName(getTestBucketName(j))
.setKeyName(getTestKeyName(k))
.setReplicationConfig(
StandaloneReplicationConfig.getInstance(
HddsProtos.ReplicationFactor.ONE))
.setDataSize(0);
if (k == 0) {
keyArgsBuilder.setAcls(OzoneAclUtil.getAclList(
testUgi.getUserName(), testUgi.getGroupNames(), ALL, ALL));
} else {
keyArgsBuilder.setAcls(OzoneAclUtil.getAclList(
testUgi.getUserName(), testUgi.getGroupNames(), NONE, NONE));
}
OmKeyArgs keyArgs = keyArgsBuilder.build();
OpenKeySession keySession = writeClient.createFile(keyArgs, true,
false);
keyArgs.setLocationInfoList(
keySession.getKeyInfo().getLatestVersionLocations()
.getLocationList());
writeClient.commitKey(keyArgs, keySession.getId());
}
}
}
}
@Test
public void testVolumeOps() throws Exception {
OzoneObj vol0 = getTestVolumeobj(0);
// admin = true, owner = false, ownerName = testvolumeOwner
RequestContext nonOwnerContext = getUserRequestContext("om",
IAccessAuthorizer.ACLType.CREATE, false, getTestVolOwnerName(0));
Assert.assertTrue("matching admins are allowed to perform admin " +
"operations", nativeAuthorizer.checkAccess(vol0, nonOwnerContext));
// admin = true, owner = false, ownerName = null
Assert.assertTrue("matching admins are allowed to perform admin " +
"operations", nativeAuthorizer.checkAccess(vol0, nonOwnerContext));
// admin = false, owner = false, ownerName = testvolumeOwner
RequestContext nonAdminNonOwnerContext = getUserRequestContext("testuser",
IAccessAuthorizer.ACLType.CREATE, false, getTestVolOwnerName(0));
Assert.assertFalse("mismatching admins are not allowed to perform admin " +
"operations", nativeAuthorizer.checkAccess(vol0,
nonAdminNonOwnerContext));
// admin = false, owner = true
RequestContext nonAdminOwnerContext = getUserRequestContext(
getTestVolOwnerName(0), IAccessAuthorizer.ACLType.CREATE,
true, getTestVolOwnerName(0));
Assert.assertFalse("mismatching admins are not allowed to perform admin " +
"operations even for owner", nativeAuthorizer.checkAccess(vol0,
nonAdminOwnerContext));
List<IAccessAuthorizer.ACLType> aclsToTest =
Arrays.stream(IAccessAuthorizer.ACLType.values()).filter(
(type) -> type != NONE && type != CREATE)
.collect(Collectors.toList());
for (IAccessAuthorizer.ACLType type: aclsToTest) {
nonAdminOwnerContext = getUserRequestContext(getTestVolOwnerName(0),
type, true, getTestVolOwnerName(0));
Assert.assertTrue("Owner is allowed to perform all non-admin " +
"operations", nativeAuthorizer.checkAccess(vol0,
nonAdminOwnerContext));
}
}
@Test
public void testBucketOps() throws Exception {
OzoneObj obj = getTestBucketobj(1, 1);
List<IAccessAuthorizer.ACLType> aclsToTest = getAclsToTest();
// admin = false, owner = true
for (IAccessAuthorizer.ACLType type: aclsToTest) {
RequestContext nonAdminOwnerContext = getUserRequestContext(
getTestVolOwnerName(1), type, true, getTestVolOwnerName(1));
Assert.assertTrue("non admin volume owner without acls are allowed" +
" to do " + type + " on bucket",
nativeAuthorizer.checkAccess(obj, nonAdminOwnerContext));
}
// admin = false, owner = false
for (IAccessAuthorizer.ACLType type: aclsToTest) {
RequestContext nonAdminOwnerContext = getUserRequestContext(
getTestVolOwnerName(1), type, false, getTestVolOwnerName(0));
Assert.assertFalse("non admin non volume owner without acls" +
" are not allowed to do " + type + " on bucket",
nativeAuthorizer.checkAccess(obj, nonAdminOwnerContext));
}
}
@Test
public void testKeyOps() throws Exception {
OzoneObj obj = getTestKeyobj(0, 0, 1);
List<IAccessAuthorizer.ACLType> aclsToTest = getAclsToTest();
// admin = false, owner = true
for (IAccessAuthorizer.ACLType type: aclsToTest) {
RequestContext nonAdminOwnerContext = getUserRequestContext(
getTestVolOwnerName(0), type, true, getTestVolOwnerName(0));
Assert.assertTrue("non admin volume owner without acls are allowed to " +
"access key",
nativeAuthorizer.checkAccess(obj, nonAdminOwnerContext));
}
// admin = false, owner = false
for (IAccessAuthorizer.ACLType type: aclsToTest) {
RequestContext nonAdminOwnerContext = getUserRequestContext(
getTestVolOwnerName(0), type, false, getTestVolOwnerName(1));
Assert.assertFalse("non admin volume owner without acls are" +
" not allowed to access key",
nativeAuthorizer.checkAccess(obj, nonAdminOwnerContext));
}
}
private RequestContext getUserRequestContext(String username,
IAccessAuthorizer.ACLType type, boolean isOwner, String ownerName) {
return RequestContext.getBuilder(
UserGroupInformation.createRemoteUser(username), null, null,
type, ownerName).build();
}
private static String getTestVolumeName(int index) {
return "vol" + index;
}
private static String getTestVolOwnerName(int index) {
return "owner" + index;
}
private static String getTestBucketName(int index) {
return "bucket" + index;
}
private static String getTestKeyName(int index) {
return "key" + index;
}
private OzoneObj getTestVolumeobj(int index) {
return OzoneObjInfo.Builder.getBuilder(OzoneObj.ResourceType.VOLUME,
OzoneObj.StoreType.OZONE,
getTestVolumeName(index), null, null).build();
}
private OzoneObj getTestBucketobj(int volIndex, int bucketIndex) {
return OzoneObjInfo.Builder.newBuilder()
.setResType(OzoneObj.ResourceType.BUCKET)
.setStoreType(OzoneObj.StoreType.OZONE)
.setVolumeName(getTestVolumeName(volIndex))
.setBucketName(getTestBucketName(bucketIndex)).build();
}
private OzoneObj getTestKeyobj(int volIndex, int bucketIndex,
int keyIndex) {
return OzoneObjInfo.Builder.newBuilder()
.setResType(OzoneObj.ResourceType.KEY)
.setStoreType(OzoneObj.StoreType.OZONE)
.setVolumeName(getTestVolumeName(volIndex))
.setBucketName(getTestBucketName(bucketIndex))
.setKeyName(getTestKeyName(keyIndex))
.build();
}
List<IAccessAuthorizer.ACLType> getAclsToTest() {
return Arrays.stream(IAccessAuthorizer.ACLType.values()).filter(
(type) -> type != NONE).collect(Collectors.toList());
}
}