Skip to content
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

Vault 7721 ElastiCache Acceptance Tests #3

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
File renamed without changes.
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,13 @@ fmtcheck:

.PHONY: fmt
fmt:
gofumpt -l -w .
gofumpt -l -w .

.PHONY: setup-env
setup-env:
cd bootstrap/terraform && terraform init && terraform apply -auto-approve


.PHONY: teardown-env
teardown-env:
cd bootstrap/terraform && terraform init && terraform destroy -auto-approve
60 changes: 56 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ If you wish to work on this plugin, you'll first need

Make sure Go is properly installed, including setting up a [GOPATH](https://golang.org/doc/code.html#GOPATH).

To run the tests locally you will need to have write permissions to an [ElastiCache for Redis](https://aws.amazon.com/elasticache/redis/) instance.
To run the tests locally you will need to have write permissions to an [ElastiCache for Redis](https://aws.amazon.com/elasticache/redis/) instance.
A small Terraform project is included to provision one for you if needed. More details in the [Environment Set Up](#environment-set-up) section.

## Building

Expand All @@ -56,6 +57,35 @@ $ make dev

## Tests

### Environment Set Up

To test the plugin, you need access to an Elasticache for Redis Cluster.
A Terraform project is included for convenience to initialize a new cluster if needed.
If not already available, you can install Terraform by using [this documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html).

The setup script tries to find and use available AWS credentials from the environment. You can configure AWS credentials using [this documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html).
Or if you prefer you can edit the provider defined ./bootstrap/terraform/elasticache.tf with your desired set of credentials.

Note that resources created via the Terraform project cost a small amount of money per hour.

To set up the test cluster:

```hcl
$ make set-up-env
...
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
```

### Environment Teardown

The test cluster created via the set-up-env command can be destroyed using the teardown-env command.

```hcl
$ make teardown-env
...
Destroy complete! Resources: 4 destroyed.
```

### Testing Manually

Put the plugin binary into a location of your choice. This directory
Expand Down Expand Up @@ -114,9 +144,9 @@ Configure a role:
```sh
$ vault write database/roles/redis-myrole \
db_name="redis-mydb" \
creation_statements=$CREATION_STATEMENTS \
default_ttl=$DEFAULT_TTL \
max_ttl=$MAX_TTL
creation_statements="on ~* +@all" \
default_ttl=5m \
max_ttl=15m
...

Success! Data written to: database/roles/redis-myrole
Expand Down Expand Up @@ -151,3 +181,25 @@ You can also specify a `TESTARGS` variable to filter tests like so:
```sh
$ make test TESTARGS='-run=TestConfig'
```

### Acceptance Tests

The majority of tests must communicate with an existing ElastiCache instance. See the [Environment Set Up](#environment-set-up) section for instructions on how to prepare a test cluster.

Some environment variables are required to run tests expecting to communicate with an ElastiCache cluster.
The username and password should be valid IAM access key and secret key with read and write access to the ElastiCache cluster used for testing. The URL should be the complete configuration endpoint including the port, for example: `vault-plugin-elasticache-test.id.xxx.use1.cache.amazonaws.com:6379`.

```sh
$ export TEST_ELASTICACHE_USERNAME="AWS ACCESS KEY ID"
$ export TEST_ELASTICACHE_PASSWORD="AWS SECRET ACCESS KEY"
$ export TEST_ELASTICACHE_URL="vault-plugin-elasticache-test.id.xxx.use1.cache.amazonaws.com:6379"
$ export TEST_ELASTICACHE_REGION="us-east-1"

$ make test
```

You can also specify a `TESTARGS` variable to filter tests like so:

```sh
$ make test TESTARGS='-run=TestConfig'
```
78 changes: 78 additions & 0 deletions bootstrap/terraform/elasticache.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
provider "aws" {
// Credentials and configuration derived from the environment
// Uncomment if you wish to configure the provider explicitly

// access_key = ""
// secret_key = ""
// region = ""
}

resource "aws_elasticache_cluster" "vault_plugin_elasticache_test" {
cluster_id = "vault-plugin-elasticache-test"
engine = "redis"
engine_version = "6.2"
node_type = "cache.t4g.micro"
num_cache_nodes = 1
parameter_group_name = "default.redis6.x"

tags = {
"description" : "vault elasticache plugin generated test cluster"
}
}

resource "aws_iam_user" "vault_plugin_elasticache_test" {
name = "vault-plugin-elasticache-user-test"

tags = {
"description" : "vault elasticache plugin generated test user"
}
}

resource "aws_iam_access_key" "vault_plugin_elasticache_test" {
user = aws_iam_user.vault_plugin_elasticache_test.name
}

resource "aws_iam_user_policy" "vault_plugin_elasticache_test" {
name = "vault-plugin-elasticache-policy-test"
user = aws_iam_user.vault_plugin_elasticache_test.name

policy = data.aws_iam_policy_document.vault_plugin_elasticache_test.json
}

data "aws_iam_policy_document" "vault_plugin_elasticache_test" {
statement {
actions = [
"elasticache:DescribeUsers",
"elasticache:CreateUser",
"elasticache:ModifyUser",
"elasticache:DeleteUser",
]
resources = ["arn:aws:elasticache:*:*:user:*"]
}
}

// export TEST_ELASTICACHE_USERNAME=${username}
output "username" {
value = aws_iam_access_key.vault_plugin_elasticache_test.id
}

// export TEST_ELASTICACHE_PASSWORD=${password}
// Use `terraform output password` to access the value
output "password" {
sensitive = true
value = aws_iam_access_key.vault_plugin_elasticache_test.secret
}

// export TEST_ELASTICACHE_URL=${url}
output "url" {
value = format(
"%s:%s",
aws_elasticache_cluster.vault_plugin_elasticache_test.cache_nodes[0].address,
aws_elasticache_cluster.vault_plugin_elasticache_test.port)
}

// export TEST_ELASTICACHE_REGION=${region}
data "aws_region" "current" {}
output "region" {
value = data.aws_region.current.name
}
8 changes: 2 additions & 6 deletions cmd/vault-plugin-database-redis-elasticache/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"os"

"github.com/hashicorp/vault-plugin-database-redis-elasticache/internal/plugin"

"github.com/hashicorp/vault/sdk/database/dbplugin/v5"
)

Expand All @@ -18,10 +17,7 @@ func main() {

// Run starts serving the plugin
func Run() error {
db, err := plugin.New()
if err != nil {
return err
}
dbplugin.Serve(db.(dbplugin.Database))
dbplugin.ServeMultiplex(plugin.New)

return nil
}
2 changes: 1 addition & 1 deletion internal/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type config struct {
Region string `mapstructure:"region,omitempty"`
}

func New() (dbplugin.Database, error) {
func New() (interface{}, error) {
logger := hclog.New(&hclog.LoggerOptions{
Level: hclog.Trace,
Output: os.Stderr,
Expand Down
Loading