Skip to content

Commit e900df3

Browse files
committed
add some tests
1 parent 98653b9 commit e900df3

9 files changed

Lines changed: 276 additions & 59 deletions

File tree

sdk/src/main/java/io/opentdf/platform/sdk/Autoconfigure.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ List<KeySplitStep> getSplits(List<String> defaultKases, Supplier<String> genSpli
361361
}
362362

363363
logger.warn("no grants or mapped keys found, generating plan from default KASes. this is deprecated");
364+
// this is a little bit weird because we don't take into account the KIDs here. This is the way
365+
// that it works in
364366
return generatePlanFromDefaultKases(defaultKases, genSplitID);
365367
}
366368

sdk/src/main/java/io/opentdf/platform/sdk/Planner.java

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,38 @@
11
package io.opentdf.platform.sdk;
22

3+
import com.connectrpc.ConnectException;
4+
import com.google.gson.Gson;
5+
import com.google.gson.JsonSyntaxException;
6+
import com.google.gson.annotations.SerializedName;
7+
import io.opentdf.platform.policy.Algorithm;
8+
import io.opentdf.platform.policy.SimpleKasKey;
9+
import io.opentdf.platform.policy.SimpleKasPublicKey;
310
import io.opentdf.platform.policy.Value;
11+
import io.opentdf.platform.wellknownconfiguration.GetWellKnownConfigurationRequest;
12+
import io.opentdf.platform.wellknownconfiguration.GetWellKnownConfigurationResponse;
413
import org.slf4j.Logger;
514
import org.slf4j.LoggerFactory;
615

716
import java.util.ArrayList;
17+
import java.util.Collections;
818
import java.util.HashMap;
919
import java.util.List;
1020
import java.util.Map;
1121
import java.util.Objects;
1222
import java.util.Optional;
1323
import java.util.UUID;
1424

