Skip to content

Commit

Permalink
Merge pull request #40 from Yubico/versions
Browse files Browse the repository at this point in the history
Read all version info from manifest
  • Loading branch information
emlun authored Oct 16, 2019
2 parents 4b40a5e + db7d6fb commit 72bff0f
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 15 deletions.
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ task assembleJavadoc(type: Sync) {
destinationDir = file("${rootProject.buildDir}/javadoc")
}

String getGitCommit() {
def proc = "git rev-parse HEAD".execute(null, projectDir)
proc.waitFor()
if (proc.exitValue() != 0) {
throw new RuntimeException("Failed to get git commit ID");
}
return proc.text.trim()
}

subprojects { project ->

sourceCompatibility = 1.8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ plugins {

dependencies {
implementation(project(":webauthn-server-attestation"))
testImplementation("junit:junit:4.12")
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.yubico.webauthn.attestation;

import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.jar.Manifest;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class ManifestInfoTest {

private static String lookup(String key) throws IOException {
final Enumeration<URL> resources = AttestationResolver.class.getClassLoader().getResources("META-INF/MANIFEST.MF");

while (resources.hasMoreElements()) {
final URL resource = resources.nextElement();
final Manifest manifest = new Manifest(resource.openStream());
if ("java-webauthn-server-attestation".equals(manifest.getMainAttributes().getValue("Implementation-Id"))) {
return manifest.getMainAttributes().getValue(key);
}
}
throw new NoSuchElementException("Could not find \"" + key + "\" in manifest.");
}

@Test
public void standardImplementationPropertiesAreSet() throws IOException {
assertTrue(lookup("Implementation-Title").contains("attestation"));
assertTrue(lookup("Implementation-Version").matches("^\\d+\\.\\d+\\.\\d+(-.*)?"));
assertEquals("Yubico", lookup("Implementation-Vendor"));
}

@Test
public void customImplementationPropertiesAreSet() throws IOException {
assertTrue(lookup("Git-Commit").matches("^[a-f0-9]{40}$"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ plugins {

dependencies {
implementation(project(":webauthn-server-core"))
testImplementation("junit:junit:4.12")
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.yubico.webauthn.meta;

import com.yubico.webauthn.RelyingParty;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDate;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.jar.Manifest;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class ManifestInfoTest {

private static String lookup(String key) throws IOException {
final Enumeration<URL> resources = RelyingParty.class.getClassLoader().getResources("META-INF/MANIFEST.MF");

while (resources.hasMoreElements()) {
final URL resource = resources.nextElement();
final Manifest manifest = new Manifest(resource.openStream());
if ("java-webauthn-server".equals(manifest.getMainAttributes().getValue("Implementation-Id"))) {
return manifest.getMainAttributes().getValue(key);
}
}
throw new NoSuchElementException("Could not find \"" + key + "\" in manifest.");
}

@Test
public void standardSpecPropertiesAreSet() throws IOException {
assertTrue(lookup("Specification-Title").startsWith("Web Authentication"));
assertTrue(lookup("Specification-Version").startsWith("Level"));
assertEquals("World Wide Web Consortium", lookup("Specification-Vendor"));
}


@Test
public void customSpecPropertiesAreSet() throws IOException {
assertTrue(lookup("Specification-Url").startsWith("https://"));
assertTrue(lookup("Specification-Url-Latest").startsWith("https://"));
assertTrue(DocumentStatus.fromString(lookup("Specification-W3c-Status")).isPresent());
assertTrue(LocalDate.parse(lookup("Specification-Release-Date")).isAfter(LocalDate.of(2019, 3, 3)));
}

@Test
public void standardImplementationPropertiesAreSet() throws IOException {
assertTrue(lookup("Implementation-Title").contains("Web Authentication"));
assertTrue(lookup("Implementation-Version").matches("^\\d+\\.\\d+\\.\\d+(-.*)?"));
assertEquals("Yubico", lookup("Implementation-Vendor"));
}

@Test
public void customImplementationPropertiesAreSet() throws IOException {
assertTrue(lookup("Git-Commit").matches("^[a-f0-9]{40}$"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.yubico.webauthn.meta;

import java.time.LocalDate;
import org.junit.Test;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

/**
* Since this depends on the manifest of the core jar, and the manifest is build by Gradle, this test is likely to fail
* when run in an IDE. It works as expected when run via Gradle.
*/
public class VersionInfoTest {

final VersionInfo versionInfo = VersionInfo.getInstance();

@Test
public void specPropertiesAreSet() {
final Specification spec = versionInfo.getSpecification();
assertTrue(spec.getLatestVersionUrl().toExternalForm().startsWith("https://"));
assertTrue(spec.getUrl().toExternalForm().startsWith("https://"));
assertTrue(spec.getReleaseDate().isAfter(LocalDate.of(2019, 3, 3)));
assertNotNull(spec.getStatus());
}

@Test
public void implementationPropertiesAreSet() {
final Implementation impl = versionInfo.getImplementation();
assertTrue(impl.getSourceCodeUrl().toExternalForm().startsWith("https://"));
assertTrue(impl.getVersion().matches("^\\d+\\.\\d+\\.\\d+(-.*)?"));
assertTrue(impl.getGitCommit().matches("^[a-f0-9]{40}$"));
}

@Test
public void majorVersionIsAtLeast1() {
final String version = versionInfo.getImplementation().getVersion();
String[] splits = version.split("\\.");
final int majorVersion = Integer.parseInt(splits[0]);
assertTrue(majorVersion >= 1);
}

}
1 change: 1 addition & 0 deletions webauthn-server-attestation/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jar {
'Implementation-Title': project.description,
'Implementation-Version': project.version,
'Implementation-Vendor': 'Yubico',
'Git-Commit': getGitCommit(),
])
}
}
Expand Down
8 changes: 8 additions & 0 deletions webauthn-server-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,18 @@ jar {
'Specification-Title': 'Web Authentication: An API for accessing Public Key Credentials',
'Specification-Version': 'Level 1 Recommendation 2019-03-04',
'Specification-Vendor': 'World Wide Web Consortium',

'Specification-Url': 'https://www.w3.org/TR/2019/REC-webauthn-1-20190304/',
'Specification-Url-Latest': 'https://www.w3.org/TR/webauthn/',
'Specification-W3c-Status': 'recommendation',
'Specification-Release-Date': '2019-03-04',

'Implementation-Id': 'java-webauthn-server',
'Implementation-Title': 'Yubico Web Authentication server library',
'Implementation-Version': project.version,
'Implementation-Vendor': 'Yubico',
'Implementation-Source-Url': 'https://github.com/Yubico/java-webauthn-server',
'Git-Commit': getGitCommit(),
])
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.yubico.internal.util.json.JsonStringSerializable;
import com.yubico.internal.util.json.JsonStringSerializer;
import java.util.Optional;
import java.util.stream.Stream;
import lombok.AllArgsConstructor;
import lombok.NonNull;

/**
* A representation of Web Authentication specification document statuses.
Expand Down Expand Up @@ -62,6 +65,10 @@ public enum DocumentStatus implements JsonStringSerializable {

private final String id;

static Optional<DocumentStatus> fromString(@NonNull String id) {
return Stream.of(values()).filter(v -> v.id.equals(id)).findAny();
}

/**
* Used by JSON serializer.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class Implementation {
/**
* The version number of this release of the library.
*/
@NonNull
private final String version;

/**
Expand All @@ -50,8 +51,10 @@ public class Implementation {
@NonNull
private final URL sourceCodeUrl;

public Optional<String> getVersion() {
return Optional.ofNullable(version);
}
/**
* The commit ID of the source code the library was built from, if known.
*/
@NonNull
private final String gitCommit;

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@
import java.net.URL;
import java.time.LocalDate;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.jar.Manifest;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;

Expand Down Expand Up @@ -64,35 +63,35 @@ public static VersionInfo getInstance() {
* Represents the specification this implementation is based on
*/
private final Specification specification = Specification.builder()
.url(new URL("https://www.w3.org/TR/2019/REC-webauthn-1-20190304/"))
.latestVersionUrl(new URL("https://www.w3.org/TR/webauthn/"))
.status(DocumentStatus.RECOMMENDATION)
.releaseDate(LocalDate.parse("2019-03-04"))
.url(new URL(findValueInManifest("Specification-Url")))
.latestVersionUrl(new URL(findValueInManifest("Specification-Url-Latest")))
.status(DocumentStatus.fromString(findValueInManifest("Specification-W3c-Status")).get())
.releaseDate(LocalDate.parse(findValueInManifest("Specification-Release-Date")))
.build();

/**
* Description of this version of this library
*/
private final Implementation implementation = new Implementation(
findImplementationVersionInManifest().orElse(null),
new URL("https://github.com/Yubico/java-webauthn-server")
findValueInManifest("Implementation-Version"),
new URL(findValueInManifest("Implementation-Source-Url")),
findValueInManifest("Git-Commit")
);

private VersionInfo() throws IOException {
}

private Optional<String> findImplementationVersionInManifest() throws IOException {
private String findValueInManifest(String key) throws IOException {
final Enumeration<URL> resources = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");

while (resources.hasMoreElements()) {
final URL resource = resources.nextElement();
final Manifest manifest = new Manifest(resource.openStream());
if ("java-webauthn-server".equals(manifest.getMainAttributes().getValue("Implementation-Id"))) {
return Optional.ofNullable(manifest.getMainAttributes().getValue("Implementation-Version"));
return manifest.getMainAttributes().getValue(key);
}
}

return Optional.empty();
throw new NoSuchElementException("Could not find \"" + key + "\" in manifest.");
}

}

0 comments on commit 72bff0f

Please sign in to comment.