blob: 6e3d714cf77638a842da559b460c8fbea72d32c0 [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.accumulo.core.client.impl;
import static com.google.common.base.Preconditions.checkArgument;
import java.nio.ByteBuffer;
import java.util.Set;
import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.accumulo.core.client.admin.DelegationTokenConfig;
import org.apache.accumulo.core.client.admin.SecurityOperations;
import org.apache.accumulo.core.client.impl.thrift.ClientService;
import org.apache.accumulo.core.client.impl.thrift.SecurityErrorCode;
import org.apache.accumulo.core.client.impl.thrift.TableOperationExceptionType;
import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
import org.apache.accumulo.core.client.security.tokens.DelegationToken;
import org.apache.accumulo.core.client.security.tokens.PasswordToken;
import org.apache.accumulo.core.master.thrift.MasterClientService.Client;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.accumulo.core.security.NamespacePermission;
import org.apache.accumulo.core.security.SystemPermission;
import org.apache.accumulo.core.security.TablePermission;
import org.apache.accumulo.core.security.thrift.TDelegationToken;
import org.apache.accumulo.core.security.thrift.TDelegationTokenConfig;
import org.apache.accumulo.core.trace.Tracer;
import org.apache.accumulo.core.util.ByteBufferUtil;
public class SecurityOperationsImpl implements SecurityOperations {
private final ClientContext context;
private void executeVoid(ClientExec<ClientService.Client> exec) throws AccumuloException, AccumuloSecurityException {
try {
ServerClient.executeRawVoid(context, exec);
} catch (ThriftTableOperationException ttoe) {
// recast missing table
if (ttoe.getType() == TableOperationExceptionType.NOTFOUND)
throw new AccumuloSecurityException(null, SecurityErrorCode.TABLE_DOESNT_EXIST);
else if (ttoe.getType() == TableOperationExceptionType.NAMESPACE_NOTFOUND)
throw new AccumuloSecurityException(null, SecurityErrorCode.NAMESPACE_DOESNT_EXIST);
else
throw new AccumuloException(ttoe);
} catch (ThriftSecurityException e) {
throw new AccumuloSecurityException(e.user, e.code, e);
} catch (AccumuloException e) {
throw e;
} catch (Exception e) {
throw new AccumuloException(e);
}
}
private <T> T execute(ClientExecReturn<T,ClientService.Client> exec) throws AccumuloException, AccumuloSecurityException {
try {
return ServerClient.executeRaw(context, exec);
} catch (ThriftTableOperationException ttoe) {
// recast missing table
if (ttoe.getType() == TableOperationExceptionType.NOTFOUND)
throw new AccumuloSecurityException(null, SecurityErrorCode.TABLE_DOESNT_EXIST);
else if (ttoe.getType() == TableOperationExceptionType.NAMESPACE_NOTFOUND)
throw new AccumuloSecurityException(null, SecurityErrorCode.NAMESPACE_DOESNT_EXIST);
else
throw new AccumuloException(ttoe);
} catch (ThriftSecurityException e) {
throw new AccumuloSecurityException(e.user, e.code, e);
} catch (AccumuloException e) {
throw e;
} catch (Exception e) {
throw new AccumuloException(e);
}
}
public SecurityOperationsImpl(ClientContext context) {
checkArgument(context != null, "context is null");
this.context = context;
}
@Override
public void createLocalUser(final String principal, final PasswordToken password) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
if (null == context.getSaslParams()) {
checkArgument(password != null, "password is null");
}
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
if (null == context.getSaslParams()) {
client.createLocalUser(Tracer.traceInfo(), context.rpcCreds(), principal, ByteBuffer.wrap(password.getPassword()));
} else {
client.createLocalUser(Tracer.traceInfo(), context.rpcCreds(), principal, ByteBuffer.wrap(new byte[0]));
}
}
});
}
@Override
public void dropLocalUser(final String principal) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.dropLocalUser(Tracer.traceInfo(), context.rpcCreds(), principal);
}
});
}
@Override
public boolean authenticateUser(final String principal, final AuthenticationToken token) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(token != null, "token is null");
final Credentials toAuth = new Credentials(principal, token);
return execute(new ClientExecReturn<Boolean,ClientService.Client>() {
@Override
public Boolean execute(ClientService.Client client) throws Exception {
return client.authenticateUser(Tracer.traceInfo(), context.rpcCreds(), toAuth.toThrift(context.getInstance()));
}
});
}
@Override
public void changeLocalUserPassword(final String principal, final PasswordToken token) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(token != null, "token is null");
final Credentials toChange = new Credentials(principal, token);
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.changeLocalUserPassword(Tracer.traceInfo(), context.rpcCreds(), principal, ByteBuffer.wrap(token.getPassword()));
}
});
if (context.getCredentials().getPrincipal().equals(principal)) {
context.setCredentials(toChange);
}
}
@Override
public void changeUserAuthorizations(final String principal, final Authorizations authorizations) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(authorizations != null, "authorizations is null");
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.changeAuthorizations(Tracer.traceInfo(), context.rpcCreds(), principal, ByteBufferUtil.toByteBuffers(authorizations.getAuthorizations()));
}
});
}
@Override
public Authorizations getUserAuthorizations(final String principal) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
return execute(new ClientExecReturn<Authorizations,ClientService.Client>() {
@Override
public Authorizations execute(ClientService.Client client) throws Exception {
return new Authorizations(client.getUserAuthorizations(Tracer.traceInfo(), context.rpcCreds(), principal));
}
});
}
@Override
public boolean hasSystemPermission(final String principal, final SystemPermission perm) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(perm != null, "perm is null");
return execute(new ClientExecReturn<Boolean,ClientService.Client>() {
@Override
public Boolean execute(ClientService.Client client) throws Exception {
return client.hasSystemPermission(Tracer.traceInfo(), context.rpcCreds(), principal, perm.getId());
}
});
}
@Override
public boolean hasTablePermission(final String principal, final String table, final TablePermission perm) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(table != null, "table is null");
checkArgument(perm != null, "perm is null");
try {
return execute(new ClientExecReturn<Boolean,ClientService.Client>() {
@Override
public Boolean execute(ClientService.Client client) throws Exception {
return client.hasTablePermission(Tracer.traceInfo(), context.rpcCreds(), principal, table, perm.getId());
}
});
} catch (AccumuloSecurityException e) {
if (e.getSecurityErrorCode() == org.apache.accumulo.core.client.security.SecurityErrorCode.NAMESPACE_DOESNT_EXIST)
throw new AccumuloSecurityException(null, SecurityErrorCode.TABLE_DOESNT_EXIST, e);
else
throw e;
}
}
@Override
public boolean hasNamespacePermission(final String principal, final String namespace, final NamespacePermission permission) throws AccumuloException,
AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(namespace != null, "namespace is null");
checkArgument(permission != null, "permission is null");
return execute(new ClientExecReturn<Boolean,ClientService.Client>() {
@Override
public Boolean execute(ClientService.Client client) throws Exception {
return client.hasNamespacePermission(Tracer.traceInfo(), context.rpcCreds(), principal, namespace, permission.getId());
}
});
}
@Override
public void grantSystemPermission(final String principal, final SystemPermission permission) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(permission != null, "permission is null");
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.grantSystemPermission(Tracer.traceInfo(), context.rpcCreds(), principal, permission.getId());
}
});
}
@Override
public void grantTablePermission(final String principal, final String table, final TablePermission permission) throws AccumuloException,
AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(table != null, "table is null");
checkArgument(permission != null, "permission is null");
try {
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.grantTablePermission(Tracer.traceInfo(), context.rpcCreds(), principal, table, permission.getId());
}
});
} catch (AccumuloSecurityException e) {
if (e.getSecurityErrorCode() == org.apache.accumulo.core.client.security.SecurityErrorCode.NAMESPACE_DOESNT_EXIST)
throw new AccumuloSecurityException(null, SecurityErrorCode.TABLE_DOESNT_EXIST, e);
else
throw e;
}
}
@Override
public void grantNamespacePermission(final String principal, final String namespace, final NamespacePermission permission) throws AccumuloException,
AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(namespace != null, "namespace is null");
checkArgument(permission != null, "permission is null");
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.grantNamespacePermission(Tracer.traceInfo(), context.rpcCreds(), principal, namespace, permission.getId());
}
});
}
@Override
public void revokeSystemPermission(final String principal, final SystemPermission permission) throws AccumuloException, AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(permission != null, "permission is null");
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.revokeSystemPermission(Tracer.traceInfo(), context.rpcCreds(), principal, permission.getId());
}
});
}
@Override
public void revokeTablePermission(final String principal, final String table, final TablePermission permission) throws AccumuloException,
AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(table != null, "table is null");
checkArgument(permission != null, "permission is null");
try {
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.revokeTablePermission(Tracer.traceInfo(), context.rpcCreds(), principal, table, permission.getId());
}
});
} catch (AccumuloSecurityException e) {
if (e.getSecurityErrorCode() == org.apache.accumulo.core.client.security.SecurityErrorCode.NAMESPACE_DOESNT_EXIST)
throw new AccumuloSecurityException(null, SecurityErrorCode.TABLE_DOESNT_EXIST, e);
else
throw e;
}
}
@Override
public void revokeNamespacePermission(final String principal, final String namespace, final NamespacePermission permission) throws AccumuloException,
AccumuloSecurityException {
checkArgument(principal != null, "principal is null");
checkArgument(namespace != null, "namespace is null");
checkArgument(permission != null, "permission is null");
executeVoid(new ClientExec<ClientService.Client>() {
@Override
public void execute(ClientService.Client client) throws Exception {
client.revokeNamespacePermission(Tracer.traceInfo(), context.rpcCreds(), principal, namespace, permission.getId());
}
});
}
@Override
public Set<String> listLocalUsers() throws AccumuloException, AccumuloSecurityException {
return execute(new ClientExecReturn<Set<String>,ClientService.Client>() {
@Override
public Set<String> execute(ClientService.Client client) throws Exception {
return client.listLocalUsers(Tracer.traceInfo(), context.rpcCreds());
}
});
}
@Override
public DelegationToken getDelegationToken(DelegationTokenConfig cfg) throws AccumuloException, AccumuloSecurityException {
final TDelegationTokenConfig tConfig;
if (null != cfg) {
tConfig = DelegationTokenConfigSerializer.serialize(cfg);
} else {
tConfig = new TDelegationTokenConfig();
}
TDelegationToken thriftToken;
try {
thriftToken = MasterClient.execute(context, new ClientExecReturn<TDelegationToken,Client>() {
@Override
public TDelegationToken execute(Client client) throws Exception {
return client.getDelegationToken(Tracer.traceInfo(), context.rpcCreds(), tConfig);
}
});
} catch (TableNotFoundException e) {
// should never happen
throw new AssertionError("Received TableNotFoundException on method which should not throw that exception", e);
}
AuthenticationTokenIdentifier identifier = new AuthenticationTokenIdentifier(thriftToken.getIdentifier());
// Get the password out of the thrift delegation token
return new DelegationTokenImpl(thriftToken.getPassword(), identifier);
}
}