Delete old secretstore, cmd/node and config modules

This removes even more code that is no longer necessary or interferes with new concepts. It also refactors the storage stuff into a StorageManager which deals with all the paths and async initialization.

This does intentionally break a few things which will be fixed when the CA code lands.

Test Plan: Manually tested using make launch, CI is in a separate ticket

X-Origin-Diff: phab/D182
GitOrigin-RevId: 282a4bd84b47010d859e03da53b2c2de8183b13b
diff --git a/internal/storage/data.go b/internal/storage/data.go
index 30c6686..2ffd180 100644
--- a/internal/storage/data.go
+++ b/internal/storage/data.go
@@ -16,3 +16,150 @@
 
 package storage
 
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"smalltown/internal/common"
+	"smalltown/pkg/tpm"
+	"sync"
+
+	"go.uber.org/zap"
+	"golang.org/x/sys/unix"
+)
+
+const (
+	dataMountPath         = "/data"
+	espMountPath          = "/esp"
+	espDataPath           = espMountPath + "/EFI/smalltown"
+	etcdSealedKeyLocation = espDataPath + "/data-key.bin"
+)
+
+type Manager struct {
+	logger              *zap.Logger
+	dataReady           bool
+	initializationError error
+	mutex               sync.RWMutex
+}
+
+func Initialize(logger *zap.Logger) (*Manager, error) {
+	if err := FindPartitions(); err != nil {
+		return nil, err
+	}
+
+	if err := os.Mkdir("/esp", 0755); err != nil {
+		return nil, err
+	}
+
+	// We're mounting ESP sync for reliability, this lowers our chances of getting half-written files
+	if err := unix.Mount(ESPDevicePath, espMountPath, "vfat", unix.MS_NOEXEC|unix.MS_NODEV|unix.MS_SYNC, ""); err != nil {
+		return nil, err
+	}
+
+	manager := &Manager{
+		logger:    logger,
+		dataReady: false,
+	}
+
+	manager.mutex.Lock()
+	defer manager.mutex.Unlock()
+
+	sealedKeyFile, err := os.Open(etcdSealedKeyLocation)
+	if os.IsNotExist(err) {
+		logger.Info("Initializing encrypted storage, this might take a while...")
+		go manager.initializeData()
+	} else if err != nil {
+		return nil, err
+	} else {
+		sealedKey, err := ioutil.ReadAll(sealedKeyFile)
+		sealedKeyFile.Close()
+		if err != nil {
+			return nil, err
+		}
+		key, err := tpm.Unseal(sealedKey)
+		if err != nil {
+			return nil, err
+		}
+		if err := MapEncryptedBlockDevice("data", SmalltownDataCryptPath, key); err != nil {
+			return nil, err
+		}
+		if err := manager.mountData(); err != nil {
+			return nil, err
+		}
+		logger.Info("Mounted encrypted storage")
+	}
+	return manager, nil
+}
+
+func (s *Manager) initializeData() {
+	key, err := tpm.GenerateSafeKey(256 / 8)
+	if err != nil {
+		s.logger.Error("Failed to generate master key", zap.Error(err))
+		s.initializationError = fmt.Errorf("Failed to generate master key: %w", err)
+		return
+	}
+	sealedKey, err := tpm.Seal(key, tpm.FullSystemPCRs)
+	if err != nil {
+		s.logger.Error("Failed to seal master key", zap.Error(err))
+		s.initializationError = fmt.Errorf("Failed to seal master key: %w", err)
+		return
+	}
+	if err := InitializeEncryptedBlockDevice("data", SmalltownDataCryptPath, key); err != nil {
+		s.logger.Error("Failed to initialize encrypted block device", zap.Error(err))
+		s.initializationError = fmt.Errorf("Failed to initialize encrypted block device: %w", err)
+		return
+	}
+	mkfsCmd := exec.Command("/bin/mkfs.xfs", "-qf", "/dev/data")
+	if _, err := mkfsCmd.Output(); err != nil {
+		s.logger.Error("Failed to format encrypted block device", zap.Error(err))
+		s.initializationError = fmt.Errorf("Failed to format encrypted block device: %w", err)
+		return
+	}
+	// This file is the marker if the partition has
+	if err := ioutil.WriteFile(etcdSealedKeyLocation, sealedKey, 0600); err != nil {
+		panic(err)
+	}
+
+	if err := s.mountData(); err != nil {
+		s.initializationError = err
+		return
+	}
+
+	s.mutex.Lock()
+	s.dataReady = true
+	s.mutex.Unlock()
+
+	s.logger.Info("Initialized encrypted storage")
+}
+
+func (s *Manager) mountData() error {
+	if err := os.Mkdir("/data", 0755); err != nil {
+		return err
+	}
+
+	if err := unix.Mount("/dev/data", "/data", "xfs", unix.MS_NOEXEC|unix.MS_NODEV, ""); err != nil {
+		return err
+	}
+	return nil
+}
+
+// GetPathInPlace returns a path in the given place
+// It may return ErrNotInitialized if the place you're trying to access
+// is not initialized or ErrUnknownPlace if the place is not known
+func (s *Manager) GetPathInPlace(place common.DataPlace, path string) (string, error) {
+	s.mutex.RLock()
+	defer s.mutex.RUnlock()
+	switch place {
+	case common.PlaceESP:
+		return filepath.Join(espDataPath, path), nil
+	case common.PlaceData:
+		if s.dataReady {
+			return filepath.Join(dataMountPath, path), nil
+		}
+		return "", common.ErrNotInitialized
+	default:
+		return "", common.ErrUnknownPlace
+	}
+}
diff --git a/internal/storage/xfs.go b/internal/storage/xfs.go
new file mode 100644
index 0000000..30c6686
--- /dev/null
+++ b/internal/storage/xfs.go
@@ -0,0 +1,18 @@
+// Copyright 2020 The Monogon Project Authors.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+