From 7d3eabe8401a1bc0fb1fb9ff909069cc907f0f2c Mon Sep 17 00:00:00 2001 From: Appu Goundan Date: Tue, 8 Aug 2023 13:22:51 -0400 Subject: [PATCH] Add validity helpers Signed-off-by: Appu Goundan --- .../trustroot/CertificateAuthorities.java | 2 +- .../trustroot/CertificateAuthority.java | 19 ++++--- .../java/dev/sigstore/trustroot/ValidFor.java | 18 +++++-- .../dev/sigstore/trustroot/ValidForTest.java | 53 +++++++++++++++++++ 4 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 sigstore-java/src/test/java/dev/sigstore/trustroot/ValidForTest.java diff --git a/sigstore-java/src/main/java/dev/sigstore/trustroot/CertificateAuthorities.java b/sigstore-java/src/main/java/dev/sigstore/trustroot/CertificateAuthorities.java index 269ccad0..7bfc24a3 100644 --- a/sigstore-java/src/main/java/dev/sigstore/trustroot/CertificateAuthorities.java +++ b/sigstore-java/src/main/java/dev/sigstore/trustroot/CertificateAuthorities.java @@ -63,7 +63,7 @@ public List find(Instant time) { public CertificateAuthority current() { var current = getCertificateAuthorities().stream() - .filter(ca -> ca.getValidFor().getEnd().isEmpty()) + .filter(CertificateAuthority::isCurrent) .collect(Collectors.toList()); if (current.size() == 0) { throw new IllegalStateException("Trust root contains no current certificate authorities"); diff --git a/sigstore-java/src/main/java/dev/sigstore/trustroot/CertificateAuthority.java b/sigstore-java/src/main/java/dev/sigstore/trustroot/CertificateAuthority.java index a170dd31..3a0b80eb 100644 --- a/sigstore-java/src/main/java/dev/sigstore/trustroot/CertificateAuthority.java +++ b/sigstore-java/src/main/java/dev/sigstore/trustroot/CertificateAuthority.java @@ -19,20 +19,25 @@ import java.net.URI; import java.security.cert.CertPath; import java.security.cert.CertificateException; +import java.time.Instant; import org.immutables.value.Value.Immutable; @Immutable -public interface CertificateAuthority { - CertPath getCertPath(); +public abstract class CertificateAuthority { + public abstract CertPath getCertPath(); - URI getUri(); + public abstract URI getUri(); - ValidFor getValidFor(); + public abstract ValidFor getValidFor(); - Subject getSubject(); + public abstract Subject getSubject(); - static CertificateAuthority from(dev.sigstore.proto.trustroot.v1.CertificateAuthority proto) - throws CertificateException { + public boolean isCurrent() { + return getValidFor().contains(Instant.now()); + } + + public static CertificateAuthority from( + dev.sigstore.proto.trustroot.v1.CertificateAuthority proto) throws CertificateException { return ImmutableCertificateAuthority.builder() .certPath(ProtoMutators.toCertPath(proto.getCertChain().getCertificatesList())) .validFor(ValidFor.from(proto.getValidFor())) diff --git a/sigstore-java/src/main/java/dev/sigstore/trustroot/ValidFor.java b/sigstore-java/src/main/java/dev/sigstore/trustroot/ValidFor.java index c56ace4e..e95e6097 100644 --- a/sigstore-java/src/main/java/dev/sigstore/trustroot/ValidFor.java +++ b/sigstore-java/src/main/java/dev/sigstore/trustroot/ValidFor.java @@ -22,12 +22,22 @@ import org.immutables.value.Value.Immutable; @Immutable -public interface ValidFor { - Instant getStart(); +public abstract class ValidFor { + public abstract Instant getStart(); - Optional getEnd(); + public abstract Optional getEnd(); - static ValidFor from(TimeRange proto) { + public boolean contains(Instant instant) { + if (!getStart().isBefore(instant)) { + return false; + } + if (getEnd().isEmpty() || getEnd().get().isAfter(instant)) { + return true; + } + return false; + } + + public static ValidFor from(TimeRange proto) { return ImmutableValidFor.builder() .start(ProtoMutators.toInstant(proto.getStart())) .end( diff --git a/sigstore-java/src/test/java/dev/sigstore/trustroot/ValidForTest.java b/sigstore-java/src/test/java/dev/sigstore/trustroot/ValidForTest.java new file mode 100644 index 00000000..150e37a9 --- /dev/null +++ b/sigstore-java/src/test/java/dev/sigstore/trustroot/ValidForTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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.trustroot; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ValidForTest { + + @Test + public void contains_withStartAndEnd() { + var start = Instant.now().minus(10, ChronoUnit.MINUTES); + var end = Instant.now().plus(10, ChronoUnit.MINUTES); + var range = ImmutableValidFor.builder().start(start).end(end).build(); + + Assertions.assertTrue(range.contains(Instant.now())); + + Assertions.assertTrue(range.contains(start.plus(10, ChronoUnit.SECONDS))); + Assertions.assertFalse(range.contains(start)); + Assertions.assertFalse(range.contains(start.minus(10, ChronoUnit.SECONDS))); + + Assertions.assertTrue(range.contains(end.minus(10, ChronoUnit.SECONDS))); + Assertions.assertFalse(range.contains(end)); + Assertions.assertFalse(range.contains(end.plus(10, ChronoUnit.SECONDS))); + } + + public void contains_withNoEnd() { + var start = Instant.now().minus(10, ChronoUnit.MINUTES); + var range = ImmutableValidFor.builder().start(start).build(); + + Assertions.assertTrue(range.contains(Instant.now())); + Assertions.assertTrue(range.contains(Instant.now().plus(10, ChronoUnit.SECONDS))); + + Assertions.assertTrue(range.contains(start.plus(10, ChronoUnit.SECONDS))); + Assertions.assertFalse(range.contains(start)); + Assertions.assertFalse(range.contains(start.minus(10, ChronoUnit.SECONDS))); + } +}