Search in sources :

Example 1 with UpdateGetS3SecretRequest

use of org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest in project ozone by apache.

the class S3GetSecretRequest method preExecute.

@Override
public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
    final GetS3SecretRequest s3GetSecretRequest = getOmRequest().getGetS3SecretRequest();
    // The proto field kerberosID is effectively accessId w/ Multi-Tenancy
    // 
    // But it is still named kerberosID because kerberosID == accessId before
    // multi-tenancy feature is implemented. And renaming proto field fails the
    // protolock check.
    final String accessId = s3GetSecretRequest.getKerberosID();
    final UserGroupInformation ugi = ProtobufRpcEngine.Server.getRemoteUser();
    // Permission check
    S3SecretRequestHelper.checkAccessIdSecretOpPermission(ozoneManager, ugi, accessId);
    // Client issues GetS3Secret request, when received by OM leader
    // it will generate s3Secret. Original GetS3Secret request is
    // converted to UpdateGetS3Secret request with the generated token
    // information. This updated request will be submitted to Ratis. In this
    // way S3Secret created by leader, will be replicated across all
    // OMs. With this approach, original GetS3Secret request from
    // client does not need any proto changes.
    OMRequest.Builder omRequest = OMRequest.newBuilder().setUserInfo(getUserInfo()).setCmdType(getOmRequest().getCmdType()).setClientId(getOmRequest().getClientId());
    // createIfNotExist defaults to true if not specified.
    boolean createIfNotExist = !s3GetSecretRequest.hasCreateIfNotExist() || s3GetSecretRequest.getCreateIfNotExist();
    // Recompose GetS3SecretRequest just in case createIfNotExist is missing
    final GetS3SecretRequest newGetS3SecretRequest = GetS3SecretRequest.newBuilder().setKerberosID(// See Note 1 above
    accessId).setCreateIfNotExist(createIfNotExist).build();
    omRequest.setGetS3SecretRequest(newGetS3SecretRequest);
    // otherwise, just use GetS3SecretRequest message.
    if (createIfNotExist) {
        // Generate secret here because this will be written to DB only when
        // createIfNotExist is true and accessId entry doesn't exist in DB.
        String s3Secret = DigestUtils.sha256Hex(OmUtils.getSHADigest());
        final UpdateGetS3SecretRequest updateGetS3SecretRequest = UpdateGetS3SecretRequest.newBuilder().setKerberosID(// See Note 1 above
        accessId).setAwsSecret(s3Secret).build();
        omRequest.setUpdateGetS3SecretRequest(updateGetS3SecretRequest);
    }
    if (getOmRequest().hasTraceID()) {
        omRequest.setTraceID(getOmRequest().getTraceID());
    }
    return omRequest.build();
}
Also used : OMRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest) UpdateGetS3SecretRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest) GetS3SecretRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3SecretRequest) UpdateGetS3SecretRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest) UserGroupInformation(org.apache.hadoop.security.UserGroupInformation)

Example 2 with UpdateGetS3SecretRequest

use of org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest in project ozone by apache.

the class S3GetSecretRequest method validateAndUpdateCache.

