Skip to content

[DE-69] jwt authentication #421

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

Merged
merged 12 commits into from
Dec 29, 2021
Merged
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
72 changes: 69 additions & 3 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
matrix:
docker-img:
- docker.io/arangodb/arangodb:3.7.15
- docker.io/arangodb/arangodb:3.8.2
- docker.io/arangodb/arangodb:3.8.4
- docker.io/arangodb/arangodb-preview:3.9.0-alpha.1
- docker.io/arangodb/enterprise:3.7.15
- docker.io/arangodb/enterprise:3.8.2
- docker.io/arangodb/enterprise:3.8.4
- docker.io/arangodb/enterprise-preview:3.9.0-alpha.1
topology:
- single
Expand All @@ -38,7 +38,7 @@ jobs:

steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
- name: Set up JDK
uses: actions/setup-java@v2
with:
java-version: ${{matrix.java-version}}
Expand Down Expand Up @@ -74,3 +74,69 @@ jobs:
with:
name: logs.tgz
path: ./logs.tgz

test-jwt:
timeout-minutes: 20
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
docker-img:
- docker.io/arangodb/enterprise:3.8.4
topology:
- single
- cluster
- activefailover
db-ext-names:
- false
java-version:
- 17
user-language:
- en

steps:
- uses: actions/checkout@v2
- name: Set up JDK
uses: actions/setup-java@v2
with:
java-version: ${{matrix.java-version}}
distribution: 'adopt'
- name: Start Database
run: ./docker/start_db.sh
env:
ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }}
STARTER_MODE: ${{matrix.topology}}
DOCKER_IMAGE: ${{matrix.docker-img}}
DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}}
- name: Cache local Maven repository
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven-
- name: Set JWT
run: |
ENDPOINT=$(./docker/find_active_endpoint.sh)
echo "Active endpoint: $ENDPOINT"
JWT=$(curl "http://$ENDPOINT/_db/_system/_open/auth" -X POST -d '{"username":"root","password":"test"}' | jq ".jwt" | xargs)
echo "Setting JWT: $JWT"
sed -i "/arangodb.password/c\arangodb.jwt=$JWT" src/test/resources/arangodb.properties
- name: Info
run: mvn -version
- name: Test
run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}"
- name: Collect docker logs on failure
if: ${{ cancelled() || failure() }}
uses: jwalton/gh-docker-logs@v1
with:
dest: './logs'
- name: Tar logs
if: ${{ cancelled() || failure() }}
run: tar cvzf ./logs.tgz ./logs
- name: Upload logs to GitHub
if: ${{ cancelled() || failure() }}
uses: actions/upload-artifact@master
with:
name: logs.tgz
path: ./logs.tgz
5 changes: 5 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a

## [Unreleased]

