blob: 39aeef1ff7496118d11cdb3aa5381fc3f02d0409 [file] [log] [blame]
// 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.impala.catalog;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.impala.thrift.TCatalogObject;
import org.apache.impala.thrift.TCatalogObjectType;
import org.apache.impala.thrift.TPrincipal;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.impala.thrift.TPrincipalType;
/**
* A base class that represents a principal in an authorization policy.
* This class is thread safe.
*/
public abstract class Principal extends CatalogObjectImpl {
private final TPrincipal principal_;
// The last principal ID assigned, starts at 0.
private static AtomicInteger principalId_ = new AtomicInteger(0);
// URIs are case sensitive, so we need to store privilege names in a case sensitive way.
private final CatalogObjectCache<PrincipalPrivilege> principalPrivileges_ =
new CatalogObjectCache<>(false);
protected Principal(String principalName, TPrincipalType type,
Set<String> grantGroups) {
principal_ = new TPrincipal();
principal_.setPrincipal_name(principalName);
principal_.setPrincipal_type(type);
principal_.setPrincipal_id(principalId_.incrementAndGet());
principal_.setGrant_groups(Lists.newArrayList(grantGroups));
}
protected Principal(TPrincipal principal) {
principal_ = principal;
}
/**
* Adds a privilege to the principal. Returns true if the privilege was added
* successfully or false if there was a newer version of the privilege already added
* to the principal.
*/
public boolean addPrivilege(PrincipalPrivilege privilege) {
return principalPrivileges_.add(privilege);
}
/**
* Returns all privileges for this principal. If no privileges have been added to the
* principal, an empty list is returned.
*/
public List<PrincipalPrivilege> getPrivileges() {
return new ArrayList<>(principalPrivileges_.getValues());
}
/**
* Returns all privilege names for this principal, or an empty set of no privileges are
* granted to the principal.
*/
public Set<String> getPrivilegeNames() {
return new HashSet<>(principalPrivileges_.keySet());
}
/**
* Gets a privilege with the given name from this principal. If no privilege exists
* with this name null is returned.
*/
public PrincipalPrivilege getPrivilege(String privilegeName) {
return principalPrivileges_.get(privilegeName);
}
/**
* Removes a privilege with the given name from the principal. Returns the removed
* privilege or null if no privilege exists with this name.
*/
public PrincipalPrivilege removePrivilege(String privilegeName) {
return principalPrivileges_.remove(privilegeName);
}
/**
* Adds a new grant group to this principal.
*/
public synchronized void addGrantGroup(String groupName) {
if (principal_.getGrant_groups().contains(groupName)) return;
principal_.addToGrant_groups(groupName);
}
/**
* Removes a grant group from this principal.
*/
public synchronized void removeGrantGroup(String groupName) {
principal_.getGrant_groups().remove(groupName);
// Should never have duplicates in the list of groups.
Preconditions.checkState(!principal_.getGrant_groups().contains(groupName));
}
/**
* Returns the Thrift representation of the principal.
*/
public TPrincipal toThrift() {
return principal_;
}
/**
* Creates a Principal from a TPrincipal thrift struct.
*/
public static Principal fromThrift(TPrincipal thriftPrincipal) {
return thriftPrincipal.getPrincipal_type() == TPrincipalType.ROLE ?
new Role(thriftPrincipal) : new User(thriftPrincipal);
}
/**
* Creates a new instance of Principal.
*/
public static Principal newInstance(String principalName, TPrincipalType type,
Set<String> grantGroups) {
return type == TPrincipalType.ROLE ?
new Role(principalName, grantGroups) : new User(principalName, grantGroups);
}
/**
* Gets the set of group names that have been granted to this principal or an empty
* set if no groups have been granted.
*/
public Set<String> getGrantGroups() {
return Sets.newHashSet(principal_.getGrant_groups());
}
@Override
public TCatalogObjectType getCatalogObjectType() {
return TCatalogObjectType.PRINCIPAL;
}
@Override
public String getName() { return principal_.getPrincipal_name(); }
/**
* Returns the principal ID.
*/
public int getId() { return principal_.getPrincipal_id(); }
@Override
protected void setTCatalogObject(TCatalogObject catalogObject) {
catalogObject.setPrincipal(toThrift());
}
/**
* Returns the principal type.
*/
public TPrincipalType getPrincipalType() { return principal_.getPrincipal_type(); }
public static String toString(TPrincipalType type) {
String principal;
switch (type) {
case ROLE:
principal = "Role";
break;
case USER:
principal = "User";
break;
case GROUP:
principal = "Group";
break;
default:
throw new IllegalStateException(String.format("Unsupported principal type " +
"%s.", type));
}
return principal;
}
}