cryptsetup: unify code (#2043)

* Add common backend for interacting with cryptsetup

* Use common cryptsetup backend in bootstrapper

* Use common cryptsetup backend in disk-mapper

* Use common cryptsetup backend in csi lib

---------

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2023-07-17 13:55:31 +02:00 committed by GitHub
parent f52c6752e2
commit ac1128d07f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 1061 additions and 1307 deletions

View file

@ -4,10 +4,68 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
Package diskencryption handles interaction with a node's state disk.
This package is not thread safe, since libcryptsetup is not thread safe.
There should only be one instance using this package per process.
*/
// Package diskencryption handles interaction with a node's state disk.
package diskencryption
import (
"fmt"
"github.com/edgelesssys/constellation/v2/internal/cryptsetup"
"github.com/spf13/afero"
)
const (
stateMapperDevice = "state"
initialKeyPath = "/run/cryptsetup-keys.d/state.key"
keyslot = 0
)
// DiskEncryption manages the encrypted state mapper device.
type DiskEncryption struct {
fs afero.Fs
device cryptdevice
}
// New creates a new Cryptsetup.
func New() *DiskEncryption {
return &DiskEncryption{
fs: afero.NewOsFs(),
device: cryptsetup.New(),
}
}
// Open opens the cryptdevice.
func (c *DiskEncryption) Open() (free func(), err error) {
return c.device.InitByName(stateMapperDevice)
}
// UUID gets the device's UUID.
// Only works after calling Open().
func (c *DiskEncryption) UUID() (string, error) {
return c.device.GetUUID()
}
// UpdatePassphrase switches the initial random passphrase of the mapped crypt device to a permanent passphrase.
// Only works after calling Open().
func (c *DiskEncryption) UpdatePassphrase(passphrase string) error {
initialPassphrase, err := c.getInitialPassphrase()
if err != nil {
return err
}
return c.device.KeyslotChangeByPassphrase(keyslot, keyslot, initialPassphrase, passphrase)
}
// getInitialPassphrase retrieves the initial passphrase used on first boot.
func (c *DiskEncryption) getInitialPassphrase() (string, error) {
passphrase, err := afero.ReadFile(c.fs, initialKeyPath)
if err != nil {
return "", fmt.Errorf("reading first boot encryption passphrase from disk: %w", err)
}
return string(passphrase), nil
}
type cryptdevice interface {
InitByName(name string) (func(), error)
GetUUID() (string, error)
KeyslotChangeByPassphrase(currentKeyslot int, newKeyslot int, currentPassphrase string, newPassphrase string) error
}