...

Source file src/edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/plugins/clustersecrets/grub/grub.go

Documentation: edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/plugins/clustersecrets/grub

     1  package grub
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  
     7  	"github.com/hashicorp/go-multierror"
     8  	corev1 "k8s.io/api/core/v1"
     9  
    10  	"edge-infra.dev/pkg/edge/api/graph/model"
    11  	"edge-infra.dev/pkg/k8s/runtime/controller/reconcile"
    12  	"edge-infra.dev/pkg/sds/clustersecrets"
    13  	"edge-infra.dev/pkg/sds/clustersecrets/audit"
    14  	"edge-infra.dev/pkg/sds/clustersecrets/grub"
    15  	grubsecret "edge-infra.dev/pkg/sds/clustersecrets/grub"
    16  	grubfs "edge-infra.dev/pkg/sds/clustersecrets/grub/filesystem"
    17  	v1ien "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
    18  	"edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/config"
    19  	"edge-infra.dev/pkg/sds/ien/node"
    20  )
    21  
    22  var mount = true // for unit-tests we need to override this to false
    23  
    24  type Plugin struct{}
    25  
    26  func (plugin Plugin) Reconcile(ctx context.Context, ienode *v1ien.IENode, cfg config.Config) (reconcile.Result, error) {
    27  	secret, err := grub.FromClient(ctx, cfg.GetClient())
    28  	if err != nil {
    29  		return reconcile.ResultRequeue, err
    30  	}
    31  	if err := apply(secret, ienode, cfg); err != nil {
    32  		return reconcile.ResultRequeue, err
    33  	}
    34  	return reconcile.ResultSuccess, nil
    35  }
    36  
    37  func apply(grubSecret *corev1.Secret, ienode *v1ien.IENode, cfg config.Config) error {
    38  	secret, err := grub.FromSecret(grubSecret)
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	grubEntry := secret.String()
    44  	hasChanged, err := write(grubEntry, secret.Version())
    45  	if err != nil {
    46  		return err
    47  	}
    48  	if !hasChanged {
    49  		return nil
    50  	}
    51  
    52  	terminalID := ienode.ObjectMeta.Labels[node.TerminalIDLabel]
    53  
    54  	// status reporting
    55  	if ienode.Status.ClusterSecrets == nil {
    56  		ienode.Status.ClusterSecrets = &v1ien.ClusterSecretInventory{}
    57  	}
    58  	ienode.Status.ClusterSecrets.AddClusterSecret(grub.HashedSecretName, secret.Version(), terminalID)
    59  
    60  	eventRecorder := cfg.GetEventRecorder()
    61  	clustersecrets.RecordClusterSecretEvent(eventRecorder, grubSecret, secret, terminalID)
    62  	return nil
    63  }
    64  
    65  // write will take a grub entry and attempt to update the grub config file.
    66  // This is a safe write so the file is temporarily written to tmp directory and the
    67  // entire file is copied to /boot/efi/EFI/grub/grub.cfg or /boot/grub/grub.cfg
    68  func write(grubEntry, version string) (hasChanged bool, err error) {
    69  	rootPath := grubfs.MountPath()
    70  	filePath := grubfs.GrubFilePath()
    71  	currentContents, err := os.ReadFile(filePath) // figure out
    72  	if err != nil {
    73  		return false, err
    74  	}
    75  
    76  	hasChanged, contents, err := grubsecret.UpsertEntry(currentContents, grubEntry)
    77  	if err != nil {
    78  		return false, err
    79  	}
    80  	if !hasChanged {
    81  		return false, nil
    82  	}
    83  
    84  	// audit log indicating cluster secret is taking effect
    85  	auditLog := audit.New("nodeagent")
    86  	auditLog.Log(model.ClusterSecretTypeGrub, audit.SecretApplied, "action_by", "nodeagent", "version", version)
    87  
    88  	if mount {
    89  		// remount as read-write
    90  		cleanup, err := grubfs.Remount(rootPath)
    91  		if err != nil {
    92  			return false, err
    93  		}
    94  
    95  		// remount to read only on defer
    96  		defer func() {
    97  			cleanupErr := cleanup()
    98  			if cleanupErr != nil && err != nil {
    99  				err = multierror.Append(err, cleanupErr)
   100  				return
   101  			}
   102  			err = cleanupErr
   103  		}()
   104  	}
   105  
   106  	if err := os.WriteFile(filePath, contents, grubfs.FileMode); err != nil {
   107  		return false, err
   108  	}
   109  	return true, nil
   110  }
   111  

View as plain text