Skip to content

Commit dfcb570

Browse files
committed
Added AttestationFailure to the AttesationClientException
1 parent b17be7b commit dfcb570

File tree

7 files changed

+56
-30
lines changed

7 files changed

+56
-30
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,19 @@
22

33
public class AttestationClientException extends AttestationException
44
{
5+
private final AttestationFailure attestationFailure;
6+
57
public AttestationClientException(Throwable cause) {
68
super(cause, true);
9+
this.attestationFailure = AttestationFailure.UNKNOWN;
710
}
811

9-
public AttestationClientException(String message) {
12+
public AttestationClientException(String message, AttestationFailure attestationFailure) {
1013
super(message, true);
14+
this.attestationFailure = attestationFailure;
15+
}
16+
17+
public AttestationFailure getAttestationFailure() {
18+
return this.attestationFailure;
1119
}
1220
}

src/main/java/com/uid2/shared/secure/azurecc/MaaTokenSignatureValidator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.google.common.base.Strings;
88
import com.uid2.shared.secure.AttestationClientException;
99
import com.uid2.shared.secure.AttestationException;
10+
import com.uid2.shared.secure.AttestationFailure;
1011

1112
import java.io.IOException;
1213
import java.util.Map;
@@ -66,7 +67,7 @@ public MaaTokenPayload validate(String tokenString) throws AttestationException
6667
tokenVerifier.verify(tokenString);
6768
}
6869
} catch (TokenVerifier.VerificationException e) {
69-
throw new AttestationClientException("Fail to validate the token signature, error: " + e.getMessage());
70+
throw new AttestationClientException("Fail to validate the token signature, error: " + e.getMessage(), AttestationFailure.BAD_PAYLOAD);
7071
} catch (IOException e) {
7172
throw new AttestationException("Fail to parse token, error: " + e.getMessage());
7273
}

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.google.common.base.Strings;
44
import com.uid2.shared.secure.AttestationClientException;
55
import com.uid2.shared.secure.AttestationException;
6+
import com.uid2.shared.secure.AttestationFailure;
67

78
public class PolicyValidator implements IPolicyValidator{
89
private static final String LOCATION_CHINA = "china";
@@ -17,39 +18,40 @@ public String validate(MaaTokenPayload maaTokenPayload, String publicKey) throws
1718

1819
private void verifyPublicKey(MaaTokenPayload maaTokenPayload, String publicKey) throws AttestationException {
1920
if(Strings.isNullOrEmpty(publicKey)){
20-
throw new AttestationClientException("public key to check is null or empty");
21+
throw new AttestationClientException("public key to check is null or empty", AttestationFailure.BAD_FORMAT);
2122
}
2223
var runtimePublicKey = maaTokenPayload.getRuntimeData().getPublicKey();
2324
if(!publicKey.equals(runtimePublicKey)){
2425
throw new AttestationClientException(
2526
String.format("Public key in payload is not match expected value. More info: runtime(%s), expected(%s)",
2627
runtimePublicKey,
2728
publicKey
28-
));
29+
),
30+
AttestationFailure.BAD_FORMAT);
2931
}
3032
}
3133

3234
private void verifyVM(MaaTokenPayload maaTokenPayload) throws AttestationException {
3335
if(!maaTokenPayload.isSevSnpVM()){
34-
throw new AttestationClientException("Not in SevSnp VM");
36+
throw new AttestationClientException("Not in SevSnp VM", AttestationFailure.BAD_FORMAT);
3537
}
3638
if(!maaTokenPayload.isUtilityVMCompliant()){
37-
throw new AttestationClientException("Not run in Azure Compliance Utility VM");
39+
throw new AttestationClientException("Not run in Azure Compliance Utility VM", AttestationFailure.BAD_FORMAT);
3840
}
3941
if(maaTokenPayload.isVmDebuggable()){
40-
throw new AttestationClientException("The underlying hardware should not run in debug mode");
42+
throw new AttestationClientException("The underlying hardware should not run in debug mode", AttestationFailure.BAD_FORMAT);
4143
}
4244
}
4345

