mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-05-08 01:05:16 -04:00
AB#2260 Refactor disk-mapper recovery (#82)
* Refactor disk-mapper recovery * Adapt constellation recover command to use new disk-mapper recovery API * Fix Cilium connectivity on rebooting nodes (#89) * Lower CoreDNS reschedule timeout to 10 seconds (#93) Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
a7b20b2a11
commit
8cb155d5c5
40 changed files with 1600 additions and 1130 deletions
|
@ -9,17 +9,21 @@ package proto
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/edgelesssys/constellation/disk-mapper/recoverproto"
|
||||
"github.com/edgelesssys/constellation/internal/atls"
|
||||
"github.com/edgelesssys/constellation/internal/attestation"
|
||||
"github.com/edgelesssys/constellation/internal/crypto"
|
||||
"github.com/edgelesssys/constellation/internal/grpc/atlscredentials"
|
||||
"github.com/edgelesssys/constellation/state/keyproto"
|
||||
"go.uber.org/multierr"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// KeyClient wraps a KeyAPI client and the connection to it.
|
||||
type KeyClient struct {
|
||||
conn *grpc.ClientConn
|
||||
keyapi keyproto.APIClient
|
||||
// RecoverClient wraps a recoverAPI client and the connection to it.
|
||||
type RecoverClient struct {
|
||||
conn *grpc.ClientConn
|
||||
recoverapi recoverproto.APIClient
|
||||
}
|
||||
|
||||
// Connect connects the client to a given server, using the handed
|
||||
|
@ -27,7 +31,7 @@ type KeyClient struct {
|
|||
// The connection must be closed using Close(). If connect is
|
||||
// called on a client that already has a connection, the old
|
||||
// connection is closed.
|
||||
func (c *KeyClient) Connect(endpoint string, validators atls.Validator) error {
|
||||
func (c *RecoverClient) Connect(endpoint string, validators atls.Validator) error {
|
||||
creds := atlscredentials.New(nil, []atls.Validator{validators})
|
||||
|
||||
conn, err := grpc.Dial(endpoint, grpc.WithTransportCredentials(creds))
|
||||
|
@ -36,14 +40,14 @@ func (c *KeyClient) Connect(endpoint string, validators atls.Validator) error {
|
|||
}
|
||||
_ = c.Close()
|
||||
c.conn = conn
|
||||
c.keyapi = keyproto.NewAPIClient(conn)
|
||||
c.recoverapi = recoverproto.NewAPIClient(conn)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close closes the grpc connection of the client.
|
||||
// Close is idempotent and can be called on non connected clients
|
||||
// without returning an error.
|
||||
func (c *KeyClient) Close() error {
|
||||
func (c *RecoverClient) Close() error {
|
||||
if c.conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -55,17 +59,58 @@ func (c *KeyClient) Close() error {
|
|||
}
|
||||
|
||||
// PushStateDiskKey pushes the state disk key to a constellation instance in recovery mode.
|
||||
// The state disk key must be derived from the UUID of the state disk and the master key.
|
||||
func (c *KeyClient) PushStateDiskKey(ctx context.Context, stateDiskKey, measurementSecret []byte) error {
|
||||
if c.keyapi == nil {
|
||||
func (c *RecoverClient) Recover(ctx context.Context, masterSecret, salt []byte) (retErr error) {
|
||||
if c.recoverapi == nil {
|
||||
return errors.New("client is not connected")
|
||||
}
|
||||
|
||||
req := &keyproto.PushStateDiskKeyRequest{
|
||||
StateDiskKey: stateDiskKey,
|
||||
MeasurementSecret: measurementSecret,
|
||||
measurementSecret, err := attestation.DeriveMeasurementSecret(masterSecret, salt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := c.keyapi.PushStateDiskKey(ctx, req)
|
||||
return err
|
||||
recoverclient, err := c.recoverapi.Recover(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := recoverclient.CloseSend(); err != nil {
|
||||
multierr.AppendInto(&retErr, err)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := recoverclient.Send(&recoverproto.RecoverMessage{
|
||||
Request: &recoverproto.RecoverMessage_MeasurementSecret{
|
||||
MeasurementSecret: measurementSecret,
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
res, err := recoverclient.Recv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stateDiskKey, err := deriveStateDiskKey(masterSecret, salt, res.DiskUuid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := recoverclient.Send(&recoverproto.RecoverMessage{
|
||||
Request: &recoverproto.RecoverMessage_StateDiskKey{
|
||||
StateDiskKey: stateDiskKey,
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := recoverclient.Recv(); err != nil && !errors.Is(err, io.EOF) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// deriveStateDiskKey derives a state disk key from a master key, a salt, and a disk UUID.
|
||||
func deriveStateDiskKey(masterKey, salt []byte, diskUUID string) ([]byte, error) {
|
||||
return crypto.DeriveKey(masterKey, salt, []byte(crypto.HKDFInfoPrefix+diskUUID), crypto.StateDiskKeyLength)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue