External ref for actions and status-update events (#830)

* Add feature to listen to rollout status update
* With this feature, extensions can update back the status of a given rollout using an event(containing distributionSetId and targetId).
* In future, AmqpMessageHandlerService can make use of this feature and de-couple its own implementation from performing status update of an action.
* Implement ActionStatusUpdateHandlerService using actionId
* Extend actions to support externalRef
* Update the action status using externalRef.
* Update securityContext to support running a callable under specific authorities.
* Fixing the review comments
* Increase length of externalRef to 128 chars
* Remove actionStatusUpdateEvent and the handler service
* Use 256 chars for externalRef
* Increment the version for migration script
* Another feature had use v1_12_12 in a recent PR. So incrementing the version.
* Create length limit for externalRef and add it to index
* Externalref will be much longer than 256 chars if controllerId is as long as 256 chars
* Adding tests for verifying externalRef in controllerManagement
* Improve test to consider multiple externalRefs
* Fix issue in migration script for mssql server
* Fix documentation

Signed-off-by: Ravindranath Sandeep (INST-IOT/ESW-Imb) <Sandeep.Ravindranath@bosch-si.com>
This commit is contained in:
Sandeep Ravindranath
2019-07-25 09:45:07 +02:00
committed by Stefan Behl
parent e80399bc79
commit fba6cf9787
11 changed files with 196 additions and 0 deletions

View File

@@ -11,12 +11,18 @@ package org.eclipse.hawkbit.security;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
@@ -111,6 +117,42 @@ public class SystemSecurityContext {
}
}
/**
* Runs a given {@link Callable} within a system security context, which has
* the provided {@link GrantedAuthority}s to successfully run the
* {@link Callable}.
*
* The security context will be switched to the a new
* {@link SecurityContext} and back after the callable is called.
*
* @param tenant
* under which the {@link Callable#call()} must be executed.
* @param callable
* to call within the security context
* @return the return value of the {@link Callable#call()} method.
*/
// The callable API throws a Exception and not a specific one
@SuppressWarnings({ "squid:S2221", "squid:S00112" })
public <T> T runAsControllerAsTenant(@NotEmpty final String tenant, @NotNull final Callable<T> callable) {
final SecurityContext oldContext = SecurityContextHolder.getContext();
List<SimpleGrantedAuthority> authorities = Collections
.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS));
try {
return tenantAware.runAsTenant(tenant, () -> {
try {
setCustomSecurityContext(tenant, oldContext.getAuthentication().getPrincipal(), authorities);
return callable.call();
} catch (final Exception e) {
throw new RuntimeException(e);
}
});
} finally {
SecurityContextHolder.setContext(oldContext);
}
}
/**
* @return {@code true} if the current running code is running as system
* code block.
@@ -119,6 +161,16 @@ public class SystemSecurityContext {
return SecurityContextHolder.getContext().getAuthentication() instanceof SystemCodeAuthentication;
}
private void setCustomSecurityContext(final String tenantId, final Object principal,
final Collection<? extends GrantedAuthority> authorities) {
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(
UUID.randomUUID().toString(), principal, authorities);
authenticationToken.setDetails(new TenantAwareAuthenticationDetails(tenantId, true));
final SecurityContextImpl securityContextImpl = new SecurityContextImpl();
securityContextImpl.setAuthentication(authenticationToken);
SecurityContextHolder.setContext(securityContextImpl);
}
private static void setSystemContext(final SecurityContext oldContext) {
final Authentication oldAuthentication = oldContext.getAuthentication();
final SecurityContextImpl securityContextImpl = new SecurityContextImpl();