Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.apache.hadoop.ozone.om.helpers.TenantUserInfoValue;
import org.apache.hadoop.ozone.om.helpers.TenantUserList;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteTenantResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3VolumeResponse;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
import org.apache.hadoop.ozone.security.acl.OzoneObj;
import org.apache.hadoop.security.UserGroupInformation;
Expand Down Expand Up @@ -154,7 +155,11 @@ public OzoneVolume getVolume(String volumeName) throws IOException {
}

public OzoneVolume getS3Volume() throws IOException {
return proxy.getS3VolumeDetails();
return proxy.getS3Volume();
}

public GetS3VolumeResponse getS3VolumeInfo() throws IOException {
return proxy.getS3VolumeInfo();
}

public S3SecretValue getS3Secret(String kerberosID) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.OmMultipartInfo;
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadCompleteInfo;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
import org.apache.hadoop.ozone.om.helpers.RepeatedOmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
Expand All @@ -54,6 +55,7 @@
import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
import org.apache.hadoop.ozone.om.protocol.S3Auth;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteTenantResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3VolumeResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRoleInfo;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
import org.apache.hadoop.ozone.security.acl.OzoneObj;
Expand Down Expand Up @@ -125,10 +127,17 @@ OzoneVolume getVolumeDetails(String volumeName)

/**
* @return The {@link OzoneVolume} that should be used to for this S3
* request based on its access ID.
* request based on its access ID. S3Auth user principal will be updated.
*/
OzoneVolume getS3Volume() throws IOException;

/**
* @return Raw GetS3VolumeResponse. S3Auth won't be updated.
* @throws IOException
*/
OzoneVolume getS3VolumeDetails() throws IOException;
GetS3VolumeResponse getS3VolumeInfo() throws IOException;

OzoneVolume buildOzoneVolume(OmVolumeArgs volume);

