mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
bootstrapper: allow building without cgo dependencies for linting
This commit is contained in:
parent
78085cba68
commit
94758bc392
@ -3,13 +3,24 @@ load("//bazel/go:go_test.bzl", "go_ld_test", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "diskencryption",
|
||||
srcs = ["diskencryption.go"],
|
||||
srcs = [
|
||||
"diskencryption.go",
|
||||
"diskencryption_cgo.go",
|
||||
"diskencryption_cross.go",
|
||||
],
|
||||
importpath = "github.com/edgelesssys/constellation/v2/bootstrapper/internal/diskencryption",
|
||||
visibility = ["//bootstrapper:__subpackages__"],
|
||||
deps = [
|
||||
deps = select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"@com_github_martinjungblut_go_cryptsetup//:go-cryptsetup",
|
||||
"@com_github_spf13_afero//:afero",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"@com_github_martinjungblut_go_cryptsetup//:go-cryptsetup",
|
||||
"@com_github_spf13_afero//:afero",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
go_test(
|
||||
@ -18,12 +29,21 @@ go_test(
|
||||
embed = [":diskencryption"],
|
||||
# keep
|
||||
tags = ["manual"],
|
||||
deps = [
|
||||
deps = select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"@com_github_spf13_afero//:afero",
|
||||
"@com_github_stretchr_testify//assert",
|
||||
"@com_github_stretchr_testify//require",
|
||||
"@org_uber_go_goleak//:goleak",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"@com_github_spf13_afero//:afero",
|
||||
"@com_github_stretchr_testify//assert",
|
||||
"@com_github_stretchr_testify//require",
|
||||
"@org_uber_go_goleak//:goleak",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
go_ld_test(
|
||||
|
@ -11,121 +11,3 @@ 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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/martinjungblut/go-cryptsetup"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
const (
|
||||
stateMapperDevice = "state"
|
||||
initialKeyPath = "/run/cryptsetup-keys.d/state.key"
|
||||
keyslot = 0
|
||||
)
|
||||
|
||||
var (
|
||||
// packageLock is needed to block concurrent use of package functions, since libcryptsetup is not thread safe.
|
||||
// See: https://gitlab.com/cryptsetup/cryptsetup/-/issues/710
|
||||
// https://stackoverflow.com/questions/30553386/cryptsetup-backend-safe-with-multithreading
|
||||
packageLock = sync.Mutex{}
|
||||
errDeviceNotOpen = errors.New("cryptdevice not open")
|
||||
errDeviceAlreadyOpen = errors.New("cryptdevice already open")
|
||||
)
|
||||
|
||||
// Cryptsetup manages the encrypted state mapper device.
|
||||
type Cryptsetup struct {
|
||||
fs afero.Fs
|
||||
device cryptdevice
|
||||
initByName initByName
|
||||
}
|
||||
|
||||
// New creates a new Cryptsetup.
|
||||
func New() *Cryptsetup {
|
||||
return &Cryptsetup{
|
||||
fs: afero.NewOsFs(),
|
||||
initByName: func(name string) (cryptdevice, error) {
|
||||
return cryptsetup.InitByName(name)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Open opens the cryptdevice.
|
||||
func (c *Cryptsetup) Open() error {
|
||||
packageLock.Lock()
|
||||
defer packageLock.Unlock()
|
||||
if c.device != nil {
|
||||
return errDeviceAlreadyOpen
|
||||
}
|
||||
var err error
|
||||
c.device, err = c.initByName(stateMapperDevice)
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing crypt device for mapped device %q: %w", stateMapperDevice, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close closes the cryptdevice.
|
||||
func (c *Cryptsetup) Close() error {
|
||||
packageLock.Lock()
|
||||
defer packageLock.Unlock()
|
||||
if c.device == nil {
|
||||
return errDeviceNotOpen
|
||||
}
|
||||
c.device.Free()
|
||||
c.device = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// UUID gets the device's UUID.
|
||||
// Only works after calling Open().
|
||||
func (c *Cryptsetup) UUID() (string, error) {
|
||||
packageLock.Lock()
|
||||
defer packageLock.Unlock()
|
||||
if c.device == nil {
|
||||
return "", errDeviceNotOpen
|
||||
}
|
||||
uuid := c.device.GetUUID()
|
||||
if uuid == "" {
|
||||
return "", fmt.Errorf("unable to get UUID for mapped device %q", stateMapperDevice)
|
||||
}
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// UpdatePassphrase switches the initial random passphrase of the mapped crypt device to a permanent passphrase.
|
||||
// Only works after calling Open().
|
||||
func (c *Cryptsetup) UpdatePassphrase(passphrase string) error {
|
||||
packageLock.Lock()
|
||||
defer packageLock.Unlock()
|
||||
if c.device == nil {
|
||||
return errDeviceNotOpen
|
||||
}
|
||||
initialPassphrase, err := c.getInitialPassphrase()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.device.KeyslotChangeByPassphrase(keyslot, keyslot, initialPassphrase, passphrase); err != nil {
|
||||
return fmt.Errorf("changing passphrase for mapped device %q: %w", stateMapperDevice, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getInitialPassphrase retrieves the initial passphrase used on first boot.
|
||||
func (c *Cryptsetup) 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 {
|
||||
GetUUID() string
|
||||
KeyslotChangeByPassphrase(currentKeyslot int, newKeyslot int, currentPassphrase string, newPassphrase string) error
|
||||
Free() bool
|
||||
}
|
||||
|
||||
type initByName func(name string) (cryptdevice, error)
|
||||
|
127
bootstrapper/internal/diskencryption/diskencryption_cgo.go
Normal file
127
bootstrapper/internal/diskencryption/diskencryption_cgo.go
Normal file
@ -0,0 +1,127 @@
|
||||
//go:build linux && cgo
|
||||
|
||||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package diskencryption
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/martinjungblut/go-cryptsetup"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
const (
|
||||
stateMapperDevice = "state"
|
||||
initialKeyPath = "/run/cryptsetup-keys.d/state.key"
|
||||
keyslot = 0
|
||||
)
|
||||
|
||||
var (
|
||||
// packageLock is needed to block concurrent use of package functions, since libcryptsetup is not thread safe.
|
||||
// See: https://gitlab.com/cryptsetup/cryptsetup/-/issues/710
|
||||
// https://stackoverflow.com/questions/30553386/cryptsetup-backend-safe-with-multithreading
|
||||
packageLock = sync.Mutex{}
|
||||
errDeviceNotOpen = errors.New("cryptdevice not open")
|
||||
errDeviceAlreadyOpen = errors.New("cryptdevice already open")
|
||||
)
|
||||
|
||||
// Cryptsetup manages the encrypted state mapper device.
|
||||
type Cryptsetup struct {
|
||||
fs afero.Fs
|
||||
device cryptdevice
|
||||
initByName initByName
|
||||
}
|
||||
|
||||
// New creates a new Cryptsetup.
|
||||
func New() *Cryptsetup {
|
||||
return &Cryptsetup{
|
||||
fs: afero.NewOsFs(),
|
||||
initByName: func(name string) (cryptdevice, error) {
|
||||
return cryptsetup.InitByName(name)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Open opens the cryptdevice.
|
||||
func (c *Cryptsetup) Open() error {
|
||||
packageLock.Lock()
|
||||
defer packageLock.Unlock()
|
||||
if c.device != nil {
|
||||
return errDeviceAlreadyOpen
|
||||
}
|
||||
var err error
|
||||
c.device, err = c.initByName(stateMapperDevice)
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing crypt device for mapped device %q: %w", stateMapperDevice, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close closes the cryptdevice.
|
||||
func (c *Cryptsetup) Close() error {
|
||||
packageLock.Lock()
|
||||
defer packageLock.Unlock()
|
||||
if c.device == nil {
|
||||
return errDeviceNotOpen
|
||||
}
|
||||
c.device.Free()
|
||||
c.device = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// UUID gets the device's UUID.
|
||||
// Only works after calling Open().
|
||||
func (c *Cryptsetup) UUID() (string, error) {
|
||||
packageLock.Lock()
|
||||
defer packageLock.Unlock()
|
||||
if c.device == nil {
|
||||
return "", errDeviceNotOpen
|
||||
}
|
||||
uuid := c.device.GetUUID()
|
||||
if uuid == "" {
|
||||
return "", fmt.Errorf("unable to get UUID for mapped device %q", stateMapperDevice)
|
||||
}
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// UpdatePassphrase switches the initial random passphrase of the mapped crypt device to a permanent passphrase.
|
||||
// Only works after calling Open().
|
||||
func (c *Cryptsetup) UpdatePassphrase(passphrase string) error {
|
||||
packageLock.Lock()
|
||||
defer packageLock.Unlock()
|
||||
if c.device == nil {
|
||||
return errDeviceNotOpen
|
||||
}
|
||||
initialPassphrase, err := c.getInitialPassphrase()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.device.KeyslotChangeByPassphrase(keyslot, keyslot, initialPassphrase, passphrase); err != nil {
|
||||
return fmt.Errorf("changing passphrase for mapped device %q: %w", stateMapperDevice, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getInitialPassphrase retrieves the initial passphrase used on first boot.
|
||||
func (c *Cryptsetup) 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 {
|
||||
GetUUID() string
|
||||
KeyslotChangeByPassphrase(currentKeyslot int, newKeyslot int, currentPassphrase string, newPassphrase string) error
|
||||
Free() bool
|
||||
}
|
||||
|
||||
type initByName func(name string) (cryptdevice, error)
|
50
bootstrapper/internal/diskencryption/diskencryption_cross.go
Normal file
50
bootstrapper/internal/diskencryption/diskencryption_cross.go
Normal file
@ -0,0 +1,50 @@
|
||||
//go:build !linux || !cgo
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
import "errors"
|
||||
|
||||
// Cryptsetup manages the encrypted state mapper device.
|
||||
type Cryptsetup struct{}
|
||||
|
||||
// New creates a new Cryptsetup.
|
||||
// This function panics if CGO is disabled.
|
||||
func New() *Cryptsetup {
|
||||
return &Cryptsetup{}
|
||||
}
|
||||
|
||||
// Open opens the cryptdevice.
|
||||
// This function does nothing if CGO is disabled.
|
||||
func (c *Cryptsetup) Open() error {
|
||||
return errors.New("using cryptsetup requires building with CGO")
|
||||
}
|
||||
|
||||
// Close closes the cryptdevice.
|
||||
// This function errors if CGO is disabled.
|
||||
func (c *Cryptsetup) Close() error {
|
||||
return errors.New("using cryptsetup requires building with CGO")
|
||||
}
|
||||
|
||||
// UUID gets the device's UUID.
|
||||
// This function errors if CGO is disabled.
|
||||
func (c *Cryptsetup) UUID() (string, error) {
|
||||
return "", errors.New("using cryptsetup requires building with CGO")
|
||||
}
|
||||
|
||||
// UpdatePassphrase switches the initial random passphrase of the mapped crypt device to a permanent passphrase.
|
||||
// This function errors if CGO is disabled.
|
||||
func (c *Cryptsetup) UpdatePassphrase(_ string) error {
|
||||
return errors.New("using cryptsetup requires building with CGO")
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
//go:build linux && cgo
|
||||
|
||||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user