storj/pkg/peertls/tlsopts/tls_test.go
2019-11-14 21:46:15 +02:00

158 lines
4.7 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package tlsopts_test
import (
"crypto/x509"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"storj.io/storj/pkg/identity"
"storj.io/storj/pkg/peertls"
"storj.io/storj/pkg/peertls/extensions"
"storj.io/storj/pkg/peertls/tlsopts"
"storj.io/storj/pkg/storj"
"storj.io/storj/private/testcontext"
"storj.io/storj/private/testidentity"
"storj.io/storj/private/testpeertls"
"storj.io/storj/private/testrevocation"
"storj.io/storj/storage"
)
func TestVerifyIdentity_success(t *testing.T) {
for i := 0; i < 50; i++ {
ident, err := testidentity.PregeneratedIdentity(i, storj.LatestIDVersion())
require.NoError(t, err)
err = tlsopts.VerifyIdentity(ident.ID)(nil, identity.ToChains(ident.Chain()))
assert.NoError(t, err)
}
}
func TestVerifyIdentity_success_signed(t *testing.T) {
for i := 0; i < 50; i++ {
ident, err := testidentity.PregeneratedSignedIdentity(i, storj.LatestIDVersion())
require.NoError(t, err)
err = tlsopts.VerifyIdentity(ident.ID)(nil, identity.ToChains(ident.Chain()))
assert.NoError(t, err)
}
}
func TestVerifyIdentity_error(t *testing.T) {
ident, err := testidentity.PregeneratedIdentity(0, storj.LatestIDVersion())
require.NoError(t, err)
identTheftVictim, err := testidentity.PregeneratedIdentity(1, storj.LatestIDVersion())
require.NoError(t, err)
cases := []struct {
test string
nodeID storj.NodeID
}{
{"empty node ID", storj.NodeID{}},
{"garbage node ID", storj.NodeID{0, 1, 2, 3}},
{"wrong node ID", identTheftVictim.ID},
}
for _, cc := range cases {
testCase := cc
t.Run(testCase.test, func(t *testing.T) {
err := tlsopts.VerifyIdentity(testCase.nodeID)(nil, identity.ToChains(ident.Chain()))
assert.Error(t, err)
})
}
}
func TestExtensionMap_HandleExtensions(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
testidentity.IdentityVersionsTest(t, func(t *testing.T, version storj.IDVersion, _ *identity.FullIdentity) {
keys, originalChain, err := testpeertls.NewCertChain(2, version.Number)
assert.NoError(t, err)
rev := new(extensions.Revocation)
oldRevokedLeafChain, revocationExt, err := testpeertls.RevokeLeaf(keys[peertls.CAIndex], originalChain)
require.NoError(t, err)
err = rev.Unmarshal(revocationExt.Value)
require.NoError(t, err)
err = rev.Verify(oldRevokedLeafChain[peertls.CAIndex])
require.NoError(t, err)
// NB: node ID is the same, timestamp must change
// (see: identity.RevocationDB#Put)
time.Sleep(1 * time.Second)
newRevokedLeafChain, revocationExt, err := testpeertls.RevokeLeaf(keys[peertls.CAIndex], oldRevokedLeafChain)
require.NoError(t, err)
err = rev.Unmarshal(revocationExt.Value)
require.NoError(t, err)
err = rev.Verify(newRevokedLeafChain[peertls.CAIndex])
require.NoError(t, err)
testrevocation.RunDBs(t, func(t *testing.T, revDB extensions.RevocationDB, db storage.KeyValueStore) {
opts := &extensions.Options{
RevocationDB: revDB,
PeerIDVersions: "*",
}
testcases := []struct {
name string
chain []*x509.Certificate
}{
{"no extensions", originalChain},
{"leaf revocation", oldRevokedLeafChain},
{"double leaf revocation", newRevokedLeafChain},
// TODO: more and more diverse extensions in cases
}
{
handlerFuncMap := extensions.DefaultHandlers.WithOptions(opts)
for _, testcase := range testcases {
t.Log(testcase.name)
extensionsMap := tlsopts.NewExtensionsMap(testcase.chain...)
err := extensionsMap.HandleExtensions(handlerFuncMap, identity.ToChains(testcase.chain))
assert.NoError(t, err)
}
}
})
})
}
func TestExtensionMap_HandleExtensions_error(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
testrevocation.RunDBs(t, func(t *testing.T, revDB extensions.RevocationDB, db storage.KeyValueStore) {
keys, chain, oldRevocation, err := testpeertls.NewRevokedLeafChain()
assert.NoError(t, err)
// NB: node ID is the same, timestamp must change
// (see: identity.RevocationDB#Put)
time.Sleep(time.Second)
_, newRevocation, err := testpeertls.RevokeLeaf(keys[peertls.CAIndex], chain)
require.NoError(t, err)
assert.NotEqual(t, oldRevocation, newRevocation)
err = revDB.Put(ctx, chain, newRevocation)
assert.NoError(t, err)
opts := &extensions.Options{RevocationDB: revDB}
handlerFuncMap := extensions.HandlerFactories{
extensions.RevocationUpdateHandler,
}.WithOptions(opts)
extensionsMap := tlsopts.NewExtensionsMap(chain[peertls.LeafIndex])
assert.Equal(t, oldRevocation, extensionsMap[extensions.RevocationExtID.String()])
err = extensionsMap.HandleExtensions(handlerFuncMap, identity.ToChains(chain))
assert.Errorf(t, err, extensions.ErrRevocationTimestamp.Error())
})
}