@Override
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, long transactionLogIndex, OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) {
    OMClientResponse omClientResponse = null;
    OMResponse.Builder omResponse = OmResponseUtil.getOMResponseBuilder(getOmRequest());
    boolean acquiredLock = false;
    IOException exception = null;
    OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
    final GetS3SecretRequest getS3SecretRequest = getOmRequest().getGetS3SecretRequest();
    assert (getS3SecretRequest.hasCreateIfNotExist());
    final boolean createIfNotExist = getS3SecretRequest.getCreateIfNotExist();
    // See Note 1 above
    final String accessId = getS3SecretRequest.getKerberosID();
    String awsSecret = null;
    if (createIfNotExist) {
        final UpdateGetS3SecretRequest updateGetS3SecretRequest = getOmRequest().getUpdateGetS3SecretRequest();
        awsSecret = updateGetS3SecretRequest.getAwsSecret();
        assert (accessId.equals(updateGetS3SecretRequest.getKerberosID()));
    }
    try {
        acquiredLock = omMetadataManager.getLock().acquireWriteLock(S3_SECRET_LOCK, accessId);
        final S3SecretValue assignS3SecretValue;
        final S3SecretValue s3SecretValue = omMetadataManager.getS3SecretTable().get(accessId);
        if (s3SecretValue == null) {
            // Not found in S3SecretTable.
            if (createIfNotExist) {
                // Add new entry in this case
                assignS3SecretValue = new S3SecretValue(accessId, awsSecret);
                // Add cache entry first.
                omMetadataManager.getS3SecretTable().addCacheEntry(new CacheKey<>(accessId), new CacheValue<>(Optional.of(assignS3SecretValue), transactionLogIndex));
            } else {
                assignS3SecretValue = null;
            }
        } else {
            // Found in S3SecretTable.
            awsSecret = s3SecretValue.getAwsSecret();
            assignS3SecretValue = null;
        }
        // when createIfNotExist is false.
        if (awsSecret == null) {
            assert (!createIfNotExist);
            throw new OMException("accessId '" + accessId + "' doesn't exist", OMException.ResultCodes.ACCESS_ID_NOT_FOUND);
        }
        // Compose response
        final GetS3SecretResponse.Builder getS3SecretResponse = GetS3SecretResponse.newBuilder().setS3Secret(S3Secret.newBuilder().setAwsSecret(awsSecret).setKerberosID(// See Note 1 above
        accessId));
        // If entry exists or createIfNotExist is false, assignS3SecretValue
        // will be null, so we won't write or overwrite the entry.
        omClientResponse = new S3GetSecretResponse(assignS3SecretValue, omResponse.setGetS3SecretResponse(getS3SecretResponse).build());
    } catch (IOException ex) {
        exception = ex;
        omClientResponse = new S3GetSecretResponse(null, createErrorOMResponse(omResponse, ex));
    } finally {
        addResponseToDoubleBuffer(transactionLogIndex, omClientResponse, ozoneManagerDoubleBufferHelper);
        if (acquiredLock) {
            omMetadataManager.getLock().releaseWriteLock(S3_SECRET_LOCK, accessId);
        }
    }
    Map<String, String> auditMap = new HashMap<>();
    auditMap.put(OzoneConsts.S3_GETSECRET_USER, accessId);
    // audit log
    auditLog(ozoneManager.getAuditLogger(), buildAuditMessage(OMAction.GET_S3_SECRET, auditMap, exception, getOmRequest().getUserInfo()));
    if (exception == null) {
        LOG.debug("Success: GetSecret for accessKey '{}', createIfNotExist '{}'", accessId, createIfNotExist);
    } else {
        LOG.error("Failed to GetSecret for accessKey '{}', createIfNotExist " + "'{}': {}", accessId, createIfNotExist, exception);
    }
    return omClientResponse;
}
Also used : GetS3SecretRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3SecretRequest) UpdateGetS3SecretRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest) OMClientResponse(org.apache.hadoop.ozone.om.response.OMClientResponse) HashMap(java.util.HashMap) IOException(java.io.IOException) S3SecretValue(org.apache.hadoop.ozone.om.helpers.S3SecretValue) OMResponse(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse) UpdateGetS3SecretRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest) S3GetSecretResponse(org.apache.hadoop.ozone.om.response.s3.security.S3GetSecretResponse) OMMetadataManager(org.apache.hadoop.ozone.om.OMMetadataManager) OMException(org.apache.hadoop.ozone.om.exceptions.OMException) GetS3SecretResponse(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3SecretResponse)

Example 3 with UpdateGetS3SecretRequest

use of org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest in project ozone by apache.

the class OMTenantAssignUserAccessIdRequest method validateAndUpdateCache.

