use of io.cdap.cdap.api.security.AccessException in project cdap by caskdata.
the class MessagingProgramStatePublisher method publish.
public void publish(Notification.Type notificationType, Map<String, String> properties) {
// ProgramRunId is always required in a notification
Notification programStatusNotification = new Notification(notificationType, properties);
int failureCount = 0;
long startTime = -1L;
boolean done = false;
// This should be refactored into a common class for publishing to TMS with a retry strategy
while (!done) {
try {
messagingService.publish(StoreRequestBuilder.of(topicId).addPayload(GSON.toJson(programStatusNotification)).build());
LOG.trace("Published program status notification: {}", programStatusNotification);
done = true;
} catch (IOException | AccessException e) {
throw Throwables.propagate(e);
} catch (TopicNotFoundException | ServiceUnavailableException e) {
// These exceptions are retry-able due to TMS not completely started
if (startTime < 0) {
startTime = System.currentTimeMillis();
}
long retryMillis = retryStrategy.nextRetry(++failureCount, startTime);
if (retryMillis < 0) {
LOG.error("Failed to publish messages to TMS and exceeded retry limit.", e);
throw Throwables.propagate(e);
}
LOG.debug("Failed to publish messages to TMS due to {}. Will be retried in {} ms.", e.getMessage(), retryMillis);
try {
TimeUnit.MILLISECONDS.sleep(retryMillis);
} catch (InterruptedException e1) {
// Something explicitly stopping this thread. Simply just break and reset the interrupt flag.
LOG.warn("Publishing message to TMS interrupted.");
Thread.currentThread().interrupt();
done = true;
}
}
}
}
use of io.cdap.cdap.api.security.AccessException in project cdap by caskdata.
the class AdminEventPublisher method publishMessage.
private void publishMessage(EntityId entityId, MetadataMessage.Type type, Object payload) {
MetadataMessage message = new MetadataMessage(type, entityId, GSON.toJsonTree(payload));
LOG.trace("Publishing message: {}", message);
try {
Retries.supplyWithRetries(() -> {
try {
messagingContext.getMessagePublisher().publish(NamespaceId.SYSTEM.getNamespace(), topic.getTopic(), GSON.toJson(message));
} catch (TopicNotFoundException | ServiceUnavailableException e) {
throw new RetryableException(e);
} catch (IOException | AccessException e) {
throw Throwables.propagate(e);
}
return null;
}, retryStrategy);
} catch (Exception e) {
throw new RuntimeException(String.format("Failed to publish profile metadata request for entity id %s", entityId), e);
}
}
use of io.cdap.cdap.api.security.AccessException in project cdap by caskdata.
the class ProvisionerNotifier method publish.
private void publish(Map<String, String> properties) {
final StoreRequest storeRequest = StoreRequestBuilder.of(topic).addPayload(GSON.toJson(new Notification(Notification.Type.PROGRAM_STATUS, properties))).build();
Retries.supplyWithRetries(() -> {
try {
messagingService.publish(storeRequest);
} catch (TopicNotFoundException e) {
throw new RetryableException(e);
} catch (IOException | AccessException e) {
throw Throwables.propagate(e);
}
return null;
}, retryStrategy);
}
use of io.cdap.cdap.api.security.AccessException in project cdap by caskdata.
the class ApplicationLifecycleService method createAppDetailsArchive.
/**
* Creates a ZIP archive that contains the {@link ApplicationDetail} for all applications. The archive created will
* contain a directory entry for each of the namespace. Inside each namespace directory, it contains the
* application detail json, the application name as the file name, with {@code ".json"} as the file extension.
* <p/>
* This method requires instance admin permission.
*
* @param zipOut the {@link ZipOutputStream} for writing out the application details
*/
public void createAppDetailsArchive(ZipOutputStream zipOut) throws Exception {
accessEnforcer.enforce(new InstanceId(cConf.get(Constants.INSTANCE_NAME)), authenticationContext.getPrincipal(), StandardPermission.GET);
Set<NamespaceId> namespaces = new HashSet<>();
JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(zipOut, StandardCharsets.UTF_8));
store.scanApplications(batchSize, (appId, appSpec) -> {
// Skip the SYSTEM namespace apps
if (NamespaceId.SYSTEM.equals(appId.getParent())) {
return;
}
try {
ApplicationDetail applicationDetail = enforceApplicationDetailAccess(appId, ApplicationDetail.fromSpec(appSpec, null));
// Add a directory for the namespace
if (namespaces.add(appId.getParent())) {
ZipEntry entry = new ZipEntry(appId.getNamespace() + "/");
zipOut.putNextEntry(entry);
zipOut.closeEntry();
}
ZipEntry entry = new ZipEntry(appId.getNamespace() + "/" + appId.getApplication() + ".json");
zipOut.putNextEntry(entry);
GSON.toJson(applicationDetail, ApplicationDetail.class, jsonWriter);
jsonWriter.flush();
zipOut.closeEntry();
} catch (IOException | AccessException e) {
throw new RuntimeException("Failed to add zip entry for application " + appId, e);
}
});
}
use of io.cdap.cdap.api.security.AccessException in project cdap by caskdata.
the class DefaultUGIProvider method createUGI.
/**
* Resolves the {@link UserGroupInformation} for a given user, performing any keytab localization, if necessary.
*
* @return a {@link UserGroupInformation}, based upon the information configured for a particular user
* @throws IOException if there was any IOException during localization of the keytab
*/
@Override
protected UGIWithPrincipal createUGI(ImpersonationRequest impersonationRequest) throws AccessException {
try {
// Get impersonation keytab and principal from runtime arguments if present
Map<String, String> properties = getRuntimeProperties(impersonationRequest.getEntityId());
if ((properties != null) && (properties.containsKey(SystemArguments.RUNTIME_KEYTAB_PATH)) && (properties.containsKey(SystemArguments.RUNTIME_PRINCIPAL_NAME))) {
String keytab = properties.get(SystemArguments.RUNTIME_KEYTAB_PATH);
String principal = properties.get(SystemArguments.RUNTIME_PRINCIPAL_NAME);
LOG.debug("Using runtime config principal: {}, keytab: {}", principal, keytab);
UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytab);
return new UGIWithPrincipal(principal, ugi);
}
// no need to get a UGI if the current UGI is the one we're requesting; simply return it
String configuredPrincipalShortName = new KerberosName(impersonationRequest.getPrincipal()).getShortName();
if (UserGroupInformation.getCurrentUser().getShortUserName().equals(configuredPrincipalShortName)) {
return new UGIWithPrincipal(impersonationRequest.getPrincipal(), UserGroupInformation.getCurrentUser());
}
String keytab = impersonationRequest.getKeytabURI();
if (keytab == null) {
throw new AccessIOException("Missing keytab file from the impersonation request " + impersonationRequest);
}
URI keytabURI = URI.create(keytab);
boolean isKeytabLocal = keytabURI.getScheme() == null || "file".equals(keytabURI.getScheme());
File localKeytabFile = isKeytabLocal ? new File(keytabURI.getPath()) : localizeKeytab(locationFactory.create(keytabURI));
try {
String expandedPrincipal = SecurityUtil.expandPrincipal(impersonationRequest.getPrincipal());
LOG.debug("Logging in as: principal={}, keytab={}", expandedPrincipal, localKeytabFile);
// if the local keytab file is not readable to ensure that the client gets the same exception in both the modes.
if (!Files.isReadable(localKeytabFile.toPath())) {
throw new AccessIOException(String.format("Keytab file is not a readable file: %s", localKeytabFile));
}
UserGroupInformation loggedInUGI;
try {
loggedInUGI = UserGroupInformation.loginUserFromKeytabAndReturnUGI(expandedPrincipal, localKeytabFile.getAbsolutePath());
} catch (Exception e) {
// not working
throw new AccessException(String.format("Failed to login for principal=%s, keytab=%s. Check that " + "the principal was not deleted and that the keytab is still valid.", expandedPrincipal, keytabURI), e);
}
return new UGIWithPrincipal(impersonationRequest.getPrincipal(), loggedInUGI);
} finally {
if (!isKeytabLocal && !localKeytabFile.delete()) {
LOG.warn("Failed to delete file: {}", localKeytabFile);
}
}
} catch (IOException e) {
throw new AccessIOException(e);
}
}
Aggregations