mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 09:44:51 +00:00
RDS & Redshfit support for AWS China regions (part 1?) (#10560)
This commit is contained in:
parent
5a11006f81
commit
fd12e934ee
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/gravitational/teleport/api/utils"
|
||||
awsutils "github.com/gravitational/teleport/api/utils/aws"
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
|
@ -378,8 +379,8 @@ func (d *DatabaseV3) CheckAndSetDefaults() error {
|
|||
// In case of RDS, Aurora or Redshift, AWS information such as region or
|
||||
// cluster ID can be extracted from the endpoint if not provided.
|
||||
switch {
|
||||
case strings.Contains(d.Spec.URI, RDSEndpointSuffix):
|
||||
instanceID, region, err := parseRDSEndpoint(d.Spec.URI)
|
||||
case awsutils.IsRDSEndpoint(d.Spec.URI):
|
||||
instanceID, region, err := awsutils.ParseRDSEndpoint(d.Spec.URI)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
@ -389,8 +390,8 @@ func (d *DatabaseV3) CheckAndSetDefaults() error {
|
|||
if d.Spec.AWS.Region == "" {
|
||||
d.Spec.AWS.Region = region
|
||||
}
|
||||
case strings.Contains(d.Spec.URI, RedshiftEndpointSuffix):
|
||||
clusterID, region, err := parseRedshiftEndpoint(d.Spec.URI)
|
||||
case awsutils.IsRedshiftEndpoint(d.Spec.URI):
|
||||
clusterID, region, err := awsutils.ParseRedshiftEndpoint(d.Spec.URI)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
@ -412,36 +413,6 @@ func (d *DatabaseV3) CheckAndSetDefaults() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// parseRDSEndpoint extracts region from the provided RDS endpoint.
|
||||
func parseRDSEndpoint(endpoint string) (instanceID, region string, err error) {
|
||||
host, _, err := net.SplitHostPort(endpoint)
|
||||
if err != nil {
|
||||
return "", "", trace.Wrap(err)
|
||||
}
|
||||
// RDS/Aurora endpoint looks like this:
|
||||
// aurora-instance-1.abcdefghijklmnop.us-west-1.rds.amazonaws.com
|
||||
parts := strings.Split(host, ".")
|
||||
if !strings.HasSuffix(host, RDSEndpointSuffix) || len(parts) != 6 {
|
||||
return "", "", trace.BadParameter("failed to parse %v as RDS endpoint", endpoint)
|
||||
}
|
||||
return parts[0], parts[2], nil
|
||||
}
|
||||
|
||||
// parseRedshiftEndpoint extracts cluster ID and region from the provided Redshift endpoint.
|
||||
func parseRedshiftEndpoint(endpoint string) (clusterID, region string, err error) {
|
||||
host, _, err := net.SplitHostPort(endpoint)
|
||||
if err != nil {
|
||||
return "", "", trace.Wrap(err)
|
||||
}
|
||||
// Redshift endpoint looks like this:
|
||||
// redshift-cluster-1.abcdefghijklmnop.us-east-1.rds.amazonaws.com
|
||||
parts := strings.Split(host, ".")
|
||||
if !strings.HasSuffix(host, RedshiftEndpointSuffix) || len(parts) != 6 {
|
||||
return "", "", trace.BadParameter("failed to parse %v as Redshift endpoint", endpoint)
|
||||
}
|
||||
return parts[0], parts[2], nil
|
||||
}
|
||||
|
||||
// parseAzureEndpoint extracts database server name from Azure endpoint.
|
||||
func parseAzureEndpoint(endpoint string) (name string, err error) {
|
||||
host, _, err := net.SplitHostPort(endpoint)
|
||||
|
@ -590,10 +561,6 @@ func (d Databases) Less(i, j int) bool { return d[i].GetName() < d[j].GetName()
|
|||
func (d Databases) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
||||
|
||||
const (
|
||||
// RDSEndpointSuffix is the RDS/Aurora endpoint suffix.
|
||||
RDSEndpointSuffix = ".rds.amazonaws.com"
|
||||
// RedshiftEndpointSuffix is the Redshift endpoint suffix.
|
||||
RedshiftEndpointSuffix = ".redshift.amazonaws.com"
|
||||
// AzureEndpointSuffix is the Azure database endpoint suffix.
|
||||
AzureEndpointSuffix = ".database.azure.com"
|
||||
)
|
||||
|
|
157
api/utils/aws/endpoint.go
Normal file
157
api/utils/aws/endpoint.go
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
Copyright 2022 Gravitational, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
// IsAWSEndpoint returns true if the input URI is an AWS endpoint.
|
||||
func IsAWSEndpoint(uri string) bool {
|
||||
// Note that AWSCNEndpointSuffix contains AWSEndpointSuffix so there is no
|
||||
// need to search for AWSCNEndpointSuffix explicitly.
|
||||
return strings.Contains(uri, AWSEndpointSuffix)
|
||||
}
|
||||
|
||||
// IsRDSEndpoint returns true if the input URI is an RDS endpoint.
|
||||
//
|
||||
// https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.Endpoints.html
|
||||
func IsRDSEndpoint(uri string) bool {
|
||||
return strings.Contains(uri, RDSEndpointSubdomain) &&
|
||||
IsAWSEndpoint(uri)
|
||||
}
|
||||
|
||||
// IsRedshiftEndpoint returns true if the input URI is an Redshift endpoint.
|
||||
//
|
||||
// https://docs.aws.amazon.com/redshift/latest/mgmt/connecting-from-psql.html
|
||||
func IsRedshiftEndpoint(uri string) bool {
|
||||
return strings.Contains(uri, RedshiftEndpointSubdomain) &&
|
||||
IsAWSEndpoint(uri)
|
||||
}
|
||||
|
||||
// ParseRDSEndpoint extracts the identifier and region from the provided RDS
|
||||
// endpoint.
|
||||
func ParseRDSEndpoint(endpoint string) (id, region string, err error) {
|
||||
if strings.ContainsRune(endpoint, ':') {
|
||||
endpoint, _, err = net.SplitHostPort(endpoint)
|
||||
if err != nil {
|
||||
return "", "", trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasSuffix(endpoint, AWSCNEndpointSuffix) {
|
||||
return parseRDSCNEndpoint(endpoint)
|
||||
}
|
||||
return parseRDSEndpoint(endpoint)
|
||||
}
|
||||
|
||||
// parseRDSEndpoint extracts the identifier and region from the provided RDS
|
||||
// endpoint for standard regions.
|
||||
//
|
||||
// RDS/Aurora endpoints look like this:
|
||||
// aurora-instance-1.abcdefghijklmnop.us-west-1.rds.amazonaws.com
|
||||
func parseRDSEndpoint(endpoint string) (id, region string, err error) {
|
||||
parts := strings.Split(endpoint, ".")
|
||||
if !strings.HasSuffix(endpoint, AWSEndpointSuffix) || len(parts) != 6 || parts[3] != RDSServiceName {
|
||||
return "", "", trace.BadParameter("failed to parse %v as RDS endpoint", endpoint)
|
||||
}
|
||||
return parts[0], parts[2], nil
|
||||
}
|
||||
|
||||
// parseRDSEndpoint extracts the identifier and region from the provided RDS
|
||||
// endpoint for AWS China regions.
|
||||
//
|
||||
// RDS/Aurora endpoints look like this for AWS China regions:
|
||||
// aurora-instance-2.abcdefghijklmnop.rds.cn-north-1.amazonaws.com.cn
|
||||
func parseRDSCNEndpoint(endpoint string) (id, region string, err error) {
|
||||
parts := strings.Split(endpoint, ".")
|
||||
if !strings.HasSuffix(endpoint, AWSCNEndpointSuffix) || len(parts) != 7 || parts[2] != RDSServiceName {
|
||||
return "", "", trace.BadParameter("failed to parse %v as RDS CN endpoint", endpoint)
|
||||
}
|
||||
return parts[0], parts[3], nil
|
||||
}
|
||||
|
||||
// ParseRedshiftEndpoint extracts cluster ID and region from the provided
|
||||
// Redshift endpoint.
|
||||
func ParseRedshiftEndpoint(endpoint string) (clusterID, region string, err error) {
|
||||
if strings.ContainsRune(endpoint, ':') {
|
||||
endpoint, _, err = net.SplitHostPort(endpoint)
|
||||
if err != nil {
|
||||
return "", "", trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasSuffix(endpoint, AWSCNEndpointSuffix) {
|
||||
return parseRedshiftCNEndpoint(endpoint)
|
||||
}
|
||||
return parseRedshiftEndpoint(endpoint)
|
||||
}
|
||||
|
||||
// parseRedshiftEndpoint extracts cluster ID and region from the provided
|
||||
// Redshift endpoint for standard regions.
|
||||
//
|
||||
// Redshift endpoints look like this:
|
||||
// redshift-cluster-1.abcdefghijklmnop.us-east-1.redshift.amazonaws.com
|
||||
func parseRedshiftEndpoint(endpoint string) (clusterID, region string, err error) {
|
||||
parts := strings.Split(endpoint, ".")
|
||||
if !strings.HasSuffix(endpoint, AWSEndpointSuffix) || len(parts) != 6 || parts[3] != RedshiftServiceName {
|
||||
return "", "", trace.BadParameter("failed to parse %v as Redshift endpoint", endpoint)
|
||||
}
|
||||
return parts[0], parts[2], nil
|
||||
}
|
||||
|
||||
// parseRedshiftCNEndpoint extracts cluster ID and region from the provided
|
||||
// Redshift endpoint for AWS China regions.
|
||||
//
|
||||
// Redshift endpoints look like this for AWS China regions:
|
||||
// redshift-cluster-2.abcdefghijklmnop.redshift.cn-north-1.amazonaws.com.cn
|
||||
func parseRedshiftCNEndpoint(endpoint string) (clusterID, region string, err error) {
|
||||
parts := strings.Split(endpoint, ".")
|
||||
if !strings.HasSuffix(endpoint, AWSCNEndpointSuffix) || len(parts) != 7 || parts[2] != RedshiftServiceName {
|
||||
return "", "", trace.BadParameter("failed to parse %v as Redshift CN endpoint", endpoint)
|
||||
}
|
||||
return parts[0], parts[3], nil
|
||||
}
|
||||
|
||||
const (
|
||||
// AWSEndpointSuffix is the endpoint suffix for AWS Standard and AWS US
|
||||
// GovCloud regions.
|
||||
//
|
||||
// https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints
|
||||
// https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/using-govcloud-endpoints.html
|
||||
AWSEndpointSuffix = ".amazonaws.com"
|
||||
|
||||
// AWSCNEndpointSuffix is the endpoint suffix for AWS China regions.
|
||||
//
|
||||
// https://docs.amazonaws.cn/en_us/aws/latest/userguide/endpoints-arns.html
|
||||
AWSCNEndpointSuffix = ".amazonaws.com.cn"
|
||||
|
||||
// RDSServiceName is the service name for AWS RDS.
|
||||
RDSServiceName = "rds"
|
||||
|
||||
// RedshiftServiceName is the service name for AWS Redshift.
|
||||
RedshiftServiceName = "redshift"
|
||||
|
||||
// RDSEndpointSubdomain is the RDS/Aurora subdomain.
|
||||
RDSEndpointSubdomain = "." + RDSServiceName + "."
|
||||
|
||||
// RedshiftEndpointSubdomain is the Redshift endpoint subdomain.
|
||||
RedshiftEndpointSubdomain = "." + RedshiftServiceName + "."
|
||||
)
|
138
api/utils/aws/endpoint_test.go
Normal file
138
api/utils/aws/endpoint_test.go
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
Copyright 2022 Gravitational, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseRDSEndpoint(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
endpoint string
|
||||
expectIsRDSEndpoint bool
|
||||
expectInstanceID string
|
||||
expectRegion string
|
||||
expectParseErrorIs func(error) bool
|
||||
}{
|
||||
{
|
||||
name: "standard",
|
||||
endpoint: "aurora-instance-1.abcdefghijklmnop.us-west-1.rds.amazonaws.com:5432",
|
||||
expectIsRDSEndpoint: true,
|
||||
expectInstanceID: "aurora-instance-1",
|
||||
expectRegion: "us-west-1",
|
||||
},
|
||||
{
|
||||
name: "cn-north-1",
|
||||
endpoint: "aurora-instance-2.abcdefghijklmnop.rds.cn-north-1.amazonaws.com.cn",
|
||||
expectIsRDSEndpoint: true,
|
||||
expectInstanceID: "aurora-instance-2",
|
||||
expectRegion: "cn-north-1",
|
||||
},
|
||||
{
|
||||
name: "localhost:5432",
|
||||
endpoint: "localhost",
|
||||
expectIsRDSEndpoint: false,
|
||||
expectParseErrorIs: trace.IsBadParameter,
|
||||
},
|
||||
{
|
||||
name: "Redshift endpoint fails",
|
||||
endpoint: "redshift-cluster-1.abcdefghijklmnop.us-east-1.redshift.amazonaws.com",
|
||||
expectIsRDSEndpoint: false,
|
||||
expectParseErrorIs: trace.IsBadParameter,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require.Equal(t, test.expectIsRDSEndpoint, IsRDSEndpoint(test.endpoint))
|
||||
|
||||
instanceID, region, err := ParseRDSEndpoint(test.endpoint)
|
||||
if test.expectParseErrorIs != nil {
|
||||
require.Error(t, err)
|
||||
require.True(t, test.expectParseErrorIs(err))
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.expectInstanceID, instanceID)
|
||||
require.Equal(t, test.expectRegion, region)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRedshiftEndpoint(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
endpoint string
|
||||
expectIsRedshiftEndpoint bool
|
||||
expectClusterID string
|
||||
expectRegion string
|
||||
expectParseErrorIs func(error) bool
|
||||
}{
|
||||
{
|
||||
name: "standard",
|
||||
endpoint: "redshift-cluster-1.abcdefghijklmnop.us-east-1.redshift.amazonaws.com:5432",
|
||||
expectClusterID: "redshift-cluster-1",
|
||||
expectRegion: "us-east-1",
|
||||
expectIsRedshiftEndpoint: true,
|
||||
},
|
||||
{
|
||||
name: "cn-north-1",
|
||||
endpoint: "redshift-cluster-2.abcdefghijklmnop.redshift.cn-north-1.amazonaws.com.cn",
|
||||
expectClusterID: "redshift-cluster-2",
|
||||
expectRegion: "cn-north-1",
|
||||
expectIsRedshiftEndpoint: true,
|
||||
},
|
||||
{
|
||||
name: "localhost:5432",
|
||||
endpoint: "localhost",
|
||||
expectIsRedshiftEndpoint: false,
|
||||
expectParseErrorIs: trace.IsBadParameter,
|
||||
},
|
||||
{
|
||||
name: "RDS endpoint fails",
|
||||
endpoint: "aurora-instance-1.abcdefghijklmnop.us-west-1.rds.amazonaws.com",
|
||||
expectIsRedshiftEndpoint: false,
|
||||
expectParseErrorIs: trace.IsBadParameter,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require.Equal(t, test.expectIsRedshiftEndpoint, IsRedshiftEndpoint(test.endpoint))
|
||||
|
||||
clusterID, region, err := ParseRedshiftEndpoint(test.endpoint)
|
||||
if test.expectParseErrorIs != nil {
|
||||
require.Error(t, err)
|
||||
require.True(t, test.expectParseErrorIs(err))
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.expectClusterID, clusterID)
|
||||
require.Equal(t, test.expectRegion, region)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
37
api/utils/aws/region.go
Normal file
37
api/utils/aws/region.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Copyright 2022 Gravitational, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import "strings"
|
||||
|
||||
// IsCNRegion returns true if the region is an AWS China region.
|
||||
func IsCNRegion(region string) bool {
|
||||
return strings.HasPrefix(region, CNRegionPrefix)
|
||||
}
|
||||
|
||||
// IsUSGovRegion returns true if the region is an AWS US GovCloud region.
|
||||
func IsUSGovRegion(region string) bool {
|
||||
return strings.HasPrefix(region, USGovRegionPrefix)
|
||||
}
|
||||
|
||||
const (
|
||||
// CNRegionPrefix is the prefix for all AWS China regions.
|
||||
CNRegionPrefix = "cn-"
|
||||
|
||||
// USGovRegionPrefix is the prefix for all AWS US GovCloud regions.
|
||||
USGovRegionPrefix = "us-gov-"
|
||||
)
|
|
@ -17,9 +17,9 @@ package databases
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
awsutils "github.com/gravitational/teleport/api/utils/aws"
|
||||
awslib "github.com/gravitational/teleport/lib/cloud/aws"
|
||||
"github.com/gravitational/teleport/lib/config"
|
||||
"github.com/gravitational/trace"
|
||||
|
@ -451,7 +451,7 @@ func hasRedshiftDatabases(flags BootstrapFlags, fileConfig *config.FileConfig) b
|
|||
|
||||
// Check if there is any static Redshift database configured.
|
||||
for _, database := range fileConfig.Databases.Databases {
|
||||
if strings.Contains(database.URI, types.RedshiftEndpointSuffix) {
|
||||
if awsutils.IsRedshiftEndpoint(database.URI) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
apiutils "github.com/gravitational/teleport/api/utils"
|
||||
awsutils "github.com/gravitational/teleport/api/utils/aws"
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
|
@ -180,7 +181,9 @@ func NewDatabasesFromRDSClusterCustomEndpoints(cluster *rds.DBCluster) (types.Da
|
|||
var errors []error
|
||||
var databases types.Databases
|
||||
for _, endpoint := range cluster.CustomEndpoints {
|
||||
endpointName, err := parseRDSCustomEndpoint(aws.StringValue(endpoint))
|
||||
// RDS custom endpoint format:
|
||||
// <endpointName>.cluster-custom-<customerDnsIdentifier>.<dnsSuffix>
|
||||
endpointName, _, err := awsutils.ParseRDSEndpoint(aws.StringValue(endpoint))
|
||||
if err != nil {
|
||||
errors = append(errors, trace.Wrap(err))
|
||||
continue
|
||||
|
@ -297,21 +300,6 @@ func engineToProtocol(engine string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// parseRDSCustomEndpoint endpoint name from the provided RDS custom endpoint.
|
||||
func parseRDSCustomEndpoint(endpoint string) (name string, err error) {
|
||||
// https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.Endpoints.html#Aurora.Endpoints.Custom
|
||||
//
|
||||
// RDS custom endpoint format:
|
||||
// <endpointName>.cluster-custom-<customerDnsIdentifier>.<dnsSuffix>
|
||||
//
|
||||
// Note that endpoint name can only contain letters, numbers, and hyphens, so it's safe to to split on ".".
|
||||
parts := strings.Split(endpoint, ".")
|
||||
if !strings.HasSuffix(endpoint, rdsEndpointSuffix) || len(parts) != 6 {
|
||||
return "", trace.BadParameter("failed to parse %v as RDS custom endpoint", endpoint)
|
||||
}
|
||||
return parts[0], nil
|
||||
}
|
||||
|
||||
// labelsFromRDSInstance creates database labels for the provided RDS instance.
|
||||
func labelsFromRDSInstance(rdsInstance *rds.DBInstance, meta *types.AWS) map[string]string {
|
||||
labels := rdsTagsToLabels(rdsInstance.TagList)
|
||||
|
@ -548,11 +536,6 @@ const (
|
|||
labelEndpointType = "endpoint-type"
|
||||
)
|
||||
|
||||
const (
|
||||
// rdsEndpointSuffix is the RDS/Aurora endpoint suffix.
|
||||
rdsEndpointSuffix = ".rds.amazonaws.com"
|
||||
)
|
||||
|
||||
const (
|
||||
// RDSEngineMySQL is RDS engine name for MySQL instances.
|
||||
RDSEngineMySQL = "mysql"
|
||||
|
|
|
@ -283,12 +283,6 @@ func TestDatabaseFromRDSCluster(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestParseRDSCustomEndpoint(t *testing.T) {
|
||||
name, err := parseRDSCustomEndpoint("custom-endpoint.cluster-custom-example.ca-central-1.rds.amazonaws.com")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "custom-endpoint", name)
|
||||
}
|
||||
|
||||
func TestAuroraMySQLVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
engineVersion string
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
|
||||
"github.com/gravitational/teleport"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
awsutils "github.com/gravitational/teleport/api/utils/aws"
|
||||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
|
@ -195,18 +196,24 @@ func (d *realDownloader) downloadForCloudSQL(ctx context.Context, database types
|
|||
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
|
||||
func rdsCAURLForDatabase(database types.Database) string {
|
||||
region := database.GetAWS().Region
|
||||
if u, ok := rdsGovCloudCAURLs[region]; ok {
|
||||
return u
|
||||
}
|
||||
|
||||
return fmt.Sprintf(rdsDefaultCAURLTemplate, region, region)
|
||||
switch {
|
||||
case awsutils.IsCNRegion(region):
|
||||
return fmt.Sprintf(rdsCNRegionCAURLTemplate, region, region)
|
||||
|
||||
case awsutils.IsUSGovRegion(region):
|
||||
return fmt.Sprintf(rdsUSGovRegionCAURLTemplate, region, region)
|
||||
|
||||
default:
|
||||
return fmt.Sprintf(rdsDefaultCAURLTemplate, region, region)
|
||||
}
|
||||
}
|
||||
|
||||
// redshiftCAURLForDatabase returns root certificate download URL based on the region
|
||||
// of the provided RDS server instance.
|
||||
func redshiftCAURLForDatabase(database types.Database) string {
|
||||
if u, ok := redshiftCAURLs[database.GetAWS().Region]; ok {
|
||||
return u
|
||||
if awsutils.IsCNRegion(database.GetAWS().Region) {
|
||||
return redshiftCNRegionCAURL
|
||||
}
|
||||
return redshiftDefaultCAURL
|
||||
}
|
||||
|
@ -217,10 +224,26 @@ const (
|
|||
//
|
||||
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
|
||||
rdsDefaultCAURLTemplate = "https://truststore.pki.rds.amazonaws.com/%s/%s-bundle.pem"
|
||||
// rdsUSGovRegionCAURLTemplate is the string format template that creates URLs
|
||||
// for region based RDS CA bundles for AWS US GovCloud regions
|
||||
//
|
||||
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
|
||||
rdsUSGovRegionCAURLTemplate = "https://truststore.pki.us-gov-west-1.rds.amazonaws.com/%s/%s-bundle.pem"
|
||||
// rdsCNRegionCAURLTemplate is the string format template that creates URLs
|
||||
// for region based RDS CA bundles for AWS China regions.
|
||||
//
|
||||
// https://docs.amazonaws.cn/en_us/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
|
||||
rdsCNRegionCAURLTemplate = "https://rds-truststore.s3.cn-north-1.amazonaws.com.cn/%s/%s-bundle.pem"
|
||||
// redshiftDefaultCAURL is the Redshift CA bundle download URL.
|
||||
//
|
||||
// https://docs.aws.amazon.com/redshift/latest/mgmt/connecting-ssl-support.html
|
||||
redshiftDefaultCAURL = "https://s3.amazonaws.com/redshift-downloads/amazon-trust-ca-bundle.crt"
|
||||
// redshiftDefaultCAURL is the Redshift CA bundle download URL for AWS
|
||||
// China regions.
|
||||
//
|
||||
// https://docs.amazonaws.cn/redshift/latest/mgmt/connecting-ssl-support.html
|
||||
redshiftCNRegionCAURL = "https://s3.cn-north-1.amazonaws.com.cn/redshift-downloads-cn/amazon-trust-ca-bundle.crt"
|
||||
|
||||
// azureCAURL is the URL of the CA certificate for validating certificates
|
||||
// presented by Azure hosted databases. See:
|
||||
//
|
||||
|
@ -241,18 +264,3 @@ To correct the error you can try the following:
|
|||
* Download root certificate for your Cloud SQL instance %q manually and set
|
||||
it in the database configuration using "ca_cert_file" configuration field.`
|
||||
)
|
||||
|
||||
// rdsGovCloudCAURLs maps AWS regions to URLs of their RDS root certificates.
|
||||
//
|
||||
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
|
||||
var rdsGovCloudCAURLs = map[string]string{
|
||||
"us-gov-east-1": "https://truststore.pki.us-gov-west-1.rds.amazonaws.com/us-gov-east-1/us-gov-east-1-bundle.pem",
|
||||
"us-gov-west-1": "https://truststore.pki.us-gov-west-1.rds.amazonaws.com/us-gov-west-1/us-gov-west-1-bundle.pem",
|
||||
}
|
||||
|
||||
// redshiftCAURLs maps opt-in AWS regions to URLs of their Redshift root certificates.
|
||||
//
|
||||
// https://docs.aws.amazon.com/redshift/latest/mgmt/connecting-ssl-support.html
|
||||
var redshiftCAURLs = map[string]string{
|
||||
"cn-north-1": "https://s3.cn-north-1.amazonaws.com.cn/redshift-downloads-cn/amazon-trust-ca-bundle.crt",
|
||||
}
|
||||
|
|
|
@ -490,10 +490,12 @@ func TestTLSConfiguration(t *testing.T) {
|
|||
|
||||
func TestRDSCAURLForDatabase(t *testing.T) {
|
||||
tests := map[string]string{
|
||||
"us-west-1": "https://truststore.pki.rds.amazonaws.com/us-west-1/us-west-1-bundle.pem",
|
||||
"ca-central-1": "https://truststore.pki.rds.amazonaws.com/ca-central-1/ca-central-1-bundle.pem",
|
||||
"us-gov-east-1": "https://truststore.pki.us-gov-west-1.rds.amazonaws.com/us-gov-east-1/us-gov-east-1-bundle.pem",
|
||||
"us-gov-west-1": "https://truststore.pki.us-gov-west-1.rds.amazonaws.com/us-gov-west-1/us-gov-west-1-bundle.pem",
|
||||
"us-west-1": "https://truststore.pki.rds.amazonaws.com/us-west-1/us-west-1-bundle.pem",
|
||||
"ca-central-1": "https://truststore.pki.rds.amazonaws.com/ca-central-1/ca-central-1-bundle.pem",
|
||||
"us-gov-east-1": "https://truststore.pki.us-gov-west-1.rds.amazonaws.com/us-gov-east-1/us-gov-east-1-bundle.pem",
|
||||
"us-gov-west-1": "https://truststore.pki.us-gov-west-1.rds.amazonaws.com/us-gov-west-1/us-gov-west-1-bundle.pem",
|
||||
"cn-northwest-1": "https://rds-truststore.s3.cn-north-1.amazonaws.com.cn/cn-northwest-1/cn-northwest-1-bundle.pem",
|
||||
"cn-north-1": "https://rds-truststore.s3.cn-north-1.amazonaws.com.cn/cn-north-1/cn-north-1-bundle.pem",
|
||||
}
|
||||
for region, expectURL := range tests {
|
||||
t.Run(region, func(t *testing.T) {
|
||||
|
@ -512,9 +514,10 @@ func TestRDSCAURLForDatabase(t *testing.T) {
|
|||
|
||||
func TestRedshiftCAURLForDatabase(t *testing.T) {
|
||||
tests := map[string]string{
|
||||
"us-west-1": "https://s3.amazonaws.com/redshift-downloads/amazon-trust-ca-bundle.crt",
|
||||
"ca-central-1": "https://s3.amazonaws.com/redshift-downloads/amazon-trust-ca-bundle.crt",
|
||||
"cn-north-1": "https://s3.cn-north-1.amazonaws.com.cn/redshift-downloads-cn/amazon-trust-ca-bundle.crt",
|
||||
"us-west-1": "https://s3.amazonaws.com/redshift-downloads/amazon-trust-ca-bundle.crt",
|
||||
"ca-central-1": "https://s3.amazonaws.com/redshift-downloads/amazon-trust-ca-bundle.crt",
|
||||
"cn-north-1": "https://s3.cn-north-1.amazonaws.com.cn/redshift-downloads-cn/amazon-trust-ca-bundle.crt",
|
||||
"cn-northwest-1": "https://s3.cn-north-1.amazonaws.com.cn/redshift-downloads-cn/amazon-trust-ca-bundle.crt",
|
||||
}
|
||||
for region, expectURL := range tests {
|
||||
t.Run(region, func(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue