Fix auth -> authentication in some props in SDK (#2839)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -12,7 +12,7 @@ information. In
|
|||||||
hawkBit [SecurityAutoConfiguration](https://github.com/eclipse-hawkbit/hawkbit/blob/master/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java)
|
hawkBit [SecurityAutoConfiguration](https://github.com/eclipse-hawkbit/hawkbit/blob/master/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java)
|
||||||
is a good starting point for integration.
|
is a good starting point for integration.
|
||||||
|
|
||||||
The default implementation is single user/tenant with basic auth and the logged in user is provided with all
|
The default implementation is single user/tenant with basic authentication and the logged-in user is provided with all
|
||||||
permissions. Additionally, the application properties may be configured for multiple static users;
|
permissions. Additionally, the application properties may be configured for multiple static users;
|
||||||
see [Multiple Users](#multiple-users) for details.
|
see [Multiple Users](#multiple-users) for details.
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||||||
* hasRole([role]) Returns true if the current principal has the specified role.
|
* hasRole([role]) Returns true if the current principal has the specified role.
|
||||||
* hasAnyRole([role1,role2]) Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings)
|
* hasAnyRole([role1,role2]) Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings)
|
||||||
* principal Allows direct access to the principal object representing the current user
|
* principal Allows direct access to the principal object representing the current user
|
||||||
* auth Allows direct access to the current Authentication object obtained from the SecurityContext
|
* authentication Allows direct access to the current Authentication object obtained from the SecurityContext
|
||||||
* permitAll Always evaluates to true
|
* permitAll Always evaluates to true
|
||||||
* denyAll Always evaluates to false
|
* denyAll Always evaluates to false
|
||||||
* isAnonymous() Returns true if the current principal is an anonymous user
|
* isAnonymous() Returns true if the current principal is an anonymous user
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ public class AccessContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// simplified info for the security context keeping just the basic info needed for background execution of
|
// simplified info for the security context keeping just the basic info needed for background execution of
|
||||||
// controller auth is not supported - always is false
|
// controller authentication is not supported - always is false
|
||||||
// only authenticated user is supported
|
// only authenticated user is supported
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
@@ -342,7 +342,6 @@ public class AccessContext {
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private String tenant;
|
private String tenant;
|
||||||
// auditor / username (auth principal name)
|
|
||||||
private String auditor = "n/a"; // default value "n/a" is used only on deserialization if field is missing
|
private String auditor = "n/a"; // default value "n/a" is used only on deserialization if field is missing
|
||||||
@JsonProperty(required = true)
|
@JsonProperty(required = true)
|
||||||
private String[] authorities;
|
private String[] authorities;
|
||||||
@@ -354,7 +353,7 @@ public class AccessContext {
|
|||||||
}
|
}
|
||||||
if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails) {
|
if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails) {
|
||||||
if (tenantAwareDetails.controller()) {
|
if (tenantAwareDetails.controller()) {
|
||||||
throw new IllegalStateException("Controller auth context is not supported");
|
throw new IllegalStateException("Controller authentication context is not supported");
|
||||||
}
|
}
|
||||||
tenant = tenantAwareDetails.tenant();
|
tenant = tenantAwareDetails.tenant();
|
||||||
} else if (authentication.getPrincipal() instanceof TenantAwareUser tenantAwareUser) {
|
} else if (authentication.getPrincipal() instanceof TenantAwareUser tenantAwareUser) {
|
||||||
@@ -362,7 +361,7 @@ public class AccessContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// keep the auditor, ofr audit purposes,
|
// keep the auditor, ofr audit purposes,
|
||||||
// sets principal to the resolved auditor and then deserialized auth will return it as principal
|
// sets principal to the resolved auditor and then deserialized authentication will return it as principal
|
||||||
// since the class is not known to auditor aware - it shall used default - principal as auditor
|
// since the class is not known to auditor aware - it shall used default - principal as auditor
|
||||||
auditor = resolve(authentication);
|
auditor = resolve(authentication);
|
||||||
authorities = authentication.getAuthorities().stream().map(Object::toString).toArray(String[]::new);
|
authorities = authentication.getAuthorities().stream().map(Object::toString).toArray(String[]::new);
|
||||||
@@ -417,7 +416,7 @@ public class AccessContext {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the Spring's {@link Authentication} object which is used within a system security code block and
|
* An implementation of the Spring's {@link Authentication} object which is used within a system security code block and
|
||||||
* wraps the original auth object. The wrapped object contains the necessary {@link SpRole#SYSTEM_ROLE}
|
* wraps the original authentication object. The wrapped object contains the necessary {@link SpRole#SYSTEM_ROLE}
|
||||||
* which is allowed to execute all secured methods.
|
* which is allowed to execute all secured methods.
|
||||||
*/
|
*/
|
||||||
static final class SystemCodeAuthentication implements Authentication {
|
static final class SystemCodeAuthentication implements Authentication {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class Mdc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the auth in the MDC context.
|
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the authentication in the MDC context.
|
||||||
*
|
*
|
||||||
* @param <T> the return type
|
* @param <T> the return type
|
||||||
* @param callable the callable to execute
|
* @param callable the callable to execute
|
||||||
@@ -81,7 +81,7 @@ public class Mdc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the auth in the MDC context.
|
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the authentication in the MDC context.
|
||||||
* Calls the {@link #withAuth(Callable)} method and wraps any catchable exception into a {@link RuntimeException}.
|
* Calls the {@link #withAuth(Callable)} method and wraps any catchable exception into a {@link RuntimeException}.
|
||||||
*
|
*
|
||||||
* @param <T> the return type
|
* @param <T> the return type
|
||||||
@@ -116,7 +116,7 @@ public class Mdc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the auth in the MDC context.
|
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the authentication in the MDC context.
|
||||||
* Calls the {@link #asTenantAsActor(String, String, Callable)} method and wraps any catchable exception into a {@link RuntimeException}.
|
* Calls the {@link #asTenantAsActor(String, String, Callable)} method and wraps any catchable exception into a {@link RuntimeException}.
|
||||||
*
|
*
|
||||||
* @param <T> the return type
|
* @param <T> the return type
|
||||||
|
|||||||
@@ -43,11 +43,11 @@ public class HawkbitSecurityProperties {
|
|||||||
*/
|
*/
|
||||||
private List<String> httpFirewallIgnoredPaths;
|
private List<String> httpFirewallIgnoredPaths;
|
||||||
/**
|
/**
|
||||||
* Basic auth realm, see https://tools.ietf.org/html/rfc2617#page-3 .
|
* Basic authentication realm, see https://tools.ietf.org/html/rfc2617#page-3 .
|
||||||
*/
|
*/
|
||||||
private String basicRealm = "hawkBit";
|
private String basicRealm = "hawkBit";
|
||||||
/**
|
/**
|
||||||
* If to allow http auth when there is OAuth2 auth enabled.
|
* If to allow http authentication when there is OAuth2 authentication enabled.
|
||||||
*/
|
*/
|
||||||
private boolean allowHttpBasicOnOAuthEnabled = false;
|
private boolean allowHttpBasicOnOAuthEnabled = false;
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import java.io.Serializable;
|
|||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An auth details object {@link AbstractAuthenticationToken#getDetails()} which is stored in the
|
* An authentication details object {@link AbstractAuthenticationToken#getDetails()} which is stored in the
|
||||||
* spring security auth token details to transport the principal and tenant in the security context session.
|
* spring security authentication token details to transport the principal and tenant in the security context session.
|
||||||
*/
|
*/
|
||||||
public record TenantAwareAuthenticationDetails(String tenant, boolean controller) implements Serializable {
|
public record TenantAwareAuthenticationDetails(String tenant, boolean controller) implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -27,39 +27,39 @@ class AccessContextAsSystemTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test() {
|
void test() {
|
||||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
|
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||||
"test", "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
"test", "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
||||||
auth.setDetails("string details");
|
authentication.setDetails("string details");
|
||||||
test(auth);
|
test(authentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWithNullPrincipal() {
|
void testWithNullPrincipal() {
|
||||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
|
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||||
null, "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
null, "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
||||||
auth.setDetails("string details");
|
authentication.setDetails("string details");
|
||||||
test(auth);
|
test(authentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWithNullCredentials() {
|
void testWithNullCredentials() {
|
||||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
|
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||||
"test", null, List.of(new SimpleGrantedAuthority("anonymous")));
|
"test", null, List.of(new SimpleGrantedAuthority("anonymous")));
|
||||||
auth.setDetails("string details");
|
authentication.setDetails("string details");
|
||||||
test(auth);
|
test(authentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWitAllNull() {
|
void testWitAllNull() {
|
||||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
|
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||||
null, null, List.of(new SimpleGrantedAuthority("anonymous")));
|
null, null, List.of(new SimpleGrantedAuthority("anonymous")));
|
||||||
auth.setDetails(null);
|
authentication.setDetails(null);
|
||||||
test(auth);
|
test(authentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void test(final UsernamePasswordAuthenticationToken auth) {
|
private static void test(final UsernamePasswordAuthenticationToken authentication) {
|
||||||
final SecurityContext sc = SecurityContextHolder.createEmptyContext();
|
final SecurityContext sc = SecurityContextHolder.createEmptyContext();
|
||||||
sc.setAuthentication(auth);
|
sc.setAuthentication(authentication);
|
||||||
SecurityContextHolder.setContext(sc);
|
SecurityContextHolder.setContext(sc);
|
||||||
asSystemAsTenant("tenant", () -> {
|
asSystemAsTenant("tenant", () -> {
|
||||||
final Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
|
final Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|||||||
public interface Authenticator {
|
public interface Authenticator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the auth mechanism is not enabled for the tenant - it just returns null.
|
* If the authentication mechanism is not enabled for the tenant - it just returns null.
|
||||||
* If the auth mechanism is supported, the filter extracts from the security token the related credentials,
|
* If the authentication mechanism is supported, the filter extracts from the security token the related credentials,
|
||||||
* validate them (do authenticate the caller).
|
* validate them (do authenticate the caller).
|
||||||
* If validation / auth is successful returns an authenticated auth object. Otherwise,
|
* If validation / authentication is successful returns an authenticated authentication object. Otherwise,
|
||||||
* throws BadCredentialsException.
|
* throws BadCredentialsException.
|
||||||
*
|
*
|
||||||
* @param controllerSecurityToken the securityToken
|
* @param controllerSecurityToken the securityToken
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public class DdiSecurityProperties {
|
|||||||
public static class Gatewaytoken {
|
public static class Gatewaytoken {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gateway token based auth enabled.
|
* Gateway token based authentication enabled.
|
||||||
*/
|
*/
|
||||||
private boolean enabled = false;
|
private boolean enabled = false;
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class GatewayTokenAuthenticator extends Authenticator.AbstractAuthenticat
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isEnabled(controllerSecurityToken)) {
|
if (!isEnabled(controllerSecurityToken)) {
|
||||||
log.debug("The gateway token auth is disabled");
|
log.debug("The gateway token authentication is disabled");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class SecurityHeaderAuthenticator extends Authenticator.AbstractAuthentic
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isEnabled(controllerSecurityToken)) {
|
if (!isEnabled(controllerSecurityToken)) {
|
||||||
log.debug("The gateway header auth is disabled");
|
log.debug("The gateway header authentication is disabled");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class SecurityTokenAuthenticator extends Authenticator.AbstractAuthentica
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isEnabled(controllerSecurityToken)) {
|
if (!isEnabled(controllerSecurityToken)) {
|
||||||
log.debug("The target security token auth is disabled");
|
log.debug("The target security token authentication is disabled");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Feature: Unit Tests - Security<br/>
|
* Feature: Unit Tests - Security<br/>
|
||||||
* Story: Gateway token auth
|
* Story: Gateway token authentication
|
||||||
*/
|
*/
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class GatewayTokenAuthenticatorTest {
|
class GatewayTokenAuthenticatorTest {
|
||||||
@@ -54,7 +54,7 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests successful auth with gateway token
|
* Tests successful authentication with gateway token
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithGwToken() {
|
void testWithGwToken() {
|
||||||
@@ -70,7 +70,7 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if gateway token doesn't match, the auth fails
|
* Tests that if gateway token doesn't match, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithBadGwToken() {
|
void testWithBadGwToken() {
|
||||||
@@ -84,7 +84,7 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if gateway token miss, the auth fails
|
* Tests that if gateway token miss, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithoutGwToken() {
|
void testWithoutGwToken() {
|
||||||
@@ -92,7 +92,7 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if disabled, the auth fails
|
* Tests that if disabled, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithGwTokenButDisabled() {
|
void testWithGwTokenButDisabled() {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests successful auth with multiple a single hashes
|
* Tests successful authentication with multiple a single hashes
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithSingleKnownHash() {
|
void testWithSingleKnownHash() {
|
||||||
@@ -79,7 +79,7 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests successful auth with multiple hashes
|
* Tests successful authentication with multiple hashes
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithMultipleKnownHashes() {
|
void testWithMultipleKnownHashes() {
|
||||||
@@ -100,7 +100,7 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if the hash is unknown, the auth fails
|
* Tests that if the hash is unknown, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithUnknownHash() {
|
void testWithUnknownHash() {
|
||||||
@@ -114,7 +114,7 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if CN doesn't match the CN in the security token, the auth fails
|
* Tests that if CN doesn't match the CN in the security token, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithNonMatchingCN() {
|
void testWithNonMatchingCN() {
|
||||||
@@ -126,7 +126,7 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if the hash miss, the auth fails
|
* Tests that if the hash miss, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithoutHash() {
|
void testWithoutHash() {
|
||||||
@@ -134,7 +134,7 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if disabled, the auth fails
|
* Tests that if disabled, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithSingleKnownHashButDisabled() {
|
void testWithSingleKnownHashButDisabled() {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Feature: Unit Tests - Security<br/>
|
* Feature: Unit Tests - Security<br/>
|
||||||
* Story: Gateway token auth
|
* Story: Gateway token authentication
|
||||||
*/
|
*/
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class SecurityTokenAuthenticatorTest {
|
class SecurityTokenAuthenticatorTest {
|
||||||
@@ -57,7 +57,7 @@ class SecurityTokenAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests successful auth with gateway token
|
* Tests successful authentication with gateway token
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithSecToken() {
|
void testWithSecToken() {
|
||||||
@@ -76,7 +76,7 @@ class SecurityTokenAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if gateway token doesn't match, the auth fails
|
* Tests that if gateway token doesn't match, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithBadSecToken() {
|
void testWithBadSecToken() {
|
||||||
@@ -88,7 +88,7 @@ class SecurityTokenAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if gateway token miss, the auth fails
|
* Tests that if gateway token miss, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithoutSecToken() {
|
void testWithoutSecToken() {
|
||||||
@@ -96,7 +96,7 @@ class SecurityTokenAuthenticatorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that if disabled, the auth fails
|
* Tests that if disabled, the authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithSecTokenButDisabled() {
|
void testWithSecTokenButDisabled() {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ server.servlet.encoding.charset=UTF-8
|
|||||||
server.servlet.encoding.enabled=true
|
server.servlet.encoding.enabled=true
|
||||||
server.servlet.encoding.force=true
|
server.servlet.encoding.force=true
|
||||||
|
|
||||||
# DDI auth configuration
|
# DDI authentication configuration
|
||||||
hawkbit.server.ddi.security.authentication.targettoken.enabled=false
|
hawkbit.server.ddi.security.authentication.targettoken.enabled=false
|
||||||
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
|
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ public class DmfApiConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the DMF API receiver queue for auth requests called by 3rd
|
* Create the DMF API receiver queue for authentication requests called by 3rd
|
||||||
* party artifact storages for download authorization by devices.
|
* party artifact storages for download authorization by devices.
|
||||||
*
|
*
|
||||||
* @return the receiver queue
|
* @return the receiver queue
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ import org.springframework.http.ResponseEntity;
|
|||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Api for handling basic auth user validation
|
* Api for handling basic authentication user validation
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("squid:S1609")
|
@SuppressWarnings("squid:S1609")
|
||||||
@Tag(
|
@Tag(
|
||||||
name = "Basic Authentication", description = "API for basic auth user validation.",
|
name = "Basic Authentication", description = "API for basic authentication user validation.",
|
||||||
extensions = @Extension(name = OpenApi.X_HAWKBIT, properties = @ExtensionProperty(name = "order", value = BASIC_AUTH_ORDER)))
|
extensions = @Extension(name = OpenApi.X_HAWKBIT, properties = @ExtensionProperty(name = "order", value = BASIC_AUTH_ORDER)))
|
||||||
// no request mapping specified here to avoid CVE-2021-22044 in Feign client
|
// no request mapping specified here to avoid CVE-2021-22044 in Feign client
|
||||||
public interface MgmtBasicAuthRestApi {
|
public interface MgmtBasicAuthRestApi {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public final class MgmtRestConstants {
|
|||||||
*/
|
*/
|
||||||
public static final String ROLLOUT_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/rollouts";
|
public static final String ROLLOUT_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/rollouts";
|
||||||
/**
|
/**
|
||||||
* The basic auth validation mapping
|
* The basic authentication validation mapping
|
||||||
*/
|
*/
|
||||||
public static final String AUTH_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/userinfo";
|
public static final String AUTH_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/userinfo";
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* REST Resource handling basic auth validation.
|
* REST Resource handling basic authentication validation.
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
public class MgmtBasicAuthResource implements MgmtBasicAuthRestApi {
|
public class MgmtBasicAuthResource implements MgmtBasicAuthRestApi {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import org.springframework.web.context.WebApplicationContext;
|
|||||||
* Test for {@link MgmtBasicAuthResource}.
|
* Test for {@link MgmtBasicAuthResource}.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Feature: Component Tests - Management API<br/>
|
* Feature: Component Tests - Management API<br/>
|
||||||
* Story: Basic auth Userinfo Resource
|
* Story: Basic authentication Userinfo Resource
|
||||||
*/
|
*/
|
||||||
@ActiveProfiles({ "test" })
|
@ActiveProfiles({ "test" })
|
||||||
@ExtendWith({ TestLoggerExtension.class, SharedSqlTestDatabaseExtension.class })
|
@ExtendWith({ TestLoggerExtension.class, SharedSqlTestDatabaseExtension.class })
|
||||||
@@ -80,7 +80,7 @@ class MgmtBasicAuthResourceTest {
|
|||||||
MockMvc defaultMock;
|
MockMvc defaultMock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of userinfo api with basic auth validation
|
* Test of userinfo api with basic authentication validation
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@WithUser(principal = TEST_USER, authorities = {"READ", "WRITE", "DELETE"})
|
@WithUser(principal = TEST_USER, authorities = {"READ", "WRITE", "DELETE"})
|
||||||
@@ -97,7 +97,7 @@ class MgmtBasicAuthResourceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test of userinfo api with invalid basic auth fails
|
* Test of userinfo api with invalid basic authentication fails
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void validateBasicAuthFailsWithInvalidCredentials() throws Exception {
|
void validateBasicAuthFailsWithInvalidCredentials() throws Exception {
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class MgmtSecurityConfiguration {
|
|||||||
final HttpSecurity http,
|
final HttpSecurity http,
|
||||||
@Autowired(required = false) @Qualifier("hawkbitOAuth2ResourceServerCustomizer") final Customizer<OAuth2ResourceServerConfigurer<HttpSecurity>> oauth2ResourceServerCustomizer,
|
@Autowired(required = false) @Qualifier("hawkbitOAuth2ResourceServerCustomizer") final Customizer<OAuth2ResourceServerConfigurer<HttpSecurity>> oauth2ResourceServerCustomizer,
|
||||||
// called just before build of the SecurityFilterChain.
|
// called just before build of the SecurityFilterChain.
|
||||||
// could be used for instance to set auth provider
|
// could be used for instance to set authentication provider
|
||||||
// Note: implementation of the customizer shall always take in account what is the already set by the hawkBit
|
// Note: implementation of the customizer shall always take in account what is the already set by the hawkBit
|
||||||
@Autowired(required = false) @Qualifier("hawkbitHttpSecurityCustomizer") final Customizer<HttpSecurity> httpSecurityCustomizer,
|
@Autowired(required = false) @Qualifier("hawkbitHttpSecurityCustomizer") final Customizer<HttpSecurity> httpSecurityCustomizer,
|
||||||
final SystemManagement systemManagement) throws Exception {
|
final SystemManagement systemManagement) throws Exception {
|
||||||
@@ -120,7 +120,7 @@ public class MgmtSecurityConfiguration {
|
|||||||
.anonymous(AbstractHttpConfigurer::disable)
|
.anonymous(AbstractHttpConfigurer::disable)
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
.addFilterAfter(
|
.addFilterAfter(
|
||||||
// Servlet filter to create metadata after successful auth over RESTful.
|
// Servlet filter to create metadata after successful authentication over RESTful.
|
||||||
(request, response, chain) -> {
|
(request, response, chain) -> {
|
||||||
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
if (authentication != null && authentication.isAuthenticated()) {
|
if (authentication != null && authentication.isAuthenticated()) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ server.servlet.encoding.charset=UTF-8
|
|||||||
server.servlet.encoding.enabled=true
|
server.servlet.encoding.enabled=true
|
||||||
server.servlet.encoding.force=true
|
server.servlet.encoding.force=true
|
||||||
|
|
||||||
# DDI auth configuration
|
# DDI authentication configuration
|
||||||
hawkbit.server.ddi.security.authentication.targettoken.enabled=false
|
hawkbit.server.ddi.security.authentication.targettoken.enabled=false
|
||||||
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
|
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import java.time.Duration;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.repository.exception.InvalidTenantConfigurationKeyException;
|
import org.eclipse.hawkbit.repository.exception.InvalidTenantConfigurationKeyException;
|
||||||
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException;
|
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
@@ -25,6 +26,7 @@ import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
|||||||
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.context.EnvironmentAware;
|
import org.springframework.context.EnvironmentAware;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
@@ -35,8 +37,16 @@ import org.springframework.core.env.Environment;
|
|||||||
*/
|
*/
|
||||||
class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest implements EnvironmentAware {
|
class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest implements EnvironmentAware {
|
||||||
|
|
||||||
|
private TenantConfigurationManagement tenantConfigurationManagement;
|
||||||
private Environment env;
|
private Environment env;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
@Override
|
||||||
|
public void beforeAll() throws Exception {
|
||||||
|
super.beforeAll();
|
||||||
|
tenantConfigurationManagement = tenantConfigurationManagement();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEnvironment(final Environment env) {
|
public void setEnvironment(final Environment env) {
|
||||||
this.env = env;
|
this.env = env;
|
||||||
@@ -51,7 +61,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
assertThat(envPropertyDefault).isNotNull();
|
assertThat(envPropertyDefault).isNotNull();
|
||||||
|
|
||||||
// get the configuration from the system management
|
// get the configuration from the system management
|
||||||
final TenantConfigurationValue<String> defaultConfigValue = tenantConfigurationManagement().getConfigurationValue(
|
final TenantConfigurationValue<String> defaultConfigValue = tenantConfigurationManagement.getConfigurationValue(
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
||||||
|
|
||||||
assertThat(defaultConfigValue.isGlobal()).isTrue();
|
assertThat(defaultConfigValue.isGlobal()).isTrue();
|
||||||
@@ -60,11 +70,11 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
// update the tenant specific configuration, create
|
// update the tenant specific configuration, create
|
||||||
final String newConfigurationValue = "thisIsAnotherTokenName";
|
final String newConfigurationValue = "thisIsAnotherTokenName";
|
||||||
assertThat(newConfigurationValue).isNotEqualTo(defaultConfigValue.getValue());
|
assertThat(newConfigurationValue).isNotEqualTo(defaultConfigValue.getValue());
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(
|
tenantConfigurationManagement.addOrUpdateConfiguration(
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, newConfigurationValue);
|
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, newConfigurationValue);
|
||||||
|
|
||||||
// verify that new configuration value is used
|
// verify that new configuration value is used
|
||||||
final TenantConfigurationValue<String> updatedConfigurationValue = tenantConfigurationManagement()
|
final TenantConfigurationValue<String> updatedConfigurationValue = tenantConfigurationManagement
|
||||||
.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
||||||
|
|
||||||
assertThat(updatedConfigurationValue.isGlobal()).isFalse();
|
assertThat(updatedConfigurationValue.isGlobal()).isFalse();
|
||||||
@@ -73,16 +83,15 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
// update the tenant specific configuration, create
|
// update the tenant specific configuration, create
|
||||||
final String newConfigurationValue2 = "thisIsAnotherTokenName2";
|
final String newConfigurationValue2 = "thisIsAnotherTokenName2";
|
||||||
assertThat(newConfigurationValue2).isNotEqualTo(updatedConfigurationValue.getValue());
|
assertThat(newConfigurationValue2).isNotEqualTo(updatedConfigurationValue.getValue());
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(
|
tenantConfigurationManagement.addOrUpdateConfiguration(
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, newConfigurationValue2);
|
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, newConfigurationValue2);
|
||||||
|
|
||||||
// verify that new configuration value is used
|
// verify that new configuration value is used
|
||||||
final TenantConfigurationValue<String> updatedConfigurationValue2 = tenantConfigurationManagement()
|
final TenantConfigurationValue<String> updatedConfigurationValue2 = tenantConfigurationManagement
|
||||||
.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
||||||
|
|
||||||
assertThat(updatedConfigurationValue2.isGlobal()).isFalse();
|
assertThat(updatedConfigurationValue2.isGlobal()).isFalse();
|
||||||
assertThat(updatedConfigurationValue2.getValue()).isEqualTo(newConfigurationValue2);
|
assertThat(updatedConfigurationValue2.getValue()).isEqualTo(newConfigurationValue2);
|
||||||
// assertThat(tenantConfigurationManagement().getTenantConfigurations()).hasSize(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,12 +104,12 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
final String value2 = "secondValue";
|
final String value2 = "secondValue";
|
||||||
|
|
||||||
// add value first
|
// add value first
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, value1);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, value1);
|
||||||
assertThat(tenantConfigurationManagement().getConfigurationValue(configKey, String.class).getValue()).isEqualTo(value1);
|
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, String.class).getValue()).isEqualTo(value1);
|
||||||
|
|
||||||
// update to value second
|
// update to value second
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, value2);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, value2);
|
||||||
assertThat(tenantConfigurationManagement().getConfigurationValue(configKey, String.class).getValue()).isEqualTo(value2);
|
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, String.class).getValue()).isEqualTo(value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,12 +123,12 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
// add value first
|
// add value first
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configuration);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configuration);
|
||||||
assertThat(tenantConfigurationManagement().getConfigurationValue(
|
assertThat(tenantConfigurationManagement.getConfigurationValue(
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class).getValue())
|
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class).getValue())
|
||||||
.isEqualTo("token_123");
|
.isEqualTo("token_123");
|
||||||
assertThat(
|
assertThat(
|
||||||
tenantConfigurationManagement().getConfigurationValue(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class).getValue())
|
tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class).getValue())
|
||||||
.isTrue();
|
.isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,11 +139,11 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
void storeAndUpdateTenantSpecificConfigurationAsBoolean() {
|
void storeAndUpdateTenantSpecificConfigurationAsBoolean() {
|
||||||
final String configKey = TenantConfigurationKey.AUTHENTICATION_HEADER_ENABLED;
|
final String configKey = TenantConfigurationKey.AUTHENTICATION_HEADER_ENABLED;
|
||||||
final Boolean value1 = true;
|
final Boolean value1 = true;
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, value1);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, value1);
|
||||||
assertThat(tenantConfigurationManagement().getConfigurationValue(configKey, Boolean.class).getValue()).isEqualTo(value1);
|
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, Boolean.class).getValue()).isEqualTo(value1);
|
||||||
final Boolean value2 = false;
|
final Boolean value2 = false;
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, value2);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, value2);
|
||||||
assertThat(tenantConfigurationManagement().getConfigurationValue(configKey, Boolean.class).getValue()).isEqualTo(value2);
|
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, Boolean.class).getValue()).isEqualTo(value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,7 +155,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
final String value1 = "thisIsNotABoolean";
|
final String value1 = "thisIsNotABoolean";
|
||||||
|
|
||||||
// add value as String
|
// add value as String
|
||||||
assertThatThrownBy(() -> tenantConfigurationManagement().addOrUpdateConfiguration(configKey, value1))
|
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, value1))
|
||||||
.as("Should not have worked as value is not a boolean")
|
.as("Should not have worked as value is not a boolean")
|
||||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||||
}
|
}
|
||||||
@@ -163,15 +172,15 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configuration);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configuration);
|
||||||
fail("should not have worked as type is wrong");
|
fail("should not have worked as type is wrong");
|
||||||
} catch (final TenantConfigurationValidatorException e) {
|
} catch (final TenantConfigurationValidatorException e) {
|
||||||
assertThat(
|
assertThat(
|
||||||
tenantConfigurationManagement().getConfigurationValue(
|
tenantConfigurationManagement.getConfigurationValue(
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class).getValue())
|
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class).getValue())
|
||||||
.isNotEqualTo("token_123");
|
.isNotEqualTo("token_123");
|
||||||
assertThat(
|
assertThat(
|
||||||
tenantConfigurationManagement().getConfigurationValue(
|
tenantConfigurationManagement.getConfigurationValue(
|
||||||
TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class).getValue())
|
TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, Boolean.class).getValue())
|
||||||
.isNotEqualTo(true);
|
.isNotEqualTo(true);
|
||||||
}
|
}
|
||||||
@@ -185,22 +194,22 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
final String configKey = TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
|
final String configKey = TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
|
||||||
|
|
||||||
// gateway token does not have default value so no configuration value should be available
|
// gateway token does not have default value so no configuration value should be available
|
||||||
final String defaultConfigValue = tenantConfigurationManagement().getConfigurationValue(configKey, String.class).getValue();
|
final String defaultConfigValue = tenantConfigurationManagement.getConfigurationValue(configKey, String.class).getValue();
|
||||||
assertThat(defaultConfigValue).isEmpty();
|
assertThat(defaultConfigValue).isEmpty();
|
||||||
|
|
||||||
// update the tenant specific configuration
|
// update the tenant specific configuration
|
||||||
final String newConfigurationValue = "thisIsAnotherValueForPolling";
|
final String newConfigurationValue = "thisIsAnotherValueForPolling";
|
||||||
assertThat(newConfigurationValue).isNotEqualTo(defaultConfigValue);
|
assertThat(newConfigurationValue).isNotEqualTo(defaultConfigValue);
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, newConfigurationValue);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, newConfigurationValue);
|
||||||
|
|
||||||
// verify that new configuration value is used
|
// verify that new configuration value is used
|
||||||
final String updatedConfigurationValue = tenantConfigurationManagement().getConfigurationValue(configKey, String.class).getValue();
|
final String updatedConfigurationValue = tenantConfigurationManagement.getConfigurationValue(configKey, String.class).getValue();
|
||||||
assertThat(updatedConfigurationValue).isEqualTo(newConfigurationValue);
|
assertThat(updatedConfigurationValue).isEqualTo(newConfigurationValue);
|
||||||
|
|
||||||
// delete the tenant specific configuration
|
// delete the tenant specific configuration
|
||||||
tenantConfigurationManagement().deleteConfiguration(configKey);
|
tenantConfigurationManagement.deleteConfiguration(configKey);
|
||||||
// ensure that now gateway token is set again, because is deleted and must be empty now
|
// ensure that now gateway token is set again, because is deleted and must be empty now
|
||||||
assertThat(tenantConfigurationManagement().getConfigurationValue(configKey, String.class).getValue()).isEmpty();
|
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, String.class).getValue()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,7 +219,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
void storesIntegerWhenStringIsExpected() {
|
void storesIntegerWhenStringIsExpected() {
|
||||||
final String configKey = TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
|
final String configKey = TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
|
||||||
final Integer wrongDatType = 123;
|
final Integer wrongDatType = 123;
|
||||||
assertThatThrownBy(() -> tenantConfigurationManagement().addOrUpdateConfiguration(configKey, wrongDatType))
|
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDatType))
|
||||||
.as("Should not have worked as integer is not a string")
|
.as("Should not have worked as integer is not a string")
|
||||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||||
}
|
}
|
||||||
@@ -222,7 +231,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
void storesIntegerWhenBooleanIsExpected() {
|
void storesIntegerWhenBooleanIsExpected() {
|
||||||
final String configKey = TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED;
|
final String configKey = TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED;
|
||||||
final Integer wrongDataType = 123;
|
final Integer wrongDataType = 123;
|
||||||
assertThatThrownBy(() -> tenantConfigurationManagement().addOrUpdateConfiguration(configKey, wrongDataType))
|
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDataType))
|
||||||
.as("Should not have worked as integer is not a boolean")
|
.as("Should not have worked as integer is not a boolean")
|
||||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||||
}
|
}
|
||||||
@@ -234,7 +243,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
void storesIntegerWhenPollingIntervalIsExpected() {
|
void storesIntegerWhenPollingIntervalIsExpected() {
|
||||||
final String configKey = TenantConfigurationKey.POLLING_TIME;
|
final String configKey = TenantConfigurationKey.POLLING_TIME;
|
||||||
final Integer wrongDataType = 123;
|
final Integer wrongDataType = 123;
|
||||||
assertThatThrownBy(() -> tenantConfigurationManagement().addOrUpdateConfiguration(configKey, wrongDataType))
|
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDataType))
|
||||||
.as("Should not have worked as integer is not a time field")
|
.as("Should not have worked as integer is not a time field")
|
||||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||||
}
|
}
|
||||||
@@ -246,7 +255,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
void storesWrongFormattedStringAsPollingInterval() {
|
void storesWrongFormattedStringAsPollingInterval() {
|
||||||
final String configKey = TenantConfigurationKey.POLLING_TIME;
|
final String configKey = TenantConfigurationKey.POLLING_TIME;
|
||||||
final String wrongFormatted = "wrongFormatted";
|
final String wrongFormatted = "wrongFormatted";
|
||||||
assertThatThrownBy(() -> tenantConfigurationManagement().addOrUpdateConfiguration(configKey, wrongFormatted))
|
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongFormatted))
|
||||||
.as("should not have worked as string is not a time field")
|
.as("should not have worked as string is not a time field")
|
||||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||||
}
|
}
|
||||||
@@ -259,7 +268,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
final String configKey = TenantConfigurationKey.POLLING_TIME;
|
final String configKey = TenantConfigurationKey.POLLING_TIME;
|
||||||
|
|
||||||
final String tooSmallDuration = DurationHelper.toString(getDurationByTimeValues(0, 0, 1));
|
final String tooSmallDuration = DurationHelper.toString(getDurationByTimeValues(0, 0, 1));
|
||||||
assertThatThrownBy(() -> tenantConfigurationManagement().addOrUpdateConfiguration(configKey, tooSmallDuration))
|
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, tooSmallDuration))
|
||||||
.as("Should not have worked as string has an invalid format")
|
.as("Should not have worked as string has an invalid format")
|
||||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||||
}
|
}
|
||||||
@@ -274,9 +283,9 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
final Duration duration = getDurationByTimeValues(1, 2, 0);
|
final Duration duration = getDurationByTimeValues(1, 2, 0);
|
||||||
assertThat(duration).isEqualTo(Duration.ofHours(1).plusMinutes(2));
|
assertThat(duration).isEqualTo(Duration.ofHours(1).plusMinutes(2));
|
||||||
|
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, DurationHelper.toString(duration));
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, DurationHelper.toString(duration));
|
||||||
|
|
||||||
final String storedDurationString = tenantConfigurationManagement().getConfigurationValue(configKey, String.class).getValue();
|
final String storedDurationString = tenantConfigurationManagement.getConfigurationValue(configKey, String.class).getValue();
|
||||||
assertThat(duration).isEqualTo(DurationHelper.fromString(storedDurationString));
|
assertThat(duration).isEqualTo(DurationHelper.fromString(storedDurationString));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +294,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void requestConfigValueWithWrongType() {
|
void requestConfigValueWithWrongType() {
|
||||||
assertThatThrownBy(() -> tenantConfigurationManagement().getConfigurationValue(
|
assertThatThrownBy(() -> tenantConfigurationManagement.getConfigurationValue(
|
||||||
TenantConfigurationKey.POLLING_TIME, Serializable.class))
|
TenantConfigurationKey.POLLING_TIME, Serializable.class))
|
||||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||||
}
|
}
|
||||||
@@ -319,7 +328,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
@Test
|
@Test
|
||||||
void storeTenantConfigurationWhichIsNotDeclaredThrowsException() {
|
void storeTenantConfigurationWhichIsNotDeclaredThrowsException() {
|
||||||
final String configKeyWhichDoesNotExists = "configKeyWhichDoesNotExists";
|
final String configKeyWhichDoesNotExists = "configKeyWhichDoesNotExists";
|
||||||
assertThatThrownBy(() -> tenantConfigurationManagement().addOrUpdateConfiguration(configKeyWhichDoesNotExists, "value"))
|
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKeyWhichDoesNotExists, "value"))
|
||||||
.as("Expected InvalidTenantConfigurationKeyException for tenant configuration key which is not declared")
|
.as("Expected InvalidTenantConfigurationKeyException for tenant configuration key which is not declared")
|
||||||
.isInstanceOf(InvalidTenantConfigurationKeyException.class);
|
.isInstanceOf(InvalidTenantConfigurationKeyException.class);
|
||||||
}
|
}
|
||||||
@@ -328,16 +337,16 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
void storeTenantConfigNumberValue() {
|
void storeTenantConfigNumberValue() {
|
||||||
final String configKey = TenantConfigurationKey.ACTION_CLEANUP_AUTO_EXPIRY;
|
final String configKey = TenantConfigurationKey.ACTION_CLEANUP_AUTO_EXPIRY;
|
||||||
// set auto cleanup for 1 day in Integer ms
|
// set auto cleanup for 1 day in Integer ms
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, 86400000);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, 86400000);
|
||||||
|
|
||||||
// expect long
|
// expect long
|
||||||
Long autoCleanupDaysInMs = tenantConfigurationManagement().getConfigurationValue(configKey, Long.class).getValue();
|
Long autoCleanupDaysInMs = tenantConfigurationManagement.getConfigurationValue(configKey, Long.class).getValue();
|
||||||
Assertions.assertEquals(86400000, autoCleanupDaysInMs);
|
Assertions.assertEquals(86400000, autoCleanupDaysInMs);
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, 86400000);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, 86400000);
|
||||||
|
|
||||||
// 30 days 2,592,000,000 ms as Long
|
// 30 days 2,592,000,000 ms as Long
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, 2592000000L);
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, 2592000000L);
|
||||||
autoCleanupDaysInMs = tenantConfigurationManagement().getConfigurationValue(configKey, Long.class).getValue();
|
autoCleanupDaysInMs = tenantConfigurationManagement.getConfigurationValue(configKey, Long.class).getValue();
|
||||||
Assertions.assertEquals(2592000000L, autoCleanupDaysInMs);
|
Assertions.assertEquals(2592000000L, autoCleanupDaysInMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +355,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
|||||||
final String configKey = TenantConfigurationKey.ACTION_CLEANUP_AUTO_EXPIRY;
|
final String configKey = TenantConfigurationKey.ACTION_CLEANUP_AUTO_EXPIRY;
|
||||||
// set auto cleanup for 1 day in String ms
|
// set auto cleanup for 1 day in String ms
|
||||||
assertThatThrownBy(() ->
|
assertThatThrownBy(() ->
|
||||||
tenantConfigurationManagement().addOrUpdateConfiguration(configKey, "86400000"))
|
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, "86400000"))
|
||||||
.as("Cannot convert the value 86400000 of type String to the type Long defined by the configuration key.")
|
.as("Cannot convert the value 86400000 of type String to the type Long defined by the configuration key.")
|
||||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import org.springframework.security.web.firewall.StrictHttpFirewall;
|
|||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All configurations related to HawkBit's auth and authorization layer.
|
* All configurations related to HawkBit's authentication and authorization layer.
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class HawkbitClient {
|
|||||||
template.header(AUTHORIZATION, "GatewayToken " + tenant.getGatewayToken());
|
template.header(AUTHORIZATION, "GatewayToken " + tenant.getGatewayToken());
|
||||||
} else if (!ObjectUtils.isEmpty(controller.getSecurityToken())) {
|
} else if (!ObjectUtils.isEmpty(controller.getSecurityToken())) {
|
||||||
template.header(AUTHORIZATION, "TargetToken " + controller.getSecurityToken());
|
template.header(AUTHORIZATION, "TargetToken " + controller.getSecurityToken());
|
||||||
} // else do not send auth, no auth or certificate based
|
} // else do not send authentication, no authentication or certificate based
|
||||||
};
|
};
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
private static final ErrorDecoder DEFAULT_ERROR_DECODER_0 = new ErrorDecoder.Default();
|
private static final ErrorDecoder DEFAULT_ERROR_DECODER_0 = new ErrorDecoder.Default();
|
||||||
@@ -279,7 +279,7 @@ public class HawkbitClient {
|
|||||||
(controller == null ? hawkBitServer.getMgmtUrl() : hawkBitServer.getDdiUrl()) + path).openConnection();
|
(controller == null ? hawkBitServer.getMgmtUrl() : hawkBitServer.getDdiUrl()) + path).openConnection();
|
||||||
conn.setRequestMethod("POST");
|
conn.setRequestMethod("POST");
|
||||||
|
|
||||||
// deal with auth - only from headers1
|
// deal with authentication - only from headers1
|
||||||
final RequestTemplate requestTemplate = new RequestTemplate();
|
final RequestTemplate requestTemplate = new RequestTemplate();
|
||||||
requestInterceptorFn.apply(tenant, controller).apply(requestTemplate);
|
requestInterceptorFn.apply(tenant, controller).apply(requestTemplate);
|
||||||
requestTemplate.headers().forEach((k, v) -> v.forEach(e -> conn.setRequestProperty(k, e)));
|
requestTemplate.headers().forEach((k, v) -> v.forEach(e -> conn.setRequestProperty(k, e)));
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class Tenant {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private String tenantId = "DEFAULT";
|
private String tenantId = "DEFAULT";
|
||||||
|
|
||||||
// basic auth user, to access management api
|
// basic authentication user, to access management api
|
||||||
@Nullable
|
@Nullable
|
||||||
private String username = "admin";
|
private String username = "admin";
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ import org.eclipse.hawkbit.sdk.ca.CA;
|
|||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for auth setup
|
* Helper for authentication setup
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class AuthenticationSetupHelper {
|
public class AuthenticationSetupHelper {
|
||||||
|
|
||||||
private static final String AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY = "auth.gatewaytoken.key";
|
private static final String AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY = "authentication.gatewaytoken.key";
|
||||||
private static final String AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED = "auth.gatewaytoken.enabled";
|
private static final String AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED = "authentication.gatewaytoken.enabled";
|
||||||
private static final String AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED = "auth.targettoken.enabled";
|
private static final String AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED = "authentication.targettoken.enabled";
|
||||||
private static final String AUTHENTICATION_MODE_HEADER_ENABLED = "auth.header.enabled";
|
private static final String AUTHENTICATION_MODE_HEADER_ENABLED = "authentication.header.enabled";
|
||||||
private static final String AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME = "auth.header.authority";
|
private static final String AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME = "authentication.header.authority";
|
||||||
|
|
||||||
private static final Random RND = new SecureRandom();
|
private static final Random RND = new SecureRandom();
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ public class AuthenticationSetupHelper {
|
|||||||
return Base64.getEncoder().encodeToString(rnd);
|
return Base64.getEncoder().encodeToString(rnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets up a certificate auth, if DdiCA is null - generate self signed CA
|
// sets up a certificate authentication, if DdiCA is null - generate self signed CA
|
||||||
public void setupCertificateAuthentication() throws CertificateException {
|
public void setupCertificateAuthentication() throws CertificateException {
|
||||||
final MgmtTenantManagementRestApi mgmtTenantManagementRestApi = hawkbitClient.mgmtService(MgmtTenantManagementRestApi.class, tenant);
|
final MgmtTenantManagementRestApi mgmtTenantManagementRestApi = hawkbitClient.mgmtService(MgmtTenantManagementRestApi.class, tenant);
|
||||||
CA ddiCA = tenant.getDdiCA();
|
CA ddiCA = tenant.getDdiCA();
|
||||||
@@ -80,7 +80,7 @@ public class AuthenticationSetupHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// enables secure token auth
|
// enables secure token authentication
|
||||||
public void setupSecureTokenAuthentication() {
|
public void setupSecureTokenAuthentication() {
|
||||||
final MgmtTenantManagementRestApi mgmtTenantManagementRestApi = hawkbitClient.mgmtService(MgmtTenantManagementRestApi.class, tenant);
|
final MgmtTenantManagementRestApi mgmtTenantManagementRestApi = hawkbitClient.mgmtService(MgmtTenantManagementRestApi.class, tenant);
|
||||||
if (!(Boolean.TRUE.equals(Objects.requireNonNull(mgmtTenantManagementRestApi
|
if (!(Boolean.TRUE.equals(Objects.requireNonNull(mgmtTenantManagementRestApi
|
||||||
@@ -90,7 +90,7 @@ public class AuthenticationSetupHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set gateway token auth (generate and sets gateway token to tenant, if not set up)
|
// set gateway token authentication (generate and sets gateway token to tenant, if not set up)
|
||||||
// return the gateway token
|
// return the gateway token
|
||||||
public void setupGatewayTokenAuthentication() {
|
public void setupGatewayTokenAuthentication() {
|
||||||
String gatewayToken = tenant.getGatewayToken();
|
String gatewayToken = tenant.getGatewayToken();
|
||||||
@@ -112,8 +112,8 @@ public class AuthenticationSetupHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if gateway token is configured then the gateway auth is enabled, so all devices use gateway token auth.
|
// if gateway token is configured then the gateway authentication is enabled, so all devices use gateway token authentication.
|
||||||
// otherwise, target token auth is enabled - then all devices shall be registered and the target token shall be set to the one from
|
// otherwise, target token authentication is enabled - then all devices shall be registered and the target token shall be set to the one from
|
||||||
// the DDI controller instance
|
// the DDI controller instance
|
||||||
public void setupTargetAuthentication() {
|
public void setupTargetAuthentication() {
|
||||||
final String gatewayToken = tenant.getGatewayToken();
|
final String gatewayToken = tenant.getGatewayToken();
|
||||||
|
|||||||
@@ -128,8 +128,8 @@ public class HawkbitUiApp implements AppShellConfigurator {
|
|||||||
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
conn.setRequestMethod("GET");
|
conn.setRequestMethod("GET");
|
||||||
|
|
||||||
final String auth = username + ":" + password;
|
final String authentication = username + ":" + password;
|
||||||
final String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
|
final String encodedAuth = Base64.getEncoder().encodeToString(authentication.getBytes());
|
||||||
conn.setRequestProperty(AUTHORIZATION_HEADER, "Basic " + encodedAuth);
|
conn.setRequestProperty(AUTHORIZATION_HEADER, "Basic " + encodedAuth);
|
||||||
|
|
||||||
return conn.getResponseCode() != 401;
|
return conn.getResponseCode() != 401;
|
||||||
|
|||||||
Reference in New Issue
Block a user