Skip to content

Commit

Permalink
Add tuf conformance
Browse files Browse the repository at this point in the history
ignores all currently failing tests with xfails

Signed-off-by: Appu Goundan <[email protected]>
  • Loading branch information
loosebazooka committed Nov 5, 2024
1 parent 1cd9762 commit 8fe7087
Show file tree
Hide file tree
Showing 9 changed files with 407 additions and 1 deletion.
41 changes: 41 additions & 0 deletions .github/workflows/tuf-conformance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: TUF Conformance Tests

on:
push:
branches:
- '**'
pull_request:
workflow_dispatch:
# TODO: add cron

jobs:
conformance:
strategy:
max-parallel: 1
matrix:
java-version: [11, 17]
fail-fast: false

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1

- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0
with:
java-version: ${{ matrix.java-version }}
distribution: 'temurin'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0

- name: Build tuf cli
run: ./gradlew :tuf-cli:build

- name: Unpack tuf distribution
run: tar -xvf ${{ github.workspace }}/tuf-cli/build/distributions/tuf-cli-*.tar --strip-components 1

- uses: theupdateframework/tuf-conformance@v2
with:
entrypoint: ${{ github.workspace }}/bin/tuf-cli
artifact-name: test repositories for tuf-cli java ${{ matrix.java-version }}
4 changes: 3 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ include("sigstore-java")
include("sigstore-gradle:sigstore-gradle-sign-base-plugin")
include("sigstore-gradle:sigstore-gradle-sign-plugin")
include("sigstore-testkit")
include("sigstore-cli")
include("sigstore-maven-plugin")

include("sigstore-cli")
include("tuf-cli")

include("fuzzing")
11 changes: 11 additions & 0 deletions tuf-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Sigstore-Java Tuf CLI

Used for conformance testing and internal processes. This is not meant for public consumption, we will not support
any usecase that uses this.

## Usage

### Help
```
./gradlew tuf-cli:run
```
39 changes: 39 additions & 0 deletions tuf-cli/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
plugins {
id("build-logic.java")
id("application")
}

repositories {
mavenCentral()
}

dependencies {
implementation(project(":sigstore-java"))
implementation("info.picocli:picocli:4.7.6")
implementation("com.google.guava:guava:33.3.1-jre")

implementation(platform("com.google.oauth-client:google-oauth-client-bom:1.36.0"))
implementation("com.google.oauth-client:google-oauth-client")

annotationProcessor("info.picocli:picocli-codegen:4.7.6")
}

tasks.compileJava {
options.compilerArgs.add("-Aproject=${project.group}/${project.name}")
}

application {
mainClass.set("dev.sigstore.tuf.cli.Tuf")
}

distributions.main {
contents {
from("tuf-cli.xfails") {
into("bin")
}
}
}

tasks.run.configure {
workingDir = rootProject.projectDir
}
59 changes: 59 additions & 0 deletions tuf-cli/src/main/java/dev/sigstore/tuf/cli/Download.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2024 The Sigstore Authors.
*
* 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 dev.sigstore.tuf.cli;

import dev.sigstore.tuf.FileSystemTufStore;
import dev.sigstore.tuf.HttpFetcher;
import dev.sigstore.tuf.MetaFetcher;
import dev.sigstore.tuf.PassthroughCacheMetaStore;
import dev.sigstore.tuf.RootProvider;
import dev.sigstore.tuf.TrustedMetaStore;
import dev.sigstore.tuf.Updater;
import java.util.concurrent.Callable;
import picocli.CommandLine.Command;
import picocli.CommandLine.ParentCommand;

@Command(name = "download", description = "download targets from a remote location")
public class Download implements Callable<Integer> {

@ParentCommand private Tuf tufCommand;

@Override
public Integer call() throws Exception {
var metadataDir = tufCommand.getMetadataDir();
var metadataUrl = tufCommand.getMetadataUrl();
var targetDir = tufCommand.getTargetDir();
var targetBaseUrl = tufCommand.getTargetBaseUrl();
var targetName = tufCommand.getTargetName();

var fsStore = FileSystemTufStore.newFileSystemStore(metadataDir, targetDir);
var tuf =
Updater.builder()
.setTrustedMetaStore(
TrustedMetaStore.newTrustedMetaStore(
PassthroughCacheMetaStore.newPassthroughMetaCache(fsStore)))
.setTrustedRootPath(RootProvider.fromFile(metadataDir.resolve("root.json")))
.setMetaFetcher(MetaFetcher.newFetcher(HttpFetcher.newFetcher(metadataUrl)))
.setTargetFetcher(HttpFetcher.newFetcher(targetBaseUrl))
.setTargetStore(fsStore)
.build();
// the java client isn't one shot like other clients, so downloadTarget doesn't call update
// for the sake of conformance updateMeta here
tuf.updateMeta();
tuf.downloadTarget(targetName);
return 0;
}
}
51 changes: 51 additions & 0 deletions tuf-cli/src/main/java/dev/sigstore/tuf/cli/Init.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2024 The Sigstore Authors.
*
* 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 dev.sigstore.tuf.cli;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.Callable;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
import picocli.CommandLine.ParentCommand;

