Skip to content

Commit 918876c

Browse files
Add support for authenticating a user with an X.509 cert (#266)
1 parent bf8f11c commit 918876c

38 files changed

+500
-99
lines changed

.github/workflows/plugins-tests.yml

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: enterprise plugins tests workflow
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
esdb_version:
7+
required: true
8+
type: string
9+
10+
jobs:
11+
single_node:
12+
name: Single Node
13+
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
test: [ Plugins ]
18+
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Login to Cloudsmith
22+
uses: docker/login-action@v3
23+
with:
24+
registry: docker.eventstore.com
25+
username: ${{ secrets.CLOUDSMITH_CICD_USER }}
26+
password: ${{ secrets.CLOUDSMITH_CICD_TOKEN }}
27+
28+
- uses: actions/checkout@v3
29+
30+
- name: Set up JDK 8
31+
uses: actions/setup-java@v3
32+
with:
33+
java-version: '8'
34+
distribution: 'temurin'
35+
36+
- name: Setup Gradle
37+
uses: gradle/gradle-build-action@v2
38+
with:
39+
gradle-version: 7.4
40+
41+
- name: Generate certificates
42+
run: |
43+
docker compose --file configure-tls-for-tests.yml up
44+
docker compose --file configure-user-certs-for-tests.yml up
45+
46+
- name: Execute Gradle build
47+
run: ./gradlew ci --tests ${{ matrix.test }}Tests
48+
env:
49+
EVENTSTORE_DOCKER_REGISTRY_ENV: docker.eventstore.com
50+
EVENTSTORE_DOCKER_IMAGE_ENV: eventstore-ee/eventstoredb-commercial
51+
EVENTSTORE_DOCKER_TAG_ENV: ${{ inputs.esdb_version }}
52+
SECURE: true
53+
54+
- uses: actions/upload-artifact@v3
55+
if: failure()
56+
with:
57+
name: esdb_logs.tar.gz
58+
path: db-client-java/esdb_logs.tar.gz
59+
if-no-files-found: error
60+
61+
cluster:
62+
name: Cluster
63+
64+
strategy:
65+
fail-fast: false
66+
matrix:
67+
test: [ Plugins ]
68+
69+
runs-on: ubuntu-latest
70+
steps:
71+
- name: Login to Cloudsmith
72+
uses: docker/login-action@v3
73+
with:
74+
registry: docker.eventstore.com
75+
username: ${{ secrets.CLOUDSMITH_CICD_USER }}
76+
password: ${{ secrets.CLOUDSMITH_CICD_TOKEN }}
77+
78+
- uses: actions/checkout@v3
79+
80+
- name: Enable plugins
81+
run: echo "EventStore__Plugins__UserCertificates__Enabled=true" >> vars.env
82+
83+
- name: Set up cluster with Docker Compose
84+
run: docker compose up -d
85+
env:
86+
CONTAINER_REGISTRY: docker.eventstore.com
87+
CONTAINER_IMAGE: eventstore-ee/eventstoredb-commercial
88+
CONTAINER_IMAGE_VERSION: ${{ inputs.esdb_version }}
89+
90+
- name: Generate user certificates
91+
run: docker compose --file configure-user-certs-for-tests.yml up
92+
93+
- name: Set up JDK 8
94+
uses: actions/setup-java@v3
95+
with:
96+
java-version: '8'
97+
distribution: 'temurin'
98+
99+
- name: Setup Gradle
100+
uses: gradle/gradle-build-action@v2
101+
with:
102+
gradle-version: 7.4
103+
104+
- name: Execute Gradle build
105+
run: ./gradlew ci --tests ${{ matrix.test }}Tests
106+
env:
107+
SECURE: true
108+
CLUSTER: true
109+
110+
- name: Shutdown cluster
111+
run: docker compose down

.github/workflows/pull-requests.yml

+16-1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,19 @@ jobs:
4242

4343
uses: ./.github/workflows/tests.yml
4444
with:
45-
esdb_version: ${{ matrix.version }}
45+
esdb_version: ${{ matrix.version }}
46+
47+
plugins-tests:
48+
needs: build
49+
name: Plugins Tests
50+
51+
strategy:
52+
fail-fast: false
53+
matrix:
54+
version: [24.2.0-jammy]
55+
56+
uses: ./.github/workflows/plugins-tests.yml
57+
with:
58+
esdb_version: ${{ matrix.version }}
59+
60+
secrets: inherit

.github/workflows/tests.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
fail-fast: false
1616
matrix:
17-
test: [Streams, PersistentSubscriptions, Expectations ]
17+
test: [Streams, PersistentSubscriptions, Expectations]
1818

1919
runs-on: ubuntu-latest
2020
steps:
@@ -56,7 +56,7 @@ jobs:
5656
- uses: actions/checkout@v3
5757

5858
- name: Generate certificates
59-
run: docker-compose --file configure-tls-for-tests.yml up
59+
run: docker compose --file configure-tls-for-tests.yml up
6060

6161
- name: Set up JDK 8
6262
uses: actions/setup-java@v3
@@ -94,7 +94,7 @@ jobs:
9494
- uses: actions/checkout@v3
9595

9696
- name: Set up cluster with Docker Compose
97-
run: docker-compose up -d
97+
run: docker compose up -d
9898
env:
9999
CONTAINER_IMAGE_VERSION: ${{ inputs.esdb_version }}
100100

@@ -117,4 +117,4 @@ jobs:
117117
SECURE: true
118118

119119
- name: Shutdown cluster
120-
run: docker-compose down
120+
run: docker compose down

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,5 +171,5 @@ fabric.properties
171171
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
172172
!gradle-wrapper.jar
173173

174-
# Generated certs
174+
# Generated certificates
175175
certs/

configure-tls-for-tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ services:
1010
network_mode: "none"
1111

1212
setup:
13-
image: eventstore/es-gencert-cli:1.0.2
13+
image: ghcr.io/eventstore/es-gencert-cli:1.3.0
1414
entrypoint: bash
1515
user: "1000:1000"
1616
command: >

configure-user-certs-for-tests.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
version: '3.5'
2+
3+
services:
4+
volumes-provisioner:
5+
image: "hasnat/volumes-provisioner"
6+
environment:
7+
PROVISION_DIRECTORIES: "1000:1000:0755:/tmp/certs"
8+
volumes:
9+
- "./certs:/tmp/certs"
10+
network_mode: "none"
11+
12+
setup:
13+
image: ghcr.io/eventstore/es-gencert-cli:1.3.0
14+
entrypoint: bash
15+
user: "1000:1000"
16+
command: >
17+
-c "mkdir -p ./certs && cd /certs
18+
&& es-gencert-cli create-user -username admin
19+
&& es-gencert-cli create-user -username invalid
20+
&& find . -type f -print0 | xargs -0 chmod 666"
21+
container_name: setup
22+
volumes:
23+
- ./certs:/certs
24+
depends_on:
25+
- volumes-provisioner

db-client-java/build.gradle

+18
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ dependencies {
4747
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
4848
implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
4949
implementation 'org.slf4j:slf4j-api:2.0.9'
50+
implementation "org.bouncycastle:bcprov-jdk18on:1.77"
51+
implementation "org.bouncycastle:bcpkix-jdk18on:1.77"
5052

5153
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
5254
testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}"
@@ -78,6 +80,11 @@ tasks.register("generateCertificates", Exec) {
7880
commandLine 'docker', 'compose', '--file', '../configure-tls-for-tests.yml', 'up'
7981
}
8082

83+
tasks.register("generateUserCertificates", Exec) {
84+
description = "Generates X.509 certificates for Plugins tests"
85+
commandLine 'docker', 'compose', '--file', '../configure-user-certs-for-tests.yml', 'up'
86+
}
87+
8188
tasks.register("startDockerCompose", Exec) {
8289
description = "Starts ESDB cluster"
8390
commandLine 'docker', 'compose', '--file', '../docker-compose.yml', 'up', '-d'
@@ -125,6 +132,17 @@ tasks.register("clusterTests", Test) {
125132
}
126133
}
127134

135+
tasks.register("pluginsTests", Test) {
136+
dependsOn generateCertificates
137+
dependsOn generateUserCertificates
138+
139+
environment "SECURE", "true"
140+
141+
useJUnitPlatform {
142+
include("**/PluginsTests.class")
143+
}
144+
}
145+
128146
tasks.register("ci", Test) {
129147
useJUnitPlatform()
130148
}

db-client-java/src/main/java/com/eventstore/dbclient/AbstractCreatePersistentSubscription.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ abstract class AbstractCreatePersistentSubscription<TPos, TSettings extends Pers
1111
private final GrpcClient client;
1212
private final String group;
1313
private final TSettings settings;
14-
private final OptionsBase options;
14+
private final OptionsBase<?> options;
1515
private static final Logger logger = LoggerFactory.getLogger(AbstractCreatePersistentSubscription.class);
1616

1717
public AbstractCreatePersistentSubscription(GrpcClient client, String group,
18-
TSettings settings, OptionsBase options) {
18+
TSettings settings, OptionsBase<?> options) {
1919
this.client = client;
2020
this.group = group;
2121
this.settings = settings;

db-client-java/src/main/java/com/eventstore/dbclient/AbstractRead.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ abstract class AbstractRead implements Publisher<ReadMessage> {
1616
protected static final StreamsOuterClass.ReadReq.Options.Builder defaultReadOptions;
1717

1818
private final GrpcClient client;
19-
private final OptionsBase options;
19+
private final OptionsBase<?> options;
2020

21-
protected AbstractRead(GrpcClient client, OptionsBase options) {
21+
protected AbstractRead(GrpcClient client, OptionsBase<?> options) {
2222
this.client = client;
2323
this.options = options;
2424
}

db-client-java/src/main/java/com/eventstore/dbclient/AbstractRegularSubscription.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ abstract class AbstractRegularSubscription {
2222
protected SubscriptionListener listener;
2323
protected Checkpointer checkpointer = null;
2424
private final GrpcClient client;
25-
private final OptionsBase options;
25+
private final OptionsBase<?> options;
2626

27-
protected AbstractRegularSubscription(GrpcClient client, OptionsBase options) {
27+
protected AbstractRegularSubscription(GrpcClient client, OptionsBase<?> options) {
2828
this.client = client;
2929
this.options = options;
3030
}

db-client-java/src/main/java/com/eventstore/dbclient/AbstractSubscribePersistentSubscription.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
abstract class AbstractSubscribePersistentSubscription {
1616
protected static final Persistent.ReadReq.Options.Builder defaultReadOptions;
17-
private final GrpcClient connection;
17+
private final GrpcClient client;
1818
private final String group;
1919
private final PersistentSubscriptionListener listener;
2020
private final SubscribePersistentSubscriptionOptions options;
@@ -25,10 +25,10 @@ abstract class AbstractSubscribePersistentSubscription {
2525
.setStructured(Shared.Empty.getDefaultInstance()));
2626
}
2727

28-
public AbstractSubscribePersistentSubscription(GrpcClient connection, String group,
28+
public AbstractSubscribePersistentSubscription(GrpcClient client, String group,
2929
SubscribePersistentSubscriptionOptions options,
3030
PersistentSubscriptionListener listener) {
31-
this.connection = connection;
31+
this.client = client;
3232
this.group = group;
3333
this.options = options;
3434
this.listener = listener;
@@ -37,9 +37,9 @@ public AbstractSubscribePersistentSubscription(GrpcClient connection, String gro
3737
protected abstract Persistent.ReadReq.Options.Builder createOptions();
3838

3939
public CompletableFuture<PersistentSubscription> execute() {
40-
return this.connection.runWithArgs(args -> {
40+
return this.client.runWithArgs(args -> {
4141
PersistentSubscriptionsGrpc.PersistentSubscriptionsStub client =
42-
GrpcUtils.configureStub(PersistentSubscriptionsGrpc.newStub(args.getChannel()), this.connection.getSettings(), this.options);
42+
GrpcUtils.configureStub(PersistentSubscriptionsGrpc.newStub(args.getChannel()), this.client.getSettings(), this.options);
4343

4444
final CompletableFuture<PersistentSubscription> result = new CompletableFuture<>();
4545

db-client-java/src/main/java/com/eventstore/dbclient/AbstractUpdatePersistentSubscription.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
import java.util.concurrent.CompletableFuture;
99

1010
abstract class AbstractUpdatePersistentSubscription {
11-
private final GrpcClient connection;
11+
private final GrpcClient client;
1212
private final String group;
1313
private final PersistentSubscriptionSettings settings;
14-
private final OptionsBase options;
14+
private final OptionsBase<?> options;
1515
private static final Logger logger = LoggerFactory.getLogger(AbstractUpdatePersistentSubscription.class);
1616

17-
public AbstractUpdatePersistentSubscription(GrpcClient connection, String group,
18-
PersistentSubscriptionSettings settings, OptionsBase options) {
19-
this.connection = connection;
17+
public AbstractUpdatePersistentSubscription(GrpcClient client, String group,
18+
PersistentSubscriptionSettings settings, OptionsBase<?> options) {
19+
this.client = client;
2020
this.group = group;
2121
this.settings = settings;
2222
this.options = options;
@@ -30,10 +30,10 @@ protected Persistent.UpdateReq.Settings.Builder createSettings() {
3030

3131
@SuppressWarnings("unchecked")
3232
public CompletableFuture execute() {
33-
return this.connection.runWithArgs(args -> {
33+
return this.client.runWithArgs(args -> {
3434
CompletableFuture result = new CompletableFuture();
3535
PersistentSubscriptionsGrpc.PersistentSubscriptionsStub client =
36-
GrpcUtils.configureStub(PersistentSubscriptionsGrpc.newStub(args.getChannel()), this.connection.getSettings(), this.options);
36+
GrpcUtils.configureStub(PersistentSubscriptionsGrpc.newStub(args.getChannel()), this.client.getSettings(), this.options);
3737
Persistent.UpdateReq.Settings.Builder settingsBuilder = createSettings();
3838

3939
settingsBuilder

0 commit comments

Comments
 (0)