@Override
@SuppressWarnings("checkstyle:methodlength")
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, long transactionLogIndex, OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) {
    final OMMultiTenantManager multiTenantManager = ozoneManager.getMultiTenantManager();
    final OMMetrics omMetrics = ozoneManager.getMetrics();
    omMetrics.incNumTenantAssignUsers();
    OMClientResponse omClientResponse = null;
    final OMResponse.Builder omResponse = OmResponseUtil.getOMResponseBuilder(getOmRequest());
    final UpdateGetS3SecretRequest updateGetS3SecretRequest = getOmRequest().getUpdateGetS3SecretRequest();
    final String accessId = updateGetS3SecretRequest.getKerberosID();
    final String awsSecret = updateGetS3SecretRequest.getAwsSecret();
    boolean acquiredVolumeLock = false;
    boolean acquiredS3SecretLock = false;
    final Map<String, String> auditMap = new HashMap<>();
    final OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
    final TenantAssignUserAccessIdRequest request = getOmRequest().getTenantAssignUserAccessIdRequest();
    final String tenantId = request.getTenantId();
    final String userPrincipal = request.getUserPrincipal();
    Preconditions.checkState(accessId.equals(request.getAccessId()));
    IOException exception = null;
    String volumeName = null;
    try {
        volumeName = ozoneManager.getMultiTenantManager().getTenantVolumeName(tenantId);
        acquiredVolumeLock = omMetadataManager.getLock().acquireWriteLock(VOLUME_LOCK, volumeName);
        // Expect tenant existence in tenantStateTable
        if (!omMetadataManager.getTenantStateTable().isExist(tenantId)) {
            LOG.error("tenant {} doesn't exist", tenantId);
            throw new OMException("tenant '" + tenantId + "' doesn't exist", ResultCodes.TENANT_NOT_FOUND);
        }
        // Expect accessId absence from tenantAccessIdTable
        if (omMetadataManager.getTenantAccessIdTable().isExist(accessId)) {
            LOG.error("accessId {} already exists", accessId);
            throw new OMException("accessId '" + accessId + "' already exists!", ResultCodes.TENANT_USER_ACCESS_ID_ALREADY_EXISTS);
        }
        OmDBUserPrincipalInfo principalInfo = omMetadataManager.getPrincipalToAccessIdsTable().getIfExist(userPrincipal);
        // Reject if the user is already assigned to the tenant
        if (principalInfo != null) {
            // TODO: There is room for perf improvement. add a map in OMMTM.
            for (final String existingAccId : principalInfo.getAccessIds()) {
                final OmDBAccessIdInfo accessIdInfo = omMetadataManager.getTenantAccessIdTable().get(existingAccId);
                if (accessIdInfo == null) {
                    LOG.error("Metadata error: accessIdInfo is null for accessId '{}'. " + "Ignoring.", existingAccId);
                    throw new NullPointerException("accessIdInfo is null");
                }
                if (tenantId.equals(accessIdInfo.getTenantId())) {
                    throw new OMException("The same user is not allowed to be assigned " + "to the same tenant more than once. User '" + userPrincipal + "' is already assigned to tenant '" + tenantId + "' with " + "accessId '" + existingAccId + "'.", ResultCodes.TENANT_USER_ACCESS_ID_ALREADY_EXISTS);
                }
            }
        }
        final S3SecretValue s3SecretValue = new S3SecretValue(accessId, awsSecret);
        // Add to tenantAccessIdTable
        final OmDBAccessIdInfo omDBAccessIdInfo = new OmDBAccessIdInfo.Builder().setTenantId(tenantId).setUserPrincipal(userPrincipal).setIsAdmin(false).setIsDelegatedAdmin(false).build();
        omMetadataManager.getTenantAccessIdTable().addCacheEntry(new CacheKey<>(accessId), new CacheValue<>(Optional.of(omDBAccessIdInfo), transactionLogIndex));
        // Add to principalToAccessIdsTable
        if (principalInfo == null) {
            principalInfo = new OmDBUserPrincipalInfo.Builder().setAccessIds(new TreeSet<>(Collections.singleton(accessId))).build();
        } else {
            principalInfo.addAccessId(accessId);
        }
        omMetadataManager.getPrincipalToAccessIdsTable().addCacheEntry(new CacheKey<>(userPrincipal), new CacheValue<>(Optional.of(principalInfo), transactionLogIndex));
        // Add S3SecretTable cache entry
        acquiredS3SecretLock = omMetadataManager.getLock().acquireWriteLock(S3_SECRET_LOCK, accessId);
        // Expect accessId absence from S3SecretTable
        if (omMetadataManager.getS3SecretTable().isExist(accessId)) {
            LOG.error("accessId '{}' already exists in S3SecretTable", accessId);
            throw new OMException("accessId '" + accessId + "' already exists in S3SecretTable", ResultCodes.TENANT_USER_ACCESS_ID_ALREADY_EXISTS);
        }
        omMetadataManager.getS3SecretTable().addCacheEntry(new CacheKey<>(accessId), new CacheValue<>(Optional.of(s3SecretValue), transactionLogIndex));
        omMetadataManager.getLock().releaseWriteLock(S3_SECRET_LOCK, accessId);
        acquiredS3SecretLock = false;
        // Update tenant cache
        multiTenantManager.getCacheOp().assignUserToTenant(userPrincipal, tenantId, accessId);
        // Generate response
        omResponse.setTenantAssignUserAccessIdResponse(TenantAssignUserAccessIdResponse.newBuilder().setS3Secret(S3Secret.newBuilder().setAwsSecret(awsSecret).setKerberosID(accessId)).build());
        omClientResponse = new OMTenantAssignUserAccessIdResponse(omResponse.build(), s3SecretValue, userPrincipal, accessId, omDBAccessIdInfo, principalInfo);
    } catch (IOException ex) {
        exception = ex;
        omResponse.setTenantAssignUserAccessIdResponse(TenantAssignUserAccessIdResponse.newBuilder().build());
        omClientResponse = new OMTenantAssignUserAccessIdResponse(createErrorOMResponse(omResponse, ex));
    } finally {
        addResponseToDoubleBuffer(transactionLogIndex, omClientResponse, ozoneManagerDoubleBufferHelper);
        if (acquiredS3SecretLock) {
            omMetadataManager.getLock().releaseWriteLock(S3_SECRET_LOCK, accessId);
        }
        if (acquiredVolumeLock) {
            Preconditions.checkNotNull(volumeName);
            omMetadataManager.getLock().releaseWriteLock(VOLUME_LOCK, volumeName);
        }
        // Release authorizer write lock
        multiTenantManager.getAuthorizerLock().unlockWriteInOMRequest();
    }
    // Audit
    auditMap.put(OzoneConsts.TENANT, tenantId);
    auditMap.put("user", userPrincipal);
    auditMap.put("accessId", accessId);
    auditLog(ozoneManager.getAuditLogger(), buildAuditMessage(OMAction.TENANT_ASSIGN_USER_ACCESSID, auditMap, exception, getOmRequest().getUserInfo()));
    if (exception == null) {
        LOG.info("Assigned user '{}' to tenant '{}' with accessId '{}'", userPrincipal, tenantId, accessId);
    } else {
        LOG.error("Failed to assign '{}' to tenant '{}' with accessId '{}': {}", userPrincipal, tenantId, accessId, exception.getMessage());
        omMetrics.incNumTenantAssignUserFails();
    }
    return omClientResponse;
}
Also used : OMClientResponse(org.apache.hadoop.ozone.om.response.OMClientResponse) HashMap(java.util.HashMap) OMMultiTenantManager(org.apache.hadoop.ozone.om.OMMultiTenantManager) IOException(java.io.IOException) S3SecretValue(org.apache.hadoop.ozone.om.helpers.S3SecretValue) OMTenantAssignUserAccessIdResponse(org.apache.hadoop.ozone.om.response.s3.tenant.OMTenantAssignUserAccessIdResponse) OMMetrics(org.apache.hadoop.ozone.om.OMMetrics) OMResponse(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse) UpdateGetS3SecretRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest) OmDBAccessIdInfo(org.apache.hadoop.ozone.om.helpers.OmDBAccessIdInfo) OMMetadataManager(org.apache.hadoop.ozone.om.OMMetadataManager) OmDBUserPrincipalInfo(org.apache.hadoop.ozone.om.helpers.OmDBUserPrincipalInfo) TenantAssignUserAccessIdRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignUserAccessIdRequest) OMException(org.apache.hadoop.ozone.om.exceptions.OMException)