- fixed swallowing connection exceptions (#420)
- fixed `stopwords` analyzer (#414)
- set max retries for active failover redirects (#412)
- fixed deserializing `null` value as String (#411)

## [6.14.0] - 2021-10-01

- fixed issues with non-English locales (#407)
Expand Down
13 changes: 13 additions & 0 deletions docker/find_active_endpoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

COORDINATORS=("172.17.0.1:8529" "172.17.0.1:8539" "172.17.0.1:8549")

for a in ${COORDINATORS[*]} ; do
if curl -u root:test --silent --fail "http://$a"; then
echo "$a"
exit 0
fi
done

echo "Could not find any active endpoint!"
exit 1
41 changes: 31 additions & 10 deletions src/main/java/com/arangodb/ArangoDB.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@ public Builder password(final String password) {
return this;
}

/**
* Sets the JWT for the user authentication.
*
* @param jwt token to use (default: {@code null})
* @return {@link ArangoDB.Builder}
*/
public Builder jwt(final String jwt) {
setJwt(jwt);
return this;
}

/**
* If set to {@code true} SSL will be used when connecting to an ArangoDB server.
*
Expand Down Expand Up @@ -217,7 +228,7 @@ public Builder hostnameVerifier(final HostnameVerifier hostnameVerifier) {
*
* @param httpRequestRetryHandler HttpRequestRetryHandler to be used
* @return {@link ArangoDB.Builder}
*
* <p>
* <br /><br />
* NOTE:
* Some ArangoDB HTTP endpoints do not honor RFC-2616 HTTP 1.1 specification in respect to
Expand Down Expand Up @@ -647,12 +658,18 @@ public synchronized ArangoDB build() {
final Collection<Host> hostList = createHostList(max, connectionFactory);
final HostResolver hostResolver = createHostResolver(hostList, max, connectionFactory);
final HostHandler hostHandler = createHostHandler(hostResolver);
hostHandler.setJwt(jwt);

return new ArangoDBImpl(
new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password)
.useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
.connectionTtl(connectionTtl),
new HttpCommunication.Builder(hostHandler), util, protocol, hostResolver, new ArangoContext());
.jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize)
.maxConnections(maxConnections).connectionTtl(connectionTtl),
new HttpCommunication.Builder(hostHandler),
util,
protocol,
hostResolver,
hostHandler,
new ArangoContext());
}

}
Expand All @@ -664,6 +681,14 @@ public synchronized ArangoDB build() {
*/
void shutdown() throws ArangoDBException;

/**
* Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST
* connections are authenticated during the initialization phase.
*
* @param jwt token to use
*/
void updateJwt(String jwt);

/**
* Returns a {@code ArangoDatabase} instance for the {@code _system} database.
*
Expand Down Expand Up @@ -897,10 +922,8 @@ public synchronized ArangoDB build() {
/**
* Returns fatal, error, warning or info log messages from the server's global log.
*
* @param options
* Additional options, can be null
* @param options Additional options, can be null
* @return the log messages
*
* @throws ArangoDBException
* @see <a href= "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API
* Documentation</a>
Expand All @@ -912,10 +935,8 @@ public synchronized ArangoDB build() {
/**
* Returns the server logs
*
* @param options
* Additional options, can be null
* @param options Additional options, can be null
* @return the log messages
*
* @see <a href= "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API
* Documentation</a>
* @since ArangoDB 3.8
Expand Down
55 changes: 27 additions & 28 deletions src/main/java/com/arangodb/async/ArangoDBAsync.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,7 @@
import com.arangodb.async.internal.ArangoDBAsyncImpl;
import com.arangodb.async.internal.velocystream.VstCommunicationAsync;
import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync;
import com.arangodb.entity.ArangoDBVersion;
import com.arangodb.entity.LoadBalancingStrategy;
import com.arangodb.entity.LogEntity;
import com.arangodb.entity.LogEntriesEntity;
import com.arangodb.entity.LogLevelEntity;
import com.arangodb.entity.Permissions;
import com.arangodb.entity.ServerRole;
import com.arangodb.entity.UserEntity;
import com.arangodb.entity.*;
import com.arangodb.internal.ArangoContext;
import com.arangodb.internal.ArangoDefaults;
import com.arangodb.internal.InternalArangoDBBuilder;
Expand All @@ -53,18 +46,7 @@
import com.arangodb.util.ArangoDeserializer;
import com.arangodb.util.ArangoSerialization;
import com.arangodb.util.ArangoSerializer;
import com.arangodb.velocypack.VPack;
import com.arangodb.velocypack.VPackAnnotationFieldFilter;
import com.arangodb.velocypack.VPackAnnotationFieldNaming;
import com.arangodb.velocypack.VPackDeserializer;
import com.arangodb.velocypack.VPackInstanceCreator;
import com.arangodb.velocypack.VPackJsonDeserializer;
import com.arangodb.velocypack.VPackJsonSerializer;
import com.arangodb.velocypack.VPackModule;
import com.arangodb.velocypack.VPackParser;
import com.arangodb.velocypack.VPackParserModule;
import com.arangodb.velocypack.VPackSerializer;
import com.arangodb.velocypack.ValueType;
import com.arangodb.velocypack.*;
import com.arangodb.velocystream.Request;
import com.arangodb.velocystream.Response;

Expand Down Expand Up @@ -92,6 +74,14 @@ public interface ArangoDBAsync extends ArangoSerializationAccessor {

void shutdown() throws ArangoDBException;

/**
* Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST
* connections are authenticated during the initialization phase.
*
* @param jwt token to use
*/
void updateJwt(String jwt);

/**
* Returns a handler of the system database
*
Expand Down Expand Up @@ -281,10 +271,8 @@ public interface ArangoDBAsync extends ArangoSerializationAccessor {
/**
* Returns fatal, error, warning or info log messages from the server's global log.
*
* @param options
* Additional options, can be null
* @param options Additional options, can be null
* @return the log messages
*
* @see <a href= "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API
* Documentation</a>
* @deprecated use {@link #getLogEntries(LogOptions)} instead
Expand All @@ -295,10 +283,8 @@ public interface ArangoDBAsync extends ArangoSerializationAccessor {
/**
* Returns the server logs
*
* @param options
* Additional options, can be null
* @param options Additional options, can be null
* @return the log messages
*
* @see <a href= "https://www.arangodb.com/docs/stable/http/administration-and-monitoring.html#read-global-logs-from-the-server">API
* Documentation</a>
* @since ArangoDB 3.8
Expand Down Expand Up @@ -383,6 +369,17 @@ public Builder password(final String password) {
return this;
}

/**
* Sets the JWT for the user authentication.
*
* @param jwt token to use (default: {@code null})
* @return {@link ArangoDBAsync.Builder}
*/
public Builder jwt(final String jwt) {
setJwt(jwt);
return this;
}

/**
* If set to <code>true</code> SSL will be used when connecting to an ArangoDB server.
*
Expand Down Expand Up @@ -812,18 +809,20 @@ public synchronized ArangoDBAsync build() {
syncBuilder(syncHostHandler),
asyncHostResolver,
syncHostResolver,
asyncHostHandler,
syncHostHandler,
new ArangoContext());
}

private VstCommunicationAsync.Builder asyncBuilder(final HostHandler hostHandler) {
return new VstCommunicationAsync.Builder(hostHandler).timeout(timeout).user(user).password(password)
.useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
.jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
.connectionTtl(connectionTtl);
}

private VstCommunicationSync.Builder syncBuilder(final HostHandler hostHandler) {
return new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password)
.useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
.jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections)
.connectionTtl(connectionTtl);
}

Expand Down
15 changes: 15 additions & 0 deletions src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.arangodb.entity.*;
import com.arangodb.internal.*;
import com.arangodb.internal.net.CommunicationProtocol;
import com.arangodb.internal.net.HostHandler;
import com.arangodb.internal.net.HostResolver;
import com.arangodb.internal.util.ArangoSerializationFactory;
import com.arangodb.internal.util.ArangoSerializationFactory.Serializer;
Expand Down Expand Up @@ -55,13 +56,17 @@ public class ArangoDBAsyncImpl extends InternalArangoDB<ArangoExecutorAsync> imp
private static final Logger LOGGER = LoggerFactory.getLogger(ArangoDBAsyncImpl.class);

private final CommunicationProtocol cp;
private final HostHandler asyncHostHandler;
private final HostHandler syncHostHandler;

public ArangoDBAsyncImpl(
final VstCommunicationAsync.Builder asyncCommBuilder,
final ArangoSerializationFactory util,
final VstCommunicationSync.Builder syncCommBuilder,
final HostResolver asyncHostResolver,
final HostResolver syncHostResolver,
final HostHandler asyncHostHandler,
final HostHandler syncHostHandler,
final ArangoContext context
) {

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

cp = new VstProtocol(cacheCom);
this.asyncHostHandler = asyncHostHandler;
this.syncHostHandler = syncHostHandler;

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

@Override
public void updateJwt(String jwt) {
asyncHostHandler.setJwt(jwt);
syncHostHandler.setJwt(jwt);
cp.setJwt(jwt);
executor.setJwt(jwt);
}

@Override
public ArangoDatabaseAsync db() {
return db(ArangoRequestParam.SYSTEM);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,9 @@ public void disconnect() {
outgoingExecutor.shutdown();
}
}

public void setJwt(String jwt) {
communication.setJwt(jwt);
}

}
Loading