storj/pkg/provider/identity.go
JT Olio 45a3c2e974
pkg/provider: with pkg/provider merged, make a single heavy client binary, gateway binary, and deprecate old services (#165)
* pkg/provider: with pkg/provider merged, make a single heavy client binary and deprecate old services

* add setup to gw binary too

* captplanet: output what addresses everything is listening on

* revert peertls/io_util changes

* define config flag across all commands

* use trimsuffix
2018-07-26 08:21:35 -06:00

124 lines
3.5 KiB
Go

// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package provider
import (
"context"
"crypto"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"net"
base58 "github.com/jbenet/go-base58"
"go.uber.org/zap"
"storj.io/storj/pkg/dht"
"storj.io/storj/pkg/peertls"
)
// PeerIdentity represents another peer on the network.
type PeerIdentity struct {
// CA represents the peer's self-signed CA. The ID is taken from this cert.
CA *x509.Certificate
// Leaf represents the leaf they're currently using. The leaf should be
// signed by the CA. The leaf is what is used for communication.
Leaf *x509.Certificate
// The ID is calculated from the CA cert.
ID dht.NodeID
}
// FullIdentity represents you on the network. In addition to a PeerIdentity,
// a FullIdentity also has a PrivateKey, which a PeerIdentity doesn't have.
// The PrivateKey should be for the PeerIdentity's Leaf certificate.
type FullIdentity struct {
PeerIdentity
PrivateKey crypto.PrivateKey
todoCert *tls.Certificate // TODO(jt): get rid of this and only use the above
}
// IdentityConfig allows you to run a set of Responsibilities with the given
// identity. You can also just load an Identity from disk.
type IdentityConfig struct {
CertPath string `help:"path to the certificate chain for this identity" default:"$CONFDIR/identity.leaf.cert"`
KeyPath string `help:"path to the private key for this identity" default:"$CONFDIR/identity.leaf.key"`
Address string `help:"address to listen on" default:":7777"`
}
// LoadIdentity loads a FullIdentity from the given configuration
func (ic IdentityConfig) LoadIdentity() (*FullIdentity, error) {
pi, err := FullIdentityFromFiles(ic.CertPath, ic.KeyPath)
if err != nil {
return nil, Error.New("failed to load identity %#v, %#v: %v",
ic.CertPath, ic.KeyPath, err)
}
return pi, nil
}
// Run will run the given responsibilities with the configured identity.
func (ic IdentityConfig) Run(ctx context.Context,
responsibilities ...Responsibility) (
err error) {
defer mon.Task()(&ctx)(&err)
pi, err := ic.LoadIdentity()
if err != nil {
return err
}
lis, err := net.Listen("tcp", ic.Address)
if err != nil {
return err
}
defer func() { _ = lis.Close() }()
s, err := NewProvider(pi, lis, responsibilities...)
if err != nil {
return err
}
defer func() { _ = s.Close() }()
zap.S().Infof("Node %s started", s.Identity().ID)
return s.Run(ctx)
}
// PeerIdentityFromCertChain loads a PeerIdentity from a chain of certificates
func PeerIdentityFromCertChain(chain [][]byte) (*PeerIdentity, error) {
// TODO(jt): yeah, this totally does not do the right thing yet
// TODO(jt): fill this in correctly.
hash := sha256.Sum256(chain[0]) // TODO(jt): this is wrong
return &PeerIdentity{
CA: nil, // TODO(jt)
Leaf: nil, // TODO(jt)
ID: nodeID(base58.Encode(hash[:])), // TODO(jt): this is wrong
}, nil
}
// FullIdentityFromFiles loads a FullIdentity from a certificate chain and
// private key file
func FullIdentityFromFiles(certPath, keyPath string) (*FullIdentity, error) {
cert, err := peertls.LoadCert(certPath, keyPath)
if err != nil {
return nil, Error.Wrap(err)
}
peer, err := PeerIdentityFromCertChain(cert.Certificate)
if err != nil {
return nil, Error.Wrap(err)
}
return &FullIdentity{
PeerIdentity: *peer,
PrivateKey: cert.PrivateKey,
todoCert: cert,
}, nil
}
type nodeID string
func (n nodeID) String() string { return string(n) }
func (n nodeID) Bytes() []byte { return []byte(n) }