Skip to content

Commit 940182e

Browse files
authored
Use AuthorizationService to validate Authorization header of /tee/challenges/{chainTaskId} endpoint (#256)
1 parent 7563cd5 commit 940182e

File tree

5 files changed

+131
-72
lines changed

5 files changed

+131
-72
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file.
66

77
### New Features
88

9-
- Add `Authorization` header on `/tee/challenges/{chainTaskId}` endpoint. (#255)
9+
- Add `Authorization` header on `/tee/challenges/{chainTaskId}` endpoint. (#255 #256)
1010

1111
### Quality
1212

src/main/java/com/iexec/sms/authorization/AuthorizationService.java

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.iexec.sms.authorization;
1818

19-
2019
import com.iexec.commons.poco.chain.ChainDeal;
2120
import com.iexec.commons.poco.chain.ChainTask;
2221
import com.iexec.commons.poco.chain.ChainTaskStatus;
@@ -49,52 +48,49 @@ public AuthorizationService(IexecHubService iexecHubService) {
4948

5049
/**
5150
* Checks whether this execution is authorized.
52-
* If not authorized, return the reason.
53-
* Otherwise, returns an empty {@link Optional}.
51+
*
52+
* @param workerpoolAuthorization The workerpool authorization to check
53+
* @return {@code Optional.empty()} if all checks passed, the failure reason otherwise
5454
*/
55-
public Optional<AuthorizationError> isAuthorizedOnExecutionWithDetailedIssue(WorkerpoolAuthorization workerpoolAuthorization, boolean isTeeTask) {
55+
public Optional<AuthorizationError> isAuthorizedOnExecutionWithDetailedIssue(WorkerpoolAuthorization workerpoolAuthorization) {
5656
if (workerpoolAuthorization == null || StringUtils.isEmpty(workerpoolAuthorization.getChainTaskId())) {
5757
log.error("Not authorized with empty params");
5858
return Optional.of(EMPTY_PARAMS_UNAUTHORIZED);
5959
}
6060

61-
String chainTaskId = workerpoolAuthorization.getChainTaskId();
62-
Optional<ChainTask> optionalChainTask = iexecHubService.getChainTask(chainTaskId);
63-
if (optionalChainTask.isEmpty()) {
61+
final String chainTaskId = workerpoolAuthorization.getChainTaskId();
62+
final ChainTask chainTask = iexecHubService.getChainTask(chainTaskId).orElse(null);
63+
if (chainTask == null) {
6464
log.error("Could not get chainTask [chainTaskId:{}]", chainTaskId);
6565
return Optional.of(GET_CHAIN_TASK_FAILED);
6666
}
67-
ChainTask chainTask = optionalChainTask.get();
68-
ChainTaskStatus taskStatus = chainTask.getStatus();
69-
String chainDealId = chainTask.getDealid();
67+
final String chainDealId = chainTask.getDealid();
7068

71-
if (taskStatus != ChainTaskStatus.ACTIVE) {
72-
log.error("Task not active onchain [chainTaskId:{}, status:{}]",
73-
chainTaskId, taskStatus);
69+
if (chainTask.getStatus() != ChainTaskStatus.ACTIVE) {
70+
log.error("Task not active on chain [chainTaskId:{}, status:{}]",
71+
chainTaskId, chainTask.getStatus());
7472
return Optional.of(TASK_NOT_ACTIVE);
7573
}
7674

77-
Optional<ChainDeal> optionalChainDeal = iexecHubService.getChainDeal(chainDealId);
78-
if (optionalChainDeal.isEmpty()) {
75+
final ChainDeal chainDeal = iexecHubService.getChainDeal(chainDealId).orElse(null);
76+
if (chainDeal == null) {
7977
log.error("isAuthorizedOnExecution failed (getChainDeal failed) [chainTaskId:{}]", chainTaskId);
8078
return Optional.of(GET_CHAIN_DEAL_FAILED);
8179
}
82-
ChainDeal chainDeal = optionalChainDeal.get();
8380

84-
boolean isTeeTaskOnchain = TeeUtils.isTeeTag(chainDeal.getTag());
85-
if (isTeeTask != isTeeTaskOnchain) {
86-
log.error("Could not match onchain task type [isTeeTask:{}, isTeeTaskOnchain:{}, chainTaskId:{}, walletAddress:{}]",
87-
isTeeTask, isTeeTaskOnchain, chainTaskId, workerpoolAuthorization.getWorkerWallet());
81+
final boolean isTeeTaskOnchain = TeeUtils.isTeeTag(chainDeal.getTag());
82+
if (!isTeeTaskOnchain) {
83+
log.error("Could not match onchain task type [isTeeTaskOnchain:{}, chainTaskId:{}]",
84+
isTeeTaskOnchain, chainTaskId);
8885
return Optional.of(NO_MATCH_ONCHAIN_TYPE);
8986
}
9087

91-
String workerpoolAddress = chainDeal.getPoolOwner();
92-
boolean isSignerByWorkerpool = isSignedByHimself(workerpoolAuthorization.getHash(),
93-
workerpoolAuthorization.getSignature().getValue(), workerpoolAddress);
88+
final boolean isSignedByWorkerpool = isSignedByHimself(workerpoolAuthorization.getHash(),
89+
workerpoolAuthorization.getSignature().getValue(), chainDeal.getPoolOwner());
9490

95-
if (!isSignerByWorkerpool) {
96-
log.error("isAuthorizedOnExecution failed (invalid signature) [chainTaskId:{}, isWorkerpoolSignatureValid:{}]",
97-
chainTaskId, isSignerByWorkerpool);
91+
if (!isSignedByWorkerpool) {
92+
log.error("isAuthorizedOnExecution failed (invalid signature) [chainTaskId:{}, isSignedByWorkerpool:{}]",
93+
chainTaskId, isSignedByWorkerpool);
9894
return Optional.of(INVALID_SIGNATURE);
9995
}
10096

@@ -110,14 +106,6 @@ public boolean isSignedByOwner(String message, String signature, String address)
110106
String owner = iexecHubService.getOwner(address);
111107
return !owner.isEmpty() && isSignedByHimself(message, signature, owner);
112108
}
113-
114-
public String getChallengeForSetWeb3Secret(String secretAddress,
115-
String secretValue) {
116-
return HashUtils.concatenateAndHash(
117-
Hash.sha3String(DOMAIN),
118-
secretAddress,
119-
Hash.sha3String(secretValue));
120-
}
121109
// endregion
122110

123111
// region challenges
@@ -152,6 +140,14 @@ public String getChallengeForSetWeb2Secret(String ownerAddress,
152140
Hash.sha3String(secretValue));
153141
}
154142

143+
public String getChallengeForSetWeb3Secret(String secretAddress,
144+
String secretValue) {
145+
return HashUtils.concatenateAndHash(
146+
Hash.sha3String(DOMAIN),
147+
secretAddress,
148+
Hash.sha3String(secretValue));
149+
}
150+
155151
public String getChallengeForWorker(WorkerpoolAuthorization workerpoolAuthorization) {
156152
return HashUtils.concatenateAndHash(
157153
workerpoolAuthorization.getWorkerWallet(),

src/main/java/com/iexec/sms/tee/TeeController.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 IEXEC BLOCKCHAIN TECH
2+
* Copyright 2020-2024 IEXEC BLOCKCHAIN TECH
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,13 +19,13 @@
1919

2020
import com.iexec.common.web.ApiResponseBody;
2121
import com.iexec.commons.poco.chain.WorkerpoolAuthorization;
22+
import com.iexec.commons.poco.security.Signature;
2223
import com.iexec.commons.poco.tee.TeeFramework;
2324
import com.iexec.sms.api.TeeSessionGenerationError;
2425
import com.iexec.sms.api.TeeSessionGenerationResponse;
2526
import com.iexec.sms.api.config.TeeServicesProperties;
2627
import com.iexec.sms.authorization.AuthorizationError;
2728
import com.iexec.sms.authorization.AuthorizationService;
28-
import com.iexec.sms.tee.challenge.TeeChallenge;
2929
import com.iexec.sms.tee.challenge.TeeChallengeService;
3030
import com.iexec.sms.tee.session.TeeSessionService;
3131
import com.iexec.sms.tee.session.generic.TeeSessionGenerationException;
@@ -111,11 +111,19 @@ public ResponseEntity<TeeServicesProperties> getTeeServicesProperties(
111111
*/
112112
@PostMapping("/challenges/{chainTaskId}")
113113
public ResponseEntity<String> generateTeeChallenge(@RequestHeader String authorization, @PathVariable String chainTaskId) {
114-
Optional<TeeChallenge> executionChallenge =
115-
teeChallengeService.getOrCreate(chainTaskId, false);
116-
return executionChallenge
117-
.map(teeChallenge -> ResponseEntity
118-
.ok(teeChallenge.getCredentials().getAddress()))
114+
log.debug("generateTeeChallenge [authorization:{}, chainTaskId:{}]", authorization, chainTaskId);
115+
final Optional<AuthorizationError> authorizationError = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(
116+
WorkerpoolAuthorization.builder()
117+
.chainTaskId(chainTaskId)
118+
.enclaveChallenge("")
119+
.workerWallet("")
120+
.signature(new Signature(authorization))
121+
.build());
122+
if (authorizationError.isPresent()) {
123+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
124+
}
125+
return teeChallengeService.getOrCreate(chainTaskId, false)
126+
.map(teeChallenge -> ResponseEntity.ok(teeChallenge.getCredentials().getAddress()))
119127
.orElseGet(() -> ResponseEntity.notFound().build());
120128
}
121129

@@ -149,7 +157,7 @@ public ResponseEntity<ApiResponseBody<TeeSessionGenerationResponse, TeeSessionGe
149157
.body(body);
150158
}
151159
final Optional<AuthorizationError> authorizationError =
152-
authorizationService.isAuthorizedOnExecutionWithDetailedIssue(workerpoolAuthorization, true);
160+
authorizationService.isAuthorizedOnExecutionWithDetailedIssue(workerpoolAuthorization);
153161
if (authorizationError.isPresent()) {
154162
final TeeSessionGenerationError teeSessionGenerationError =
155163
authorizationToGenerationError.get(authorizationError.get());

src/test/java/com/iexec/sms/authorization/AuthorizationServiceTests.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.iexec.commons.poco.chain.WorkerpoolAuthorization;
2222
import com.iexec.commons.poco.security.Signature;
2323
import com.iexec.commons.poco.tee.TeeUtils;
24+
import com.iexec.commons.poco.utils.BytesUtils;
2425
import com.iexec.commons.poco.utils.TestUtils;
2526
import com.iexec.sms.blockchain.IexecHubService;
2627
import org.junit.jupiter.api.Assertions;
@@ -60,33 +61,36 @@ void shouldBeAuthorizedOnExecutionOfTeeTaskWithDetails() {
6061
when(iexecHubService.getChainTask(auth.getChainTaskId())).thenReturn(Optional.of(chainTask));
6162
when(iexecHubService.getChainDeal(chainTask.getDealid())).thenReturn(Optional.of(chainDeal));
6263

63-
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth, true);
64+
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth);
6465
assertThat(isAuth).isEmpty();
6566
}
6667

6768
@Test
6869
void shouldNotBeAuthorizedOnExecutionOfTeeTaskWithNullAuthorizationWithDetails() {
69-
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(null, true);
70+
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(null);
7071
assertThat(isAuth).isNotEmpty()
7172
.contains(EMPTY_PARAMS_UNAUTHORIZED);
7273
}
7374

7475
@Test
7576
void shouldNotBeAuthorizedOnExecutionOfTeeTaskWithEmptyAuthorizationWithDetails() {
76-
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(WorkerpoolAuthorization.builder().build(), true);
77+
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(WorkerpoolAuthorization.builder().build());
7778
assertThat(isAuth).isNotEmpty()
7879
.contains(EMPTY_PARAMS_UNAUTHORIZED);
7980
}
8081

8182
@Test
82-
void shouldNotBeAuthorizedOnExecutionOfTeeTaskWhenTaskTypeNotMatchedOnchainWithDetails() {
83-
ChainDeal chainDeal = getChainDeal();
83+
void shouldNotBeAuthorizedOnExecutionOfTeeTaskWhenTaskTypeNotTeeOnchainWithDetails() {
84+
ChainDeal chainDeal = ChainDeal.builder()
85+
.poolOwner("0xc911f9345717ba7c8ec862ce002af3e058df84e4")
86+
.tag(BytesUtils.EMPTY_HEX_STRING_32)
87+
.build();
8488
ChainTask chainTask = TestUtils.getChainTask(ACTIVE);
8589
WorkerpoolAuthorization auth = TestUtils.getTeeWorkerpoolAuth();
8690
when(iexecHubService.getChainTask(auth.getChainTaskId())).thenReturn(Optional.of(chainTask));
8791
when(iexecHubService.getChainDeal(chainTask.getDealid())).thenReturn(Optional.of(chainDeal));
8892

89-
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth, false);
93+
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth);
9094
assertThat(isAuth).isNotEmpty()
9195
.contains(NO_MATCH_ONCHAIN_TYPE);
9296
}
@@ -97,7 +101,7 @@ void shouldNotBeAuthorizedOnExecutionOfTeeTaskWhenGetTaskFailedWithDetails() {
97101
when(iexecHubService.isTeeTask(auth.getChainTaskId())).thenReturn(true);
98102
when(iexecHubService.getChainTask(auth.getChainTaskId())).thenReturn(Optional.empty());
99103

100-
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth, true);
104+
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth);
101105
assertThat(isAuth).isNotEmpty()
102106
.contains(GET_CHAIN_TASK_FAILED);
103107
}
@@ -109,7 +113,7 @@ void shouldNotBeAuthorizedOnExecutionOfTeeTaskWhenTaskNotActiveWithDetails() {
109113
when(iexecHubService.isTeeTask(auth.getChainTaskId())).thenReturn(true);
110114
when(iexecHubService.getChainTask(auth.getChainTaskId())).thenReturn(Optional.of(chainTask));
111115

112-
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth, true);
116+
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth);
113117
assertThat(isAuth).isNotEmpty()
114118
.contains(TASK_NOT_ACTIVE);
115119
}
@@ -124,7 +128,7 @@ void shouldNotBeAuthorizedOnExecutionOfTeeTaskWhenGetDealFailedWithDetails() {
124128
when(iexecHubService.getChainTask(auth.getChainTaskId())).thenReturn(Optional.of(chainTask));
125129
when(iexecHubService.getChainDeal(chainTask.getDealid())).thenReturn(Optional.empty());
126130

127-
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth, true);
131+
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth);
128132
assertThat(isAuth).isNotEmpty()
129133
.contains(GET_CHAIN_DEAL_FAILED);
130134
}
@@ -139,7 +143,7 @@ void shouldNotBeAuthorizedOnExecutionOfTeeTaskWhenPoolSignatureIsNotValidWithDet
139143
when(iexecHubService.getChainTask(auth.getChainTaskId())).thenReturn(Optional.of(chainTask));
140144
when(iexecHubService.getChainDeal(chainTask.getDealid())).thenReturn(Optional.of(chainDeal));
141145

142-
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth, true);
146+
Optional<AuthorizationError> isAuth = authorizationService.isAuthorizedOnExecutionWithDetailedIssue(auth);
143147
assertThat(isAuth).isNotEmpty()
144148
.contains(INVALID_SIGNATURE);
145149
}

0 commit comments

Comments
 (0)