Skip to content

Commit 2ea4b4e

Browse files
authored
[DE-69] jwt authentication (#421)
* changelog upd * JwtAuthTest * update jwt * jwt initial configuration * async test * async jwt initial configuration * made existing tests compatible with jwt from properties file * javadoc upd * CI jwt tests * fixed setting jwt in HostSet * fixed CI activefailover tests * CURLLogger: jwt support
1 parent 6142b59 commit 2ea4b4e

38 files changed

+643
-92
lines changed

Diff for: .github/workflows/maven.yml

+69-3
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ jobs:
2020
matrix:
2121
docker-img:
2222
- docker.io/arangodb/arangodb:3.7.15
23-
- docker.io/arangodb/arangodb:3.8.2
23+
- docker.io/arangodb/arangodb:3.8.4
2424
- docker.io/arangodb/arangodb-preview:3.9.0-alpha.1
2525
- docker.io/arangodb/enterprise:3.7.15
26-
- docker.io/arangodb/enterprise:3.8.2
26+
- docker.io/arangodb/enterprise:3.8.4
2727
- docker.io/arangodb/enterprise-preview:3.9.0-alpha.1
2828
topology:
2929
- single
@@ -38,7 +38,7 @@ jobs:
3838

3939
steps:
4040
- uses: actions/checkout@v2
41-
- name: Set up JDK 1.8
41+
- name: Set up JDK
4242
uses: actions/setup-java@v2
4343
with:
4444
java-version: ${{matrix.java-version}}
@@ -74,3 +74,69 @@ jobs:
7474
with:
7575
name: logs.tgz
7676
path: ./logs.tgz
77+
78+
test-jwt:
79+
timeout-minutes: 20
80+
runs-on: ubuntu-latest
81+
82+
strategy:
83+
fail-fast: false
84+
matrix:
85+
docker-img:
86+
- docker.io/arangodb/enterprise:3.8.4
87+
topology:
88+
- single
89+
- cluster
90+
- activefailover
91+
db-ext-names:
92+
- false
93+
java-version:
94+
- 17
95+
user-language:
96+
- en
97+
98+
steps:
99+
- uses: actions/checkout@v2
100+
- name: Set up JDK
101+
uses: actions/setup-java@v2
102+
with:
103+
java-version: ${{matrix.java-version}}
104+
distribution: 'adopt'
105+
- name: Start Database
106+
run: ./docker/start_db.sh
107+
env:
108+
ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }}
109+
STARTER_MODE: ${{matrix.topology}}
110+
DOCKER_IMAGE: ${{matrix.docker-img}}
111+
DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}}
112+
- name: Cache local Maven repository
113+
uses: actions/cache@v2
114+
with:
115+
path: ~/.m2/repository
116+
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
117+
restore-keys: ${{ runner.os }}-maven-
118+
- name: Set JWT
119+
run: |
120+
ENDPOINT=$(./docker/find_active_endpoint.sh)
121+
echo "Active endpoint: $ENDPOINT"
122+
JWT=$(curl "http://$ENDPOINT/_db/_system/_open/auth" -X POST -d '{"username":"root","password":"test"}' | jq ".jwt" | xargs)
123+
echo "Setting JWT: $JWT"
124+
sed -i "/arangodb.password/c\arangodb.jwt=$JWT" src/test/resources/arangodb.properties
125+
- name: Info
126+
run: mvn -version
127+
- name: Test
128+
run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}"
129+
- name: Collect docker logs on failure
130+
if: ${{ cancelled() || failure() }}
131+
uses: jwalton/gh-docker-logs@v1
132+
with:
133+
dest: './logs'
134+
- name: Tar logs
135+
if: ${{ cancelled() || failure() }}
136+
run: tar cvzf ./logs.tgz ./logs
137+
- name: Upload logs to GitHub
138+
if: ${{ cancelled() || failure() }}
139+
uses: actions/upload-artifact@master
140+
with:
141+
name: logs.tgz
142+
path: ./logs.tgz

