Skip to content

Commit b264db8

Browse files
authored
Merge pull request #187 from IABTechLab/tjm-UID2-2808-attest-core-url
Attest Core URL as passed in by the operators
2 parents 2dff779 + e9e6e5f commit b264db8

23 files changed

+253
-108
lines changed

pom.xml

+10-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.uid2</groupId>
88
<artifactId>uid2-shared</artifactId>
9-
<version>6.1.8-6e6866128b</version>
9+
<version>6.1.19-SNAPSHOT</version>
1010
<name>${project.groupId}:${project.artifactId}</name>
1111
<description>Library for all the shared uid2 operations</description>
1212
<url>https://github.com/IABTechLab/uid2docs</url>
@@ -33,6 +33,14 @@
3333
<url>https://github.com/IABTechLab/uid2-shared</url>
3434
</scm>
3535

36+
<repositories>
37+
<repository>
38+
<id>snapshots-repo</id>
39+
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
40+
<releases><enabled>false</enabled></releases>
41+
<snapshots><enabled>true</enabled></snapshots>
42+
</repository>
43+
</repositories>
3644
<distributionManagement>
3745
<snapshotRepository>
3846
<id>ossrh</id>
@@ -71,7 +79,7 @@
7179
<dependency>
7280
<groupId>com.uid2</groupId>
7381
<artifactId>uid2-attestation-api</artifactId>
74-
<version>1.5.0-676519b018</version>
82+
<version>2.0.0-f968aec0e3</version>
7583
</dependency>
7684
<dependency>
7785
<groupId>io.vertx</groupId>

src/main/java/com/uid2/shared/attest/AttestationTokenRetriever.java

