mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-01 05:27:24 +08:00
do not register Aurora serverless db clusters (#9386)
This commit is contained in:
@@ -19,8 +19,10 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
apiutils "github.com/gravitational/teleport/api/utils"
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
@@ -225,6 +227,49 @@ func tagsToLabels(tags []*rds.Tag) map[string]string {
|
||||
return labels
|
||||
}
|
||||
|
||||
// IsRDSClusterSupported checks whether the aurora cluster is supported and logs
|
||||
// related info if not.
|
||||
func IsRDSClusterSupported(cluster *rds.DBCluster) bool {
|
||||
switch aws.StringValue(cluster.EngineMode) {
|
||||
// Aurora Serverless (v1 and v2) does not support IAM authentication
|
||||
// https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html#aurora-serverless.limitations
|
||||
// https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-2.limitations.html
|
||||
case RDSEngineModeServerless:
|
||||
return false
|
||||
|
||||
// Aurora MySQL 1.22.2, 1.20.1, 1.19.6, and 5.6.10a only: Parallel query doesn't support AWS Identity and Access Management (IAM) database authentication.
|
||||
// https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-mysql-parallel-query.html#aurora-mysql-parallel-query-limitations
|
||||
case RDSEngineModeParallelQuery:
|
||||
if apiutils.SliceContainsStr([]string{"1.22.2", "1.20.1", "1.19.6", "5.6.10a"}, auroraMySQLVersion(cluster)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// auroraMySQLVersion extracts aurora mysql version from engine version
|
||||
func auroraMySQLVersion(cluster *rds.DBCluster) string {
|
||||
// version guide: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.Versions.html
|
||||
// a list of all the available versions: https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-engine-versions.html
|
||||
//
|
||||
// some examples of possible inputs:
|
||||
// 5.6.10a
|
||||
// 5.7.12
|
||||
// 5.6.mysql_aurora.1.22.0
|
||||
// 5.6.mysql_aurora.1.22.1
|
||||
// 5.6.mysql_aurora.1.22.1.3
|
||||
//
|
||||
// general format is: <mysql-major-version>.mysql_aurora.<aurora-mysql-version>
|
||||
// 5.6.10a and 5.7.12 are "legacy" versions and they are returned as it is
|
||||
version := aws.StringValue(cluster.EngineVersion)
|
||||
parts := strings.Split(version, ".mysql_aurora.")
|
||||
if len(parts) == 2 {
|
||||
return parts[1]
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
const (
|
||||
// labelAccountID is the label key containing AWS account ID.
|
||||
labelAccountID = "account-id"
|
||||
@@ -248,3 +293,16 @@ const (
|
||||
// RDSEngineAuroraPostgres is RDS engine name for Aurora Postgres clusters.
|
||||
RDSEngineAuroraPostgres = "aurora-postgresql"
|
||||
)
|
||||
|
||||
const (
|
||||
// RDSEngineModeProvisioned is the RDS engine mode for provisioned Aurora clusters
|
||||
RDSEngineModeProvisioned = "provisioned"
|
||||
// RDSEngineModeServerless is the RDS engine mode for Aurora Serverless DB clusters
|
||||
RDSEngineModeServerless = "serverless"
|
||||
// RDSEngineModeParallelQuery is the RDS engine mode for Aurora MySQL clusters with parallel query enabled
|
||||
RDSEngineModeParallelQuery = "parallelquery"
|
||||
// RDSEngineModeGlobal is the RDS engine mode for Aurora Global databases
|
||||
RDSEngineModeGlobal = "global"
|
||||
// RDSEngineModeMultiMaster is the RDS engine mode for Multi-master clusters
|
||||
RDSEngineModeMultiMaster = "multimaster"
|
||||
)
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/fixtures"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
"github.com/pborman/uuid"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/rds"
|
||||
@@ -189,3 +190,78 @@ func TestDatabaseFromRDSCluster(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestAuroraMySQLVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
engineVersion string
|
||||
expectedMySQLVersion string
|
||||
}{
|
||||
{
|
||||
engineVersion: "5.6.10a",
|
||||
expectedMySQLVersion: "5.6.10a",
|
||||
},
|
||||
{
|
||||
engineVersion: "5.6.mysql_aurora.1.22.1",
|
||||
expectedMySQLVersion: "1.22.1",
|
||||
},
|
||||
{
|
||||
engineVersion: "5.6.mysql_aurora.1.22.1.3",
|
||||
expectedMySQLVersion: "1.22.1.3",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.engineVersion, func(t *testing.T) {
|
||||
require.Equal(t, test.expectedMySQLVersion, auroraMySQLVersion(&rds.DBCluster{EngineVersion: aws.String(test.engineVersion)}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsRDSClusterSupported(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
engineMode string
|
||||
engineVersion string
|
||||
isSupported bool
|
||||
}{
|
||||
{
|
||||
name: "provisioned",
|
||||
engineMode: RDSEngineModeProvisioned,
|
||||
engineVersion: "5.6.mysql_aurora.1.22.0",
|
||||
isSupported: true,
|
||||
},
|
||||
{
|
||||
name: "serverless",
|
||||
engineMode: RDSEngineModeServerless,
|
||||
engineVersion: "5.6.mysql_aurora.1.22.0",
|
||||
isSupported: false,
|
||||
},
|
||||
{
|
||||
name: "parallel query supported",
|
||||
engineMode: RDSEngineModeParallelQuery,
|
||||
engineVersion: "5.6.mysql_aurora.1.22.0",
|
||||
isSupported: true,
|
||||
},
|
||||
{
|
||||
name: "parallel query unsupported",
|
||||
engineMode: RDSEngineModeParallelQuery,
|
||||
engineVersion: "5.6.mysql_aurora.1.19.6",
|
||||
isSupported: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
cluster := &rds.DBCluster{
|
||||
DBClusterArn: aws.String("arn:aws:rds:us-east-1:1234567890:cluster:test"),
|
||||
DBClusterIdentifier: aws.String(test.name),
|
||||
DbClusterResourceId: aws.String(uuid.New()),
|
||||
Engine: aws.String(RDSEngineAuroraMySQL),
|
||||
EngineMode: aws.String(test.engineMode),
|
||||
EngineVersion: aws.String(test.engineVersion),
|
||||
}
|
||||
|
||||
require.Equal(t, test.isSupported, IsRDSClusterSupported(cluster))
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +142,14 @@ func (f *rdsFetcher) getAuroraDatabases(ctx context.Context) (types.Databases, e
|
||||
}
|
||||
databases := make(types.Databases, 0, len(clusters))
|
||||
for _, cluster := range clusters {
|
||||
if !services.IsRDSClusterSupported(cluster) {
|
||||
f.log.Debugf("Aurora cluster %q (engine mode %v, engine version %v) doesn't support IAM authentication. Skipping.",
|
||||
aws.StringValue(cluster.DBClusterIdentifier),
|
||||
aws.StringValue(cluster.EngineMode),
|
||||
aws.StringValue(cluster.EngineVersion))
|
||||
continue
|
||||
}
|
||||
|
||||
database, err := services.NewDatabaseFromRDSCluster(cluster)
|
||||
if err != nil {
|
||||
f.log.Infof("Could not convert RDS cluster %q to database resource: %v.",
|
||||
|
||||
@@ -43,9 +43,10 @@ func TestWatcher(t *testing.T) {
|
||||
rdsInstance2, _ := makeRDSInstance(t, "instance-2", "us-east-2", map[string]string{"env": "prod"})
|
||||
rdsInstance3, _ := makeRDSInstance(t, "instance-3", "us-east-1", map[string]string{"env": "dev"})
|
||||
|
||||
auroraCluster1, auroraDatabase1 := makeRDSCluster(t, "cluster-1", "us-east-1", map[string]string{"env": "prod"})
|
||||
auroraCluster2, auroraDatabase2 := makeRDSCluster(t, "cluster-2", "us-east-2", map[string]string{"env": "dev"})
|
||||
auroraCluster3, _ := makeRDSCluster(t, "cluster-3", "us-east-2", map[string]string{"env": "prod"})
|
||||
auroraCluster1, auroraDatabase1 := makeRDSCluster(t, "cluster-1", "us-east-1", services.RDSEngineModeProvisioned, map[string]string{"env": "prod"})
|
||||
auroraCluster2, auroraDatabase2 := makeRDSCluster(t, "cluster-2", "us-east-2", services.RDSEngineModeProvisioned, map[string]string{"env": "dev"})
|
||||
auroraCluster3, _ := makeRDSCluster(t, "cluster-3", "us-east-2", services.RDSEngineModeProvisioned, map[string]string{"env": "prod"})
|
||||
auroraClusterUnsupported, _ := makeRDSCluster(t, "serverless", "us-east-1", services.RDSEngineModeServerless, map[string]string{"env": "prod"})
|
||||
|
||||
watcher, err := NewWatcher(ctx, WatcherConfig{
|
||||
AWSMatchers: []services.AWSMatcher{
|
||||
@@ -64,7 +65,7 @@ func TestWatcher(t *testing.T) {
|
||||
RDSPerRegion: map[string]rdsiface.RDSAPI{
|
||||
"us-east-1": &cloud.RDSMock{
|
||||
DBInstances: []*rds.DBInstance{rdsInstance1, rdsInstance3},
|
||||
DBClusters: []*rds.DBCluster{auroraCluster1},
|
||||
DBClusters: []*rds.DBCluster{auroraCluster1, auroraClusterUnsupported},
|
||||
},
|
||||
"us-east-2": &cloud.RDSMock{
|
||||
DBInstances: []*rds.DBInstance{rdsInstance2},
|
||||
@@ -102,12 +103,13 @@ func makeRDSInstance(t *testing.T, name, region string, labels map[string]string
|
||||
return instance, database
|
||||
}
|
||||
|
||||
func makeRDSCluster(t *testing.T, name, region string, labels map[string]string) (*rds.DBCluster, types.Database) {
|
||||
func makeRDSCluster(t *testing.T, name, region, engineMode string, labels map[string]string) (*rds.DBCluster, types.Database) {
|
||||
cluster := &rds.DBCluster{
|
||||
DBClusterArn: aws.String(fmt.Sprintf("arn:aws:rds:%v:1234567890:cluster:%v", region, name)),
|
||||
DBClusterIdentifier: aws.String(name),
|
||||
DbClusterResourceId: aws.String(uuid.New()),
|
||||
Engine: aws.String(services.RDSEngineAuroraMySQL),
|
||||
EngineMode: aws.String(engineMode),
|
||||
Endpoint: aws.String("localhost"),
|
||||
Port: aws.Int64(3306),
|
||||
TagList: labelsToTags(labels),
|
||||
|
||||
Reference in New Issue
Block a user