| /** |
| * 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.lib.service.security; |
| |
| import org.apache.hadoop.classification.InterfaceAudience; |
| import org.apache.hadoop.fs.http.server.HttpFSServerWebApp; |
| import org.apache.hadoop.io.Text; |
| import org.apache.hadoop.lib.server.BaseService; |
| import org.apache.hadoop.lib.server.ServerException; |
| import org.apache.hadoop.lib.server.ServiceException; |
| import org.apache.hadoop.lib.service.DelegationTokenIdentifier; |
| import org.apache.hadoop.lib.service.DelegationTokenManager; |
| import org.apache.hadoop.lib.service.DelegationTokenManagerException; |
| import org.apache.hadoop.security.SecurityUtil; |
| import org.apache.hadoop.security.UserGroupInformation; |
| import org.apache.hadoop.security.token.Token; |
| import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.DataInputStream; |
| import java.io.IOException; |
| |
| /** |
| * DelegationTokenManager service implementation. |
| */ |
| @InterfaceAudience.Private |
| public class DelegationTokenManagerService extends BaseService |
| implements DelegationTokenManager { |
| |
| private static final String PREFIX = "delegation.token.manager"; |
| |
| private static final String UPDATE_INTERVAL = "update.interval"; |
| |
| private static final String MAX_LIFETIME = "max.lifetime"; |
| |
| private static final String RENEW_INTERVAL = "renew.interval"; |
| |
| private static final long HOUR = 60 * 60 * 1000; |
| private static final long DAY = 24 * HOUR; |
| |
| DelegationTokenSecretManager secretManager = null; |
| |
| public DelegationTokenManagerService() { |
| super(PREFIX); |
| } |
| |
| /** |
| * Initializes the service. |
| * |
| * @throws ServiceException thrown if the service could not be initialized. |
| */ |
| @Override |
| protected void init() throws ServiceException { |
| |
| long updateInterval = getServiceConfig().getLong(UPDATE_INTERVAL, DAY); |
| long maxLifetime = getServiceConfig().getLong(MAX_LIFETIME, 7 * DAY); |
| long renewInterval = getServiceConfig().getLong(RENEW_INTERVAL, DAY); |
| secretManager = new DelegationTokenSecretManager(updateInterval, |
| maxLifetime, |
| renewInterval, HOUR); |
| try { |
| secretManager.startThreads(); |
| } catch (IOException ex) { |
| throw new ServiceException(ServiceException.ERROR.S12, |
| DelegationTokenManager.class.getSimpleName(), |
| ex.toString(), ex); |
| } |
| } |
| |
| /** |
| * Destroys the service. |
| */ |
| @Override |
| public void destroy() { |
| secretManager.stopThreads(); |
| super.destroy(); |
| } |
| |
| /** |
| * Returns the service interface. |
| * |
| * @return the service interface. |
| */ |
| @Override |
| public Class getInterface() { |
| return DelegationTokenManager.class; |
| } |
| |
| /** |
| * Creates a delegation token. |
| * |
| * @param ugi UGI creating the token. |
| * @param renewer token renewer. |
| * @return new delegation token. |
| * @throws DelegationTokenManagerException thrown if the token could not be |
| * created. |
| */ |
| @Override |
| public Token<DelegationTokenIdentifier> createToken(UserGroupInformation ugi, |
| String renewer) |
| throws DelegationTokenManagerException { |
| renewer = (renewer == null) ? ugi.getShortUserName() : renewer; |
| String user = ugi.getUserName(); |
| Text owner = new Text(user); |
| Text realUser = null; |
| if (ugi.getRealUser() != null) { |
| realUser = new Text(ugi.getRealUser().getUserName()); |
| } |
| DelegationTokenIdentifier tokenIdentifier = |
| new DelegationTokenIdentifier(owner, new Text(renewer), realUser); |
| Token<DelegationTokenIdentifier> token = |
| new Token<DelegationTokenIdentifier>(tokenIdentifier, secretManager); |
| try { |
| SecurityUtil.setTokenService(token, |
| HttpFSServerWebApp.get().getAuthority()); |
| } catch (ServerException ex) { |
| throw new DelegationTokenManagerException( |
| DelegationTokenManagerException.ERROR.DT04, ex.toString(), ex); |
| } |
| return token; |
| } |
| |
| /** |
| * Renews a delegation token. |
| * |
| * @param token delegation token to renew. |
| * @param renewer token renewer. |
| * @return epoc expiration time. |
| * @throws DelegationTokenManagerException thrown if the token could not be |
| * renewed. |
| */ |
| @Override |
| public long renewToken(Token<DelegationTokenIdentifier> token, String renewer) |
| throws DelegationTokenManagerException { |
| try { |
| return secretManager.renewToken(token, renewer); |
| } catch (IOException ex) { |
| throw new DelegationTokenManagerException( |
| DelegationTokenManagerException.ERROR.DT02, ex.toString(), ex); |
| } |
| } |
| |
| /** |
| * Cancels a delegation token. |
| * |
| * @param token delegation token to cancel. |
| * @param canceler token canceler. |
| * @throws DelegationTokenManagerException thrown if the token could not be |
| * canceled. |
| */ |
| @Override |
| public void cancelToken(Token<DelegationTokenIdentifier> token, |
| String canceler) |
| throws DelegationTokenManagerException { |
| try { |
| secretManager.cancelToken(token, canceler); |
| } catch (IOException ex) { |
| throw new DelegationTokenManagerException( |
| DelegationTokenManagerException.ERROR.DT03, ex.toString(), ex); |
| } |
| } |
| |
| /** |
| * Verifies a delegation token. |
| * |
| * @param token delegation token to verify. |
| * @return the UGI for the token. |
| * @throws DelegationTokenManagerException thrown if the token could not be |
| * verified. |
| */ |
| @Override |
| public UserGroupInformation verifyToken(Token<DelegationTokenIdentifier> token) |
| throws DelegationTokenManagerException { |
| ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier()); |
| DataInputStream dis = new DataInputStream(buf); |
| DelegationTokenIdentifier id = new DelegationTokenIdentifier(); |
| try { |
| id.readFields(dis); |
| dis.close(); |
| secretManager.verifyToken(id, token.getPassword()); |
| } catch (Exception ex) { |
| throw new DelegationTokenManagerException( |
| DelegationTokenManagerException.ERROR.DT01, ex.toString(), ex); |
| } |
| return id.getUser(); |
| } |
| |
| private static class DelegationTokenSecretManager |
| extends AbstractDelegationTokenSecretManager<DelegationTokenIdentifier> { |
| |
| /** |
| * Create a secret manager |
| * |
| * @param delegationKeyUpdateInterval the number of seconds for rolling new |
| * secret keys. |
| * @param delegationTokenMaxLifetime the maximum lifetime of the delegation |
| * tokens |
| * @param delegationTokenRenewInterval how often the tokens must be renewed |
| * @param delegationTokenRemoverScanInterval how often the tokens are |
| * scanned |
| * for expired tokens |
| */ |
| public DelegationTokenSecretManager(long delegationKeyUpdateInterval, |
| long delegationTokenMaxLifetime, |
| long delegationTokenRenewInterval, |
| long delegationTokenRemoverScanInterval) { |
| super(delegationKeyUpdateInterval, delegationTokenMaxLifetime, |
| delegationTokenRenewInterval, delegationTokenRemoverScanInterval); |
| } |
| |
| @Override |
| public DelegationTokenIdentifier createIdentifier() { |
| return new DelegationTokenIdentifier(); |
| } |
| |
| } |
| |
| } |