From dec7e3c62fc0e154ff51313f1857edcb9264917f Mon Sep 17 00:00:00 2001 From: Haydn Evans Date: Mon, 30 Dec 2024 13:52:02 +0100 Subject: [PATCH 1/2] enable aws iam rds auth for the postgres scaler add iam auth for postgres --- go.mod | 1 + go.sum | 2 + pkg/scalers/postgresql_scaler.go | 50 +++ pkg/scalers/postgresql_scaler_test.go | 19 + .../feature/rds/auth/CHANGELOG.md | 382 ++++++++++++++++++ .../feature/rds/auth/LICENSE.txt | 202 +++++++++ .../aws-sdk-go-v2/feature/rds/auth/connect.go | 125 ++++++ .../aws/aws-sdk-go-v2/feature/rds/auth/doc.go | 8 + .../feature/rds/auth/go_module_metadata.go | 6 + vendor/modules.txt | 3 + 10 files changed, 798 insertions(+) create mode 100644 vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/CHANGELOG.md create mode 100644 vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/LICENSE.txt create mode 100644 vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/connect.go create mode 100644 vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/doc.go create mode 100644 vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/go_module_metadata.go diff --git a/go.mod b/go.mod index 5fc7977aee5..acf4daee3e3 100644 --- a/go.mod +++ b/go.mod @@ -123,6 +123,7 @@ require ( github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect + github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect github.com/envoyproxy/go-control-plane v0.13.1 // indirect diff --git a/go.sum b/go.sum index e993505b713..2f4d06c78a3 100644 --- a/go.sum +++ b/go.sum @@ -1501,6 +1501,8 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.48/go.mod h1:tOscxHN3CGmuX9idQ3+q github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.13/go.mod h1:y0eXmsNBFIVjUE8ZBjES8myOHlMsXDz7qGT93+MVdjk= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 h1:kqOrpojG71DxJm/KDPO+Z/y1phm1JlC8/iT+5XRmAn8= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22/go.mod h1:NtSFajXVVL8TA2QNngagVZmUtXciyrHOt7xgz4faS/M= +github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2 h1:fo+GuZNME9oGDc7VY+EBT+oCrco6RjRgUp1bKTcaHrU= +github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2/go.mod h1:fnqb94UO6YCjBIic4WaqDYkNVAEFWOWiReVHitBBWW0= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.19/go.mod h1:llxE6bwUZhuCas0K7qGiu5OgMis3N7kdWtFSxoHmJ7E= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 h1:I/5wmGMffY4happ8NOCuIUEWGUvvFp5NSeQcXl9RHcI= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26/go.mod h1:FR8f4turZtNy6baO0KJ5FJUmXH/cSkI9fOngs0yl6mA= diff --git a/pkg/scalers/postgresql_scaler.go b/pkg/scalers/postgresql_scaler.go index 6ea0203b898..04ce1af2c27 100644 --- a/pkg/scalers/postgresql_scaler.go +++ b/pkg/scalers/postgresql_scaler.go @@ -11,8 +11,10 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/aws/aws-sdk-go-v2/feature/rds/auth" "github.com/go-logr/logr" _ "github.com/jackc/pgx/v5/stdlib" // PostreSQL drive required for this scaler + awsutils "github.com/kedacore/keda/v2/pkg/scalers/aws" v2 "k8s.io/api/autoscaling/v2" "k8s.io/metrics/pkg/apis/external_metrics" @@ -47,6 +49,9 @@ type postgreSQLMetadata struct { Query string `keda:"name=query, order=triggerMetadata"` triggerIndex int azureAuthContext azureAuthContext + AwsRegion string `keda:"name=awsRegion, order=triggerMetadata;authParams"` + awsAuthorization awsutils.AuthorizationMetadata + awsAuthContext awsAuthContext Host string `keda:"name=host, order=authParams;triggerMetadata, optional"` Port string `keda:"name=port, order=authParams;triggerMetadata, optional"` @@ -88,6 +93,10 @@ type azureAuthContext struct { token *azcore.AccessToken } +type awsAuthContext struct { + expiry time.Time +} + // NewPostgreSQLScaler creates a new postgreSQL scaler func NewPostgreSQLScaler(ctx context.Context, config *scalersconfig.ScalerConfig) (Scaler, error) { metricType, err := GetMetricTargetType(config) @@ -144,6 +153,19 @@ func parsePostgreSQLMetadata(logger logr.Logger, config *scalersconfig.ScalerCon meta.azureAuthContext.cred = cred authPodIdentity = kedav1alpha1.AuthPodIdentity{Provider: config.PodIdentity.Provider} + params = append(params, "%PASSWORD%") + meta.Connection = strings.Join(params, " ") + case kedav1alpha1.PodIdentityProviderAws: + params := buildConnArray(meta) + + auth, err := awsutils.GetAwsAuthorization(config.TriggerUniqueKey, meta.AwsRegion, config.PodIdentity, config.TriggerMetadata, config.AuthParams, config.ResolvedEnv) + if err != nil { + return nil, authPodIdentity, err + } + + meta.awsAuthorization = auth + authPodIdentity = kedav1alpha1.AuthPodIdentity{Provider: config.PodIdentity.Provider} + params = append(params, "%PASSWORD%") meta.Connection = strings.Join(params, " ") } @@ -175,6 +197,22 @@ func getConnection(ctx context.Context, meta *postgreSQLMetadata, podIdentity ke connectionString = passwordConnPattern.ReplaceAllString(meta.Connection, newPasswordField) } + if podIdentity.Provider == kedav1alpha1.PodIdentityProviderAws { + cfg, err := awsutils.GetAwsConfig(ctx, meta.awsAuthorization) + if err != nil { + return nil, err + } + DBendpoint := fmt.Sprintf("%s:%s", meta.Host, meta.Port) + password, err := auth.BuildAuthToken(ctx, DBendpoint, meta.AwsRegion, meta.UserName, cfg.Credentials) + if err != nil { + return nil, err + } + meta.awsAuthContext.expiry = time.Now().Add(14 * time.Minute) + + newPasswordField := "password=" + escapePostgreConnectionParameter(password) + connectionString = passwordConnPattern.ReplaceAllString(meta.Connection, newPasswordField) + } + db, err := sql.Open("pgx", connectionString) if err != nil { logger.Error(err, fmt.Sprintf("Found error opening postgreSQL: %s", err)) @@ -213,6 +251,18 @@ func (s *postgreSQLScaler) getActiveNumber(ctx context.Context) (float64, error) } } + if s.podIdentity.Provider == kedav1alpha1.PodIdentityProviderAws { + if s.metadata.awsAuthContext.expiry.Before(time.Now()) { + s.logger.Info("The AWS Access Token expired, retrieving a new AWS Access Token and instantiating a new Postgres connection object.") + s.connection.Close() + newConnection, err := getConnection(ctx, s.metadata, s.podIdentity, s.logger) + if err != nil { + return 0, fmt.Errorf("error establishing postgreSQL connection: %w", err) + } + s.connection = newConnection + } + } + err := s.connection.QueryRowContext(ctx, s.metadata.Query).Scan(&id) if err != nil { s.logger.Error(err, fmt.Sprintf("could not query postgreSQL: %s", err)) diff --git a/pkg/scalers/postgresql_scaler_test.go b/pkg/scalers/postgresql_scaler_test.go index da82ca6e3d4..83fdaf354d9 100644 --- a/pkg/scalers/postgresql_scaler_test.go +++ b/pkg/scalers/postgresql_scaler_test.go @@ -96,6 +96,11 @@ var testPodIdentityAzureWorkloadPostgreSQLConnectionstring = []postgreSQLConnect {metadata: map[string]string{"query": "test_query", "targetQueryValue": "5", "host": "localhost", "port": "1234", "dbName": "testDb", "userName": "user", "sslmode": "required"}, connectionString: "host=localhost port=1234 user=user dbname=testDb sslmode=required %PASSWORD%"}, } +var testPodIdentityAwsWorkloadPostgresSQLConnectionstring = []postgreSQLConnectionStringTestData{ + // from meta + {metadata: map[string]string{"query": "test_query", "targetQueryValue": "5", "host": "localhost", "port": "1234", "dbName": "testDb", "userName": "user", "sslmode": "required"}, connectionString: "host=localhost port=1234 user=user dbname=testDb sslmode=required %PASSWORD%"}, +} + func TestPodIdentityAzureWorkloadPosgresSQLConnectionStringGeneration(t *testing.T) { identityID := "IDENTITY_ID_CORRESPONDING_TO_USERNAME_FIELD" for _, testData := range testPodIdentityAzureWorkloadPostgreSQLConnectionstring { @@ -110,6 +115,20 @@ func TestPodIdentityAzureWorkloadPosgresSQLConnectionStringGeneration(t *testing } } +func TestPodIdentityAWSWorkloadPosgresSQLConnectionStringGeneration(t *testing.T) { + identityID := "IDENTITY_ID_CORRESPONDING_TO_USERNAME_FIELD" + for _, testData := range testPodIdentityAwsWorkloadPostgresSQLConnectionstring { + meta, _, err := parsePostgreSQLMetadata(logr.Discard(), &scalersconfig.ScalerConfig{ResolvedEnv: testData.resolvedEnv, TriggerMetadata: testData.metadata, PodIdentity: kedav1alpha1.AuthPodIdentity{Provider: kedav1alpha1.PodIdentityProviderAWSWorkload, IdentityID: &identityID}, AuthParams: testData.authParam, TriggerIndex: 0}) + if err != nil { + t.Fatal("Could not parse metadata:", err) + } + + if meta.Connection != testData.connectionString { + t.Errorf("Error generating connectionString, expected '%s' and get '%s'", testData.connectionString, meta.Connection) + } + } +} + type parsePostgresMetadataTestData struct { metadata map[string]string authParams map[string]string diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/CHANGELOG.md new file mode 100644 index 00000000000..9dc410e182f --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/CHANGELOG.md @@ -0,0 +1,382 @@ +# v1.5.2 (2024-12-19) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.5.1 (2024-12-06) + +* **Bug Fix**: **BREAKFIX**: Revert bad API release. + +# v1.5.0 (2024-12-03.2) + +* No change notes available for this release. + +# v1.4.25 (2024-12-02) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.24 (2024-11-18) + +* **Dependency Update**: Update to smithy-go v1.22.1. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.23 (2024-11-06) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.22 (2024-10-28) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.21 (2024-10-08) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.20 (2024-10-07) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.19 (2024-10-04) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.18 (2024-09-20) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.17 (2024-09-03) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.16 (2024-08-15) + +* **Dependency Update**: Bump minimum Go version to 1.21. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.15 (2024-07-10.2) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.14 (2024-07-10) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.13 (2024-06-28) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.12 (2024-06-19) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.11 (2024-06-18) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.10 (2024-06-17) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.9 (2024-06-07) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.8 (2024-06-03) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.7 (2024-05-16) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.6 (2024-05-15) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.5 (2024-03-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.4 (2024-03-18) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.3 (2024-03-07) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.2 (2024-02-23) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.1 (2024-02-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.4.0 (2024-02-13) + +* **Feature**: Bump minimum Go version to 1.20 per our language support policy. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.10 (2024-01-04) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.9 (2023-12-07) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.8 (2023-12-01) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.7 (2023-11-30) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.6 (2023-11-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.5 (2023-11-28.2) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.4 (2023-11-20) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.3 (2023-11-15) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.2 (2023-11-09) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.1 (2023-11-01) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.3.0 (2023-10-31) + +* **Feature**: **BREAKING CHANGE**: Bump minimum go version to 1.19 per the revised [go version support policy](https://aws.amazon.com/blogs/developer/aws-sdk-for-go-aligns-with-go-release-policy-on-supported-runtimes/). +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.21 (2023-10-12) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.20 (2023-10-06) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.19 (2023-08-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.18 (2023-08-18) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.17 (2023-08-17) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.16 (2023-08-07) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.15 (2023-07-31) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.14 (2023-07-28) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.13 (2023-07-13) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.12 (2023-06-13) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.11 (2023-04-24) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.10 (2023-04-07) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.9 (2023-03-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.8 (2023-03-10) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.7 (2023-02-20) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.6 (2023-02-03) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.5 (2022-12-15) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.4 (2022-12-02) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.3 (2022-10-24) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.2 (2022-10-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.1 (2022-09-20) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.2.0 (2022-09-14) + +* **Feature**: Updated `BuildAuthToken` to validate the provided endpoint contains a port. +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.31 (2022-09-02) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.30 (2022-08-31) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.29 (2022-08-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.28 (2022-08-11) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.27 (2022-08-09) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.26 (2022-08-08) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.25 (2022-08-01) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.24 (2022-07-05) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.23 (2022-06-29) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.22 (2022-06-07) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.21 (2022-05-17) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.20 (2022-04-25) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.19 (2022-03-30) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.18 (2022-03-24) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.17 (2022-03-23) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.16 (2022-03-08) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.15 (2022-02-24) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.14 (2022-01-14) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.13 (2022-01-07) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.12 (2021-12-02) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.11 (2021-11-19) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.10 (2021-11-06) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.9 (2021-10-21) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.8 (2021-10-11) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.7 (2021-09-17) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.6 (2021-08-27) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.5 (2021-08-19) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.4 (2021-08-04) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.3 (2021-07-15) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.2 (2021-06-25) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.1 (2021-05-20) + +* **Dependency Update**: Updated to the latest SDK module versions + +# v1.1.0 (2021-05-14) + +* **Feature**: Constant has been added to modules to enable runtime version inspection for reporting. +* **Dependency Update**: Updated to the latest SDK module versions + diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/LICENSE.txt b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/LICENSE.txt new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/connect.go b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/connect.go new file mode 100644 index 00000000000..9a1406e7ed3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/connect.go @@ -0,0 +1,125 @@ +package auth + +import ( + "context" + "fmt" + "net/http" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/signer/v4" +) + +const ( + signingID = "rds-db" + emptyPayloadHash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +) + +// BuildAuthTokenOptions is the optional set of configuration properties for BuildAuthToken +type BuildAuthTokenOptions struct{} + +// BuildAuthToken will return an authorization token used as the password for a DB +// connection. +// +// * endpoint - Endpoint consists of the port needed to connect to the DB. : +// * region - Region is the location of where the DB is +// * dbUser - User account within the database to sign in with +// * creds - Credentials to be signed with +// +// The following example shows how to use BuildAuthToken to create an authentication +// token for connecting to a MySQL database in RDS. +// +// authToken, err := BuildAuthToken(dbEndpoint, awsRegion, dbUser, awsCreds) +// +// // Create the MySQL DNS string for the DB connection +// // user:password@protocol(endpoint)/dbname? +// connectStr = fmt.Sprintf("%s:%s@tcp(%s)/%s?allowCleartextPasswords=true&tls=rds", +// dbUser, authToken, dbEndpoint, dbName, +// ) +// +// // Use db to perform SQL operations on database +// db, err := sql.Open("mysql", connectStr) +// +// See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html +// for more information on using IAM database authentication with RDS. +func BuildAuthToken(ctx context.Context, endpoint, region, dbUser string, creds aws.CredentialsProvider, optFns ...func(options *BuildAuthTokenOptions)) (string, error) { + _, port := validateURL(endpoint) + if port == "" { + return "", fmt.Errorf("the provided endpoint is missing a port, or the provided port is invalid") + } + + o := BuildAuthTokenOptions{} + + for _, fn := range optFns { + fn(&o) + } + + if creds == nil { + return "", fmt.Errorf("credetials provider must not ne nil") + } + + // the scheme is arbitrary and is only needed because validation of the URL requires one. + if !(strings.HasPrefix(endpoint, "http://") || strings.HasPrefix(endpoint, "https://")) { + endpoint = "https://" + endpoint + } + + req, err := http.NewRequest("GET", endpoint, nil) + if err != nil { + return "", err + } + values := req.URL.Query() + values.Set("Action", "connect") + values.Set("DBUser", dbUser) + req.URL.RawQuery = values.Encode() + + signer := v4.NewSigner() + + credentials, err := creds.Retrieve(ctx) + if err != nil { + return "", err + } + + // Expire Time: 15 minute + query := req.URL.Query() + query.Set("X-Amz-Expires", "900") + req.URL.RawQuery = query.Encode() + + signedURI, _, err := signer.PresignHTTP(ctx, credentials, req, emptyPayloadHash, signingID, region, time.Now().UTC()) + if err != nil { + return "", err + } + + url := signedURI + if strings.HasPrefix(url, "http://") { + url = url[len("http://"):] + } else if strings.HasPrefix(url, "https://") { + url = url[len("https://"):] + } + + return url, nil +} + +func validateURL(hostPort string) (host, port string) { + colon := strings.LastIndexByte(hostPort, ':') + if colon != -1 { + host, port = hostPort[:colon], hostPort[colon+1:] + } + if !validatePort(port) { + port = "" + return + } + if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") { + host = host[1 : len(host)-1] + } + + return +} + +func validatePort(port string) bool { + if _, err := strconv.Atoi(port); err == nil { + return true + } + return false +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/doc.go b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/doc.go new file mode 100644 index 00000000000..f4056bf0491 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/doc.go @@ -0,0 +1,8 @@ +// Package auth is used to generate authentication tokens used to +// connect to a given Amazon Relational Database Service (RDS) database. +// +// Before using the authentication please visit the docs here to ensure +// the database has the proper policies to allow for IAM token authentication. +// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html#UsingWithRDS.IAMDBAuth.Availability +// https://aws.github.io/aws-sdk-go-v2/docs/sdk-utilities/rds +package auth diff --git a/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/go_module_metadata.go new file mode 100644 index 00000000000..2655dbb68d1 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/feature/rds/auth/go_module_metadata.go @@ -0,0 +1,6 @@ +// Code generated by internal/repotools/cmd/updatemodulemeta DO NOT EDIT. + +package auth + +// goModuleVersion is the tagged release for this module +const goModuleVersion = "1.5.2" diff --git a/vendor/modules.txt b/vendor/modules.txt index 1b5fa322815..794c84029a5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -374,6 +374,9 @@ github.com/aws/aws-sdk-go-v2/credentials/stscreds ## explicit; go 1.21 github.com/aws/aws-sdk-go-v2/feature/ec2/imds github.com/aws/aws-sdk-go-v2/feature/ec2/imds/internal/config +# github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2 +## explicit; go 1.21 +github.com/aws/aws-sdk-go-v2/feature/rds/auth # github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 ## explicit; go 1.21 github.com/aws/aws-sdk-go-v2/internal/configsources From fce9192caafb818e67c725c005937b40a64c4648 Mon Sep 17 00:00:00 2001 From: Haydn Evans Date: Mon, 30 Dec 2024 14:36:02 +0100 Subject: [PATCH 2/2] code quality suggestions --- pkg/scalers/postgresql_scaler.go | 7 ++++--- pkg/scalers/postgresql_scaler_test.go | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/scalers/postgresql_scaler.go b/pkg/scalers/postgresql_scaler.go index 04ce1af2c27..2404ee4f4ad 100644 --- a/pkg/scalers/postgresql_scaler.go +++ b/pkg/scalers/postgresql_scaler.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "fmt" + "net" "regexp" "strings" "time" @@ -14,11 +15,11 @@ import ( "github.com/aws/aws-sdk-go-v2/feature/rds/auth" "github.com/go-logr/logr" _ "github.com/jackc/pgx/v5/stdlib" // PostreSQL drive required for this scaler - awsutils "github.com/kedacore/keda/v2/pkg/scalers/aws" v2 "k8s.io/api/autoscaling/v2" "k8s.io/metrics/pkg/apis/external_metrics" kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1" + awsutils "github.com/kedacore/keda/v2/pkg/scalers/aws" "github.com/kedacore/keda/v2/pkg/scalers/azure" "github.com/kedacore/keda/v2/pkg/scalers/scalersconfig" kedautil "github.com/kedacore/keda/v2/pkg/util" @@ -49,7 +50,7 @@ type postgreSQLMetadata struct { Query string `keda:"name=query, order=triggerMetadata"` triggerIndex int azureAuthContext azureAuthContext - AwsRegion string `keda:"name=awsRegion, order=triggerMetadata;authParams"` + AwsRegion string `keda:"name=awsRegion, order=triggerMetadata;authParams, optional"` awsAuthorization awsutils.AuthorizationMetadata awsAuthContext awsAuthContext @@ -202,7 +203,7 @@ func getConnection(ctx context.Context, meta *postgreSQLMetadata, podIdentity ke if err != nil { return nil, err } - DBendpoint := fmt.Sprintf("%s:%s", meta.Host, meta.Port) + DBendpoint := net.JoinHostPort(meta.Host, meta.Port) password, err := auth.BuildAuthToken(ctx, DBendpoint, meta.AwsRegion, meta.UserName, cfg.Credentials) if err != nil { return nil, err diff --git a/pkg/scalers/postgresql_scaler_test.go b/pkg/scalers/postgresql_scaler_test.go index 83fdaf354d9..fff69a10af3 100644 --- a/pkg/scalers/postgresql_scaler_test.go +++ b/pkg/scalers/postgresql_scaler_test.go @@ -98,7 +98,7 @@ var testPodIdentityAzureWorkloadPostgreSQLConnectionstring = []postgreSQLConnect var testPodIdentityAwsWorkloadPostgresSQLConnectionstring = []postgreSQLConnectionStringTestData{ // from meta - {metadata: map[string]string{"query": "test_query", "targetQueryValue": "5", "host": "localhost", "port": "1234", "dbName": "testDb", "userName": "user", "sslmode": "required"}, connectionString: "host=localhost port=1234 user=user dbname=testDb sslmode=required %PASSWORD%"}, + {metadata: map[string]string{"query": "test_query", "targetQueryValue": "5", "host": "localhost", "port": "1234", "dbName": "testDb", "userName": "user", "sslmode": "required", "awsRegion": "eu-central-1"}, connectionString: "host=localhost port=1234 user=user dbname=testDb sslmode=required %PASSWORD%"}, } func TestPodIdentityAzureWorkloadPosgresSQLConnectionStringGeneration(t *testing.T) { @@ -118,7 +118,7 @@ func TestPodIdentityAzureWorkloadPosgresSQLConnectionStringGeneration(t *testing func TestPodIdentityAWSWorkloadPosgresSQLConnectionStringGeneration(t *testing.T) { identityID := "IDENTITY_ID_CORRESPONDING_TO_USERNAME_FIELD" for _, testData := range testPodIdentityAwsWorkloadPostgresSQLConnectionstring { - meta, _, err := parsePostgreSQLMetadata(logr.Discard(), &scalersconfig.ScalerConfig{ResolvedEnv: testData.resolvedEnv, TriggerMetadata: testData.metadata, PodIdentity: kedav1alpha1.AuthPodIdentity{Provider: kedav1alpha1.PodIdentityProviderAWSWorkload, IdentityID: &identityID}, AuthParams: testData.authParam, TriggerIndex: 0}) + meta, _, err := parsePostgreSQLMetadata(logr.Discard(), &scalersconfig.ScalerConfig{ResolvedEnv: testData.resolvedEnv, TriggerMetadata: testData.metadata, PodIdentity: kedav1alpha1.AuthPodIdentity{Provider: kedav1alpha1.PodIdentityProviderAws, IdentityID: &identityID}, AuthParams: testData.authParam, TriggerIndex: 0}) if err != nil { t.Fatal("Could not parse metadata:", err) }