storj/satellite/satellitedb/certdb.go
aligeti 65932ad692
Updating the certdb to support storage of multiple public keys for same node ID (#2692)
* updating the certdb to support storage of multiple public keys for same node ID
2019-08-02 13:47:35 -04:00

101 lines
2.9 KiB
Go

// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package satellitedb
import (
"context"
"crypto"
"database/sql"
"storj.io/storj/internal/dbutil/pgutil"
"storj.io/storj/internal/dbutil/sqliteutil"
"storj.io/storj/pkg/pkcrypto"
"storj.io/storj/pkg/storj"
dbx "storj.io/storj/satellite/satellitedb/dbx"
)
type certDB struct {
db *dbx.DB
}
func (certs *certDB) SavePublicKey(ctx context.Context, nodeID storj.NodeID, publicKey crypto.PublicKey) (err error) {
defer mon.Task()(&ctx)(&err)
pubbytes, err := pkcrypto.PublicKeyToPKIX(publicKey)
if err != nil {
return Error.Wrap(err)
}
_, err = certs.db.Get_CertRecord_By_Publickey(ctx, dbx.CertRecord_Publickey(pubbytes))
if err != nil {
if err == sql.ErrNoRows {
return certs.tryAddPublicKey(ctx, nodeID, publicKey)
}
return Error.Wrap(err)
}
// publickey for the nodeID entry already exists, just return
return nil
}
func (certs *certDB) tryAddPublicKey(ctx context.Context, nodeID storj.NodeID, publicKey crypto.PublicKey) (err error) {
defer mon.Task()(&ctx)(&err)
// no rows err, so create/insert an entry
pubbytes, err := pkcrypto.PublicKeyToPKIX(publicKey)
if err != nil {
return Error.Wrap(err)
}
// TODO: use upsert here instead of create
_, err = certs.db.Create_CertRecord(ctx,
dbx.CertRecord_Publickey(pubbytes),
dbx.CertRecord_Id(nodeID.Bytes()),
)
// another goroutine might race to create the cert record, let's ignore that error
if pgutil.IsConstraintError(err) || sqliteutil.IsConstraintError(err) {
return nil
} else if err != nil {
return Error.Wrap(err)
}
return nil
}
// GetPublicKey gets the public key of uplink corresponding to uplink id
func (certs *certDB) GetPublicKey(ctx context.Context, nodeID storj.NodeID) (_ crypto.PublicKey, err error) {
defer mon.Task()(&ctx)(&err)
dbxInfo, err := certs.db.All_CertRecord_By_Id_OrderBy_Desc_UpdateAt(ctx, dbx.CertRecord_Id(nodeID.Bytes()))
if err != nil {
return nil, err
}
// the first indext always holds the lastest of the keys
pubkey, err := pkcrypto.PublicKeyFromPKIX(dbxInfo[0].Publickey)
if err != nil {
return nil, Error.New("Failed to extract Public Key from Order: %+v", err)
}
return pubkey, nil
}
// GetPublicKeys gets the public keys of a storagenode corresponding to storagenode id
func (certs *certDB) GetPublicKeys(ctx context.Context, nodeID storj.NodeID) (pubkeys []crypto.PublicKey, err error) {
defer mon.Task()(&ctx)(&err)
dbxInfo, err := certs.db.All_CertRecord_By_Id_OrderBy_Desc_UpdateAt(ctx, dbx.CertRecord_Id(nodeID.Bytes()))
if err != nil {
return nil, err
}
if len(dbxInfo) == 0 {
return nil, Error.New("Failed to extract Public Key from ID: %+v", nodeID.String())
}
for _, v := range dbxInfo {
pubkey, err := pkcrypto.PublicKeyFromPKIX(v.Publickey)
if err != nil {
return nil, Error.New("Failed to extract Public Key from Order: %+v", err)
}
pubkeys = append(pubkeys, pubkey)
}
return pubkeys, nil
}