Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
injectives committed Mar 5, 2024
1 parent fd8ae13 commit a60f851
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
import org.neo4j.driver.AuthTokenManager;
import org.neo4j.driver.BookmarkManager;
import org.neo4j.driver.ClientCertificateManager;
import org.neo4j.driver.Logging;
import org.neo4j.driver.internal.cluster.RoutingTableRegistry;
import reactor.core.publisher.Mono;
Expand All @@ -54,6 +55,8 @@ public class TestkitState {
private static final String RESULT_NOT_FOUND_MESSAGE = "Could not find result";
private static final String BOOKMARK_MANAGER_NOT_FOUND_MESSAGE = "Could not find bookmark manager";
private static final String AUTH_PROVIDER_NOT_FOUND_MESSAGE = "Could not find authentication provider";
private static final String CLIENT_CERTIFICATE_PROVIDER_NOT_FOUND_MESSAGE =
"Could not find client certificate provider";

private final Map<String, DriverHolder> driverIdToDriverHolder = new HashMap<>();

Expand All @@ -79,6 +82,7 @@ public class TestkitState {
private final Map<String, BookmarkManager> bookmarkManagerIdToBookmarkManager = new HashMap<>();
private final Logging logging;
private final Map<String, AuthTokenManager> authProviderIdToAuthProvider = new HashMap<>();
private final Map<String, ClientCertificateManager> managerIdToClientCertificateManager = new HashMap<>();

@Getter
private final Map<String, Exception> errors = new HashMap<>();
Expand Down Expand Up @@ -260,6 +264,20 @@ public void removeAuthProvider(String id) {
}
}

public void addClientCertificateManager(String id, ClientCertificateManager manager) {
managerIdToClientCertificateManager.put(id, manager);
}

public ClientCertificateManager getClientCertificateManager(String id) {
return get(id, managerIdToClientCertificateManager, CLIENT_CERTIFICATE_PROVIDER_NOT_FOUND_MESSAGE);
}

public void removeClientCertificateManager(String id) {
if (managerIdToClientCertificateManager.remove(id) == null) {
throw new RuntimeException(CLIENT_CERTIFICATE_PROVIDER_NOT_FOUND_MESSAGE);
}
}

private <T> String add(T value, Map<String, T> idToT) {
var id = newId();
idToT.put(id, value);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package neo4j.org.testkit.backend.messages.requests;

import lombok.Getter;
import lombok.Setter;
import neo4j.org.testkit.backend.TestkitState;
import neo4j.org.testkit.backend.messages.responses.ClientCertificateProvider;
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;

@Setter
@Getter
public class ClientCertificateProviderClose extends AbstractBasicTestkitRequest {
private AuthTokenManagerCloseBody data;

@Override
protected TestkitResponse processAndCreateResponse(TestkitState testkitState) {
testkitState.removeClientCertificateManager(data.getId());
return ClientCertificateProvider.builder()
.data(ClientCertificateProvider.ClientCertificateProviderBody.builder()
.id(data.getId())
.build())
.build();
}

@Setter
@Getter
public static class AuthTokenManagerCloseBody {
private String id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package neo4j.org.testkit.backend.messages.requests;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class ClientCertificateProviderCompleted implements TestkitCallbackResult {
private ClientCertificateProviderCompletedBody data;

@Override
public String getCallbackId() {
return data.getRequestId();
}

@Setter
@Getter
public static class ClientCertificateProviderCompletedBody {
private String requestId;
private ClientCertificate clientCertificate;
private boolean hasUpdate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package neo4j.org.testkit.backend.messages.requests;

import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import lombok.Getter;
import lombok.Setter;
import neo4j.org.testkit.backend.TestkitState;
import neo4j.org.testkit.backend.messages.responses.ClientCertificateProvider;
import neo4j.org.testkit.backend.messages.responses.ClientCertificateProviderRequest;
import neo4j.org.testkit.backend.messages.responses.TestkitCallback;
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
import org.neo4j.driver.ClientCertificate;
import org.neo4j.driver.ClientCertificateManager;
import org.neo4j.driver.ClientCertificates;

@Setter
@Getter
public class NewClientCertificateProvider extends AbstractBasicTestkitRequest {
private NewClientCertificateProviderBody data;

@Override
protected TestkitResponse processAndCreateResponse(TestkitState testkitState) {
var id = testkitState.newId();
testkitState.addClientCertificateManager(id, new TestkitClientCertificateManager(id, testkitState));
return ClientCertificateProvider.builder()
.data(ClientCertificateProvider.ClientCertificateProviderBody.builder()
.id(id)
.build())
.build();
}

private record TestkitClientCertificateManager(String id, TestkitState testkitState)
implements ClientCertificateManager {
@Override
public CompletionStage<ClientCertificate> getCertificate() {
var callbackId = testkitState.newId();

var callback = ClientCertificateProviderRequest.builder()
.data(ClientCertificateProviderRequest.ClientCertificateProviderRequestBody.builder()
.clientCertificateProviderId(id)
.build())
.build();

ClientCertificate clientCertificate = null;
var callbackStage = dispatchTestkitCallback(testkitState, callback);
try {
var response = callbackStage.toCompletableFuture().get();
if (response instanceof ClientCertificateProviderCompleted clientCertificateComplete) {
var data = clientCertificateComplete.getData();
var certificateData = data.getClientCertificate().getData();
var hasUpdate = data.isHasUpdate();
clientCertificate = ClientCertificates.of(
Paths.get(certificateData.getCertfile()).toFile(),
Paths.get(certificateData.getKeyfile()).toFile(),
certificateData.getPassword(),
hasUpdate);
}
} catch (Exception e) {
throw new RuntimeException("Unexpected failure during Testkit callback", e);
}
return CompletableFuture.completedStage(clientCertificate);
}

private CompletionStage<TestkitCallbackResult> dispatchTestkitCallback(
TestkitState testkitState, TestkitCallback response) {
var future = new CompletableFuture<TestkitCallbackResult>();
testkitState.getCallbackIdToFuture().put(response.getCallbackId(), future);
testkitState.getResponseWriter().accept(response);
return future;
}
}

@Setter
@Getter
public static class NewClientCertificateProviderBody {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,16 @@ public TestkitResponse process(TestkitState testkitState) {
configBuilder.withNotificationConfig(
toNotificationConfig(data.notificationsMinSeverity, data.notificationsDisabledCategories));
configBuilder.withDriverMetrics();
var clientCertificateManager = Optional.ofNullable(data.getClientCertificate())
.map(ClientCertificate::getData)
.map(certificateData -> ClientCertificates.of(
Paths.get(certificateData.getCertfile()).toFile(),
Paths.get(certificateData.getKeyfile()).toFile(),
certificateData.getPassword(),
true))
.map(ClientCertificateManagers::rotating)
var clientCertificateManager = Optional.ofNullable(data.getClientCertificateProviderId())
.map(testkitState::getClientCertificateManager)
.or(() -> Optional.ofNullable(data.getClientCertificate())
.map(ClientCertificate::getData)
.map(certificateData -> ClientCertificates.of(
Paths.get(certificateData.getCertfile()).toFile(),
Paths.get(certificateData.getKeyfile()).toFile(),
certificateData.getPassword(),
true))
.map(ClientCertificateManagers::rotating))
.orElse(null);
configBuilder.withLogging(testkitState.getLogging());
org.neo4j.driver.Driver driver;
Expand Down Expand Up @@ -309,6 +311,7 @@ public static class NewDriverBody {
private List<String> trustedCertificates;
private Boolean telemetryDisabled;
private ClientCertificate clientCertificate;
private String clientCertificateProviderId;
}

@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@
@JsonSubTypes.Type(FakeTimeTick.class),
@JsonSubTypes.Type(FakeTimeUninstall.class),
@JsonSubTypes.Type(CheckSessionAuthSupport.class),
@JsonSubTypes.Type(VerifyAuthentication.class)
@JsonSubTypes.Type(VerifyAuthentication.class),
@JsonSubTypes.Type(NewClientCertificateProvider.class),
@JsonSubTypes.Type(ClientCertificateProviderCompleted.class),
@JsonSubTypes.Type(ClientCertificateProviderClose.class)
})
public interface TestkitRequest {
TestkitResponse process(TestkitState testkitState);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package neo4j.org.testkit.backend.messages.responses;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ClientCertificateProvider implements TestkitResponse {
private ClientCertificateProviderBody data;

@Override
public String testkitName() {
return "ClientCertificateProvider";
}

@Getter
@Builder
public static class ClientCertificateProviderBody {
private String id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package neo4j.org.testkit.backend.messages.responses;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ClientCertificateProviderRequest implements TestkitCallback {
private ClientCertificateProviderRequestBody data;

@Override
public String getCallbackId() {
return data.getId();
}

@Override
public String testkitName() {
return "ClientCertificateProviderRequest";
}

@Getter
@Builder
public static class ClientCertificateProviderRequestBody {
private String id;
private String clientCertificateProviderId;
}
}

0 comments on commit a60f851

Please sign in to comment.