Search in sources :

Example 1 with SecureStoreMetadata

use of io.cdap.cdap.api.security.store.SecureStoreMetadata in project cdap by caskdata.

the class RemoteExecutionJobMain method initialize.

@VisibleForTesting
RemoteExecutionRuntimeJobEnvironment initialize(CConfiguration cConf) throws Exception {
    zkServer = InMemoryZKServer.builder().build();
    zkServer.startAndWait();
    InetSocketAddress zkAddr = ResolvingDiscoverable.resolve(zkServer.getLocalAddress());
    String zkConnectStr = String.format("%s:%d", zkAddr.getHostString(), zkAddr.getPort());
    LOG.debug("In memory ZK started at {}", zkConnectStr);
    cConf.set(Constants.Zookeeper.QUORUM, zkConnectStr);
    Injector injector = Guice.createInjector(new ConfigModule(cConf), RemoteAuthenticatorModules.getDefaultModule(), new DFSLocationModule(), new InMemoryDiscoveryModule(), new TwillModule(), new AuthenticationContextModules().getProgramContainerModule(cConf), new AbstractModule() {

        @Override
        protected void configure() {
            // don't need to perform any impersonation from within user programs
            bind(UGIProvider.class).to(CurrentUGIProvider.class).in(Scopes.SINGLETON);
            // Binds a no-op SecureStore for the TwillModule to setup TokenSecureStoreRenewer.
            bind(SecureStore.class).toInstance(new SecureStore() {

                @Override
                public List<SecureStoreMetadata> list(String namespace) {
                    return Collections.emptyList();
                }

                @Override
                public SecureStoreData get(String namespace, String name) throws Exception {
                    throw new NotFoundException("Secure key " + name + " not found in namespace " + namespace);
                }
            });
        }
    });
    Map<String, String> properties = new HashMap<>();
    properties.put(Constants.Zookeeper.QUORUM, zkConnectStr);
    locationFactory = injector.getInstance(LocationFactory.class);
    locationFactory.create("/").mkdirs();
    twillRunnerService = injector.getInstance(TwillRunnerService.class);
    twillRunnerService.start();
    if (UserGroupInformation.isSecurityEnabled()) {
        TokenSecureStoreRenewer secureStoreRenewer = injector.getInstance(TokenSecureStoreRenewer.class);
        secureStoreUpdateCancellable = twillRunnerService.setSecureStoreRenewer(secureStoreRenewer, 30000L, secureStoreRenewer.getUpdateInterval(), 30000L, TimeUnit.MILLISECONDS);
    }
    return new RemoteExecutionRuntimeJobEnvironment(locationFactory, twillRunnerService, properties);
}
Also used : InMemoryDiscoveryModule(io.cdap.cdap.common.guice.InMemoryDiscoveryModule) TwillModule(io.cdap.cdap.app.guice.TwillModule) SecureStoreMetadata(io.cdap.cdap.api.security.store.SecureStoreMetadata) HashMap(java.util.HashMap) InetSocketAddress(java.net.InetSocketAddress) ConfigModule(io.cdap.cdap.common.guice.ConfigModule) AuthenticationContextModules(io.cdap.cdap.security.auth.context.AuthenticationContextModules) TokenSecureStoreRenewer(io.cdap.cdap.security.TokenSecureStoreRenewer) UGIProvider(io.cdap.cdap.security.impersonation.UGIProvider) CurrentUGIProvider(io.cdap.cdap.security.impersonation.CurrentUGIProvider) NotFoundException(io.cdap.cdap.common.NotFoundException) SecureStore(io.cdap.cdap.api.security.store.SecureStore) AbstractModule(com.google.inject.AbstractModule) LocationFactory(org.apache.twill.filesystem.LocationFactory) DFSLocationModule(io.cdap.cdap.common.guice.DFSLocationModule) Injector(com.google.inject.Injector) TwillRunnerService(org.apache.twill.api.TwillRunnerService) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 2 with SecureStoreMetadata

use of io.cdap.cdap.api.security.store.SecureStoreMetadata in project cdap by caskdata.

the class DefaultSecureStoreServiceTest method testSecureStoreAccess.