Diff for: ChangeLog.md

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
66

77
## [Unreleased]
88

9+
- fixed swallowing connection exceptions (#420)
10+
- fixed `stopwords` analyzer (#414)
11+
- set max retries for active failover redirects (#412)
12+
- fixed deserializing `null` value as String (#411)
13+
914
## [6.14.0] - 2021-10-01
1015

1116
- fixed issues with non-English locales (#407)

Diff for: docker/find_active_endpoint.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
3+
COORDINATORS=("172.17.0.1:8529" "172.17.0.1:8539" "172.17.0.1:8549")
4+
5+
for a in ${COORDINATORS[*]} ; do
6+
if curl -u root:test --silent --fail "http://$a"; then
7+
echo "$a"
8+
exit 0
9+
fi
10+
done
11+
12+
echo "Could not find any active endpoint!"
13+
exit 1

Diff for: src/main/java/com/arangodb/ArangoDB.java

+31-10
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,17 @@ public Builder password(final String password) {
179179
return this;
180180
}
181181

182+
/**
183+
* Sets the JWT for the user authentication.
184+
*
185+
* @param jwt token to use (default: {@code null})
186+
* @return {@link ArangoDB.Builder}
187+
*/
188+
public Builder jwt(final String jwt) {
189+
setJwt(jwt);
190+
return this;
191+
}
192+
182193
/**
183194
* If set to {@code true} SSL will be used when connecting to an ArangoDB server.
184195
*
@@ -217,7 +228,7 @@ public Builder hostnameVerifier(final HostnameVerifier hostnameVerifier) {
217228
*
218229
* @param httpRequestRetryHandler HttpRequestRetryHandler to be used
219230
* @return {@link ArangoDB.Builder}
220-
*
231+
* <p>
221232
* <br /><br />
222233
* NOTE:
223234
* Some ArangoDB HTTP endpoints do not honor RFC-2616 HTTP 1.1 specification in respect to
@@ -647,12 +658,18 @@ public synchronized ArangoDB build() {
647658
final Collection<Host> hostList = createHostList(max, connectionFactory);
648659
final HostResolver hostResolver = createHostResolver(hostList, max, connectionFactory);
649660
final HostHandler hostHandler = createHostHandler(hostResolver);
661+
hostHandler.setJwt(jwt);
650662

651663
return new ArangoDBImpl(
652664
new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password)
653-
.useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
654-
.connectionTtl(connectionTtl),
655-
new HttpCommunication.Builder(hostHandler), util, protocol, hostResolver, new ArangoContext());
665+
.jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize)
666+
.maxConnections(maxConnections).connectionTtl(connectionTtl),
667+
new HttpCommunication.Builder(hostHandler),
668+
util,
669+
protocol,
670+
hostResolver,
671+
hostHandler,
672+
new ArangoContext());
656673
}
657674

658675
}
@@ -664,6 +681,14 @@ public synchronized ArangoDB build() {
664681
*/
665682
void shutdown() throws ArangoDBException;
666683

684+
/**
685+
* Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST
686+
* connections are authenticated during the initialization phase.
687+
*
688+
* @param jwt token to use
689+
*/
690+
void updateJwt(String jwt);
691+
667692
/**
668693
* Returns a {@code ArangoDatabase} instance for the {@code _system} database.
669694
*
@@ -897,10 +922,8 @@ public synchronized ArangoDB build() {
897922
/**
898923
* Returns fatal, error, warning or info log messages from the server's global log.
899924
*
900-
* @param options
901-
* Additional options, can be null
925+
* @param options Additional options, can be null
902926
* @return the log messages
903-
*
904927
* @throws ArangoDBException
905928
* @see <a href= "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API
906929
* Documentation</a>
@@ -912,10 +935,8 @@ public synchronized ArangoDB build() {
912935
/**
913936
* Returns the server logs
914937
*
915-
* @param options
916-
* Additional options, can be null
938+
* @param options Additional options, can be null
917939
* @return the log messages
918-
*
919940
* @see <a href= "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API
920941
* Documentation</a>
921942
* @since ArangoDB 3.8

Diff for: src/main/java/com/arangodb/async/ArangoDBAsync.java

+27-28
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,7 @@
2626
import com.arangodb.async.internal.ArangoDBAsyncImpl;
2727
import com.arangodb.async.internal.velocystream.VstCommunicationAsync;
2828
import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync;
29-
import com.arangodb.entity.ArangoDBVersion;
30-
import com.arangodb.entity.LoadBalancingStrategy;
31-
import com.arangodb.entity.LogEntity;
32-
import com.arangodb.entity.LogEntriesEntity;
33-
import com.arangodb.entity.LogLevelEntity;
34-
import com.arangodb.entity.Permissions;
35-
import com.arangodb.entity.ServerRole;
36-
import com.arangodb.entity.UserEntity;
29+
import com.arangodb.entity.*;
3730
import com.arangodb.internal.ArangoContext;
3831
import com.arangodb.internal.ArangoDefaults;
3932
import com.arangodb.internal.InternalArangoDBBuilder;
@@ -53,18 +46,7 @@
5346
import com.arangodb.util.ArangoDeserializer;
5447
import com.arangodb.util.ArangoSerialization;
5548
import com.arangodb.util.ArangoSerializer;
56-
import com.arangodb.velocypack.VPack;
57-
import com.arangodb.velocypack.VPackAnnotationFieldFilter;
58-
import com.arangodb.velocypack.VPackAnnotationFieldNaming;
59-
import com.arangodb.velocypack.VPackDeserializer;
60-
import com.arangodb.velocypack.VPackInstanceCreator;
61-
import com.arangodb.velocypack.VPackJsonDeserializer;
62-
import com.arangodb.velocypack.VPackJsonSerializer;
63-
import com.arangodb.velocypack.VPackModule;
64-
import com.arangodb.velocypack.VPackParser;
65-
import com.arangodb.velocypack.VPackParserModule;
66-
import com.arangodb.velocypack.VPackSerializer;
67-
import com.arangodb.velocypack.ValueType;
49+
import com.arangodb.velocypack.*;
6850
import com.arangodb.velocystream.Request;
6951
import com.arangodb.velocystream.Response;
7052

@@ -92,6 +74,14 @@ public interface ArangoDBAsync extends ArangoSerializationAccessor {
9274

9375
void shutdown() throws ArangoDBException;
9476

77+
/**
78+
* Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST
79+
* connections are authenticated during the initialization phase.
80+
*
81+
* @param jwt token to use
82+
*/
83+
void updateJwt(String jwt);
84+
9585
/**
9686
* Returns a handler of the system database
9787
*
@@ -281,10 +271,8 @@ public interface ArangoDBAsync extends ArangoSerializationAccessor {
281271
/**
282272
* Returns fatal, error, warning or info log messages from the server's global log.
283273
*
284-
* @param options
285-
* Additional options, can be null
274+
* @param options Additional options, can be null
286275
* @return the log messages
287-
*
288276
* @see <a href= "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API
289277
* Documentation</a>
290278
* @deprecated use {@link #getLogEntries(LogOptions)} instead
@@ -295,10 +283,8 @@ public interface ArangoDBAsync extends ArangoSerializationAccessor {
295283
/**
296284
* Returns the server logs
297285
*
298-
* @param options
299-
* Additional options, can be null
286+
* @param options Additional options, can be null
300287
* @return the log messages
301-
*
302288
* @see <a href= "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API
303289
* Documentation</a>
304290
* @since ArangoDB 3.8
@@ -383,6 +369,17 @@ public Builder password(final String password) {
383369
return this;
384370
}
385371

372+
/**
373+
* Sets the JWT for the user authentication.
374+
*
375+
* @param jwt token to use (default: {@code null})
376+
* @return {@link ArangoDBAsync.Builder}
377+
*/
378+
public Builder jwt(final String jwt) {
379+
setJwt(jwt);
380+
return this;
381+
}
382+
386383
/**
387384
* If set to <code>true</code> SSL will be used when connecting to an ArangoDB server.
388385
*
@@ -812,18 +809,20 @@ public synchronized ArangoDBAsync build() {
812809
syncBuilder(syncHostHandler),
813810
asyncHostResolver,
814811
syncHostResolver,
812+
asyncHostHandler,
813+
syncHostHandler,
815814
new ArangoContext());
816815
}
817816

818817
private VstCommunicationAsync.Builder asyncBuilder(final HostHandler hostHandler) {
819818
return new VstCommunicationAsync.Builder(hostHandler).timeout(timeout).user(user).password(password)
820-
.useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
819+
.jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
821820
.connectionTtl(connectionTtl);
822821
}
823822

824823
private VstCommunicationSync.Builder syncBuilder(final HostHandler hostHandler) {
825824
return new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password)
826-
.useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
825+
.jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
827826
.connectionTtl(connectionTtl);
828827
}
829828

Diff for: src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java

+15
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.arangodb.entity.*;
2828
import com.arangodb.internal.*;
2929
import com.arangodb.internal.net.CommunicationProtocol;
30+
import com.arangodb.internal.net.HostHandler;
3031
import com.arangodb.internal.net.HostResolver;
3132
import com.arangodb.internal.util.ArangoSerializationFactory;
3233
import com.arangodb.internal.util.ArangoSerializationFactory.Serializer;
@@ -55,13 +56,17 @@ public class ArangoDBAsyncImpl extends InternalArangoDB<ArangoExecutorAsync> imp
5556
private static final Logger LOGGER = LoggerFactory.getLogger(ArangoDBAsyncImpl.class);
5657

5758
private final CommunicationProtocol cp;
59+
private final HostHandler asyncHostHandler;
60+
private final HostHandler syncHostHandler;
5861

5962
public ArangoDBAsyncImpl(
6063
final VstCommunicationAsync.Builder asyncCommBuilder,
6164
final ArangoSerializationFactory util,
6265
final VstCommunicationSync.Builder syncCommBuilder,
6366
final HostResolver asyncHostResolver,
6467
final HostResolver syncHostResolver,
68+
final HostHandler asyncHostHandler,
69+
final HostHandler syncHostHandler,
6570
final ArangoContext context
6671
) {
6772

@@ -70,6 +75,8 @@ public ArangoDBAsyncImpl(
7075
final VstCommunication<Response, VstConnectionSync> cacheCom = syncCommBuilder.build(util.get(Serializer.INTERNAL));
7176

7277
cp = new VstProtocol(cacheCom);
78+
this.asyncHostHandler = asyncHostHandler;
79+
this.syncHostHandler = syncHostHandler;
7380

7481
ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, util, new DocumentCache());
7582
asyncHostResolver.init(arangoExecutorSync, util.get(Serializer.INTERNAL));
@@ -95,6 +102,14 @@ public void shutdown() throws ArangoDBException {
95102
}
96103
}
97104

105+
@Override
106+
public void updateJwt(String jwt) {
107+
asyncHostHandler.setJwt(jwt);
108+
syncHostHandler.setJwt(jwt);
109+
cp.setJwt(jwt);
110+
executor.setJwt(jwt);
111+
}
112+
98113
@Override
99114
public ArangoDatabaseAsync db() {
100115
return db(ArangoRequestParam.SYSTEM);

Diff for: src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java

+5
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,9 @@ public void disconnect() {
8080
outgoingExecutor.shutdown();
8181
}
8282
}
83+
84+
public void setJwt(String jwt) {
85+
communication.setJwt(jwt);
86+
}
87+
8388
}

0 commit comments

Comments
 (0)