Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various updates #18

Closed
wants to merge 15 commits into from
Closed
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
59 changes: 57 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,69 @@ and requires the use of a suitable OAUTH2 server.

## How to use docker

Folder [keycloak](keycloak) contains a keycloak installation to be used in a local development environment
Folder [docker-compose](docker-compose) contains the following services to be used in a local development environment:

### Keycloak

A Keycloak instance accessible via https://localhost/idp/ with the Realm *pid-issuer-realm*.

The Realm *pid-issuer-realm*:

- has user self-registration active with a custom registration page accessible via https://localhost/idp/realms/pid-issuer-realm/account/#/
- defines *eu.europa.ec.eudiw.pid_vc_sd_jwt* scope for requesting PID issuance in SD JWT VC format
- defines *eu.europa.ec.eudiw.pid_mso_mdoc* scope for requesting PID issuance in MSO MDOC format
- defines *wallet-dev* and *pid-issuer-srv* clients
- contains sample user with credentials: tneal / password

Administration console is accessible via https://localhost/idp/admin/ using the credentials admin / password

### PID Issuer

A PID Issuer instance accessible via https://localhost/pid-issuer/

It uses the configured Keycloak instance as an Authorization Server, and PID issuance both *SD JWT VC* and *MSO MDOC*
formats is enabled. Additionally *deferred issuance* is enabled for *SD JWT VC* format.

The issuing country is set to GR (Greece).

### HA Proxy

An HA Proxy instance is also configured. This instance exposes both Keyclaok and PID Issuer via https. The certificate
and respective private key can be found in [docker-compose/haproxy/certs](docker-compose/haproxy/certs).

### docker compose usage

```shell
cd keycloak
cd docker-compose
docker-compose up -d
```

or

```shell
cd docker-compose
docker compose up -d
```

## Configuration

The PID Issuer application can be configured using the following *environment variables*:

| Environment variable | Description | Default value |
|-----------------------------------------------------------------|---------------------------------------------------------------------------------|--------------------------------------------------------------------------|
| SPRING_PROFILES_ACTIVE | Spring profiles to enable. | None. Enable *insecure* profile to disable SSL certificates verification |
| SPRING_WEBFLUX_BASE_PATH | Context path for the PID issuer application. | / |
| SERVER_PORT | Port for the HTTP listener of the PID Isser application | 8080 |
| SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_ID | Client Id of the OAuth2 client registered in the Authorization Server | N/A |
| SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_SECRET | Client Server of the OAuth2 client registered in the Authorization Server | N/A |
| ISSUER_PUBLIC_URL | URL the PID Issuer application is accessible from. | http://localhost:${SERVER_PORT}/${SPRING_WEBFLUX_BASE_PATH} |
| ISSUER_AUTHORIZATIONSERVER | URL of the Authorization Server | N/A |
| ISSUER_AUTHORIZATIONSERVER_INTROSPECTION | URL of the Token Introspection endpoint of the Authorization Server | N/A |
| ISSUER_AUTHORIZATIONSERVER_USERINFO | URL of the UserInfo endpoint of the Authorization Server | N/A |
| ISSUER_PID_MSO_MDOC_ENABLED | Whether to enable support for PID issuance in *MSO MDOC* format | true |
| ISSUER_PID_SD_JWT_VC_ENABLED | Whether to enable support for PID issuance in *SD JWT VC* format | true |
| ISSUER_PID_SD_JWT_VC_DEFERRED | Whether PID issueance in *SD JWT VC* format should be *deferred* or *immediate* | false (i.e. immediate issuance) |
| ISSUER_PID_ISSUING_COUNTRY | Code of the Country issuing the PID | N/A |

## Endpoints

Expand Down
23 changes: 7 additions & 16 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage
import java.net.URI
import kotlin.jvm.optionals.getOrNull

plugins {
base
Expand Down Expand Up @@ -52,6 +51,9 @@ dependencies {
implementation(libs.bouncy.castle) {
because("To support X509 certificates parsing")
}
implementation("org.springframework.boot:spring-boot-starter-actuator") {
because("To add Actuator's health endpoint")
}
testImplementation(kotlin("test"))
testImplementation(libs.kotlinx.coroutines.test)
testImplementation("org.springframework.boot:spring-boot-starter-test")
Expand All @@ -61,32 +63,25 @@ dependencies {
}

java {
val javaVersion = getVersionFromCatalog("java")
val javaVersion = libs.versions.java.get()
sourceCompatibility = JavaVersion.toVersion(javaVersion)
}

kotlin {

jvmToolchain {
val javaVersion = getVersionFromCatalog("java")
val javaVersion = libs.versions.java.get()
languageVersion.set(JavaLanguageVersion.of(javaVersion))
}
}
fun getVersionFromCatalog(lookup: String): String {
val versionCatalog: VersionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
return versionCatalog
.findVersion(lookup)
.getOrNull()
?.requiredVersion
?: throw GradleException("Version '$lookup' is not specified in the version catalog")
}

tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
freeCompilerArgs += "-Xcontext-receivers"
freeCompilerArgs += "-Xjsr305=strict"
}
}