@Command(name = "init", description = "initialize a local tuf repo")
public class Init implements Callable<Integer> {

@Parameters(arity = "1", paramLabel = "<TRUSTED_ROOT>")
Path trustedRoot;

@ParentCommand private Tuf tufCommand;

@Override
public Integer call() throws Exception {
var metadataDir = tufCommand.getMetadataDir();

if (!Files.isRegularFile(trustedRoot)) {
throw new IllegalArgumentException(trustedRoot + " is not a regular file");
}
if (Files.exists(metadataDir)) {
if (!Files.isDirectory(metadataDir)) {
throw new IllegalArgumentException(metadataDir + " is not a directory");
}
} else {
Files.createDirectories(metadataDir);
}

Files.copy(trustedRoot, metadataDir.resolve("root.json"));
return 0;
}
}
51 changes: 51 additions & 0 deletions tuf-cli/src/main/java/dev/sigstore/tuf/cli/Refresh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2024 The Sigstore Authors.
*
* 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 dev.sigstore.tuf.cli;

import dev.sigstore.tuf.FileSystemTufStore;
import dev.sigstore.tuf.HttpFetcher;
import dev.sigstore.tuf.MetaFetcher;
import dev.sigstore.tuf.PassthroughCacheMetaStore;
import dev.sigstore.tuf.RootProvider;
import dev.sigstore.tuf.TrustedMetaStore;
import dev.sigstore.tuf.Updater;
import java.util.concurrent.Callable;
import picocli.CommandLine.Command;
import picocli.CommandLine.ParentCommand;

@Command(name = "refresh", description = "update local tuf metadata from the repository")
public class Refresh implements Callable<Integer> {

@ParentCommand private Tuf tufCommand;

@Override
public Integer call() throws Exception {
var metadataDir = tufCommand.getMetadataDir();
var metadataUrl = tufCommand.getMetadataUrl();

var fsStore = FileSystemTufStore.newFileSystemStore(metadataDir);
var tuf =
Updater.builder()
.setTrustedMetaStore(
TrustedMetaStore.newTrustedMetaStore(
PassthroughCacheMetaStore.newPassthroughMetaCache(fsStore)))
.setTrustedRootPath(RootProvider.fromFile(metadataDir.resolve("root.json")))
.setMetaFetcher(MetaFetcher.newFetcher(HttpFetcher.newFetcher(metadataUrl)))
.build();
tuf.updateMeta();
return 0;
}
}
107 changes: 107 additions & 0 deletions tuf-cli/src/main/java/dev/sigstore/tuf/cli/Tuf.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2024 The Sigstore Authors.
*
* 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 dev.sigstore.tuf.cli;

import java.net.URL;
import java.nio.file.Path;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParameterException;
import picocli.CommandLine.Spec;

@Command(
name = "tuf",
mixinStandardHelpOptions = true,
subcommands = {Init.class, Refresh.class, Download.class})
public class Tuf {
@Spec CommandSpec spec;

public CommandSpec getSpec() {
return spec;
}

@Option(
names = {"--metadata-dir"},
required = false,
paramLabel = "<METADATA_DIR>")
private Path metadataDir;

@Option(
names = {"--metadata-url"},
required = false,
paramLabel = "<METADATA_URL>")
private URL metadataUrl;

@Option(
names = {"--target-name"},
required = false,
paramLabel = "<TARGET_PATH>")
private String targetName;

@Option(
names = {"--target-base-url"},
required = false,
paramLabel = "<TARGET_URL>")
private URL targetBaseUrl;

@Option(
names = {"--target-dir"},
required = false,
paramLabel = "<TARGET_DIR>")
private Path targetDir;

Path getMetadataDir() {
if (metadataDir == null) {
throw new ParameterException(spec.commandLine(), "--metadata-dir not set");
}
return metadataDir;
}

URL getMetadataUrl() {
if (metadataUrl == null) {
throw new ParameterException(spec.commandLine(), "--metadata-url not set");
}
return metadataUrl;
}

String getTargetName() {
if (targetName == null) {
throw new ParameterException(spec.commandLine(), "--target-name not set");
}
return targetName;
}

URL getTargetBaseUrl() {
if (targetBaseUrl == null) {
throw new ParameterException(spec.commandLine(), "--target-base-url not set");
}
return targetBaseUrl;
}

Path getTargetDir() {
if (targetDir == null) {
throw new ParameterException(spec.commandLine(), "--target-dir not set");
}
return targetDir;
}

public static void main(String[] args) {
int exitCode = new CommandLine(new Tuf()).execute(args);
System.exit(exitCode);
}
}
Loading

0 comments on commit 8fe7087

Please sign in to comment.