Skip to content

Commit 6b8c1e8

Browse files
authored
Add configurable cron job to delete expired tasks TEE challenges and Ethereum credentials (#278)
1 parent c4d34e3 commit 6b8c1e8

File tree

10 files changed

+129
-36
lines changed

10 files changed

+129
-36
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
99
- Accept scheduler default result-proxy as a web2 secret to fallback on it when no proxy
1010
is specified in deal parameters. (#273)
1111
- Configure the SMS at startup to generate Scone sessions in Hardware or MAA mode. (#275)
12+
- Add configurable cron job to delete expired tasks TEE challenges and Ethereum credentials. (#278)
1213

1314
### Quality
1415

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ To support:
6565
| `IEXEC_SECRET_PROVISIONER_WEB_PORT` | Secret provisioner server port for session management. | Positive integer | `8081` | `8080` |
6666
| `IEXEC_SECRET_PROVISIONER_ENCLAVE_HOSTNAME` | Secret provisioner server host for retrieving secrets from attested enclaves. Typically used by workers to execute TEE tasks. | Positive integer | `localhost` | `localhost` |
6767
| `IEXEC_SECRET_PROVISIONER_ENCLAVE_PORT`| Secret provisioner server port for retrieving secrets from attested enclaves. | Positive integer | `18765` | `4433` |
68+
| `IEXEC_TEE_CHALLENGE_CLEANUP_CRON` | Cron expression to configure TEE challenges cleanup policy. | String | `@hourly` | `@hourly` |
6869
| `IEXEC_TEE_WORKER_PRE_COMPUTE_IMAGE` | TEE enabled OCI image name for worker pre-compute stage of TEE tasks. | String | | |
6970
| `IEXEC_TEE_WORKER_PRE_COMPUTE_FINGERPRINT` | Fingerprint (aka mrenclave) of the TEE enabled worker pre-compute image. | String | | |
7071
| `IEXEC_TEE_WORKER_PRE_COMPUTE_HEAP_SIZE_GB` | Required heap size for a worker pre-compute enclave (in Giga Bytes). | Positive integer | `3` | `3` |

src/main/java/com/iexec/sms/App.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020 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,7 +19,9 @@
1919
import org.springframework.boot.SpringApplication;
2020
import org.springframework.boot.autoconfigure.SpringBootApplication;
2121
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
22+
import org.springframework.scheduling.annotation.EnableScheduling;
2223

24+
@EnableScheduling
2325
@SpringBootApplication
2426
@ConfigurationPropertiesScan
2527
public class App {

src/main/java/com/iexec/sms/tee/challenge/EthereumCredentials.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import javax.persistence.Entity;
2929
import javax.persistence.GeneratedValue;
3030
import javax.persistence.Id;
31+
import java.security.GeneralSecurityException;
3132

3233
/**
3334
* Domain entity
@@ -61,10 +62,9 @@ private EthereumCredentials(String privateKey, String address) {
6162
* secure random source).
6263
*
6364
* @return Ethereum credentials
64-
* @throws java.security.GeneralSecurityException exception if failed to
65-
* generate credentials
65+
* @throws GeneralSecurityException exception if credentials generation failed
6666
*/
67-
public static EthereumCredentials generate() throws java.security.GeneralSecurityException {
67+
public static EthereumCredentials generate() throws GeneralSecurityException {
6868
ECKeyPair randomEcKeyPair = Keys.createEcKeyPair();
6969
String privateKey =
7070
Numeric.toHexStringWithPrefixZeroPadded(randomEcKeyPair.getPrivateKey(),

src/main/java/com/iexec/sms/tee/challenge/TeeChallenge.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import org.hibernate.annotations.GenericGenerator;
2424

2525
import javax.persistence.*;
26+
import java.security.GeneralSecurityException;
27+
import java.time.Instant;
2628

2729
@Entity
2830
@Getter
@@ -38,11 +40,14 @@ public class TeeChallenge {
3840

3941
private String taskId;
4042

43+
private Instant finalDeadline;
44+
4145
@OneToOne(cascade = {CascadeType.ALL})
4246
private EthereumCredentials credentials;
4347

44-
public TeeChallenge(String taskId) throws Exception {
48+
public TeeChallenge(final String taskId, final Instant finalDeadline) throws GeneralSecurityException {
4549
this.taskId = taskId;
4650
this.credentials = EthereumCredentials.generate();
51+
this.finalDeadline = finalDeadline;
4752
}
4853
}

src/main/java/com/iexec/sms/tee/challenge/TeeChallengeRepository.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@
1717
package com.iexec.sms.tee.challenge;
1818

1919
import org.springframework.data.jpa.repository.JpaRepository;
20+
import org.springframework.transaction.annotation.Transactional;
2021

22+
import java.time.Instant;
2123
import java.util.Optional;
2224

2325
public interface TeeChallengeRepository extends JpaRepository<TeeChallenge, String> {
2426
Optional<TeeChallenge> findByTaskId(String taskId);
27+
28+
@Transactional
29+
void deleteByFinalDeadlineBefore(Instant now);
2530
}

src/main/java/com/iexec/sms/tee/challenge/TeeChallengeService.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616

1717
package com.iexec.sms.tee.challenge;
1818

19+
import com.iexec.sms.blockchain.IexecHubService;
1920
import com.iexec.sms.encryption.EncryptionService;
2021
import com.iexec.sms.secret.MeasuredSecretService;
2122
import lombok.extern.slf4j.Slf4j;
23+
import org.springframework.scheduling.annotation.Scheduled;
2224
import org.springframework.stereotype.Service;
2325

26+
import java.time.Instant;
2427
import java.util.Optional;
2528

2629
@Slf4j
@@ -29,15 +32,18 @@ public class TeeChallengeService {
2932

3033
private final TeeChallengeRepository teeChallengeRepository;
3134
private final EncryptionService encryptionService;
35+
private final IexecHubService iexecHubService;
3236
private final MeasuredSecretService teeChallengesMeasuredSecretService;
3337
private final MeasuredSecretService ethereumCredentialsMeasuredSecretService;
3438

35-
public TeeChallengeService(TeeChallengeRepository teeChallengeRepository,
36-
EncryptionService encryptionService,
37-
MeasuredSecretService teeChallengeMeasuredSecretService,
38-
MeasuredSecretService ethereumCredentialsMeasuredSecretService) {
39+
public TeeChallengeService(final TeeChallengeRepository teeChallengeRepository,
40+
final EncryptionService encryptionService,
41+
final IexecHubService iexecHubService,
42+
final MeasuredSecretService teeChallengeMeasuredSecretService,
43+
final MeasuredSecretService ethereumCredentialsMeasuredSecretService) {
3944
this.teeChallengeRepository = teeChallengeRepository;
4045
this.encryptionService = encryptionService;
46+
this.iexecHubService = iexecHubService;
4147
this.teeChallengesMeasuredSecretService = teeChallengeMeasuredSecretService;
4248
this.ethereumCredentialsMeasuredSecretService = ethereumCredentialsMeasuredSecretService;
4349
}
@@ -54,7 +60,8 @@ public Optional<TeeChallenge> getOrCreate(String taskId, boolean shouldDecryptKe
5460

5561
// otherwise create it
5662
try {
57-
TeeChallenge teeChallenge = new TeeChallenge(taskId);
63+
final long finalDeadline = iexecHubService.getTaskDescription(taskId).getFinalDeadline();
64+
TeeChallenge teeChallenge = new TeeChallenge(taskId, Instant.ofEpochMilli(finalDeadline));
5865
encryptChallengeKeys(teeChallenge);
5966
teeChallenge = teeChallengeRepository.save(teeChallenge);
6067
teeChallengesMeasuredSecretService.newlyAddedSecret();
@@ -88,4 +95,16 @@ public void decryptChallengeKeys(TeeChallenge teeChallenge) {
8895
credentials.setPlainTextPrivateKey(privateKey);
8996
}
9097
}
98+
99+
/**
100+
* Clean expired tasks challenges at regular intervals.
101+
* <p>
102+
* The interval between two consecutive executions is based on the {@code @Scheduled} annotation
103+
* and its {@code cron} attribute.
104+
*/
105+
@Scheduled(cron = "${tee.challenge.cleanup.cron}")
106+
void cleanExpiredTasksTeeChallenges() {
107+
log.debug("cleanExpiredTasksTeeChallenges");
108+
teeChallengeRepository.deleteByFinalDeadlineBefore(Instant.now());
109+
}
91110
}

src/main/resources/application.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ metrics:
4545
storage:
4646
refresh-interval: ${IEXEC_SMS_METRICS_STORAGE_REFRESH_INTERVAL:30} # In seconds
4747

48-
# level:
49-
# org.springframework: DEBUG
50-
# org.apache.http: DEBUG
51-
5248
springdoc:
5349
packagesToScan: com.iexec.sms
5450
pathsToMatch: /**
51+
52+
tee:
53+
challenge.cleanup.cron: ${IEXEC_TEE_CHALLENGE_CLEANUP_CRON:@hourly}

src/test/java/com/iexec/sms/tee/TeeControllerTests.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
import org.web3j.crypto.Credentials;
4848
import org.web3j.crypto.Keys;
4949

50+
import java.security.GeneralSecurityException;
51+
import java.time.Instant;
5052
import java.util.Optional;
5153
import java.util.stream.Stream;
5254

@@ -241,15 +243,15 @@ void shouldNotGenerateTeeChallengeWhenExceptionDuringGeneration() {
241243
}
242244

243245
@Test
244-
void shouldGenerateTeeChallenge() throws Exception {
246+
void shouldGenerateTeeChallenge() throws GeneralSecurityException {
245247
final WorkerpoolAuthorization workerpoolAuthorization = WorkerpoolAuthorization
246248
.builder()
247249
.chainTaskId(TASK_ID)
248250
.enclaveChallenge("")
249251
.workerWallet("")
250252
.signature(new Signature(AUTHORIZATION))
251253
.build();
252-
final TeeChallenge teeChallenge = new TeeChallenge(TASK_ID);
254+
final TeeChallenge teeChallenge = new TeeChallenge(TASK_ID, Instant.now().plusMillis(1000));
253255
when(authorizationService.isAuthorizedOnExecutionWithDetailedIssue(workerpoolAuthorization))
254256
.thenReturn(Optional.empty());
255257
when(teeChallengeService.getOrCreate(TASK_ID, false)).thenReturn(Optional.of(teeChallenge));

0 commit comments

Comments
 (0)