Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/go_modules/google.golang.org/grpc…
Browse files Browse the repository at this point in the history
…-1.60.0
  • Loading branch information
faisal-memon authored Dec 12, 2023
2 parents a596a9c + 3ba5715 commit 6ca090f
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 66 deletions.
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ If `-config` is not specified, the default value `helper.conf` is assumed.
## 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"` |
|`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"` |
| 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"` |
|`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_audience` | JWT SVID audience. | `"your-audience"` |
|`jwt_svid_file_name` | File name to be used to store JWT SVID in Base64-encoded string. | `"jwt_svid.token"` |
|`jwt_bundle_file_name` | File name to be used to store JWT Bundle in JSON format. | `"jwt_bundle.json"` |

### Configuration example
```
Expand All @@ -38,6 +41,9 @@ renew_signal = "SIGUSR1"
svid_file_name = "svid.pem"
svid_key_file_name = "svid_key.pem"
svid_bundle_file_name = "svid_bundle.pem"
jwt_audience = "your-audience"
jwt_svid_file_name = "jwt.token"
jwt_bundle_file_name = "bundle.json"
```

### Windows example
Expand All @@ -47,4 +53,7 @@ cert_dir = "certs"
svid_file_name = "svid.pem"
svid_key_file_name = "svid_key.pem"
svid_bundle_file_name = "svid_bundle.pem"
jwt_audience = "your-audience"
jwt_svid_file_name = "jwt.token"
jwt_bundle_file_name = "bundle.json"
```
40 changes: 31 additions & 9 deletions pkg/sidecar/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ type Config struct {
SvidBundleFileNameDeprecated string `hcl:"svidBundleFileName"`
RenewSignal string `hcl:"renew_signal"`
RenewSignalDeprecated string `hcl:"renewSignal"`

// JWT configuration
JWTAudience string `hcl:"jwt_audience"`
JWTSvidFilename string `hcl:"jwt_svid_file_name"`
JWTBundleFilename string `hcl:"jwt_bundle_file_name"`

// TODO: is there a reason for this to be exposed? and inside of config?
ReloadExternalProcess func() error
// TODO: is there a reason for this to be exposed? and inside of config?
Expand Down Expand Up @@ -114,18 +120,34 @@ func ValidateConfig(c *Config) error {
c.RenewSignal = c.RenewSignalDeprecated
}

switch {
case c.SvidFileName == "":
return errors.New("svid_file_name is required")
case c.SvidKeyFileName == "":
return errors.New("svid_key_file_name is required")
case c.SvidBundleFileName == "":
return errors.New("svid_bundle_file_name is required")
default:
return nil
x509EmptyCount := countEmpty(c.SvidFileName, c.SvidBundleFileName, c.SvidKeyFileName)
jwtSVIDEmptyCount := countEmpty(c.JWTSvidFilename, c.JWTAudience)
jwtBundleEmptyCount := countEmpty(c.SvidBundleFileName)
if x509EmptyCount == 3 && jwtSVIDEmptyCount == 2 && jwtBundleEmptyCount == 1 {
return errors.New("at least one of the sets ('svid_file_name', 'svid_key_file_name', 'svid_bundle_file_name'), ('jwt_file_name', 'jwt_audience'), 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")
}

if jwtSVIDEmptyCount != 0 && jwtSVIDEmptyCount != 2 {
return errors.New("all or none of 'jwt_file_name', 'jwt_audience' must be specified")
}

return nil
}

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

func countEmpty(configs ...string) int {
cnt := 0
for _, config := range configs {
if config == "" {
cnt++
}
}
return cnt
}
45 changes: 27 additions & 18 deletions pkg/sidecar/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ func TestParseConfig(t *testing.T) {
expectedSvidFileName := "svid.pem"
expectedKeyFileName := "svid_key.pem"
expectedSvidBundleFileName := "svid_bundle.pem"
expectedJWTSVIDFileName := "jwt_svid.token"
expectedJWTBundleFileName := "jwt_bundle.json"
expectedJWTAudience := "your-audience"

assert.Equal(t, expectedAgentAddress, c.AgentAddress)
assert.Equal(t, expectedCmd, c.Cmd)
Expand All @@ -31,6 +34,9 @@ func TestParseConfig(t *testing.T) {
assert.Equal(t, expectedSvidFileName, c.SvidFileName)
assert.Equal(t, expectedKeyFileName, c.SvidKeyFileName)
assert.Equal(t, expectedSvidBundleFileName, c.SvidBundleFileName)
assert.Equal(t, expectedJWTSVIDFileName, c.JWTSvidFilename)
assert.Equal(t, expectedJWTBundleFileName, c.JWTBundleFilename)
assert.Equal(t, expectedJWTAudience, c.JWTAudience)
assert.True(t, c.AddIntermediatesToBundle)
}

Expand All @@ -51,33 +57,37 @@ func TestValidateConfig(t *testing.T) {
},
},
{
name: "no SVID file",
name: "no error",
config: &Config{
AgentAddress: "path",
SvidKeyFileName: "key.pem",
SvidBundleFileName: "bundle.pem",
AgentAddress: "path",
JWTAudience: "your-audience",
JWTSvidFilename: "jwt.token",
JWTBundleFilename: "bundle.json",
},
expectError: "svid_file_name is required",
},
{
name: "no key file",
name: "no set specified",
config: &Config{
AgentAddress: "path",
SvidFileName: "cert.pem",
SvidBundleFileName: "bundle.pem",
AgentAddress: "path",
},
expectError: "svid_key_file_name is required",
expectError: "at least one of the sets ('svid_file_name', 'svid_key_file_name', 'svid_bundle_file_name'), ('jwt_file_name', 'jwt_audience'), or ('jwt_bundle_file_name') must be fully specified",
},
{
name: "no bundle file",
name: "missing svid config",
config: &Config{
AgentAddress: "path",
SvidFileName: "cert.pem",
},
expectError: "all or none of 'svid_file_name', 'svid_key_file_name', 'svid_bundle_file_name' must be specified",
},
{
name: "missing jwt config",
config: &Config{
AgentAddress: "path",
SvidFileName: "cert.pem",
SvidKeyFileName: "key.pem",
JWTSvidFilename: "cert.pem",
},
expectError: "svid_bundle_file_name is required",
expectError: "all or none of 'jwt_file_name', 'jwt_audience' must be specified",
},

// Duplicated field error:
{
name: "Both agent_address & agentAddress in use",
Expand All @@ -88,7 +98,7 @@ func TestValidateConfig(t *testing.T) {
SvidKeyFileName: "key.pem",
SvidBundleFileName: "bundle.pem",
},
expectError: "use of agent_address and AgentAddress found, use only agent_address",
expectError: "use of agent_address and agentAddress found, use only agent_address",
},
{
name: "Both cmd_args & cmdArgs in use",
Expand Down Expand Up @@ -159,7 +169,6 @@ func TestValidateConfig(t *testing.T) {
},
expectError: "use of renew_signal and renewSignal found, use only renew_signal",
},

// Deprecated field warning:
{
name: "Using AgentAddressDeprecated",
Expand Down Expand Up @@ -276,7 +285,7 @@ func TestValidateConfig(t *testing.T) {
require.ElementsMatch(t, tt.expectLogs, getShortEntries(hook.AllEntries()))

if tt.expectError != "" {
require.Error(t, err, tt.expectError)
require.EqualError(t, err, tt.expectError)
return
}

Expand Down
Loading

0 comments on commit 6ca090f

Please sign in to comment.