15-
import static io.opentdf.platform.sdk.Autoconfigure.Granter.generatePlanFromDefaultKases;
16-
1725
public class Planner {
26+
private static final String BASE_KEY = "base_key";
1827
private final Config.TDFConfig tdfConfig;
19-
private final SDK.Services sdkServices;
28+
private final SDK.Services services;
29+
2030

2131
private static final Logger logger = LoggerFactory.getLogger(Planner.class);
2232

2333
public Planner(Config.TDFConfig config, SDK.Services services) {
24-
tdfConfig = Objects.requireNonNull(config);
25-
sdkServices = Objects.requireNonNull(services) ;
34+
this.tdfConfig = Objects.requireNonNull(config);
35+
this.services = Objects.requireNonNull(services);
2636
}
2737

2838
private static String getUUID() {
@@ -31,43 +41,107 @@ private static String getUUID() {
3141

3242
Map<String, List<Config.KASInfo>> getSplits(Config.TDFConfig tdfConfig) {
3343
List<Autoconfigure.KeySplitStep> splitPlan;
34-
List<String> defaultKases = defaultKases(tdfConfig);
3544
if (tdfConfig.autoconfigure) {
45+
if (tdfConfig.splitPlan != null && !tdfConfig.splitPlan.isEmpty()) {
46+
throw new IllegalArgumentException("cannot use autoconfigure with a split plan provided in the TDFConfig");
47+
}
3648
splitPlan = getAutoconfigurePlan(tdfConfig);
3749
} else if (tdfConfig.splitPlan == null || tdfConfig.splitPlan.isEmpty()) {
38-
splitPlan = defaultKases.isEmpty()
39-
? createPlanFromBaseKey()
40-
: generatePlanFromDefaultKases(defaultKases, Planner::getUUID);
50+
splitPlan = generatePlanFromProvidedKases(tdfConfig.kasInfoList);
4151
} else {
4252
splitPlan = tdfConfig.splitPlan;
4353
}
4454

4555
if (tdfConfig.kasInfoList.isEmpty() && tdfConfig.splitPlan.isEmpty()) {
4656
throw new SDK.KasInfoMissing("kas information is missing, no key access template specified or inferred");
4757
}
48-
49-
// split plan: restructure by conjunctions
5058
return fillInKeys(tdfConfig, splitPlan);
5159
}
5260

5361
private List<Autoconfigure.KeySplitStep> getAutoconfigurePlan(Config.TDFConfig tdfConfig) {
54-
if (tdfConfig.splitPlan != null && !tdfConfig.splitPlan.isEmpty()) {
55-
throw new IllegalArgumentException("cannot use autoconfigure with a split plan provided in the TDFConfig");
56-
}
5762
Autoconfigure.Granter granter = new Autoconfigure.Granter(new ArrayList<>());
5863
if (tdfConfig.attributeValues != null && !tdfConfig.attributeValues.isEmpty()) {
59-
granter = Autoconfigure.newGranterFromAttributes(sdkServices.kas().getKeyCache(), tdfConfig.attributeValues.toArray(new Value[0]));
64+
granter = Autoconfigure.newGranterFromAttributes(services.kas().getKeyCache(), tdfConfig.attributeValues.toArray(new Value[0]));
6065
} else if (tdfConfig.attributes != null && !tdfConfig.attributes.isEmpty()) {
61-
granter = Autoconfigure.newGranterFromService(sdkServices.attributes(), sdkServices.kas().getKeyCache(),
66+
granter = Autoconfigure.newGranterFromService(services.attributes(), services.kas().getKeyCache(),
6267
tdfConfig.attributes.toArray(new Autoconfigure.AttributeValueFQN[0]));
6368
}
64-
return granter.getSplits(defaultKases(tdfConfig), Planner::getUUID, Optional::empty);
69+
return granter.getSplits(defaultKases(tdfConfig), Planner::getUUID, this::fetchBaseKey);
70+
}
71+
72+
List<Autoconfigure.KeySplitStep> generatePlanFromProvidedKases(List<Config.KASInfo> kases) {
73+
if (kases.size() == 1) {
74+
var kasInfo = kases.get(0);
75+
return Collections.singletonList(new Autoconfigure.KeySplitStep(kasInfo.URL, "", kasInfo.KID));
76+
}
77+
List<Autoconfigure.KeySplitStep> splitPlan = new ArrayList<>();
78+
for (var kasInfo : kases) {
79+
splitPlan.add(new Autoconfigure.KeySplitStep(kasInfo.URL, getUUID(), kasInfo.KID));
80+
}
81+
return splitPlan;
82+
}
83+
84+
Optional<SimpleKasKey> fetchBaseKey() {
85+
var responseMessage = services.wellknown()
86+
.getWellKnownConfigurationBlocking(GetWellKnownConfigurationRequest.getDefaultInstance(), Collections.emptyMap())
87+
.execute();
88+
GetWellKnownConfigurationResponse response;
89+
try {
90+
response = RequestHelper.getOrThrow(responseMessage);
91+
} catch (ConnectException e) {
92+
logger.error("unable to retrieve configuration from well known endpoint", e);
93+
throw new SDKException("unable to retrieve base key from well known endpoint", e);
94+
}
95+
96+
String baseKeyJson;
97+
try {
98+
baseKeyJson = response
99+
.getConfiguration()
100+
.getFieldsOrThrow(BASE_KEY)
101+
.getStringValue();
102+
} catch (IllegalArgumentException e) {
103+
logger.info( "no `" + BASE_KEY + "` found in well known configuration.", e);
104+
return Optional.empty();
105+
}
106+
107+
BaseKey baseKey;
108+
try {
109+
baseKey = gson.fromJson(baseKeyJson, BaseKey.class);
110+
} catch (JsonSyntaxException e) {
111+
throw new SDKException("base key in well known configuration is malformed [" + baseKeyJson + "]", e);
112+
}
113+
114+
if (baseKey == null || baseKey.kasUrl == null || baseKey.publicKey == null || baseKey.publicKey.kid == null || baseKey.publicKey.pem == null || baseKey.publicKey.algorithm == null) {
115+
throw new SDKException("base key in well known configuration is missing required fields [" + baseKeyJson + "]");
116+
}
117+
118+
return Optional.of(SimpleKasKey.newBuilder()
119+
.setKasUri(baseKey.kasUrl)
120+
.setPublicKey(SimpleKasPublicKey.newBuilder()
121+
.setKid(baseKey.publicKey.kid)
122+
.setAlgorithm(baseKey.publicKey.algorithm)
123+
.setPem(baseKey.publicKey.pem)
124+
.build())
125+
.build());
65126
}
66127

67-
private List<Autoconfigure.KeySplitStep> createPlanFromBaseKey() {
68-
return null;
128+
private static Gson gson = new Gson();
129+
130+
private static class BaseKey {
131+
@SerializedName("kas_url")
132+
String kasUrl;
133+
134+
@SerializedName("public_key")
135+
Key publicKey;
136+
137+
private static class Key {
138+
String kid;
139+
String pem;
140+
Algorithm algorithm;
141+
}
69142
}
70143

144+
71145
private Map<String, List<Config.KASInfo>> fillInKeys(Config.TDFConfig tdfConfig, List<Autoconfigure.KeySplitStep> splitPlan) {
72146
Map<String, List<Config.KASInfo>> conjunction = new HashMap<>();
73147
var latestKASInfo = new HashMap<String, Config.KASInfo>();
@@ -87,7 +161,7 @@ private Map<String, List<Config.KASInfo>> fillInKeys(Config.TDFConfig tdfConfig,
87161
var getKI = new Config.KASInfo();
88162
getKI.URL = splitInfo.kas;
89163
getKI.Algorithm = tdfConfig.wrappingKeyType.toString();
90-
getKI = sdkServices.kas().getPublicKey(getKI);
164+
getKI = services.kas().getPublicKey(getKI);
91165
latestKASInfo.put(splitInfo.kas, getKI);
92166
ki = getKI;
93167
}

sdk/src/main/java/io/opentdf/platform/sdk/SDK.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.opentdf.platform.policy.namespaces.NamespaceServiceClientInterface;
1010
import io.opentdf.platform.policy.resourcemapping.ResourceMappingServiceClientInterface;
1111
import io.opentdf.platform.policy.subjectmapping.SubjectMappingServiceClientInterface;
12+
import io.opentdf.platform.wellknownconfiguration.WellKnownServiceClientInterface;
1213

1314
import javax.net.ssl.TrustManager;
1415
import java.io.IOException;
@@ -75,6 +76,8 @@ public interface Services extends AutoCloseable {
7576

7677
KeyAccessServerRegistryServiceClientInterface kasRegistry();
7778

79+
WellKnownServiceClientInterface wellknown();
80+
7881
KAS kas();
7982
}
8083

sdk/src/main/java/io/opentdf/platform/sdk/SDKBuilder.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.opentdf.platform.wellknownconfiguration.GetWellKnownConfigurationRequest;
3434
import io.opentdf.platform.wellknownconfiguration.GetWellKnownConfigurationResponse;
3535
import io.opentdf.platform.wellknownconfiguration.WellKnownServiceClient;
36+
import io.opentdf.platform.wellknownconfiguration.WellKnownServiceClientInterface;
3637
import nl.altindag.ssl.SSLFactory;
3738
import nl.altindag.ssl.pem.util.PemUtils;
3839
import okhttp3.OkHttpClient;
@@ -251,6 +252,7 @@ ServicesAndInternals buildServices() {
251252
var resourceMappingService = new ResourceMappingServiceClient(client);
252253
var authorizationService = new AuthorizationServiceClient(client);
253254
var kasRegistryService = new KeyAccessServerRegistryServiceClient(client);
255+
var wellKnownService = new WellKnownServiceClient(client);
254256

255257
var services = new SDK.Services() {
256258
@Override
@@ -290,6 +292,11 @@ public KeyAccessServerRegistryServiceClient kasRegistry() {
290292
return kasRegistryService;
291293
}
292294

295+
@Override
296+
public WellKnownServiceClientInterface wellknown() {
297+
return wellKnownService;
298+
}
299+
293300
@Override
294301
public SDK.KAS kas() {
295302
return kasClient;

sdk/src/main/java/io/opentdf/platform/sdk/TDF.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import io.opentdf.platform.policy.kasregistry.ListKeyAccessServersRequest;
99
import io.opentdf.platform.policy.kasregistry.ListKeyAccessServersResponse;
10-
import io.opentdf.platform.sdk.Config.TDFConfig;
1110
import io.opentdf.platform.sdk.Config.KASInfo;
1211

1312
import org.apache.commons.codec.DecoderException;
@@ -346,7 +345,6 @@ private static byte[] calculateSignature(byte[] data, byte[] secret, Config.Inte
346345
}
347346

348347
TDFObject createTDF(InputStream payload, OutputStream outputStream, Config.TDFConfig tdfConfig) throws SDKException, IOException {
349-
350348
Planner planner = new Planner(tdfConfig, services);
351349
Map<String, List<KASInfo>> splits = planner.getSplits(tdfConfig);
352350

sdk/src/test/java/io/opentdf/platform/sdk/FakeServices.java

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,86 @@
11
package io.opentdf.platform.sdk;
22

33
import io.opentdf.platform.authorization.AuthorizationServiceClient;
4+
import io.opentdf.platform.authorization.AuthorizationServiceClientInterface;
45
import io.opentdf.platform.policy.attributes.AttributesServiceClient;
6+
import io.opentdf.platform.policy.attributes.AttributesServiceClientInterface;
57
import io.opentdf.platform.policy.kasregistry.KeyAccessServerRegistryServiceClient;
8+
import io.opentdf.platform.policy.kasregistry.KeyAccessServerRegistryServiceClientInterface;
69
import io.opentdf.platform.policy.namespaces.NamespaceServiceClient;
10+
import io.opentdf.platform.policy.namespaces.NamespaceServiceClientInterface;
711
import io.opentdf.platform.policy.resourcemapping.ResourceMappingServiceClient;
12+
import io.opentdf.platform.policy.resourcemapping.ResourceMappingServiceClientInterface;
813
import io.opentdf.platform.policy.subjectmapping.SubjectMappingServiceClient;
14+
import io.opentdf.platform.policy.subjectmapping.SubjectMappingServiceClientInterface;
15+
import io.opentdf.platform.wellknownconfiguration.WellKnownServiceClientInterface;
916

1017
import java.util.Objects;
1118

1219
public class FakeServices implements SDK.Services {
1320

14-
private final AuthorizationServiceClient authorizationService;
15-
private final AttributesServiceClient attributesService;
16-
private final NamespaceServiceClient namespaceService;
17-
private final SubjectMappingServiceClient subjectMappingService;
18-
private final ResourceMappingServiceClient resourceMappingService;
19-
private final KeyAccessServerRegistryServiceClient keyAccessServerRegistryServiceFutureStub;
21+
private final AuthorizationServiceClientInterface authorizationService;
22+
private final AttributesServiceClientInterface attributesService;
23+
private final NamespaceServiceClientInterface namespaceService;
24+
private final SubjectMappingServiceClientInterface subjectMappingService;
25+
private final ResourceMappingServiceClientInterface resourceMappingService;
26+
private final KeyAccessServerRegistryServiceClientInterface keyAccessServerRegistryServiceFutureStub;
27+
private final WellKnownServiceClientInterface wellKnownService;
2028
private final SDK.KAS kas;
2129

2230
public FakeServices(
23-
AuthorizationServiceClient authorizationService,
24-
AttributesServiceClient attributesService,
25-
NamespaceServiceClient namespaceService,
26-
SubjectMappingServiceClient subjectMappingService,
27-
ResourceMappingServiceClient resourceMappingService,
28-
KeyAccessServerRegistryServiceClient keyAccessServerRegistryServiceFutureStub,
31+
AuthorizationServiceClientInterface authorizationService,
32+
AttributesServiceClientInterface attributesService,
33+
NamespaceServiceClientInterface namespaceService,
34+
SubjectMappingServiceClientInterface subjectMappingService,
35+
ResourceMappingServiceClientInterface resourceMappingService,
36+
KeyAccessServerRegistryServiceClientInterface keyAccessServerRegistryServiceFutureStub,
37+
WellKnownServiceClientInterface wellKnownServiceClient,
2938
SDK.KAS kas) {
3039
this.authorizationService = authorizationService;
3140
this.attributesService = attributesService;
3241
this.namespaceService = namespaceService;
3342
this.subjectMappingService = subjectMappingService;
3443
this.resourceMappingService = resourceMappingService;
3544
this.keyAccessServerRegistryServiceFutureStub = keyAccessServerRegistryServiceFutureStub;
45+
this.wellKnownService = wellKnownServiceClient;
3646
this.kas = kas;
3747
}
3848

3949
@Override
40-
public AuthorizationServiceClient authorization() {
50+
public AuthorizationServiceClientInterface authorization() {
4151
return Objects.requireNonNull(authorizationService);
4252
}
4353

4454
@Override
45-
public AttributesServiceClient attributes() {
55+
public AttributesServiceClientInterface attributes() {
4656
return Objects.requireNonNull(attributesService);
4757
}
4858

4959
@Override
50-
public NamespaceServiceClient namespaces() {
60+
public NamespaceServiceClientInterface namespaces() {
5161
return Objects.requireNonNull(namespaceService);
5262
}
5363

5464
@Override
55-
public SubjectMappingServiceClient subjectMappings() {
65+
public SubjectMappingServiceClientInterface subjectMappings() {
5666
return Objects.requireNonNull(subjectMappingService);
5767
}
5868

5969
@Override
60-
public ResourceMappingServiceClient resourceMappings() {
70+
public ResourceMappingServiceClientInterface resourceMappings() {
6171
return Objects.requireNonNull(resourceMappingService);
6272
}
6373

6474
@Override
65-
public KeyAccessServerRegistryServiceClient kasRegistry() {
75+
public KeyAccessServerRegistryServiceClientInterface kasRegistry() {
6676
return Objects.requireNonNull(keyAccessServerRegistryServiceFutureStub);
6777
}
6878

79+
@Override
80+
public WellKnownServiceClientInterface wellknown() {
81+
return Objects.requireNonNull(wellKnownService);
82+
}
83+
6984
@Override
7085
public SDK.KAS kas() {
7186
return Objects.requireNonNull(kas);

0 commit comments

Comments
 (0)