View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.security.token;
20  
21  import java.io.IOException;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.hbase.CoprocessorEnvironment;
26  import org.apache.hadoop.hbase.coprocessor.BaseEndpointCoprocessor;
27  import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
28  import org.apache.hadoop.hbase.ipc.RequestContext;
29  import org.apache.hadoop.hbase.ipc.RpcServer;
30  import org.apache.hadoop.hbase.ipc.SecureServer;
31  import org.apache.hadoop.hbase.security.AccessDeniedException;
32  import org.apache.hadoop.hbase.security.User;
33  import org.apache.hadoop.security.UserGroupInformation;
34  import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
35  import org.apache.hadoop.security.token.SecretManager;
36  import org.apache.hadoop.security.token.Token;
37  
38  /**
39   * Provides a service for obtaining authentication tokens via the
40   * {@link AuthenticationProtocol} coprocessor protocol.
41   */
42  public class TokenProvider extends BaseEndpointCoprocessor
43      implements AuthenticationProtocol {
44  
45    public static final long VERSION = 0L;
46    private static Log LOG = LogFactory.getLog(TokenProvider.class);
47  
48    private AuthenticationTokenSecretManager secretManager;
49  
50  
51    @Override
52    public void start(CoprocessorEnvironment env) {
53      super.start(env);
54  
55      // if running at region
56      if (env instanceof RegionCoprocessorEnvironment) {
57        RegionCoprocessorEnvironment regionEnv =
58            (RegionCoprocessorEnvironment)env;
59        RpcServer server = regionEnv.getRegionServerServices().getRpcServer();
60        if (server instanceof SecureServer) {
61          SecretManager mgr = ((SecureServer)server).getSecretManager();
62          if (mgr instanceof AuthenticationTokenSecretManager) {
63            secretManager = (AuthenticationTokenSecretManager)mgr;
64          }
65        }
66      }
67    }
68  
69    @Override
70    public Token<AuthenticationTokenIdentifier> getAuthenticationToken()
71        throws IOException {
72      if (secretManager == null) {
73        throw new IOException(
74            "No secret manager configured for token authentication");
75      }
76  
77      User currentUser = RequestContext.getRequestUser();
78      UserGroupInformation ugi = null;
79      if (currentUser != null) {
80        ugi = currentUser.getUGI();
81      }
82      if (currentUser == null) {
83        throw new AccessDeniedException("No authenticated user for request!");
84      } else if (!isAllowedDelegationTokenOp(ugi)) {
85        LOG.warn("Token generation denied for user="+currentUser.getName()
86            +", authMethod="+ugi.getAuthenticationMethod());
87        throw new AccessDeniedException(
88            "Token generation only allowed for Kerberos authenticated clients");
89      }
90  
91      return secretManager.generateToken(currentUser.getName());
92    }
93  
94    /**
95     * @param ugi
96     * @return true if delegation token operation is allowed
97     */
98    private boolean isAllowedDelegationTokenOp(UserGroupInformation ugi) throws IOException {
99      AuthenticationMethod authMethod = ugi.getAuthenticationMethod();
100     if (authMethod == AuthenticationMethod.PROXY) {
101       authMethod = ugi.getRealUser().getAuthenticationMethod();
102     }
103     if (authMethod != AuthenticationMethod.KERBEROS
104         && authMethod != AuthenticationMethod.KERBEROS_SSL
105         && authMethod != AuthenticationMethod.CERTIFICATE) {
106       return false;
107     }
108     return true;
109   }
110 
111   @Override
112   public String whoami() {
113     return RequestContext.getRequestUserName();
114   }
115 
116   @Override
117   public long getProtocolVersion(String protocol, long clientVersion)
118       throws IOException {
119     if (AuthenticationProtocol.class.getName().equals(protocol)) {
120       return TokenProvider.VERSION;
121     }
122     LOG.warn("Unknown protocol requested: "+protocol);
123     return -1;
124   }
125 }