Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/build-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ jobs:
run: ./deploy/build.sh unused ${BRANCH_NAME}
env:
MDM_ENDPOINT: ${{ secrets.MDM_ENDPOINT }}
MDM_TASK_PASSWORD: ${{ secrets.MDM_TASK_PASSWORD }}
MDM_TASK_USER: ${{ secrets.MDM_TASK_USER }}
FDZ_ISSUER_URI: ${{ secrets.FDZ_ISSUER_URI }}
FDZ_CLIENT_ID: ${{ secrets.FDZ_CLIENT_ID }}
FDZ_CLIENT_SECRET: ${{ secrets.FDZ_CLIENT_SECRET }}
- name: Deploy to AWS
run: ./deploy/deploy.sh unused ${BRANCH_NAME}
env:
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ jobs:
run: ./deploy/build.sh unused ${BRANCH_NAME}
env:
MDM_ENDPOINT: ${{ secrets.MDM_ENDPOINT }}
MDM_TASK_PASSWORD: ${{ secrets.MDM_TASK_PASSWORD }}
MDM_TASK_USER: ${{ secrets.MDM_TASK_USER }}
FDZ_ISSUER_URI: ${{ secrets.FDZ_ISSUER_URI }}
FDZ_CLIENT_ID: ${{ secrets.FDZ_CLIENT_ID }}
FDZ_CLIENT_SECRET: ${{ secrets.FDZ_CLIENT_SECRET }}
- name: Report build status via Slack
uses: act10ns/slack@v1
if: always()
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ Developers need to have at least `maven` and `docker` on their machines. Current
The following environment variables have to be set for running the JUnit test:
```shell
MDM_ENDPOINT=https://dev.metadata.fdz.dzhw.eu
MDM_TASK_USER=taskuser
MDM_TASK_PASSWORD=**** (see s3://metadatamanagement-private/sensitive_variables.tf)
FDZ_ISSUER_URI=**** (Path to Identity Provider)
FDZ_CLIENT_ID=**** (see Identity Provider)
FDZ_CLIENT_SECRET=**** (see s3://metadatamanagement-private/sensitive_variables.tf)
```

The docker image can be build with:
Expand All @@ -21,7 +22,7 @@ mvn -Pdev clean install

If you want to run the task against an [MDM] instance running on your local machine, you can run:
```shell
docker run -it --network=host dzhw/report-task java -jar /app/report-task.jar --task.id=dat-gra2005-ds2$ --task.version=1.2.3 --task.onBehalfOf=dataprovider --task.language=de --task.type=DATA_SET_REPORT --mdm.username=${MDM_TASK_USER} --mdm.password=${MDM_TASK_PASSWORD} --mdm.endpoint=http://127.0.0.1:8080
docker run -it --network=host dzhw/report-task java -jar /app/report-task.jar --task.id=dat-gra2005-ds2$ --task.version=1.2.3 --task.onBehalfOf=dataprovider --task.language=de --task.type=DATA_SET_REPORT --mdm.endpoint=http://127.0.0.1:8080
```

