Skip to content

Commit cf02b0b

Browse files
parameter store is always secureString
Signed-off-by: bruce-szalwinski-he <bruce.szalwinski@engine.com>
1 parent 8a54645 commit cf02b0b

5 files changed

Lines changed: 28 additions & 53 deletions

File tree

README.rst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,6 @@ This command requires a ``.sops.yaml`` configuration file. Below is an example:
12111211
aws_region: "us-west-2"
12121212
path_regex: aws-secrets/*
12131213
- aws_parameter_store_path: "/sops/"
1214-
aws_parameter_store_type: "SecureString" # default
12151214
aws_region: "us-west-2"
12161215
path_regex: aws-params/*
12171216
@@ -1220,8 +1219,9 @@ all files under ``gcs/*`` into the GCS bucket ``sops-secrets``, the contents of
12201219
``vault/*`` into Vault's KV store under the path ``secrets/sops/``, files under ``aws-secrets/*``
12211220
into AWS Secrets Manager as JSON secrets, and files under ``aws-params/*`` into AWS Parameter Store
12221221
as SecureString parameters. For the files that will be published to S3 and GCS, it will decrypt them
1223-
and re-encrypt them using the ``F69E4901EDBAD2D1753F8C67A64535C4163FB307`` pgp key. Files published to Vault,
1224-
AWS Secrets Manager, and AWS Parameter Store will be decrypted and stored as plaintext JSON data.
1222+
and re-encrypt them using the ``F69E4901EDBAD2D1753F8C67A64535C4163FB307`` pgp key. Files published to Vault
1223+
will be decrypted and stored as plaintext JSON data. Files published to AWS Secrets Manager and AWS Parameter Store
1224+
will be decrypted and stored as JSON data encrypted by AWS KMS.
12251225
12261226
You would deploy a file to S3 with a command like: ``sops publish s3/app.yaml``
12271227
@@ -1319,22 +1319,23 @@ Publishing to AWS Parameter Store
13191319
**********************************
13201320
13211321
AWS Systems Manager Parameter Store provides secure, hierarchical storage for configuration data
1322-
and secrets management. SOPS can publish decrypted data directly to Parameter Store as JSON parameters.
1322+
and secrets management. SOPS can publish decrypted data directly to Parameter Store as JSON parameters encrypted by AWS KMS.
13231323
13241324
There are a few settings for AWS Parameter Store that you can place in your destination rules:
13251325
13261326
* ``aws_parameter_store_path`` - The parameter path in AWS Parameter Store. If it ends with ``/``, the filename will be appended. If not specified, the filename will be used as the parameter name with a leading ``/``.
1327-
* ``aws_parameter_store_type`` - The parameter type. Can be ``String``, ``StringList``, or ``SecureString``. Defaults to ``SecureString``.
13281327
* ``aws_region`` - The AWS region where the parameter should be stored. This is required.
13291328
1329+
All parameters are stored as ``SecureString`` type for security, since SOPS files may contain sensitive data.
1330+
13301331
SOPS uses the AWS SDK for Go v2, which automatically uses your configured AWS credentials from the AWS CLI,
13311332
environment variables, or IAM roles.
13321333
13331334
If the destination parameter already exists in AWS Parameter Store and contains the same data as the source
13341335
file, it will be skipped to avoid creating unnecessary versions.
13351336
13361337
Note: Recreation rules (re-encryption with different keys) are not supported for AWS Parameter Store.
1337-
The data is decrypted from the source file and stored as JSON in the parameter.
1338+
The data is decrypted from the source file and stored as JSON in the SecureString parameter, encrypted by AWS KMS.
13381339
13391340
Below is an example of publishing to AWS Parameter Store:
13401341

config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ func parseDestinationRuleForFile(conf *configFile, filePath string, kmsEncryptio
547547
dest = publish.NewAWSSecretsManagerDestination(dRule.AWSSecretsManagerRegion, dRule.AWSSecretsManagerSecretName)
548548
}
549549
if dRule.AWSParameterStoreRegion != "" {
550-
dest = publish.NewAWSParameterStoreDestination(dRule.AWSParameterStoreRegion, dRule.AWSParameterStorePath, dRule.AWSParameterStoreType)
550+
dest = publish.NewAWSParameterStoreDestination(dRule.AWSParameterStoreRegion, dRule.AWSParameterStorePath)
551551
}
552552

553553
config, err := configFromRule(rule, kmsEncryptionContext)

publish/aws_integration_test.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ var (
3535
testAWSRegion = getEnvOrDefault("SOPS_TEST_AWS_REGION", "us-east-1")
3636
testSecretName = os.Getenv("SOPS_TEST_AWS_SECRET_NAME") // e.g., "sops-test-secret"
3737
testParameterName = os.Getenv("SOPS_TEST_AWS_PARAMETER_NAME") // e.g., "/sops-test/parameter"
38-
testParameterType = getEnvOrDefault("SOPS_TEST_AWS_PARAMETER_TYPE", "SecureString")
3938
)
4039

4140
func getEnvOrDefault(key, defaultValue string) string {
@@ -157,7 +156,7 @@ func TestAWSParameterStoreDestination_Integration(t *testing.T) {
157156
}
158157

159158
ctx := context.Background()
160-
dest := NewAWSParameterStoreDestination(testAWSRegion, testParameterName, testParameterType)
159+
dest := NewAWSParameterStoreDestination(testAWSRegion, testParameterName)
161160

162161
// Test data
163162
testData := map[string]interface{}{
@@ -194,12 +193,8 @@ func TestAWSParameterStoreDestination_Integration(t *testing.T) {
194193

195194
assert.Equal(t, testData, storedData, "Stored data doesn't match original")
196195

197-
// Verify parameter type
198-
expectedType := testParameterType
199-
if expectedType == "" {
200-
expectedType = "SecureString"
201-
}
202-
assert.Equal(t, expectedType, string(result.Parameter.Type), "Parameter type mismatch")
196+
// Verify parameter type is always SecureString
197+
assert.Equal(t, "SecureString", string(result.Parameter.Type), "Parameter type should always be SecureString")
203198

204199
// Test no-op behavior (upload same data again)
205200
err = dest.UploadUnencrypted(testData, "test-config")
@@ -211,7 +206,7 @@ func TestAWSParameterStoreDestination_EncryptedFile_Integration(t *testing.T) {
211206
t.Skip("Skipping integration test: SOPS_TEST_AWS_PARAMETER_NAME not set")
212207
}
213208

214-
dest := NewAWSParameterStoreDestination(testAWSRegion, testParameterName+"-file", testParameterType)
209+
dest := NewAWSParameterStoreDestination(testAWSRegion, testParameterName+"-file")
215210

216211
encryptedContent := []byte(`# SOPS encrypted file
217212
database:

publish/aws_parameter_store.go

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,23 @@ func init() {
2222
parameterLog = logging.NewLogger("PUBLISH")
2323
}
2424

25-
// AWSParameterStoreDestination is the AWS Parameter Store implementation of the Destination interface
25+
// AWSParameterStoreDestination is the AWS Parameter Store implementation of the Destination interface.
2626
type AWSParameterStoreDestination struct {
2727
region string
2828
parameterPath string
29-
parameterType string
3029
}
3130

32-
// NewAWSParameterStoreDestination is the constructor for an AWS Parameter Store Destination
33-
func NewAWSParameterStoreDestination(region, parameterPath, parameterType string) *AWSParameterStoreDestination {
34-
// Default to SecureString if not specified
35-
if parameterType == "" {
36-
parameterType = "SecureString"
37-
}
38-
31+
// NewAWSParameterStoreDestination creates a new AWS Parameter Store destination.
32+
func NewAWSParameterStoreDestination(region, parameterPath string) *AWSParameterStoreDestination {
3933
// Ensure parameter path starts with /
4034
if parameterPath != "" && !strings.HasPrefix(parameterPath, "/") {
4135
parameterPath = "/" + parameterPath
4236
}
4337

44-
return &AWSParameterStoreDestination{region, parameterPath, parameterType}
38+
return &AWSParameterStoreDestination{region, parameterPath}
4539
}
4640

47-
// Path returns the AWS Parameter Store path
41+
// Path returns the AWS Parameter Store path for the given fileName.
4842
func (awspsd *AWSParameterStoreDestination) Path(fileName string) string {
4943
if awspsd.parameterPath != "" {
5044
// If path ends with /, append filename; otherwise use path as-is
@@ -60,12 +54,12 @@ func (awspsd *AWSParameterStoreDestination) Path(fileName string) string {
6054
return fileName
6155
}
6256

63-
// Returns NotImplementedError
57+
// Upload returns NotImplementedError as AWS Parameter Store does not support uploading encrypted files directly.
6458
func (awspsd *AWSParameterStoreDestination) Upload(fileContents []byte, fileName string) error {
6559
return &NotImplementedError{"AWS Parameter Store does not support uploading encrypted sops files directly. Use UploadUnencrypted instead."}
6660
}
6761

68-
// UploadUnencrypted uploads unencrypted data to AWS Parameter Store as JSON
62+
// UploadUnencrypted uploads unencrypted data to AWS Parameter Store as JSON.
6963
func (awspsd *AWSParameterStoreDestination) UploadUnencrypted(data map[string]interface{}, fileName string) error {
7064
ctx := context.TODO()
7165

@@ -110,18 +104,8 @@ func (awspsd *AWSParameterStoreDestination) UploadUnencrypted(data map[string]in
110104
}
111105
}
112106

113-
// Determine parameter type
114-
var paramType types.ParameterType
115-
switch strings.ToLower(awspsd.parameterType) {
116-
case "string":
117-
paramType = types.ParameterTypeString
118-
case "stringlist":
119-
paramType = types.ParameterTypeStringList
120-
case "securestring":
121-
paramType = types.ParameterTypeSecureString
122-
default:
123-
paramType = types.ParameterTypeSecureString
124-
}
107+
// Always use SecureString for security - SOPS files may contain secrets
108+
paramType := types.ParameterTypeSecureString
125109

126110
// Put parameter (creates or updates)
127111
_, err = client.PutParameter(ctx, &ssm.PutParameterInput{

publish/aws_parameter_store_test.go

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,40 @@ import (
77
)
88

99
func TestNewAWSParameterStoreDestination(t *testing.T) {
10-
dest := NewAWSParameterStoreDestination("us-east-1", "/myapp/config", "SecureString")
10+
dest := NewAWSParameterStoreDestination("us-east-1", "/myapp/config")
1111
assert.NotNil(t, dest)
1212
assert.Equal(t, "us-east-1", dest.region)
1313
assert.Equal(t, "/myapp/config", dest.parameterPath)
14-
assert.Equal(t, "SecureString", dest.parameterType)
15-
16-
// Test with empty parameter type (should default to SecureString)
17-
dest = NewAWSParameterStoreDestination("us-east-1", "/myapp/config", "")
18-
assert.Equal(t, "SecureString", dest.parameterType)
1914

2015
// Test path normalization (should add leading slash)
21-
dest = NewAWSParameterStoreDestination("us-east-1", "myapp/config", "String")
16+
dest = NewAWSParameterStoreDestination("us-east-1", "myapp/config")
2217
assert.Equal(t, "/myapp/config", dest.parameterPath)
2318
}
2419

2520
func TestAWSParameterStoreDestination_Path(t *testing.T) {
2621
// Test with specific parameter path (no trailing slash)
27-
dest := NewAWSParameterStoreDestination("us-east-1", "/myapp/database", "SecureString")
22+
dest := NewAWSParameterStoreDestination("us-east-1", "/myapp/database")
2823
path := dest.Path("config.yaml")
2924
assert.Equal(t, "/myapp/database", path)
3025

3126
// Test with parameter path ending with slash
32-
dest = NewAWSParameterStoreDestination("us-east-1", "/myapp/configs/", "SecureString")
27+
dest = NewAWSParameterStoreDestination("us-east-1", "/myapp/configs/")
3328
path = dest.Path("api.yaml")
3429
assert.Equal(t, "/myapp/configs/api.yaml", path)
3530

3631
// Test with empty parameter path (uses filename)
37-
dest = NewAWSParameterStoreDestination("us-east-1", "", "SecureString")
32+
dest = NewAWSParameterStoreDestination("us-east-1", "")
3833
path = dest.Path("standalone.yaml")
3934
assert.Equal(t, "/standalone.yaml", path)
4035

4136
// Test with filename that already has leading slash
42-
dest = NewAWSParameterStoreDestination("us-east-1", "", "SecureString")
37+
dest = NewAWSParameterStoreDestination("us-east-1", "")
4338
path = dest.Path("/already-prefixed.yaml")
4439
assert.Equal(t, "/already-prefixed.yaml", path)
4540
}
4641

4742
func TestAWSParameterStoreDestination_Upload(t *testing.T) {
48-
dest := NewAWSParameterStoreDestination("us-east-1", "/test-parameter", "SecureString")
43+
dest := NewAWSParameterStoreDestination("us-east-1", "/test-parameter")
4944
err := dest.Upload([]byte("test content"), "test.yaml")
5045

5146
assert.NotNil(t, err)

0 commit comments

Comments
 (0)