blob: 07cf358f6368edc0ccaeb724a32ace3af2c2174a [file]
// Copyright 2016 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package certconfig
import (
"crypto/x509/pkix"
"math/big"
"testing"
"time"
"github.com/luci/luci-go/appengine/gaetesting"
"github.com/luci/luci-go/common/clock/testclock"
"github.com/luci/luci-go/tokenserver/appengine/impl/utils"
"github.com/luci/luci-go/tokenserver/appengine/impl/utils/shards"
. "github.com/smartystreets/goconvey/convey"
)
func TestCRL(t *testing.T) {
Convey("CRL storage works", t, func() {
caName := "CA"
shardCount := 4
cachingTime := 10 * time.Second
ctx := gaetesting.TestingContext()
ctx, clk := testclock.UseTime(ctx, testclock.TestTimeUTC)
// Prepare a set of CRLs (with holes, to be more close to life)
crl := &pkix.CertificateList{}
for i := 1; i < 100; i++ {
crl.TBSCertList.RevokedCertificates = append(crl.TBSCertList.RevokedCertificates, pkix.RevokedCertificate{
SerialNumber: big.NewInt(int64(i * 3)),
})
}
// Upload it.
So(UpdateCRLSet(ctx, caName, shardCount, crl), ShouldBeNil)
// Use it.
checker := NewCRLChecker(caName, shardCount, cachingTime)
for i := 1; i < 300; i++ {
revoked, err := checker.IsRevokedSN(ctx, big.NewInt(int64(i)))
So(err, ShouldBeNil)
So(revoked, ShouldEqual, (i%3) == 0)
}
// Cert #1 is revoked now too. It will invalidate one cache shard.
crl.TBSCertList.RevokedCertificates = append(crl.TBSCertList.RevokedCertificates, pkix.RevokedCertificate{
SerialNumber: big.NewInt(1),
})
// Upload it.
So(UpdateCRLSet(ctx, caName, shardCount, crl), ShouldBeNil)
// Old cache is still used.
revoked, err := checker.IsRevokedSN(ctx, big.NewInt(1))
So(err, ShouldBeNil)
So(revoked, ShouldBeFalse)
// Roll time to invalidate the cache.
clk.Add(cachingTime * 2)
// New shard version is fetched.
revoked, err = checker.IsRevokedSN(ctx, big.NewInt(1))
So(err, ShouldBeNil)
So(revoked, ShouldBeTrue)
// Hit a code path for refetching of an unchanged shard. Pick a SN that
// doesn't belong to shard where '1' is.
shardIdx := func(sn int64) int {
blob, err := utils.SerializeSN(big.NewInt(sn))
So(err, ShouldBeNil)
return shards.ShardIndex(blob, shardCount)
}
forbiddenIdx := shardIdx(1)
sn := int64(2)
for shardIdx(sn) == forbiddenIdx {
sn++
}
// Hit this shard.
revoked, err = checker.IsRevokedSN(ctx, big.NewInt(sn))
So(err, ShouldBeNil)
So(revoked, ShouldEqual, (sn%3) == 0)
})
}