001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.hadoop.lib.service.security; 019 020 import org.apache.hadoop.classification.InterfaceAudience; 021 import org.apache.hadoop.fs.http.server.HttpFSServerWebApp; 022 import org.apache.hadoop.io.Text; 023 import org.apache.hadoop.lib.server.BaseService; 024 import org.apache.hadoop.lib.server.ServerException; 025 import org.apache.hadoop.lib.server.ServiceException; 026 import org.apache.hadoop.lib.service.DelegationTokenIdentifier; 027 import org.apache.hadoop.lib.service.DelegationTokenManager; 028 import org.apache.hadoop.lib.service.DelegationTokenManagerException; 029 import org.apache.hadoop.security.SecurityUtil; 030 import org.apache.hadoop.security.UserGroupInformation; 031 import org.apache.hadoop.security.token.Token; 032 import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager; 033 034 import java.io.ByteArrayInputStream; 035 import java.io.DataInputStream; 036 import java.io.IOException; 037 038 /** 039 * DelegationTokenManager service implementation. 040 */ 041 @InterfaceAudience.Private 042 public class DelegationTokenManagerService extends BaseService 043 implements DelegationTokenManager { 044 045 private static final String PREFIX = "delegation.token.manager"; 046 047 private static final String UPDATE_INTERVAL = "update.interval"; 048 049 private static final String MAX_LIFETIME = "max.lifetime"; 050 051 private static final String RENEW_INTERVAL = "renew.interval"; 052 053 private static final long HOUR = 60 * 60 * 1000; 054 private static final long DAY = 24 * HOUR; 055 056 DelegationTokenSecretManager secretManager = null; 057 058 public DelegationTokenManagerService() { 059 super(PREFIX); 060 } 061 062 /** 063 * Initializes the service. 064 * 065 * @throws ServiceException thrown if the service could not be initialized. 066 */ 067 @Override 068 protected void init() throws ServiceException { 069 070 long updateInterval = getServiceConfig().getLong(UPDATE_INTERVAL, DAY); 071 long maxLifetime = getServiceConfig().getLong(MAX_LIFETIME, 7 * DAY); 072 long renewInterval = getServiceConfig().getLong(RENEW_INTERVAL, DAY); 073 secretManager = new DelegationTokenSecretManager(updateInterval, 074 maxLifetime, 075 renewInterval, HOUR); 076 try { 077 secretManager.startThreads(); 078 } catch (IOException ex) { 079 throw new ServiceException(ServiceException.ERROR.S12, 080 DelegationTokenManager.class.getSimpleName(), 081 ex.toString(), ex); 082 } 083 } 084 085 /** 086 * Destroys the service. 087 */ 088 @Override 089 public void destroy() { 090 secretManager.stopThreads(); 091 super.destroy(); 092 } 093 094 /** 095 * Returns the service interface. 096 * 097 * @return the service interface. 098 */ 099 @Override 100 public Class getInterface() { 101 return DelegationTokenManager.class; 102 } 103 104 /** 105 * Creates a delegation token. 106 * 107 * @param ugi UGI creating the token. 108 * @param renewer token renewer. 109 * @return new delegation token. 110 * @throws DelegationTokenManagerException thrown if the token could not be 111 * created. 112 */ 113 @Override 114 public Token<DelegationTokenIdentifier> createToken(UserGroupInformation ugi, 115 String renewer) 116 throws DelegationTokenManagerException { 117 renewer = (renewer == null) ? ugi.getShortUserName() : renewer; 118 String user = ugi.getUserName(); 119 Text owner = new Text(user); 120 Text realUser = null; 121 if (ugi.getRealUser() != null) { 122 realUser = new Text(ugi.getRealUser().getUserName()); 123 } 124 DelegationTokenIdentifier tokenIdentifier = 125 new DelegationTokenIdentifier(owner, new Text(renewer), realUser); 126 Token<DelegationTokenIdentifier> token = 127 new Token<DelegationTokenIdentifier>(tokenIdentifier, secretManager); 128 try { 129 SecurityUtil.setTokenService(token, 130 HttpFSServerWebApp.get().getAuthority()); 131 } catch (ServerException ex) { 132 throw new DelegationTokenManagerException( 133 DelegationTokenManagerException.ERROR.DT04, ex.toString(), ex); 134 } 135 return token; 136 } 137 138 /** 139 * Renews a delegation token. 140 * 141 * @param token delegation token to renew. 142 * @param renewer token renewer. 143 * @return epoc expiration time. 144 * @throws DelegationTokenManagerException thrown if the token could not be 145 * renewed. 146 */ 147 @Override 148 public long renewToken(Token<DelegationTokenIdentifier> token, String renewer) 149 throws DelegationTokenManagerException { 150 try { 151 return secretManager.renewToken(token, renewer); 152 } catch (IOException ex) { 153 throw new DelegationTokenManagerException( 154 DelegationTokenManagerException.ERROR.DT02, ex.toString(), ex); 155 } 156 } 157 158 /** 159 * Cancels a delegation token. 160 * 161 * @param token delegation token to cancel. 162 * @param canceler token canceler. 163 * @throws DelegationTokenManagerException thrown if the token could not be 164 * canceled. 165 */ 166 @Override 167 public void cancelToken(Token<DelegationTokenIdentifier> token, 168 String canceler) 169 throws DelegationTokenManagerException { 170 try { 171 secretManager.cancelToken(token, canceler); 172 } catch (IOException ex) { 173 throw new DelegationTokenManagerException( 174 DelegationTokenManagerException.ERROR.DT03, ex.toString(), ex); 175 } 176 } 177 178 /** 179 * Verifies a delegation token. 180 * 181 * @param token delegation token to verify. 182 * @return the UGI for the token. 183 * @throws DelegationTokenManagerException thrown if the token could not be 184 * verified. 185 */ 186 @Override 187 public UserGroupInformation verifyToken(Token<DelegationTokenIdentifier> token) 188 throws DelegationTokenManagerException { 189 ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier()); 190 DataInputStream dis = new DataInputStream(buf); 191 DelegationTokenIdentifier id = new DelegationTokenIdentifier(); 192 try { 193 id.readFields(dis); 194 dis.close(); 195 secretManager.verifyToken(id, token.getPassword()); 196 } catch (Exception ex) { 197 throw new DelegationTokenManagerException( 198 DelegationTokenManagerException.ERROR.DT01, ex.toString(), ex); 199 } 200 return id.getUser(); 201 } 202 203 private static class DelegationTokenSecretManager 204 extends AbstractDelegationTokenSecretManager<DelegationTokenIdentifier> { 205 206 /** 207 * Create a secret manager 208 * 209 * @param delegationKeyUpdateInterval the number of seconds for rolling new 210 * secret keys. 211 * @param delegationTokenMaxLifetime the maximum lifetime of the delegation 212 * tokens 213 * @param delegationTokenRenewInterval how often the tokens must be renewed 214 * @param delegationTokenRemoverScanInterval how often the tokens are 215 * scanned 216 * for expired tokens 217 */ 218 public DelegationTokenSecretManager(long delegationKeyUpdateInterval, 219 long delegationTokenMaxLifetime, 220 long delegationTokenRenewInterval, 221 long delegationTokenRemoverScanInterval) { 222 super(delegationKeyUpdateInterval, delegationTokenMaxLifetime, 223 delegationTokenRenewInterval, delegationTokenRemoverScanInterval); 224 } 225 226 @Override 227 public DelegationTokenIdentifier createIdentifier() { 228 return new DelegationTokenIdentifier(); 229 } 230 231 } 232 233 }