Skip to content

Commit

Permalink
Merge branch 'main' into hint
Browse files Browse the repository at this point in the history
Signed-off-by: kfox1111 <[email protected]>
  • Loading branch information
kfox1111 authored Jan 29, 2025
2 parents be5159e + a2320d1 commit b31e34f
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 59 deletions.
48 changes: 29 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,35 @@ The flag `-exitWhenReady` is also supported.
## Configuration
The configuration file is an [HCL](https://github.com/hashicorp/hcl) formatted file that defines the following configurations:

| Configuration | Description | Example Value |
|-------------------------------|----------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_address` | Socket address of SPIRE Agent. | `"/tmp/agent.sock"` |
| `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"` |
| `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"` |
| `svid_key_file_name` | File name to be used to store the X.509 SVID private key and public certificate in PEM format. | `"svid_key.pem"` |
| `svid_bundle_file_name` | File name to be used to store the X.509 SVID Bundle in PEM format. | `"svid_bundle.pem"` |
| `jwt_svids` | An array with the audience, optional extra audiences array, and file name to store the JWT SVIDs. File is Base64-encoded string). | `[{jwt_audience="your-audience", jwt_extra_audiences=["your-extra-audience-1", "your-extra-audience-2"], jwt_svid_file_name="jwt_svid.token"}]` |
| `jwt_bundle_file_name` | File name to be used to store JWT Bundle in JSON format. | `"jwt_bundle.json"` |
| `include_federated_domains` | Include trust domains from federated servers in the CA bundle. | `true` |
| `cert_file_mode` | The octal file mode to use when saving the X.509 public certificate file. | `0644` |
| `key_file_mode` | The octal file mode to use when saving the X.509 private key file. | `0600` |
| `jwt_bundle_file_mode` | The octal file mode to use when saving a JWT Bundle file. | `0600` |
| `jwt_svid_file_mode` | The octal file mode to use when saving a JWT SVID file. | `0600` |
| Configuration | Description | Example Value |
|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_address` | Socket address of SPIRE Agent. | `"/tmp/agent.sock"` |
| `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"` |
| `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"` |
| `svid_key_file_name` | File name to be used to store the X.509 SVID private key and public certificate in PEM format. | `"svid_key.pem"` |
| `svid_bundle_file_name` | File name to be used to store the X.509 SVID Bundle in PEM format. | `"svid_bundle.pem"` |
| `jwt_svids` | An array with the audience, optional extra audiences array, and file name to store the JWT SVIDs. File is Base64-encoded string). | `[{jwt_audience="your-audience", jwt_extra_audiences=["your-extra-audience-1", "your-extra-audience-2"], jwt_svid_file_name="jwt_svid.token"}]` |
| `jwt_bundle_file_name` | File name to be used to store JWT Bundle in JSON format. | `"jwt_bundle.json"` |
| `include_federated_domains` | Include trust domains from federated servers in the CA bundle. | `true` |
| `cert_file_mode` | The octal file mode to use when saving the X.509 public certificate file. | `0644` |
| `key_file_mode` | The octal file mode to use when saving the X.509 private key file. | `0600` |
| `jwt_bundle_file_mode` | The octal file mode to use when saving a JWT Bundle file. | `0600` |
| `jwt_svid_file_mode` | The octal file mode to use when saving a JWT SVID file. | `0600` |

### Health Checks Configuration
SPIFFE Helper can expose and endpoint that can be used for health checking

| Configuration | Description | Example Value |
|----------------------------------|----------------------------------------------------------------------------------------------------------------------|---------------|
| `health_checks.listener_enabled` | Whether to start an HTTP server at the configured endpoint for the daemon health. Doesn't apply for non-daemon mode. | `false` |
| `health_checks.bind_port` | The port to run the HTTP health server. | `8081` |
| `health_checks.liveness_path` | The URL path for the liveness health check | `/live` |
| `health_checks.readiness_path` | The URL path for the readiness health check | `/readu` |

