Search in sources :

Example 41 with AccessController

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();
    }
}
Also used : MasterAuthenticationContext(io.cdap.cdap.security.auth.context.MasterAuthenticationContext) CommonNettyHttpServiceBuilder(io.cdap.cdap.common.http.CommonNettyHttpServiceBuilder) AccessControllerInstantiator(io.cdap.cdap.security.authorization.AccessControllerInstantiator) AccessException(io.cdap.cdap.api.security.AccessException) FeatureDisabledException(io.cdap.cdap.common.FeatureDisabledException) AlreadyExistsException(io.cdap.cdap.security.spi.authorization.AlreadyExistsException) Role(io.cdap.cdap.proto.security.Role) InMemoryAccessController(io.cdap.cdap.security.authorization.InMemoryAccessController) AccessController(io.cdap.cdap.security.spi.authorization.AccessController) InMemoryAccessController(io.cdap.cdap.security.authorization.InMemoryAccessController) NettyHttpService(io.cdap.http.NettyHttpService) AuthorizationClient(io.cdap.cdap.client.AuthorizationClient) NamespaceId(io.cdap.cdap.proto.id.NamespaceId)

Example 42 with AccessController

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());
}
Also used : MasterAuthenticationContext(io.cdap.cdap.security.auth.context.MasterAuthenticationContext) InMemoryAccessController(io.cdap.cdap.security.authorization.InMemoryAccessController) AccessController(io.cdap.cdap.security.spi.authorization.AccessController) CommonNettyHttpServiceBuilder(io.cdap.cdap.common.http.CommonNettyHttpServiceBuilder) InMemoryAccessController(io.cdap.cdap.security.authorization.InMemoryAccessController) AccessControllerInstantiator(io.cdap.cdap.security.authorization.AccessControllerInstantiator) AuthorizationClient(io.cdap.cdap.client.AuthorizationClient) CConfiguration(io.cdap.cdap.common.conf.CConfiguration) ChannelPipelineModifier(io.cdap.http.ChannelPipelineModifier) ChannelPipeline(io.netty.channel.ChannelPipeline) Before(org.junit.Before)

Example 43 with AccessController

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();
}
Also used : ClassWriter(org.objectweb.asm.ClassWriter) Manifest(java.util.jar.Manifest) Authorizer(io.cdap.cdap.security.spi.authorization.Authorizer) Arrays(java.util.Arrays) MethodVisitor(org.objectweb.asm.MethodVisitor) LoggerFactory(org.slf4j.LoggerFactory) TypeToken(com.google.common.reflect.TypeToken) Type(org.objectweb.asm.Type) HashSet(java.util.HashSet) Method(org.objectweb.asm.commons.Method) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ClassVisitor(org.objectweb.asm.ClassVisitor) Nullable(javax.annotation.Nullable) FinallyAdapter(io.cdap.cdap.internal.asm.FinallyAdapter) Opcodes(org.objectweb.asm.Opcodes) ImmutableSet(com.google.common.collect.ImmutableSet) Logger(org.slf4j.Logger) AccessController(io.cdap.cdap.security.spi.authorization.AccessController) Set(java.util.Set) IOException(java.io.IOException) Attributes(java.util.jar.Attributes) Collectors(java.util.stream.Collectors) File(java.io.File) FilterClassLoader(io.cdap.cdap.common.lang.FilterClassLoader) Stream(java.util.stream.Stream) ClassPathResources(io.cdap.cdap.common.lang.ClassPathResources) Signatures(io.cdap.cdap.internal.asm.Signatures) ClassReader(org.objectweb.asm.ClassReader) DirectoryClassLoader(io.cdap.cdap.common.lang.DirectoryClassLoader) BundleJarUtil(io.cdap.cdap.common.lang.jar.BundleJarUtil) VisibleForTesting(com.google.common.annotations.VisibleForTesting) DirUtils(io.cdap.cdap.common.utils.DirUtils) InputStream(java.io.InputStream) FinallyAdapter(io.cdap.cdap.internal.asm.FinallyAdapter) HashSet(java.util.HashSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Method(org.objectweb.asm.commons.Method) ClassVisitor(org.objectweb.asm.ClassVisitor) ClassWriter(org.objectweb.asm.ClassWriter) MethodVisitor(org.objectweb.asm.MethodVisitor) Type(org.objectweb.asm.Type) ClassReader(org.objectweb.asm.ClassReader) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) HashSet(java.util.HashSet) Nullable(javax.annotation.Nullable)

Example 44 with AccessController

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);
        }
    }
}
Also used : AccessController(io.cdap.cdap.security.spi.authorization.AccessController) NoOpAccessController(io.cdap.cdap.security.spi.authorization.NoOpAccessController) File(java.io.File) IOException(java.io.IOException)

Example 45 with AccessController

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"));
    }
}
Also used : AccessController(io.cdap.cdap.security.spi.authorization.AccessController) NoOpAccessController(io.cdap.cdap.security.spi.authorization.NoOpAccessController) CConfiguration(io.cdap.cdap.common.conf.CConfiguration) File(java.io.File) Principal(io.cdap.cdap.proto.security.Principal) Location(org.apache.twill.filesystem.Location) Test(org.junit.Test)

Aggregations

AccessController (io.cdap.cdap.security.spi.authorization.AccessController)50 NoOpAccessController (io.cdap.cdap.security.spi.authorization.NoOpAccessController)30 Test (org.junit.Test)24 InMemoryAccessController (io.cdap.cdap.security.authorization.InMemoryAccessController)18 CConfiguration (io.cdap.cdap.common.conf.CConfiguration)12 Principal (io.cdap.cdap.proto.security.Principal)12 Credential (io.cdap.cdap.proto.security.Credential)10 GrantedPermission (io.cdap.cdap.proto.security.GrantedPermission)10 DatasetId (io.cdap.cdap.proto.id.DatasetId)8 StandardPermission (io.cdap.cdap.proto.security.StandardPermission)8 ImmutableSet (com.google.common.collect.ImmutableSet)6 SConfiguration (io.cdap.cdap.common.conf.SConfiguration)6 EntityId (io.cdap.cdap.proto.id.EntityId)6 NamespaceId (io.cdap.cdap.proto.id.NamespaceId)6 TinkCipher (io.cdap.cdap.security.auth.TinkCipher)6 File (java.io.File)6 IOException (java.io.IOException)6 AuthorizationClient (io.cdap.cdap.client.AuthorizationClient)4 CommonNettyHttpServiceBuilder (io.cdap.cdap.common.http.CommonNettyHttpServiceBuilder)4 MasterAuthenticationContext (io.cdap.cdap.security.auth.context.MasterAuthenticationContext)4