use of io.cdap.cdap.proto.id.SecureKeyId 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));
}
};
}
use of io.cdap.cdap.proto.id.SecureKeyId in project cdap by caskdata.
the class DefaultSecureStoreService method get.
/**
* Checks if the user has access to read the secure key and returns the {@link SecureStoreData} associated
* with the key if they do.
*
* @return Data associated with the key if the user has read access.
* @throws NamespaceNotFoundException If the specified namespace does not exist.
* @throws NotFoundException If the key is not found in the store.
* @throws IOException If there was a problem reading from the store.
* @throws UnauthorizedException If the user does not have READ permissions on the secure key.
*/
@Override
public final SecureStoreData get(String namespace, String name) throws Exception {
Principal principal = authenticationContext.getPrincipal();
SecureKeyId secureKeyId = new SecureKeyId(namespace, name);
accessEnforcer.enforce(secureKeyId, principal, StandardPermission.GET);
return secureStoreService.get(namespace, name);
}
use of io.cdap.cdap.proto.id.SecureKeyId in project cdap by caskdata.
the class FileSecureStoreService method delete.
/**
* Deletes the element with the given name. Flushes the keystore after deleting the key from the in memory keystore.
* If the flush fails, we attempt to insert to key back to the in memory store and notify the user that delete failed.
* If the insertion in the key store fails after a flush failure then there would be a discrepancy between the
* in memory store and the file on the disk. This will be remedied the next time a flush happens.
* If another flush does not happen and the system is restarted, the only time that file is read,
* then we will have an extra key in the keystore.
* @param namespace The namespace this key belongs to.
* @param name Name of the element to be deleted.
* @throws NamespaceNotFoundException If the specified namespace does not exist.
* @throws NotFoundException If the key to be deleted is not found.
* @throws IOException If their was a problem during deleting the key from the in memory store
* or if there was a problem persisting the keystore after deleting the element.
*/
@Override
public void delete(String namespace, String name) throws Exception {
checkNamespaceExists(namespace);
String keyName = getKeyName(namespace, name);
Key key = null;
writeLock.lock();
try {
if (!keyStore.containsAlias(keyName)) {
throw new NotFoundException(new SecureKeyId(namespace, name));
}
key = deleteFromStore(keyName, password);
flush();
LOG.debug(String.format("Successfully deleted key %s from namespace %s", name, namespace));
} catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) {
throw new IOException("Failed to delete the key. ", e);
} catch (IOException ioe) {
try {
keyStore.setKeyEntry(keyName, key, password, null);
} catch (KeyStoreException e) {
ioe.addSuppressed(e);
}
throw ioe;
} finally {
writeLock.unlock();
}
}
use of io.cdap.cdap.proto.id.SecureKeyId in project cdap by caskdata.
the class FileSecureStoreService method getSecureStoreMetadata.
/**
* Returns the metadata for the element identified by the given name.
* The name must be of the format namespace + NAME_SEPARATOR + key name.
* @param keyName Name of the element
* @return An object representing the metadata associated with the element
* @throws NotFoundException If the key was not found in the store.
* @throws IOException If there was a problem in getting the key from the store
*/
private SecureStoreMetadata getSecureStoreMetadata(String keyName) throws Exception {
String[] namespaceAndName = keyName.split(NAME_SEPARATOR);
Preconditions.checkArgument(namespaceAndName.length == 2);
String namespace = namespaceAndName[0];
String name = namespaceAndName[1];
readLock.lock();
try {
if (!keyStore.containsAlias(keyName)) {
throw new NotFoundException(new SecureKeyId(namespace, name));
}
Key key = keyStore.getKey(keyName, password);
return deserialize(key.getEncoded()).getMetadata();
} catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {
throw new IOException("Unable to retrieve the metadata for " + name + " in namespace " + namespace, e);
} finally {
readLock.unlock();
}
}
use of io.cdap.cdap.proto.id.SecureKeyId in project cdap by caskdata.
the class SecretManagerSecureStoreService method get.
@Override
public SecureStoreData get(String namespace, String name) throws Exception {
validate(namespace);
try {
Secret secret = secretManager.get(namespace, name);
SecretMetadata metadata = secret.getMetadata();
return new SecureStoreData(new SecureStoreMetadata(metadata.getName(), metadata.getDescription(), metadata.getCreationTimeMs(), metadata.getProperties()), secret.getData());
} catch (SecretNotFoundException e) {
throw new SecureKeyNotFoundException(new SecureKeyId(namespace, name), e);
}
}
Aggregations