diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java b/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java index b13b320b..af7ec0cc 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java @@ -52,7 +52,7 @@ public String getPublicKey(Config.KASInfo kasInfo) { } @Override - public void close() { + public synchronized void close() { var entries = new ArrayList<>(stubs.values()); stubs.clear(); for (var entry: entries) { diff --git a/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java b/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java index 417ef97e..75639ab2 100644 --- a/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java +++ b/sdk/src/main/java/io/opentdf/platform/sdk/SDK.java @@ -1,6 +1,7 @@ package io.opentdf.platform.sdk; import io.grpc.Channel; +import io.grpc.ManagedChannel; import io.opentdf.platform.policy.attributes.AttributesServiceGrpc; import io.opentdf.platform.policy.attributes.AttributesServiceGrpc.AttributesServiceFutureStub; import io.opentdf.platform.policy.namespaces.NamespaceServiceGrpc; @@ -14,29 +15,40 @@ * The SDK class represents a software development kit for interacting with the opentdf platform. It * provides various services and stubs for making API calls to the opentdf platform. */ -public class SDK { +public class SDK implements AutoCloseable { private final Services services; - public interface KAS { + @Override + public void close() throws Exception { + services.close(); + } + + public interface KAS extends AutoCloseable { String getPublicKey(Config.KASInfo kasInfo); byte[] unwrap(Manifest.KeyAccess keyAccess, String policy); } // TODO: add KAS - public interface Services { + public interface Services extends AutoCloseable { AttributesServiceFutureStub attributes(); NamespaceServiceFutureStub namespaces(); SubjectMappingServiceFutureStub subjectMappings(); ResourceMappingServiceFutureStub resourceMappings(); KAS kas(); - static Services newServices(Channel channel, KAS kas) { + static Services newServices(ManagedChannel channel, KAS kas) { var attributeService = AttributesServiceGrpc.newFutureStub(channel); var namespaceService = NamespaceServiceGrpc.newFutureStub(channel); var subjectMappingService = SubjectMappingServiceGrpc.newFutureStub(channel); var resourceMappingService = ResourceMappingServiceGrpc.newFutureStub(channel); return new Services() { + @Override + public void close() throws Exception { + channel.shutdownNow(); + kas.close(); + } + @Override public AttributesServiceFutureStub attributes() { return attributeService; diff --git a/sdk/src/test/java/io/opentdf/platform/sdk/SDKBuilderTest.java b/sdk/src/test/java/io/opentdf/platform/sdk/SDKBuilderTest.java index d5adefec..cf94995c 100644 --- a/sdk/src/test/java/io/opentdf/platform/sdk/SDKBuilderTest.java +++ b/sdk/src/test/java/io/opentdf/platform/sdk/SDKBuilderTest.java @@ -114,6 +114,7 @@ void sdkServicesSetup(boolean useSSL) throws Exception{ Server platformServicesServer = null; Server kasServer = null; + SDK.Services services = null; // we use the HTTP server for two things: // * it returns the OIDC configuration we use at bootstrapping time // * it fakes out being an IDP and returns an access token when need to retrieve an access token @@ -223,7 +224,7 @@ public ServerCall.Listener interceptCall(ServerCall ServerCall.Listener interceptCall(ServerCall