diff --git a/cmd/spiffe-helper/config/config.go b/cmd/spiffe-helper/config/config.go index f3f1b5c..29aa14a 100644 --- a/cmd/spiffe-helper/config/config.go +++ b/cmd/spiffe-helper/config/config.go @@ -26,6 +26,7 @@ type Config struct { AgentAddressDeprecated string `hcl:"agentAddress"` Cmd string `hcl:"cmd"` CmdArgs string `hcl:"cmd_args"` + PidFileName string `hcl:"pid_file_name"` CmdArgsDeprecated string `hcl:"cmdArgs"` CertDir string `hcl:"cert_dir"` CertDirDeprecated string `hcl:"certDir"` @@ -203,6 +204,7 @@ func NewSidecarConfig(config *Config, log logrus.FieldLogger) *sidecar.Config { AgentAddress: config.AgentAddress, Cmd: config.Cmd, CmdArgs: config.CmdArgs, + PidFileName: config.PidFileName, CertDir: config.CertDir, CertFileMode: fs.FileMode(config.CertFileMode), //nolint:gosec,G115 KeyFileMode: fs.FileMode(config.KeyFileMode), //nolint:gosec,G115 diff --git a/pkg/sidecar/config.go b/pkg/sidecar/config.go index c269486..1000716 100644 --- a/pkg/sidecar/config.go +++ b/pkg/sidecar/config.go @@ -20,6 +20,9 @@ type Config struct { // The arguments of the process to launch. CmdArgs string + // Signal external process via PID file + PidFileName string + // The directory name to store the x509s and/or JWTs. CertDir string diff --git a/pkg/sidecar/sidecar.go b/pkg/sidecar/sidecar.go index 45deefa..1159cfd 100644 --- a/pkg/sidecar/sidecar.go +++ b/pkg/sidecar/sidecar.go @@ -1,11 +1,13 @@ package sidecar import ( + "bytes" "context" "encoding/csv" "fmt" "os" "os/exec" + "strconv" "strings" "sync" "sync/atomic" @@ -170,10 +172,8 @@ func (s *Sidecar) updateCertificates(svidResponse *workloadapi.X509Context) { } s.config.Log.Info("X.509 certificates updated") - if s.config.Cmd != "" { - if err := s.signalProcess(); err != nil { - s.config.Log.WithError(err).Error("Unable to signal process") - } + if err := s.signalProcess(); err != nil { + s.config.Log.WithError(err).Error("Unable to signal process") } select { @@ -185,27 +185,46 @@ func (s *Sidecar) updateCertificates(svidResponse *workloadapi.X509Context) { // signalProcess sends the configured Renew signal to the process running the proxy // to reload itself so that the proxy uses the new SVID func (s *Sidecar) signalProcess() (err error) { + if s.config.PidFileName != "" { + byts, err := os.ReadFile(s.config.PidFileName) + if err != nil { + return fmt.Errorf("failed to read pid file: %s\n%w", s.config.PidFileName, err) + } + pid, err := strconv.Atoi(string(bytes.TrimSpace(byts))) + if err != nil { + return fmt.Errorf("failed to parse pid file: %s\n%w", s.config.PidFileName, err) + } + s.process, err = os.FindProcess(pid) + if err != nil { + return fmt.Errorf("failed to find process: %d\n%w", pid, err) + } + if err := s.SignalProcess(); err != nil { + return err + } + } // TODO: is ReloadExternalProcess still used? switch s.config.ReloadExternalProcess { case nil: - if atomic.LoadInt32(&s.processRunning) == 0 { - cmdArgs, err := getCmdArgs(s.config.CmdArgs) - if err != nil { - return fmt.Errorf("error parsing cmd arguments: %w", err) - } - - cmd := exec.Command(s.config.Cmd, cmdArgs...) // #nosec - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err = cmd.Start() - if err != nil { - return fmt.Errorf("error executing process: %v\n%w", s.config.Cmd, err) - } - s.process = cmd.Process - go s.checkProcessExit() - } else { - if err := s.SignalProcess(); err != nil { - return err + if s.config.Cmd != "" { + if atomic.LoadInt32(&s.processRunning) == 0 { + cmdArgs, err := getCmdArgs(s.config.CmdArgs) + if err != nil { + return fmt.Errorf("error parsing cmd arguments: %w", err) + } + + cmd := exec.Command(s.config.Cmd, cmdArgs...) // #nosec + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Start() + if err != nil { + return fmt.Errorf("error executing process: %v\n%w", s.config.Cmd, err) + } + s.process = cmd.Process + go s.checkProcessExit() + } else { + if err := s.SignalProcess(); err != nil { + return err + } } }