Skip to content

Commit 24a002f

Browse files
geso02aaronzi
andauthored
Switch Keycloak Integration to NGINX Proxy for Flexible Authentication Setup (#718)
* Update example to use nginx setup instead of keycloak plugin * Uncomment keycloak fixed uri instance to check which test is using it * Fix aas repository registry integration tests * Update keycloak reference for test cases * Update aas environment test * Trigger build * Update submodel service example * Use the real token instead of a mock for testing --------- Co-authored-by: Aaron Zielstorff <aaron.zi@web.de>
1 parent 2f374eb commit 24a002f

28 files changed

Lines changed: 3262 additions & 622 deletions

File tree

basyx.aasenvironment/basyx.aasenvironment-client/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/client/TestAuthorizedConnectedAasEnvironment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public static void cleanUpContext() {
9393

9494
@Before
9595
public void setup() throws IOException {
96-
TokenManager mockTokenManager = new TokenManager("http://localhost:9096/realms/BaSyx/protocol/openid-connect/token", new ClientCredentialAccessTokenProvider(new ClientCredential("workstation-1", "nY0mjyECF60DGzNmQUjL81XurSl8etom")));
96+
TokenManager mockTokenManager = new TokenManager("http://localhost:9098/realms/BaSyx/protocol/openid-connect/token", new ClientCredentialAccessTokenProvider(new ClientCredential("workstation-1", "nY0mjyECF60DGzNmQUjL81XurSl8etom")));
9797

9898
aasEnvironment = new AuthorizedConnectedAasEnvironment(mockTokenManager);
9999
}

basyx.aasenvironment/basyx.aasenvironment-client/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/client/TestAuthorizedConnectedAasManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ public class TestAuthorizedConnectedAasManager extends TestConnectedAasManager {
6363
protected final static String AAS_REGISTRY_BASE_PATH = "http://localhost:8051";
6464
protected final static String SM_REGISTRY_BASE_PATH = "http://localhost:8061";
6565

66-
private final static TokenManager TOKEN_MANAGER = new TokenManager("http://localhost:9096/realms/BaSyx/protocol/openid-connect/token", new ClientCredentialAccessTokenProvider(new ClientCredential("workstation-1", "nY0mjyECF60DGzNmQUjL81XurSl8etom")));
67-
private final static TokenManager TOKEN_MANAGER_REGISTRY = new TokenManager("http://localhost:9097/realms/BaSyx/protocol/openid-connect/token", new ClientCredentialAccessTokenProvider(new ClientCredential("workstation-1", "nY0mjyECF60DGzNmQUjL81XurSl8etom")));
66+
private final static TokenManager TOKEN_MANAGER = new TokenManager("http://localhost:9098/realms/BaSyx/protocol/openid-connect/token", new ClientCredentialAccessTokenProvider(new ClientCredential("workstation-1", "nY0mjyECF60DGzNmQUjL81XurSl8etom")));
67+
private final static TokenManager TOKEN_MANAGER_REGISTRY = new TokenManager("http://localhost/realms/BaSyx/protocol/openid-connect/token", new ClientCredentialAccessTokenProvider(new ClientCredential("workstation-1", "nY0mjyECF60DGzNmQUjL81XurSl8etom")));
6868

6969
private static AuthorizedConnectedAasRepository connectedAasRepository;
7070
private static AuthorizedConnectedSubmodelRepository connectedSmRepository;

basyx.aasenvironment/basyx.aasenvironment-client/src/test/resources/application-authorization.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ basyx.feature.authorization.enabled = true
3737
basyx.feature.authorization.type = rbac
3838
basyx.feature.authorization.jwtBearerTokenProvider = keycloak
3939
basyx.feature.authorization.rbac.file = classpath:rbac_rules.json
40-
spring.security.oauth2.resourceserver.jwt.issuer-uri= http://localhost:9096/realms/BaSyx
40+
spring.security.oauth2.resourceserver.jwt.issuer-uri= http://localhost:9098/realms/BaSyx
4141

4242
####################################################################################
4343
# Operation Delegation

basyx.aasrepository/basyx.aasrepository-client/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/client/internal/AssetAdministrationShellRepositoryApi.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,6 @@ private void addAuthorizationHeaderIfAuthIsEnabled(HttpRequest.Builder localVarR
10891089
try {
10901090
localVarRequestBuilder.header("Authorization", "Bearer " + tokenManager.getAccessToken());
10911091
} catch (IOException e) {
1092-
e.printStackTrace();
10931092
throw new AccessTokenRetrievalException("Unable to request access token");
10941093
}
10951094
}

basyx.aasrepository/basyx.aasrepository-feature-registry-integration/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/registry/integration/AuthorizedAasRepositoryRegistryLinkTest.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,22 @@
2727

2828
import static org.junit.Assert.assertEquals;
2929
import static org.junit.Assert.assertThrows;
30+
3031
import java.io.FileNotFoundException;
3132
import java.io.IOException;
33+
import java.util.List;
3234

3335
import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException;
3436
import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi;
3537
import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor;
3638
import org.eclipse.digitaltwin.basyx.aasregistry.main.client.AuthorizedConnectedAasRegistry;
39+
import org.eclipse.digitaltwin.basyx.client.internal.authorization.AccessTokenProviderFactory;
3740
import org.eclipse.digitaltwin.basyx.client.internal.authorization.TokenManager;
41+
import org.eclipse.digitaltwin.basyx.client.internal.authorization.grant.AccessTokenProvider;
42+
import org.eclipse.digitaltwin.basyx.client.internal.authorization.grant.GrantType;
3843
import org.junit.AfterClass;
3944
import org.junit.BeforeClass;
4045
import org.junit.Test;
41-
import org.mockito.Mockito;
4246
import org.springframework.boot.SpringApplication;
4347
import org.springframework.context.ConfigurableApplicationContext;
4448
import org.springframework.http.HttpStatus;
@@ -51,7 +55,7 @@
5155
public class AuthorizedAasRepositoryRegistryLinkTest extends AasRepositoryRegistryLinkTestSuite {
5256

5357
private static final String AAS_REPO_URL = "http://localhost:8081";
54-
private static final String AAS_REGISTRY_BASE_URL = "http://localhost:8051";
58+
private static final String AAS_REGISTRY_BASE_URL = "http://localhost:8052";
5559
private static ConfigurableApplicationContext appContext;
5660
private static AasRepositoryRegistryLink aasRepositoryRegistryLink;
5761

@@ -70,21 +74,26 @@ public static void tearDown() {
7074
appContext.close();
7175
}
7276

77+
7378
@Test
7479
public void sendUnauthorizedRequest() throws IOException {
75-
TokenManager mockTokenManager = Mockito.mock(TokenManager.class);
76-
77-
Mockito.when(mockTokenManager.getAccessToken()).thenReturn("mockedAccessToken");
80+
String clientId = "workstation-1";
81+
String clientSecret = "nY0mjyECF60DGzNmQUjL81XurSl8etom";
82+
83+
AccessTokenProviderFactory factory = new AccessTokenProviderFactory(GrantType.CLIENT_CREDENTIALS, List.of());
84+
factory.setClientCredentials(clientId, clientSecret);
85+
AccessTokenProvider provider = factory.create();
86+
//issuer will also have the port number and will not match the registry issuer -> 401 invalid token, unauthorized
87+
TokenManager tokenManager = new TokenManager("http://localhost:9098/realms/BaSyx/protocol/openid-connect/token", provider);
7888

79-
RegistryAndDiscoveryInterfaceApi registryApi = new AuthorizedConnectedAasRegistry(AAS_REGISTRY_BASE_URL, mockTokenManager);
89+
RegistryAndDiscoveryInterfaceApi registryApi = new AuthorizedConnectedAasRegistry("http://localhost:8051", tokenManager);
8090

8191
AssetAdministrationShellDescriptor descriptor = new AssetAdministrationShellDescriptor();
8292
descriptor.setIdShort("shortId");
8393

8494
ApiException exception = assertThrows(ApiException.class, () -> {
8595
registryApi.postAssetAdministrationShellDescriptor(descriptor);
8696
});
87-
8897
assertEquals(HttpStatus.UNAUTHORIZED.value(), exception.getCode());
8998
}
9099

basyx.aasrepository/basyx.aasrepository-feature-registry-integration/src/test/resources/application-authregistry.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ basyx.externalurl=http://localhost:8081
3636

3737
# Authorized registry integration
3838
basyx.aasrepository.feature.registryintegration.authorization.enabled=true
39-
basyx.aasrepository.feature.registryintegration.authorization.token-endpoint=http://localhost:9097/realms/BaSyx/protocol/openid-connect/token
39+
basyx.aasrepository.feature.registryintegration.authorization.token-endpoint=http://localhost/realms/BaSyx/protocol/openid-connect/token
4040
basyx.aasrepository.feature.registryintegration.authorization.grant-type = CLIENT_CREDENTIALS
4141
basyx.aasrepository.feature.registryintegration.authorization.client-id=workstation-1
4242
basyx.aasrepository.feature.registryintegration.authorization.client-secret=nY0mjyECF60DGzNmQUjL81XurSl8etom

basyx.submodelrepository/basyx.submodelrepository-feature-registry-integration/src/test/resources/application-authregistry.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ basyx.externalurl=http://localhost:8081
3636

3737
# Authorized registry integration
3838
basyx.submodelrepository.feature.registryintegration.authorization.enabled=true
39-
basyx.submodelrepository.feature.registryintegration.authorization.token-endpoint=http://localhost:9097/realms/BaSyx/protocol/openid-connect/token
39+
basyx.submodelrepository.feature.registryintegration.authorization.token-endpoint=http://localhost/realms/BaSyx/protocol/openid-connect/token
4040
basyx.submodelrepository.feature.registryintegration.authorization.grant-type = CLIENT_CREDENTIALS
4141
basyx.submodelrepository.feature.registryintegration.authorization.client-id=workstation-1
4242
basyx.submodelrepository.feature.registryintegration.authorization.client-secret=nY0mjyECF60DGzNmQUjL81XurSl8etom

basyx.submodelservice/basyx.submodelservice.component/example/auth/application-rbac.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ spring:
1111
oauth2:
1212
resourceserver:
1313
jwt:
14-
issuer-uri: http://keycloak:9102/realms/BaSyx
14+
issuer-uri: http://keycloak.basyx.localhost/realms/BaSyx

basyx.submodelservice/basyx.submodelservice.component/example/docker-compose.yml

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,21 @@ networks:
33
driver: bridge
44

55
services:
6+
7+
# nginx reverse proxy to support dns lookup
8+
nginx-proxy:
9+
image: nginxproxy/nginx-proxy:1.6.0-alpine
10+
container_name: proxy
11+
restart: always
12+
ports:
13+
- "80:80"
14+
volumes:
15+
- /var/run/docker.sock:/tmp/docker.sock:ro
16+
environment:
17+
DEFAULT_HOST: keycloak.basyx.localhost
18+
networks:
19+
- auth
20+
621
submodel-service:
722
image: eclipsebasyx/submodel-service:${REVISION}
823
container_name: submodel-service
@@ -23,12 +38,13 @@ services:
2338
- ./sources/:/application/sources/:ro
2439
- ./jars/HelloWorld.jar:/application/jars/HelloWorld.jar:ro
2540
- ./application-mappings.yml:/application/config/application-mappings.yml/:ro
41+
2642
submodel-service-auth:
2743
image: eclipsebasyx/submodel-service:${REVISION}
2844
container_name: submodel-service-auth
2945
pull_policy: missing
30-
# extra_hosts:
31-
# - "host.docker.internal:host-gateway"
46+
extra_hosts:
47+
- "keycloak.basyx.localhost:host-gateway"
3248
environment:
3349
# add the mounted jar file file:submodel.json or submodel.json
3450
BASYX_SUBMODELSERVICE_SUBMODEL_FILE: submodel.json
@@ -55,24 +71,23 @@ services:
5571
condition: service_completed_successfully
5672

5773
keycloak:
58-
image: test/keycloak-submodel:24.0.4
59-
build:
60-
context: ../../../ci/keycloak
61-
dockerfile: Dockerfile.keycloak
74+
image: keycloak/keycloak:24.0.4
6275
container_name: keycloak
63-
command: ["start-dev", "--import-realm"]
64-
ports:
65-
- 9102:9102
6676
environment:
67-
KC_HTTP_PORT: 9102
68-
KC_HTTP_ENABLED: "true"
69-
KC_HTTPS_ENABLED: "false"
70-
KC_HEALTH_ENABLED: "true"
71-
KC_HOSTNAME: localhost
72-
KC_SPI_INITIALIZER_ISSUER_BASE_URI: http://keycloak:9102
77+
VIRTUAL_HOST: keycloak.basyx.localhost
78+
VIRTUAL_PORT: "8080"
79+
KC_HOSTNAME: keycloak.basyx.localhost
7380
KEYCLOAK_ADMIN: admin
7481
KEYCLOAK_ADMIN_PASSWORD: keycloak-admin
82+
KC_HTTP_ENABLED: "true"
83+
KC_HTTPS_ENABLED: "false"
84+
KC_HEALTH_ENABLED: "true"
7585
KC_IMPORT: /opt/keycloak/data/import/
86+
command: ["start-dev", "--import-realm"]
87+
ports:
88+
- 9097:8080
89+
volumes:
90+
- ./keycloak/realm:/opt/keycloak/data/import
7691
networks:
7792
- auth
7893

@@ -81,7 +96,7 @@ services:
8196
command: >
8297
sh -c "
8398
echo 'Waiting for Keycloak to become ready...';
84-
until curl -sf http://keycloak:9102/health/ready; do
99+
until curl -sf http://keycloak:8080/health/ready; do
85100
sleep 5;
86101
done;
87102
echo 'Keycloak is ready!'"

0 commit comments

Comments
 (0)