Wait-list gating (#534)
This commit is contained in:
parent
fdfb5f1da9
commit
df1f7a6214
@ -36,8 +36,15 @@ var (
|
|||||||
ErrTLSTemplate = errs.Class("tls template error")
|
ErrTLSTemplate = errs.Class("tls template error")
|
||||||
// ErrVerifyPeerCert is used when an error occurs during `VerifyPeerCertificate`
|
// ErrVerifyPeerCert is used when an error occurs during `VerifyPeerCertificate`
|
||||||
ErrVerifyPeerCert = errs.Class("tls peer certificate verification error")
|
ErrVerifyPeerCert = errs.Class("tls peer certificate verification error")
|
||||||
|
// ErrParseCerts is used when an error occurs while parsing a certificate or cert chain
|
||||||
|
ErrParseCerts = errs.Class("unable to parse certificate")
|
||||||
// ErrVerifySignature is used when a cert-chain signature verificaion error occurs
|
// ErrVerifySignature is used when a cert-chain signature verificaion error occurs
|
||||||
ErrVerifySignature = errs.Class("tls certificate signature verification error")
|
ErrVerifySignature = errs.Class("tls certificate signature verification error")
|
||||||
|
// ErrVerifyCertificateChain is used when a certificate chain can't be verified from leaf to root
|
||||||
|
// (i.e.: each cert in the chain should be signed by the preceding cert and the root should be self-signed)
|
||||||
|
ErrVerifyCertificateChain = errs.Class("certificate chain signature verification failed")
|
||||||
|
// ErrVerifyCAWhitelist is used when the leaf of a peer certificate isn't signed by any CA in the whitelist
|
||||||
|
ErrVerifyCAWhitelist = errs.Class("certificate isn't signed by any CA in the whitelist")
|
||||||
)
|
)
|
||||||
|
|
||||||
// PeerCertVerificationFunc is the signature for a `*tls.Config{}`'s
|
// PeerCertVerificationFunc is the signature for a `*tls.Config{}`'s
|
||||||
@ -90,13 +97,13 @@ func VerifyPeerFunc(next ...PeerCertVerificationFunc) PeerCertVerificationFunc {
|
|||||||
return func(chain [][]byte, _ [][]*x509.Certificate) error {
|
return func(chain [][]byte, _ [][]*x509.Certificate) error {
|
||||||
c, err := parseCertificateChains(chain)
|
c, err := parseCertificateChains(chain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return ErrVerifyPeerCert.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range next {
|
for _, n := range next {
|
||||||
if n != nil {
|
if n != nil {
|
||||||
if err := n(chain, [][]*x509.Certificate{c}); err != nil {
|
if err := n(chain, [][]*x509.Certificate{c}); err != nil {
|
||||||
return err
|
return ErrVerifyPeerCert.Wrap(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,6 +117,25 @@ func VerifyPeerCertChains(_ [][]byte, parsedChains [][]*x509.Certificate) error
|
|||||||
return verifyChainSignatures(parsedChains[0])
|
return verifyChainSignatures(parsedChains[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyCAWhitelist verifies that the peer identity's leaf was signed by any one of the
|
||||||
|
// (certificate authority) certificates in the provided whitelist
|
||||||
|
func VerifyCAWhitelist(cas []*x509.Certificate) PeerCertVerificationFunc {
|
||||||
|
if cas == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(_ [][]byte, parsedChains [][]*x509.Certificate) error {
|
||||||
|
var err error
|
||||||
|
for _, ca := range cas {
|
||||||
|
err = verifyCertSignature(ca, parsedChains[0][0])
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ErrVerifyCAWhitelist.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewKeyBlock converts an ASN1/DER-encoded byte-slice of a private key into
|
// NewKeyBlock converts an ASN1/DER-encoded byte-slice of a private key into
|
||||||
// a `pem.Block` pointer
|
// a `pem.Block` pointer
|
||||||
func NewKeyBlock(b []byte) *pem.Block {
|
func NewKeyBlock(b []byte) *pem.Block {
|
||||||
|
@ -124,4 +124,65 @@ func TestVerifyPeerCertChains(t *testing.T) {
|
|||||||
|
|
||||||
err = VerifyPeerFunc(VerifyPeerCertChains)([][]byte{l.Raw, c.Raw}, nil)
|
err = VerifyPeerFunc(VerifyPeerCertChains)([][]byte{l.Raw, c.Raw}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
c, err = NewCert(ct, nil, &cp.PublicKey, k)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
k2, err := NewKey()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
l, err = NewCert(lt, nil, &lp.PublicKey, k2)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = VerifyPeerFunc(VerifyPeerCertChains)([][]byte{l.Raw, c.Raw}, nil)
|
||||||
|
assert.True(t, ErrVerifyPeerCert.Has(err))
|
||||||
|
assert.True(t, ErrVerifyCertificateChain.Has(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerifyCAWhitelist(t *testing.T) {
|
||||||
|
k, err := NewKey()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
ct, err := CATemplate()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
cp, ok := k.(*ecdsa.PrivateKey)
|
||||||
|
assert.True(t, ok)
|
||||||
|
c, err := NewCert(ct, nil, &cp.PublicKey, k)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
lt, err := LeafTemplate()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
lp, ok := k.(*ecdsa.PrivateKey)
|
||||||
|
assert.True(t, ok)
|
||||||
|
l, err := NewCert(lt, ct, &lp.PublicKey, k)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = VerifyPeerFunc(VerifyCAWhitelist(nil))([][]byte{l.Raw, c.Raw}, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = VerifyPeerFunc(VerifyCAWhitelist([]*x509.Certificate{c}))([][]byte{l.Raw, c.Raw}, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
zk, err := NewKey()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
zt, err := CATemplate()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
zp, ok := zk.(*ecdsa.PrivateKey)
|
||||||
|
assert.True(t, ok)
|
||||||
|
z, err := NewCert(zt, nil, &zp.PublicKey, zk)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = VerifyPeerFunc(VerifyCAWhitelist([]*x509.Certificate{z}))([][]byte{l.Raw, c.Raw}, nil)
|
||||||
|
assert.True(t, ErrVerifyCAWhitelist.Has(err))
|
||||||
|
assert.True(t, ErrVerifySignature.Has(err))
|
||||||
|
|
||||||
|
err = VerifyPeerFunc(VerifyCAWhitelist([]*x509.Certificate{z, c}))([][]byte{l.Raw, c.Raw}, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = VerifyPeerFunc(VerifyCAWhitelist([]*x509.Certificate{c, z}))([][]byte{l.Raw, c.Raw}, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func parseCerts(rawCerts [][]byte) ([]*x509.Certificate, error) {
|
|||||||
var err error
|
var err error
|
||||||
certs[i], err = x509.ParseCertificate(c)
|
certs[i], err = x509.ParseCertificate(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrVerifyPeerCert.New("unable to parse certificate: %v", err)
|
return nil, ErrParseCerts.New("unable to parse certificate at index %d", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return certs, nil
|
return certs, nil
|
||||||
@ -54,53 +54,48 @@ func verifyChainSignatures(certs []*x509.Certificate) error {
|
|||||||
for i, cert := range certs {
|
for i, cert := range certs {
|
||||||
j := len(certs)
|
j := len(certs)
|
||||||
if i+1 < j {
|
if i+1 < j {
|
||||||
isValid, err := verifyCertSignature(certs[i+1], cert)
|
err := verifyCertSignature(certs[i+1], cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrVerifyPeerCert.Wrap(err)
|
return ErrVerifyCertificateChain.Wrap(err)
|
||||||
}
|
|
||||||
|
|
||||||
if !isValid {
|
|
||||||
return ErrVerifyPeerCert.New("certificate chain signature verification failed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rootIsValid, err := verifyCertSignature(cert, cert)
|
err := verifyCertSignature(cert, cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrVerifyPeerCert.Wrap(err)
|
return ErrVerifyCertificateChain.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !rootIsValid {
|
|
||||||
return ErrVerifyPeerCert.New("certificate chain signature verification failed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyCertSignature(parentCert, childCert *x509.Certificate) (bool, error) {
|
func verifyCertSignature(parentCert, childCert *x509.Certificate) error {
|
||||||
pubKey, ok := parentCert.PublicKey.(*ecdsa.PublicKey)
|
pubKey, ok := parentCert.PublicKey.(*ecdsa.PublicKey)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, ErrUnsupportedKey.New("%T", parentCert.PublicKey)
|
return ErrUnsupportedKey.New("%T", parentCert.PublicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
signature := new(ecdsaSignature)
|
signature := new(ecdsaSignature)
|
||||||
|
|
||||||
if _, err := asn1.Unmarshal(childCert.Signature, signature); err != nil {
|
if _, err := asn1.Unmarshal(childCert.Signature, signature); err != nil {
|
||||||
return false, ErrVerifySignature.New("unable to unmarshal ecdsa signature: %v", err)
|
return ErrVerifySignature.New("unable to unmarshal ecdsa signature: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
h := crypto.SHA256.New()
|
h := crypto.SHA256.New()
|
||||||
_, err := h.Write(childCert.RawTBSCertificate)
|
_, err := h.Write(childCert.RawTBSCertificate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return ErrVerifySignature.Wrap(err)
|
||||||
}
|
}
|
||||||
digest := h.Sum(nil)
|
digest := h.Sum(nil)
|
||||||
|
|
||||||
isValid := ecdsa.Verify(pubKey, digest, signature.R, signature.S)
|
if !ecdsa.Verify(pubKey, digest, signature.R, signature.S) {
|
||||||
|
return ErrVerifySignature.New("signature is not valid")
|
||||||
|
}
|
||||||
|
|
||||||
return isValid, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSerialNumber() (*big.Int, error) {
|
func newSerialNumber() (*big.Int, error) {
|
||||||
|
@ -53,6 +53,9 @@ type FullIdentity struct {
|
|||||||
ID nodeID
|
ID nodeID
|
||||||
// Key is the key this identity uses with the leaf for communication.
|
// Key is the key this identity uses with the leaf for communication.
|
||||||
Key crypto.PrivateKey
|
Key crypto.PrivateKey
|
||||||
|
// PeerCAWhitelist is a whitelist of CA certs which, if present, restricts which peers this identity will verify as valid;
|
||||||
|
// peer certs must be signed by a CA in this list to pass peer certificate verification.
|
||||||
|
PeerCAWhitelist []*x509.Certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
// IdentitySetupConfig allows you to run a set of Responsibilities with the given
|
// IdentitySetupConfig allows you to run a set of Responsibilities with the given
|
||||||
@ -67,14 +70,15 @@ type IdentitySetupConfig struct {
|
|||||||
// IdentityConfig allows you to run a set of Responsibilities with the given
|
// IdentityConfig allows you to run a set of Responsibilities with the given
|
||||||
// identity. You can also just load an Identity from disk.
|
// identity. You can also just load an Identity from disk.
|
||||||
type IdentityConfig struct {
|
type IdentityConfig struct {
|
||||||
CertPath string `help:"path to the certificate chain for this identity" default:"$CONFDIR/identity.cert"`
|
CertPath string `help:"path to the certificate chain for this identity" default:"$CONFDIR/identity.cert"`
|
||||||
KeyPath string `help:"path to the private key for this identity" default:"$CONFDIR/identity.key"`
|
KeyPath string `help:"path to the private key for this identity" default:"$CONFDIR/identity.key"`
|
||||||
Address string `help:"address to listen on" default:":7777"`
|
PeerCAWhitelistPath string `help:"path to the CA cert whitelist (peer identities must be signed by one these to be verified)"`
|
||||||
|
Address string `help:"address to listen on" default:":7777"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FullIdentityFromPEM loads a FullIdentity from a certificate chain and
|
// FullIdentityFromPEM loads a FullIdentity from a certificate chain and
|
||||||
// private key file
|
// private key file
|
||||||
func FullIdentityFromPEM(chainPEM, keyPEM []byte) (*FullIdentity, error) {
|
func FullIdentityFromPEM(chainPEM, keyPEM, CAWhitelistPEM []byte) (*FullIdentity, error) {
|
||||||
cb, err := decodePEM(chainPEM)
|
cb, err := decodePEM(chainPEM)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errs.Wrap(err)
|
return nil, errs.Wrap(err)
|
||||||
@ -101,11 +105,27 @@ func FullIdentityFromPEM(chainPEM, keyPEM []byte) (*FullIdentity, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
wb [][]byte
|
||||||
|
whitelist []*x509.Certificate
|
||||||
|
)
|
||||||
|
if CAWhitelistPEM != nil {
|
||||||
|
wb, err = decodePEM(CAWhitelistPEM)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.Wrap(err)
|
||||||
|
}
|
||||||
|
whitelist, err = ParseCertChain(wb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &FullIdentity{
|
return &FullIdentity{
|
||||||
CA: ch[1],
|
CA: ch[1],
|
||||||
Leaf: ch[0],
|
Leaf: ch[0],
|
||||||
Key: k,
|
Key: k,
|
||||||
ID: i,
|
ID: i,
|
||||||
|
PeerCAWhitelist: whitelist,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,8 +210,12 @@ func (ic IdentityConfig) Load() (*FullIdentity, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, peertls.ErrNotExist.Wrap(err)
|
return nil, peertls.ErrNotExist.Wrap(err)
|
||||||
}
|
}
|
||||||
|
w, err := ioutil.ReadFile(ic.PeerCAWhitelistPath)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
fi, err := FullIdentityFromPEM(c, k)
|
fi, err := FullIdentityFromPEM(c, k, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errs.New("failed to load identity %#v, %#v: %v",
|
return nil, errs.New("failed to load identity %#v, %#v: %v",
|
||||||
ic.CertPath, ic.KeyPath, err)
|
ic.CertPath, ic.KeyPath, err)
|
||||||
@ -251,19 +275,23 @@ func (ic IdentityConfig) Run(ctx context.Context, interceptor grpc.UnaryServerIn
|
|||||||
|
|
||||||
// ServerOption returns a grpc `ServerOption` for incoming connections
|
// ServerOption returns a grpc `ServerOption` for incoming connections
|
||||||
// to the node with this full identity
|
// to the node with this full identity
|
||||||
func (fi *FullIdentity) ServerOption() (grpc.ServerOption, error) {
|
func (fi *FullIdentity) ServerOption(pcvFuncs ...peertls.PeerCertVerificationFunc) (grpc.ServerOption, error) {
|
||||||
ch := [][]byte{fi.Leaf.Raw, fi.CA.Raw}
|
ch := [][]byte{fi.Leaf.Raw, fi.CA.Raw}
|
||||||
c, err := peertls.TLSCert(ch, fi.Leaf, fi.Key)
|
c, err := peertls.TLSCert(ch, fi.Leaf, fi.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pcvFuncs = append(
|
||||||
|
[]peertls.PeerCertVerificationFunc{peertls.VerifyPeerCertChains},
|
||||||
|
pcvFuncs...,
|
||||||
|
)
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
Certificates: []tls.Certificate{*c},
|
Certificates: []tls.Certificate{*c},
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
ClientAuth: tls.RequireAnyClientCert,
|
ClientAuth: tls.RequireAnyClientCert,
|
||||||
VerifyPeerCertificate: peertls.VerifyPeerFunc(
|
VerifyPeerCertificate: peertls.VerifyPeerFunc(
|
||||||
peertls.VerifyPeerCertChains,
|
pcvFuncs...,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,10 @@ import (
|
|||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
@ -87,7 +89,7 @@ func TestFullIdentityFromPEM(t *testing.T) {
|
|||||||
keyPEM := bytes.NewBuffer([]byte{})
|
keyPEM := bytes.NewBuffer([]byte{})
|
||||||
assert.NoError(t, pem.Encode(keyPEM, peertls.NewKeyBlock(lkB)))
|
assert.NoError(t, pem.Encode(keyPEM, peertls.NewKeyBlock(lkB)))
|
||||||
|
|
||||||
fi, err := FullIdentityFromPEM(chainPEM.Bytes(), keyPEM.Bytes())
|
fi, err := FullIdentityFromPEM(chainPEM.Bytes(), keyPEM.Bytes(), nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, l.Raw, fi.Leaf.Raw)
|
assert.Equal(t, l.Raw, fi.Leaf.Raw)
|
||||||
assert.Equal(t, c.Raw, fi.CA.Raw)
|
assert.Equal(t, c.Raw, fi.CA.Raw)
|
||||||
@ -183,7 +185,7 @@ AwEHoUQDQgAEoLy/0hs5deTXZunRumsMkiHpF0g8wAc58aXANmr7Mxx9tzoIYFnx
|
|||||||
ic, cleanup, err := tempIdentityConfig()
|
ic, cleanup, err := tempIdentityConfig()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
fi, err := FullIdentityFromPEM([]byte(chain), []byte(key))
|
fi, err := FullIdentityFromPEM([]byte(chain), []byte(key), nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
return cleanup, ic, fi, difficulty
|
return cleanup, ic, fi, difficulty
|
||||||
@ -198,6 +200,7 @@ func TestIdentityConfig_LoadIdentity(t *testing.T) {
|
|||||||
|
|
||||||
fi, err := ic.Load()
|
fi, err := ic.Load()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, fi.PeerCAWhitelist)
|
||||||
assert.NotEmpty(t, fi)
|
assert.NotEmpty(t, fi)
|
||||||
assert.NotEmpty(t, fi.Key)
|
assert.NotEmpty(t, fi.Key)
|
||||||
assert.NotEmpty(t, fi.Leaf)
|
assert.NotEmpty(t, fi.Leaf)
|
||||||
@ -208,6 +211,24 @@ func TestIdentityConfig_LoadIdentity(t *testing.T) {
|
|||||||
assert.Equal(t, expectedFI.Leaf, fi.Leaf)
|
assert.Equal(t, expectedFI.Leaf, fi.Leaf)
|
||||||
assert.Equal(t, expectedFI.CA, fi.CA)
|
assert.Equal(t, expectedFI.CA, fi.CA)
|
||||||
assert.Equal(t, expectedFI.ID.Bytes(), fi.ID.Bytes())
|
assert.Equal(t, expectedFI.ID.Bytes(), fi.ID.Bytes())
|
||||||
|
|
||||||
|
tmp := path.Join(os.TempDir(), "temp-ca-whitelist.pem")
|
||||||
|
w, err := os.Create(tmp)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer func() {
|
||||||
|
err := os.RemoveAll(tmp)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("unable to cleanup temp ca whitelist at \"%s\": %s", tmp, err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = peertls.WriteChain(w, fi.CA)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
ic.PeerCAWhitelistPath = tmp
|
||||||
|
fi, err = ic.Load()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, fi.PeerCAWhitelist)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeID_Difficulty(t *testing.T) {
|
func TestNodeID_Difficulty(t *testing.T) {
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
"storj.io/storj/pkg/peertls"
|
||||||
"storj.io/storj/storage"
|
"storj.io/storj/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ type Provider struct {
|
|||||||
func NewProvider(identity *FullIdentity, lis net.Listener, interceptor grpc.UnaryServerInterceptor,
|
func NewProvider(identity *FullIdentity, lis net.Listener, interceptor grpc.UnaryServerInterceptor,
|
||||||
responsibilities ...Responsibility) (*Provider, error) {
|
responsibilities ...Responsibility) (*Provider, error) {
|
||||||
// NB: talk to anyone with an identity
|
// NB: talk to anyone with an identity
|
||||||
ident, err := identity.ServerOption()
|
ident, err := identity.ServerOption(peertls.VerifyCAWhitelist(identity.PeerCAWhitelist))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user