/**
* Checks if a Volume exists and the user with a role specified has access
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerClientProtocol;
import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolClientSideTranslatorPB;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteTenantResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3VolumeResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRoleInfo;
import org.apache.hadoop.ozone.security.GDPRSymmetricKey;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
Expand Down Expand Up @@ -437,12 +438,27 @@ public OzoneVolume getVolumeDetails(String volumeName)
}

@Override
public OzoneVolume getS3VolumeDetails() throws IOException {
OmVolumeArgs volume = ozoneManagerClient.getS3Volume();
public OzoneVolume getS3Volume() throws IOException {
Comment thread
smengcl marked this conversation as resolved.
Outdated
final GetS3VolumeResponse resp = getS3VolumeInfo();

// Update user principal, to be used for KMS
S3Auth s3Auth = getThreadLocalS3Auth();
if (s3Auth != null) {
LOG.info("Updating S3Auth->UserPrincipal"); // TODO: Switch to debug
Comment thread
smengcl marked this conversation as resolved.
Outdated
s3Auth.setUserPrincipal(resp.getUserPrincipal());
setTheadLocalS3Auth(s3Auth);
}

OmVolumeArgs volume = OmVolumeArgs.getFromProtobuf(resp.getVolumeInfo());
return buildOzoneVolume(volume);
}

private OzoneVolume buildOzoneVolume(OmVolumeArgs volume) {
@Override
public GetS3VolumeResponse getS3VolumeInfo() throws IOException {
return ozoneManagerClient.getS3VolumeInfo();
}

public OzoneVolume buildOzoneVolume(OmVolumeArgs volume) {
return new OzoneVolume(
conf,
this,
Expand Down Expand Up @@ -1062,8 +1078,10 @@ private KeyProvider.KeyVersion getDEK(FileEncryptionInfo feInfo)
UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
UserGroupInformation proxyUser;
if (getThreadLocalS3Auth() != null) {
String userPrincipal = getThreadLocalS3Auth().getUserPrincipal();
Preconditions.checkNotNull(userPrincipal);
UserGroupInformation s3gUGI = UserGroupInformation.createRemoteUser(
getThreadLocalS3Auth().getAccessID());
userPrincipal);
proxyUser = UserGroupInformation.createProxyUser(
s3gUGI.getShortUserName(), loginUser);
decrypted = proxyUser.doAs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.apache.hadoop.ozone.om.helpers.TenantUserList;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteTenantResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3VolumeResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneAclInfo;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareStatusResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareStatusResponse.PrepareStatus;
Expand Down Expand Up @@ -617,7 +618,7 @@ default S3SecretValue tenantAssignUserAccessId(String username,
"this to be implemented, as write requests use a new approach");
}

OmVolumeArgs getS3Volume() throws IOException;
GetS3VolumeResponse getS3VolumeInfo() throws IOException;

/**
* Revoke user accessId to a tenant.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@ public class S3Auth {
private String signature;
private String accessID;
public static final String S3_AUTH_CHECK = "ozone.s3.auth.check";
// User principal to be used for KMS encryption and decryption
private String userPrincipal;

public S3Auth(final String stringToSign,
final String signature, final String accessID) {
final String signature,
final String accessID,
final String userPrincipal) {
this.accessID = accessID;
this.stringToSign = stringToSign;
this.signature = signature;
this.userPrincipal = userPrincipal;
}
public String getStringTosSign() {
return stringToSign;
Expand All @@ -43,4 +48,12 @@ public String getSignature() {
public String getAccessID() {
return accessID;
}

public String getUserPrincipal() {
return userPrincipal;
}

public void setUserPrincipal(String userPrincipal) {
this.userPrincipal = userPrincipal;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1124,17 +1124,15 @@ public TenantUserList listUsersInTenant(String tenantName, String prefix)
}

@Override
public OmVolumeArgs getS3Volume() throws IOException {
public GetS3VolumeResponse getS3VolumeInfo() throws IOException {
final GetS3VolumeRequest request = GetS3VolumeRequest.newBuilder()
.build();
final OMRequest omRequest = createOMRequest(Type.GetS3Volume)
.setGetS3VolumeRequest(request)
.build();
final OMResponse omResponse = submitRequest(omRequest);
final GetS3VolumeResponse resp = handleError(omResponse)
.getGetS3VolumeResponse();

return OmVolumeArgs.getFromProtobuf(resp.getVolumeInfo());
return handleError(omResponse).getGetS3VolumeResponse();
Comment thread
smengcl marked this conversation as resolved.
Outdated
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ private ObjectStore getStoreForAccessID(String accessID) throws Exception {
// Manually construct an object store instead of using the cluster
// provided one so we can specify the access ID.
RpcClient client = new RpcClient(conf, null);
client.setTheadLocalS3Auth(new S3Auth("unused1", "unused2", accessID));
client.setTheadLocalS3Auth(
new S3Auth("unused1", "unused2", accessID, accessID));
Comment thread
smengcl marked this conversation as resolved.
return new ObjectStore(conf, client);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,8 @@ message OmDBAccessInfo {

message GetS3VolumeResponse {
optional VolumeInfo volumeInfo = 1;
// Piggybacked user name (principal) response to be used for KMS operations
optional string userPrincipal = 2;
Comment thread
smengcl marked this conversation as resolved.
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public static void setOMMultiTenantManager(
* If the access ID does not belong to a tenant, the access ID is returned
* as is to be used as the principal.
*/
// TODO: Should be named accessIdToPrincipal instead?
Comment thread
smengcl marked this conversation as resolved.
Outdated
public static String principalToAccessID(String accessID) throws IOException {
String principal = multiTenantManager.getUserNameGivenAccessId(accessID);
if (principal == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerAdminProtocolProtos.OzoneManagerAdminService;
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.GetS3VolumeResponse;
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;
Expand Down Expand Up @@ -3077,12 +3078,14 @@ public TenantUserList listUsersInTenant(String tenantId, String prefix)
}

@Override
public OmVolumeArgs getS3Volume() throws IOException {
public GetS3VolumeResponse getS3VolumeInfo() throws IOException {
// Unless the OM request contains S3 authentication info with an access
// ID that corresponds to a tenant volume, the request will be directed
// to the default S3 volume.
String s3Volume = HddsClientUtils.getDefaultS3VolumeName(configuration);
S3Authentication s3Auth = getS3Auth();
// TODO: Double check return value
String userPrincipal = Server.getRemoteUser().getShortUserName();
Comment thread
smengcl marked this conversation as resolved.

if (s3Auth != null) {
String accessID = s3Auth.getAccessId();
Expand Down Expand Up @@ -3110,6 +3113,9 @@ public OmVolumeArgs getS3Volume() throws IOException {
"tenant {} is directed to the volume {}.", accessID, tenantId,
s3Volume);
}

// Inject user name to the response to be used for KMS on the client
userPrincipal = OzoneAclUtils.principalToAccessID(accessID);
Comment thread
smengcl marked this conversation as resolved.
Outdated
} else if (LOG.isDebugEnabled()) {
LOG.debug("No tenant found for access ID {}. Directing " +
"requests to default s3 volume {}.", accessID, s3Volume);
Expand All @@ -3123,8 +3129,13 @@ public OmVolumeArgs getS3Volume() throws IOException {
s3Volume);
}

// This call performs acl checks and checks volume existence.
return getVolumeInfo(s3Volume);
// getVolumeInfo() performs acl checks and checks volume existence.
final GetS3VolumeResponse resp = GetS3VolumeResponse.newBuilder()
.setVolumeInfo(getVolumeInfo(s3Volume).getProtobuf())
.setUserPrincipal(userPrincipal)
.build();

return resp;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ public OMResponse handleReadRequest(OMRequest request) {
responseBuilder.setPrepareStatusResponse(prepareStatusResponse);
break;
case GetS3Volume:
GetS3VolumeResponse s3VolumeResponse = getS3Volume();
GetS3VolumeResponse s3VolumeResponse = getS3VolumeInfo();
responseBuilder.setGetS3VolumeResponse(s3VolumeResponse);
break;
case TenantGetUserInfo:
Expand Down Expand Up @@ -708,12 +708,9 @@ private PrepareStatusResponse getPrepareStatus() {
.setCurrentTxnIndex(prepareState.getIndex()).build();
}

private GetS3VolumeResponse getS3Volume()
private GetS3VolumeResponse getS3VolumeInfo()
throws IOException {
OmVolumeArgs s3VolArgs = impl.getS3Volume();
return GetS3VolumeResponse.newBuilder()
.setVolumeInfo(s3VolArgs.getProtobuf())
.build();
return impl.getS3VolumeInfo();
}

public OzoneManager getOzoneManager() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public S3Auth getSignature() {
validateAccessId(awsAccessId);
return new S3Auth(stringToSign,
signatureInfo.getSignature(),
awsAccessId);
awsAccessId, awsAccessId);
} catch (OS3Exception ex) {
LOG.debug("Error during Client Creation: ", ex);
throw wrapOS3Exception(ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ protected void execute(OzoneClient client, OzoneAddress address) {
objStore.tenantAssignAdmin(accessId, tenantId, delegated);
// TODO: Make tenantAssignAdmin return accessId, tenantName, user later.
err().println("Assigned admin to '" + accessId +
(tenantId != null ? "' in tenant '" + tenantId + "'" : ""));
(tenantId != null ? "' in tenant '" + tenantId : "") + "'");
} catch (IOException e) {
err().println("Failed to assign admin to '" + accessId +
(tenantId != null ? "' in tenant '" + tenantId + "'" : "") +
": " + e.getMessage());
(tenantId != null ? "' in tenant '" + tenantId : "") + "': " +
e.getMessage());
if (e instanceof OMException) {
final OMException omEx = (OMException) e;
// Don't bother continuing the loop if current user isn't Ozone admin
Expand Down