4446
private void verifyLocation(MaaTokenPayload maaTokenPayload) throws AttestationException {
4547
var location = maaTokenPayload.getRuntimeData().getLocation();
4648
if(Strings.isNullOrEmpty(location)){
47-
throw new AttestationClientException("Location is not specified.");
49+
throw new AttestationClientException("Location is not specified.", AttestationFailure.BAD_PAYLOAD);
4850
}
4951
var lowerCaseLocation = location.toLowerCase();
5052
if(lowerCaseLocation.contains(LOCATION_CHINA) ||
5153
lowerCaseLocation.contains(LOCATION_EU)){
52-
throw new AttestationClientException("Location is not supported. Value: " + location);
54+
throw new AttestationClientException("Location is not supported. Value: " + location, AttestationFailure.BAD_PAYLOAD);
5355
}
5456
}
5557
}

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.uid2.shared.Utils;
77
import com.uid2.shared.secure.AttestationClientException;
88
import com.uid2.shared.secure.AttestationException;
9+
import com.uid2.shared.secure.AttestationFailure;
910
import com.uid2.shared.util.UrlEquivalenceValidator;
1011
import org.apache.commons.collections4.CollectionUtils;
1112
import org.apache.commons.collections4.MapUtils;
@@ -67,18 +68,18 @@ public String validate(TokenPayload payload) throws AttestationException {
6768

6869
private static boolean checkConfidentialSpace(TokenPayload payload) throws AttestationException{
6970
if(!payload.isConfidentialSpaceSW()){
70-
throw new AttestationClientException("Unexpected SW_NAME: " + payload.getSwName());
71+
throw new AttestationClientException("Unexpected SW_NAME: " + payload.getSwName(), AttestationFailure.BAD_FORMAT);
7172
}
7273
var isDebugMode = payload.isDebugMode();
7374
if(!isDebugMode && !payload.isStableVersion()){
74-
throw new AttestationClientException("Confidential space image version is not stable.");
75+
throw new AttestationClientException("Confidential space image version is not stable.", AttestationFailure.BAD_FORMAT);
7576
}
7677
return isDebugMode;
7778
}
7879

7980
private static String checkWorkload(TokenPayload payload) throws AttestationException{
8081
if(!payload.isRestartPolicyNever()){
81-
throw new AttestationClientException("Restart policy is not set to Never. Value: " + payload.getRestartPolicy());
82+
throw new AttestationClientException("Restart policy is not set to Never. Value: " + payload.getRestartPolicy(), AttestationFailure.BAD_FORMAT);
8283
}
8384
return payload.getWorkloadImageDigest();
8485
}
@@ -89,35 +90,35 @@ private static String checkWorkload(TokenPayload payload) throws AttestationExce
8990
private static String checkRegion(TokenPayload payload) throws AttestationException{
9091
var region = payload.getGceZone();
9192
if(Strings.isNullOrEmpty(region) || region.startsWith(EU_REGION_PREFIX)){
92-
throw new AttestationClientException("Region is not supported. Value: " + region);
93+
throw new AttestationClientException("Region is not supported. Value: " + region, AttestationFailure.BAD_FORMAT);
9394
}
9495
return region;
9596
}
9697

9798
private static void checkCmdOverrides(TokenPayload payload) throws AttestationException{
9899
if(!CollectionUtils.isEmpty(payload.getCmdOverrides())){
99-
throw new AttestationClientException("Payload should not have cmd overrides");
100+
throw new AttestationClientException("Payload should not have cmd overrides", AttestationFailure.BAD_FORMAT);
100101
}
101102
}
102103

103104
private Environment checkEnvOverrides(TokenPayload payload) throws AttestationException{
104105
var envOverrides = payload.getEnvOverrides();
105106
if(MapUtils.isEmpty(envOverrides)){
106-
throw new AttestationClientException("env overrides should not be empty");
107+
throw new AttestationClientException("env overrides should not be empty", AttestationFailure.BAD_FORMAT);
107108
}
108109
HashMap<String, String> envOverridesCopy = new HashMap(envOverrides);
109110

110111
// check all required env overrides
111112
for(var envKey: REQUIRED_ENV_OVERRIDES){
112113
if(Strings.isNullOrEmpty(envOverridesCopy.get(envKey))){
113-
throw new AttestationClientException("Required env override is missing. key: " + envKey);
114+
throw new AttestationClientException("Required env override is missing. key: " + envKey, AttestationFailure.BAD_FORMAT);
114115
}
115116
}
116117

117118
// env could be parsed
118119
var env = Environment.fromString(envOverridesCopy.get(ENV_ENVIRONMENT));
119120
if(env == null){
120-
throw new AttestationClientException("Environment can not be parsed. " + envOverridesCopy.get(ENV_ENVIRONMENT));
121+
throw new AttestationClientException("Environment can not be parsed. " + envOverridesCopy.get(ENV_ENVIRONMENT), AttestationFailure.BAD_FORMAT);
121122
}
122123

123124
// make sure there's no unexpected overrides
@@ -134,7 +135,7 @@ private Environment checkEnvOverrides(TokenPayload payload) throws AttestationEx
134135
checkAttestationUrl(new HashMap<>(envOverrides));
135136

136137
if(!envOverridesCopy.isEmpty()){
137-
throw new AttestationClientException("More env overrides than allowed. " + envOverridesCopy);
138+
throw new AttestationClientException("More env overrides than allowed. " + envOverridesCopy, AttestationFailure.BAD_FORMAT);
138139
}
139140

140141
return env;
@@ -144,7 +145,7 @@ private void checkAttestationUrl(HashMap<String, String> optionalEnvOverrides) t
144145
if (!Strings.isNullOrEmpty(optionalEnvOverrides.get(ENV_CORE_ENDPOINT))) {
145146
String givenAttestationUrl = optionalEnvOverrides.get(ENV_CORE_ENDPOINT);
146147
if (!UrlEquivalenceValidator.areUrlsEquivalent(givenAttestationUrl, this.attestationUrl, LOGGER)) {
147-
throw new AttestationClientException("The given attestation URL is unknown. Given URL: " + givenAttestationUrl);
148+
throw new AttestationClientException("The given attestation URL is unknown. Given URL: " + givenAttestationUrl, AttestationFailure.UNKNOWN_ATTESTATION_URL);
148149
}
149150
}
150151
}

src/test/java/com/uid2/shared/secure/AzureCCCoreAttestationServiceTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public void testHappyPath() throws AttestationException {
6060
@Test
6161
public void testSignatureCheckFailed_ClientError() throws AttestationException {
6262
var errorStr = "token signature validation failed";
63-
when(alwaysFailTokenValidator.validate(any())).thenThrow(new AttestationClientException(errorStr));
63+
when(alwaysFailTokenValidator.validate(any())).thenThrow(new AttestationClientException(errorStr, AttestationFailure.BAD_PAYLOAD));
6464
var provider = new AzureCCCoreAttestationService(alwaysFailTokenValidator, alwaysPassPolicyValidator);
6565
provider.registerEnclave(ENCLAVE_ID);
6666
attest(provider, ar -> {
@@ -84,7 +84,7 @@ public void testSignatureCheckFailed_ServerError() throws AttestationException {
8484
@Test
8585
public void testPolicyCheckFailed_ClientError() throws AttestationException {
8686
var errorStr = "policy validation failed";
87-
when(alwaysFailPolicyValidator.validate(any(), any())).thenThrow(new AttestationClientException(errorStr));
87+
when(alwaysFailPolicyValidator.validate(any(), any())).thenThrow(new AttestationClientException(errorStr, AttestationFailure.BAD_PAYLOAD));
8888
var provider = new AzureCCCoreAttestationService(alwaysFailTokenValidator, alwaysFailPolicyValidator);
8989
provider.registerEnclave(ENCLAVE_ID);
9090
attest(provider, ar -> {

src/test/java/com/uid2/shared/secure/GcpOidcCoreAttestationServiceTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void testHappyPath() throws AttestationException {
6767
@Test
6868
public void testSignatureCheckFailed_ClientError() throws AttestationException {
6969
var errorStr = "signature validation failed";
70-
when(alwaysFailTokenValidator.validate(any())).thenThrow(new AttestationClientException(errorStr));
70+
when(alwaysFailTokenValidator.validate(any())).thenThrow(new AttestationClientException(errorStr, AttestationFailure.BAD_PAYLOAD));
7171
var provider = new GcpOidcCoreAttestationService(alwaysFailTokenValidator, Arrays.asList(alwaysPassPolicyValidator1));
7272
provider.registerEnclave(ENCLAVE_ID_1);
7373
attest(provider, ar -> {
@@ -91,7 +91,7 @@ public void testSignatureCheckFailed_ServerError() throws AttestationException {
9191
@Test
9292
public void testPolicyCheckFailed_ClientError() throws AttestationException {
9393
var errorStr = "policy validation failed";
94-
when(alwaysFailPolicyValidator.validate(any())).thenThrow(new AttestationClientException(errorStr));
94+
when(alwaysFailPolicyValidator.validate(any())).thenThrow(new AttestationClientException(errorStr, AttestationFailure.BAD_PAYLOAD));
9595
var provider = new GcpOidcCoreAttestationService(alwaysPassTokenValidator, Arrays.asList(alwaysFailPolicyValidator));
9696
provider.registerEnclave(ENCLAVE_ID_1);
9797
attest(provider, ar -> {

src/test/java/com/uid2/shared/secure/gcpoidc/PolicyValidatorTest.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package com.uid2.shared.secure.gcpoidc;
22

3+
import com.uid2.shared.secure.AttestationClientException;
34
import com.uid2.shared.secure.AttestationException;
5+
import com.uid2.shared.secure.AttestationFailure;
46
import org.junit.jupiter.api.Test;
7+
import static org.junit.Assert.assertThat;
8+
import static org.hamcrest.CoreMatchers.instanceOf;
59

610
import java.util.HashMap;
711
import java.util.List;
@@ -28,7 +32,9 @@ public void testValidationFailure_MissRequiredEnvProd() {
2832
var newPayload = payload.toBuilder()
2933
.envOverrides(envOverrides)
3034
.build();
31-
assertThrows(AttestationException.class, ()-> validator.validate(newPayload));
35+
var e = assertThrows(AttestationException.class, ()-> validator.validate(newPayload));
36+
assertThat(e, instanceOf(AttestationClientException.class));
37+
assertEquals(AttestationFailure.BAD_FORMAT, ((AttestationClientException)e).getAttestationFailure());
3238
}
3339

3440
@Test
@@ -40,7 +46,8 @@ public void testValidationFailure_UnknownEnv() {
4046
var newPayload = payload.toBuilder()
4147
.envOverrides(envOverrides)
4248
.build();
43-
assertThrows(AttestationException.class, ()-> validator.validate(newPayload));
49+
var e = assertThrows(AttestationException.class, ()-> validator.validate(newPayload));
50+
assertEquals(AttestationFailure.BAD_FORMAT, ((AttestationClientException)e).getAttestationFailure());
4451
}
4552

4653
@Test
@@ -66,7 +73,8 @@ public void testValidationFailure_ExtraEnvOverride(){
6673
var newPayload = payload.toBuilder()
6774
.envOverrides(envOverrides)
6875
.build();
69-
assertThrows(AttestationException.class, ()-> validator.validate(newPayload));
76+
var e = assertThrows(AttestationException.class, ()-> validator.validate(newPayload));
77+
assertEquals(AttestationFailure.BAD_FORMAT, ((AttestationClientException)e).getAttestationFailure());
7078
}
7179

7280
@Test
@@ -75,7 +83,8 @@ public void testValidationFailure_NotConfidentialSpace(){
7583
var payload = generateBasicPayload().toBuilder()
7684
.swName("dummy")
7785
.build();
78-
assertThrows(AttestationException.class, ()-> validator.validate(payload));
86+
var e = assertThrows(AttestationException.class, ()-> validator.validate(payload));
87+
assertEquals(AttestationFailure.BAD_FORMAT, ((AttestationClientException)e).getAttestationFailure());
7988
}
8089

8190
@Test
@@ -84,7 +93,8 @@ public void testValidationFailure_EURegion(){
8493
var payload = generateBasicPayload().toBuilder()
8594
.gceZone("europe-north1-a")
8695
.build();
87-
assertThrows(AttestationException.class, ()-> validator.validate(payload));
96+
var e = assertThrows(AttestationException.class, ()-> validator.validate(payload));
97+
assertEquals(AttestationFailure.BAD_FORMAT, ((AttestationClientException)e).getAttestationFailure());
8898
}
8999

90100
@Test
@@ -93,7 +103,8 @@ public void testValidationFailure_NotStableConfidentialSpace(){
93103
var payload = generateBasicPayload().toBuilder()
94104
.csSupportedAttributes(null)
95105
.build();
96-
assertThrows(AttestationException.class, ()-> validator.validate(payload));
106+
var e = assertThrows(AttestationException.class, ()-> validator.validate(payload));
107+
assertEquals(AttestationFailure.BAD_FORMAT, ((AttestationClientException)e).getAttestationFailure());
97108
}
98109

99110
@Test
@@ -102,7 +113,8 @@ public void testValidationFailure_NoRestartPolicy(){
102113
var payload = generateBasicPayload().toBuilder()
103114
.restartPolicy("")
104115
.build();
105-
assertThrows(AttestationException.class, ()-> validator.validate(payload));
116+
var e = assertThrows(AttestationException.class, ()-> validator.validate(payload));
117+
assertEquals(AttestationFailure.BAD_FORMAT, ((AttestationClientException)e).getAttestationFailure());
106118
}
107119

108120
@Test
@@ -155,6 +167,8 @@ public void testValidationFailure_DifferentAttestationUrl() {
155167
var payload = generateBasicPayload();
156168
Throwable t = assertThrows(AttestationException.class, ()-> validator.validate(payload));
157169
assertEquals("The given attestation URL is unknown. Given URL: " + attestationUrl, t.getMessage());
170+
assertEquals(AttestationFailure.UNKNOWN_ATTESTATION_URL, ((AttestationClientException)t).getAttestationFailure());
171+
158172
}
159173

160174
@Test

0 commit comments

Comments
 (0)