View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.accumulo.server.security.handler;
18  
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.Map;
22  import java.util.Set;
23  import java.util.TreeSet;
24  
25  import org.apache.accumulo.core.Constants;
26  import org.apache.accumulo.core.client.AccumuloSecurityException;
27  import org.apache.accumulo.core.security.Authorizations;
28  import org.apache.accumulo.core.security.SystemPermission;
29  import org.apache.accumulo.core.security.TablePermission;
30  import org.apache.accumulo.core.security.thrift.Credential;
31  import org.apache.accumulo.core.security.thrift.SecurityErrorCode;
32  import org.apache.accumulo.fate.zookeeper.IZooReaderWriter;
33  import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
34  import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeMissingPolicy;
35  import org.apache.accumulo.server.zookeeper.ZooCache;
36  import org.apache.accumulo.server.zookeeper.ZooReaderWriter;
37  import org.apache.log4j.Logger;
38  import org.apache.zookeeper.KeeperException;
39  
40  public class ZKAuthorizor implements Authorizor {
41    private static final Logger log = Logger.getLogger(ZKAuthorizor.class);
42    private static Authorizor zkAuthorizorInstance = null;
43    
44    private final String ZKUserAuths = "/Authorizations";
45    
46    private String ZKUserPath;
47    private final ZooCache zooCache;
48    
49    public static synchronized Authorizor getInstance() {
50      if (zkAuthorizorInstance == null)
51        zkAuthorizorInstance = new ZKAuthorizor();
52      return zkAuthorizorInstance;
53    }
54    
55    public ZKAuthorizor() {
56      zooCache = new ZooCache();
57    }
58    
59    public void initialize(String instanceId, boolean initialize) {
60      ZKUserPath = ZKSecurityTool.getInstancePath(instanceId) + "/users";
61    }
62    
63    public Authorizations getCachedUserAuthorizations(String user) {
64      byte[] authsBytes = zooCache.get(ZKUserPath + "/" + user + ZKUserAuths);
65      if (authsBytes != null)
66        return ZKSecurityTool.convertAuthorizations(authsBytes);
67      return Constants.NO_AUTHS;
68    }
69    
70    @Override
71    public boolean validSecurityHandlers(Authenticator auth, PermissionHandler pm) {
72      return true;
73    }
74    
75    @Override
76    public void initializeSecurity(Credential itw, String rootuser) throws AccumuloSecurityException {
77      IZooReaderWriter zoo = ZooReaderWriter.getRetryingInstance();
78      
79      // create the root user with all system privileges, no table privileges, and no record-level authorizations
80      Set<SystemPermission> rootPerms = new TreeSet<SystemPermission>();
81      for (SystemPermission p : SystemPermission.values())
82        rootPerms.add(p);
83      Map<String,Set<TablePermission>> tablePerms = new HashMap<String,Set<TablePermission>>();
84      // Allow the root user to flush the !METADATA table
85      tablePerms.put(Constants.METADATA_TABLE_ID, Collections.singleton(TablePermission.ALTER_TABLE));
86      
87      try {
88        // prep parent node of users with root username
89        if (!zoo.exists(ZKUserPath))
90          zoo.putPersistentData(ZKUserPath, rootuser.getBytes(), NodeExistsPolicy.FAIL);
91        
92        initUser(rootuser);
93        zoo.putPersistentData(ZKUserPath + "/" + rootuser + ZKUserAuths, ZKSecurityTool.convertAuthorizations(Constants.NO_AUTHS), NodeExistsPolicy.FAIL);
94      } catch (KeeperException e) {
95        log.error(e, e);
96        throw new RuntimeException(e);
97      } catch (InterruptedException e) {
98        log.error(e, e);
99        throw new RuntimeException(e);
100     }
101   }
102   
103   /**
104    * @param user
105    * @throws AccumuloSecurityException
106    */
107   public void initUser(String user) throws AccumuloSecurityException {
108     IZooReaderWriter zoo = ZooReaderWriter.getRetryingInstance();
109     try {
110       zoo.putPersistentData(ZKUserPath + "/" + user, new byte[0], NodeExistsPolicy.SKIP);
111     } catch (KeeperException e) {
112       log.error(e, e);
113       throw new AccumuloSecurityException(user, SecurityErrorCode.CONNECTION_ERROR, e);
114     } catch (InterruptedException e) {
115       log.error(e, e);
116       throw new RuntimeException(e);
117     }
118   }
119   
120   @Override
121   public void dropUser(String user) throws AccumuloSecurityException {
122     try {
123       synchronized (zooCache) {
124         IZooReaderWriter zoo = ZooReaderWriter.getRetryingInstance();
125         zoo.recursiveDelete(ZKUserPath + "/" + user + ZKUserAuths, NodeMissingPolicy.SKIP);
126         zooCache.clear(ZKUserPath + "/" + user);
127       }
128     } catch (InterruptedException e) {
129       log.error(e, e);
130       throw new RuntimeException(e);
131     } catch (KeeperException e) {
132       log.error(e, e);
133       if (e.code().equals(KeeperException.Code.NONODE))
134         throw new AccumuloSecurityException(user, SecurityErrorCode.USER_DOESNT_EXIST, e);
135       throw new AccumuloSecurityException(user, SecurityErrorCode.CONNECTION_ERROR, e);
136       
137     }
138   }
139   
140   @Override
141   public void changeAuthorizations(String user, Authorizations authorizations) throws AccumuloSecurityException {
142     try {
143       synchronized (zooCache) {
144         zooCache.clear();
145         ZooReaderWriter.getRetryingInstance().putPersistentData(ZKUserPath + "/" + user + ZKUserAuths, ZKSecurityTool.convertAuthorizations(authorizations),
146             NodeExistsPolicy.OVERWRITE);
147       }
148     } catch (KeeperException e) {
149       log.error(e, e);
150       throw new AccumuloSecurityException(user, SecurityErrorCode.CONNECTION_ERROR, e);
151     } catch (InterruptedException e) {
152       log.error(e, e);
153       throw new RuntimeException(e);
154     }
155   }
156   
157 }