Skip to content

Commit

Permalink
feat(configmap) init aws ssmprovider
Browse files Browse the repository at this point in the history
  • Loading branch information
Linaa authored and Lina committed Feb 9, 2025
1 parent d1d4d69 commit 4458f6e
Show file tree
Hide file tree
Showing 15 changed files with 323 additions and 1 deletion.
27 changes: 27 additions & 0 deletions .chloggen/ssm-provider.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: new_component

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: ssmprovider

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: "`ConfigMapProvider` implementation for Amazon SSM Parameter Store (`ssm`) that allows the Collector to read data stored in AWS SSM Parameter Store."

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: []

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ cmd/telemetrygen/ @open-telemetry
confmap/provider/aesprovider/ @open-telemetry/collector-contrib-approvers @djaglowski @shazlehu
confmap/provider/s3provider/ @open-telemetry/collector-contrib-approvers @Aneurysm9
confmap/provider/secretsmanagerprovider/ @open-telemetry/collector-contrib-approvers @driverpt @atoulme
confmap/provider/ssmprovider/ @open-telemetry/collector-contrib-approvers @jpkrohling
connector/countconnector/ @open-telemetry/collector-contrib-approvers @djaglowski @jpkrohling
connector/datadogconnector/ @open-telemetry/collector-contrib-approvers @mx-psi @dineshg13 @ankitpatel96 @jade-guiton-dd @IbraheemA
connector/exceptionsconnector/ @open-telemetry/collector-contrib-approvers @marctc
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ body:
- confmap/provider/aesprovider
- confmap/provider/s3provider
- confmap/provider/secretsmanagerprovider
- confmap/provider/ssmprovider
- connector/count
- connector/datadog
- connector/exceptions
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ body:
- confmap/provider/aesprovider
- confmap/provider/s3provider
- confmap/provider/secretsmanagerprovider
- confmap/provider/ssmprovider
- connector/count
- connector/datadog
- connector/exceptions
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/other.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ body:
- confmap/provider/aesprovider
- confmap/provider/s3provider
- confmap/provider/secretsmanagerprovider
- confmap/provider/ssmprovider
- connector/count
- connector/datadog
- connector/exceptions
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/unmaintained.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ body:
- confmap/provider/aesprovider
- confmap/provider/s3provider
- confmap/provider/secretsmanagerprovider
- confmap/provider/ssmprovider
- connector/count
- connector/datadog
- connector/exceptions
Expand Down
2 changes: 1 addition & 1 deletion cmd/otelcontribcol/builder-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ providers:
- gomod: go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.25.0
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/s3provider v0.119.0
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/secretsmanagerprovider v0.119.0

- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/ssmprovider v0.119.0
# When using `make genotelcontribcol`, a `replaces` section is appended to this
# file before passing it to OCB, to ensure that local versions are used for all
# Contrib modules.
1 change: 1 addition & 0 deletions confmap/provider/ssmprovider/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include ../../../Makefile.Common
13 changes: 13 additions & 0 deletions confmap/provider/ssmprovider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Summary
This package provides a `ConfigMapProvider` implementation for Amazon SSM Parameter Store (`ssm`) that allows the Collector to read data stored in AWS SSM Parameter Store.

## How it works
- Use placeholders with the following pattern `${ssm:<parameter-name>}`
- To extract a value from a JSON parameter, use `${ssm:<parameter-name>#json-key}`
- Ensure the OTEL Collector Role has the `ssm:GetParameter` permission
- Parameters are automatically decrypted if they are stored as SecureString

## Prerequisites
- Set up access keys from the IAM console (`aws_access_key_id` and `aws_secret_access_key`) with permission to access Amazon SSM Parameter Store
- For details, refer to [AWS SDK for Go V2 Configuration](https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/)

36 changes: 36 additions & 0 deletions confmap/provider/ssmprovider/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/ssmprovider

go 1.23.6

require (
github.com/aws/aws-sdk-go-v2/config v1.29.6
github.com/aws/aws-sdk-go-v2/service/ssm v1.56.12
github.com/stretchr/testify v1.10.0
go.opentelemetry.io/collector/confmap v1.25.0
)

