diff --git a/.dockerignore b/.dockerignore index b86c7ac..774e56c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,6 @@ * +!src/main/docker/hashes.txt !target/*-runner !target/*-runner.jar -!target/lib/* \ No newline at end of file +!target/lib/* +!target/quarkus-app/* \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..8281c20 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,23 @@ +version: '3.9' +services: + application: + build: + context: . + dockerfile: ./src/main/docker/Dockerfile.jvm + ports: + - 8080:8080 + environment: + - NOTARIZATION_APPLEAPI_KEYFILE=/var/run/secrets/apple-api.json + volumes: + - ./config/application/apple-api.json:/var/run/secrets/apple-api.json + deploy: + restart_policy: + condition: on-failure + max_attempts: 3 + resources: + limits: + cpus: '0.5' + memory: 256M + reservations: + cpus: '0.001' + memory: 192M diff --git a/src/main/docker/Dockerfile.jvm b/src/main/docker/Dockerfile.jvm new file mode 100644 index 0000000..2eee3ec --- /dev/null +++ b/src/main/docker/Dockerfile.jvm @@ -0,0 +1,34 @@ +# +# Based on a base image defined in the EF dockerfile project under https://github.com/EclipseFdn/dockerfiles/blob/master/java-api-base/Dockerfile. +# +# This image centralizes the base image version as well as any security patches to reduce the need to update all APIs manually in case of vulnerabilities or minor updates. +# +FROM eclipsefdn/java-api-base:j17-openjdk + +# Install curl. +RUN microdnf --setopt=tsflags=nodocs install -y gzip + +WORKDIR /deployments/bin + +# Download apple-codesign tool and verify its hash +COPY src/main/docker/hashes.txt /deployments/bin/ + +ENV APPLE_CODESIGN_VERSION "0.26.0" +ENV APPLE_CODESIGN_ARCHIVE "apple-codesign-${APPLE_CODESIGN_VERSION}.tar.gz" + +RUN curl -L -o ${APPLE_CODESIGN_ARCHIVE} "https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F${APPLE_CODESIGN_VERSION}/apple-codesign-$APPLE_CODESIGN_VERSION-x86_64-unknown-linux-musl.tar.gz" \ + && sha256sum -c hashes.txt \ + && tar xzf ${APPLE_CODESIGN_ARCHIVE} --strip-components=1 \ + && rm -f ${APPLE_CODESIGN_ARCHIVE} \ + && chmod a+x rcodesign + +ENV PATH "${PATH}:/deployments/bin" + +# We make four distinct layers so if there are application changes the library layers can be re-used +COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ +COPY --chown=185 target/quarkus-app/*.jar /deployments/ +COPY --chown=185 target/quarkus-app/app/ /deployments/app/ +COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 185 \ No newline at end of file diff --git a/src/main/docker/hashes.txt b/src/main/docker/hashes.txt new file mode 100644 index 0000000..9a75fcf --- /dev/null +++ b/src/main/docker/hashes.txt @@ -0,0 +1 @@ +cc2458901b2e93e21f1a4cc19ecc19a71dc2867d4d5f3f974091dac9ee536b1c apple-codesign-0.26.0.tar.gz \ No newline at end of file diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/ApplicationLifecycle.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/ApplicationLifecycle.java index 07c4097..546cbee 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/ApplicationLifecycle.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/ApplicationLifecycle.java @@ -15,10 +15,14 @@ import java.util.Comparator; import java.util.stream.Stream; +import io.quarkus.runtime.Quarkus; +import io.quarkus.runtime.configuration.ConfigurationException; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationCredentials; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationTool; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,7 +39,15 @@ public class ApplicationLifecycle { @ConfigProperty(name = "notarization.cache.uploadedFiles", defaultValue = "/tmp/macos-notarization-service/pending-files") String pendingFiles; + @Inject + NotarizationTool notarizationTool; + + @Inject + NotarizationCredentials notarizationCredentials; + void onStart(@Observes StartupEvent ev) throws IOException { + validateNotarizationCredentials(); + Path pendingFilesPath = Paths.get(pendingFiles); if (!Files.isDirectory(pendingFilesPath)) { @@ -50,6 +62,13 @@ void onStart(@Observes StartupEvent ev) throws IOException { } } + private void validateNotarizationCredentials() { + if (!notarizationTool.validate(notarizationCredentials)) { + Quarkus.asyncExit(1); + Quarkus.waitForExit(); + } + } + void onStop(@Observes ShutdownEvent ev) { LOGGER.info("The application is stopping..."); } diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/NotarizationService.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/NotarizationService.java index 985de68..8a6a9d8 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/NotarizationService.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/NotarizationService.java @@ -19,7 +19,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledExecutorService; -import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.ws.rs.*; @@ -28,8 +27,10 @@ import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.ResponseBuilder; +import org.eclipse.cbi.ws.macos.notarization.execution.*; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; import org.eclipse.cbi.ws.macos.notarization.request.*; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.*; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; import org.slf4j.Logger; @@ -45,9 +46,15 @@ public class NotarizationService { @Inject NotarizationCache cache; + @Inject + NotarizationCredentials notarizationCredentials; + @Inject NotarizationTool notarizationTool; + @Inject + StaplerTool staplerTool; + @Inject @Named("macos-notarization-service-pool") ScheduledExecutorService executor; @@ -56,18 +63,6 @@ public class NotarizationService { @ConfigProperty(name = "notarization.cache.uploadedFiles", defaultValue = "/tmp/macos-notarization-service/pending-files") String pendingFilesPath; - @Inject - @ConfigProperty(name = "notarization.appleid.password") - String appleIDPassword; - - @Inject - @ConfigProperty(name = "notarization.appleid.username") - String appleIDUsername; - - @Inject - @ConfigProperty(name = "notarization.appleid.teamid") - String appleIDTeamID; - @Inject @ConfigProperty(name = "notarization.upload.timeout", defaultValue = "PT60M") Duration uploadTimeout; @@ -165,9 +160,7 @@ private NotarizationStatusWithUUID notarize(MultipartFormDataInputWrapper formDa requestBuilder.notarizer(() -> Notarizer.builder() .primaryBundleId(options.primaryBundleId()) - .appleIDUsername(appleIDUsername) - .appleIDPassword(appleIDPassword) - .appleIDTeamID(appleIDTeamID) + .credentials(notarizationCredentials) .fileToNotarize(fileToNotarize) .uploadTimeout(uploadTimeout) .tool(notarizationTool) @@ -176,9 +169,7 @@ private NotarizationStatusWithUUID notarize(MultipartFormDataInputWrapper formDa requestBuilder.notarizationInfo((NotarizerResult r) -> NotarizationInfo.builder() - .appleIDUsername(appleIDUsername) - .appleIDPassword(appleIDPassword) - .appleIDTeamID(appleIDTeamID) + .credentials(notarizationCredentials) .appleRequestUUID(r.appleRequestUUID()) .pollingTimeout(infoPollingTimeout) .tool(notarizationTool) @@ -191,6 +182,7 @@ private NotarizationStatusWithUUID notarize(MultipartFormDataInputWrapper formDa Stapler.builder() .fileToStaple(fileToNotarize) .staplingTimeout(staplingTimeout) + .tool(staplerTool) .build() .stapleFailsafe(staplingMaxAttempts, staplingMinBackOffDelay, staplingMaxBackOffDelay))); } diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/Producer.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/Producer.java index 58dce66..ea639c6 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/Producer.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/Producer.java @@ -16,8 +16,10 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationTool; -import org.eclipse.cbi.ws.macos.notarization.xcrun.notarytool.NotarytoolNotarizer; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationTool; +import org.eclipse.cbi.ws.macos.notarization.execution.StaplerTool; +import org.eclipse.cbi.ws.macos.notarization.execution.generic.RustNotarizer; +import org.eclipse.cbi.ws.macos.notarization.execution.generic.RustStapler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,6 +48,18 @@ public NotarizationTool produceNotarizationTool() { // OkHttpClient httpClient = new OkHttpClient.Builder().callTimeout(Duration.ofSeconds(30)).build(); //return new AltoolNotarizer(httpClient); - return new NotarytoolNotarizer(); + // for notarytool: + //return new NotarytoolNotarizer(); + + return new RustNotarizer(); + } + + @Produces + @ApplicationScoped + public StaplerTool produceStaplerTool() { + // for running on macos: + //return new XcrunStapler(); + + return new RustStapler(); } } diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationCredentials.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationCredentials.java new file mode 100644 index 0000000..1a873be --- /dev/null +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationCredentials.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Foundation and others. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License 2.0 + * which is available at http://www.eclipse.org/legal/epl-v20.html + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.cbi.ws.macos.notarization.execution; + +import io.quarkus.runtime.Startup; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.eclipse.cbi.ws.macos.notarization.NotarizationService; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; + +@Startup +@ApplicationScoped +public class NotarizationCredentials { + private static final Logger LOGGER = LoggerFactory.getLogger(NotarizationCredentials.class); + + @Inject + @ConfigProperty(name = "notarization.appleid.password") + private Optional appleIDPassword; + + @Inject + @ConfigProperty(name = "notarization.appleid.username") + private Optional appleIDUsername; + + @Inject + @ConfigProperty(name = "notarization.appleid.teamid") + private Optional appleIDTeamID; + + @Inject + @ConfigProperty(name = "notarization.appleapi.keyfile") + private Optional appleApiKeyFile; + + public boolean requireUsername() { + if (appleIDUsername.isEmpty()) { + LOGGER.error("required configuration value 'notarization.appleid.username' is missing"); + return false; + } else { + return true; + } + } + + public boolean requirePassword() { + if (appleIDUsername.isEmpty()) { + LOGGER.error("required configuration value 'notarization.appleid.password' is missing"); + return false; + } else { + return true; + } + } + + public boolean requireTeamID() { + if (appleIDUsername.isEmpty()) { + LOGGER.error("required configuration value 'notarization.appleid.teamid' is missing"); + return false; + } else { + return true; + } + } + + public boolean requireAppleApiKeyFile() { + if (appleApiKeyFile.isEmpty()) { + LOGGER.error("required configuration value 'notarization.appleapi.keyfile' is missing"); + return false; + } else { + return true; + } + } + + public String getUsername() { + return appleIDUsername.get(); + } + + public boolean hasPassword() { + return appleIDPassword.isPresent(); + } + + public String getPassword() { + return appleIDPassword.get(); + } + + public String getTeamID() { + return appleIDTeamID.get(); + } + + public String getAppleApiKeyFile() { + return appleApiKeyFile.get(); + } +} diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationInfo.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationInfo.java similarity index 91% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationInfo.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationInfo.java index 6bf58a9..7cff1aa 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationInfo.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationInfo.java @@ -5,12 +5,13 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.concurrent.ExecutionException; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,9 +22,7 @@ @RecordBuilder public record NotarizationInfo( - String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + NotarizationCredentials credentials, String appleRequestUUID, Duration pollingTimeout, NotarizationTool tool) { @@ -65,6 +64,6 @@ public NotarizationInfoResult retrieveInfoFailsafe(Duration maxTotalDuration, .onFailure(l -> LOGGER.error("Fail to fetch notarization info retrieval attempt #" + l.getAttemptCount() + ", cause: " + l.getFailure().getMessage() + ", elapsed time: " + l.getElapsedTime(), l.getFailure())) - .get(() -> tool().retrieveInfo(appleIDUsername(), appleIDPassword(), appleIDTeamID(), appleRequestUUID(), pollingTimeout())); + .get(() -> tool().retrieveInfo(credentials(), appleRequestUUID(), pollingTimeout())); } } diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationTool.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationTool.java similarity index 65% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationTool.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationTool.java index 9d50065..afb7ef3 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationTool.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/NotarizationTool.java @@ -5,7 +5,7 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution; import java.io.File; import java.io.IOException; @@ -18,6 +18,9 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Stream; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResultBuilder; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,22 +32,26 @@ public abstract class NotarizationTool { private static final Logger LOGGER = LoggerFactory.getLogger(NotarizationTool.class); private static final String TMPDIR = "TMPDIR"; - public NotarizerResult upload(String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + public boolean validate(NotarizationCredentials credentials) { + return true; + } + + public NotarizerResult upload(NotarizationCredentials credentials, String primaryBundleId, Path fileToNotarize, Duration uploadTimeout) throws ExecutionException, IOException { - List cmd = getUploadCommand(appleIDUsername, appleIDPassword, appleIDTeamID, primaryBundleId, fileToNotarize); + List cmd = getUploadCommand(credentials, primaryBundleId, fileToNotarize); - Path xcrunTempFolder = + Path tempFolder = Files.createTempDirectory(fileToNotarize.getParent(), - com.google.common.io.Files.getNameWithoutExtension(fileToNotarize.toString())+ "-xcrun-notarize-app-"); + com.google.common.io.Files.getNameWithoutExtension(fileToNotarize.toString())+ "-notarize-app-"); ProcessBuilder processBuilder = new ProcessBuilder().command(cmd); - processBuilder.environment().put(APPLEID_PASSWORD_ENV_VAR_NAME, appleIDPassword); - processBuilder.environment().put(TMPDIR, xcrunTempFolder.toString()); + if (credentials.hasPassword()) { + processBuilder.environment().put(APPLEID_PASSWORD_ENV_VAR_NAME, credentials.getPassword()); + } + processBuilder.environment().put(TMPDIR, tempFolder.toString()); try(NativeProcess.Result nativeProcessResult = NativeProcess.startAndWait(processBuilder, uploadTimeout)) { NotarizerResult result = analyzeSubmissionResult(nativeProcessResult, fileToNotarize); @@ -57,47 +64,43 @@ public NotarizerResult upload(String appleIDUsername, LOGGER.error("IOException happened during notarization upload of file " + fileToNotarize, e); throw new ExecutionException("IOException happened during notarization upload", e); } finally { - if (Files.exists(xcrunTempFolder)) { - LOGGER.trace("Deleting xcrun-notarize-app temporary folder " + xcrunTempFolder); - try (Stream filesToDelete = Files.walk(xcrunTempFolder).sorted(Comparator.reverseOrder()).map(Path::toFile)) { + if (Files.exists(tempFolder)) { + LOGGER.trace("Deleting notarize-app temporary folder " + tempFolder); + try (Stream filesToDelete = Files.walk(tempFolder).sorted(Comparator.reverseOrder()).map(Path::toFile)) { filesToDelete.forEach(File::delete); } catch (IOException e) { - LOGGER.warn("IOException happened during deletion of xcrun-notarize-app temporary folder " + xcrunTempFolder, e); + LOGGER.warn("IOException happened during deletion of notarize-app temporary folder " + tempFolder, e); } } } } - protected abstract List getUploadCommand(String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + protected abstract List getUploadCommand(NotarizationCredentials credentials, String primaryBundleId, Path fileToNotarize); protected abstract NotarizerResult analyzeSubmissionResult(NativeProcess.Result nativeProcessResult, Path fileToNotarize) throws ExecutionException; - public NotarizationInfoResult retrieveInfo(String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + public NotarizationInfoResult retrieveInfo(NotarizationCredentials credentials, String appleRequestUUID, Duration pollingTimeout) throws ExecutionException, IOException { - List cmd = getInfoCommand(appleIDUsername, appleIDPassword, appleIDTeamID, appleRequestUUID); + List cmd = getInfoCommand(credentials, appleRequestUUID); - Path xcrunTempFolder = Files.createTempDirectory("-xcrun-notarization-info-"); + Path tempFolder = Files.createTempDirectory("-notarization-info-"); ProcessBuilder processBuilder = new ProcessBuilder().command(cmd); - processBuilder.environment().put(APPLEID_PASSWORD_ENV_VAR_NAME, appleIDPassword); - processBuilder.environment().put(TMPDIR, xcrunTempFolder.toString()); + if (credentials.hasPassword()) { + processBuilder.environment().put(APPLEID_PASSWORD_ENV_VAR_NAME, credentials.getPassword()); + } + processBuilder.environment().put(TMPDIR, tempFolder.toString()); NotarizationInfoResultBuilder resultBuilder = NotarizationInfoResult.builder(); try (NativeProcess.Result nativeProcessResult = NativeProcess.startAndWait(processBuilder, pollingTimeout)) { boolean addLog = analyzeInfoResult(nativeProcessResult, resultBuilder, appleRequestUUID); if (addLog && hasLogCommand()) { - resultBuilder.notarizationLog(retrieveLog(appleIDUsername, - appleIDPassword, - appleIDTeamID, + resultBuilder.notarizationLog(retrieveLog(credentials, appleRequestUUID, pollingTimeout)); } @@ -111,34 +114,34 @@ public NotarizationInfoResult retrieveInfo(String appleIDUsername, LOGGER.error("Timeout while retrieving notarization info of request '" + appleRequestUUID + "'", e); throw new ExecutionException("Timeout while retrieving notarization info", e); } finally { - LOGGER.trace("Deleting xcrun-notarization-info temporary folder " + xcrunTempFolder); - try (Stream filesToDelete = Files.walk(xcrunTempFolder).sorted(Comparator.reverseOrder()).map(Path::toFile)) { + LOGGER.trace("Deleting notarization-info temporary folder " + tempFolder); + try (Stream filesToDelete = Files.walk(tempFolder).sorted(Comparator.reverseOrder()).map(Path::toFile)) { filesToDelete.forEach(File::delete); } catch (IOException e) { - LOGGER.warn("IOException happened during deletion of xcrun-notarization-info temporary folder " + xcrunTempFolder, e); + LOGGER.warn("IOException happened during deletion of notarization-info temporary folder " + tempFolder, e); } } } - protected abstract List getInfoCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String appleRequestUUID); + protected abstract List getInfoCommand(NotarizationCredentials credentials, String appleRequestUUID); protected abstract boolean analyzeInfoResult(NativeProcess.Result nativeProcessResult, NotarizationInfoResultBuilder resultBuilder, String appleRequestUUID) throws ExecutionException; - public String retrieveLog(String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + public String retrieveLog(NotarizationCredentials credentials, String appleRequestUUID, Duration pollingTimeout) throws ExecutionException, IOException { - List cmd = getLogCommand(appleIDUsername, appleIDPassword, appleIDTeamID, appleRequestUUID); + List cmd = getLogCommand(credentials, appleRequestUUID); - Path xcrunTempFolder = Files.createTempDirectory("-xcrun-notarization-log-"); + Path tempFolder = Files.createTempDirectory("-notarization-log-"); ProcessBuilder processBuilder = new ProcessBuilder().command(cmd); - processBuilder.environment().put(APPLEID_PASSWORD_ENV_VAR_NAME, appleIDPassword); - processBuilder.environment().put(TMPDIR, xcrunTempFolder.toString()); + if (credentials.hasPassword()) { + processBuilder.environment().put(APPLEID_PASSWORD_ENV_VAR_NAME, credentials.getPassword()); + } + processBuilder.environment().put(TMPDIR, tempFolder.toString()); try (NativeProcess.Result nativeProcessResult = NativeProcess.startAndWait(processBuilder, pollingTimeout)) { if (nativeProcessResult.exitValue() == 0) { @@ -154,16 +157,16 @@ public String retrieveLog(String appleIDUsername, LOGGER.error("Timeout while retrieving notarization log of request '" + appleRequestUUID + "'", e); throw new ExecutionException("Timeout while retrieving notarization log", e); } finally { - LOGGER.trace("Deleting xcrun-notarization-info temporary folder " + xcrunTempFolder); - try (Stream filesToDelete = Files.walk(xcrunTempFolder).sorted(Comparator.reverseOrder()).map(Path::toFile)) { + LOGGER.trace("Deleting notarization-info temporary folder " + tempFolder); + try (Stream filesToDelete = Files.walk(tempFolder).sorted(Comparator.reverseOrder()).map(Path::toFile)) { filesToDelete.forEach(File::delete); } catch (IOException e) { - LOGGER.warn("IOException happened during deletion of xcrun-notarization-log temporary folder " + xcrunTempFolder, e); + LOGGER.warn("IOException happened during deletion of notarization-log temporary folder " + tempFolder, e); } } } protected abstract boolean hasLogCommand(); - protected abstract List getLogCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String appleRequestUUID); + protected abstract List getLogCommand(NotarizationCredentials credentials, String appleRequestUUID); } \ No newline at end of file diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/Notarizer.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/Notarizer.java similarity index 88% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/Notarizer.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/Notarizer.java index 3456961..6fac067 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/Notarizer.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/Notarizer.java @@ -5,13 +5,14 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution; import java.nio.file.Path; import java.time.Duration; import java.time.temporal.ChronoUnit; import io.soabase.recordbuilder.core.RecordBuilder; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,9 +22,7 @@ @RecordBuilder public record Notarizer( String primaryBundleId, - String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + NotarizationCredentials credentials, Path fileToNotarize, Duration uploadTimeout, NotarizationTool tool) { @@ -55,6 +54,6 @@ public NotarizerResult uploadFailsafe(int maxFailedAttempts, Duration minBackOff String.format("Failure on notarization upload attempt #%d, cause: %s, elapsed time: %s", l.getAttemptCount(), l.getFailure().getMessage(), l.getElapsedTime()), l.getFailure())) - .get(() -> tool().upload(appleIDUsername(), appleIDPassword(), appleIDTeamID(), primaryBundleId(), fileToNotarize(), uploadTimeout())); + .get(() -> tool().upload(credentials(), primaryBundleId(), fileToNotarize(), uploadTimeout())); } } diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/Stapler.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/Stapler.java similarity index 62% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/Stapler.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/Stapler.java index 2d112a3..f881aa7 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/Stapler.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/Stapler.java @@ -5,27 +5,23 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.time.Duration; import java.time.temporal.ChronoUnit; -import java.util.Comparator; import java.util.List; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.google.common.collect.ImmutableList; - import io.soabase.recordbuilder.core.RecordBuilder; import org.eclipse.cbi.common.util.Zips; -import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; +import org.eclipse.cbi.ws.macos.notarization.execution.result.SimpleStaplerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.StaplerResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,21 +29,20 @@ import net.jodah.failsafe.RetryPolicy; @RecordBuilder -public record Stapler(Path fileToStaple, Duration staplingTimeout) { +public record Stapler(Path fileToStaple, Duration staplingTimeout, StaplerTool tool) { private static final Logger LOGGER = LoggerFactory.getLogger(Stapler.class); private static final String DOT_APP_GLOB_PATTERN = "glob:**.{app,plugin,framework}"; - private static final String TMPDIR = "TMPDIR"; public static StaplerBuilder builder() { return StaplerBuilder.builder(); } public StaplerResult staple() throws ExecutionException, IOException { - if ("zip".equals(com.google.common.io.Files.getFileExtension(fileToStaple().toString()))) { - return stapleZipFile(fileToStaple()); + if ("zip".equals(com.google.common.io.Files.getFileExtension(fileToStaple.toString()))) { + return stapleZipFile(fileToStaple); } else { - return stapleFile(fileToStaple()); + return tool.stapleFile(fileToStaple, staplingTimeout); } } @@ -61,7 +56,7 @@ private StaplerResult stapleZipFile(Path zipFile) throws ExecutionException { .filter(p -> Files.isDirectory(p) && dotAppPattern.matches(p)) .map(p -> { try { - return stapleFile(p); + return tool.stapleFile(p, staplingTimeout); } catch (ExecutionException | IOException e) { LOGGER.error("Error while stapling a file from a zip", e); return new SimpleStaplerResult(StaplerResult.Status.ERROR, e.getMessage()); @@ -79,41 +74,6 @@ private StaplerResult stapleZipFile(Path zipFile) throws ExecutionException { } } - private StaplerResult stapleFile(Path file) throws ExecutionException, IOException { - Path xcrunTempFolder = Files.createTempDirectory("-xcrun-stapler-"); - - List cmd = - ImmutableList.builder().add("xcrun", "stapler") - .add("staple", file.toString()) - .build(); - - ProcessBuilder processBuilder = new ProcessBuilder().command(cmd); - processBuilder.environment().put(TMPDIR, xcrunTempFolder.toString()); - - try(NativeProcess.Result nativeProcessResult = NativeProcess.startAndWait(processBuilder, staplingTimeout())) { - if (nativeProcessResult.exitValue() == 0) { - return new SimpleStaplerResult(StaplerResult.Status.SUCCESS, - "Notarization ticket has been stapled to the uploaded file successfully"); - } else { - return new SimpleStaplerResult(StaplerResult.Status.ERROR, - "Error happened while stapling notarization ticket to the uploaded file"); - } - } catch (IOException e) { - LOGGER.error("Error while stapling notarization ticket to file " + file, e); - throw new ExecutionException("Error happened while stapling notarization ticket to the uploaded file", e); - } catch (TimeoutException e) { - LOGGER.error("Timeout while stapling notarization ticket to file " + file, e); - throw new ExecutionException("Timeout while stapling notarization ticket to the uploaded file", e); - } finally { - LOGGER.trace("Deleting xcrun-stapler temporary folder " + xcrunTempFolder); - try (Stream filesToDelete = Files.walk(xcrunTempFolder).sorted(Comparator.reverseOrder()).map(Path::toFile)) { - filesToDelete.forEach(File::delete); - } catch (IOException e) { - LOGGER.warn("IOException happened during deletion of xcrun-stapler temporary folder " + xcrunTempFolder, e); - } - } - } - public StaplerResult stapleFailsafe(int maxFailedAttempts, Duration minBackOffDelay, Duration maxBackOffDelay) { RetryPolicy retryOnFailure = new RetryPolicy() .handleResultIf(info -> info.status() == StaplerResult.Status.ERROR) diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/StaplerTool.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/StaplerTool.java new file mode 100644 index 0000000..dc6ee58 --- /dev/null +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/StaplerTool.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2019 Eclipse Foundation and others. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License 2.0 + * which is available at http://www.eclipse.org/legal/epl-v20.html + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.cbi.ws.macos.notarization.execution; + +import org.eclipse.cbi.ws.macos.notarization.execution.result.SimpleStaplerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.StaplerResult; +import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; + +public abstract class StaplerTool { + private static final Logger LOGGER = LoggerFactory.getLogger(StaplerTool.class); + private static final String TMPDIR = "TMPDIR"; + + public StaplerResult stapleFile(Path file, Duration staplingTimeout) throws ExecutionException, IOException { + Path tempFolder = Files.createTempDirectory("-stapler-"); + + List cmd = getStapleCommand(file); + + ProcessBuilder processBuilder = new ProcessBuilder().command(cmd); + processBuilder.environment().put(TMPDIR, tempFolder.toString()); + + try(NativeProcess.Result nativeProcessResult = NativeProcess.startAndWait(processBuilder, staplingTimeout)) { + if (nativeProcessResult.exitValue() == 0) { + return new SimpleStaplerResult(StaplerResult.Status.SUCCESS, + "Notarization ticket has been stapled to the uploaded file successfully"); + } else { + return new SimpleStaplerResult(StaplerResult.Status.ERROR, + "Error happened while stapling notarization ticket to the uploaded file"); + } + } catch (IOException e) { + LOGGER.error("Error while stapling notarization ticket to file " + file, e); + throw new ExecutionException("Error happened while stapling notarization ticket to the uploaded file", e); + } catch (TimeoutException e) { + LOGGER.error("Timeout while stapling notarization ticket to file " + file, e); + throw new ExecutionException("Timeout while stapling notarization ticket to the uploaded file", e); + } finally { + LOGGER.trace("Deleting stapler temporary folder " + tempFolder); + try (Stream filesToDelete = Files.walk(tempFolder).sorted(Comparator.reverseOrder()).map(Path::toFile)) { + filesToDelete.forEach(File::delete); + } catch (IOException e) { + LOGGER.warn("IOException happened during deletion of stapler temporary folder " + tempFolder, e); + } + } + } + + protected abstract List getStapleCommand(Path fileToStaple); +} diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustNotarizer.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustNotarizer.java new file mode 100644 index 0000000..0c61363 --- /dev/null +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustNotarizer.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Foundation and others. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License 2.0 + * which is available at http://www.eclipse.org/legal/epl-v20.html + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.cbi.ws.macos.notarization.execution.generic; + +import com.google.common.collect.ImmutableList; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationCredentials; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationTool; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResultBuilder; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResultBuilder; +import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RustNotarizer extends NotarizationTool { + private static final Logger LOGGER = LoggerFactory.getLogger(RustNotarizer.class); + + private static final Pattern SUBMISSION_ID_PATTERN = Pattern.compile("^created submission ID: ([0-9a-f\\-]+)$", Pattern.CASE_INSENSITIVE); + private static final Pattern POLL_STATE_PATTERN = Pattern.compile("poll state after [0-9]+s: (.+)", Pattern.CASE_INSENSITIVE); + private static final String NOTARY_LOG_PREFIX = "notary log> "; + + @Override + public boolean validate(NotarizationCredentials credentials) { + return credentials.requireAppleApiKeyFile(); + } + + @Override + protected List getUploadCommand(NotarizationCredentials credentials, String primaryBundleId, Path fileToNotarize) { + return ImmutableList.builder() + .add("rcodesign") + .add("notary-submit") + .add("--api-key-file", credentials.getAppleApiKeyFile()) + .add("--max-wait-seconds", "1") + .add(fileToNotarize.toString()).build(); + } + + @Override + protected NotarizerResult analyzeSubmissionResult(NativeProcess.Result nativeProcessResult, Path fileToNotarize) throws ExecutionException { + NotarizerResultBuilder resultBuilder = NotarizerResult.builder(); + try { + if (nativeProcessResult.exitValue() == 0) { + String commandOutput = new String(nativeProcessResult.stderrAsStream().readAllBytes()); + String submissionId = null; + for (String line : commandOutput.split("\n")) { + Matcher matcher = SUBMISSION_ID_PATTERN.matcher(line); + if (matcher.matches()) { + submissionId = matcher.group(1); + LOGGER.debug("parsed submission id: " + submissionId); + resultBuilder + .status(NotarizerResult.Status.UPLOAD_SUCCESSFUL) + .message(line) + .appleRequestUUID(submissionId); + break; + } + } + + if (submissionId == null) { + throw new IllegalStateException("Cannot find the Apple submission ID in command output: " + commandOutput); + } + } else { + resultBuilder + .status(NotarizerResult.Status.UPLOAD_FAILED) + .message("Failed to notarize the requested file. Reason: "); + } + } catch (IOException e) { + LOGGER.error("Error while parsing the output after the upload of '" + fileToNotarize + "' to the Apple notarization service", e); + throw new ExecutionException("Error while parsing the output after the upload of the file to be notarized", e); + } + + return resultBuilder.build(); + } + + @Override + protected List getInfoCommand(NotarizationCredentials credentials, String appleRequestUUID) { + return ImmutableList.builder() + .add("rcodesign") + .add("notary-wait") + .add("--api-key-file", credentials.getAppleApiKeyFile()) + .add("--max-wait-seconds", "1") + .add(appleRequestUUID).build(); + } + + @Override + protected boolean analyzeInfoResult(NativeProcess.Result nativeProcessResult, NotarizationInfoResultBuilder resultBuilder, String appleRequestUUID) throws ExecutionException { + try { + if (nativeProcessResult.exitValue() == 0) { + String commandOutput = new String(nativeProcessResult.stderrAsStream().readAllBytes()); + String statusStr = null; + for (String line : commandOutput.split("\n")) { + Matcher matcher = POLL_STATE_PATTERN.matcher(line); + if (matcher.matches()) { + statusStr = matcher.group(1); + LOGGER.debug("parsed status: " + statusStr); + } + } + + if (statusStr == null) { + throw new IllegalStateException("Cannot find the submission status in command output: " + commandOutput); + } else { + if ("Accepted".equalsIgnoreCase(statusStr)) { + resultBuilder + .status(NotarizationInfoResult.Status.NOTARIZATION_SUCCESSFUL) + .notarizationLog(extractNotarizationLog(commandOutput)) + .message("Notarization status: " + statusStr); + } else if ("InProgress".equalsIgnoreCase(statusStr)) { + resultBuilder + .status(NotarizationInfoResult.Status.NOTARIZATION_IN_PROGRESS) + .message("Notarization in progress"); + } else { + resultBuilder.status(NotarizationInfoResult.Status.NOTARIZATION_FAILED); + + String errorMessage = ""; + String errorCode = ""; + resultBuilder.message("Failed to notarize the requested file (status="+statusStr+"). Error code="+errorCode+". Reason: " + errorMessage); + } + } + } else { + resultBuilder + .status(NotarizationInfoResult.Status.RETRIEVAL_FAILED) + .message("Failed to notarize the requested file. Reason: "); + } + } catch (IOException e) { + LOGGER.error("Cannot parse notarization info for request '" + appleRequestUUID + "'", e); + throw new ExecutionException("Failed to retrieve notarization info.", e); + } + + return false; + } + + private String extractNotarizationLog(String commandOutput) { + List log = new ArrayList<>(); + + for (String line : commandOutput.split("\n")) { + if (line.startsWith(NOTARY_LOG_PREFIX)) { + log.add(line.replaceFirst(NOTARY_LOG_PREFIX, "")); + } + } + + return String.join("\n", log); + } + + @Override + protected boolean hasLogCommand() { + return false; + } + + @Override + protected List getLogCommand(NotarizationCredentials credentials, String appleRequestUUID) { + return null; + } +} diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustStapler.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustStapler.java new file mode 100644 index 0000000..e9f37ea --- /dev/null +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustStapler.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Foundation and others. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License 2.0 + * which is available at http://www.eclipse.org/legal/epl-v20.html + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.cbi.ws.macos.notarization.execution.generic; + +import com.google.common.collect.ImmutableList; +import org.eclipse.cbi.ws.macos.notarization.execution.StaplerTool; + +import java.nio.file.Path; +import java.util.List; + +public class RustStapler extends StaplerTool { + @Override + protected List getStapleCommand(Path fileToStaple) { + return ImmutableList.builder() + .add("rcodesign") + .add("staple") + .add(fileToStaple.toString()).build(); + } +} diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/AltoolNotarizer.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/AltoolNotarizer.java similarity index 92% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/AltoolNotarizer.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/AltoolNotarizer.java index e316353..a5d2a65 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/AltoolNotarizer.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/AltoolNotarizer.java @@ -5,7 +5,7 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.altool; +package org.eclipse.cbi.ws.macos.notarization.execution.macos; import com.google.common.collect.ImmutableList; import net.jodah.failsafe.Failsafe; @@ -14,8 +14,12 @@ import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.Request; +import org.eclipse.cbi.ws.macos.notarization.execution.*; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResultBuilder; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResultBuilder; import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; @@ -42,16 +46,21 @@ public AltoolNotarizer(OkHttpClient httpClient) { } @Override - protected List getUploadCommand(String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + public boolean validate(NotarizationCredentials credentials) { + boolean valid = credentials.requireUsername(); + valid |= credentials.requirePassword(); + return valid; + } + + @Override + protected List getUploadCommand(NotarizationCredentials credentials, String primaryBundleId, Path fileToNotarize) { return ImmutableList.builder() .add("xcrun", "altool") .add("--notarize-app") .add("--output-format", "xml") - .add("--username", appleIDUsername) + .add("--username", credentials.getUsername()) .add("--password", "@env:" + APPLEID_PASSWORD_ENV_VAR_NAME) .add("--primary-bundle-id", primaryBundleId) .add("--file", fileToNotarize.toString()).build(); @@ -141,14 +150,12 @@ private Optional parseAppleRequestID(String message) { } @Override - protected List getInfoCommand(String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + protected List getInfoCommand(NotarizationCredentials credentials, String appleRequestUUID) { return ImmutableList.builder().add("xcrun", "altool") .add("--notarization-info", appleRequestUUID) .add("--output-format", "xml") - .add("--username", appleIDUsername) + .add("--username", credentials.getUsername()) .add("--password", "@env:" + APPLEID_PASSWORD_ENV_VAR_NAME) .build(); } @@ -263,9 +270,7 @@ protected boolean hasLogCommand() { } @Override - protected List getLogCommand(String appleIDUsername, - String appleIDPassword, - String appleIDTeamID, + protected List getLogCommand(NotarizationCredentials credentials, String appleRequestUUID) { throw new IllegalStateException("should not be called"); } diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/NotarytoolNotarizer.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/NotarytoolNotarizer.java similarity index 78% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/NotarytoolNotarizer.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/NotarytoolNotarizer.java index 8d63f21..691cace 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/NotarytoolNotarizer.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/NotarytoolNotarizer.java @@ -5,11 +5,16 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.notarytool; +package org.eclipse.cbi.ws.macos.notarization.execution.macos; import com.google.common.collect.ImmutableList; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationCredentials; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResultBuilder; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationTool; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResultBuilder; import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; @@ -24,14 +29,22 @@ public class NotarytoolNotarizer extends NotarizationTool { private static final Logger LOGGER = LoggerFactory.getLogger(NotarytoolNotarizer.class); @Override - protected List getUploadCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String primaryBundleId, Path fileToNotarize) { + public boolean validate(NotarizationCredentials credentials) { + boolean valid = credentials.requireUsername(); + valid |= credentials.requirePassword(); + valid |= credentials.requireTeamID(); + return valid; + } + + @Override + protected List getUploadCommand(NotarizationCredentials credentials, String primaryBundleId, Path fileToNotarize) { return ImmutableList.builder() .add("xcrun", "notarytool") .add("submit") .add("--output-format", "plist") - .add("--apple-id", appleIDUsername) - .add("--password", appleIDPassword) - .add("--team-id", appleIDTeamID) + .add("--apple-id", credentials.getUsername()) + .add("--password", credentials.getPassword()) + .add("--team-id", credentials.getTeamID()) .add(fileToNotarize.toString()).build(); } @@ -72,13 +85,13 @@ protected NotarizerResult analyzeSubmissionResult(NativeProcess.Result nativePro } @Override - protected List getInfoCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String appleRequestUUID) { + protected List getInfoCommand(NotarizationCredentials credentials, String appleRequestUUID) { return ImmutableList.builder().add("xcrun", "notarytool") .add("info") .add("--output-format", "plist") - .add("--apple-id", appleIDUsername) - .add("--password", appleIDPassword) - .add("--team-id", appleIDTeamID) + .add("--apple-id", credentials.getUsername()) + .add("--password", credentials.getPassword()) + .add("--team-id", credentials.getTeamID()) .add(appleRequestUUID) .build(); } @@ -137,12 +150,12 @@ protected boolean hasLogCommand() { } @Override - protected List getLogCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String appleRequestUUID) { + protected List getLogCommand(NotarizationCredentials credentials, String appleRequestUUID) { return ImmutableList.builder().add("xcrun", "notarytool") .add("log") - .add("--apple-id", appleIDUsername) - .add("--password", appleIDPassword) - .add("--team-id", appleIDTeamID) + .add("--apple-id", credentials.getUsername()) + .add("--password", credentials.getPassword()) + .add("--team-id", credentials.getTeamID()) .add(appleRequestUUID) .build(); } diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/PListDict.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/PListDict.java similarity index 98% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/PListDict.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/PListDict.java index 216f71b..240754d 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/PListDict.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/PListDict.java @@ -5,7 +5,7 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution.macos; import java.io.BufferedInputStream; import java.io.IOException; @@ -34,7 +34,7 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; -public class PListDict extends ForwardingMap { +class PListDict extends ForwardingMap { private static final Logger LOGGER = LoggerFactory.getLogger(PListDict.class); diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/XcrunStapler.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/XcrunStapler.java new file mode 100644 index 0000000..725f898 --- /dev/null +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/XcrunStapler.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Foundation and others. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License 2.0 + * which is available at http://www.eclipse.org/legal/epl-v20.html + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.cbi.ws.macos.notarization.execution.macos; + +import com.google.common.collect.ImmutableList; +import org.eclipse.cbi.ws.macos.notarization.execution.StaplerTool; + +import java.nio.file.Path; +import java.util.List; + +public class XcrunStapler extends StaplerTool { + @Override + protected List getStapleCommand(Path fileToStaple) { + return ImmutableList.builder() + .add("xcrun", "stapler") + .add("staple", fileToStaple.toString()) + .build(); + } +} diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/ComposedStaplerResult.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/ComposedStaplerResult.java similarity index 89% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/ComposedStaplerResult.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/ComposedStaplerResult.java index fddd83d..714009c 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/ComposedStaplerResult.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/ComposedStaplerResult.java @@ -5,14 +5,14 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution.result; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -class ComposedStaplerResult implements StaplerResult { +public class ComposedStaplerResult implements StaplerResult { private final List results; ComposedStaplerResult(Collection results) { diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationInfoResult.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/NotarizationInfoResult.java similarity index 93% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationInfoResult.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/NotarizationInfoResult.java index ec59fca..a3dff70 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizationInfoResult.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/NotarizationInfoResult.java @@ -5,7 +5,7 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution.result; import io.soabase.recordbuilder.core.RecordBuilder; diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizerResult.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/NotarizerResult.java similarity index 92% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizerResult.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/NotarizerResult.java index 24d2a25..2199a14 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/NotarizerResult.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/NotarizerResult.java @@ -5,7 +5,7 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution.result; import io.soabase.recordbuilder.core.RecordBuilder; diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/SimpleStaplerResult.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/SimpleStaplerResult.java similarity index 72% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/SimpleStaplerResult.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/SimpleStaplerResult.java index eccd7a1..b6c3dd0 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/SimpleStaplerResult.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/SimpleStaplerResult.java @@ -5,7 +5,6 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution.result; - -record SimpleStaplerResult(StaplerResult.Status status, String message) implements StaplerResult {} \ No newline at end of file +public record SimpleStaplerResult(StaplerResult.Status status, String message) implements StaplerResult {} \ No newline at end of file diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/StaplerResult.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/StaplerResult.java similarity index 91% rename from src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/StaplerResult.java rename to src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/StaplerResult.java index c356c6a..5014f5e 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/xcrun/common/StaplerResult.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/execution/result/StaplerResult.java @@ -5,11 +5,10 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.common; +package org.eclipse.cbi.ws.macos.notarization.execution.result; import java.util.Collection; - public interface StaplerResult { enum Status {ERROR, SUCCESS} diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/process/NativeProcess.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/process/NativeProcess.java index 0a3b628..e61997f 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/process/NativeProcess.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/process/NativeProcess.java @@ -122,6 +122,10 @@ public InputStream stdoutAsStream() throws IOException { return Files.newInputStream(stdout, StandardOpenOption.READ); } + public InputStream stderrAsStream() throws IOException { + return Files.newInputStream(stderr, StandardOpenOption.READ); + } + Result log() { LOGGER.trace(this.toString()); if (exitValue == 0) { diff --git a/src/main/java/org/eclipse/cbi/ws/macos/notarization/request/NotarizationRequest.java b/src/main/java/org/eclipse/cbi/ws/macos/notarization/request/NotarizationRequest.java index aebc2d8..b826253 100644 --- a/src/main/java/org/eclipse/cbi/ws/macos/notarization/request/NotarizationRequest.java +++ b/src/main/java/org/eclipse/cbi/ws/macos/notarization/request/NotarizationRequest.java @@ -20,9 +20,9 @@ import io.soabase.recordbuilder.core.RecordBuilder; import org.eclipse.cbi.ws.macos.notarization.request.NotarizationStatus.State; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationInfoResult; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizerResult; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.StaplerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.StaplerResult; @RecordBuilder public record NotarizationRequest( diff --git a/src/main/resources/META-INF/resources/index.html b/src/main/resources/META-INF/resources/index.html deleted file mode 100644 index 08cf8ff..0000000 --- a/src/main/resources/META-INF/resources/index.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - - macos-notarization-service - 1.0-SNAPSHOT - - - - - - -
-
-

Congratulations, you have created a new Quarkus application.

- -

Why do you see this?

- -

This page is served by Quarkus. The source is in - src/main/resources/META-INF/resources/index.html.

- -

What can I do from here?

- -

If not already done, run the application in dev mode using: mvn compile quarkus:dev. -

-
    -
  • Add REST resources, Servlets, functions and other services in src/main/java.
  • -
  • Your static assets are located in src/main/resources/META-INF/resources.
  • -
  • Configure your application in src/main/resources/application.properties. -
  • -
- -

How do I get rid of this page?

-

Just delete the src/main/resources/META-INF/resources/index.html file.

-
-
-
-

Application

-
    -
  • GroupId: org.eclipse.cbi
  • -
  • ArtifactId: macos-notarization-service
  • -
  • Version: 1.0-SNAPSHOT
  • -
  • Quarkus Version: 0.21.1
  • -
-
- -
-
- - - - \ No newline at end of file diff --git a/src/test/java/org/eclipse/cbi/ws/macos/notarization/FailingNotarizationServiceTest.java b/src/test/java/org/eclipse/cbi/ws/macos/notarization/FailingNotarizationServiceTest.java index 3659b93..71c531e 100644 --- a/src/test/java/org/eclipse/cbi/ws/macos/notarization/FailingNotarizationServiceTest.java +++ b/src/test/java/org/eclipse/cbi/ws/macos/notarization/FailingNotarizationServiceTest.java @@ -11,13 +11,14 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import jakarta.inject.Inject; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationCredentials; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResultBuilder; import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; import org.eclipse.cbi.ws.macos.notarization.request.NotarizationRequestOptions; import org.eclipse.cbi.ws.macos.notarization.request.NotarizationStatus; import org.eclipse.cbi.ws.macos.notarization.request.NotarizationStatusWithUUID; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationInfoResultBuilder; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationTool; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationTool; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -90,7 +91,7 @@ public void notarizationFailure() throws InterruptedException { static class FailingNotarizationTool extends NotarizationTool { @Override - protected List getUploadCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String primaryBundleId, Path fileToNotarize) { + protected List getUploadCommand(NotarizationCredentials credentials, String primaryBundleId, Path fileToNotarize) { return null; } @@ -100,7 +101,7 @@ protected NotarizerResult analyzeSubmissionResult(NativeProcess.Result nativePro } @Override - protected List getInfoCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String appleRequestUUID) { + protected List getInfoCommand(NotarizationCredentials credentials, String appleRequestUUID) { return null; } @@ -115,7 +116,7 @@ protected boolean hasLogCommand() { } @Override - protected List getLogCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String appleRequestUUID) { + protected List getLogCommand(NotarizationCredentials credentials, String appleRequestUUID) { return null; } } diff --git a/src/test/java/org/eclipse/cbi/ws/macos/notarization/PassingNotarizationServiceTest.java b/src/test/java/org/eclipse/cbi/ws/macos/notarization/PassingNotarizationServiceTest.java index b09d8e6..68b164d 100644 --- a/src/test/java/org/eclipse/cbi/ws/macos/notarization/PassingNotarizationServiceTest.java +++ b/src/test/java/org/eclipse/cbi/ws/macos/notarization/PassingNotarizationServiceTest.java @@ -11,14 +11,15 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import jakarta.inject.Inject; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationCredentials; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResultBuilder; import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; import org.eclipse.cbi.ws.macos.notarization.request.NotarizationRequestOptions; import org.eclipse.cbi.ws.macos.notarization.request.NotarizationStatus; import org.eclipse.cbi.ws.macos.notarization.request.NotarizationStatusWithUUID; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationInfoResult; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationInfoResultBuilder; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationTool; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.NotarizationTool; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -86,7 +87,7 @@ public void notarizationSuccess() throws InterruptedException { static class PassingNotarizationTool extends NotarizationTool { @Override - protected List getUploadCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String primaryBundleId, Path fileToNotarize) { + protected List getUploadCommand(NotarizationCredentials credentials, String primaryBundleId, Path fileToNotarize) { return List.of("pwd"); } @@ -97,7 +98,7 @@ protected NotarizerResult analyzeSubmissionResult(NativeProcess.Result nativePro } @Override - protected List getInfoCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String appleRequestUUID) { + protected List getInfoCommand(NotarizationCredentials credentials, String appleRequestUUID) { return List.of("pwd"); } @@ -113,7 +114,7 @@ protected boolean hasLogCommand() { } @Override - protected List getLogCommand(String appleIDUsername, String appleIDPassword, String appleIDTeamID, String appleRequestUUID) { + protected List getLogCommand(NotarizationCredentials credentials, String appleRequestUUID) { return List.of("pwd"); } } diff --git a/src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustNotarizerTest.java b/src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustNotarizerTest.java new file mode 100644 index 0000000..76075d2 --- /dev/null +++ b/src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/generic/RustNotarizerTest.java @@ -0,0 +1,23 @@ +package org.eclipse.cbi.ws.macos.notarization.execution.generic; + +import org.junit.jupiter.api.Test; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RustNotarizerTest { + + @Test + public void testRegex() { + Pattern SUBMISSION_ID_PATTERN = Pattern.compile("^created submission ID: ([0-9a-f\\-]+)$", Pattern.CASE_INSENSITIVE); + + String text = "creating Notary API submission for Alfred_5.1.4_2195-7148202178110920520.dmg (sha256: 703bbaa5cc1ca2994d699d3c82791ffa977e93411a01087c8be87ef945b01df7)\n" + + "created submission ID: b49577d3-a4f3-47a6-99a6-954de9da5451\n" + + "resolving AWS S3 configuration from Apple-provided credentials"; + + for (String line : text.split("\n")) { + Matcher m = SUBMISSION_ID_PATTERN.matcher(line); + System.out.println(m.matches()); + } + } +} diff --git a/src/test/java/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/AltoolNotarizerTest.java b/src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/AltoolNotarizerTest.java similarity index 84% rename from src/test/java/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/AltoolNotarizerTest.java rename to src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/AltoolNotarizerTest.java index ad9d96b..1e70da1 100644 --- a/src/test/java/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/AltoolNotarizerTest.java +++ b/src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/AltoolNotarizerTest.java @@ -5,13 +5,13 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.altool; +package org.eclipse.cbi.ws.macos.notarization.execution.macos; import okhttp3.OkHttpClient; import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationInfoResult; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationInfoResultBuilder; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResultBuilder; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -31,7 +31,7 @@ public void setup() { @Test public void analyzeSuccessfulSubmission() throws ExecutionException { - Path stdout = Path.of(this.getClass().getResource("submission-success.log").getPath()); + Path stdout = Path.of(this.getClass().getResource("altool/submission-success.log").getPath()); Path stderr = Path.of("non-existing"); NativeProcess.Result r = @@ -51,7 +51,7 @@ public void analyzeSuccessfulSubmission() throws ExecutionException { @Test public void analyzeSubmissionInProgress() throws ExecutionException { - Path stdout = Path.of(this.getClass().getResource("submission-in-progress.log").getPath()); + Path stdout = Path.of(this.getClass().getResource("altool/submission-in-progress.log").getPath()); Path stderr = Path.of("non-existing"); NativeProcess.Result r = @@ -71,7 +71,7 @@ public void analyzeSubmissionInProgress() throws ExecutionException { @Test public void analyzeInfoSuccess() throws ExecutionException { - Path stdout = Path.of(this.getClass().getResource("info-success.log").getPath()); + Path stdout = Path.of(this.getClass().getResource("altool/info-success.log").getPath()); Path stderr = Path.of("non-existing"); NativeProcess.Result r = diff --git a/src/test/java/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/NotarytoolNotarizerTest.java b/src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/NotarytoolNotarizerTest.java similarity index 84% rename from src/test/java/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/NotarytoolNotarizerTest.java rename to src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/NotarytoolNotarizerTest.java index 41124ca..4943f00 100644 --- a/src/test/java/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/NotarytoolNotarizerTest.java +++ b/src/test/java/org/eclipse/cbi/ws/macos/notarization/execution/macos/NotarytoolNotarizerTest.java @@ -5,12 +5,12 @@ * which is available at http://www.eclipse.org/legal/epl-v20.html * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ -package org.eclipse.cbi.ws.macos.notarization.xcrun.notarytool; +package org.eclipse.cbi.ws.macos.notarization.execution.macos; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResultBuilder; import org.eclipse.cbi.ws.macos.notarization.process.NativeProcess; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationInfoResult; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizationInfoResultBuilder; -import org.eclipse.cbi.ws.macos.notarization.xcrun.common.NotarizerResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizationInfoResult; +import org.eclipse.cbi.ws.macos.notarization.execution.result.NotarizerResult; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -31,7 +31,7 @@ public void setup() { @Test public void analyzeSuccessfulSubmission() throws ExecutionException { - Path stdout = Path.of(this.getClass().getResource("submission-success.log").getPath()); + Path stdout = Path.of(this.getClass().getResource("notarytool/submission-success.log").getPath()); Path stderr = Path.of("non-existing"); NativeProcess.Result r = @@ -51,7 +51,7 @@ public void analyzeSuccessfulSubmission() throws ExecutionException { @Test public void analyzeInfoInProgress() throws ExecutionException { - Path stdout = Path.of(this.getClass().getResource("info-in-progress.log").getPath()); + Path stdout = Path.of(this.getClass().getResource("notarytool/info-in-progress.log").getPath()); Path stderr = Path.of("non-existing"); NativeProcess.Result r = @@ -73,7 +73,7 @@ public void analyzeInfoInProgress() throws ExecutionException { @Test public void analyzeInfoSuccess() throws ExecutionException { - Path stdout = Path.of(this.getClass().getResource("info-success.log").getPath()); + Path stdout = Path.of(this.getClass().getResource("notarytool/info-success.log").getPath()); Path stderr = Path.of("non-existing"); NativeProcess.Result r = diff --git a/src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/info-success.log b/src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/altool/info-success.log similarity index 100% rename from src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/info-success.log rename to src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/altool/info-success.log diff --git a/src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/submission-in-progress.log b/src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/altool/submission-in-progress.log similarity index 100% rename from src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/submission-in-progress.log rename to src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/altool/submission-in-progress.log diff --git a/src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/submission-success.log b/src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/altool/submission-success.log similarity index 100% rename from src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/altool/submission-success.log rename to src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/altool/submission-success.log diff --git a/src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/info-in-progress.log b/src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/notarytool/info-in-progress.log similarity index 100% rename from src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/info-in-progress.log rename to src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/notarytool/info-in-progress.log diff --git a/src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/info-success.log b/src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/notarytool/info-success.log similarity index 100% rename from src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/info-success.log rename to src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/notarytool/info-success.log diff --git a/src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/submission-success.log b/src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/notarytool/submission-success.log similarity index 100% rename from src/test/resources/org/eclipse/cbi/ws/macos/notarization/xcrun/notarytool/submission-success.log rename to src/test/resources/org/eclipse/cbi/ws/macos/notarization/execution/macos/notarytool/submission-success.log