diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java index 1a6da6da94..30fe17eb9f 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/OzoneDelegationTokenSecretManager.java @@ -287,18 +287,40 @@ public OzoneTokenIdentifier cancelToken(Token token, throw new AccessControlException(canceller + " is not authorized to cancel the token " + formatTokenId(id)); } - try { - store.removeToken(id); - } catch (IOException e) { - LOG.error("Unable to remove token " + id.getSequenceNumber(), e); - } - TokenInfo info = currentTokens.remove(id); - if (info == null) { - throw new InvalidToken("Token not found " + formatTokenId(id)); + + // For HA ratis will take care of removal. + // This check will be removed, when HA/Non-HA code is merged. + if (!isRatisEnabled) { + try { + store.removeToken(id); + } catch (IOException e) { + LOG.error("Unable to remove token " + id.getSequenceNumber(), e); + } + TokenInfo info = currentTokens.remove(id); + if (info == null) { + throw new InvalidToken("Token not found " + formatTokenId(id)); + } + } else { + // Check whether token is there in-memory map of tokens or not on the + // OM leader. + TokenInfo info = currentTokens.get(id); + if (info == null) { + throw new InvalidToken("Token not found in-memory map of tokens" + + formatTokenId(id)); + } } return id; } + /** + * Remove the expired token from in-memory map. + * @param ozoneTokenIdentifier + * @throws IOException + */ + public void removeToken(OzoneTokenIdentifier ozoneTokenIdentifier) { + currentTokens.remove(ozoneTokenIdentifier); + } + @Override public byte[] retrievePassword(OzoneTokenIdentifier identifier) throws InvalidToken { diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java index ea2210d7e5..65a25acdf6 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java @@ -152,6 +152,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, throw new OMException("Volume doesn't exist", OMException.ResultCodes.VOLUME_NOT_FOUND); } + //Check if bucket already exists if (metadataManager.getBucketTable().get(bucketKey) != null) { LOG.debug("bucket: {} already exists ", bucketName); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/security/OMCancelDelegationTokenRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/security/OMCancelDelegationTokenRequest.java new file mode 100644 index 0000000000..b28090db72 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/security/OMCancelDelegationTokenRequest.java @@ -0,0 +1,125 @@ +/** + * 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.om.request.security; + +import com.google.common.base.Optional; +import org.apache.hadoop.ozone.om.OMMetadataManager; +import org.apache.hadoop.ozone.om.OzoneManager; +import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper; +import org.apache.hadoop.ozone.om.request.OMClientRequest; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.om.response.security.OMCancelDelegationTokenResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +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.CancelDelegationTokenResponseProto; +import org.apache.hadoop.ozone.protocolPB.OMPBHelper; +import org.apache.hadoop.ozone.security.OzoneTokenIdentifier; +import org.apache.hadoop.security.proto.SecurityProtos; +import org.apache.hadoop.security.proto.SecurityProtos.CancelDelegationTokenRequestProto; +import org.apache.hadoop.security.token.Token; +import org.apache.hadoop.utils.db.cache.CacheKey; +import org.apache.hadoop.utils.db.cache.CacheValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * Handle CancelDelegationToken Request. + */ +public class OMCancelDelegationTokenRequest extends OMClientRequest { + + private static final Logger LOG = + LoggerFactory.getLogger(OMGetDelegationTokenRequest.class); + + public OMCancelDelegationTokenRequest(OMRequest omRequest) { + super(omRequest); + } + + @Override + public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { + + // Call OM to cancel token, this does check whether we can cancel token + // or not. This does not remove token from DB/in-memory. + ozoneManager.cancelDelegationToken(getToken()); + + return super.preExecute(ozoneManager); + } + + @Override + public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, + long transactionLogIndex, + OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) { + + OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager(); + + OMClientResponse omClientResponse = null; + OMResponse.Builder omResponse = + OMResponse.newBuilder() + .setCmdType(OzoneManagerProtocolProtos.Type.CancelDelegationToken) + .setStatus(OzoneManagerProtocolProtos.Status.OK) + .setSuccess(true); + OzoneTokenIdentifier ozoneTokenIdentifier = null; + try { + ozoneTokenIdentifier = + OzoneTokenIdentifier.readProtoBuf(getToken().getIdentifier()); + + // Remove token from in-memory. + ozoneManager.getDelegationTokenMgr().removeToken(ozoneTokenIdentifier); + + // Update Cache. + omMetadataManager.getDelegationTokenTable().addCacheEntry( + new CacheKey<>(ozoneTokenIdentifier), + new CacheValue<>(Optional.absent(), transactionLogIndex)); + + omClientResponse = + new OMCancelDelegationTokenResponse(ozoneTokenIdentifier, + omResponse.setCancelDelegationTokenResponse( + CancelDelegationTokenResponseProto.newBuilder().setResponse( + SecurityProtos.CancelDelegationTokenResponseProto + .newBuilder())).build()); + } catch (IOException ex) { + LOG.error("Error in cancel DelegationToken {}", ozoneTokenIdentifier, ex); + omClientResponse = new OMCancelDelegationTokenResponse(null, + createErrorOMResponse(omResponse, ex)); + } finally { + if (omClientResponse != null) { + omClientResponse.setFlushFuture( + ozoneManagerDoubleBufferHelper.add(omClientResponse, + transactionLogIndex)); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Cancelled delegation token: {}", ozoneTokenIdentifier); + } + + return omClientResponse; + } + + + public Token getToken() { + CancelDelegationTokenRequestProto cancelDelegationTokenRequest = + getOmRequest().getCancelDelegationTokenRequest(); + + return OMPBHelper.convertToDelegationToken( + cancelDelegationTokenRequest.getToken()); + } +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/security/OMGetDelegationTokenRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/security/OMGetDelegationTokenRequest.java index 18d50e9389..df9400efc5 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/security/OMGetDelegationTokenRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/security/OMGetDelegationTokenRequest.java @@ -25,7 +25,7 @@ import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper; import org.apache.hadoop.ozone.om.request.OMClientRequest; import org.apache.hadoop.ozone.om.response.OMClientResponse; -import org.apache.hadoop.ozone.om.response.security.OMDelegationTokenResponse; +import org.apache.hadoop.ozone.om.response.security.OMGetDelegationTokenResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetDelegationTokenResponseProto; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; @@ -65,13 +65,13 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { .getDelegationToken(new Text(getDelegationTokenRequest.getRenewer())); - // Client issues GetDelegationToken request, when received by OM leader will - // it generate Token. Original GetDelegationToken request is converted to - // UpdateGetDelegationToken request with the generated token information. - // This updated request will be submitted to Ratis. In this way delegation - // token created by leader, will be replicated across all OMs. - // And also original GetDelegationToken request from client does not need - // any proto changes. + // Client issues GetDelegationToken request, when received by OM leader + // it will generate a token. Original GetDelegationToken request is + // converted to UpdateGetDelegationToken request with the generated token + // information. This updated request will be submitted to Ratis. In this + // way delegation token created by leader, will be replicated across all + // OMs. With this approach, original GetDelegationToken request from + // client does not need any proto changes. // Create UpdateGetDelegationTokenRequest with token response. OMRequest.Builder omRequest = OMRequest.newBuilder() @@ -129,14 +129,14 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, new CacheValue<>(Optional.of(renewTime), transactionLogIndex)); omClientResponse = - new OMDelegationTokenResponse(ozoneTokenIdentifier, renewTime, + new OMGetDelegationTokenResponse(ozoneTokenIdentifier, renewTime, omResponse.setGetDelegationTokenResponse( updateGetDelegationTokenRequest .getGetDelegationTokenResponse()).build()); } catch (IOException ex) { - LOG.error("Error in Updating DelegationToken {} to DB", + LOG.error("Error in Updating DelegationToken {}", ozoneTokenIdentifierToken, ex); - omClientResponse = new OMDelegationTokenResponse(null, -1L, + omClientResponse = new OMGetDelegationTokenResponse(null, -1L, createErrorOMResponse(omResponse, ex)); } finally { if (omClientResponse != null) { @@ -147,7 +147,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, } if (LOG.isDebugEnabled()) { - LOG.debug("Updated delegation token to OM DB: {}", + LOG.debug("Updated delegation token in-memory map: {}", ozoneTokenIdentifierToken); } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMDelegationTokenResponse.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMCancelDelegationTokenResponse.java similarity index 76% rename from hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMDelegationTokenResponse.java rename to hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMCancelDelegationTokenResponse.java index 71e3371495..d2092bd7a4 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMDelegationTokenResponse.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMCancelDelegationTokenResponse.java @@ -24,30 +24,32 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; import org.apache.hadoop.ozone.security.OzoneTokenIdentifier; import org.apache.hadoop.utils.db.BatchOperation; +import org.apache.hadoop.utils.db.Table; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; /** - * Handle response for DelegationToken request. + * Handle response for CancelDelegationToken request. */ -public class OMDelegationTokenResponse extends OMClientResponse { +public class OMCancelDelegationTokenResponse extends OMClientResponse { private OzoneTokenIdentifier ozoneTokenIdentifier; - private long renewTime; - public OMDelegationTokenResponse(OzoneTokenIdentifier ozoneTokenIdentifier, - long renewTime, OMResponse omResponse) { + + public OMCancelDelegationTokenResponse( + @Nullable OzoneTokenIdentifier ozoneTokenIdentifier, + @Nonnull OMResponse omResponse) { super(omResponse); this.ozoneTokenIdentifier = ozoneTokenIdentifier; - this.renewTime = renewTime; } @Override public void addToDBBatch(OMMetadataManager omMetadataManager, BatchOperation batchOperation) throws IOException { - + Table table = omMetadataManager.getDelegationTokenTable(); if (getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK) { - omMetadataManager.getDelegationTokenTable().putWithBatch(batchOperation, - ozoneTokenIdentifier, renewTime); + table.deleteWithBatch(batchOperation, ozoneTokenIdentifier); } } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMGetDelegationTokenResponse.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMGetDelegationTokenResponse.java new file mode 100644 index 0000000000..40b9a9689a --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/security/OMGetDelegationTokenResponse.java @@ -0,0 +1,58 @@ +/** + * 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.om.response.security; + +import org.apache.hadoop.ozone.om.OMMetadataManager; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; +import org.apache.hadoop.ozone.security.OzoneTokenIdentifier; +import org.apache.hadoop.utils.db.BatchOperation; +import org.apache.hadoop.utils.db.Table; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; + +/** + * Handle response for GetDelegationToken request. + */ +public class OMGetDelegationTokenResponse extends OMClientResponse { + + private OzoneTokenIdentifier ozoneTokenIdentifier; + private long renewTime = -1L; + + public OMGetDelegationTokenResponse( + @Nullable OzoneTokenIdentifier ozoneTokenIdentifier, + long renewTime, @Nonnull OMResponse omResponse) { + super(omResponse); + this.ozoneTokenIdentifier = ozoneTokenIdentifier; + this.renewTime = renewTime; + } + + @Override + public void addToDBBatch(OMMetadataManager omMetadataManager, + BatchOperation batchOperation) throws IOException { + Table table = omMetadataManager.getDelegationTokenTable(); + if (getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK) { + table.putWithBatch(batchOperation, ozoneTokenIdentifier, renewTime); + } + } +} +