For further configuration options you should get familiar with [Spring Boot @ConfigurationProperties](https://www.baeldung.com/configuration-properties-in-spring-boot) and have a look into `src/main/java/eu/dzhw/fdz/metadatamanagement/tasks/reporttask/config`.
Expand Down
2 changes: 1 addition & 1 deletion bin/run-docker-task.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
# this script gives an example for running the report generation
# in the docker container connecting to localhost
docker run -it --network=host dzhw/report-task java -jar /app/report-task.jar --task.id=dat-gra2005-ds2$ --task.version=1.2.3 --task.onBehalfOf=localuser --task.type=DATASET_REPORT --task.language=de --mdm.username=${MDM_TASK_USER} --mdm.password=${MDM_TASK_PASSWORD} --mdm.endpoint=http://127.0.0.1:8080
docker run -it --network=host dzhw/report-task java -jar /app/report-task.jar --task.id=dat-gra2005-ds2$ --task.version=1.2.3 --task.onBehalfOf=localuser --task.type=DATASET_REPORT --task.language=de --mdm.endpoint=http://127.0.0.1:8080
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,4 @@ public class MdmProperties {
*/
@NotEmpty
private String endpoint;
/**
* The username which this task uses to interact with the API.
*/
@NotEmpty
private String username;
/**
* The password which this task uses to interact with the API.
*/
@NotEmpty
private String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package eu.dzhw.fdz.metadatamanagement.tasks.reporttask.config.oauth2.client;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;

/**
* Configure and create all beans related to Spring Security OAuth2 Client logic.
*/
@Configuration
public class OAuth2ClientConfig {

/**
* The client registration which will be used to attempt to connect to the identity provider
* to get an access token.
*
* @param issuerUri The URI of the identity provider (if necessary, with an additional path)
* @param clientId The ID of the Client which will try to authenticate and authorize against
* the identity provider
* @param clientSecret The secret of the Client which will try to authenticate and authorize
* against the identity provider
* @return All information necessary for Spring Security to attempt to authenticate and authorize
* a user against the identity provider
*/
@Bean
public ClientRegistration dzhwClientRegistration(
@Value("${spring.security.oauth2.client.provider.fdz.issuer-uri}")
final String issuerUri,
@Value("${spring.security.oauth2.client.registration.fdz.client-id}")
final String clientId,
@Value("${spring.security.oauth2.client.registration.fdz.client-secret}")
final String clientSecret
) {
return ClientRegistrations
.fromIssuerLocation(issuerUri)
.registrationId("fdz")
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.clientId(clientId)
.clientSecret(clientSecret)
.build();
}

/**
* A Repository which stores the information needed to authenticate and authorize a client
* against the identity provider.
*
* NOTE: Normally this would be added by Spring Boot, but since report-task does not have
* a servlet this needs to be added manually.
*
* @param fdzClientRegistration information about a client registration
* @return a repository which stores client registration info
*/
@Bean
public ClientRegistrationRepository clientRegistrationRepository(
ClientRegistration fdzClientRegistration
) {
return new InMemoryClientRegistrationRepository(fdzClientRegistration);
}

/**
* A Service which manages OAuth2 authorized clients.
*
* NOTE: Normally this would be added by Spring Boot, but since report-task does not have
* a servlet this needs to be added manually.
*
* @param clientRegistrationRepository the repository which stores client registration info
* @return the service which will handle managing OAuth2 authorized client(s).
*/
@Bean
public OAuth2AuthorizedClientService authorizedClientService(
ClientRegistrationRepository clientRegistrationRepository
) {
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
}

/**
* The OAuth2 Client manager which handles the authentication and authorization attempts
* of a client using stored client registration info.
*
* @param clientRegistrationRepository the repository which stores client registration info
* @param authorizedClientService the service which manages Oauth2 authorized clients
* @return a manager which attempts to use the client registration info to authenticate and/or
* authorize an Oauth2 client.
*/
@Bean
public AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService
) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();

AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(
clientRegistrationRepository,
authorizedClientService
);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

return authorizedClientManager;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.net.URI;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
Expand All @@ -10,6 +11,8 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
Expand Down Expand Up @@ -40,6 +43,8 @@ public class MdmRestClient {

private final FileSystemResource zippedEnglishTemplateDataPackageOverview;

private AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager;

/**
* Create the {@link RestTemplate} from the {@link MdmProperties}.
*
Expand All @@ -48,14 +53,20 @@ public class MdmRestClient {
* @param zippedGermanTemplateDataSetReport The zipped german data set report template folder.
* @param zippedEnglishTemplateDataSetReport The zipped english data set report template folder.
*/
public MdmRestClient(MdmProperties mdmProperties, RestTemplateBuilder templateBuilder,
public MdmRestClient(
@Value("${spring.security.oauth2.client.registration.fdz.client-id}") final String clientId,
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager,
MdmProperties mdmProperties,
RestTemplateBuilder templateBuilder,
FileSystemResource zippedGermanTemplateDataSetReport,
FileSystemResource zippedEnglishTemplateDataSetReport,
FileSystemResource zippedGermanTemplateDataPackageOverview,
FileSystemResource zippedEnglishTemplateDataPackageOverview) {
FileSystemResource zippedEnglishTemplateDataPackageOverview
) {
super();
this.authorizedClientManager = authorizedClientManager;
mdmTemplate = templateBuilder
.basicAuthentication(mdmProperties.getUsername(), mdmProperties.getPassword())
.defaultHeader("Authorization", generateAuthorizationHeaderValue(clientId))
.rootUri(mdmProperties.getEndpoint()).build();
this.zippedGermanTemplateDataSetReport = zippedGermanTemplateDataSetReport;
this.zippedEnglishTemplateDataSetReport = zippedEnglishTemplateDataSetReport;
Expand Down Expand Up @@ -208,4 +219,23 @@ public void postTaskError(String id, String onBehalfOf, String errorMessage, Tas
}
}

private String generateAuthorizationHeaderValue(final String principal) {
var request = OAuth2AuthorizeRequest
.withClientRegistrationId("fdz")
.principal(principal)
.build();

var client = this.authorizedClientManager
.authorize(request);
if (client == null) {
throw new IllegalStateException("Could not obtain OAuth2 client");
}

var token = client.getAccessToken();

return String.format(
"Bearer %s",
token.getTokenValue()
);
}
}
13 changes: 11 additions & 2 deletions src/main/resources/application-cloud.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
spring:
security:
oauth2:
client:
provider:
fdz:
issuer-uri: ${FDZ_ISSUER_URI}
registration:
fdz:
client-id: ${FDZ_CLIENT_ID}
client-secret: ${FDZ_CLIENT_SECRET}
mdm:
endpoint: ${vcap.services.mdm.credentials.endpoint}
username: ${vcap.services.mdm.credentials.username}
password: ${vcap.services.mdm.credentials.password}
14 changes: 12 additions & 2 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
spring:
security:
oauth2:
client:
provider:
fdz:
issuer-uri: ${FDZ_ISSUER_URI}
registration:
fdz:
client-id: ${FDZ_CLIENT_ID}
client-secret: ${FDZ_CLIENT_SECRET}
task:
latex-input-dir: /app/doc
latex-process-working-dir: /app/doc
pdf-report: /app/doc/Main.pdf
latex-process-command: make

mdm:
endpoint: http://localhost:8080
username: aerjaeklrj
password: kajfja
logging:
level:
root: warn
Expand Down
13 changes: 11 additions & 2 deletions src/test/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
spring:
security:
oauth2:
client:
provider:
fdz:
issuer-uri: ${FDZ_ISSUER_URI}
registration:
fdz:
client-id: ${FDZ_CLIENT_ID}
client-secret: ${FDZ_CLIENT_SECRET}
task:
latex-input-dir: target/test-classes/doc
latex-process-working-dir: .
Expand All @@ -10,8 +21,6 @@ task:
type: DATA_SET_REPORT
mdm:
endpoint: ${MDM_ENDPOINT}
username: ${MDM_TASK_USER}
password: ${MDM_TASK_PASSWORD}
logging:
level:
root: warn
Expand Down