Skip to content

feat: add system metadata assertion #270

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions .github/release-please/release-please-config.main.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
{
"type": "generic",
"path": "cmdline/src/main/java/io/opentdf/platform/Command.java"
},
{
"type": "generic",
"path": "sdk/src/main/java/io/opentdf/platform/sdk/Version.java"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
{
"type": "generic",
"path": "cmdline/src/main/java/io/opentdf/platform/Command.java"
},
{
"type": "generic",
"path": "sdk/src/main/java/io/opentdf/platform/sdk/Version.java"
}
]
}
73 changes: 42 additions & 31 deletions cmdline/src/main/java/io/opentdf/platform/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,11 @@ class Versions {
public static final String TDF_SPEC = "4.3.0";
}

@CommandLine.Command(
name = "tdf",
subcommands = {HelpCommand.class},
version =
"{\"version\":\"" + Versions.SDK + "\",\"tdfSpecVersion\":\"" + Versions.TDF_SPEC + "\"}"
)
@CommandLine.Command(name = "tdf", subcommands = { HelpCommand.class }, version = "{\"version\":\"" + Versions.SDK
+ "\",\"tdfSpecVersion\":\"" + Versions.TDF_SPEC + "\"}")
class Command {

@Option(names = {"-V", "--version"}, versionHelp = true, description = "display version info")
@Option(names = { "-V", "--version" }, versionHelp = true, description = "display version info")
boolean versionInfoRequested;

private static final String PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----";
Expand All @@ -85,7 +81,8 @@ class Command {
@Option(names = { "-p", "--platform-endpoint" }, required = true)
private String platformEndpoint;

private Object correctKeyType(AssertionConfig.AssertionKeyAlg alg, Object key, boolean publicKey) throws RuntimeException{
private Object correctKeyType(AssertionConfig.AssertionKeyAlg alg, Object key, boolean publicKey)
throws RuntimeException {
if (alg == AssertionConfig.AssertionKeyAlg.HS256) {
if (key instanceof String) {
key = ((String) key).getBytes(StandardCharsets.UTF_8);
Expand All @@ -101,14 +98,14 @@ private Object correctKeyType(AssertionConfig.AssertionKeyAlg alg, Object key, b
}
String pem = (String) key;
String pemWithNewlines = pem.replace("\\n", "\n");
if (publicKey){
String base64EncodedPem= pemWithNewlines
.replaceAll(PEM_HEADER, "")
.replaceAll(PEM_FOOTER, "")
.replaceAll("\\s", "")
.replaceAll("\r\n", "")
.replaceAll("\n", "")
.trim();
if (publicKey) {
String base64EncodedPem = pemWithNewlines
.replaceAll(PEM_HEADER, "")
.replaceAll(PEM_FOOTER, "")
.replaceAll("\\s", "")
.replaceAll("\r\n", "")
.replaceAll("\n", "")
.trim();
byte[] decoded = Base64.getDecoder().decode(base64EncodedPem);
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
KeyFactory kf = null;
Expand All @@ -122,7 +119,7 @@ private Object correctKeyType(AssertionConfig.AssertionKeyAlg alg, Object key, b
} catch (InvalidKeySpecException e) {
throw new RuntimeException(e);
}
}else {
} else {
String privateKeyPEM = pemWithNewlines
.replace(PRIVATE_KEY_HEADER, "")
.replace(PRIVATE_KEY_FOOTER, "")
Expand Down Expand Up @@ -191,8 +188,9 @@ void encrypt(
String fileJson = new String(Files.readAllBytes(Paths.get(assertionConfig)));
assertionConfigs = gson.fromJson(fileJson, AssertionConfig[].class);
} catch (JsonSyntaxException e2) {
throw new RuntimeException("Failed to parse assertion from file, expects an list of assertions", e2);
} catch(Exception e3) {
throw new RuntimeException("Failed to parse assertion from file, expects an list of assertions",
e2);
} catch (Exception e3) {
throw new RuntimeException("Could not parse assertion as json string or path to file", e3);
}
}
Expand Down Expand Up @@ -238,11 +236,15 @@ private SDK buildSDK() {

@CommandLine.Command(name = "decrypt")
void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
@Option(names = { "--rewrap-key-type" }, defaultValue = Option.NULL_VALUE, description = "Preferred rewrap algorithm, one of ${COMPLETION-CANDIDATES}") Optional<KeyType> rewrapKeyType,
@Option(names = { "--with-assertion-verification-disabled" }, defaultValue = "false") boolean disableAssertionVerification,
@Option(names = { "--with-assertion-verification-keys" }, defaultValue = Option.NULL_VALUE) Optional<String> assertionVerification,
@Option(names = {
"--rewrap-key-type" }, defaultValue = Option.NULL_VALUE, description = "Preferred rewrap algorithm, one of ${COMPLETION-CANDIDATES}") Optional<KeyType> rewrapKeyType,
@Option(names = {
"--with-assertion-verification-disabled" }, defaultValue = "false") boolean disableAssertionVerification,
@Option(names = {
"--with-assertion-verification-keys" }, defaultValue = Option.NULL_VALUE) Optional<String> assertionVerification,
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
@Option(names = { "--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
@Option(names = {
"--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
throws Exception {
try (var sdk = buildSDK()) {
var opts = new ArrayList<Consumer<Config.TDFReaderConfig>>();
Expand All @@ -254,7 +256,8 @@ void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,

AssertionVerificationKeys assertionVerificationKeys;
try {
assertionVerificationKeys = gson.fromJson(assertionVerificationInput, AssertionVerificationKeys.class);
assertionVerificationKeys = gson.fromJson(assertionVerificationInput,
AssertionVerificationKeys.class);
} catch (JsonSyntaxException e) {
// try it as a file path
try {
Expand All @@ -263,16 +266,20 @@ void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
} catch (JsonSyntaxException e2) {
throw new RuntimeException("Failed to parse assertion verification keys from file", e2);
} catch (Exception e3) {
throw new RuntimeException("Could not parse assertion verification keys as json string or path to file", e3);
throw new RuntimeException(
"Could not parse assertion verification keys as json string or path to file",
e3);
}
}

for (Map.Entry<String, AssertionConfig.AssertionKey> entry : assertionVerificationKeys.keys.entrySet()) {
for (Map.Entry<String, AssertionConfig.AssertionKey> entry : assertionVerificationKeys.keys
.entrySet()) {
try {
Object correctedKey = correctKeyType(entry.getValue().alg, entry.getValue().key, true);
entry.setValue(new AssertionConfig.AssertionKey(entry.getValue().alg, correctedKey));
} catch (Exception e) {
throw new RuntimeException("Error with assertion verification key: " + e.getMessage(), e);
throw new RuntimeException("Error with assertion verification key: " + e.getMessage(),
e);
}
}
opts.add(Config.withAssertionVerificationKeys(assertionVerificationKeys));
Expand All @@ -296,8 +303,10 @@ void decrypt(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,

@CommandLine.Command(name = "metadata")
void readMetadata(@Option(names = { "-f", "--file" }, required = true) Path tdfPath,
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
@Option(names = { "--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist) throws IOException {
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
@Option(names = {
"--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
throws IOException {
var sdk = buildSDK();
var opts = new ArrayList<Consumer<Config.TDFReaderConfig>>();
try (var in = FileChannel.open(tdfPath, StandardOpenOption.READ)) {
Expand Down Expand Up @@ -344,8 +353,10 @@ void createNanoTDF(

@CommandLine.Command(name = "decryptnano")
void readNanoTDF(@Option(names = { "-f", "--file" }, required = true) Path nanoTDFPath,
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
@Option(names = { "--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist) throws Exception {
@Option(names = { "--kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<String> kasAllowlistStr,
@Option(names = {
"--ignore-kas-allowlist" }, defaultValue = Option.NULL_VALUE) Optional<Boolean> ignoreAllowlist)
throws Exception {
var sdk = buildSDK();
try (var in = FileChannel.open(nanoTDFPath, StandardOpenOption.READ)) {
try (var stdout = new BufferedOutputStream(System.out)) {
Expand Down
78 changes: 49 additions & 29 deletions sdk/pom.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>io.opentdf.platform:sdk</name>
<artifactId>sdk</artifactId>
Expand All @@ -11,7 +13,8 @@
<packaging>jar</packaging>
<properties>
<jazzer.version>0.22.1</jazzer.version>
<jazzer.baseurl>https://github.com/CodeIntelligenceTesting/jazzer/releases/download/v${jazzer.version}</jazzer.baseurl>
<jazzer.baseurl>
https://github.com/CodeIntelligenceTesting/jazzer/releases/download/v${jazzer.version}</jazzer.baseurl>
<kotlin.version>2.1.0</kotlin.version>
<connect.version>0.7.2</connect.version>
<okhttp.version>4.12.0</okhttp.version>
Expand Down Expand Up @@ -287,6 +290,12 @@
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<!-- Plugin to create source JAR -->
<plugin>
Expand Down Expand Up @@ -362,17 +371,18 @@
<target>
<!-- Generate OpenTDF Platform Protobuf -->
<exec executable="buf" dir="." failOnError="true">
<arg value="generate"/>
<arg value="https://github.com/opentdf/platform.git#branch=${platform.branch},subdir=service"/>
<arg value="-o"/>
<arg value="target"/>
<arg value="generate" />
<arg
value="https://github.com/opentdf/platform.git#branch=${platform.branch},subdir=service" />
<arg value="-o" />
<arg value="target" />
</exec>
<!-- Generate gRPC Protobuf -->
<exec executable="buf" dir="." failOnError="true">
<arg value="generate"/>
<arg value="buf.build/grpc-ecosystem/grpc-gateway"/>
<arg value="-o"/>
<arg value="target"/>
<arg value="generate" />
<arg value="buf.build/grpc-ecosystem/grpc-gateway" />
<arg value="-o" />
<arg value="target" />
</exec>
</target>
</configuration>
Expand Down Expand Up @@ -475,7 +485,8 @@
</plugin>
</plugins>
</build>
<!--profile to execute fuzz test -->
<!--profile
to execute fuzz test -->
<profiles>
<profile>
<id>fuzz</id>
Expand All @@ -499,18 +510,21 @@
<configuration>
<target>
<condition property="jazzer.os" value="windows">
<os family="windows"/>
<os family="windows" />
</condition>
<condition property="jazzer.os" value="macos">
<os family="mac"/>
<os family="mac" />
</condition>
<condition property="jazzer.os" value="linux">
<os family="unix"/>
<os family="unix" />
</condition>
<echo message="Detected OS: ${jazzer.os}"/>
<mkdir dir="${project.build.directory}/jazzer"/>
<get src="${jazzer.baseurl}/jazzer-${jazzer.os}.tar.gz" dest="${project.build.directory}/jazzer/jazzer.tar.gz"/>
<untar compression="gzip" src="${project.build.directory}/jazzer/jazzer.tar.gz" dest="${project.build.directory}/jazzer"/>
<echo message="Detected OS: ${jazzer.os}" />
<mkdir dir="${project.build.directory}/jazzer" />
<get src="${jazzer.baseurl}/jazzer-${jazzer.os}.tar.gz"
dest="${project.build.directory}/jazzer/jazzer.tar.gz" />
<untar compression="gzip"
src="${project.build.directory}/jazzer/jazzer.tar.gz"
dest="${project.build.directory}/jazzer" />
</target>
</configuration>
<goals>
Expand Down Expand Up @@ -552,22 +566,28 @@
<configuration>
<target>
<path id="project.classpath">
<pathelement location="${project.build.directory}/classes"/>
<pathelement location="${project.build.directory}/test-classes"/>
<fileset dir="${project.build.directory}/dependency-jars">
<include name="**/*.jar"/>
<pathelement
location="${project.build.directory}/classes" />
<pathelement
location="${project.build.directory}/test-classes" />
<fileset
dir="${project.build.directory}/dependency-jars">
<include name="**/*.jar" />
</fileset>
</path>
<pathconvert property="project.classpath.string" pathsep="${path.separator}">
<path refid="project.classpath"/>
<pathconvert property="project.classpath.string"
pathsep="${path.separator}">
<path refid="project.classpath" />
</pathconvert>
<property environment="env"/>
<property environment="env" />

<chmod file="${project.build.directory}/jazzer/jazzer" perm="777"/>
<chmod file="${project.build.directory}/jazzer/jazzer"
perm="777" />

<exec executable="bash">
<arg value="-c"/>
<arg value="if [ -z &quot;${JAVA_HOME}&quot; ]; then JAVA_HOME=$(dirname $(dirname $(which java))); fi; DYLD_LIBRARY_PATH=$(find &quot;${JAVA_HOME}&quot; -type d | grep 'libexec/openjdk.jdk/Contents/Home/lib/server' 2&gt;/dev/null | head -n 1); if [ -z &quot;${DYLD_LIBRARY_PATH}&quot; ]; then DYLD_LIBRARY_PATH=&quot;${JAVA_HOME}/lib/server&quot;; fi; export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}; ${project.build.directory}/jazzer/jazzer --cp='${project.classpath.string}' --target_class='io.opentdf.platform.sdk.Fuzzing' --instrumentation_includes='io.opentdf.platform.sdk.**' ${jazzer.testDir}"/>
<arg value="-c" />
<arg
value="if [ -z &quot;${JAVA_HOME}&quot; ]; then JAVA_HOME=$(dirname $(dirname $(which java))); fi; DYLD_LIBRARY_PATH=$(find &quot;${JAVA_HOME}&quot; -type d | grep 'libexec/openjdk.jdk/Contents/Home/lib/server' 2&gt;/dev/null | head -n 1); if [ -z &quot;${DYLD_LIBRARY_PATH}&quot; ]; then DYLD_LIBRARY_PATH=&quot;${JAVA_HOME}/lib/server&quot;; fi; export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}; ${project.build.directory}/jazzer/jazzer --cp='${project.classpath.string}' --target_class='io.opentdf.platform.sdk.Fuzzing' --instrumentation_includes='io.opentdf.platform.sdk.**' ${jazzer.testDir}" />
</exec>
</target>
</configuration>
Expand All @@ -581,4 +601,4 @@
</build>
</profile>
</profiles>
</project>
</project>
Loading