Skip to content

Commit b05e19a

Browse files
Adds conformance tests for AWS Secrets store component (#3588)
Signed-off-by: Elena Kolevska <[email protected]> Co-authored-by: Yaron Schneider <[email protected]>
1 parent 9833e56 commit b05e19a

File tree

13 files changed

+179
-6
lines changed

13 files changed

+179
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: "3.8"
2+
3+
services:
4+
localstack:
5+
container_name: "conformance-aws-secrets-manager"
6+
image: localstack/localstack
7+
ports:
8+
- "127.0.0.1:4566:4566"
9+
environment:
10+
- DEBUG=1
11+
- DOCKER_HOST=unix:///var/run/docker.sock
12+
volumes:
13+
- "${PWD}/.github/scripts/docker-compose-init/init-conformance-state-aws-secrets-manager.sh:/etc/localstack/init/ready.d/init-aws.sh" # ready hook
14+
- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
15+
- "/var/run/docker.sock:/var/run/docker.sock"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
terraform {
2+
required_version = ">=0.13"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = "~> 4.0"
8+
}
9+
}
10+
}
11+
12+
variable "TIMESTAMP" {
13+
type = string
14+
description = "Timestamp of the GitHub workflow run."
15+
}
16+
17+
variable "UNIQUE_ID" {
18+
type = string
19+
description = "Unique ID of the GitHub workflow run."
20+
}
21+
22+
provider "aws" {
23+
region = "us-east-1"
24+
default_tags {
25+
tags = {
26+
Purpose = "AutomatedConformanceTesting"
27+
Timestamp = "${var.TIMESTAMP}"
28+
}
29+
}
30+
}
31+
32+
# Create the first secret in AWS Secrets Manager
33+
resource "aws_secretsmanager_secret" "conftestsecret" {
34+
name = "conftestsecret"
35+
description = "Secret for conformance test"
36+
recovery_window_in_days = 0
37+
}
38+
39+
resource "aws_secretsmanager_secret_version" "conftestsecret_value" {
40+
secret_id = aws_secretsmanager_secret.conftestsecret.id
41+
secret_string = "abcd"
42+
}
43+
44+
# Create the second secret in AWS Secrets Manager
45+
resource "aws_secretsmanager_secret" "secondsecret" {
46+
name = "secondsecret"
47+
description = "Another secret for conformance test"
48+
recovery_window_in_days = 0
49+
}
50+
51+
resource "aws_secretsmanager_secret_version" "secondsecret_value" {
52+
secret_id = aws_secretsmanager_secret.secondsecret.id
53+
secret_string = "efgh"
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/sh
2+
3+
set +e
4+
5+
# Navigate to the Terraform directory
6+
cd ".github/infrastructure/terraform/conformance/secretstores/aws/secretsmanager"
7+
8+
# Run Terraform
9+
terraform destroy -auto-approve -var="UNIQUE_ID=$UNIQUE_ID" -var="TIMESTAMP=$CURRENT_TIME"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/sh
2+
3+
set -e
4+
5+
# Set variables for GitHub Actions
6+
echo "AWS_REGION=us-east-1" >> $GITHUB_ENV
7+
8+
# Navigate to the Terraform directory
9+
cd ".github/infrastructure/terraform/conformance/secretstores/aws/secretsmanager"
10+
11+
# Run Terraform
12+
terraform init
13+
terraform validate -no-color
14+
terraform plan -no-color -var="UNIQUE_ID=$UNIQUE_ID" -var="TIMESTAMP=$CURRENT_TIME"
15+
terraform apply -auto-approve -var="UNIQUE_ID=$UNIQUE_ID" -var="TIMESTAMP=$CURRENT_TIME"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
awslocal secretsmanager create-secret \
4+
--name conftestsecret \
5+
--secret-string "abcd"
6+
7+
awslocal secretsmanager create-secret \
8+
--name secondsecret \
9+
--secret-string "efgh"

.github/scripts/test-info.mjs

+11
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,17 @@ const components = {
492492
conformance: true,
493493
certification: true,
494494
},
495+
'secretstores.aws.secretsmanager.terraform': {
496+
conformance: true,
497+
requireAWSCredentials: true,
498+
requireTerraform: true,
499+
conformanceSetup: 'conformance-secretstores.aws.secretsmanager.secretsmanager-setup.sh',
500+
conformanceDestroy: 'conformance-secretstores.aws.secretsmanager.secretsmanager-destroy.sh',
501+
},
502+
'secretstores.aws.secretsmanager.docker': {
503+
conformance: true,
504+
conformanceSetup: 'docker-compose.sh secrets-manager',
505+
},
495506
'state.aws.dynamodb': {
496507
certification: true,
497508
requireAWSCredentials: true,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# yaml-language-server: $schema=../../../component-metadata-schema.json
2+
schemaVersion: v1
3+
type: secretstores
4+
name: aws.secretsmanager
5+
version: v1
6+
status: beta
7+
title: "AWS Secrets manager"
8+
urls:
9+
- title: Reference
10+
url: https://docs.dapr.io/reference/components-reference/supported-secret-stores/aws-secret-manager/
11+
builtinAuthenticationProfiles:
12+
- name: "aws"
13+
metadata:
14+
- name: endpoint
15+
required: false
16+
description: |
17+
The Secrets manager endpoint. The AWS SDK will generate a default endpoint if not specified. Useful for local testing with AWS LocalStack
18+
example: '"http://localhost:4566"'
19+
type: string

secretstores/aws/secretmanager/secretmanager.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ func NewSecretManager(logger logger.Logger) secretstores.SecretStore {
4141
}
4242

4343
type SecretManagerMetaData struct {
44-
Region string `json:"region"`
45-
AccessKey string `json:"accessKey"`
46-
SecretKey string `json:"secretKey"`
47-
SessionToken string `json:"sessionToken"`
44+
Region string `json:"region" mapstructure:"region" mdignore:"true"`
45+
AccessKey string `json:"accessKey" mapstructure:"accessKey" mdignore:"true"`
46+
SecretKey string `json:"secretKey" mapstructure:"secretKey" mdignore:"true"`
47+
SessionToken string `json:"sessionToken" mapstructure:"sessionToken" mdignore:"true"`
48+
Endpoint string `json:"endpoint" mapstructure:"endpoint"`
4849
}
4950

5051
type smSecretStore struct {
@@ -136,7 +137,7 @@ func (s *smSecretStore) BulkGetSecret(ctx context.Context, req secretstores.Bulk
136137
}
137138

138139
func (s *smSecretStore) getClient(metadata *SecretManagerMetaData) (*secretsmanager.SecretsManager, error) {
139-
sess, err := awsAuth.GetClient(metadata.AccessKey, metadata.SecretKey, metadata.SessionToken, metadata.Region, "")
140+
sess, err := awsAuth.GetClient(metadata.AccessKey, metadata.SecretKey, metadata.SessionToken, metadata.Region, metadata.Endpoint)
140141
if err != nil {
141142
return nil, err
142143
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: dapr.io/v1alpha1
2+
kind: Component
3+
metadata:
4+
name: awssecretmanager
5+
spec:
6+
type: secretstores.aws.secretmanager
7+
version: v1
8+
metadata:
9+
- name: endpoint
10+
value: "http://localhost:4566" # AWS LocalStack address
11+
- name: accessKey
12+
value: "test" # AWS LocalStack placeholder
13+
- name: secretKey
14+
value: "test" # AWS LocalStack placeholder
15+
- name: region
16+
value: "us-east-1" # AWS LocalStack placeholder
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: dapr.io/v1alpha1
2+
kind: Component
3+
metadata:
4+
name: awssecretmanager
5+
namespace: default
6+
spec:
7+
type: secretstores.aws.secretmanager
8+
version: v1
9+
metadata:
10+
- name: accessKey
11+
value: ${{AWS_ACCESS_KEY_ID}}
12+
- name: secretKey
13+
value: ${{AWS_SECRET_ACCESS_KEY}}
14+
- name: region
15+
value: ${{AWS_REGION}}

tests/config/secretstores/tests.yml

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ components:
55
operations: []
66
- component: local.file
77
operations: []
8+
- component: aws.secretsmanager.docker
9+
operations: []
10+
- component: aws.secretsmanager.terraform
11+
operations: []
812
- component: azure.keyvault.certificate
913
operations: []
1014
- component: azure.keyvault.serviceprincipal

tests/conformance/secretstores/secretstores.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func ConformanceTests(t *testing.T, props map[string]string, store secretstores.
5858

5959
t.Run("ping", func(t *testing.T) {
6060
err := secretstores.Ping(context.Background(), store)
61-
// TODO: Ideally, all stable components should implenment ping function,
61+
// TODO: Ideally, all stable components should implement a ping function,
6262
// so will only assert require.NoError(t, err) finally, i.e. when current implementation
6363
// implements ping in existing stable components
6464
if err != nil {

tests/conformance/secretstores_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/stretchr/testify/require"
2424

2525
"github.com/dapr/components-contrib/secretstores"
26+
ss_aws "github.com/dapr/components-contrib/secretstores/aws/secretmanager"
2627
ss_azure "github.com/dapr/components-contrib/secretstores/azure/keyvault"
2728
ss_hashicorp_vault "github.com/dapr/components-contrib/secretstores/hashicorp/vault"
2829
ss_kubernetes "github.com/dapr/components-contrib/secretstores/kubernetes"
@@ -71,6 +72,10 @@ func loadSecretStore(name string) secretstores.SecretStore {
7172
return ss_local_file.NewLocalSecretStore(testLogger)
7273
case "hashicorp.vault":
7374
return ss_hashicorp_vault.NewHashiCorpVaultSecretStore(testLogger)
75+
case "aws.secretsmanager.docker":
76+
return ss_aws.NewSecretManager(testLogger)
77+
case "aws.secretsmanager.terraform":
78+
return ss_aws.NewSecretManager(testLogger)
7479
default:
7580
return nil
7681
}

0 commit comments

Comments
 (0)