do not register Aurora serverless db clusters (#9386)

This commit is contained in:
STeve Huang
2022-01-06 21:30:47 +00:00
committed by GitHub
parent 52395be1f2
commit 1be9e81bf1
4 changed files with 149 additions and 5 deletions
+58
View File
@@ -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"
)
+76
View File
@@ -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))
})
}
}
+8
View File
@@ -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.",
+7 -5
View File
@@ -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),