Skip to content
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
23 changes: 23 additions & 0 deletions pkg/cloud/endpointsv2/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/eventbridge"
rgapi "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
"github.com/aws/aws-sdk-go-v2/service/sqs"
"github.com/aws/aws-sdk-go-v2/service/ssm"
"github.com/aws/aws-sdk-go-v2/service/sts"
Expand Down Expand Up @@ -326,3 +327,25 @@ func (s *STSEndpointResolver) ResolveEndpoint(ctx context.Context, params sts.En
params.Region = &endpoint.SigningRegion
return sts.NewDefaultEndpointResolverV2().ResolveEndpoint(ctx, params)
}

// SecretsManagerEndpointResolver implements EndpointResolverV2 interface for Secrets Manager.
type SecretsManagerEndpointResolver struct {
*MultiServiceEndpointResolver
}

// ResolveEndpoint for Secrets Manager.
func (s *SecretsManagerEndpointResolver) ResolveEndpoint(ctx context.Context, params secretsmanager.EndpointParameters) (smithyendpoints.Endpoint, error) {
// If custom endpoint not found, return default endpoint for the service
log := logger.FromContext(ctx)
endpoint, ok := s.endpoints[secretsmanager.ServiceID]

if !ok {
log.Debug("Custom endpoint not found, using default endpoint")
return secretsmanager.NewDefaultEndpointResolverV2().ResolveEndpoint(ctx, params)
}

log.Debug("Custom endpoint found, using custom endpoint", "endpoint", endpoint.URL)
params.Endpoint = &endpoint.URL
params.Region = &endpoint.SigningRegion
return secretsmanager.NewDefaultEndpointResolverV2().ResolveEndpoint(ctx, params)
}
11 changes: 7 additions & 4 deletions pkg/cloud/scope/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,20 +217,23 @@ func NewResourgeTaggingClient(scopeUser cloud.ScopeUsage, session cloud.Session,
// NewSecretsManagerClient creates a new Secrets API client for a given session..
func NewSecretsManagerClient(scopeUser cloud.ScopeUsage, session cloud.Session, logger logger.Wrapper, target runtime.Object) *secretsmanager.Client {
cfg := session.Session()

secretsOpts := []func(*secretsmanager.Options){
multiSvcEndpointResolver := endpointsv2.NewMultiServiceEndpointResolver()
secretsManagerEndpointResolver := &endpointsv2.SecretsManagerEndpointResolver{
MultiServiceEndpointResolver: multiSvcEndpointResolver,
}
secretsManagerOpts := []func(*secretsmanager.Options){
func(o *secretsmanager.Options) {
o.Logger = logger.GetAWSLogger()
o.ClientLogMode = awslogs.GetAWSLogLevelV2(logger.GetLogger())
o.EndpointResolverV2 = secretsManagerEndpointResolver
},
secretsmanager.WithAPIOptions(
awsmetricsv2.WithMiddlewares(scopeUser.ControllerName(), target),
awsmetricsv2.WithCAPAUserAgentMiddleware(),
throttle.WithServiceLimiterMiddleware(session.ServiceLimiter(secretsmanager.ServiceID)),
),
}

return secretsmanager.NewFromConfig(cfg, secretsOpts...)
return secretsmanager.NewFromConfig(cfg, secretsManagerOpts...)
}

// NewEKSClient creates a new EKS API client for a given session.
Expand Down
19 changes: 11 additions & 8 deletions pkg/cloud/services/secretsmanager/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ package secretsmanager

import (
"context"
"errors"
"fmt"
"path"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
"github.com/aws/smithy-go"
kerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/uuid"

infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/awserrors"
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/convertersv2"
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/scope"
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/services/wait"
Expand Down Expand Up @@ -93,11 +94,11 @@ func (s *Service) retryableCreateSecret(name string, chunk []byte, tags infrav1.
Tags: convertersv2.MapToSecretsManagerTags(tags),
})
// If the secret already exists, delete it, return request to retry, as deletes are eventually consistent
smithyErr := awserrors.ParseSmithyError(err)
if smithyErr != nil && smithyErr.ErrorCode() == "ResourceExistsException" {
return false, s.forceDeleteSecretEntry(name)
}
if err != nil {
var aerr smithy.APIError
if errors.As(err, &aerr) && aerr.ErrorCode() == "ResourceExistsException" {
return false, s.forceDeleteSecretEntry(name)
}
return false, err
}
return true, err
Expand All @@ -109,9 +110,11 @@ func (s *Service) forceDeleteSecretEntry(name string) error {
SecretId: aws.String(name),
ForceDeleteWithoutRecovery: aws.Bool(true),
})
smithyErr := awserrors.ParseSmithyError(err)
if smithyErr != nil && smithyErr.ErrorCode() == "ResourceNotFoundException" {
return nil
if err != nil {
var aerr smithy.APIError
if errors.As(err, &aerr) && aerr.ErrorCode() == "ResourceNotFoundException" {
return nil
}
}
return err
}
Expand Down
24 changes: 12 additions & 12 deletions pkg/cloud/services/secretsmanager/secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (

infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/scope"
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/services/secretsmanager/mock_secretsmanageriface"
"sigs.k8s.io/cluster-api-provider-aws/v2/test/mocks"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
)

Expand Down Expand Up @@ -89,15 +89,15 @@ func TestServiceCreate(t *testing.T) {
secretPrefix string
expectedPrefix string
wantErr bool
expect func(g *WithT, m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder)
expect func(g *WithT, m *mocks.MockSecretsManagerAPIMockRecorder)
}{
{
name: "Should not store data in secret manager if data is having zero bytes",
bytesCount: 0,
secretPrefix: "/awsprefix",
expectedPrefix: "/awsprefix",
wantErr: false,
expect: func(g *WithT, m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder) {
expect: func(g *WithT, m *mocks.MockSecretsManagerAPIMockRecorder) {
m.CreateSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.CreateSecretInput{})).Times(0)
},
},
Expand All @@ -107,7 +107,7 @@ func TestServiceCreate(t *testing.T) {
secretPrefix: "prefix",
expectedPrefix: "prefix",
wantErr: false,
expect: func(g *WithT, m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder) {
expect: func(g *WithT, m *mocks.MockSecretsManagerAPIMockRecorder) {
m.CreateSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.CreateSecretInput{})).MinTimes(1).Return(&secretsmanager.CreateSecretOutput{}, nil).Do(
func(ctx context.Context, createSecretInput *secretsmanager.CreateSecretInput, optFns ...func(*secretsmanager.Options)) {
g.Expect(*(createSecretInput.Name)).To(HavePrefix("prefix-"))
Expand All @@ -123,7 +123,7 @@ func TestServiceCreate(t *testing.T) {
secretPrefix: "/prefix",
expectedPrefix: "/prefix",
wantErr: true,
expect: func(g *WithT, m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder) {
expect: func(g *WithT, m *mocks.MockSecretsManagerAPIMockRecorder) {
m.CreateSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.CreateSecretInput{})).Return(nil, &types.InternalServiceError{}).Do(
func(ctx context.Context, createSecretInput *secretsmanager.CreateSecretInput, optFns ...func(*secretsmanager.Options)) {
g.Expect(*(createSecretInput.Name)).To(HavePrefix("/prefix-"))
Expand All @@ -139,7 +139,7 @@ func TestServiceCreate(t *testing.T) {
secretPrefix: "",
expectedPrefix: "aws.cluster.x-k8s.io",
wantErr: false,
expect: func(g *WithT, m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder) {
expect: func(g *WithT, m *mocks.MockSecretsManagerAPIMockRecorder) {
m.CreateSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.CreateSecretInput{})).Return(nil, &types.InvalidRequestException{})
m.CreateSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.CreateSecretInput{})).Return(nil, &types.ResourceNotFoundException{})
m.CreateSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.CreateSecretInput{})).Return(&secretsmanager.CreateSecretOutput{}, nil)
Expand All @@ -151,7 +151,7 @@ func TestServiceCreate(t *testing.T) {
secretPrefix: "",
expectedPrefix: "aws.cluster.x-k8s.io",
wantErr: false,
expect: func(g *WithT, m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder) {
expect: func(g *WithT, m *mocks.MockSecretsManagerAPIMockRecorder) {
m.CreateSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.CreateSecretInput{})).Return(nil, &types.ResourceExistsException{})
m.DeleteSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.DeleteSecretInput{})).Return(&secretsmanager.DeleteSecretOutput{}, nil)
m.CreateSecret(gomock.Any(), gomock.AssignableToTypeOf(&secretsmanager.CreateSecretInput{})).Return(&secretsmanager.CreateSecretOutput{}, nil)
Expand All @@ -167,7 +167,7 @@ func TestServiceCreate(t *testing.T) {
clusterScope, err := getClusterScope(client)
g.Expect(err).NotTo(HaveOccurred())

secretManagerClientMock := mock_secretsmanageriface.NewMockSecretsManagerAPI(mockCtrl)
secretManagerClientMock := mocks.NewMockSecretsManagerAPI(mockCtrl)
tt.expect(g, secretManagerClientMock.EXPECT())
s := NewService(clusterScope)
s.SecretsManagerClient = secretManagerClientMock
Expand All @@ -189,7 +189,7 @@ func TestServiceDelete(t *testing.T) {
tests := []struct {
name string
secretCount int32
expect func(m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder)
expect func(m *mocks.MockSecretsManagerAPIMockRecorder)
check func(*WithT, error)
}{
{
Expand All @@ -202,7 +202,7 @@ func TestServiceDelete(t *testing.T) {
{
name: "Should not return error when delete is successful",
secretCount: 1,
expect: func(m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder) {
expect: func(m *mocks.MockSecretsManagerAPIMockRecorder) {
m.DeleteSecret(gomock.Any(), gomock.Eq(&secretsmanager.DeleteSecretInput{
SecretId: aws.String("prefix-0"),
ForceDeleteWithoutRecovery: aws.Bool(true),
Expand All @@ -215,7 +215,7 @@ func TestServiceDelete(t *testing.T) {
{
name: "Should return all errors except not found errors",
secretCount: 3,
expect: func(m *mock_secretsmanageriface.MockSecretsManagerAPIMockRecorder) {
expect: func(m *mocks.MockSecretsManagerAPIMockRecorder) {
m.DeleteSecret(gomock.Any(), gomock.Eq(&secretsmanager.DeleteSecretInput{
SecretId: aws.String("prefix-0"),
ForceDeleteWithoutRecovery: aws.Bool(true),
Expand All @@ -242,7 +242,7 @@ func TestServiceDelete(t *testing.T) {
clusterScope, err := getClusterScope(client)
g.Expect(err).NotTo(HaveOccurred())

secretManagerClientMock := mock_secretsmanageriface.NewMockSecretsManagerAPI(mockCtrl)
secretManagerClientMock := mocks.NewMockSecretsManagerAPI(mockCtrl)
if tt.expect != nil {
tt.expect(secretManagerClientMock.EXPECT())
}
Expand Down

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

2 changes: 2 additions & 0 deletions test/mocks/generate_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ limitations under the License.
//go:generate /usr/bin/env bash -c "cat ../../hack/boilerplate/boilerplate.generatego.txt aws_rgtagging_mock.go > _aws_rgtagging_mock.go && mv _aws_rgtagging_mock.go aws_rgtagging_mock.go"
//go:generate ../../hack/tools/bin/mockgen -destination aws_ec2api_mock.go -package mocks sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/services/common EC2API
//go:generate /usr/bin/env bash -c "cat ../../hack/boilerplate/boilerplate.generatego.txt aws_ec2api_mock.go > _aws_ec2api_mock.go && mv _aws_ec2api_mock.go aws_ec2api_mock.go"
//go:generate ../../hack/tools/bin/mockgen -destination aws_secretsmanager_mock.go -package mocks sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/services/secretsmanager SecretsManagerAPI
//go:generate /usr/bin/env bash -c "cat ../../hack/boilerplate/boilerplate.generatego.txt aws_secretsmanager_mock.go > _aws_secretsmanager_mock.go && mv _aws_secretsmanager_mock.go aws_secretsmanager_mock.go"
package mocks