Skip to content

Commit

Permalink
Add daemon mode flag
Browse files Browse the repository at this point in the history
Signed-off-by: Faisal Memon <fymemon@yahoo.com>
  • Loading branch information
faisal-memon committed Jul 1, 2024
1 parent b637c18 commit 7bac373
Show file tree
Hide file tree
Showing 12 changed files with 470 additions and 177 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The configuration file is an [HCL](https://github.com/hashicorp/hcl) formatted f
| `cmd` | The path to the process to launch. | `"ghostunnel"` |
| `cmd_args` | The arguments of the process to launch. | `"server --listen localhost:8002 --target localhost:8001--keystore certs/svid_key.pem --cacert certs/svid_bundle.pem --allow-uri-san spiffe://example.org/Database"` |
| `cert_dir` | Directory name to store the fetched certificates. This directory must be created previously. | `"certs"` |
| `exit_when_ready` | Fetch x509 certificate and then exit(0) | `true` |
| `daemon_mode` | Toggle running as a daemon, keeping X.509 and JWT up to date; or just fetch X.509 and JWT and exit 0 | `true` |
| `add_intermediates_to_bundle` | Add intermediate certificates into Bundle file instead of SVID file. | `true` |
| `renew_signal` | The signal that the process to be launched expects to reload the certificates. It is not supported on Windows. | `"SIGUSR1"` |
| `svid_file_name` | File name to be used to store the X.509 SVID public certificate in PEM format. | `"svid.pem"` |
Expand Down
104 changes: 64 additions & 40 deletions cmd/spiffe-helper/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,51 +23,51 @@ type Config struct {
CmdArgsDeprecated string `hcl:"cmdArgs"`
CertDir string `hcl:"cert_dir"`
CertDirDeprecated string `hcl:"certDir"`
ExitWhenReady bool `hcl:"exit_when_ready"`
IncludeFederatedDomains bool `hcl:"include_federated_domains"`
RenewSignal string `hcl:"renew_signal"`
RenewSignalDeprecated string `hcl:"renewSignal"`
DaemonMode *bool `hcl:"daemon_mode"`

// x509 configuration
SvidFileName string `hcl:"svid_file_name"`
SvidFileNameDeprecated string `hcl:"svidFileName"`
SvidKeyFileName string `hcl:"svid_key_file_name"`
SvidKeyFileNameDeprecated string `hcl:"svidKeyFileName"`
SvidBundleFileName string `hcl:"svid_bundle_file_name"`
SvidBundleFileNameDeprecated string `hcl:"svidBundleFileName"`
SVIDFileName string `hcl:"svid_file_name"`
SVIDFileNameDeprecated string `hcl:"svidFileName"`
SVIDKeyFileName string `hcl:"svid_key_file_name"`
SVIDKeyFileNameDeprecated string `hcl:"svidKeyFileName"`
SVIDBundleFileName string `hcl:"svid_bundle_file_name"`
SVIDBundleFileNameDeprecated string `hcl:"svidBundleFileName"`

// JWT configuration
JwtSvids []JwtConfig `hcl:"jwt_svids"`
JWTSVIDs []JWTConfig `hcl:"jwt_svids"`
JWTBundleFilename string `hcl:"jwt_bundle_file_name"`
}

type JwtConfig struct {
type JWTConfig struct {
JWTAudience string `hcl:"jwt_audience"`
JWTSvidFilename string `hcl:"jwt_svid_file_name"`
JWTSVIDFilename string `hcl:"jwt_svid_file_name"`
}

// ParseConfig parses the given HCL file into a Config struct
func ParseConfig(file string) (*Config, error) {
sidecarConfig := new(Config)

// Read HCL file
dat, err := os.ReadFile(file)
if err != nil {
return nil, err
}

// Parse HCL
if err := hcl.Decode(sidecarConfig, string(dat)); err != nil {
config := new(Config)
if err := hcl.Decode(config, string(dat)); err != nil {
return nil, err
}

return sidecarConfig, nil
return config, nil
}

func ValidateConfig(c *Config, exitWhenReady bool, log logrus.FieldLogger) error {
func ValidateConfig(c *Config, disableDaemonMode bool, log logrus.FieldLogger) error {
if err := validateOSConfig(c); err != nil {
return err
}

if c.AgentAddressDeprecated != "" {
if c.AgentAddress != "" {
return errors.New("use of agent_address and agentAddress found, use only agent_address")
Expand All @@ -92,28 +92,28 @@ func ValidateConfig(c *Config, exitWhenReady bool, log logrus.FieldLogger) error
c.CertDir = c.CertDirDeprecated
}

if c.SvidFileNameDeprecated != "" {
if c.SvidFileName != "" {
if c.SVIDFileNameDeprecated != "" {
if c.SVIDFileName != "" {
return errors.New("use of svid_file_name and svidFileName found, use only svid_file_name")
}
log.Warn(getWarning("svidFileName", "svid_file_name"))
c.SvidFileName = c.SvidFileNameDeprecated
c.SVIDFileName = c.SVIDFileNameDeprecated
}

if c.SvidKeyFileNameDeprecated != "" {
if c.SvidKeyFileName != "" {
if c.SVIDKeyFileNameDeprecated != "" {
if c.SVIDKeyFileName != "" {
return errors.New("use of svid_key_file_name and svidKeyFileName found, use only svid_key_file_name")
}
log.Warn(getWarning("svidKeyFileName", "svid_key_file_name"))
c.SvidKeyFileName = c.SvidKeyFileNameDeprecated
c.SVIDKeyFileName = c.SVIDKeyFileNameDeprecated
}

if c.SvidBundleFileNameDeprecated != "" {
if c.SvidBundleFileName != "" {
if c.SVIDBundleFileNameDeprecated != "" {
if c.SVIDBundleFileName != "" {
return errors.New("use of svid_bundle_file_name and svidBundleFileName found, use only svid_bundle_file_name")
}
log.Warn(getWarning("svidBundleFileName", "svid_bundle_file_name"))
c.SvidBundleFileName = c.SvidBundleFileNameDeprecated
c.SVIDBundleFileName = c.SVIDBundleFileNameDeprecated
}

if c.RenewSignalDeprecated != "" {
Expand All @@ -124,8 +124,8 @@ func ValidateConfig(c *Config, exitWhenReady bool, log logrus.FieldLogger) error
c.RenewSignal = c.RenewSignalDeprecated
}

for _, jwtConfig := range c.JwtSvids {
if jwtConfig.JWTSvidFilename == "" {
for _, jwtConfig := range c.JWTSVIDs {
if jwtConfig.JWTSVIDFilename == "" {
return errors.New("'jwt_file_name' is required in 'jwt_svids'")
}
if jwtConfig.JWTAudience == "" {
Expand All @@ -140,16 +140,26 @@ func ValidateConfig(c *Config, exitWhenReady bool, log logrus.FieldLogger) error
}
}

c.ExitWhenReady = c.ExitWhenReady || exitWhenReady
x509Enabled, err := validateX509Config(c)
if err != nil {
return err
}

jwtBundleEnabled, jwtSVIDsEnabled := validateJWTConfig(c)

x509EmptyCount := countEmpty(c.SvidFileName, c.SvidBundleFileName, c.SvidKeyFileName)
jwtBundleEmptyCount := countEmpty(c.SvidBundleFileName)
if x509EmptyCount == 3 && len(c.JwtSvids) == 0 && jwtBundleEmptyCount == 1 {
if !x509Enabled && !jwtBundleEnabled && !jwtSVIDsEnabled {
return errors.New("at least one of the sets ('svid_file_name', 'svid_key_file_name', 'svid_bundle_file_name'), 'jwt_svids', or 'jwt_bundle_file_name' must be fully specified")
}

if x509EmptyCount != 0 && x509EmptyCount != 3 {
return errors.New("all or none of 'svid_file_name', 'svid_key_file_name', 'svid_bundle_file_name' must be specified")
var daemonMode bool
if disableDaemonMode {
// If daemon mode is disabled by CLI this takes precedence
daemonMode = false
c.DaemonMode = &daemonMode
} else if c.DaemonMode == nil {
// If daemon mode is not set, then default to true
daemonMode = true
c.DaemonMode = &daemonMode
}

return nil
Expand All @@ -162,25 +172,39 @@ func NewSidecarConfig(config *Config, log logrus.FieldLogger) *sidecar.Config {
Cmd: config.Cmd,
CmdArgs: config.CmdArgs,
CertDir: config.CertDir,
ExitWhenReady: config.ExitWhenReady,
JWTBundleFilename: config.JWTBundleFilename,
Log: log,
RenewSignal: config.RenewSignal,
SvidFileName: config.SvidFileName,
SvidKeyFileName: config.SvidKeyFileName,
SvidBundleFileName: config.SvidBundleFileName,
SVIDFileName: config.SVIDFileName,
SVIDKeyFileName: config.SVIDKeyFileName,
SVIDBundleFileName: config.SVIDBundleFileName,
}

for _, jwtSvid := range config.JwtSvids {
sidecarConfig.JwtSvids = append(sidecarConfig.JwtSvids, sidecar.JwtConfig{
JWTAudience: jwtSvid.JWTAudience,
JWTSvidFilename: jwtSvid.JWTSvidFilename,
for _, jwtSVID := range config.JWTSVIDs {
sidecarConfig.JWTSVIDs = append(sidecarConfig.JWTSVIDs, sidecar.JWTConfig{
JWTAudience: jwtSVID.JWTAudience,
JWTSVIDFilename: jwtSVID.JWTSVIDFilename,
})
}

return sidecarConfig
}

func validateX509Config(c *Config) (bool, error) {
x509EmptyCount := countEmpty(c.SVIDFileName, c.SVIDBundleFileName, c.SVIDKeyFileName)
if x509EmptyCount != 0 && x509EmptyCount != 3 {
return false, errors.New("all or none of 'svid_file_name', 'svid_key_file_name', 'svid_bundle_file_name' must be specified")
}

return x509EmptyCount == 0, nil
}

func validateJWTConfig(c *Config) (bool, bool) {
jwtBundleEmptyCount := countEmpty(c.SVIDBundleFileName)

return jwtBundleEmptyCount == 0, len(c.JWTSVIDs) > 0
}

func getWarning(s1 string, s2 string) string {
return s1 + " will be deprecated, should be used as " + s2
}
Expand Down
Loading

0 comments on commit 7bac373

Please sign in to comment.