Example 4 with UpdateGetS3SecretRequest

use of org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest in project ozone by apache.

the class OMTenantAssignUserAccessIdRequest method preExecute.

@Override
@DisallowedUntilLayoutVersion(MULTITENANCY_SCHEMA)
public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
    final OMRequest omRequest = super.preExecute(ozoneManager);
    final TenantAssignUserAccessIdRequest request = omRequest.getTenantAssignUserAccessIdRequest();
    final String tenantId = request.getTenantId();
    final OMMultiTenantManager multiTenantManager = ozoneManager.getMultiTenantManager();
    // Caller should be an Ozone admin, or at least a tenant non-delegated admin
    multiTenantManager.checkTenantAdmin(tenantId, false);
    final String userPrincipal = request.getUserPrincipal();
    final String accessId = request.getAccessId();
    // Check accessId length.
    if (accessId.length() >= OZONE_MAXIMUM_ACCESS_ID_LENGTH) {
        throw new OMException("accessId length exceeds the maximum length allowed", ResultCodes.INVALID_ACCESS_ID);
    }
    // Check userPrincipal (username) validity.
    if (userPrincipal.contains(OzoneConsts.TENANT_ID_USERNAME_DELIMITER)) {
        throw new OMException("Invalid tenant username '" + userPrincipal + "'. Tenant username shouldn't contain delimiter.", ResultCodes.INVALID_TENANT_USERNAME);
    }
    // Check tenant name validity.
    if (tenantId.contains(OzoneConsts.TENANT_ID_USERNAME_DELIMITER)) {
        throw new OMException("Invalid tenant name '" + tenantId + "'. Tenant name shouldn't contain delimiter.", ResultCodes.INVALID_TENANT_ID);
    }
    // HDDS-6366: Disallow specifying custom accessId.
    final String expectedAccessId = OMMultiTenantManager.getDefaultAccessId(tenantId, userPrincipal);
    if (!accessId.equals(expectedAccessId)) {
        throw new OMException("Invalid accessId '" + accessId + "'. " + "Specifying a custom access ID disallowed. " + "Expected accessId to be assigned is '" + expectedAccessId + "'", ResultCodes.INVALID_ACCESS_ID);
    }
    multiTenantManager.checkTenantExistence(tenantId);
    // Below call implies user existence check in authorizer.
    // If the user doesn't exist, Ranger return 400 and the call should throw.
    // Acquire write lock to authorizer (Ranger)
    multiTenantManager.getAuthorizerLock().tryWriteLockInOMRequest();
    try {
        // Add user to tenant user role in Ranger.
        // Throws if the user doesn't exist in Ranger.
        multiTenantManager.getAuthorizerOp().assignUserToTenant(userPrincipal, tenantId, accessId);
    } catch (Exception e) {
        multiTenantManager.getAuthorizerLock().unlockWriteInOMRequest();
        throw e;
    }
    // Generate secret. However, this is used only when the accessId entry
    // doesn't exist in DB and need to be created, discarded otherwise.
    final String s3Secret = DigestUtils.sha256Hex(OmUtils.getSHADigest());
    final UpdateGetS3SecretRequest updateGetS3SecretRequest = UpdateGetS3SecretRequest.newBuilder().setKerberosID(accessId).setAwsSecret(s3Secret).build();
    final OMRequest.Builder omRequestBuilder = omRequest.toBuilder().setUpdateGetS3SecretRequest(updateGetS3SecretRequest);
    return omRequestBuilder.build();
}
Also used : OMRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest) UpdateGetS3SecretRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest) OMMultiTenantManager(org.apache.hadoop.ozone.om.OMMultiTenantManager) TenantAssignUserAccessIdRequest(org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignUserAccessIdRequest) OMException(org.apache.hadoop.ozone.om.exceptions.OMException) IOException(java.io.IOException) OMException(org.apache.hadoop.ozone.om.exceptions.OMException) DisallowedUntilLayoutVersion(org.apache.hadoop.ozone.om.upgrade.DisallowedUntilLayoutVersion)