require (
github.com/aws/aws-sdk-go-v2 v1.36.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.59 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 // indirect
github.com/aws/smithy-go v1.22.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
github.com/knadh/koanf/v2 v2.1.2 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
65 changes: 65 additions & 0 deletions confmap/provider/ssmprovider/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions confmap/provider/ssmprovider/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
status:
codeowners:
active: [jpkrohling]
92 changes: 92 additions & 0 deletions confmap/provider/ssmprovider/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package ssmprovider // import "github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/ssmprovider"

import (
"context"
"encoding/json"
"fmt"
"strings"

"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/ssm"
"go.opentelemetry.io/collector/confmap"
)

type ssmClient interface {
GetParameter(ctx context.Context, params *ssm.GetParameterInput, optFns ...func(*ssm.Options)) (*ssm.GetParameterOutput, error)
}

const (
schemeName = "ssm"
)

type provider struct {
client ssmClient
}

func NewFactory() confmap.ProviderFactory {
return confmap.NewProviderFactory(newWithSettings)
}

func newWithSettings(_ confmap.ProviderSettings) confmap.Provider {
return &provider{client: nil}
}

func (provider *provider) Retrieve(ctx context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) {
if !strings.HasPrefix(uri, schemeName+":") {
return nil, fmt.Errorf("%q uri is not supported by %q provider", uri, schemeName)
}

if provider.client == nil {
cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load configurations to initialize AWS SDK client, error: %w", err)
}
provider.client = ssm.NewFromConfig(cfg)
}

paramPath, jsonKey, hasJsonKey := strings.Cut(strings.TrimPrefix(uri, schemeName+":"), "#")

input := &ssm.GetParameterInput{
Name: &paramPath,
WithDecryption: true,
}

response, err := provider.client.GetParameter(ctx, input)
if err != nil {
return nil, fmt.Errorf("error getting parameter: %w", err)
}

if response.Parameter == nil || response.Parameter.Value == nil {
return nil, fmt.Errorf("parameter %q not found or has no value", paramPath)
}

paramValue := *response.Parameter.Value

if hasJsonKey {
var jsonData map[string]interface{}
err := json.Unmarshal([]byte(paramValue), &jsonData)
if err != nil {
return nil, fmt.Errorf("error parsing JSON from parameter: %w", err)
}

value, ok := jsonData[jsonKey]
if !ok {
return nil, fmt.Errorf("key %q not found in JSON parameter", jsonKey)
}

return confmap.NewRetrieved(value)
}

return confmap.NewRetrieved(paramValue)
}

func (*provider) Scheme() string {
return schemeName
}

func (*provider) Shutdown(context.Context) error {
return nil
}
79 changes: 79 additions & 0 deletions confmap/provider/ssmprovider/provider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package ssmprovider

import (
"context"
"fmt"
"testing"

"github.com/aws/aws-sdk-go-v2/service/ssm"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/confmap"
)

// Mock AWS SSM client
type testSSMClient struct {
parameterValue string
}

// Implement GetParameter()
func (client *testSSMClient) GetParameter(_ context.Context, _ *ssm.GetParameterInput,
_ ...func(*ssm.Options),
) (*ssm.GetParameterOutput, error) {
return &ssm.GetParameterOutput{Parameter: &ssm.Parameter{Value: &client.parameterValue}}, nil
}

// Create a provider using mock SSM client
func NewTestProvider(parameterValue string) confmap.Provider {
return &provider{client: &testSSMClient{parameterValue: parameterValue}}
}

func TestSSMProviderFetchParameter(t *testing.T) {
paramName := "FOO"
paramValue := "BAR"

fp := NewTestProvider(paramValue)
result, err := fp.Retrieve(context.Background(), "ssm:"+paramName, nil)

assert.NoError(t, err)
assert.NoError(t, fp.Shutdown(context.Background()))

value, err := result.AsRaw()
assert.NoError(t, err)
assert.NotNil(t, value)
assert.Equal(t, paramValue, value)
}

func TestSSMProviderFetchJsonKey(t *testing.T) {
paramName := "FOO#field1"
paramValue := "BAR"
jsonParam := fmt.Sprintf("{\"field1\": \"%s\"}", paramValue)

fp := NewTestProvider(jsonParam)
result, err := fp.Retrieve(context.Background(), "ssm:"+paramName, nil)

assert.NoError(t, err)
assert.NoError(t, fp.Shutdown(context.Background()))

value, err := result.AsRaw()
assert.NoError(t, err)
assert.NotNil(t, value)
assert.Equal(t, paramValue, value)
}

func TestSSMProviderInvalidURI(t *testing.T) {
fp := NewTestProvider("dummy")
_, err := fp.Retrieve(context.Background(), "invalid:FOO", nil)

assert.Error(t, err)
assert.NoError(t, fp.Shutdown(context.Background()))
}

func TestFactory(t *testing.T) {
p := NewFactory().Create(confmap.ProviderSettings{})
_, ok := p.(*provider)
require.True(t, ok)
}
1 change: 1 addition & 0 deletions versions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module-sets:
- github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/aesprovider
- github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/s3provider
- github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/secretsmanagerprovider
- github.com/open-telemetry/opentelemetry-collector-contrib/confmap/provider/ssmprovider
- github.com/open-telemetry/opentelemetry-collector-contrib/connector/countconnector
- github.com/open-telemetry/opentelemetry-collector-contrib/connector/datadogconnector
- github.com/open-telemetry/opentelemetry-collector-contrib/connector/exceptionsconnector
Expand Down

0 comments on commit 4458f6e

Please sign in to comment.