-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Nomad Secret Engine Tests #125
Merged
Merged
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package benchmarktests | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"os" | ||
"strings" | ||
|
||
"github.com/hashicorp/go-hclog" | ||
"github.com/hashicorp/go-uuid" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/gohcl" | ||
"github.com/hashicorp/vault/api" | ||
vegeta "github.com/tsenart/vegeta/v12/lib" | ||
) | ||
|
||
// Constants for test | ||
const ( | ||
NomadSecretTestType = "nomad_secret" | ||
NomadSecretTestMethod = "GET" | ||
NomadTokenEnvVar = VaultBenchmarkEnvVarPrefix + "NOMAD_TOKEN" | ||
) | ||
|
||
func init() { | ||
// "Register" this test to the main test registry | ||
TestList[NomadSecretTestType] = func() BenchmarkBuilder { return &NomadTest{} } | ||
} | ||
|
||
type NomadTest struct { | ||
pathPrefix string | ||
header http.Header | ||
roleName string | ||
config *NomadSecretTestConfig | ||
logger hclog.Logger | ||
} | ||
|
||
type NomadSecretTestConfig struct { | ||
NomadConfig *NomadConfig `hcl:"nomad,block"` | ||
NomadRoleConfig *NomadRoleConfig `hcl:"role,block"` | ||
} | ||
|
||
type NomadConfig struct { | ||
Address string `hcl:"address"` | ||
Token string `hcl:"token,optional"` | ||
MaxTokenNameLength int `hcl:"max_token_name_length,optional"` | ||
CaCert string `hcl:"ca_cert,optional"` | ||
ClientCert string `hcl:"client_cert,optional"` | ||
ClientKey string `hcl:"client_key,optional"` | ||
} | ||
|
||
type NomadRoleConfig struct { | ||
Name string `hcl:"name,optional"` | ||
Policies []string `hcl:"policies,optional"` | ||
Global bool `hcl:"global,optional"` | ||
Type string `hcl:"type,optional"` | ||
} | ||
|
||
func (c *NomadTest) ParseConfig(body hcl.Body) error { | ||
testConfig := &struct { | ||
Config *NomadSecretTestConfig `hcl:"config,block"` | ||
}{ | ||
Config: &NomadSecretTestConfig{ | ||
NomadConfig: &NomadConfig{ | ||
Token: os.Getenv(NomadTokenEnvVar), | ||
}, | ||
NomadRoleConfig: &NomadRoleConfig{ | ||
Name: "benchmark-role", | ||
}, | ||
}, | ||
} | ||
|
||
diags := gohcl.DecodeBody(body, nil, testConfig) | ||
if diags.HasErrors() { | ||
return fmt.Errorf("error decoding to struct: %v", diags) | ||
} | ||
c.config = testConfig.Config | ||
|
||
// Ensure that the token has been set by either the environment variable or the config | ||
if c.config.NomadConfig.Token == "" { | ||
return fmt.Errorf("nomad token must be set") | ||
} | ||
return nil | ||
} | ||
|
||
func (c *NomadTest) Target(client *api.Client) vegeta.Target { | ||
return vegeta.Target{ | ||
Method: "GET", | ||
URL: client.Address() + c.pathPrefix + "/creds/" + c.roleName, | ||
Header: c.header, | ||
} | ||
} | ||
|
||
func (c *NomadTest) Cleanup(client *api.Client) error { | ||
c.logger.Trace(cleanupLogMessage(c.pathPrefix)) | ||
_, err := client.Logical().Delete(strings.Replace(c.pathPrefix, "/v1/", "/sys/mounts/", 1)) | ||
if err != nil { | ||
return fmt.Errorf("error cleaning up mount: %v", err) | ||
} | ||
return nil | ||
} | ||
|
||
func (c *NomadTest) GetTargetInfo() TargetInfo { | ||
return TargetInfo{ | ||
method: NomadSecretTestMethod, | ||
pathPrefix: c.pathPrefix, | ||
} | ||
} | ||
|
||
func (c *NomadTest) Setup(client *api.Client, randomMountName bool, mountName string) (BenchmarkBuilder, error) { | ||
var err error | ||
secretPath := mountName | ||
config := c.config | ||
c.logger = targetLogger.Named(NomadSecretTestType) | ||
|
||
if randomMountName { | ||
secretPath, err = uuid.GenerateUUID() | ||
if err != nil { | ||
log.Fatalf("can't create UUID") | ||
} | ||
} | ||
|
||
c.logger.Trace(mountLogMessage("secrets", "nomad", secretPath)) | ||
err = client.Sys().Mount(secretPath, &api.MountInput{ | ||
Type: "nomad", | ||
}) | ||
if err != nil { | ||
return nil, fmt.Errorf("error mounting nomad: %v", err) | ||
} | ||
|
||
setupLogger := c.logger.Named(secretPath) | ||
|
||
// Decode Nomad Config | ||
setupLogger.Trace(parsingConfigLogMessage("nomad")) | ||
nomadConfigData, err := structToMap(config.NomadConfig) | ||
if err != nil { | ||
return nil, fmt.Errorf("error parsing nomad config from struct: %v", err) | ||
} | ||
|
||
// Write Nomad config | ||
setupLogger.Trace(writingLogMessage("nomad config")) | ||
_, err = client.Logical().Write(secretPath+"/config/access", nomadConfigData) | ||
if err != nil { | ||
return nil, fmt.Errorf("error writing nomad config: %v", err) | ||
} | ||
|
||
// Decode Role Config | ||
setupLogger.Trace(parsingConfigLogMessage("role")) | ||
nomadRoleConfigData, err := structToMap(config.NomadRoleConfig) | ||
if err != nil { | ||
return nil, fmt.Errorf("error parsing role config from struct: %v", err) | ||
} | ||
|
||
// Create Role | ||
setupLogger.Trace(writingLogMessage("nomad role"), "name", config.NomadRoleConfig.Name) | ||
_, err = client.Logical().Write(secretPath+"/role/"+config.NomadRoleConfig.Name, nomadRoleConfigData) | ||
if err != nil { | ||
return nil, fmt.Errorf("error writing nomad role: %v", err) | ||
} | ||
|
||
return &NomadTest{ | ||
pathPrefix: "/v1/" + secretPath, | ||
header: generateHeader(client), | ||
roleName: config.NomadRoleConfig.Name, | ||
logger: c.logger, | ||
}, nil | ||
} | ||
|
||
func (c *NomadTest) Flags(fs *flag.FlagSet) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Nomad Secrets Engine Benchmark | ||
|
||
This benchmark will test the dynamic generation of Nomad credentials. | ||
|
||
## Test Parameters | ||
|
||
### Nomad Database Configuration `nomad` | ||
|
||
#### NOTE: Ensure that the Nomad system has a limit high enough to support the number of roles you are creating. More information can be found in the [Nomad Documentation](https://developer.hashicorp.com/nomad/docs/configuration#limits) | ||
|
||
- `address` `(string: "")` – Specifies the address of the Nomad instance, provided as `"protocol://host:port"` like `"http://127.0.0.1:4646"`. This value can also be provided on individual calls with the NOMAD_ADDR environment variable. | ||
- `token` `(string: "")` – Specifies the Nomad Management token to use. This value can also be provided on individual calls with the NOMAD_TOKEN environment variable. This can also be provided via the `VAULT_BENCHMARK_NOMAD_TOKEN` environment variable. | ||
- `max_token_name_length` `(int: <optional>)` – Specifies the maximum length to use for the name of the Nomad token generated with [Generate Credential](https://developer.hashicorp.com/vault/api-docs/secret/nomad#generate-credential). If omitted, `0` is used and ignored, defaulting to the max value allowed by the Nomad version. For Nomad versions 0.8.3 and earlier, the default is `64`. For Nomad version 0.8.4 and later, the default is `256`. | ||
- `ca_cert` `(string: "")` - CA certificate to use when verifying Nomad server certificate, must be x509 PEM encoded. | ||
- `client_cert` `(string: "")` - Client certificate used for Nomad's TLS communication, must be x509 PEM encoded and if this is set you need to also set client_key. | ||
- `client_key` `(string: "")` - Client key used for Nomad's TLS communication, must be x509 PEM encoded and if this is set you need to also set client_cert. | ||
|
||
### Role Config `role` | ||
|
||
- `name` `(string: "benchmark-role")` – Specifies the name of an existing role against which to create this Nomad tokens. This is part of the request URL. | ||
- `policies` `(string: "")` – Comma separated list of Nomad policies the token is going to be created against. These need to be created beforehand in Nomad. | ||
- `global` `(bool: "false")` – Specifies if the token should be global, as defined in the [Nomad Documentation](https://developer.hashicorp.com/nomad/tutorials/access-control#acl-tokens). | ||
- `type` `(string: "client")` - Specifies the type of token to create when using this role. Valid values are `"client"` or `"management"`. | ||
|
||
## Example Configuration | ||
|
||
```hcl | ||
test "nomad_secret" "nomad_test_1" { | ||
weight = 100 | ||
config { | ||
nomad { | ||
address = "http://127.0.0.1:4646" | ||
token = "NOMAD_TOKEN" | ||
} | ||
role { | ||
global = true | ||
type = "management" | ||
} | ||
} | ||
} | ||
|
||
``` | ||
|
||
### Example Usage | ||
|
||
```bash | ||
$ vault-benchmark run -config=config.hcl | ||
2023-06-01T09:41:27.096-0500 [INFO] vault-benchmark: setting up targets | ||
2023-06-01T09:41:27.102-0500 [INFO] vault-benchmark: starting benchmarks: duration=5s | ||
2023-06-01T09:41:32.311-0500 [INFO] vault-benchmark: benchmark complete | ||
Target: http://127.0.0.1:8200 | ||
op count rate throughput mean 95th% 99th% successRatio | ||
nomad_test_1 177 35.057995 33.990891 290.850018ms 375.292712ms 451.573602ms 100.00% | ||
``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does
NOMAD_ADDR
work?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesnt currently. But ill remove this