use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.
the class AuthorizationHandlerTest method testDisabled.
private void testDisabled(CConfiguration cConf, FeatureDisabledException.Feature feature, String configSetting) throws Exception {
final InMemoryAccessController accessController = new InMemoryAccessController();
NettyHttpService service = new CommonNettyHttpServiceBuilder(cConf, getClass().getSimpleName()).setHttpHandlers(new AuthorizationHandler(accessController, new AccessControllerInstantiator(cConf, FACTORY) {
@Override
public AccessController get() {
return accessController;
}
}, cConf, new MasterAuthenticationContext())).build();
service.start();
try {
final AuthorizationClient client = new AuthorizationClient(ClientConfig.builder().setConnectionConfig(ConnectionConfig.builder().setHostname(service.getBindAddress().getHostName()).setPort(service.getBindAddress().getPort()).setSSLEnabled(false).build()).build());
final NamespaceId ns1 = Ids.namespace("ns1");
final Role admins = new Role("admins");
// Test that the right exception is thrown when any Authorization REST API is called with authorization disabled
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.grant(Authorizable.fromEntityId(ns1), admin, ImmutableSet.of(StandardPermission.GET));
}
}, feature, configSetting);
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.revoke(Authorizable.fromEntityId(ns1), admin, ImmutableSet.of(StandardPermission.GET));
}
}, feature, configSetting);
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.revoke(Authorizable.fromEntityId(ns1));
}
}, feature, configSetting);
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.listGrants(admin);
}
}, feature, configSetting);
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.addRoleToPrincipal(admins, admin);
}
}, feature, configSetting);
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.removeRoleFromPrincipal(admins, admin);
}
}, feature, configSetting);
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.createRole(admins);
}
}, feature, configSetting);
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.dropRole(admins);
}
}, feature, configSetting);
verifyFeatureDisabled(new DisabledFeatureCaller() {
@Override
public void call() throws Exception {
client.listAllRoles();
}
}, feature, configSetting);
} finally {
service.stop();
}
}
use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.
the class AuthorizationHandlerTest method setUp.
@Before
public void setUp() throws Exception {
CConfiguration conf = CConfiguration.create();
conf.setBoolean(Constants.Security.Authorization.ENABLED, true);
conf.setBoolean(Constants.Security.ENABLED, true);
properties.setProperty("superusers", admin.getName());
final InMemoryAccessController auth = new InMemoryAccessController();
auth.initialize(FACTORY.create(properties));
service = new CommonNettyHttpServiceBuilder(conf, getClass().getSimpleName()).setHttpHandlers(new AuthorizationHandler(auth, new AccessControllerInstantiator(conf, FACTORY) {
@Override
public AccessController get() {
return auth;
}
}, conf, new MasterAuthenticationContext())).setChannelPipelineModifier(new ChannelPipelineModifier() {
@Override
public void modify(ChannelPipeline pipeline) {
pipeline.addBefore("dispatcher", "usernamesetter", new TestUserNameSetter());
}
}).build();
service.start();
client = new AuthorizationClient(ClientConfig.builder().setConnectionConfig(ConnectionConfig.builder().setHostname(service.getBindAddress().getHostName()).setPort(service.getBindAddress().getPort()).setSSLEnabled(false).build()).build());
System.setProperty(USERNAME_PROPERTY, admin.getName());
}
use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.
the class AccessControllerClassLoader method rewriteClass.
@Nullable
@Override
public byte[] rewriteClass(String className, InputStream input) throws IOException {
if (!accessControllerClassName.equals(className)) {
return null;
}
// Rewrite the AccessController class to wrap every methods call with context classloader change
Set<java.lang.reflect.Method> accessControlMethods = Stream.of(Authorizer.class, AccessController.class).flatMap(c -> Stream.of(c.getMethods())).collect(Collectors.toSet());
ClassReader cr = new ClassReader(input);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cr.accept(new ClassVisitor(Opcodes.ASM7, cw) {
private String superName;
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
this.superName = superName;
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
Method method = new Method(name, descriptor);
// Only rewrite methods defined in the Authorizer or AccessController interface.
if (accessControlMethods.removeIf(m -> method.equals(Method.getMethod(m)))) {
return rewriteMethod(access, name, descriptor, mv);
}
return mv;
}
@Override
public void visitEnd() {
if (Type.getType(Object.class).getInternalName().equals(superName)) {
// the one we need and it's not trivial as those interfaces can be in the current jar we are trying to load.
return;
}
// Generates all the missing methods on the Authorizer interface so that we can wrap them with the
// context classloader switch.
Set<Method> generatedMethods = new HashSet<>();
new HashSet<>(accessControlMethods).forEach(m -> {
Method method = Method.getMethod(m);
// Guard against same method signature that comes from different parent interfaces
if (!generatedMethods.add(method)) {
return;
}
// Generate the method by calling super.[method]
String signature = Signatures.getMethodSignature(method, TypeToken.of(m.getGenericReturnType()), Arrays.stream(m.getGenericParameterTypes()).map(TypeToken::of).toArray(TypeToken[]::new));
String[] exceptions = Arrays.stream(m.getExceptionTypes()).map(Type::getInternalName).toArray(String[]::new);
MethodVisitor mv = rewriteMethod(Opcodes.ACC_PUBLIC, method.getName(), method.getDescriptor(), visitMethod(Opcodes.ACC_PUBLIC, method.getName(), method.getDescriptor(), signature, exceptions));
GeneratorAdapter generator = new GeneratorAdapter(Opcodes.ACC_PUBLIC, method, mv);
generator.visitCode();
generator.loadThis();
generator.loadArgs();
generator.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, method.getName(), method.getDescriptor(), false);
generator.returnValue();
generator.endMethod();
});
super.visitEnd();
}
/**
* Rewrites the method by wrapping the whole method call with the context classloader switch to the
* AccessControllerClassLoader.
*/
private MethodVisitor rewriteMethod(int access, String name, String descriptor, MethodVisitor mv) {
return new FinallyAdapter(Opcodes.ASM7, mv, access, name, descriptor) {
int currentThread;
int oldClassLoader;
@Override
protected void onMethodEnter() {
// Thread currentThread = Thread.currentThread();
invokeStatic(THREAD_TYPE, new Method("currentThread", THREAD_TYPE, new Type[0]));
currentThread = newLocal(THREAD_TYPE);
storeLocal(currentThread, THREAD_TYPE);
// ClassLoader oldClassLoader = currentThread.getContextClassLoader();
loadLocal(currentThread, THREAD_TYPE);
invokeVirtual(THREAD_TYPE, new Method("getContextClassLoader", CLASSLOADER_TYPE, new Type[0]));
oldClassLoader = newLocal(CLASSLOADER_TYPE);
storeLocal(oldClassLoader, CLASSLOADER_TYPE);
// currentThread.setContextClassLoader(getClass().getClassLoader());
loadLocal(currentThread, THREAD_TYPE);
loadThis();
invokeVirtual(Type.getType(Object.class), new Method("getClass", Type.getType(Class.class), new Type[0]));
invokeVirtual(Type.getType(Class.class), new Method("getClassLoader", CLASSLOADER_TYPE, new Type[0]));
invokeVirtual(THREAD_TYPE, new Method("setContextClassLoader", Type.VOID_TYPE, new Type[] { CLASSLOADER_TYPE }));
beginTry();
}
@Override
protected void onFinally(int opcode) {
// currentThread.setContextClassLoader(oldClassLoader);
loadLocal(currentThread, THREAD_TYPE);
loadLocal(oldClassLoader, CLASSLOADER_TYPE);
invokeVirtual(THREAD_TYPE, new Method("setContextClassLoader", Type.VOID_TYPE, new Type[] { CLASSLOADER_TYPE }));
}
};
}
}, ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
}
use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.
the class AccessControllerInstantiator method get.
/**
* Returns an instance of the configured {@link AccessController} extension, or of {@link NoOpAccessController}, if
* authorization is disabled.
*/
@Override
public AccessController get() {
if (!cConf.getBoolean(Constants.Security.Authorization.ENABLED)) {
LOG.debug("Authorization is disabled. Authorization can be enabled by setting " + Constants.Security.Authorization.ENABLED + " to true.");
return NOOP_ACCESS_CONTROLLER;
}
if (!cConf.getBoolean(Constants.Security.ENABLED)) {
LOG.warn("Authorization is enabled. However, authentication is disabled. Authorization policies will not be " + "enforced. To enforce authorization policies please enable both authorization, by setting " + Constants.Security.Authorization.ENABLED + " to true and authentication, by setting " + Constants.Security.ENABLED + "to true.");
return NOOP_ACCESS_CONTROLLER;
}
// Authorization is enabled
AccessController accessController = this.accessController;
if (accessController != null) {
return accessController;
}
synchronized (this) {
accessController = this.accessController;
if (accessController != null) {
return accessController;
}
if (closed) {
throw new RuntimeException("Cannot create AccessController due to resources were closed");
}
String accessControllerExtensionJarPath = cConf.get(Constants.Security.Authorization.EXTENSION_JAR_PATH);
String accessControllerExtraClasspath = cConf.get(Constants.Security.Authorization.EXTENSION_EXTRA_CLASSPATH);
if (Strings.isNullOrEmpty(accessControllerExtensionJarPath)) {
throw new IllegalArgumentException(String.format("Access control extension jar path not found in configuration. Please set %s in " + "cdap-site.xml to the fully qualified path of the jar file to use as the authorization " + "backend.", Constants.Security.Authorization.EXTENSION_JAR_PATH));
}
try {
File accessControllerExtensionJar = new File(accessControllerExtensionJarPath);
ensureValidAuthExtensionJar(accessControllerExtensionJar);
accessControllerClassLoader = createAccessControllerClassLoader(accessControllerExtensionJar, accessControllerExtraClasspath);
this.accessController = accessController = createAccessController(accessControllerClassLoader);
return accessController;
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
}
use of io.cdap.cdap.security.spi.authorization.AccessController in project cdap by cdapio.
the class AccessControllerInstantiatorTest method testAccessControllerExtension.
@Test
public void testAccessControllerExtension() throws Exception {
Location externalAuthJar = createValidAuthExtensionJar();
CConfiguration cConfCopy = CConfiguration.copy(CCONF);
cConfCopy.set(Constants.Security.Authorization.EXTENSION_JAR_PATH, externalAuthJar.toString());
// Create a temporary file.
final File tempFile = TEMP_FOLDER.newFile("conf-file.xml");
cConfCopy.set(Constants.Security.Authorization.EXTENSION_EXTRA_CLASSPATH, tempFile.getParent());
try (AccessControllerInstantiator instantiator = new AccessControllerInstantiator(cConfCopy, AUTH_CONTEXT_FACTORY)) {
// should be able to load the ExternalAccessController class via the AccessControllerInstantiatorService
AccessController externalAccessController1 = instantiator.get();
externalAccessController1.listAllRoles();
externalAccessController1.listGrants(new Principal("test", Principal.PrincipalType.USER));
ClassLoader accessControllerClassLoader = externalAccessController1.getClass().getClassLoader();
// should be able to load the ExternalAccessController class via the AccessControllerClassLoader
accessControllerClassLoader.loadClass(ValidExternalAccessController.class.getName());
Assert.assertNotNull(accessControllerClassLoader.getResource("conf-file.xml"));
}
}
Aggregations