You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by bh...@apache.org on 2021/11/01 18:58:12 UTC
[ozone] branch master updated: HDDS-5885. OM Auth Validate for read
requests and handle non ratis enabled code. (#2779)
This is an automated email from the ASF dual-hosted git repository.
bharat pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 5c76856 HDDS-5885. OM Auth Validate for read requests and handle non ratis enabled code. (#2779)
5c76856 is described below
commit 5c76856e68599a50cbf2fc4d57fed8ac84332f3d
Author: Bharat Viswanadham <bh...@apache.org>
AuthorDate: Mon Nov 1 11:57:46 2021 -0700
HDDS-5885. OM Auth Validate for read requests and handle non ratis enabled code. (#2779)
---
.../ozone/client/rpc/TestSecureOzoneRpcClient.java | 39 +++++++++++++++++--
.../org/apache/hadoop/ozone/om/OzoneManager.java | 30 ++++++++++++++-
...OzoneManagerProtocolServerSideTranslatorPB.java | 45 ++++++++++++++++++----
.../hadoop/ozone/security/S3SecurityUtil.java | 26 ++++++-------
4 files changed, 115 insertions(+), 25 deletions(-)
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestSecureOzoneRpcClient.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestSecureOzoneRpcClient.java
index f27184a..4886110 100644
--- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestSecureOzoneRpcClient.java
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestSecureOzoneRpcClient.java
@@ -46,6 +46,7 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateVolumeRequest;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoVolumeRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Authentication;
@@ -241,7 +242,7 @@ public class TestSecureOzoneRpcClient extends TestOzoneRpcClient {
cluster.getOzoneManager().getMetadataManager().getS3SecretTable().put(
accessKey, new S3SecretValue(accessKey, secret));
- OMRequest omRequest = OMRequest.newBuilder()
+ OMRequest writeRequest = OMRequest.newBuilder()
.setCmdType(OzoneManagerProtocolProtos.Type.CreateVolume)
.setVersion(CURRENT_VERSION)
.setClientId(UUID.randomUUID().toString())
@@ -257,18 +258,50 @@ public class TestSecureOzoneRpcClient extends TestOzoneRpcClient {
GenericTestUtils.waitFor(() -> cluster.getOzoneManager().isLeaderReady(),
100, 120000);
OMResponse omResponse = cluster.getOzoneManager().getOmServerProtocol()
- .submitRequest(null, omRequest);
+ .submitRequest(null, writeRequest);
+ // Verify response.
Assert.assertTrue(omResponse.getStatus() == Status.OK);
+ // Read Request
+ OMRequest readRequest = OMRequest.newBuilder()
+ .setCmdType(OzoneManagerProtocolProtos.Type.InfoVolume)
+ .setVersion(CURRENT_VERSION)
+ .setClientId(UUID.randomUUID().toString())
+ .setInfoVolumeRequest(InfoVolumeRequest.newBuilder()
+ .setVolumeName(volumeName).build())
+ .setS3Authentication(S3Authentication.newBuilder()
+ .setAccessId(accessKey)
+ .setSignature(signature).setStringToSign(strToSign))
+ .build();
+
+ omResponse = cluster.getOzoneManager().getOmServerProtocol()
+ .submitRequest(null, readRequest);
+
+ // Verify response.
+ Assert.assertTrue(omResponse.getStatus() == Status.OK);
+
+ VolumeInfo volumeInfo = omResponse.getInfoVolumeResponse().getVolumeInfo();
+ Assert.assertNotNull(volumeInfo);
+ Assert.assertEquals(volumeName, volumeInfo.getVolume());
+ Assert.assertEquals(accessKey, volumeInfo.getAdminName());
+ Assert.assertEquals(accessKey, volumeInfo.getOwnerName());
// Override secret to S3Secret table with some dummy value
cluster.getOzoneManager().getMetadataManager().getS3SecretTable().put(
accessKey, new S3SecretValue(accessKey, "dummy"));
+
+ // Write request with invalid credentials.
omResponse = cluster.getOzoneManager().getOmServerProtocol()
- .submitRequest(null, omRequest);
+ .submitRequest(null, writeRequest);
Assert.assertTrue(omResponse.getStatus() == Status.INVALID_TOKEN);
+ // Read request with invalid credentials.
+ omResponse = cluster.getOzoneManager().getOmServerProtocol()
+ .submitRequest(null, readRequest);
+ Assert.assertTrue(omResponse.getStatus() == Status.INVALID_TOKEN);
+
+
}
private boolean verifyRatisReplication(String volumeName, String bucketName,
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index 0750b30..b52b3b1 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -143,6 +143,7 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DBUpdatesRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRoleInfo;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Authentication;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServicePort;
import org.apache.hadoop.ozone.protocolPB.OMInterServiceProtocolServerSideImpl;
import org.apache.hadoop.ozone.storage.proto.OzoneManagerStorageProtos.PersistedUserVolumeInfo;
@@ -270,6 +271,11 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
private static final String OM_DAEMON = "om";
+ // This is set for read requests when OMRequest has S3Authentication set,
+ // and it is reset when read request is processed.
+ private static final ThreadLocal<S3Authentication> S3_AUTH =
+ new ThreadLocal<>();
+
private static boolean securityEnabled = false;
private OzoneDelegationTokenSecretManager delegationTokenMgr;
private OzoneBlockTokenSecretManager blockTokenMgr;
@@ -541,6 +547,20 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
}
/**
+ * Set the {@link S3Authentication} for the current rpc handler thread.
+ */
+ public static void setS3Auth(S3Authentication val) {
+ S3_AUTH.set(val);
+ }
+
+ /**
+ * Returns the {@link S3Authentication} for the current rpc handler thread.
+ */
+ public static S3Authentication getS3Auth() {
+ return S3_AUTH.get();
+ }
+
+ /**
* This method is used to set selected instance variables in this class from
* the passed in config. This allows these variable to be reset when the OM
* instance is restarted (normally from a test mini-cluster). Note, not all
@@ -1989,8 +2009,16 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
private void checkAcls(ResourceType resType, StoreType store,
ACLType acl, String vol, String bucket, String key)
throws IOException {
- UserGroupInformation user = ProtobufRpcEngine.Server.getRemoteUser();
+ UserGroupInformation user;
+ if (getS3Auth() != null) {
+ user = UserGroupInformation.createRemoteUser(
+ getS3Auth().getAccessId());
+ } else {
+ user = ProtobufRpcEngine.Server.getRemoteUser();
+ }
+
InetAddress remoteIp = ProtobufRpcEngine.Server.getRemoteIp();
+
checkAcls(resType, store, acl, vol, bucket, key,
user != null ? user : getRemoteUser(),
remoteIp != null ? remoteIp : omRpcAddress.getAddress(),
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
index 905ca67..7946f65 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerProtocolServerSideTranslatorPB.java
@@ -128,17 +128,36 @@ public class OzoneManagerProtocolServerSideTranslatorPB implements
private OMResponse processRequest(OMRequest request) throws
ServiceException {
if (isRatisEnabled) {
+ boolean s3Auth = false;
+ try {
+ // If Request has S3Authentication validate S3 credentials
+ // if current OM is leader and then proceed with processing the request.
+ if (request.hasS3Authentication()) {
+ s3Auth = true;
+ checkLeaderStatus();
+ S3SecurityUtil.validateS3Credential(request, ozoneManager);
+ }
+ } catch (IOException ex) {
+ // If validate credentials fail return error OM Response.
+ return createErrorResponse(request, ex);
+ }
// Check if the request is a read only request
if (OmUtils.isReadOnly(request)) {
- return submitReadRequestToOM(request);
- } else {
- checkLeaderStatus();
try {
- // If Request has S3Authentication validate S3 credentials and
- // then proceed with processing the request.
if (request.hasS3Authentication()) {
- S3SecurityUtil.validateS3Credential(request, ozoneManager);
+ ozoneManager.setS3Auth(request.getS3Authentication());
}
+ return submitReadRequestToOM(request);
+ } finally {
+ ozoneManager.setS3Auth(null);
+ }
+ } else {
+ // To validate credentials we have already verified leader status.
+ // This will skip of checking leader status again if request has S3Auth.
+ if (!s3Auth) {
+ checkLeaderStatus();
+ }
+ try {
OMClientRequest omClientRequest =
createClientRequest(request, ozoneManager);
request = omClientRequest.preExecute(ozoneManager);
@@ -215,8 +234,20 @@ public class OzoneManagerProtocolServerSideTranslatorPB implements
OMClientResponse omClientResponse = null;
long index = 0L;
try {
+ // If Request has S3Authentication validate S3 credentials and
+ // then proceed with processing the request.
+ if (request.hasS3Authentication()) {
+ S3SecurityUtil.validateS3Credential(request, ozoneManager);
+ }
if (OmUtils.isReadOnly(request)) {
- return handler.handleReadRequest(request);
+ try {
+ if (request.hasS3Authentication()) {
+ ozoneManager.setS3Auth(request.getS3Authentication());
+ }
+ return handler.handleReadRequest(request);
+ } finally {
+ ozoneManager.setS3Auth(null);
+ }
} else {
OMClientRequest omClientRequest =
createClientRequest(request, ozoneManager);
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/S3SecurityUtil.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/S3SecurityUtil.java
index b9e2a05..377eec8 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/S3SecurityUtil.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/security/S3SecurityUtil.java
@@ -50,20 +50,18 @@ public final class S3SecurityUtil {
public static void validateS3Credential(OMRequest omRequest,
OzoneManager ozoneManager) throws OMException {
if (ozoneManager.isSecurityEnabled()) {
- if (omRequest.hasS3Authentication()) {
- OzoneTokenIdentifier s3Token = constructS3Token(omRequest);
- try {
- // authenticate user with signature verification through
- // delegationTokenMgr validateToken via retrievePassword
- ozoneManager.getDelegationTokenMgr().retrievePassword(s3Token);
- } catch (SecretManager.InvalidToken e) {
- // TODO: Just check are we okay to log enitre token in failure case.
- OzoneManagerProtocolServerSideTranslatorPB.getLog().error(
- "signatures do NOT match for S3 identifier:{}", s3Token, e);
- throw new OMException("User " + s3Token.getAwsAccessId()
- + " request authorization failure: signatures do NOT match",
- INVALID_TOKEN);
- }
+ OzoneTokenIdentifier s3Token = constructS3Token(omRequest);
+ try {
+ // authenticate user with signature verification through
+ // delegationTokenMgr validateToken via retrievePassword
+ ozoneManager.getDelegationTokenMgr().retrievePassword(s3Token);
+ } catch (SecretManager.InvalidToken e) {
+ // TODO: Just check are we okay to log enitre token in failure case.
+ OzoneManagerProtocolServerSideTranslatorPB.getLog().error(
+ "signatures do NOT match for S3 identifier:{}", s3Token, e);
+ throw new OMException("User " + s3Token.getAwsAccessId()
+ + " request authorization failure: signatures do NOT match",
+ INVALID_TOKEN);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org