@Test
public void testSecureStoreAccess() throws Exception {
    final SecureKeyId secureKeyId1 = NamespaceId.DEFAULT.secureKey(KEY1);
    SecurityRequestContext.setUserId(ALICE.getName());
    try {
        secureStoreManager.put(NamespaceId.DEFAULT.getNamespace(), KEY1, VALUE1, DESCRIPTION1, Collections.<String, String>emptyMap());
        Assert.fail("Alice should not be able to store a key since she does not have WRITE privileges on the namespace");
    } catch (UnauthorizedException expected) {
    // expected
    }
    // Grant ALICE admin access to the secure key
    grantAndAssertSuccess(NamespaceId.DEFAULT, ALICE, EnumSet.of(StandardPermission.GET));
    grantAndAssertSuccess(Authorizable.fromEntityId(NamespaceId.DEFAULT, EntityType.SECUREKEY), ALICE, EnumSet.of(StandardPermission.LIST));
    grantAndAssertSuccess(secureKeyId1, ALICE, EnumSet.allOf(StandardPermission.class));
    // Write should succeed
    secureStoreManager.put(NamespaceId.DEFAULT.getNamespace(), KEY1, VALUE1, DESCRIPTION1, Collections.<String, String>emptyMap());
    // Listing should return the value just written
    List<SecureStoreMetadata> metadatas = secureStore.list(NamespaceId.DEFAULT.getNamespace());
    Assert.assertEquals(1, metadatas.size());
    Assert.assertEquals(KEY1, metadatas.get(0).getName());
    Assert.assertEquals(DESCRIPTION1, metadatas.get(0).getDescription());
    revokeAndAssertSuccess(secureKeyId1, ALICE, EnumSet.allOf(StandardPermission.class));
    // Should not be able to list the keys since ALICE does not have privilege on the secure key
    try {
        secureStore.list(NamespaceId.DEFAULT.getNamespace());
    } catch (UnauthorizedException e) {
    // expected
    }
    // Give BOB read access and verify that he can read the stored data
    SecurityRequestContext.setUserId(BOB.getName());
    grantAndAssertSuccess(NamespaceId.DEFAULT, BOB, EnumSet.of(StandardPermission.GET));
    grantAndAssertSuccess(secureKeyId1, BOB, EnumSet.of(StandardPermission.GET));
    grantAndAssertSuccess(Authorizable.fromEntityId(NamespaceId.DEFAULT, EntityType.SECUREKEY), BOB, EnumSet.of(StandardPermission.LIST));
    Assert.assertEquals(VALUE1, new String(secureStore.get(NamespaceId.DEFAULT.getNamespace(), KEY1).get(), Charsets.UTF_8));
    metadatas = secureStore.list(NamespaceId.DEFAULT.getNamespace());
    Assert.assertEquals(1, metadatas.size());
    // BOB should not be able to delete the key
    try {
        secureStoreManager.delete(NamespaceId.DEFAULT.getNamespace(), KEY1);
        Assert.fail("Bob should not be able to delete a key since he does not have ADMIN privileges on the key");
    } catch (UnauthorizedException expected) {
    // expected
    }
    // Grant Bob ADMIN access and he should be able to delete the key
    grantAndAssertSuccess(secureKeyId1, BOB, ImmutableSet.of(StandardPermission.DELETE));
    secureStoreManager.delete(NamespaceId.DEFAULT.getNamespace(), KEY1);
    Assert.assertEquals(0, secureStore.list(NamespaceId.DEFAULT.getNamespace()).size());
    Predicate<GrantedPermission> secureKeyIdFilter = new Predicate<GrantedPermission>() {

        @Override
        public boolean apply(GrantedPermission input) {
            return input.getAuthorizable().equals(Authorizable.fromEntityId(secureKeyId1));
        }
    };
}
Also used : SecureKeyId(io.cdap.cdap.proto.id.SecureKeyId) SecureStoreMetadata(io.cdap.cdap.api.security.store.SecureStoreMetadata) UnauthorizedException(io.cdap.cdap.security.spi.authorization.UnauthorizedException) GrantedPermission(io.cdap.cdap.proto.security.GrantedPermission) StandardPermission(io.cdap.cdap.proto.security.StandardPermission) Predicate(com.google.common.base.Predicate) Test(org.junit.Test)

Example 3 with SecureStoreMetadata

use of io.cdap.cdap.api.security.store.SecureStoreMetadata in project cdap by caskdata.

the class KMSSecureStoreService method list.

/**
 * List of all the entries in the secure store. No filtering or authentication is done here.
 * This method makes two calls to the KMS provider, one to get the list of keys and then another call to
 * get the metadata for all the keys in the requested namespace.
 * @return A list of {@link SecureStoreMetadata} objects representing the data stored in the store.
 * @param namespace The namespace this key belongs to.
 * @throws NamespaceNotFoundException If the specified namespace does not exist.
 * @throws ConcurrentModificationException If a key was deleted between the time we got the list of keys and when
 * we got their metadata.
 * @throws IOException If there was a problem getting the list from the underlying key provider.
 */