### Configuration example
```
Expand Down
59 changes: 44 additions & 15 deletions cmd/spiffe-helper/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/token"
"github.com/sirupsen/logrus"
"github.com/spiffe/spiffe-helper/pkg/health"
"github.com/spiffe/spiffe-helper/pkg/sidecar"
)

Expand All @@ -21,22 +22,26 @@ const (
defaultKeyFileMode = 0600
defaultJWTBundleFileMode = 0600
defaultJWTSVIDFileMode = 0600
defaultBindPort = 8081
defaultLivenessPath = "/live"
defaultReadinessPath = "/ready"
)

type Config struct {
AddIntermediatesToBundle bool `hcl:"add_intermediates_to_bundle"`
AgentAddress string `hcl:"agent_address"`
Cmd string `hcl:"cmd"`
CmdArgs string `hcl:"cmd_args"`
PIDFileName string `hcl:"pid_file_name"`
CertDir string `hcl:"cert_dir"`
CertFileMode int `hcl:"cert_file_mode"`
KeyFileMode int `hcl:"key_file_mode"`
JWTBundleFileMode int `hcl:"jwt_bundle_file_mode"`
JWTSVIDFileMode int `hcl:"jwt_svid_file_mode"`
IncludeFederatedDomains bool `hcl:"include_federated_domains"`
RenewSignal string `hcl:"renew_signal"`
DaemonMode *bool `hcl:"daemon_mode"`
AddIntermediatesToBundle bool `hcl:"add_intermediates_to_bundle"`
AgentAddress string `hcl:"agent_address"`
Cmd string `hcl:"cmd"`
CmdArgs string `hcl:"cmd_args"`
PIDFileName string `hcl:"pid_file_name"`
CertDir string `hcl:"cert_dir"`
CertFileMode int `hcl:"cert_file_mode"`
KeyFileMode int `hcl:"key_file_mode"`
JWTBundleFileMode int `hcl:"jwt_bundle_file_mode"`
JWTSVIDFileMode int `hcl:"jwt_svid_file_mode"`
IncludeFederatedDomains bool `hcl:"include_federated_domains"`
RenewSignal string `hcl:"renew_signal"`
DaemonMode *bool `hcl:"daemon_mode"`
HealthCheck health.CheckConfig `hcl:"health_checks"`
Hint string `hcl:"hint"`

// x509 configuration
Expand All @@ -59,8 +64,8 @@ type JWTConfig struct {
UnusedKeyPositions map[string][]token.Pos `hcl:",unusedKeyPositions"`
}

// ParseConfig parses the given HCL file into a Config struct
func ParseConfig(file string) (*Config, error) {
// ParseConfigFile parses the given HCL file into a Config struct
func ParseConfigFile(file string) (*Config, error) {
// Read HCL file
dat, err := os.ReadFile(file)
if err != nil {
Expand Down Expand Up @@ -159,6 +164,21 @@ func (c *Config) ValidateConfig(log logrus.FieldLogger) error {
c.JWTSVIDFileMode = defaultJWTSVIDFileMode
}

if c.HealthCheck.ListenerEnabled {
if c.HealthCheck.BindPort < 0 {
return errors.New("bind port must be positive")
}
if c.HealthCheck.BindPort == 0 {
c.HealthCheck.BindPort = defaultBindPort
}
if c.HealthCheck.LivenessPath == "" {
c.HealthCheck.LivenessPath = defaultLivenessPath
}
if c.HealthCheck.ReadinessPath == "" {
c.HealthCheck.ReadinessPath = defaultReadinessPath
}
}

return nil
}

Expand All @@ -177,6 +197,15 @@ func (c *Config) checkForUnknownConfig() error {
return nil
}

func ParseConfig(configFile string, daemonModeFlag bool, daemonModeFlagName string) (*Config, error) {
hclConfig, err := ParseConfigFile(configFile)
if err != nil {
return nil, fmt.Errorf("failed to parse %q: %w", configFile, err)
}
hclConfig.ParseConfigFlagOverrides(daemonModeFlag, daemonModeFlagName)
return hclConfig, nil
}

func NewSidecarConfig(config *Config, log logrus.FieldLogger) *sidecar.Config {
sidecarConfig := &sidecar.Config{
AddIntermediatesToBundle: config.AddIntermediatesToBundle,
Expand Down
4 changes: 2 additions & 2 deletions cmd/spiffe-helper/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
)

func TestParseConfig(t *testing.T) {
c, err := ParseConfig("testdata/helper.conf")
c, err := ParseConfigFile("testdata/helper.conf")

assert.NoError(t, err)

Expand Down Expand Up @@ -185,7 +185,7 @@ func TestDetectsUnknownConfig(t *testing.T) {
_, err = configFile.WriteString(tt.config)
require.NoError(t, err)

c, err := ParseConfig(configFile.Name())
c, err := ParseConfigFile(configFile.Name())
require.NoError(t, err)

log, _ := test.NewNullLogger()
Expand Down
Loading

0 comments on commit b31e34f

Please sign in to comment.