Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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.hadoop.ozone.audit;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
* Utility class to read audit logs.
*/
public final class AuditLogTestUtils {
private static final String AUDITLOG_FILENAME = "audit.log";

private AuditLogTestUtils() {
}

/**
* Enables audit logging for the mini ozone cluster. Must be called in static
* block of the test class before starting the cluster.
*/
public static void enableAuditLog() {
System.setProperty("log4j.configurationFile", "auditlog.properties");
}

/**
* Searches for the given action in the audit log file.
*/
public static void verifyAuditLog(AuditAction action,
AuditEventStatus eventStatus) {
Path file = Paths.get(AUDITLOG_FILENAME);
try (BufferedReader br = Files.newBufferedReader(file,
StandardCharsets.UTF_8)) {
String line;
while ((line = br.readLine()) != null) {
if (line.contains(action.getAction()) &&
line.contains(eventStatus.getStatus())) {
return;
}
}
} catch (Exception e) {
throw new AssertionError(e);
} finally {
truncateAuditLogFile();
}
throw new AssertionError("Audit log file doesn't contain " +
"the message with params event=" + action.getAction() +
" result=" + eventStatus.getStatus());
}

private static void truncateAuditLogFile() {
File auditLogFile = new File(AUDITLOG_FILENAME);
try {
new FileOutputStream(auditLogFile).getChannel().truncate(0).close();
} catch (IOException e) {
System.out.println("Failed to truncate file: " + AUDITLOG_FILENAME);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,40 @@
*/
package org.apache.hadoop.ozone.om;

import java.util.ArrayList;
import java.util.UUID;

import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.ozone.MiniOzoneCluster;
import org.apache.hadoop.ozone.OzoneTestUtils;
import org.apache.hadoop.ozone.TestDataUtil;
import org.apache.hadoop.ozone.client.BucketArgs;
import org.apache.hadoop.ozone.audit.AuditEventStatus;
import org.apache.hadoop.ozone.audit.OMAction;
import org.apache.hadoop.ozone.client.ObjectStore;
import org.apache.hadoop.ozone.client.OzoneBucket;
import org.apache.hadoop.ozone.client.OzoneVolume;
import org.apache.hadoop.ozone.client.VolumeArgs;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer;
import org.apache.hadoop.ozone.security.acl.IOzoneObj;
import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
import org.apache.hadoop.ozone.security.acl.RequestContext;
import org.apache.hadoop.ozone.audit.AuditLogTestUtils;
import org.apache.ozone.test.GenericTestUtils;

import org.apache.commons.lang3.RandomStringUtils;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_AUTHORIZER_CLASS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS_WILDCARD;
import org.junit.AfterClass;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.Timeout;

import java.util.ArrayList;
import java.util.UUID;

import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_AUTHORIZER_CLASS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS_WILDCARD;
import static org.apache.hadoop.ozone.audit.AuditLogTestUtils.verifyAuditLog;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
* Test for Ozone Manager ACLs.
*/
Expand All @@ -65,15 +66,11 @@ public class TestOmAcls {
private static boolean keyAclAllow = true;
private static boolean prefixAclAllow = true;
private static MiniOzoneCluster cluster = null;
private static OMMetrics omMetrics;
private static OzoneConfiguration conf;
private static String clusterId;
private static String scmId;
private static String omId;
private static GenericTestUtils.LogCapturer logCapturer;

@Rule
public ExpectedException exception = ExpectedException.none();
static {
AuditLogTestUtils.enableAuditLog();
}

/**
* Create a MiniDFSCluster for testing.
Expand All @@ -82,10 +79,10 @@ public class TestOmAcls {
*/
@BeforeClass
public static void init() throws Exception {
conf = new OzoneConfiguration();
clusterId = UUID.randomUUID().toString();
scmId = UUID.randomUUID().toString();
omId = UUID.randomUUID().toString();
OzoneConfiguration conf = new OzoneConfiguration();
String clusterId = UUID.randomUUID().toString();
String scmId = UUID.randomUUID().toString();
String omId = UUID.randomUUID().toString();
conf.setBoolean(OZONE_ACL_ENABLED, true);
conf.setClass(OZONE_ACL_AUTHORIZER_CLASS, OzoneAccessAuthorizerTest.class,
IAccessAuthorizer.class);
Expand All @@ -96,99 +93,123 @@ public static void init() throws Exception {
.setOmId(omId)
.build();
cluster.waitForClusterToBeReady();
omMetrics = cluster.getOzoneManager().getMetrics();
logCapturer =
GenericTestUtils.LogCapturer.captureLogs(OzoneManager.getLogger());
}

/**
* Shutdown MiniDFSCluster.
*/
@AfterClass
public static void shutdown() {
if (cluster != null) {
cluster.shutdown();
}
}

/**
* Reset ACL.
*/
@Before
public void resetAcl() {
public void setup() {
logCapturer.clearOutput();

TestOmAcls.volumeAclAllow = true;
TestOmAcls.bucketAclAllow = true;
TestOmAcls.keyAclAllow = true;
TestOmAcls.prefixAclAllow = true;
}

@Test
public void testBucketCreationPermissionDenied() throws Exception {
public void testCreateVolumePermissionDenied() {
TestOmAcls.volumeAclAllow = false;

String volumeName = RandomStringUtils.randomAlphabetic(5).toLowerCase();
String bucketName = RandomStringUtils.randomAlphabetic(5).toLowerCase();
OMException exception = assertThrows(OMException.class,
() -> TestDataUtil.createVolumeAndBucket(cluster));
assertEquals(ResultCodes.PERMISSION_DENIED, exception.getResult());

VolumeArgs createVolumeArgs = VolumeArgs.newBuilder()
.setOwner("user" + RandomStringUtils.randomNumeric(5))
.setAdmin("admin" + RandomStringUtils.randomNumeric(5))
.build();
assertTrue(logCapturer.getOutput()
.contains("doesn't have CREATE permission to access volume"));
verifyAuditLog(OMAction.CREATE_VOLUME, AuditEventStatus.FAILURE);
}

cluster.getClient().getObjectStore().createVolume(volumeName,
createVolumeArgs);
OzoneVolume volume =
cluster.getClient().getObjectStore().getVolume(volumeName);
@Test
public void testReadVolumePermissionDenied() throws Exception {
OzoneBucket bucket = TestDataUtil.createVolumeAndBucket(cluster);
TestOmAcls.volumeAclAllow = false;
ObjectStore objectStore = cluster.getClient().getObjectStore();
OMException exception = assertThrows(OMException.class, () ->
objectStore.getVolume(bucket.getVolumeName()));
assertEquals(ResultCodes.PERMISSION_DENIED, exception.getResult());

assertTrue(logCapturer.getOutput()
.contains("doesn't have READ permission to access volume"));
verifyAuditLog(OMAction.READ_VOLUME, AuditEventStatus.FAILURE);
}

@Test
public void testCreateBucketPermissionDenied() {
TestOmAcls.bucketAclAllow = false;
OzoneTestUtils.expectOmException(ResultCodes.PERMISSION_DENIED,
() -> volume.createBucket(bucketName));

OMException exception = assertThrows(OMException.class,
() -> TestDataUtil.createVolumeAndBucket(cluster));
assertEquals(ResultCodes.PERMISSION_DENIED, exception.getResult());

assertTrue(logCapturer.getOutput()
.contains("doesn't have CREATE permission to access bucket"));
.contains("doesn't have CREATE permission to access bucket"));
verifyAuditLog(OMAction.CREATE_BUCKET, AuditEventStatus.FAILURE);
}

@Test
public void testFailureInKeyOp() throws Exception {
final VolumeArgs createVolumeArgs;

public void testReadBucketPermissionDenied() throws Exception {
OzoneBucket bucket = TestDataUtil.createVolumeAndBucket(cluster);
logCapturer.clearOutput();
TestOmAcls.bucketAclAllow = false;
ObjectStore objectStore = cluster.getClient().getObjectStore();
OMException exception = assertThrows(OMException.class,
() -> objectStore.getVolume(
bucket.getVolumeName()).getBucket(bucket.getName())
);

assertEquals(ResultCodes.PERMISSION_DENIED, exception.getResult());
assertTrue(logCapturer.getOutput()
.contains("doesn't have READ permission to access bucket"));
verifyAuditLog(OMAction.READ_BUCKET, AuditEventStatus.FAILURE);
}

@Test
public void testCreateKeyPermissionDenied() throws Exception {
TestOmAcls.keyAclAllow = false;

OzoneTestUtils.expectOmException(ResultCodes.PERMISSION_DENIED,
() -> TestDataUtil.createKey(bucket, "testKey", "testcontent"));
OzoneBucket bucket = TestDataUtil.createVolumeAndBucket(cluster);

OMException exception = assertThrows(OMException.class,
() -> TestDataUtil.createKey(bucket, "testKey", "testcontent"));
assertEquals(ResultCodes.PERMISSION_DENIED, exception.getResult());
assertTrue(logCapturer.getOutput().contains("doesn't have CREATE " +
"permission to access key"));
"permission to access key"));
}

@Test
public void testSetACLPermissionDenied() throws Exception {

String volumeName = RandomStringUtils.randomAlphabetic(5).toLowerCase();
String bucketName = RandomStringUtils.randomAlphabetic(5).toLowerCase();
public void testReadKeyPermissionDenied() throws Exception {
OzoneBucket bucket = TestDataUtil.createVolumeAndBucket(cluster);
TestDataUtil.createKey(bucket, "testKey", "testcontent");

VolumeArgs createVolumeArgs = VolumeArgs.newBuilder()
.setOwner("user" + RandomStringUtils.randomNumeric(5))
.setAdmin("admin" + RandomStringUtils.randomNumeric(5))
.build();
BucketArgs createBucketArgs = BucketArgs.newBuilder()
.setOwner("user" + RandomStringUtils.randomNumeric(5))
.build();
TestOmAcls.keyAclAllow = false;
OMException exception = assertThrows(OMException.class,
() -> TestDataUtil.getKey(bucket, "testKey"));

cluster.getClient().getObjectStore().createVolume(volumeName,
createVolumeArgs);
OzoneVolume volume =
cluster.getClient().getObjectStore().getVolume(volumeName);
volume.createBucket(bucketName, createBucketArgs);
assertEquals(ResultCodes.PERMISSION_DENIED, exception.getResult());
assertTrue(logCapturer.getOutput().contains("doesn't have READ " +
"permission to access key"));
verifyAuditLog(OMAction.READ_KEY, AuditEventStatus.FAILURE);
}

OzoneBucket bucket = volume.getBucket(bucketName);
@Test
public void testSetACLPermissionDenied() throws Exception {
OzoneBucket bucket = TestDataUtil.createVolumeAndBucket(cluster);

TestOmAcls.bucketAclAllow = false;
OzoneTestUtils.expectOmException(ResultCodes.PERMISSION_DENIED,
() -> bucket.setAcl(new ArrayList<>()));

OMException exception = assertThrows(OMException.class,
() -> bucket.setAcl(new ArrayList<>()));
assertEquals(ResultCodes.PERMISSION_DENIED, exception.getResult());
assertTrue(logCapturer.getOutput()
.contains("doesn't have WRITE_ACL permission to access bucket"));
verifyAuditLog(OMAction.SET_ACL, AuditEventStatus.FAILURE);
}

/**
Expand Down
Loading