+11-5
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@
1414
import java.io.IOException;
1515
import java.net.*;
1616
import java.net.http.HttpResponse;
17+
import java.nio.ByteBuffer;
1718
import java.nio.charset.StandardCharsets;
1819
import java.security.*;
1920
import java.time.Instant;
20-
import java.util.Base64;
21-
import java.util.HashMap;
22-
import java.util.Map;
23-
import java.util.Objects;
21+
import java.util.*;
2422
import java.util.concurrent.atomic.AtomicBoolean;
2523
import java.util.concurrent.atomic.AtomicReference;
2624
import java.util.concurrent.locks.Lock;
@@ -37,6 +35,7 @@ public class AttestationTokenRetriever {
3735
private final AtomicReference<String> coreJwt;
3836
private final Handler<Pair<Integer, String>> responseWatcher;
3937
private final String attestationEndpoint;
38+
private final byte[] encodedAttestationEndpoint;
4039
private final IClock clock;
4140
private final Vertx vertx;
4241
private final URLConnectionHttpClient httpClient;
@@ -71,6 +70,7 @@ public AttestationTokenRetriever(Vertx vertx,
7170
int attestCheckMilliseconds) {
7271
this.vertx = vertx;
7372
this.attestationEndpoint = attestationEndpoint;
73+
this.encodedAttestationEndpoint = this.encodeStringUnicodeAttestationEndpoint(attestationEndpoint);
7474
this.clientApiToken = clientApiToken;
7575
this.appVersion = appVersion;
7676
this.attestationProvider = attestationProvider;
@@ -153,7 +153,7 @@ public void attest() throws IOException, AttestationTokenRetrieverException {
153153
KeyPair keyPair = generateKeyPair();
154154
byte[] publicKey = keyPair.getPublic().getEncoded();
155155
JsonObject requestJson = JsonObject.of(
156-
"attestation_request", Base64.getEncoder().encodeToString(attestationProvider.getAttestationRequest(publicKey)),
156+
"attestation_request", Base64.getEncoder().encodeToString(attestationProvider.getAttestationRequest(publicKey, this.encodedAttestationEndpoint)),
157157
"public_key", Base64.getEncoder().encodeToString(publicKey),
158158
"application_name", appVersion.getAppName(),
159159
"application_version", appVersion.getAppVersion()
@@ -289,4 +289,10 @@ private void notifyResponseWatcher(int statusCode, String responseBody) {
289289
public boolean attested() {
290290
return this.attestationToken.get() != null && this.clock.now().isBefore(this.attestationTokenExpiresAt);
291291
}
292+
293+
private byte[] encodeStringUnicodeAttestationEndpoint(String data) {
294+
// buffer.array() may include extra empty bytes at the end. This returns only the bytes that have data
295+
ByteBuffer buffer = StandardCharsets.UTF_8.encode(data);
296+
return Arrays.copyOf(buffer.array(), buffer.limit());
297+
}
292298
}

src/main/java/com/uid2/shared/attest/NoAttestationProvider.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
public class NoAttestationProvider implements IAttestationProvider {
66
@Override
7-
public byte[] getAttestationRequest(byte[] publicKey) {
7+
public byte[] getAttestationRequest(byte[] publicKey, byte[] userData) {
88
byte[] req = {0};
99
return req;
1010
}

src/main/java/com/uid2/shared/attest/UidCoreClient.java

+3-10
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,27 @@ public class UidCoreClient implements IUidCoreClient, DownloadCloudStorage {
2020
private final URLConnectionHttpClient httpClient;
2121
private String userToken;
2222
private final String appVersionHeader;
23-
private final boolean enforceHttps;
2423
private boolean allowContentFromLocalFileSystem = false;
2524
private final AttestationTokenRetriever attestationTokenRetriever;
2625

2726

28-
public static UidCoreClient createNoAttest(String userToken, boolean enforceHttps, AttestationTokenRetriever attestationTokenRetriever) {
29-
return new UidCoreClient(userToken, CloudUtils.defaultProxy, enforceHttps, attestationTokenRetriever, null);
27+
public static UidCoreClient createNoAttest(String userToken, AttestationTokenRetriever attestationTokenRetriever) {
28+
return new UidCoreClient(userToken, CloudUtils.defaultProxy, attestationTokenRetriever, null);
3029
}
3130

3231
public UidCoreClient(String userToken,
3332
Proxy proxy,
34-
boolean enforceHttps,
3533
AttestationTokenRetriever attestationTokenRetriever) {
36-
this(userToken, proxy, enforceHttps, attestationTokenRetriever, null);
34+
this(userToken, proxy, attestationTokenRetriever, null);
3735
}
3836

3937
public UidCoreClient(String userToken,
4038
Proxy proxy,
41-
boolean enforceHttps,
4239
AttestationTokenRetriever attestationTokenRetriever,
4340
URLConnectionHttpClient httpClient) {
4441
this.proxy = proxy;
4542
this.userToken = userToken;
4643
this.contentStorage = new PreSignedURLStorage(proxy);
47-
this.enforceHttps = enforceHttps;
4844
if (httpClient == null) {
4945
this.httpClient = new URLConnectionHttpClient(proxy);
5046
} else {
@@ -116,9 +112,6 @@ private InputStream getWithAttest(String path) throws IOException, AttestationTo
116112

117113
private HttpResponse<String> sendHttpRequest(String path, String attestationToken) throws IOException {
118114
URI uri = URI.create(path);
119-
if (this.enforceHttps && !"https".equalsIgnoreCase(uri.getScheme())) {
120-
throw new IOException("UidCoreClient requires HTTPS connection");
121-
}
122115

123116
HashMap<String, String> headers = new HashMap<>();
124117
headers.put(Const.Http.AppVersionHeader, this.appVersionHeader);

src/main/java/com/uid2/shared/attest/UidOptOutClient.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,19 @@
88

99
public class UidOptOutClient extends UidCoreClient {
1010
public static UidOptOutClient createNoAttest(String userToken, boolean enforceHttps, AttestationTokenRetriever attestationTokenRetriever) {
11-
return new UidOptOutClient(userToken, CloudUtils.defaultProxy, enforceHttps, attestationTokenRetriever, null);
11+
return new UidOptOutClient(userToken, CloudUtils.defaultProxy, attestationTokenRetriever, null);
1212
}
1313

1414
public UidOptOutClient(String userToken,
1515
Proxy proxy,
16-
boolean enforceHttps,
1716
AttestationTokenRetriever attestationTokenRetriever) {
18-
super(userToken, proxy, enforceHttps, attestationTokenRetriever, null);
17+
super(userToken, proxy, attestationTokenRetriever, null);
1918
}
2019
public UidOptOutClient(String userToken,
2120
Proxy proxy,
22-
boolean enforceHttps,
2321
AttestationTokenRetriever attestationTokenRetriever,
2422
URLConnectionHttpClient httpClient) {
25-
super(userToken, proxy, enforceHttps, attestationTokenRetriever, httpClient);
23+
super(userToken, proxy, attestationTokenRetriever, httpClient);
2624
}
2725

2826
@Override

src/main/java/com/uid2/shared/secure/AttestationFailure.java

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public enum AttestationFailure {
66
BAD_PAYLOAD,
77
BAD_CERTIFICATE,
88
FORBIDDEN_ENCLAVE,
9+
UNKNOWN_ATTESTATION_URL,
910
UNKNOWN;
1011

1112
public String explain() {
@@ -20,6 +21,8 @@ public String explain() {
2021
return "Cannot verify the certificate chain";
2122
case FORBIDDEN_ENCLAVE:
2223
return "The enclave identifier is unknown";
24+
case UNKNOWN_ATTESTATION_URL:
25+
return "The given attestation URL is unknown";
2326
default:
2427
return "Unknown reason";
2528
}

src/main/java/com/uid2/shared/secure/AzureCCAttestationProvider.java renamed to src/main/java/com/uid2/shared/secure/AzureCCCoreAttestationService.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@
1717

1818
// CC stands for Confidential Container
1919
@Slf4j
20-
public class AzureCCAttestationProvider implements IAttestationProvider {
20+
public class AzureCCCoreAttestationService implements ICoreAttestationService {
2121

2222
private final Set<String> allowedEnclaveIds = new HashSet<>();
2323

2424
private final IMaaTokenSignatureValidator tokenSignatureValidator;
2525

2626
private final IPolicyValidator policyValidator;
2727

28-
public AzureCCAttestationProvider(String maaServerBaseUrl) {
28+
public AzureCCCoreAttestationService(String maaServerBaseUrl) {
2929
this(new MaaTokenSignatureValidator(maaServerBaseUrl), new PolicyValidator());
3030
}
3131

3232
// used in UT
33-
protected AzureCCAttestationProvider(IMaaTokenSignatureValidator tokenSignatureValidator, IPolicyValidator policyValidator) {
33+
protected AzureCCCoreAttestationService(IMaaTokenSignatureValidator tokenSignatureValidator, IPolicyValidator policyValidator) {
3434
this.tokenSignatureValidator = tokenSignatureValidator;
3535
this.policyValidator = policyValidator;
3636
}

src/main/java/com/uid2/shared/secure/GcpOidcAttestationProvider.java renamed to src/main/java/com/uid2/shared/secure/GcpOidcCoreAttestationService.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,21 @@
1010
import java.nio.charset.StandardCharsets;
1111
import java.util.*;
1212

13-
public class GcpOidcAttestationProvider implements IAttestationProvider{
14-
private static final Logger LOGGER = LoggerFactory.getLogger(GcpOidcAttestationProvider.class);
13+
public class GcpOidcCoreAttestationService implements ICoreAttestationService {
14+
private static final Logger LOGGER = LoggerFactory.getLogger(GcpOidcCoreAttestationService.class);
1515

1616
private final ITokenSignatureValidator tokenSignatureValidator;
1717

1818
private final List<IPolicyValidator> supportedPolicyValidators;
1919

2020
private final Set<String> allowedEnclaveIds = new HashSet<>();
2121

22-
public GcpOidcAttestationProvider(){
22+
public GcpOidcCoreAttestationService(){
2323
this(new TokenSignatureValidator(), Arrays.asList(new PolicyValidator()));
2424
}
2525

2626
// used in UT
27-
protected GcpOidcAttestationProvider(ITokenSignatureValidator tokenSignatureValidator, List<IPolicyValidator> supportedPolicyValidators){
27+
protected GcpOidcCoreAttestationService(ITokenSignatureValidator tokenSignatureValidator, List<IPolicyValidator> supportedPolicyValidators){
2828
this.tokenSignatureValidator = tokenSignatureValidator;
2929
this.supportedPolicyValidators = supportedPolicyValidators;
3030
}

src/main/java/com/uid2/shared/secure/GcpVmidAttestationProvider.java renamed to src/main/java/com/uid2/shared/secure/GcpVmidCoreAttestationService.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
import java.nio.charset.StandardCharsets;
1818
import java.util.*;
1919

20-
public class GcpVmidAttestationProvider implements IAttestationProvider {
21-
private static final Logger LOGGER = LoggerFactory.getLogger(GcpVmidAttestationProvider.class);
20+
public class GcpVmidCoreAttestationService implements ICoreAttestationService {
21+
private static final Logger LOGGER = LoggerFactory.getLogger(GcpVmidCoreAttestationService.class);
2222

2323
private final InstanceDocumentVerifier idVerifier = new InstanceDocumentVerifier();
2424
private final VmConfigVerifier vmConfigVerifier;
2525
private final Set<String> allowedVmConfigIds = new HashSet<>();
2626

27-
public GcpVmidAttestationProvider(GoogleCredentials credentials, Set<String> enclaveParams) throws Exception {
27+
public GcpVmidCoreAttestationService(GoogleCredentials credentials, Set<String> enclaveParams) throws Exception {
2828
LoadBalancerRegistry.getDefaultRegistry().register(new PickFirstLoadBalancerProvider());
2929
this.vmConfigVerifier = new VmConfigVerifier(credentials, enclaveParams);
3030
LOGGER.info("Using Google Service Account: " + credentials.toString());

src/main/java/com/uid2/shared/secure/IAttestationProvider.java renamed to src/main/java/com/uid2/shared/secure/ICoreAttestationService.java

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
package com.uid2.shared.secure;
22

3-
import com.uid2.shared.secure.AttestationException;
4-
import com.uid2.shared.secure.AttestationResult;
5-
63
import java.util.Collection;
74

85
import io.vertx.core.AsyncResult;
96
import io.vertx.core.Handler;
107

11-
public interface IAttestationProvider {
8+
public interface ICoreAttestationService {
129
void attest(
1310
byte[] attestationRequest,
1411
byte[] publicKey,

src/main/java/com/uid2/shared/secure/NitroAttestationProvider.java renamed to src/main/java/com/uid2/shared/secure/NitroCoreAttestationService.java

+15-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.uid2.shared.secure.nitro.AttestationDocument;
44
import com.uid2.shared.secure.nitro.AttestationRequest;
5-
import com.uid2.shared.secure.IAttestationProvider;
65

76
import java.util.Arrays;
87
import java.util.Base64;
@@ -11,16 +10,23 @@
1110
import java.util.Set;
1211
import java.util.stream.Collectors;
1312

13+
import com.uid2.shared.util.UrlEquivalenceValidator;
1414
import io.vertx.core.AsyncResult;
1515
import io.vertx.core.Future;
1616
import io.vertx.core.Handler;
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
1719

18-
public class NitroAttestationProvider implements IAttestationProvider {
20+
public class NitroCoreAttestationService implements ICoreAttestationService {
1921

22+
private final String attestationUrl;
2023
private Set<NitroEnclaveIdentifier> allowedEnclaveIds;
21-
private ICertificateProvider certificateProvider;
24+
private final ICertificateProvider certificateProvider;
2225

23-
public NitroAttestationProvider(ICertificateProvider certificateProvider) {
26+
private static final Logger LOGGER = LoggerFactory.getLogger(NitroCoreAttestationService.class);
27+
28+
public NitroCoreAttestationService(ICertificateProvider certificateProvider, String attestationUrl) {
29+
this.attestationUrl = attestationUrl;
2430
this.allowedEnclaveIds = new HashSet<>();
2531
this.certificateProvider = certificateProvider;
2632
}
@@ -49,6 +55,11 @@ private AttestationResult attestInternal(byte[] publicKey, AttestationRequest aR
4955
return new AttestationResult(AttestationFailure.BAD_CERTIFICATE);
5056
}
5157

58+
String givenAttestationUrl = aDoc.getUserDataString();
59+
if (!UrlEquivalenceValidator.areUrlsEquivalent(this.attestationUrl, givenAttestationUrl, LOGGER)) {
60+
return new AttestationResult(AttestationFailure.UNKNOWN_ATTESTATION_URL);
61+
}
62+
5263
NitroEnclaveIdentifier id = NitroEnclaveIdentifier.fromRaw(aDoc.getPcr(0));
5364
if (!allowedEnclaveIds.contains(id)) {
5465
return new AttestationResult(AttestationFailure.FORBIDDEN_ENCLAVE);

src/main/java/com/uid2/shared/secure/TrustedAttestationProvider.java renamed to src/main/java/com/uid2/shared/secure/TrustedCoreAttestationService.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
import java.util.Collection;
88
import java.util.Collections;
99

10-
public class TrustedAttestationProvider implements IAttestationProvider {
11-
public TrustedAttestationProvider() {}
10+
public class TrustedCoreAttestationService implements ICoreAttestationService {
11+
public TrustedCoreAttestationService() {}
1212

1313
@Override
1414
public void attest(byte[] attestationRequest, byte[] publicKey, Handler<AsyncResult<AttestationResult>> handler) {

src/main/java/com/uid2/shared/secure/gcpoidc/PolicyValidator.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ public class PolicyValidator implements IPolicyValidator {
3030

3131
private static final List<String> REQUIRED_ENV_OVERRIDES = ImmutableList.of(
3232
ENV_ENVIRONMENT,
33-
ENV_OPERATOR_API_KEY_SECRET_NAME
33+
ENV_OPERATOR_API_KEY_SECRET_NAME,
34+
ENV_CORE_ENDPOINT,
35+
ENV_OPT_OUT_ENDPOINT
3436
);
3537

3638
private static final Map<Environment, List<String>> OPTIONAL_ENV_OVERRIDES_MAP = ImmutableMap.of(
37-
Environment.Integration, ImmutableList.of(ENV_CORE_ENDPOINT, ENV_OPT_OUT_ENDPOINT)
39+
Environment.Integration, ImmutableList.of()
3840
);
3941

4042
@Override

src/main/java/com/uid2/shared/secure/nitro/AttestationDocument.java

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import java.io.ByteArrayInputStream;
88
import java.math.BigInteger;
9+
import java.nio.charset.StandardCharsets;
910
import java.security.cert.CertPath;
1011
import java.security.cert.Certificate;
1112
import java.security.cert.CertificateException;
@@ -46,6 +47,7 @@ public static AttestationDocument createFrom(byte[] data) throws CborException {
4647
private List<byte[]> cabundle;
4748
private byte[] publicKey;
4849
private byte[] userData;
50+
private String userDataString;
4951
private byte[] nonce;
5052

5153
private AttestationDocument() {}
@@ -96,6 +98,7 @@ private void loadUserData(DataItem d) {
9698
this.userData = null;
9799
} else {
98100
this.userData = ((ByteString) d).getBytes();
101+
this.userDataString = new String(this.userData, StandardCharsets.UTF_8);
99102
}
100103
}
101104

@@ -146,6 +149,10 @@ public byte[] getUserData() {
146149
return userData;
147150
}
148151

152+
public String getUserDataString() {
153+
return userDataString;
154+
}
155+
149156
public byte[] getNonce() {
150157
return nonce;
151158
}

0 commit comments

Comments
 (0)