Aggregations

UpdateGetS3SecretRequest (org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UpdateGetS3SecretRequest)4 IOException (java.io.IOException)3 OMException (org.apache.hadoop.ozone.om.exceptions.OMException)3 HashMap (java.util.HashMap)2 OMMetadataManager (org.apache.hadoop.ozone.om.OMMetadataManager)2 OMMultiTenantManager (org.apache.hadoop.ozone.om.OMMultiTenantManager)2 S3SecretValue (org.apache.hadoop.ozone.om.helpers.S3SecretValue)2 OMClientResponse (org.apache.hadoop.ozone.om.response.OMClientResponse)2 GetS3SecretRequest (org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3SecretRequest)2 OMRequest (org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest)2 OMResponse (org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse)2 TenantAssignUserAccessIdRequest (org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignUserAccessIdRequest)2 OMMetrics (org.apache.hadoop.ozone.om.OMMetrics)1 OmDBAccessIdInfo (org.apache.hadoop.ozone.om.helpers.OmDBAccessIdInfo)1 OmDBUserPrincipalInfo (org.apache.hadoop.ozone.om.helpers.OmDBUserPrincipalInfo)1 S3GetSecretResponse (org.apache.hadoop.ozone.om.response.s3.security.S3GetSecretResponse)1 OMTenantAssignUserAccessIdResponse (org.apache.hadoop.ozone.om.response.s3.tenant.OMTenantAssignUserAccessIdResponse)1 DisallowedUntilLayoutVersion (org.apache.hadoop.ozone.om.upgrade.DisallowedUntilLayoutVersion)1 GetS3SecretResponse (org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3SecretResponse)1 UserGroupInformation (org.apache.hadoop.security.UserGroupInformation)1