Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public Optional<AuthorizationError> isAuthorizedOnExecutionWithDetailedIssue(fin
return Optional.of(GET_CHAIN_DEAL_FAILED);
}

final boolean isTeeTaskOnchain = TeeUtils.isTeeTag(chainDeal.getTag());
final boolean isTeeTaskOnchain = TeeUtils.getTeeFramework(chainDeal.getTag()) != null;
if (!isTeeTaskOnchain) {
log.error("Could not match onchain task type [isTeeTaskOnchain:{}, chainTaskId:{}]",
isTeeTaskOnchain, chainTaskId);
Expand Down
21 changes: 11 additions & 10 deletions src/main/java/com/iexec/sms/ssl/SslConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
import com.iexec.sms.tee.ConditionalOnTeeFramework;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.net.ssl.SSLContext;
Expand All @@ -35,7 +36,7 @@
@Slf4j
@Value
@ConfigurationProperties(prefix = "tee.ssl")
@ConditionalOnTeeFramework(frameworks = TeeFramework.SCONE)
@ConditionalOnTeeFramework(frameworks = {TeeFramework.SCONE, TeeFramework.TDX})
public class SslConfig {

String keystore;
Expand All @@ -48,14 +49,14 @@
*/
public SSLContext getFreshSslContext() {
try {
return SSLContexts.custom()
.setKeyStoreType(keystoreType)
.loadKeyMaterial(new File(keystore),
keystorePassword,
keystorePassword,
(aliases, socket) -> keyAlias)
.loadTrustMaterial(null, (chain, authType) -> true) //TODO: Add CAS certificate to truststore
.build();
final SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
if (!StringUtils.isEmpty(keystore)) {
sslContextBuilder.setKeyStoreType(keystoreType).loadKeyMaterial(
new File(keystore), keystorePassword, keystorePassword,
((aliases, sslParameters) -> keyAlias));
}
sslContextBuilder.loadTrustMaterial(null, (chain, authType) -> true); //TODO: Add CAS certificate to truststore

Check warning on line 58 in src/main/java/com/iexec/sms/ssl/SslConfig.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this TODO comment.

See more on https://sonarcloud.io/project/issues?id=com.iexec.sms%3Aiexec-sms&issues=AZrjooolj_-tlNf2Saeq&open=AZrjooolj_-tlNf2Saeq&pullRequest=320
return sslContextBuilder.build();
} catch (IOException | NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException |
CertificateException | KeyManagementException e) {
log.warn("Failed to create a fresh SSL context", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ public Map<String, TeeServicesProperties> sconeServicesPropertiesMap(
@ConditionalOnTeeFramework(frameworks = TeeFramework.TDX)
public Map<String, TeeServicesProperties> tdxServicesPropertiesMap(
final TeeWorkerPipelineConfiguration pipelineConfig) {
if (pipelineConfig.getPipelines().size() != 1) {
throw new IllegalStateException("Only a singleton pipeline list is currently supported for TDX");
}
return pipelineConfig.getPipelines().stream()
.map(pipeline -> new TdxServicesProperties(
pipeline.version(),
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/com/iexec/sms/tee/session/TeeSessionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,19 @@ public TeeSessionGenerationResponse generateTeeSession(
}

final TeeEnclaveConfiguration teeEnclaveConfiguration = taskDescription.getAppEnclaveConfiguration();
if (teeEnclaveConfiguration == null) {
if (taskDescription.requiresSgx() && teeEnclaveConfiguration == null) {
throw new TeeSessionGenerationException(
APP_COMPUTE_NO_ENCLAVE_CONFIG,
String.format("TEE enclave configuration can't be null [taskId:%s]", taskId));
}

final TeeServicesProperties teeServicesProperties;

try {
teeServicesProperties = resolveTeeServiceProperties(teeEnclaveConfiguration.getVersion());
if (taskDescription.requiresSgx()) {
teeServicesProperties = resolveTeeServiceProperties(teeEnclaveConfiguration.getVersion());
} else {
teeServicesProperties = teeServicesPropertiesMap.values().stream().findFirst().orElseThrow();
}
} catch (NoSuchElementException e) {
// TODO Add appropriate error type
throw new TeeSessionGenerationException(
Expand All @@ -94,7 +97,6 @@ public TeeSessionGenerationResponse generateTeeSession(
String.format("TEE framework can't be null [taskId:%s]", taskId));
}

// /!\ TODO clean expired tasks sessions
final String secretProvisioningUrl = teeSessionHandler.buildAndPostSession(request);
return new TeeSessionGenerationResponse(sessionId, secretProvisioningUrl);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,20 +308,22 @@ SecretEnclaveBase getAppTokens(final TeeSessionRequest request) throws TeeSessio
final TaskDescription taskDescription = request.getTaskDescription();

final Map<String, String> tokens = new HashMap<>();
final TeeEnclaveConfiguration enclaveConfig = taskDescription.getAppEnclaveConfiguration();
if (enclaveConfig == null) {
throw new TeeSessionGenerationException(
APP_COMPUTE_NO_ENCLAVE_CONFIG,
"Enclave configuration must not be null");
}
if (!enclaveConfig.getValidator().isValid()) {
throw new TeeSessionGenerationException(
APP_COMPUTE_INVALID_ENCLAVE_CONFIG,
"Invalid enclave configuration: " +
enclaveConfig.getValidator().validate().toString());
}
if (taskDescription.requiresSgx()) {
final TeeEnclaveConfiguration enclaveConfig = taskDescription.getAppEnclaveConfiguration();
if (enclaveConfig == null) {
throw new TeeSessionGenerationException(
APP_COMPUTE_NO_ENCLAVE_CONFIG,
"Enclave configuration must not be null");
}
if (!enclaveConfig.getValidator().isValid()) {
throw new TeeSessionGenerationException(
APP_COMPUTE_INVALID_ENCLAVE_CONFIG,
"Invalid enclave configuration: " +
enclaveConfig.getValidator().validate().toString());
}

enclaveBase.mrenclave(enclaveConfig.getFingerprint());
enclaveBase.mrenclave(enclaveConfig.getFingerprint());
}

final Map<String, String> computeSecrets = getApplicationComputeSecrets(taskDescription);
tokens.putAll(computeSecrets);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,40 @@

package com.iexec.sms.tee.session.tdx;

import com.iexec.common.utils.FeignBuilder;
import com.iexec.commons.poco.tee.TeeFramework;
import com.iexec.sms.api.TeeSessionGenerationError;
import com.iexec.sms.ssl.SslConfig;
import com.iexec.sms.tee.ConditionalOnTeeFramework;
import com.iexec.sms.tee.session.generic.TeeSessionGenerationException;
import com.iexec.sms.tee.session.generic.TeeSessionHandler;
import com.iexec.sms.tee.session.generic.TeeSessionRequest;
import com.iexec.sms.tee.session.tdx.storage.TdxSession;
import com.iexec.sms.tee.session.tdx.storage.TdxSessionStorageApiClient;
import com.iexec.sms.tee.session.tdx.storage.TdxSessionStorageConfiguration;
import feign.Client;
import feign.Logger;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.springframework.stereotype.Service;

@Service
@ConditionalOnTeeFramework(frameworks = TeeFramework.TDX)
public class TdxSessionHandlerService implements TeeSessionHandler {
private final TdxSessionMakerService sessionService;
private final TdxSessionStorageConfiguration storageConfiguration;
private final TdxSessionStorageApiClient storageClient;

public TdxSessionHandlerService(
final SslConfig sslConfig,
final TdxSessionMakerService sessionService,
final TdxSessionStorageConfiguration storageConfiguration) {
this.sessionService = sessionService;
this.storageConfiguration = storageConfiguration;
this.storageClient = FeignBuilder.createBuilder(Logger.Level.FULL)
.client(new Client.Default(sslConfig.getFreshSslContext().getSocketFactory(), NoopHostnameVerifier.INSTANCE))
.target(TdxSessionStorageApiClient.class, storageConfiguration.getPostUrl());
}

/**
* Build and post secret session on secret provisioning service.
*
Expand All @@ -36,9 +59,15 @@ public class TdxSessionHandlerService implements TeeSessionHandler {
*/
@Override
public String buildAndPostSession(final TeeSessionRequest request) throws TeeSessionGenerationException {
throw new TeeSessionGenerationException(
TeeSessionGenerationError.SECURE_SESSION_STORAGE_CALL_FAILED,
"Not implemented yet"
);
final TdxSession session = sessionService.generateSession(request);

try {
storageClient.postSession(session);
return storageConfiguration.getRemoteAttestationUrl();
} catch (Exception e) {
throw new TeeSessionGenerationException(
TeeSessionGenerationError.SECURE_SESSION_STORAGE_CALL_FAILED,
"Failed to post session: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2025 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.iexec.sms.tee.session.tdx;

import com.iexec.commons.poco.tee.TeeFramework;
import com.iexec.sms.api.config.TeeAppProperties;
import com.iexec.sms.tee.ConditionalOnTeeFramework;
import com.iexec.sms.tee.session.base.SecretEnclaveBase;
import com.iexec.sms.tee.session.base.SecretSessionBase;
import com.iexec.sms.tee.session.base.SecretSessionBaseService;
import com.iexec.sms.tee.session.generic.TeeSessionGenerationException;
import com.iexec.sms.tee.session.generic.TeeSessionRequest;
import com.iexec.sms.tee.session.tdx.storage.TdxSession;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
@ConditionalOnTeeFramework(frameworks = TeeFramework.TDX)
public class TdxSessionMakerService {
public static final String TDX_SESSION_VERSION = "0.1.0";
private final SecretSessionBaseService secretSessionBaseService;

public TdxSessionMakerService(final SecretSessionBaseService secretSessionBaseService) {
this.secretSessionBaseService = secretSessionBaseService;
}

public TdxSession generateSession(final TeeSessionRequest request) throws TeeSessionGenerationException {
final SecretSessionBase baseSession = secretSessionBaseService.getSecretsTokens(request);
final List<TdxSession.Service> tdxEnclaves = new ArrayList<>();
if (baseSession.getPreCompute() != null) {
tdxEnclaves.add(toTdxEnclave(baseSession.getPreCompute(), request.getTeeServicesProperties().getPreComputeProperties()));
}
// FIXME fingerprint should be dapp checksum from TaskDescription after commons-poco update

Check warning on line 49 in src/main/java/com/iexec/sms/tee/session/tdx/TdxSessionMakerService.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Take the required action to fix the issue indicated by this comment.

See more on https://sonarcloud.io/project/issues?id=com.iexec.sms%3Aiexec-sms&issues=AZrjoolkj_-tlNf2Saep&open=AZrjoolkj_-tlNf2Saep&pullRequest=320
tdxEnclaves.add(toTdxEnclave(baseSession.getAppCompute(), request.getTaskDescription().getAppUri(), ""));
tdxEnclaves.add(toTdxEnclave(baseSession.getPostCompute(), request.getTeeServicesProperties().getPostComputeProperties()));
return new TdxSession(request.getSessionId(), TDX_SESSION_VERSION, List.copyOf(tdxEnclaves));
}

private TdxSession.Service toTdxEnclave(final SecretEnclaveBase enclaveBase, final TeeAppProperties teeAppProperties) {
return toTdxEnclave(enclaveBase, teeAppProperties.getImage(), teeAppProperties.getFingerprint());
}

private TdxSession.Service toTdxEnclave(final SecretEnclaveBase enclaveBase, final String image_name, final String fingerprint) {
return new TdxSession.Service(
enclaveBase.getName(), image_name, fingerprint, enclaveBase.getEnvironment()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2025 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.iexec.sms.tee.session.tdx.storage;

import java.util.List;
import java.util.Map;

public record TdxSession(String name, String version, List<Service> services) {
public record Service(String name, String image_name, String fingerprint, Map<String, String> environment) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2025 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.iexec.sms.tee.session.tdx.storage;

import feign.RequestLine;

public interface TdxSessionStorageApiClient {
@RequestLine("POST /session")
String postSession(TdxSession tdxSession);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2025 IEXEC BLOCKCHAIN TECH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.iexec.sms.tee.session.tdx.storage;

import com.iexec.commons.poco.tee.TeeFramework;
import com.iexec.sms.tee.ConditionalOnTeeFramework;
import lombok.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Value
@ConfigurationProperties(prefix = "tee.secret-provisioner")
@ConditionalOnTeeFramework(frameworks = TeeFramework.TDX)
public class TdxSessionStorageConfiguration {
String postUrl;
String remoteAttestationUrl;
}
Loading