mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-05-06 08:15:48 -04:00
Replace logging with default logging interface (#233)
* Add test logger * Refactor access manager logging * Refactor activation service logging * Refactor debugd logging * Refactor kms server logging * Refactor disk-mapper logging Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
e3f78a5bff
commit
b10b13b173
42 changed files with 513 additions and 328 deletions
|
@ -2,8 +2,8 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
@ -12,7 +12,10 @@ import (
|
|||
|
||||
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||
"github.com/edgelesssys/constellation/internal/logger"
|
||||
"github.com/spf13/afero"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
v1Options "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -30,7 +33,7 @@ const (
|
|||
// evictedHomePath holds the directory to which deleted user directories are moved to.
|
||||
evictedHomePath = "/var/evicted"
|
||||
|
||||
// relativePathToSSHKeys holds the path inside an user's directory to the SSH keys.
|
||||
// relativePathToSSHKeys holds the path inside a user's directory to the SSH keys.
|
||||
// Needs to be in sync with internal/deploy/ssh.go.
|
||||
relativePathToSSHKeys = ".ssh/authorized_keys.d/constellation-ssh-keys"
|
||||
|
||||
|
@ -45,33 +48,35 @@ type uidGIDPair struct {
|
|||
}
|
||||
|
||||
func main() {
|
||||
log := logger.New(logger.JSONLog, zapcore.InfoLevel)
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
log.Println("Starting constellation-access-manager as unknown pod.")
|
||||
log.Warnf("Starting constellation-access-manager as unknown pod")
|
||||
} else {
|
||||
log.Println("Starting constellation-access-manager as", hostname)
|
||||
log.Infof("Starting constellation-access-manager as %q", hostname)
|
||||
}
|
||||
|
||||
// Retrieve configMap from Kubernetes API before we chroot into the host filesystem.
|
||||
configMap, err := retrieveConfigMap()
|
||||
configMap, err := retrieveConfigMap(log)
|
||||
if err != nil {
|
||||
log.Panicf("Failed to retrieve ConfigMap from Kubernetes API: %v", err)
|
||||
log.With(zap.Error(err)).Fatalf("Failed to retrieve ConfigMap from Kubernetes API")
|
||||
}
|
||||
|
||||
// Chroot into main system
|
||||
if err := syscall.Chroot(hostPath); err != nil {
|
||||
log.Panicf("Failed to chroot into host filesystem: %v", err)
|
||||
log.With(zap.Error(err)).Fatalf("Failed to chroot into host filesystem")
|
||||
}
|
||||
if err := syscall.Chdir("/"); err != nil {
|
||||
log.Panicf("Failed to chdir into host filesystem: %v", err)
|
||||
log.With(zap.Error(err)).Fatalf("Failed to chdir into host filesystem")
|
||||
}
|
||||
|
||||
fs := afero.NewOsFs()
|
||||
linuxUserManager := user.NewLinuxUserManager(fs)
|
||||
|
||||
if err := run(fs, linuxUserManager, configMap); err != nil {
|
||||
if err := run(log, fs, linuxUserManager, configMap); err != nil {
|
||||
// So far there is only one error path in this code, and this is getting the user directories... So just make the error specific here for now.
|
||||
log.Panicf("Failed to retrieve existing user directories: %v", err)
|
||||
log.With(zap.Error(err)).Fatalf("Failed to retrieve existing user directories")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,21 +97,28 @@ func loadClientSet() (*kubernetes.Clientset, error) {
|
|||
}
|
||||
|
||||
// deployKeys creates or evicts users based on the ConfigMap and deploy their SSH keys.
|
||||
func deployKeys(ctx context.Context, configMap *v1.ConfigMap, fs afero.Fs, linuxUserManager user.LinuxUserManager, userMap map[string]uidGIDPair, sshAccess *ssh.Access) {
|
||||
func deployKeys(
|
||||
ctx context.Context, log *logger.Logger, configMap *v1.ConfigMap, fs afero.Fs,
|
||||
linuxUserManager user.LinuxUserManager, userMap map[string]uidGIDPair, sshAccess *ssh.Access,
|
||||
) {
|
||||
// If no ConfigMap exists or has been emptied, evict all users and exit.
|
||||
if configMap == nil || len(configMap.Data) == 0 {
|
||||
for username, ownership := range userMap {
|
||||
log := log.With(zap.String("username", username))
|
||||
if username != "root" {
|
||||
evictedUserPath := path.Join(evictedHomePath, username)
|
||||
log.Printf("Evicting '%s' with previous UID '%d' and GID '%d' to %s.\n", username, ownership.UID, ownership.GID, evictedUserPath)
|
||||
log.With(zap.Uint32("UID", ownership.UID), zap.Uint32("GID", ownership.GID)).
|
||||
Infof("Evicting user to %q", evictedUserPath)
|
||||
|
||||
if err := evictUser(username, fs, linuxUserManager); err != nil {
|
||||
log.Printf("Did not evict '%s': %v\n", username, err)
|
||||
log.With(zap.Error(err)).Errorf("Did not evict user")
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
log.Infof("Removing any old keys for 'root', if existent")
|
||||
// Remove root's SSH key specifically instead of evicting the whole directory.
|
||||
if err := evictRootKey(fs, linuxUserManager); err != nil && !os.IsNotExist(err) {
|
||||
log.Printf("Failed to remove previously existing root key: %v\n", err)
|
||||
log.With(zap.Error(err)).Errorf("Failed to remove previously existing root key")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -118,25 +130,36 @@ func deployKeys(ctx context.Context, configMap *v1.ConfigMap, fs afero.Fs, linux
|
|||
// First, recreate users that already existed, if they are defined in the configMap.
|
||||
// For users which do not exist, we move their user directories to avoid accidental takeovers but also loss of data.
|
||||
for username, ownership := range userMap {
|
||||
log := log.With(zap.String("username", username))
|
||||
if username != "root" {
|
||||
if _, ok := configMap.Data[username]; ok {
|
||||
log.Printf("Recreating '%s' with UID %d and GID %d, if not existent.\n", username, ownership.UID, ownership.GID)
|
||||
if err := linuxUserManager.Creator.CreateUserWithSpecificUIDAndGID(ctx, username, int(ownership.UID), int(ownership.GID)); err != nil {
|
||||
log.Printf("Did not recreate '%s': %v\n", username, err)
|
||||
log.With(zap.Uint32("UID", ownership.UID), zap.Uint32("GID", ownership.GID)).
|
||||
Infof("Recreating user, if not existent")
|
||||
|
||||
if err := linuxUserManager.Creator.CreateUserWithSpecificUIDAndGID(
|
||||
ctx, username, int(ownership.UID), int(ownership.GID),
|
||||
); err != nil {
|
||||
if errors.Is(err, user.ErrUserOrGroupAlreadyExists) {
|
||||
log.Infof("User already exists, skipping")
|
||||
} else {
|
||||
log.With(zap.Error(err)).Errorf("Failed to recreate user")
|
||||
}
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
evictedUserPath := path.Join(evictedHomePath, username)
|
||||
log.Printf("Evicting '%s' with previous UID '%d' and GID '%d' to %s.\n", username, ownership.UID, ownership.GID, evictedUserPath)
|
||||
log.With(zap.Uint32("UID", ownership.UID), zap.Uint32("GID", ownership.GID)).
|
||||
Infof("Evicting user to %q", evictedUserPath)
|
||||
if err := evictUser(username, fs, linuxUserManager); err != nil {
|
||||
log.Printf("Did not to evict '%s': %v\n", username, err)
|
||||
log.With(zap.Error(err)).Errorf("Did not evict user")
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Infof("Removing any old keys for 'root', if existent")
|
||||
// Always remove the root key first, even if it is about to be redeployed.
|
||||
if err := evictRootKey(fs, linuxUserManager); err != nil && !os.IsNotExist(err) {
|
||||
log.Printf("Failed to remove previously existing root key: %v\n", err)
|
||||
log.With(zap.Error(err)).Errorf("Failed to remove previously existing root key")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -144,25 +167,30 @@ func deployKeys(ctx context.Context, configMap *v1.ConfigMap, fs afero.Fs, linux
|
|||
|
||||
// Then, create the remaining users from the configMap (if remaining) and deploy SSH keys for all users.
|
||||
for username, publicKey := range configMap.Data {
|
||||
log := log.With(zap.String("username", username))
|
||||
if _, ok := userMap[username]; !ok {
|
||||
log.Printf("Creating user '%s'\n", username)
|
||||
log.Infof("Creating user")
|
||||
if err := linuxUserManager.Creator.CreateUser(ctx, username); err != nil {
|
||||
log.Printf("Failed to create '%s': %v\n", username, err)
|
||||
if errors.Is(err, user.ErrUserOrGroupAlreadyExists) {
|
||||
log.Infof("User already exists, skipping")
|
||||
} else {
|
||||
log.With(zap.Error(err)).Errorf("Failed to create user")
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// If we created an user, let's actually get the home directory instead of assuming it's the same as the normal home directory.
|
||||
// If we created a user, let's actually get the home directory instead of assuming it's the same as the normal home directory.
|
||||
user, err := linuxUserManager.GetLinuxUser(username)
|
||||
if err != nil {
|
||||
log.Printf("Failed to retrieve information about user '%s': %v\n", username, err)
|
||||
log.With(zap.Error(err)).Errorf("Failed to retrieve information about user")
|
||||
continue
|
||||
}
|
||||
|
||||
// Delete already deployed keys
|
||||
pathToSSHKeys := filepath.Join(user.Home, relativePathToSSHKeys)
|
||||
if err := fs.Remove(pathToSSHKeys); err != nil && !os.IsNotExist(err) {
|
||||
log.Printf("Failed to delete remaining managed SSH keys for '%s': %v\n", username, err)
|
||||
log.With(zap.Error(err)).Errorf("Failed to delete remaining managed SSH keys for user")
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -172,15 +200,15 @@ func deployKeys(ctx context.Context, configMap *v1.ConfigMap, fs afero.Fs, linux
|
|||
PublicKey: publicKey,
|
||||
}
|
||||
|
||||
log.Printf("Deploying new SSH key for '%s'.\n", username)
|
||||
log.Infof("Deploying new SSH key for user")
|
||||
if err := sshAccess.DeployAuthorizedKey(context.Background(), newKey); err != nil {
|
||||
log.Printf("Failed to deploy SSH keys for '%s': %v\n", username, err)
|
||||
log.With(zap.Error(err)).Errorf("Failed to deploy SSH keys for user")
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// evictUser moves an user directory to evictedPath and changes their owner recursive to root.
|
||||
// evictUser moves a user directory to evictedPath and changes their owner recursive to root.
|
||||
func evictUser(username string, fs afero.Fs, linuxUserManager user.LinuxUserManager) error {
|
||||
if _, err := linuxUserManager.GetLinuxUser(username); err == nil {
|
||||
return fmt.Errorf("user '%s' still seems to exist", username)
|
||||
|
@ -219,7 +247,6 @@ func evictUser(username string, fs afero.Fs, linuxUserManager user.LinuxUserMana
|
|||
|
||||
// evictRootKey removes the root key from the filesystem, instead of evicting the whole user directory.
|
||||
func evictRootKey(fs afero.Fs, linuxUserManager user.LinuxUserManager) error {
|
||||
log.Println("Removing any old keys for 'root', if existent.")
|
||||
user, err := linuxUserManager.GetLinuxUser("root")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -235,9 +262,9 @@ func evictRootKey(fs afero.Fs, linuxUserManager user.LinuxUserManager) error {
|
|||
}
|
||||
|
||||
// retrieveConfigMap contacts the Kubernetes API server and retrieves the ssh-users ConfigMap.
|
||||
func retrieveConfigMap() (*v1.ConfigMap, error) {
|
||||
func retrieveConfigMap(log *logger.Logger) (*v1.ConfigMap, error) {
|
||||
// Authenticate with the Kubernetes API and get the information from the ssh-users ConfigMap to recreate the users we need.
|
||||
log.Println("Authenticating with Kubernetes...")
|
||||
log.Infof("Authenticating with Kubernetes...")
|
||||
clientset, err := loadClientSet()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -246,7 +273,7 @@ func retrieveConfigMap() (*v1.ConfigMap, error) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
log.Println("Requesting 'ssh-users' ConfigMap...")
|
||||
log.Infof("Requesting 'ssh-users' ConfigMap...")
|
||||
configmap, err := clientset.CoreV1().ConfigMaps("kube-system").Get(ctx, "ssh-users", v1Options.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -256,7 +283,7 @@ func retrieveConfigMap() (*v1.ConfigMap, error) {
|
|||
}
|
||||
|
||||
// generateUserMap iterates the list of existing home directories to create a map of previously existing usernames to their previous respective UID and GID.
|
||||
func generateUserMap(fs afero.Fs) (map[string]uidGIDPair, error) {
|
||||
func generateUserMap(log *logger.Logger, fs afero.Fs) (map[string]uidGIDPair, error) {
|
||||
// Go through the normalHomePath directory, and create a mapping of existing user names in combination with their owner's UID & GID.
|
||||
// We use this information later to create missing users under the same UID and GID to avoid breakage.
|
||||
fileInfo, err := afero.ReadDir(fs, normalHomePath)
|
||||
|
@ -268,12 +295,14 @@ func generateUserMap(fs afero.Fs) (map[string]uidGIDPair, error) {
|
|||
userMap["root"] = uidGIDPair{UID: 0, GID: 0}
|
||||
// This will fail under MemMapFS, since it's not UNIX-compatible.
|
||||
for _, singleInfo := range fileInfo {
|
||||
log := log.With("username", singleInfo.Name())
|
||||
// Fail gracefully instead of hard.
|
||||
if stat, ok := singleInfo.Sys().(*syscall.Stat_t); ok {
|
||||
userMap[singleInfo.Name()] = uidGIDPair{UID: stat.Uid, GID: stat.Gid}
|
||||
log.Printf("Found home directory for '%s' (%d:%d).\n", singleInfo.Name(), stat.Uid, stat.Gid)
|
||||
log.With(zap.Uint32("UID", stat.Uid), zap.Uint32("GID", stat.Gid)).
|
||||
Infof("Found home directory for user")
|
||||
} else {
|
||||
log.Printf("WARNING: Failed to retrieve UNIX stat for %s. User will not be evicted, or if this directory belongs to an user that is to be created later, it might be created under a different UID/GID than before.\n", singleInfo.Name())
|
||||
log.Warnf("Failed to retrieve UNIX stat for user. User will not be evicted, or if this directory belongs to a user that is to be created later, it might be created under a different UID/GID than before")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -281,17 +310,17 @@ func generateUserMap(fs afero.Fs) (map[string]uidGIDPair, error) {
|
|||
return userMap, nil
|
||||
}
|
||||
|
||||
func run(fs afero.Fs, linuxUserManager user.LinuxUserManager, configMap *v1.ConfigMap) error {
|
||||
sshAccess := ssh.NewAccess(linuxUserManager)
|
||||
func run(log *logger.Logger, fs afero.Fs, linuxUserManager user.LinuxUserManager, configMap *v1.ConfigMap) error {
|
||||
sshAccess := ssh.NewAccess(log, linuxUserManager)
|
||||
|
||||
// Generate userMap containing existing user directories and their ownership
|
||||
userMap, err := generateUserMap(fs)
|
||||
userMap, err := generateUserMap(log, fs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Try to deploy keys based on configmap.
|
||||
deployKeys(context.Background(), configMap, fs, linuxUserManager, userMap, sshAccess)
|
||||
deployKeys(context.Background(), log, configMap, fs, linuxUserManager, userMap, sshAccess)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue