HDDS-1834. parent directories not found in secure setup due to ACL check. Contributed by Doroszlai, Attila.
This closes #1171.
This commit is contained in:
parent
42683aef1a
commit
e68d8446c4
|
@ -17,6 +17,7 @@
|
||||||
package org.apache.hadoop.ozone.security.acl;
|
package org.apache.hadoop.ozone.security.acl;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
|
||||||
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
|
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
|
||||||
|
|
||||||
import static org.apache.hadoop.ozone.OzoneConsts.OZONE_URI_DELIMITER;
|
import static org.apache.hadoop.ozone.OzoneConsts.OZONE_URI_DELIMITER;
|
||||||
|
@ -158,6 +159,14 @@ public final class OzoneObjInfo extends OzoneObj {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Builder fromKeyArgs(OmKeyArgs args) {
|
||||||
|
return new Builder()
|
||||||
|
.setVolumeName(args.getVolumeName())
|
||||||
|
.setBucketName(args.getBucketName())
|
||||||
|
.setKeyName(args.getKeyName())
|
||||||
|
.setResType(ResourceType.KEY);
|
||||||
|
}
|
||||||
|
|
||||||
public Builder setResType(OzoneObj.ResourceType res) {
|
public Builder setResType(OzoneObj.ResourceType res) {
|
||||||
this.resType = res;
|
this.resType = res;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -57,6 +57,7 @@ import org.apache.hadoop.hdds.scm.protocol.ScmBlockLocationProtocol;
|
||||||
import org.apache.hadoop.hdds.scm.server.SCMConfigurator;
|
import org.apache.hadoop.hdds.scm.server.SCMConfigurator;
|
||||||
import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
|
import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
|
||||||
import org.apache.hadoop.ozone.OzoneAcl;
|
import org.apache.hadoop.ozone.OzoneAcl;
|
||||||
|
import org.apache.hadoop.ozone.OzoneTestUtils;
|
||||||
import org.apache.hadoop.ozone.om.exceptions.OMException;
|
import org.apache.hadoop.ozone.om.exceptions.OMException;
|
||||||
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
|
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
|
||||||
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
|
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
|
||||||
|
@ -73,6 +74,7 @@ import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLIdentityType;
|
||||||
import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType;
|
import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType;
|
||||||
import org.apache.hadoop.ozone.security.acl.OzoneObj;
|
import org.apache.hadoop.ozone.security.acl.OzoneObj;
|
||||||
import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
|
import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
|
||||||
|
import org.apache.hadoop.ozone.security.acl.RequestContext;
|
||||||
import org.apache.hadoop.ozone.web.utils.OzoneUtils;
|
import org.apache.hadoop.ozone.web.utils.OzoneUtils;
|
||||||
import org.apache.hadoop.security.UserGroupInformation;
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
import org.apache.hadoop.test.GenericTestUtils;
|
import org.apache.hadoop.test.GenericTestUtils;
|
||||||
|
@ -395,6 +397,53 @@ public class TestKeyManagerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckAccessForFileKey() throws Exception {
|
||||||
|
OmKeyArgs keyArgs = createBuilder()
|
||||||
|
.setKeyName("testdir/deep/NOTICE.txt")
|
||||||
|
.build();
|
||||||
|
OpenKeySession keySession = keyManager.createFile(keyArgs, false, true);
|
||||||
|
keyArgs.setLocationInfoList(
|
||||||
|
keySession.getKeyInfo().getLatestVersionLocations().getLocationList());
|
||||||
|
keyManager.commitKey(keyArgs, keySession.getId());
|
||||||
|
|
||||||
|
OzoneObj fileKey = OzoneObjInfo.Builder.fromKeyArgs(keyArgs)
|
||||||
|
.setStoreType(OzoneObj.StoreType.OZONE)
|
||||||
|
.build();
|
||||||
|
RequestContext context = currentUserReads();
|
||||||
|
Assert.assertTrue(keyManager.checkAccess(fileKey, context));
|
||||||
|
|
||||||
|
OzoneObj parentDirKey = OzoneObjInfo.Builder.fromKeyArgs(keyArgs)
|
||||||
|
.setStoreType(OzoneObj.StoreType.OZONE)
|
||||||
|
.setKeyName("testdir")
|
||||||
|
.build();
|
||||||
|
Assert.assertTrue(keyManager.checkAccess(parentDirKey, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckAccessForNonExistentKey() throws Exception {
|
||||||
|
OmKeyArgs keyArgs = createBuilder()
|
||||||
|
.setKeyName("testdir/deep/NO_SUCH_FILE.txt")
|
||||||
|
.build();
|
||||||
|
OzoneObj nonExistentKey = OzoneObjInfo.Builder.fromKeyArgs(keyArgs)
|
||||||
|
.setStoreType(OzoneObj.StoreType.OZONE)
|
||||||
|
.build();
|
||||||
|
OzoneTestUtils.expectOmException(OMException.ResultCodes.KEY_NOT_FOUND,
|
||||||
|
() -> keyManager.checkAccess(nonExistentKey, currentUserReads()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckAccessForDirectoryKey() throws Exception {
|
||||||
|
OmKeyArgs keyArgs = createBuilder()
|
||||||
|
.setKeyName("some/dir")
|
||||||
|
.build();
|
||||||
|
keyManager.createDirectory(keyArgs);
|
||||||
|
|
||||||
|
OzoneObj dirKey = OzoneObjInfo.Builder.fromKeyArgs(keyArgs)
|
||||||
|
.setStoreType(OzoneObj.StoreType.OZONE)
|
||||||
|
.build();
|
||||||
|
Assert.assertTrue(keyManager.checkAccess(dirKey, currentUserReads()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrefixAclOps() throws IOException {
|
public void testPrefixAclOps() throws IOException {
|
||||||
|
@ -914,4 +963,12 @@ public class TestKeyManagerImpl {
|
||||||
ALL, ALL))
|
ALL, ALL))
|
||||||
.setVolumeName(VOLUME_NAME);
|
.setVolumeName(VOLUME_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RequestContext currentUserReads() throws IOException {
|
||||||
|
return RequestContext.newBuilder()
|
||||||
|
.setClientUgi(UserGroupInformation.getCurrentUser())
|
||||||
|
.setAclRights(ACLType.READ_ACL)
|
||||||
|
.setAclType(ACLIdentityType.USER)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1638,24 +1638,38 @@ public class KeyManagerImpl implements KeyManager {
|
||||||
String volume = ozObject.getVolumeName();
|
String volume = ozObject.getVolumeName();
|
||||||
String bucket = ozObject.getBucketName();
|
String bucket = ozObject.getBucketName();
|
||||||
String keyName = ozObject.getKeyName();
|
String keyName = ozObject.getKeyName();
|
||||||
|
String objectKey = metadataManager.getOzoneKey(volume, bucket, keyName);
|
||||||
|
OmKeyArgs args = new OmKeyArgs.Builder()
|
||||||
|
.setVolumeName(volume)
|
||||||
|
.setBucketName(bucket)
|
||||||
|
.setKeyName(keyName)
|
||||||
|
.build();
|
||||||
|
|
||||||
metadataManager.getLock().acquireLock(BUCKET_LOCK, volume, bucket);
|
metadataManager.getLock().acquireLock(BUCKET_LOCK, volume, bucket);
|
||||||
try {
|
try {
|
||||||
validateBucket(volume, bucket);
|
validateBucket(volume, bucket);
|
||||||
String objectKey = metadataManager.getOzoneKey(volume, bucket, keyName);
|
OmKeyInfo keyInfo = null;
|
||||||
OmKeyInfo keyInfo = metadataManager.getKeyTable().get(objectKey);
|
try {
|
||||||
if (keyInfo == null) {
|
OzoneFileStatus fileStatus = getFileStatus(args);
|
||||||
objectKey = OzoneFSUtils.addTrailingSlashIfNeeded(objectKey);
|
keyInfo = fileStatus.getKeyInfo();
|
||||||
keyInfo = metadataManager.getKeyTable().get(objectKey);
|
|
||||||
|
|
||||||
if (keyInfo == null) {
|
if (keyInfo == null) {
|
||||||
|
// the key does not exist, but it is a parent "dir" of some key
|
||||||
|
// let access be determined based on volume/bucket/prefix ACL
|
||||||
|
LOG.debug("key:{} is non-existent parent, permit access to user:{}",
|
||||||
|
keyName, context.getClientUgi());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (OMException e) {
|
||||||
|
if (e.getResult() == FILE_NOT_FOUND) {
|
||||||
keyInfo = metadataManager.getOpenKeyTable().get(objectKey);
|
keyInfo = metadataManager.getOpenKeyTable().get(objectKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (keyInfo == null) {
|
if (keyInfo == null) {
|
||||||
throw new OMException("Key not found, checkAccess failed. Key:" +
|
throw new OMException("Key not found, checkAccess failed. Key:" +
|
||||||
objectKey, KEY_NOT_FOUND);
|
objectKey, KEY_NOT_FOUND);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
boolean hasAccess = OzoneUtils.checkAclRight(keyInfo.getAcls(), context);
|
boolean hasAccess = OzoneUtils.checkAclRight(keyInfo.getAcls(), context);
|
||||||
LOG.debug("user:{} has access rights for key:{} :{} ",
|
LOG.debug("user:{} has access rights for key:{} :{} ",
|
||||||
context.getClientUgi(), ozObject.getKeyName(), hasAccess);
|
context.getClientUgi(), ozObject.getKeyName(), hasAccess);
|
||||||
|
|
Loading…
Reference in New Issue