testing {
suites {
val test by getting(JvmTestSuite::class) {
Expand Down Expand Up @@ -116,7 +111,7 @@ tasks.named<BootBuildImage>("bootBuildImage") {
}

spotless {
val ktlintVersion = getVersionFromCatalog("ktlintVersion")
val ktlintVersion = libs.versions.ktlintVersion.get()
kotlin {
ktlint(ktlintVersion)
licenseHeaderFile("FileHeader.txt")
Expand All @@ -125,7 +120,3 @@ spotless {
ktlint(ktlintVersion)
}
}

// tasks.withType<Test> {
// useJUnitPlatform()
// }
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ services:
- postgres_data:/var/lib/postgresql/data
networks:
- default
ports:
- "0.0.0.0:5432:5432"
healthcheck:
test: "exit 0"
environment:
Expand All @@ -34,7 +32,11 @@ services:
environment:
- KC_PROXY=edge
- KC_HTTP_RELATIVE_PATH=/idp
- KC_HOSTNAME=localhost
- KC_HOSTNAME_STRICT=false
- KC_HOSTNAME_STRICT_BACKCHANNEL=false
- KC_HTTPS_CERTIFICATE_FILE=/etc/ssl/certs/keycloak.tls.crt
- KC_HTTPS_CERTIFICATE_KEY_FILE=/etc/ssl/certs/keycloak.tls.key
- KC_HEALTH_ENABLED=true
- KC_METRICS_ENABLED=true
- KC_DB=postgres
Expand All @@ -56,9 +58,33 @@ services:
postgres:
condition: service_healthy
volumes:
- ./keycloak-extra/health-check.sh:/opt/keycloak/health-check.sh
- ./keycloak-realms/:/opt/keycloak/data/import
- ./keycloak-themes/:/opt/keycloak/themes
- ./keycloak/extra/health-check.sh:/opt/keycloak/health-check.sh
- ./keycloak/realms/:/opt/keycloak/data/import
- ./keycloak/themes/:/opt/keycloak/themes
- ./keycloak/certs/:/etc/ssl/certs/
networks:
- default

pid-issuer:
image: ghcr.io/eu-digital-identity-wallet/eudi-srv-pid-issuer:edge
pull_policy: always
container_name: pid-issuer
depends_on:
keycloak:
condition: service_healthy
environment:
- SPRING_PROFILES_ACTIVE=insecure
- SPRING_WEBFLUX_BASE_PATH=/pid-issuer
- SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_ID=pid-issuer-srv
- SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_SECRET=zIKAV9DIIIaJCzHCVBPlySgU8KgY68U2
- ISSUER_PUBLIC_URL=https://localhost/pid-issuer
- ISSUER_AUTHORIZATIONSERVER=https://localhost/idp/realms/pid-issuer-realm
- ISSUER_AUTHORIZATIONSERVER_INTROSPECTION=https://keycloak:8443/idp/realms/pid-issuer-realm/protocol/openid-connect/token/introspect
- ISSUER_AUTHORIZATIONSERVER_USERINFO=https://keycloak:8443/idp/realms/pid-issuer-realm/protocol/openid-connect/userinfo
- ISSUER_PID_MSO_MDOC_ENABLED=true
- ISSUER_PID_SD_JWT_VC_ENABLED=true
- ISSUER_PID_SD_JWT_VC_DEFERRED=true
- ISSUER_PID_ISSUING_COUNTRY=GR
networks:
- default

Expand All @@ -71,6 +97,8 @@ services:
depends_on:
keycloak:
condition: service_healthy
pid-issuer:
condition: service_started
volumes:
- ./haproxy/haproxy.conf:/usr/local/etc/haproxy/haproxy.cfg
- ./haproxy/certs/:/etc/ssl/certs/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,24 @@ defaults
frontend all_http_frontend
bind 0.0.0.0:80
use_backend keycloak-backend if { path_beg /idp }
use_backend pid-issuer-backend if { path_beg /pid-issuer }

frontend all_https_frontend
bind 0.0.0.0:443 ssl crt /etc/ssl/certs/localhost.tls.pem
use_backend keycloak-backend if { path_beg /idp }
use_backend pid-issuer-backend if { path_beg /pid-issuer }

backend keycloak-backend
balance roundrobin
cookie SERVERUSED insert indirect nocache
option forwarded proto host by by_port for
server server1 keycloak:8080 cookie server1

backend pid-issuer-backend
balance roundrobin
cookie SERVERUSED insert indirect nocache
option forwarded proto host by by_port for
server server1 pid-issuer:8080 cookie server1

backend no-match
http-request deny deny_status 404
28 changes: 28 additions & 0 deletions docker-compose/keycloak/certs/keycloak.tls.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIE2jCCAsKgAwIBAgIEZVdYUDANBgkqhkiG9w0BAQ0FADAgMQswCQYDVQQGEwJH
UjERMA8GA1UEAwwIa2V5Y2xvYWswIBcNMjMxMTE3MTIxMDU2WhgPMjEyMzExMTcx
MjEwNTZaMCAxCzAJBgNVBAYTAkdSMREwDwYDVQQDDAhrZXljbG9hazCCAiIwDQYJ
KoZIhvcNAQEBBQADggIPADCCAgoCggIBAOJj3CZsu1Lyx5Vgnb7xTSmT12nsPBWu
1aLELGMgKlaMlzteQHczvuEchyhswy2Slu+SK69v+fIMx/gETPlRA3dv25s6niRg
kARdOLKVWtNbfe73xlLzxs53o6tGYu3B3IqcEQ6rrY0290xv106yFFKjtuXrIjCK
xRq4feRc1iYxw50eQlGTH1JFDI/hTSrs0y5vChahYL3aJmKRoYdf/yFtc3md6bCG
AEnAa0d8bMiMgPFw97i4IMrRImpd2f9/Cf7f5UkmghUcQ2+EdpI6LfQwRqw6WcmM
PJiayEYBHfapvS7HJTw9WeLANoQ9SUe5kpA5oL0fAIzSmHNMl3XhNM59wmdAeweu
jjGSEYqs5+8mmvvxP0ORtQVeJjjSPJdBfWDVgd+8Zp9LfEOChA8eavQjMpv1Q/fW
LuwAOq4kdKGWv6aFcu+FvCADQ/kNhTU96StzjVyeNycGn4uxQBpWHSMR4zbb3d5r
B2vQ9EYrnTu6WqUT28hoAaCJ+dhBZ/n2Ph/FTMpNPKZPqN2MRQD3NkMJ0NVSqgzX
Kom5NRrCfjOW2wsNy2CTUkzy9kBzWTV6rWoZ1O79P48XRDApCCGxwg34ehjtdbv/
2CG7A6jV45bJwaAdMQoliJiNOfBMQ22KMVY5/fkyzAj7zuJV1iLo/umq76+7ziQF
f2ZFGcU8N/pLAgMBAAGjGjAYMBYGA1UdEQEB/wQMMAqCCGtleWNsb2FrMA0GCSqG
SIb3DQEBDQUAA4ICAQA0ahabnZfv8+w/fi48HoypFzhDtHnKrd8P73n1nGgJ3/Ld
WG/9LE3xVXdAQzeqAXkpiGZ+KCzJVtT2QJFJmI48tmbxpSRH6LI4UY6OgsmhqADV
M3/HVx+Qkc2JQHrzPESJwOsXtfxmI/pwN3oVyO5Sp5IMvcJ0Cg7gWfeBtcYkJC91
+AQBuwKvH7PxI0q/OvK52SR0vvMeZD14qhWARLHFkGQ/VMS2eSIMTS9mTHY9+pRx
4JwyUu/j5G8jH6KGM3laiJpoPGY1cQlvYL25bNIyLoThDbBKt5O6CUvEgrFHvtLk
u2WSCg+ErZnSYGndcydwEzqU6yFAVDEyqwSl3AJ+CVqxCOYEirhKHrl5MoeBitls
drab89+6zOgHFAIC5NLX+PPwVjq0e33wTCMKMMNLPjZk/S4TjjaR4IQmLx7zWxR2
Ua/mlH2HwfjF4Y2v/GawTpfgN19oFds87BB2nAFmL2i3b/+x15RCZb8khrfT8Cpk
LyZusR3o9bQGEuK8yGxROWiXKWgXXmtlDA53/ZXu/m/u1234hJiF/C1jSjSeI4W1
sahCkuXivAxc+h0yK+TftBWMZABTMywlOu89Tocv8Zgr3lYNQEf2MyZrIsyDs3DI
VhIvU8ig0f/Mt62JLoCTD/Dxai4S/iFJ4fOaAZhdCGABzWcOkfvR3BZoPt5yzw==
-----END CERTIFICATE-----
52 changes: 52 additions & 0 deletions docker-compose/keycloak/certs/keycloak.tls.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
R3yen8xSKBIYRzr8AoDtC2GtlXc9TOg=
-----END PRIVATE KEY-----
Loading