// Unfortunately KeyProvider does not specify the underlying cause except in the message, so we can not throw a
// more specific exception.
@Override
public List<SecureStoreMetadata> list(String namespace) throws Exception {
    checkNamespaceExists(namespace);
    String prefix = namespace + NAME_SEPARATOR;
    List<String> keysInNamespace = new ArrayList<>();
    KeyProvider.Metadata[] metadatas;
    try {
        for (String key : provider.getKeys()) {
            if (key.startsWith(prefix)) {
                keysInNamespace.add(key);
            }
        }
        metadatas = provider.getKeysMetadata(keysInNamespace.toArray(new String[keysInNamespace.size()]));
    } catch (IOException e) {
        throw new IOException("Failed to get the list of elements from the secure store.", e);
    }
    // If a key was deleted between the time we get the list of keys and their metadatas then throw an exception
    if (metadatas.length != keysInNamespace.size()) {
        throw new ConcurrentModificationException("A key was deleted while listing was in progress. Please try again.");
    }
    List<SecureStoreMetadata> secureStoreMetadatas = new ArrayList<>(metadatas.length);
    for (int i = 0; i < metadatas.length; i++) {
        KeyProvider.Metadata metadata = metadatas[i];
        secureStoreMetadatas.add(new SecureStoreMetadata(keysInNamespace.get(i).substring(prefix.length()), metadata.getDescription(), metadata.getCreated().getTime(), metadata.getAttributes()));
    }
    return secureStoreMetadatas;
}
Also used : KeyProvider(org.apache.hadoop.crypto.key.KeyProvider) ConcurrentModificationException(java.util.ConcurrentModificationException) SecureStoreMetadata(io.cdap.cdap.api.security.store.SecureStoreMetadata) ArrayList(java.util.ArrayList) SecureStoreMetadata(io.cdap.cdap.api.security.store.SecureStoreMetadata) IOException(java.io.IOException)

Example 4 with SecureStoreMetadata

use of io.cdap.cdap.api.security.store.SecureStoreMetadata in project cdap by caskdata.

the class FileSecureStoreService method serialize.

private byte[] serialize(SecureStoreData data) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try (DataOutputStream dos = new DataOutputStream(bos)) {
        // Writing the metadata
        SecureStoreMetadata meta = data.getMetadata();
        dos.writeUTF(meta.getName());
        dos.writeBoolean(meta.getDescription() != null);
        if (meta.getDescription() != null) {
            dos.writeUTF(meta.getDescription());
        }
        dos.writeLong(meta.getLastModifiedTime());
        Map<String, String> properties = meta.getProperties();
        dos.writeInt(properties.size());
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            dos.writeUTF(entry.getKey());
            dos.writeUTF(entry.getValue());
        }
        byte[] secret = data.get();
        dos.writeInt(secret.length);
        dos.write(secret);
    }
    return bos.toByteArray();
}
Also used : SecureStoreMetadata(io.cdap.cdap.api.security.store.SecureStoreMetadata) DataOutputStream(java.io.DataOutputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) HashMap(java.util.HashMap) Map(java.util.Map)

Example 5 with SecureStoreMetadata

use of io.cdap.cdap.api.security.store.SecureStoreMetadata in project cdap by caskdata.

the class FileSecureStoreService method list.

/**
 * List of all the entries in the secure store belonging to the specified namespace. No filtering or authentication
 * is done here.
 * @return A list of {@link SecureStoreMetadata} objects representing the data stored in the store.
 * @param namespace The namespace this key belongs to.
 * @throws NamespaceNotFoundException If the specified namespace does not exist.
 * @throws IOException If there was a problem reading from the keystore.
 */
@Override
public List<SecureStoreMetadata> list(String namespace) throws Exception {
    checkNamespaceExists(namespace);
    readLock.lock();
    try {
        Enumeration<String> aliases = keyStore.aliases();
        List<SecureStoreMetadata> metadataList = new ArrayList<>();
        String prefix = namespace + NAME_SEPARATOR;
        while (aliases.hasMoreElements()) {
            String alias = aliases.nextElement();
            // Filter out elements not in this namespace.
            if (alias.startsWith(prefix)) {
                metadataList.add(getSecureStoreMetadata(alias));
            }
        }
        return metadataList;
    } catch (KeyStoreException e) {
        throw new IOException("Failed to get the list of elements from the secure store.", e);
    } finally {
        readLock.unlock();
    }
}
Also used : SecureStoreMetadata(io.cdap.cdap.api.security.store.SecureStoreMetadata) ArrayList(java.util.ArrayList) KeyStoreException(java.security.KeyStoreException) IOException(java.io.IOException)

Aggregations

SecureStoreMetadata (io.cdap.cdap.api.security.store.SecureStoreMetadata)20 SecureStoreData (io.cdap.cdap.api.security.store.SecureStoreData)9 Test (org.junit.Test)8 HashMap (java.util.HashMap)5 SecureKeyId (io.cdap.cdap.proto.id.SecureKeyId)4 IOException (java.io.IOException)4 HttpResponse (io.cdap.common.http.HttpResponse)3 ArrayList (java.util.ArrayList)3 NamespaceNotFoundException (io.cdap.cdap.common.NamespaceNotFoundException)2 NotFoundException (io.cdap.cdap.common.NotFoundException)2 SecureKeyCreateRequest (io.cdap.cdap.proto.security.SecureKeyCreateRequest)2 SecretMetadata (io.cdap.cdap.securestore.spi.secret.SecretMetadata)2 KeyStoreException (java.security.KeyStoreException)2 Map (java.util.Map)2 KeyProvider (org.apache.hadoop.crypto.key.KeyProvider)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Predicate (com.google.common.base.Predicate)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 TypeToken (com.google.common.reflect.TypeToken)1 AbstractModule (com.google.inject.AbstractModule)1