From 44209ce8dc8f0cfedf37536235a8dcfee62b0dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Andr=C3=A9=20Dinis?= Date: Wed, 4 Oct 2023 14:48:09 +0100 Subject: [PATCH] DiscoveryMatchers: move checkandset to types package (#32857) * DiscoveryMatchers: move checkandset to types package * add opensearch to iamrole as users --- api/types/constants.go | 10 + api/types/installers/installers.go | 4 +- api/types/matchers_aws.go | 155 ++++- api/types/matchers_aws_test.go | 243 ++++++++ api/types/matchers_azure.go | 90 ++- api/types/matchers_azure_test.go | 129 ++++ api/types/matchers_gcp.go | 86 ++- api/types/matchers_gcp_test.go | 160 +++++ api/types/matchers_kube.go | 40 +- api/types/matchers_kube_test.go | 88 +++ api/utils/aws/identifiers.go | 40 ++ api/utils/aws/identifiers_test.go | 67 ++ e2e/aws/eks_test.go | 2 +- e2e/aws/rds_test.go | 4 +- lib/config/configuration.go | 121 ++-- lib/config/configuration_test.go | 555 ++++++++++++++++- lib/config/fileconf.go | 314 +--------- lib/config/fileconf_test.go | 576 ------------------ lib/configurators/aws/aws.go | 36 +- lib/configurators/aws/aws_test.go | 144 ++--- lib/defaults/defaults.go | 24 - lib/services/matchers.go | 100 --- lib/srv/db/watcher_test.go | 8 +- lib/srv/discovery/common/renaming.go | 11 +- lib/srv/discovery/common/renaming_test.go | 10 +- lib/srv/discovery/discovery.go | 14 +- lib/srv/discovery/discovery_test.go | 20 +- .../fetchers/db/aws_elasticache_test.go | 12 +- .../fetchers/db/aws_memorydb_test.go | 10 +- .../fetchers/db/aws_opensearch_test.go | 14 +- .../fetchers/db/aws_rds_proxy_test.go | 8 +- lib/srv/discovery/fetchers/db/aws_rds_test.go | 24 +- .../db/aws_redshift_serverless_test.go | 10 +- .../fetchers/db/aws_redshift_test.go | 8 +- .../discovery/fetchers/db/azure_dbserver.go | 4 +- .../fetchers/db/azure_dbserver_test.go | 16 +- .../fetchers/db/azure_mysql_flex_test.go | 4 +- .../fetchers/db/azure_postgres_flex_test.go | 4 +- .../discovery/fetchers/db/azure_redis_test.go | 6 +- lib/srv/discovery/fetchers/db/db.go | 22 +- lib/srv/discovery/fetchers/kube_services.go | 2 +- lib/srv/server/ec2_watcher.go | 3 +- lib/utils/aws/aws.go | 4 +- 43 files changed, 1924 insertions(+), 1278 deletions(-) create mode 100644 api/types/matchers_aws_test.go create mode 100644 api/types/matchers_azure_test.go create mode 100644 api/types/matchers_gcp_test.go create mode 100644 api/types/matchers_kube_test.go diff --git a/api/types/constants.go b/api/types/constants.go index f99240598a0..198569f9807 100644 --- a/api/types/constants.go +++ b/api/types/constants.go @@ -1116,3 +1116,13 @@ const ( // JWTClaimsRewriteNone include neither traits nor roles in the JWT token. JWTClaimsRewriteNone = "none" ) + +const ( + // DefaultInstallerScriptName is the name of the by default populated, EC2 + // installer script + DefaultInstallerScriptName = "default-installer" + + // DefaultInstallerScriptNameAgentless is the name of the by default populated, EC2 + // installer script when agentless mode is enabled for a matcher + DefaultInstallerScriptNameAgentless = "default-agentless-installer" +) diff --git a/api/types/installers/installers.go b/api/types/installers/installers.go index c98f16ca3d8..fcd6e024574 100644 --- a/api/types/installers/installers.go +++ b/api/types/installers/installers.go @@ -30,11 +30,11 @@ var defaultAgentlessInstallScript string // InstallerScriptName is the name of the by default populated, EC2 // installer script -const InstallerScriptName = "default-installer" +const InstallerScriptName = types.DefaultInstallerScriptName // InstallerScriptName is the name of the by default populated, EC2 // installer script when agentless mode is enabled for a matcher -const InstallerScriptNameAgentless = "default-agentless-installer" +const InstallerScriptNameAgentless = types.DefaultInstallerScriptNameAgentless // DefaultInstaller represents a the default installer script provided // by teleport diff --git a/api/types/matchers_aws.go b/api/types/matchers_aws.go index 1f58dc9f1a3..d2d23e9496b 100644 --- a/api/types/matchers_aws.go +++ b/api/types/matchers_aws.go @@ -16,6 +16,80 @@ limitations under the License. package types +import ( + "github.com/gravitational/trace" + "golang.org/x/exp/slices" + + apiutils "github.com/gravitational/teleport/api/utils" + awsapiutils "github.com/gravitational/teleport/api/utils/aws" +) + +const ( + // IAMInviteTokenName is the name of the default Teleport IAM + // token to use when templating the script to be executed. + IAMInviteTokenName = "aws-discovery-iam-token" + + // SSHDConfigPath is the path to the sshd config file to modify + // when using the agentless installer + SSHDConfigPath = "/etc/ssh/sshd_config" + + // AWSInstallerDocument is the name of the default AWS document + // that will be called when executing the SSM command. + AWSInstallerDocument = "TeleportDiscoveryInstaller" + + // AWSAgentlessInstallerDocument is the name of the default AWS document + // that will be called when executing the SSM command . + AWSAgentlessInstallerDocument = "TeleportAgentlessDiscoveryInstaller" + + // AWSMatcherEC2 is the AWS matcher type for EC2 instances. + AWSMatcherEC2 = "ec2" + // AWSMatcherEKS is the AWS matcher type for AWS Kubernetes. + AWSMatcherEKS = "eks" + // AWSMatcherRDS is the AWS matcher type for RDS databases. + AWSMatcherRDS = "rds" + // AWSMatcherRDSProxy is the AWS matcher type for RDS Proxy databases. + AWSMatcherRDSProxy = "rdsproxy" + // AWSMatcherRedshift is the AWS matcher type for Redshift databases. + AWSMatcherRedshift = "redshift" + // AWSMatcherRedshiftServerless is the AWS matcher type for Redshift Serverless databases. + AWSMatcherRedshiftServerless = "redshift-serverless" + // AWSMatcherElastiCache is the AWS matcher type for ElastiCache databases. + AWSMatcherElastiCache = "elasticache" + // AWSMatcherMemoryDB is the AWS matcher type for MemoryDB databases. + AWSMatcherMemoryDB = "memorydb" + // AWSMatcherOpenSearch is the AWS matcher type for OpenSearch databases. + AWSMatcherOpenSearch = "opensearch" +) + +// SupportedAWSMatchers is list of AWS services currently supported by the +// Teleport discovery service. +var SupportedAWSMatchers = append([]string{ + AWSMatcherEC2, + AWSMatcherEKS, +}, SupportedAWSDatabaseMatchers...) + +// SupportedAWSDatabaseMatchers is a list of the AWS databases currently +// supported by the Teleport discovery service. +var SupportedAWSDatabaseMatchers = []string{ + AWSMatcherRDS, + AWSMatcherRDSProxy, + AWSMatcherRedshift, + AWSMatcherRedshiftServerless, + AWSMatcherElastiCache, + AWSMatcherMemoryDB, + AWSMatcherOpenSearch, +} + +// RequireAWSIAMRolesAsUsersMatchers is a list of the AWS databases that +// require AWS IAM roles as database users. +// IMPORTANT: if you add database matchers for AWS keyspaces, OpenSearch, or +// DynamoDB discovery, add them here and in RequireAWSIAMRolesAsUsers in +// api/types. +var RequireAWSIAMRolesAsUsersMatchers = []string{ + AWSMatcherRedshiftServerless, + AWSMatcherOpenSearch, +} + // GetTypes gets the types that the matcher can match. func (m AWSMatcher) GetTypes() []string { return m.Types @@ -29,7 +103,84 @@ func (m AWSMatcher) CopyWithTypes(t []string) Matcher { } // CheckAndSetDefaults that the matcher is correct and adds default values. -func (m AWSMatcher) CheckAndSetDefaults() error { - // TODO(marco): implement +func (m *AWSMatcher) CheckAndSetDefaults() error { + for _, matcherType := range m.Types { + if !slices.Contains(SupportedAWSMatchers, matcherType) { + return trace.BadParameter("discovery service type does not support %q, supported resource types are: %v", + matcherType, SupportedAWSMatchers) + } + } + + if len(m.Types) == 0 { + return trace.BadParameter("discovery service requires at least one type") + } + + if len(m.Regions) == 0 { + return trace.BadParameter("discovery service requires at least one region") + } + + for _, region := range m.Regions { + if err := awsapiutils.IsValidRegion(region); err != nil { + return trace.BadParameter("discovery service does not support region %q", region) + } + } + + if m.AssumeRole != nil { + if m.AssumeRole.RoleARN != "" { + if err := awsapiutils.CheckRoleARN(m.AssumeRole.RoleARN); err != nil { + return trace.BadParameter("invalid assume role: %v", err) + } + } else if m.AssumeRole.ExternalID != "" { + for _, t := range m.Types { + if !slices.Contains(RequireAWSIAMRolesAsUsersMatchers, t) { + return trace.BadParameter("discovery service AWS matcher assume_role_arn is empty, but has external_id %q", + m.AssumeRole.ExternalID) + } + } + } + } + + if m.Tags == nil || len(m.Tags) == 0 { + m.Tags = map[string]apiutils.Strings{Wildcard: {Wildcard}} + } + + if m.Params == nil { + m.Params = &InstallerParams{ + InstallTeleport: true, + } + } + + switch m.Params.JoinMethod { + case JoinMethodIAM, "": + m.Params.JoinMethod = JoinMethodIAM + default: + return trace.BadParameter("only IAM joining is supported for EC2 auto-discovery") + } + + if m.Params.JoinToken == "" { + m.Params.JoinToken = IAMInviteTokenName + } + + if m.Params.SSHDConfig == "" { + m.Params.SSHDConfig = SSHDConfigPath + } + + if m.Params.ScriptName == "" { + m.Params.ScriptName = DefaultInstallerScriptNameAgentless + if m.Params.InstallTeleport { + m.Params.ScriptName = DefaultInstallerScriptName + } + } + + if m.SSM == nil { + m.SSM = &AWSSSM{} + } + + if m.SSM.DocumentName == "" { + m.SSM.DocumentName = AWSAgentlessInstallerDocument + if m.Params.InstallTeleport { + m.SSM.DocumentName = AWSInstallerDocument + } + } return nil } diff --git a/api/types/matchers_aws_test.go b/api/types/matchers_aws_test.go new file mode 100644 index 00000000000..3eb527c5182 --- /dev/null +++ b/api/types/matchers_aws_test.go @@ -0,0 +1,243 @@ +// Copyright 2023 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 types + +import ( + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" +) + +func TestAWSMatcherCheckAndSetDefaults(t *testing.T) { + isBadParameterErr := func(tt require.TestingT, err error, i ...any) { + require.True(tt, trace.IsBadParameter(err), "expected bad parameter, got %v", err) + } + + for _, tt := range []struct { + name string + in *AWSMatcher + errCheck require.ErrorAssertionFunc + expected *AWSMatcher + }{ + { + name: "valid", + in: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + Tags: Labels{ + "*": []string{"*"}, + }, + Params: &InstallerParams{ + JoinMethod: JoinMethodIAM, + JoinToken: IAMInviteTokenName, + InstallTeleport: true, + ScriptName: DefaultInstallerScriptName, + SSHDConfig: SSHDConfigPath, + }, + SSM: &AWSSSM{DocumentName: AWSInstallerDocument}, + AssumeRole: &AssumeRole{ + RoleARN: "arn:aws:iam:us-west-2:123456789012:role/MyRole001", + }, + }, + errCheck: require.NoError, + expected: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + Tags: Labels{ + "*": []string{"*"}, + }, + Params: &InstallerParams{ + JoinMethod: "iam", + JoinToken: "aws-discovery-iam-token", + InstallTeleport: true, + ScriptName: "default-installer", + SSHDConfig: "/etc/ssh/sshd_config", + }, + SSM: &AWSSSM{DocumentName: "TeleportDiscoveryInstaller"}, + AssumeRole: &AssumeRole{ + RoleARN: "arn:aws:iam:us-west-2:123456789012:role/MyRole001", + }, + }, + }, + { + name: "default values", + in: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + }, + errCheck: require.NoError, + expected: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + Tags: Labels{ + "*": []string{"*"}, + }, + Params: &InstallerParams{ + JoinMethod: "iam", + JoinToken: "aws-discovery-iam-token", + InstallTeleport: true, + ScriptName: "default-installer", + SSHDConfig: "/etc/ssh/sshd_config", + }, + SSM: &AWSSSM{DocumentName: "TeleportDiscoveryInstaller"}, + }, + }, + { + name: "default values for agentless mode", + in: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + Params: &InstallerParams{ + InstallTeleport: false, + }, + }, + errCheck: require.NoError, + expected: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + Tags: Labels{ + "*": []string{"*"}, + }, + Params: &InstallerParams{ + JoinMethod: "iam", + JoinToken: "aws-discovery-iam-token", + InstallTeleport: false, + ScriptName: "default-agentless-installer", + SSHDConfig: "/etc/ssh/sshd_config", + }, + SSM: &AWSSSM{DocumentName: "TeleportAgentlessDiscoveryInstaller"}, + }, + }, + { + name: "wildcard is invalid for types", + in: &AWSMatcher{ + Types: []string{"*"}, + Regions: []string{"eu-west-2"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "wildcard is invalid for regions", + in: &AWSMatcher{ + Types: []string{"ec2", "rds"}, + Regions: []string{"*"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid type", + in: &AWSMatcher{ + Types: []string{"ec2", "rds", "xpto"}, + Regions: []string{"eu-west-2"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid region", + in: &AWSMatcher{ + Types: []string{"ec2", "rds", "xpto"}, + Regions: []string{"pt-nope-4"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid join method", + in: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + Params: &InstallerParams{ + JoinMethod: "ec2", + }, + }, + errCheck: isBadParameterErr, + }, + { + name: "no type", + in: &AWSMatcher{ + Types: []string{}, + Regions: []string{"eu-west-2"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "no region", + in: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid assume role arn", + in: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + AssumeRole: &AssumeRole{ + RoleARN: "arn:aws:not valid", + }, + }, + errCheck: isBadParameterErr, + }, + { + name: "external id was set but assume role is missing", + in: &AWSMatcher{ + Types: []string{"ec2"}, + Regions: []string{"eu-west-2"}, + AssumeRole: &AssumeRole{ + ExternalID: "id123", + }, + }, + errCheck: isBadParameterErr, + }, + { + name: "external id was set, assume role is missing but type allows it", + in: &AWSMatcher{ + Types: []string{"redshift-serverless"}, + Regions: []string{"eu-west-2"}, + AssumeRole: &AssumeRole{ + ExternalID: "id123", + }, + }, + errCheck: require.NoError, + expected: &AWSMatcher{ + Types: []string{"redshift-serverless"}, + Regions: []string{"eu-west-2"}, + Tags: Labels{ + "*": []string{"*"}, + }, + Params: &InstallerParams{ + JoinMethod: "iam", + JoinToken: "aws-discovery-iam-token", + InstallTeleport: true, + ScriptName: "default-installer", + SSHDConfig: "/etc/ssh/sshd_config", + }, + AssumeRole: &AssumeRole{ + ExternalID: "id123", + }, + SSM: &AWSSSM{DocumentName: "TeleportDiscoveryInstaller"}, + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + err := tt.in.CheckAndSetDefaults() + tt.errCheck(t, err) + if tt.expected != nil { + require.Equal(t, tt.expected, tt.in) + } + }) + } +} diff --git a/api/types/matchers_azure.go b/api/types/matchers_azure.go index e7ce23351aa..739dfd91a78 100644 --- a/api/types/matchers_azure.go +++ b/api/types/matchers_azure.go @@ -16,6 +16,43 @@ limitations under the License. package types +import ( + "github.com/gravitational/trace" + "golang.org/x/exp/slices" + + apiutils "github.com/gravitational/teleport/api/utils" +) + +const ( + // AzureInviteTokenName is the name of the default token to use + // when templating the script to be executed on Azure. + AzureInviteTokenName = "azure-discovery-token" + + // AzureMatcherVM is the Azure matcher type for Azure VMs. + AzureMatcherVM = "vm" + // AzureMatcherKubernetes is the Azure matcher type for Azure Kubernetes. + AzureMatcherKubernetes = "aks" + // AzureMatcherMySQL is the Azure matcher type for Azure MySQL databases. + AzureMatcherMySQL = "mysql" + // AzureMatcherPostgres is the Azure matcher type for Azure Postgres databases. + AzureMatcherPostgres = "postgres" + // AzureMatcherRedis is the Azure matcher type for Azure Cache for Redis databases. + AzureMatcherRedis = "redis" + // AzureMatcherSQLServer is the Azure matcher type for SQL Server databases. + AzureMatcherSQLServer = "sqlserver" +) + +// SupportedAzureMatchers is list of Azure services currently supported by the +// Teleport discovery service. +var SupportedAzureMatchers = []string{ + AzureMatcherVM, + AzureMatcherKubernetes, + AzureMatcherMySQL, + AzureMatcherPostgres, + AzureMatcherRedis, + AzureMatcherSQLServer, +} + // GetTypes gets the types that the matcher can match. func (m AzureMatcher) GetTypes() []string { return m.Types @@ -29,7 +66,56 @@ func (m AzureMatcher) CopyWithTypes(t []string) Matcher { } // CheckAndSetDefaults that the matcher is correct and adds default values. -func (m AzureMatcher) CheckAndSetDefaults() error { - // TODO(marco): implement +func (m *AzureMatcher) CheckAndSetDefaults() error { + if len(m.Types) == 0 { + return trace.BadParameter("At least one Azure discovery service type must be specified, the supported resource types are: %v", + SupportedAzureMatchers) + } + + for _, matcherType := range m.Types { + if !slices.Contains(SupportedAzureMatchers, matcherType) { + return trace.BadParameter("Azure discovery service type does not support %q resource type; supported resource types are: %v", + matcherType, SupportedAzureMatchers) + } + } + + if slices.Contains(m.Types, AzureMatcherVM) { + if m.Params == nil { + m.Params = &InstallerParams{} + } + + switch m.Params.JoinMethod { + case JoinMethodAzure, "": + m.Params.JoinMethod = JoinMethodAzure + default: + return trace.BadParameter("only Azure joining is supported for Azure auto-discovery") + } + + if m.Params.JoinToken == "" { + m.Params.JoinToken = AzureInviteTokenName + } + + if m.Params.ScriptName == "" { + m.Params.ScriptName = DefaultInstallerScriptName + } + } + + if slices.Contains(m.Regions, Wildcard) || len(m.Regions) == 0 { + m.Regions = []string{Wildcard} + } + + if slices.Contains(m.Subscriptions, Wildcard) || len(m.Subscriptions) == 0 { + m.Subscriptions = []string{Wildcard} + } + + if slices.Contains(m.ResourceGroups, Wildcard) || len(m.ResourceGroups) == 0 { + m.ResourceGroups = []string{Wildcard} + } + + if len(m.ResourceTags) == 0 { + m.ResourceTags = map[string]apiutils.Strings{ + Wildcard: {Wildcard}, + } + } return nil } diff --git a/api/types/matchers_azure_test.go b/api/types/matchers_azure_test.go new file mode 100644 index 00000000000..32f34e94ae1 --- /dev/null +++ b/api/types/matchers_azure_test.go @@ -0,0 +1,129 @@ +// Copyright 2023 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 types + +import ( + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" +) + +func TestAzureMatcherCheckAndSetDefaults(t *testing.T) { + isBadParameterErr := func(tt require.TestingT, err error, i ...any) { + require.True(tt, trace.IsBadParameter(err), "expected bad parameter, got %v", err) + } + + for _, tt := range []struct { + name string + in *AzureMatcher + errCheck require.ErrorAssertionFunc + expected *AzureMatcher + }{ + { + name: "valid", + in: &AzureMatcher{ + Types: []string{"vm"}, + Regions: []string{"westeurope"}, + Subscriptions: []string{"s1", "s2"}, + ResourceGroups: []string{"rg1"}, + ResourceTags: Labels{ + "x": []string{"y"}, + }, + Params: &InstallerParams{ + JoinMethod: JoinMethodAzure, + JoinToken: AzureInviteTokenName, + ScriptName: DefaultInstallerScriptName, + }, + }, + errCheck: require.NoError, + expected: &AzureMatcher{ + Types: []string{"vm"}, + Regions: []string{"westeurope"}, + Subscriptions: []string{"s1", "s2"}, + ResourceGroups: []string{"rg1"}, + ResourceTags: Labels{ + "x": []string{"y"}, + }, + Params: &InstallerParams{ + JoinMethod: "azure", + JoinToken: "azure-discovery-token", + ScriptName: "default-installer", + }, + }, + }, + { + name: "default values", + in: &AzureMatcher{ + Types: []string{"vm"}, + }, + errCheck: require.NoError, + expected: &AzureMatcher{ + Types: []string{"vm"}, + Regions: []string{"*"}, + Subscriptions: []string{"*"}, + ResourceGroups: []string{"*"}, + ResourceTags: Labels{ + "*": []string{"*"}, + }, + Params: &InstallerParams{ + JoinMethod: "azure", + JoinToken: "azure-discovery-token", + ScriptName: "default-installer", + }, + }, + }, + { + name: "wildcard is invalid for types", + in: &AzureMatcher{ + Types: []string{"*"}, + Regions: []string{"eu-west-2"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid type", + in: &AzureMatcher{ + Types: []string{"ec2"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "no type", + in: &AzureMatcher{ + Types: []string{}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid join method", + in: &AzureMatcher{ + Types: []string{"vm"}, + Params: &InstallerParams{ + JoinMethod: "invalid", + }, + }, + errCheck: isBadParameterErr, + }, + } { + t.Run(tt.name, func(t *testing.T) { + err := tt.in.CheckAndSetDefaults() + tt.errCheck(t, err) + if tt.expected != nil { + require.Equal(t, tt.expected, tt.in) + } + }) + } +} diff --git a/api/types/matchers_gcp.go b/api/types/matchers_gcp.go index e390b8ad95f..095aef93864 100644 --- a/api/types/matchers_gcp.go +++ b/api/types/matchers_gcp.go @@ -16,6 +16,31 @@ limitations under the License. package types +import ( + "github.com/gravitational/trace" + "golang.org/x/exp/slices" + + apiutils "github.com/gravitational/teleport/api/utils" +) + +const ( + // GCPInviteTokenName is the name of the default token to use + // when templating the script to be executed on GCP. + GCPInviteTokenName = "gcp-discovery-token" + + // GCPMatcherKubernetes is the GCP matcher type for GCP kubernetes. + GCPMatcherKubernetes = "gke" + // GCPMatcherCompute is the GCP matcher for GCP VMs. + GCPMatcherCompute = "gce" +) + +// SupportedGCPMatchers is list of GCP services currently supported by the +// Teleport discovery service. +var SupportedGCPMatchers = []string{ + GCPMatcherKubernetes, + GCPMatcherCompute, +} + // GetTypes gets the types that the matcher can match. func (m GCPMatcher) GetTypes() []string { return m.Types @@ -38,7 +63,64 @@ func (m GCPMatcher) GetLabels() Labels { } // CheckAndSetDefaults that the matcher is correct and adds default values. -func (m GCPMatcher) CheckAndSetDefaults() error { - // TODO(marco): implement +func (m *GCPMatcher) CheckAndSetDefaults() error { + if len(m.Types) == 0 { + return trace.BadParameter("At least one GCP discovery service type must be specified, the supported resource types are: %v", + SupportedGCPMatchers) + } + + for _, matcherType := range m.Types { + if !slices.Contains(SupportedGCPMatchers, matcherType) { + return trace.BadParameter("GCP discovery service type does not support %q resource type; supported resource types are: %v", + matcherType, SupportedGCPMatchers) + } + } + + if slices.Contains(m.Types, GCPMatcherCompute) { + if m.Params == nil { + m.Params = &InstallerParams{} + } + + switch m.Params.JoinMethod { + case JoinMethodGCP, "": + m.Params.JoinMethod = JoinMethodGCP + default: + return trace.BadParameter("only GCP joining is supported for GCP auto-discovery") + } + + if m.Params.JoinToken == "" { + m.Params.JoinToken = GCPInviteTokenName + } + + if m.Params.ScriptName == "" { + m.Params.ScriptName = DefaultInstallerScriptName + } + } + + if slices.Contains(m.Locations, Wildcard) || len(m.Locations) == 0 { + m.Locations = []string{Wildcard} + } + + if slices.Contains(m.ProjectIDs, Wildcard) { + return trace.BadParameter("GCP discovery service project_ids does not support wildcards; please specify at least one value in project_ids.") + } + if len(m.ProjectIDs) == 0 { + return trace.BadParameter("GCP discovery service project_ids does cannot be empty; please specify at least one value in project_ids.") + } + + if len(m.Labels) > 0 && len(m.Tags) > 0 { + return trace.BadParameter("labels and tags should not both be set.") + } + + if len(m.Tags) > 0 { + m.Labels = m.Tags + } + + if len(m.Labels) == 0 { + m.Labels = map[string]apiutils.Strings{ + Wildcard: {Wildcard}, + } + } + return nil } diff --git a/api/types/matchers_gcp_test.go b/api/types/matchers_gcp_test.go new file mode 100644 index 00000000000..46eb18fe248 --- /dev/null +++ b/api/types/matchers_gcp_test.go @@ -0,0 +1,160 @@ +// Copyright 2023 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 types + +import ( + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" +) + +func TestGCPMatcherCheckAndSetDefaults(t *testing.T) { + isBadParameterErr := func(tt require.TestingT, err error, i ...any) { + require.True(tt, trace.IsBadParameter(err), "expected bad parameter, got %v", err) + } + + for _, tt := range []struct { + name string + in *GCPMatcher + errCheck require.ErrorAssertionFunc + expected *GCPMatcher + }{ + { + name: "valid", + in: &GCPMatcher{ + Types: []string{"gce"}, + Locations: []string{"europe-west2"}, + ProjectIDs: []string{"project01"}, + Labels: Labels{ + "x": []string{"y"}, + }, + Params: &InstallerParams{ + JoinMethod: JoinMethodGCP, + JoinToken: GCPInviteTokenName, + ScriptName: DefaultInstallerScriptName, + }, + }, + errCheck: require.NoError, + expected: &GCPMatcher{ + Types: []string{"gce"}, + Locations: []string{"europe-west2"}, + ProjectIDs: []string{"project01"}, + Labels: Labels{ + "x": []string{"y"}, + }, + Params: &InstallerParams{ + JoinMethod: "gcp", + JoinToken: "gcp-discovery-token", + ScriptName: "default-installer", + }, + }, + }, + { + name: "default values", + in: &GCPMatcher{ + Types: []string{"gce"}, + ProjectIDs: []string{"project01"}, + }, + errCheck: require.NoError, + expected: &GCPMatcher{ + Types: []string{"gce"}, + Locations: []string{"*"}, + ProjectIDs: []string{"project01"}, + Labels: Labels{ + "*": []string{"*"}, + }, + Params: &InstallerParams{ + JoinMethod: "gcp", + JoinToken: "gcp-discovery-token", + ScriptName: "default-installer", + }, + }, + }, + { + name: "wildcard is invalid for types", + in: &GCPMatcher{ + Types: []string{"*"}, + ProjectIDs: []string{"project01"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "wildcard is invalid for project ids", + in: &GCPMatcher{ + Types: []string{"gce"}, + ProjectIDs: []string{"*"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid type", + in: &GCPMatcher{ + Types: []string{"invalid"}, + ProjectIDs: []string{"project01"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid join method", + in: &GCPMatcher{ + Types: []string{"gce"}, + ProjectIDs: []string{"project01"}, + Params: &InstallerParams{ + JoinMethod: "invalid", + }, + }, + errCheck: isBadParameterErr, + }, + { + name: "no type", + in: &GCPMatcher{ + Types: []string{}, + ProjectIDs: []string{"project01"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "no project id", + in: &GCPMatcher{ + Types: []string{"gce"}, + ProjectIDs: []string{}, + }, + errCheck: isBadParameterErr, + }, + { + name: "error if both labels and tags are set", + in: &GCPMatcher{ + Types: []string{"gce"}, + ProjectIDs: []string{"project001"}, + Labels: Labels{ + "*": []string{"*"}, + }, + Tags: Labels{ + "*": []string{"*"}, + }, + }, + errCheck: isBadParameterErr, + }, + } { + t.Run(tt.name, func(t *testing.T) { + err := tt.in.CheckAndSetDefaults() + tt.errCheck(t, err) + if tt.expected != nil { + require.Equal(t, tt.expected, tt.in) + } + }) + } +} diff --git a/api/types/matchers_kube.go b/api/types/matchers_kube.go index 0d4b355b05f..1f2102e6f95 100644 --- a/api/types/matchers_kube.go +++ b/api/types/matchers_kube.go @@ -16,8 +16,44 @@ limitations under the License. package types +import ( + "github.com/gravitational/trace" + "golang.org/x/exp/slices" + + apiutils "github.com/gravitational/teleport/api/utils" +) + +const ( + // KubernetesMatchersApp is app matcher type for Kubernetes services + KubernetesMatchersApp = "app" +) + +// SupportedKubernetesMatchers is a list of Kubernetes matchers supported by +// Teleport discovery service +var SupportedKubernetesMatchers = []string{ + KubernetesMatchersApp, +} + // CheckAndSetDefaults that the matcher is correct and adds default values. -func (m KubernetesMatcher) CheckAndSetDefaults() error { - // TODO(marco): implement +func (m *KubernetesMatcher) CheckAndSetDefaults() error { + for _, t := range m.Types { + if !slices.Contains(SupportedKubernetesMatchers, t) { + return trace.BadParameter("Kubernetes discovery does not support %q resource type; supported resource types are: %v", + t, SupportedKubernetesMatchers) + } + } + + if len(m.Types) == 0 { + m.Types = []string{KubernetesMatchersApp} + } + + if len(m.Namespaces) == 0 { + m.Namespaces = []string{Wildcard} + } + + if len(m.Labels) == 0 { + m.Labels = map[string]apiutils.Strings{Wildcard: {Wildcard}} + } + return nil } diff --git a/api/types/matchers_kube_test.go b/api/types/matchers_kube_test.go new file mode 100644 index 00000000000..841acf23650 --- /dev/null +++ b/api/types/matchers_kube_test.go @@ -0,0 +1,88 @@ +// Copyright 2023 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 types + +import ( + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" +) + +func TestKubeMatcherCheckAndSetDefaults(t *testing.T) { + isBadParameterErr := func(tt require.TestingT, err error, i ...any) { + require.True(tt, trace.IsBadParameter(err), "expected bad parameter, got %v", err) + } + + for _, tt := range []struct { + name string + in *KubernetesMatcher + errCheck require.ErrorAssertionFunc + expected *KubernetesMatcher + }{ + { + name: "valid", + in: &KubernetesMatcher{ + Types: []string{"app"}, + Namespaces: []string{"default"}, + Labels: Labels{ + "x": []string{"y"}, + }, + }, + errCheck: require.NoError, + expected: &KubernetesMatcher{ + Types: []string{"app"}, + Namespaces: []string{"default"}, + Labels: Labels{ + "x": []string{"y"}, + }, + }, + }, + { + name: "default values", + in: &KubernetesMatcher{}, + errCheck: require.NoError, + expected: &KubernetesMatcher{ + Types: []string{"app"}, + Namespaces: []string{"*"}, + Labels: Labels{ + "*": []string{"*"}, + }, + }, + }, + { + name: "wildcard is invalid for types", + in: &KubernetesMatcher{ + Types: []string{"*"}, + }, + errCheck: isBadParameterErr, + }, + { + name: "invalid type", + in: &KubernetesMatcher{ + Types: []string{"db"}, + }, + errCheck: isBadParameterErr, + }, + } { + t.Run(tt.name, func(t *testing.T) { + err := tt.in.CheckAndSetDefaults() + tt.errCheck(t, err) + if tt.expected != nil { + require.Equal(t, tt.expected, tt.in) + } + }) + } +} diff --git a/api/utils/aws/identifiers.go b/api/utils/aws/identifiers.go index efc093e4a70..e48da06a834 100644 --- a/api/utils/aws/identifiers.go +++ b/api/utils/aws/identifiers.go @@ -18,6 +18,7 @@ package aws import ( "regexp" + "strings" "github.com/gravitational/trace" ) @@ -61,6 +62,45 @@ func IsValidRegion(region string) error { return trace.BadParameter("region %q is invalid", region) } +const ( + arnDelimiter = ":" + arnPrefix = "arn:" + arnSections = 6 + sectionService = 2 // arn:::... + sectionAccount = 4 // arn:::::... + sectionResource = 5 // arn::::: + iamServiceName = "iam" +) + +// CheckRoleARN returns whether a string is a valid IAM Role ARN. +// Example role ARN: arn:aws:iam::123456789012:role/some-role-name +func CheckRoleARN(arn string) error { + if !strings.HasPrefix(arn, arnPrefix) { + return trace.BadParameter("arn: invalid prefix: %q", arn) + } + + sections := strings.SplitN(arn, arnDelimiter, arnSections) + if len(sections) != arnSections { + return trace.BadParameter("arn: not enough sections: %q", arn) + } + + resourceParts := strings.SplitN(sections[sectionResource], "/", 2) + + if resourceParts[0] != "role" || sections[sectionService] != iamServiceName { + return trace.BadParameter("%q is not an AWS IAM role ARN", arn) + } + + if len(resourceParts) < 2 || resourceParts[1] == "" { + return trace.BadParameter("%q is missing AWS IAM role name", arn) + } + + if err := IsValidAccountID(sections[sectionAccount]); err != nil { + return trace.BadParameter("%q invalid account ID: %v", arn, err) + } + + return nil +} + var ( // matchRoleName is a regex that matches against AWS IAM Role Names. matchRoleName = regexp.MustCompile(`^[\w+=,.@-]+$`).MatchString diff --git a/api/utils/aws/identifiers_test.go b/api/utils/aws/identifiers_test.go index 452e36f5493..a5398185b0a 100644 --- a/api/utils/aws/identifiers_test.go +++ b/api/utils/aws/identifiers_test.go @@ -179,3 +179,70 @@ func TestIsValidRegion(t *testing.T) { }) } } + +func TestCheckRoleARN(t *testing.T) { + isBadParamErrFn := func(tt require.TestingT, err error, i ...any) { + require.True(tt, trace.IsBadParameter(err), "expected bad parameter, got %v", err) + } + + for _, tt := range []struct { + name string + arn string + errCheck require.ErrorAssertionFunc + }{ + { + name: "valid", + arn: "arn:aws:iam:us-west-2:123456789012:role/foo/bar", + errCheck: require.NoError, + }, + { + name: "empty string", + arn: "", + errCheck: isBadParamErrFn, + }, + { + name: "arn identifier but no other section", + arn: "arn:nil", + errCheck: isBadParamErrFn, + }, + { + name: "valid with resource that has spaces", + arn: "arn:aws:iam:us-west-2:123456789012:role/foo bar", + errCheck: require.NoError, + }, + { + name: "valid when resource section has :", + arn: "arn:aws:iam:us-west-2:123456789012:role/foo bar:a", + errCheck: require.NoError, + }, + { + name: "invalid when resource is missing", + arn: "arn:aws:iam:us-west-2:123456789012", + errCheck: isBadParamErrFn, + }, + { + name: "valid even if region is missing", + arn: "arn:aws:iam::123456789012:role/foo bar", + errCheck: require.NoError, + }, + { + name: "invalid when the resource is not role", + arn: "arn:aws:iam::123456789012:user/foo bar", + errCheck: isBadParamErrFn, + }, + { + name: "invalid when the resource is of type role, but role name section is missing", + arn: "arn:aws:iam::123456789012:role", + errCheck: isBadParamErrFn, + }, + { + name: "invalid when the resource is of type role, but role is empty", + arn: "arn:aws:iam::123456789012:role/", + errCheck: isBadParamErrFn, + }, + } { + t.Run(tt.name, func(t *testing.T) { + tt.errCheck(t, CheckRoleARN(tt.arn)) + }) + } +} diff --git a/e2e/aws/eks_test.go b/e2e/aws/eks_test.go index 870bc6e3dcf..62f4b1c4f15 100644 --- a/e2e/aws/eks_test.go +++ b/e2e/aws/eks_test.go @@ -215,7 +215,7 @@ func withKubeService(t *testing.T, matchers ...services.ResourceMatcher) testOpt func withKubeDiscoveryService(t *testing.T, tags types.Labels) testOptionsFunc { t.Helper() return withDiscoveryService(t, "kube-e2e-test", types.AWSMatcher{ - Types: []string{services.AWSMatcherEKS}, + Types: []string{types.AWSMatcherEKS}, Tags: tags, Regions: []string{os.Getenv(awsRegionEnv)}, AssumeRole: &types.AssumeRole{ diff --git a/e2e/aws/rds_test.go b/e2e/aws/rds_test.go index b50d4b31c82..fab27fb7ee8 100644 --- a/e2e/aws/rds_test.go +++ b/e2e/aws/rds_test.go @@ -65,7 +65,7 @@ func awsDBDiscoveryUnmatched(t *testing.T) { cluster := createTeleportCluster(t, withSingleProxyPort(t), withDiscoveryService(t, "db-e2e-test", types.AWSMatcher{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Tags: types.Labels{ // This label should not match. "env": {"tag_not_found"}, @@ -110,7 +110,7 @@ func awsDBDiscoveryMatched(t *testing.T) { cluster := createTeleportCluster(t, withSingleProxyPort(t), withDiscoveryService(t, "db-e2e-test", types.AWSMatcher{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Tags: mustGetDiscoveryMatcherLabels(t), Regions: []string{awsRegion}, AssumeRole: &types.AssumeRole{ diff --git a/lib/config/configuration.go b/lib/config/configuration.go index efc2660b816..582689d96c7 100644 --- a/lib/config/configuration.go +++ b/lib/config/configuration.go @@ -1361,9 +1361,21 @@ func applyDiscoveryConfig(fc *FileConfig, cfg *servicecfg.Config) error { cfg.Discovery.DiscoveryGroup = fc.Discovery.DiscoveryGroup cfg.Discovery.PollInterval = fc.Discovery.PollInterval for _, matcher := range fc.Discovery.AWSMatchers { - installParams, err := matcher.InstallParams.Parse() - if err != nil { - return trace.Wrap(err) + var err error + var installParams *types.InstallerParams + if matcher.InstallParams != nil { + installParams, err = matcher.InstallParams.parse() + if err != nil { + return trace.Wrap(err) + } + } + + var assumeRole *types.AssumeRole + if matcher.AssumeRoleARN != "" || matcher.ExternalID != "" { + assumeRole = &types.AssumeRole{ + RoleARN: matcher.AssumeRoleARN, + ExternalID: matcher.ExternalID, + } } for _, region := range matcher.Regions { @@ -1377,73 +1389,96 @@ func applyDiscoveryConfig(fc *FileConfig, cfg *servicecfg.Config) error { } } - cfg.Discovery.AWSMatchers = append(cfg.Discovery.AWSMatchers, - types.AWSMatcher{ - Types: matcher.Types, - Regions: matcher.Regions, - AssumeRole: &types.AssumeRole{ - RoleARN: matcher.AssumeRoleARN, - ExternalID: matcher.ExternalID, - }, - Tags: matcher.Tags, - Params: &installParams, - SSM: &types.AWSSSM{DocumentName: matcher.SSM.DocumentName}, - }) + serviceMatcher := types.AWSMatcher{ + Types: matcher.Types, + Regions: matcher.Regions, + AssumeRole: assumeRole, + Tags: matcher.Tags, + Params: installParams, + SSM: &types.AWSSSM{DocumentName: matcher.SSM.DocumentName}, + } + if err := serviceMatcher.CheckAndSetDefaults(); err != nil { + return trace.Wrap(err) + } + + cfg.Discovery.AWSMatchers = append(cfg.Discovery.AWSMatchers, serviceMatcher) } for _, matcher := range fc.Discovery.AzureMatchers { - m := types.AzureMatcher{ - Subscriptions: matcher.Subscriptions, - ResourceGroups: matcher.ResourceGroups, - Types: matcher.Types, - Regions: matcher.Regions, - ResourceTags: matcher.ResourceTags, - } - + var installerParams *types.InstallerParams if matcher.InstallParams != nil { - m.Params = &types.InstallerParams{ + installerParams = &types.InstallerParams{ JoinMethod: matcher.InstallParams.JoinParams.Method, JoinToken: matcher.InstallParams.JoinParams.TokenName, ScriptName: matcher.InstallParams.ScriptName, PublicProxyAddr: getInstallerProxyAddr(matcher.InstallParams, fc), } if matcher.InstallParams.Azure != nil { - m.Params.Azure = &types.AzureInstallerParams{ + installerParams.Azure = &types.AzureInstallerParams{ ClientID: matcher.InstallParams.Azure.ClientID, } } } - cfg.Discovery.AzureMatchers = append(cfg.Discovery.AzureMatchers, m) + + serviceMatcher := types.AzureMatcher{ + Subscriptions: matcher.Subscriptions, + ResourceGroups: matcher.ResourceGroups, + Types: matcher.Types, + Regions: matcher.Regions, + ResourceTags: matcher.ResourceTags, + Params: installerParams, + } + if err := serviceMatcher.CheckAndSetDefaults(); err != nil { + return trace.Wrap(err) + } + + cfg.Discovery.AzureMatchers = append(cfg.Discovery.AzureMatchers, serviceMatcher) } for _, matcher := range fc.Discovery.GCPMatchers { - m := types.GCPMatcher{ - Types: matcher.Types, - Locations: matcher.Locations, - Labels: matcher.Labels, - Tags: matcher.Tags, - ProjectIDs: matcher.ProjectIDs, - ServiceAccounts: matcher.ServiceAccounts, - } + var installerParams *types.InstallerParams if matcher.InstallParams != nil { - m.Params = &types.InstallerParams{ + installerParams = &types.InstallerParams{ JoinMethod: matcher.InstallParams.JoinParams.Method, JoinToken: matcher.InstallParams.JoinParams.TokenName, ScriptName: matcher.InstallParams.ScriptName, PublicProxyAddr: getInstallerProxyAddr(matcher.InstallParams, fc), } } - cfg.Discovery.GCPMatchers = append(cfg.Discovery.GCPMatchers, m) + serviceMatcher := types.GCPMatcher{ + Types: matcher.Types, + Locations: matcher.Locations, + Labels: matcher.Labels, + Tags: matcher.Tags, + ProjectIDs: matcher.ProjectIDs, + ServiceAccounts: matcher.ServiceAccounts, + Params: installerParams, + } + if err := serviceMatcher.CheckAndSetDefaults(); err != nil { + return trace.Wrap(err) + } + + cfg.Discovery.GCPMatchers = append(cfg.Discovery.GCPMatchers, serviceMatcher) } + if len(fc.Discovery.KubernetesMatchers) > 0 { + if fc.Discovery.DiscoveryGroup == "" { + // TODO(anton): add link to documentation when it's available + return trace.BadParameter(`parameter 'discovery_group' should be defined for discovery service if +kubernetes matchers are present`) + } + } for _, matcher := range fc.Discovery.KubernetesMatchers { - cfg.Discovery.KubernetesMatchers = append(cfg.Discovery.KubernetesMatchers, - types.KubernetesMatcher{ - Types: matcher.Types, - Namespaces: matcher.Namespaces, - Labels: matcher.Labels, - }, - ) + serviceMatcher := types.KubernetesMatcher{ + Types: matcher.Types, + Namespaces: matcher.Namespaces, + Labels: matcher.Labels, + } + if err := serviceMatcher.CheckAndSetDefaults(); err != nil { + return trace.Wrap(err) + } + + cfg.Discovery.KubernetesMatchers = append(cfg.Discovery.KubernetesMatchers, serviceMatcher) } return nil diff --git a/lib/config/configuration_test.go b/lib/config/configuration_test.go index f211048877c..33eab3f8edc 100644 --- a/lib/config/configuration_test.go +++ b/lib/config/configuration_test.go @@ -40,6 +40,7 @@ import ( "github.com/gravitational/teleport/api/constants" apidefaults "github.com/gravitational/teleport/api/defaults" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/installers" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib" "github.com/gravitational/teleport/lib/auth/keystore" @@ -360,15 +361,6 @@ func TestConfigReading(t *testing.T) { }, AssumeRoleARN: "arn:aws:iam::123456789012:role/DBDiscoverer", ExternalID: "externalID123", - InstallParams: &InstallParams{ - JoinParams: JoinParams{ - TokenName: "aws-discovery-iam-token", - Method: "iam", - }, - SSHDConfig: "/etc/ssh/sshd_config", - ScriptName: "default-installer", - }, - SSM: AWSSSM{DocumentName: "TeleportDiscoveryInstaller"}, }, }, AzureMatchers: []AzureMatcher{ @@ -903,9 +895,9 @@ SREzU8onbBsjMg9QDiSf5oJLKvd/Ren+zGY7 require.Equal(t, cfg.Discovery.AWSMatchers[0].Params, &types.InstallerParams{ InstallTeleport: true, JoinMethod: "iam", - JoinToken: defaults.IAMInviteTokenName, + JoinToken: types.IAMInviteTokenName, ScriptName: "default-installer", - SSHDConfig: defaults.SSHDConfigPath, + SSHDConfig: types.SSHDConfigPath, }) require.True(t, cfg.Okta.Enabled) @@ -3771,6 +3763,9 @@ func TestApplyDiscoveryConfig(t *testing.T) { ClientID: "abcd1234", }, }, + Regions: []string{"*"}, + ResourceTags: types.Labels{"*": []string{"*"}}, + ResourceGroups: []string{"*"}, }, }, }, @@ -3789,8 +3784,11 @@ func TestApplyDiscoveryConfig(t *testing.T) { Enabled: true, AzureMatchers: []types.AzureMatcher{ { - Subscriptions: []string{"abcd"}, - Types: []string{"aks"}, + Subscriptions: []string{"abcd"}, + Types: []string{"aks"}, + Regions: []string{"*"}, + ResourceTags: types.Labels{"*": []string{"*"}}, + ResourceGroups: []string{"*"}, }, }, }, @@ -4197,3 +4195,534 @@ func TestGetInstallerProxyAddr(t *testing.T) { }) } } + +func TestDiscoveryConfig(t *testing.T) { + t.Parallel() + testCases := []struct { + desc string + mutate func(cfgMap) + expectError require.ErrorAssertionFunc + expectEnabled require.BoolAssertionFunc + expectedTotalMatchers int + expectedAWSMatchers []types.AWSMatcher + expectedAzureMatchers []types.AzureMatcher + expectedGCPMatchers []types.GCPMatcher + }{ + { + desc: "default", + mutate: func(cfgMap) {}, + expectError: require.NoError, + expectEnabled: require.False, + }, + { + desc: "GCP section without project_ids", + expectError: require.Error, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["gcp"] = []cfgMap{ + { + "types": []string{"gke"}, + }, + } + }, + }, + { + desc: "GCP section is filled with defaults", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["gcp"] = []cfgMap{ + { + "types": []string{"gke"}, + "project_ids": []string{"p1", "p2"}, + }, + } + }, + expectedGCPMatchers: []types.GCPMatcher{{ + Types: []string{"gke"}, + Locations: []string{"*"}, + Labels: map[string]apiutils.Strings{ + "*": []string{"*"}, + }, + ProjectIDs: []string{"p1", "p2"}, + }}, + }, + { + desc: "GCP section is filled", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["gcp"] = []cfgMap{ + { + "types": []string{"gke"}, + "locations": []string{"eucentral1"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + "project_ids": []string{"p1", "p2"}, + }, + } + }, + expectedGCPMatchers: []types.GCPMatcher{{ + Types: []string{"gke"}, + Locations: []string{"eucentral1"}, + Labels: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + Tags: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + ProjectIDs: []string{"p1", "p2"}, + }}, + }, + { + desc: "GCP section is filled with installer", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["gcp"] = []cfgMap{ + { + "types": []string{"gce"}, + "locations": []string{"eucentral1"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + "project_ids": []string{"p1", "p2"}, + "service_accounts": []string{"a@example.com", "b@example.com"}, + }, + } + }, + expectedGCPMatchers: []types.GCPMatcher{{ + Types: []string{"gce"}, + Locations: []string{"eucentral1"}, + Labels: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + Tags: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + ProjectIDs: []string{"p1", "p2"}, + ServiceAccounts: []string{"a@example.com", "b@example.com"}, + Params: &types.InstallerParams{ + JoinMethod: types.JoinMethodGCP, + JoinToken: types.GCPInviteTokenName, + ScriptName: installers.InstallerScriptName, + }, + }}, + }, + { + desc: "Azure section is filled with defaults (aks)", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ + { + "types": []string{"aks"}, + }, + } + }, + expectedAzureMatchers: []types.AzureMatcher{{ + Types: []string{"aks"}, + Regions: []string{"*"}, + ResourceTags: map[string]apiutils.Strings{ + "*": []string{"*"}, + }, + Subscriptions: []string{"*"}, + ResourceGroups: []string{"*"}, + }}, + }, + { + desc: "Azure section is filled with values", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ + { + "types": []string{"aks"}, + "regions": []string{"eucentral1"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + "subscriptions": []string{"sub1", "sub2"}, + "resource_groups": []string{"group1", "group2"}, + }, + } + }, + expectedAzureMatchers: []types.AzureMatcher{{ + Types: []string{"aks"}, + Regions: []string{"eucentral1"}, + ResourceTags: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + Subscriptions: []string{"sub1", "sub2"}, + ResourceGroups: []string{"group1", "group2"}, + }}, + }, + { + desc: "AWS section is filled with defaults", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "types": []string{"ec2"}, + "regions": []string{"eu-central-1"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + }, + } + }, + expectedAWSMatchers: []types.AWSMatcher{{ + Types: []string{"ec2"}, + Regions: []string{"eu-central-1"}, + Tags: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + Params: &types.InstallerParams{ + JoinMethod: types.JoinMethodIAM, + JoinToken: types.IAMInviteTokenName, + SSHDConfig: "/etc/ssh/sshd_config", + ScriptName: installers.InstallerScriptName, + InstallTeleport: true, + }, + SSM: &types.AWSSSM{DocumentName: types.AWSInstallerDocument}, + }}, + }, + { + desc: "AWS section is filled with custom configs", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "types": []string{"ec2"}, + "regions": []string{"eu-central-1"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + "install": cfgMap{ + "join_params": cfgMap{ + "token_name": "hello-iam-a-token", + "method": "iam", + }, + "script_name": "installer-custom", + }, + "ssm": cfgMap{ + "document_name": "hello_document", + }, + "assume_role_arn": "arn:aws:iam::123456789012:role/DBDiscoverer", + "external_id": "externalID123", + }, + } + }, + expectedAWSMatchers: []types.AWSMatcher{{ + Types: []string{"ec2"}, + Regions: []string{"eu-central-1"}, + Tags: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + Params: &types.InstallerParams{ + JoinMethod: types.JoinMethodIAM, + JoinToken: "hello-iam-a-token", + SSHDConfig: "/etc/ssh/sshd_config", + ScriptName: "installer-custom", + InstallTeleport: true, + }, + SSM: &types.AWSSSM{DocumentName: "hello_document"}, + AssumeRole: &types.AssumeRole{ + RoleARN: "arn:aws:iam::123456789012:role/DBDiscoverer", + ExternalID: "externalID123", + }, + }}, + }, + { + desc: "AWS section is filled with invalid region", + expectError: require.Error, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "types": []string{"ec2"}, + "regions": []string{"*"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + }, + } + }, + }, + { + desc: "AWS section is filled with invalid join method", + expectError: require.Error, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "install": cfgMap{ + "join_params": cfgMap{ + "token_name": "hello-iam-a-token", + "method": "token", + }, + }, + }, + } + }, + }, + { + desc: "AWS section is filled with external_id but empty assume_role_arn", + expectError: require.Error, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "types": []string{"rds"}, + "regions": []string{"us-west-1"}, + "assume_role_arn": "", + "external_id": "externalid123", + "tags": cfgMap{ + "discover_teleport": "yes", + }, + }, + } + }, + }, + { + desc: "AWS section is filled with external_id but empty assume_role_arn is ok for redshift serverless", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "types": []string{"redshift-serverless"}, + "regions": []string{"us-west-1"}, + "assume_role_arn": "", + "external_id": "externalid123", + "tags": cfgMap{ + "discover_teleport": "yes", + }, + }, + } + }, + expectedAWSMatchers: []types.AWSMatcher{{ + Types: []string{"redshift-serverless"}, + Regions: []string{"us-west-1"}, + Tags: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + Params: &types.InstallerParams{ + JoinMethod: types.JoinMethodIAM, + JoinToken: "aws-discovery-iam-token", + SSHDConfig: "/etc/ssh/sshd_config", + ScriptName: "default-installer", + InstallTeleport: true, + }, + SSM: &types.AWSSSM{DocumentName: "TeleportDiscoveryInstaller"}, + AssumeRole: &types.AssumeRole{ + RoleARN: "", + ExternalID: "externalid123", + }, + }}, + }, + { + desc: "AWS section is filled with invalid assume_role_arn", + expectError: require.Error, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "types": []string{"rds"}, + "regions": []string{"us-west-1"}, + "assume_role_arn": "foobar", + "tags": cfgMap{ + "discover_teleport": "yes", + }, + }, + } + }, + }, + { + desc: "AWS section is filled with assume_role_arn that is not an iam ARN", + expectError: require.Error, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "types": []string{"rds"}, + "regions": []string{"us-west-1"}, + "assume_role_arn": "arn:aws:sts::123456789012:federated-user/Alice", + "tags": cfgMap{ + "discover_teleport": "yes", + }, + }, + } + }, + }, + { + desc: "AWS section is filled with no token", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ + { + "types": []string{"ec2"}, + "regions": []string{"eu-west-1"}, + "install": cfgMap{ + "join_params": cfgMap{ + "method": "iam", + }, + }, + }, + } + }, + expectedAWSMatchers: []types.AWSMatcher{{ + Types: []string{"ec2"}, + SSM: &types.AWSSSM{ + DocumentName: types.AWSInstallerDocument, + }, + Regions: []string{"eu-west-1"}, + Tags: map[string]apiutils.Strings{"*": {"*"}}, + Params: &types.InstallerParams{ + JoinMethod: types.JoinMethodIAM, + JoinToken: types.IAMInviteTokenName, + ScriptName: installers.InstallerScriptName, + SSHDConfig: "/etc/ssh/sshd_config", + InstallTeleport: true, + }, + }}, + }, + { + desc: "Azure section is filled with defaults (vm)", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ + { + "types": []string{"vm"}, + "regions": []string{"westcentralus"}, + "resource_groups": []string{"rg1"}, + "subscriptions": []string{"88888888-8888-8888-8888-888888888888"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + }, + } + }, + expectedAzureMatchers: []types.AzureMatcher{{ + Types: []string{"vm"}, + Regions: []string{"westcentralus"}, + ResourceGroups: []string{"rg1"}, + Subscriptions: []string{"88888888-8888-8888-8888-888888888888"}, + ResourceTags: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + Params: &types.InstallerParams{ + JoinMethod: "azure", + JoinToken: "azure-discovery-token", + ScriptName: "default-installer", + }, + }}, + }, + { + desc: "Azure section is filled with custom config", + expectError: require.NoError, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ + {"types": []string{"vm"}, + "regions": []string{"westcentralus"}, + "resource_groups": []string{"rg1"}, + "subscriptions": []string{"88888888-8888-8888-8888-888888888888"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + "install": cfgMap{ + "join_params": cfgMap{ + "token_name": "custom-azure-token", + "method": "azure", + }, + "script_name": "custom-installer", + "public_proxy_addr": "teleport.example.com", + }, + }, + } + }, + expectedAzureMatchers: []types.AzureMatcher{{ + Types: []string{"vm"}, + Regions: []string{"westcentralus"}, + ResourceGroups: []string{"rg1"}, + Subscriptions: []string{"88888888-8888-8888-8888-888888888888"}, + ResourceTags: map[string]apiutils.Strings{ + "discover_teleport": []string{"yes"}, + }, + Params: &types.InstallerParams{ + JoinMethod: "azure", + JoinToken: "custom-azure-token", + ScriptName: "custom-installer", + PublicProxyAddr: "teleport.example.com", + }, + }}, + }, + { + desc: "Azure section is filled with invalid join method", + expectError: require.Error, + expectEnabled: require.True, + mutate: func(cfg cfgMap) { + cfg["discovery_service"].(cfgMap)["enabled"] = "yes" + cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ + {"types": []string{"vm"}, + "regions": []string{"westcentralus"}, + "resource_groups": []string{"rg1"}, + "subscriptions": []string{"88888888-8888-8888-8888-888888888888"}, + "tags": cfgMap{ + "discover_teleport": "yes", + }, + "install": cfgMap{ + "join_params": cfgMap{ + "token_name": "custom-azure-token", + "method": "token", + }, + }, + }, + } + }, + }, + } + for _, testCase := range testCases { + t.Run(testCase.desc, func(t *testing.T) { + text := bytes.NewBuffer(editConfig(t, testCase.mutate)) + fc, err := ReadConfig(text) + require.NoError(t, err) + + cfg := servicecfg.MakeDefaultConfig() + + err = ApplyFileConfig(fc, cfg) + testCase.expectError(t, err) + if cfg == nil { + return + } + + testCase.expectEnabled(t, cfg.Discovery.Enabled) + require.Equal(t, testCase.expectedAWSMatchers, cfg.Discovery.AWSMatchers) + require.Equal(t, testCase.expectedAzureMatchers, cfg.Discovery.AzureMatchers) + require.Equal(t, testCase.expectedGCPMatchers, cfg.Discovery.GCPMatchers) + }) + } +} diff --git a/lib/config/fileconf.go b/lib/config/fileconf.go index f6efd9ad8fe..8a8293e9f5d 100644 --- a/lib/config/fileconf.go +++ b/lib/config/fileconf.go @@ -41,9 +41,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/constants" "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/api/types/installers" apiutils "github.com/gravitational/teleport/api/utils" - awsapiutils "github.com/gravitational/teleport/api/utils/aws" "github.com/gravitational/teleport/api/utils/tlsutils" "github.com/gravitational/teleport/lib/backend" "github.com/gravitational/teleport/lib/client" @@ -52,7 +50,6 @@ import ( "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/sshutils/x11" "github.com/gravitational/teleport/lib/utils" - awsutils "github.com/gravitational/teleport/lib/utils/aws" ) // FileConfig structure represents the teleport configuration stored in a config file @@ -485,311 +482,6 @@ func (conf *FileConfig) CheckAndSetDefaults() error { } } - if err := checkAndSetDefaultsForAWSMatchers(conf.Discovery.AWSMatchers); err != nil { - return trace.Wrap(err) - } - if err := checkAndSetDefaultsForAzureMatchers(conf.Discovery.AzureMatchers); err != nil { - return trace.Wrap(err) - } - if err := checkAndSetDefaultsForGCPMatchers(conf.Discovery.GCPMatchers); err != nil { - return trace.Wrap(err) - } - if len(conf.Discovery.KubernetesMatchers) > 0 { - if conf.Discovery.DiscoveryGroup == "" { - // TODO(anton): add link to documentation when it's available - return trace.BadParameter(`parameter 'discovery_group' should be defined for discovery service if -kubernetes matchers are present`) - } - if err := checkAndSetDefaultsForKubeMatchers(conf.Discovery.KubernetesMatchers); err != nil { - return trace.Wrap(err) - } - } - - return nil -} - -// checkAndSetDefaultsForAWSMatchers sets the default values for discovery AWS matchers -// and validates the provided types. -func checkAndSetDefaultsForAWSMatchers(matcherInput []AWSMatcher) error { - for i := range matcherInput { - matcher := &matcherInput[i] - for _, matcherType := range matcher.Types { - if !slices.Contains(services.SupportedAWSMatchers, matcherType) { - return trace.BadParameter("discovery service type does not support %q, supported resource types are: %v", - matcherType, services.SupportedAWSMatchers) - } - } - - if len(matcher.Regions) == 0 { - return trace.BadParameter("discovery service requires at least one region; supported regions are: %v", - awsutils.GetKnownRegions()) - } - - for _, region := range matcher.Regions { - if err := awsapiutils.IsValidRegion(region); err != nil { - return trace.BadParameter("discovery service does not support region %q; supported regions are: %v", - region, awsutils.GetKnownRegions()) - } - } - - if matcher.AssumeRoleARN != "" { - _, err := awsutils.ParseRoleARN(matcher.AssumeRoleARN) - if err != nil { - return trace.Wrap(err, "discovery service AWS matcher assume_role_arn is invalid") - } - } else if matcher.ExternalID != "" { - for _, t := range matcher.Types { - if !slices.Contains(services.RequireAWSIAMRolesAsUsersMatchers, t) { - return trace.BadParameter("discovery service AWS matcher assume_role_arn is empty, but has external_id %q", - matcher.ExternalID) - } - } - } - - if matcher.Tags == nil || len(matcher.Tags) == 0 { - matcher.Tags = map[string]apiutils.Strings{types.Wildcard: {types.Wildcard}} - } - - var installParams types.InstallerParams - var err error - - if matcher.InstallParams == nil { - matcher.InstallParams = &InstallParams{ - JoinParams: JoinParams{ - TokenName: defaults.IAMInviteTokenName, - Method: types.JoinMethodIAM, - }, - ScriptName: installers.InstallerScriptName, - InstallTeleport: "", - SSHDConfig: defaults.SSHDConfigPath, - } - installParams, err = matcher.InstallParams.Parse() - if err != nil { - return trace.Wrap(err) - } - } else { - if method := matcher.InstallParams.JoinParams.Method; method == "" { - matcher.InstallParams.JoinParams.Method = types.JoinMethodIAM - } else if method != types.JoinMethodIAM { - return trace.BadParameter("only IAM joining is supported for EC2 auto-discovery") - } - - if matcher.InstallParams.JoinParams.TokenName == "" { - matcher.InstallParams.JoinParams.TokenName = defaults.IAMInviteTokenName - } - - if matcher.InstallParams.SSHDConfig == "" { - matcher.InstallParams.SSHDConfig = defaults.SSHDConfigPath - } - - installParams, err = matcher.InstallParams.Parse() - if err != nil { - return trace.Wrap(err) - } - - if installer := matcher.InstallParams.ScriptName; installer == "" { - if installParams.InstallTeleport { - matcher.InstallParams.ScriptName = installers.InstallerScriptName - } else { - matcher.InstallParams.ScriptName = installers.InstallerScriptNameAgentless - } - } - } - - if matcher.SSM.DocumentName == "" { - if installParams.InstallTeleport { - matcher.SSM.DocumentName = defaults.AWSInstallerDocument - } else { - matcher.SSM.DocumentName = defaults.AWSAgentlessInstallerDocument - } - } - } - return nil -} - -// checkAndSetDefaultsForAzureMatchers sets the default values for discovery Azure matchers -// and validates the provided types. -func checkAndSetDefaultsForAzureMatchers(matcherInput []AzureMatcher) error { - for i := range matcherInput { - matcher := &matcherInput[i] - - if len(matcher.Types) == 0 { - return trace.BadParameter("At least one Azure discovery service type must be specified, the supported resource types are: %v", - services.SupportedAzureMatchers) - } - - for _, matcherType := range matcher.Types { - if !slices.Contains(services.SupportedAzureMatchers, matcherType) { - return trace.BadParameter("Azure discovery service type does not support %q resource type; supported resource types are: %v", - matcherType, services.SupportedAzureMatchers) - } - } - - if slices.Contains(matcher.Types, services.AzureMatcherVM) { - if err := checkAndSetDefaultsForAzureInstaller(matcher); err != nil { - return trace.Wrap(err) - } - } - - if slices.Contains(matcher.Regions, types.Wildcard) || len(matcher.Regions) == 0 { - matcher.Regions = []string{types.Wildcard} - } - - if slices.Contains(matcher.Subscriptions, types.Wildcard) || len(matcher.Subscriptions) == 0 { - matcher.Subscriptions = []string{types.Wildcard} - } - - if slices.Contains(matcher.ResourceGroups, types.Wildcard) || len(matcher.ResourceGroups) == 0 { - matcher.ResourceGroups = []string{types.Wildcard} - } - - if len(matcher.ResourceTags) == 0 { - matcher.ResourceTags = map[string]apiutils.Strings{ - types.Wildcard: {types.Wildcard}, - } - } - - } - return nil -} - -func checkAndSetDefaultsForAzureInstaller(matcher *AzureMatcher) error { - if matcher.InstallParams == nil { - matcher.InstallParams = &InstallParams{ - JoinParams: JoinParams{ - TokenName: defaults.AzureInviteTokenName, - Method: types.JoinMethodAzure, - }, - ScriptName: installers.InstallerScriptName, - } - return nil - } - - switch matcher.InstallParams.JoinParams.Method { - case types.JoinMethodAzure, "": - matcher.InstallParams.JoinParams.Method = types.JoinMethodAzure - default: - return trace.BadParameter("only Azure joining is supported for Azure auto-discovery") - } - - if token := matcher.InstallParams.JoinParams.TokenName; token == "" { - matcher.InstallParams.JoinParams.TokenName = defaults.AzureInviteTokenName - } - - if installer := matcher.InstallParams.ScriptName; installer == "" { - matcher.InstallParams.ScriptName = installers.InstallerScriptName - } - return nil -} - -// checkAndSetDefaultsForGCPMatchers sets the default values for GCP matchers -// and validates the provided types. -func checkAndSetDefaultsForGCPMatchers(matcherInput []GCPMatcher) error { - for i := range matcherInput { - matcher := &matcherInput[i] - - if len(matcher.Types) == 0 { - return trace.BadParameter("At least one GCP discovery service type must be specified, the supported resource types are: %v", - services.SupportedGCPMatchers) - } - - for _, matcherType := range matcher.Types { - if !slices.Contains(services.SupportedGCPMatchers, matcherType) { - return trace.BadParameter("GCP discovery service type does not support %q resource type; supported resource types are: %v", - matcherType, services.SupportedGCPMatchers) - } - } - - if slices.Contains(matcher.Types, services.GCPMatcherCompute) { - if err := checkAndSetDefaultsForGCPInstaller(matcher); err != nil { - return trace.Wrap(err) - } - } - - if slices.Contains(matcher.Locations, types.Wildcard) || len(matcher.Locations) == 0 { - matcher.Locations = []string{types.Wildcard} - } - - if slices.Contains(matcher.ProjectIDs, types.Wildcard) { - return trace.BadParameter("GCP discovery service project_ids does not support wildcards; please specify at least one value in project_ids.") - } - if len(matcher.ProjectIDs) == 0 { - return trace.BadParameter("GCP discovery service project_ids does cannot be empty; please specify at least one value in project_ids.") - } - - if len(matcher.Labels) > 0 && len(matcher.Tags) > 0 { - return trace.BadParameter("labels and tags should not both be set.") - } - - if len(matcher.Tags) > 0 { - matcher.Labels = matcher.Tags - } - - if len(matcher.Labels) == 0 { - matcher.Labels = map[string]apiutils.Strings{ - types.Wildcard: {types.Wildcard}, - } - } - - } - return nil -} - -func checkAndSetDefaultsForGCPInstaller(matcher *GCPMatcher) error { - if matcher.InstallParams == nil { - matcher.InstallParams = &InstallParams{ - JoinParams: JoinParams{ - TokenName: defaults.GCPInviteTokenName, - Method: types.JoinMethodGCP, - }, - ScriptName: installers.InstallerScriptName, - } - return nil - } - - switch matcher.InstallParams.JoinParams.Method { - case types.JoinMethodGCP, "": - matcher.InstallParams.JoinParams.Method = types.JoinMethodGCP - default: - return trace.BadParameter("only GCP joining is supported for GCP auto-discovery") - } - - if token := matcher.InstallParams.JoinParams.TokenName; token == "" { - matcher.InstallParams.JoinParams.TokenName = defaults.GCPInviteTokenName - } - - if installer := matcher.InstallParams.ScriptName; installer == "" { - matcher.InstallParams.ScriptName = installers.InstallerScriptName - } - return nil -} - -// checkAndSetDefaultsForKubeMatchers sets the default values for Kubernetes matchers -// and validates the provided types. -func checkAndSetDefaultsForKubeMatchers(matchers []KubernetesMatcher) error { - for i := range matchers { - matcher := &matchers[i] - - for _, t := range matcher.Types { - if !slices.Contains(services.SupportedKubernetesMatchers, t) { - return trace.BadParameter("Kubernetes discovery does not support %q resource type; supported resource types are: %v", - t, services.SupportedKubernetesMatchers) - } - } - - if len(matcher.Types) == 0 { - matcher.Types = []string{services.KubernetesMatchersApp} - } - - if len(matcher.Namespaces) == 0 { - matcher.Namespaces = []string{types.Wildcard} - } - - if len(matcher.Labels) == 0 { - matcher.Labels = map[string]apiutils.Strings{types.Wildcard: {types.Wildcard}} - } - } - return nil } @@ -1889,8 +1581,8 @@ type InstallParams struct { Azure *AzureInstallParams `yaml:"azure,omitempty"` } -func (ip *InstallParams) Parse() (types.InstallerParams, error) { - install := types.InstallerParams{ +func (ip *InstallParams) parse() (*types.InstallerParams, error) { + install := &types.InstallerParams{ JoinMethod: ip.JoinParams.Method, JoinToken: ip.JoinParams.TokenName, ScriptName: ip.ScriptName, @@ -1905,7 +1597,7 @@ func (ip *InstallParams) Parse() (types.InstallerParams, error) { var err error install.InstallTeleport, err = apiutils.ParseBool(ip.InstallTeleport) if err != nil { - return types.InstallerParams{}, trace.Wrap(err) + return nil, trace.Wrap(err) } return install, nil diff --git a/lib/config/fileconf_test.go b/lib/config/fileconf_test.go index 1eebbe6df28..8c808df8d11 100644 --- a/lib/config/fileconf_test.go +++ b/lib/config/fileconf_test.go @@ -33,7 +33,6 @@ import ( "github.com/gravitational/teleport/api/constants" "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/api/types/installers" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/modules" @@ -866,581 +865,6 @@ func TestSSHSection(t *testing.T) { } } -func TestDiscoveryConfig(t *testing.T) { - t.Parallel() - testCases := []struct { - desc string - mutate func(cfgMap) - expectError require.ErrorAssertionFunc - expectEnabled require.BoolAssertionFunc - expectedDiscoverySection Discovery - }{ - { - desc: "default", - mutate: func(cfgMap) {}, - expectError: require.NoError, - expectEnabled: require.False, - expectedDiscoverySection: Discovery{}, - }, - { - desc: "GCP section without project_ids", - expectError: require.Error, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["gcp"] = []cfgMap{ - { - "types": []string{"gke"}, - }, - } - }, - expectedDiscoverySection: Discovery{}, - }, - { - desc: "GCP section is filled with defaults", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["gcp"] = []cfgMap{ - { - "types": []string{"gke"}, - "project_ids": []string{"p1", "p2"}, - }, - } - }, - expectedDiscoverySection: Discovery{ - GCPMatchers: []GCPMatcher{ - { - Types: []string{"gke"}, - Locations: []string{"*"}, - Labels: map[string]apiutils.Strings{ - "*": []string{"*"}, - }, - ProjectIDs: []string{"p1", "p2"}, - }, - }, - }, - }, - { - desc: "GCP section is filled", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["gcp"] = []cfgMap{ - { - "types": []string{"gke"}, - "locations": []string{"eucentral1"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - "project_ids": []string{"p1", "p2"}, - }, - } - }, - expectedDiscoverySection: Discovery{ - GCPMatchers: []GCPMatcher{ - { - Types: []string{"gke"}, - Locations: []string{"eucentral1"}, - Labels: map[string]apiutils.Strings{ - "discover_teleport": []string{"yes"}, - }, - ProjectIDs: []string{"p1", "p2"}, - }, - }, - }, - }, - { - desc: "GCP section is filled with installer", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["gcp"] = []cfgMap{ - { - "types": []string{"gce"}, - "locations": []string{"eucentral1"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - "project_ids": []string{"p1", "p2"}, - "service_accounts": []string{"a@example.com", "b@example.com"}, - }, - } - }, - expectedDiscoverySection: Discovery{ - GCPMatchers: []GCPMatcher{ - { - Types: []string{"gke"}, - Locations: []string{"eucentral1"}, - Labels: map[string]apiutils.Strings{ - "discover_teleport": []string{"yes"}, - }, - ProjectIDs: []string{"p1", "p2"}, - ServiceAccounts: []string{"a@example.com", "b@example.com"}, - InstallParams: &InstallParams{ - JoinParams: JoinParams{ - TokenName: defaults.GCPInviteTokenName, - Method: types.JoinMethodGCP, - }, - ScriptName: installers.InstallerScriptName, - }, - }, - }, - }, - }, - { - desc: "Azure section is filled with defaults (aks)", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ - { - "types": []string{"aks"}, - }, - } - }, - expectedDiscoverySection: Discovery{ - AzureMatchers: []AzureMatcher{ - { - Types: []string{"aks"}, - Regions: []string{"*"}, - ResourceTags: map[string]apiutils.Strings{ - "*": []string{"*"}, - }, - Subscriptions: []string{"*"}, - ResourceGroups: []string{"*"}, - }, - }, - }, - }, - { - desc: "Azure section is filled with values", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ - { - "types": []string{"aks"}, - "regions": []string{"eucentral1"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - "subscriptions": []string{"sub1", "sub2"}, - "resource_groups": []string{"group1", "group2"}, - }, - } - }, - expectedDiscoverySection: Discovery{ - AzureMatchers: []AzureMatcher{ - { - Types: []string{"aks"}, - Regions: []string{"eucentral1"}, - ResourceTags: map[string]apiutils.Strings{ - "discover_teleport": []string{"yes"}, - }, - Subscriptions: []string{"sub1", "sub2"}, - ResourceGroups: []string{"group1", "group2"}, - }, - }, - }, - }, - { - desc: "AWS section is filled with defaults", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "types": []string{"ec2"}, - "regions": []string{"eu-central-1"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - }, - } - }, - expectedDiscoverySection: Discovery{ - AWSMatchers: []AWSMatcher{ - { - Types: []string{"ec2"}, - Regions: []string{"eu-central-1"}, - Tags: map[string]apiutils.Strings{ - "discover_teleport": []string{"yes"}, - }, - InstallParams: &InstallParams{ - JoinParams: JoinParams{ - TokenName: defaults.IAMInviteTokenName, - Method: types.JoinMethodIAM, - }, - SSHDConfig: "/etc/ssh/sshd_config", - ScriptName: installers.InstallerScriptName, - }, - SSM: AWSSSM{DocumentName: defaults.AWSInstallerDocument}, - }, - }, - }, - }, - { - desc: "AWS section is filled with custom configs", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "types": []string{"ec2"}, - "regions": []string{"eu-central-1"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - "install": cfgMap{ - "join_params": cfgMap{ - "token_name": "hello-iam-a-token", - "method": "iam", - }, - "script_name": "installer-custom", - }, - "ssm": cfgMap{ - "document_name": "hello_document", - }, - "assume_role_arn": "arn:aws:iam::123456789012:role/DBDiscoverer", - "external_id": "externalID123", - }, - } - }, - expectedDiscoverySection: Discovery{ - AWSMatchers: []AWSMatcher{ - { - Types: []string{"ec2"}, - Regions: []string{"eu-central-1"}, - Tags: map[string]apiutils.Strings{ - "discover_teleport": []string{"yes"}, - }, - InstallParams: &InstallParams{ - JoinParams: JoinParams{ - TokenName: "hello-iam-a-token", - Method: types.JoinMethodIAM, - }, - SSHDConfig: "/etc/ssh/sshd_config", - ScriptName: "installer-custom", - }, - SSM: AWSSSM{DocumentName: "hello_document"}, - AssumeRoleARN: "arn:aws:iam::123456789012:role/DBDiscoverer", - ExternalID: "externalID123", - }, - }, - }, - }, - { - desc: "AWS section is filled with invalid region", - expectError: require.Error, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "types": []string{"ec2"}, - "regions": []string{"*"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - }, - } - }, - expectedDiscoverySection: Discovery{}, - }, - { - desc: "AWS section is filled with invalid join method", - expectError: require.Error, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "install": cfgMap{ - "join_params": cfgMap{ - "token_name": "hello-iam-a-token", - "method": "token", - }, - }, - }, - } - }, - expectedDiscoverySection: Discovery{}, - }, - { - desc: "AWS section is filled with external_id but empty assume_role_arn", - expectError: require.Error, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "types": []string{"rds"}, - "regions": []string{"us-west-1"}, - "assume_role_arn": "", - "external_id": "externalid123", - "tags": cfgMap{ - "discover_teleport": "yes", - }, - }, - } - }, - expectedDiscoverySection: Discovery{}, - }, - { - desc: "AWS section is filled with external_id but empty assume_role_arn is ok for redshift serverless", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "types": []string{"redshift-serverless"}, - "regions": []string{"us-west-1"}, - "assume_role_arn": "", - "external_id": "externalid123", - "tags": cfgMap{ - "discover_teleport": "yes", - }, - }, - } - }, - expectedDiscoverySection: Discovery{ - AWSMatchers: []AWSMatcher{ - { - Types: []string{"redshift-serverless"}, - Regions: []string{"us-west-1"}, - Tags: map[string]apiutils.Strings{ - "discover_teleport": []string{"yes"}, - }, - InstallParams: &InstallParams{ - JoinParams: JoinParams{ - TokenName: "aws-discovery-iam-token", - Method: types.JoinMethodIAM, - }, - SSHDConfig: "/etc/ssh/sshd_config", - ScriptName: "default-installer", - }, - SSM: AWSSSM{DocumentName: "TeleportDiscoveryInstaller"}, - AssumeRoleARN: "", - ExternalID: "externalid123", - }, - }, - }, - }, - { - desc: "AWS section is filled with invalid assume_role_arn", - expectError: require.Error, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "types": []string{"rds"}, - "regions": []string{"us-west-1"}, - "assume_role_arn": "foobar", - "tags": cfgMap{ - "discover_teleport": "yes", - }, - }, - } - }, - expectedDiscoverySection: Discovery{}, - }, - { - desc: "AWS section is filled with assume_role_arn that is not an iam ARN", - expectError: require.Error, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "types": []string{"rds"}, - "regions": []string{"us-west-1"}, - "assume_role_arn": "arn:aws:sts::123456789012:federated-user/Alice", - "tags": cfgMap{ - "discover_teleport": "yes", - }, - }, - } - }, - expectedDiscoverySection: Discovery{}, - }, - { - desc: "AWS section is filled with no token", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["aws"] = []cfgMap{ - { - "regions": []string{"eu-west-1"}, - "install": cfgMap{ - "join_params": cfgMap{ - "method": "iam", - }, - }, - }, - } - }, - expectedDiscoverySection: Discovery{ - AWSMatchers: []AWSMatcher{ - { - SSM: AWSSSM{ - DocumentName: defaults.AWSInstallerDocument, - }, - Regions: []string{"eu-west-1"}, - Tags: map[string]apiutils.Strings{"*": {"*"}}, - InstallParams: &InstallParams{ - JoinParams: JoinParams{ - TokenName: defaults.IAMInviteTokenName, - Method: types.JoinMethodIAM, - }, - ScriptName: installers.InstallerScriptName, - SSHDConfig: "/etc/ssh/sshd_config", - }, - }, - }, - }, - }, - { - desc: "Azure section is filled with defaults (vm)", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ - { - "types": []string{"vm"}, - "regions": []string{"westcentralus"}, - "resource_groups": []string{"rg1"}, - "subscriptions": []string{"88888888-8888-8888-8888-888888888888"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - }, - } - }, - expectedDiscoverySection: Discovery{ - AzureMatchers: []AzureMatcher{ - { - Types: []string{"vm"}, - Regions: []string{"westcentralus"}, - ResourceGroups: []string{"rg1"}, - Subscriptions: []string{"88888888-8888-8888-8888-888888888888"}, - ResourceTags: map[string]apiutils.Strings{ - "discover_teleport": []string{"yes"}, - }, - InstallParams: &InstallParams{ - JoinParams: JoinParams{ - TokenName: "azure-discovery-token", - Method: "azure", - }, - ScriptName: "default-installer", - }, - }, - }, - }, - }, - { - desc: "Azure section is filled with custom config", - expectError: require.NoError, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ - {"types": []string{"vm"}, - "regions": []string{"westcentralus"}, - "resource_groups": []string{"rg1"}, - "subscriptions": []string{"88888888-8888-8888-8888-888888888888"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - "install": cfgMap{ - "join_params": cfgMap{ - "token_name": "custom-azure-token", - "method": "azure", - }, - "script_name": "custom-installer", - "public_proxy_addr": "teleport.example.com", - }, - }, - } - }, - expectedDiscoverySection: Discovery{ - AzureMatchers: []AzureMatcher{ - { - Types: []string{"vm"}, - Regions: []string{"westcentralus"}, - ResourceGroups: []string{"rg1"}, - Subscriptions: []string{"88888888-8888-8888-8888-888888888888"}, - ResourceTags: map[string]apiutils.Strings{ - "discover_teleport": []string{"yes"}, - }, - InstallParams: &InstallParams{ - JoinParams: JoinParams{ - TokenName: "custom-azure-token", - Method: "azure", - }, - ScriptName: "custom-installer", - PublicProxyAddr: "teleport.example.com", - }, - }, - }, - }, - }, - { - desc: "Azure section is filled with invalid join method", - expectError: require.Error, - expectEnabled: require.True, - mutate: func(cfg cfgMap) { - cfg["discovery_service"].(cfgMap)["enabled"] = "yes" - cfg["discovery_service"].(cfgMap)["azure"] = []cfgMap{ - {"types": []string{"vm"}, - "regions": []string{"westcentralus"}, - "resource_groups": []string{"rg1"}, - "subscriptions": []string{"88888888-8888-8888-8888-888888888888"}, - "tags": cfgMap{ - "discover_teleport": "yes", - }, - "install": cfgMap{ - "join_params": cfgMap{ - "token_name": "custom-azure-token", - "method": "token", - }, - }, - }, - } - }, - expectedDiscoverySection: Discovery{}, - }, - } - for _, testCase := range testCases { - t.Run(testCase.desc, func(t *testing.T) { - text := bytes.NewBuffer(editConfig(t, testCase.mutate)) - cfg, err := ReadConfig(text) - testCase.expectError(t, err) - if cfg == nil { - return - } - testCase.expectEnabled(t, cfg.Discovery.Enabled()) - if expectedAWS := testCase.expectedDiscoverySection.AWSMatchers; expectedAWS != nil { - require.Equal(t, expectedAWS, cfg.Discovery.AWSMatchers) - } - if expectedAzure := testCase.expectedDiscoverySection.AzureMatchers; expectedAzure != nil { - require.Equal(t, expectedAzure, cfg.Discovery.AzureMatchers) - } - }) - } -} - func TestX11Config(t *testing.T) { testCases := []struct { desc string diff --git a/lib/configurators/aws/aws.go b/lib/configurators/aws/aws.go index c15edefe22d..eaec6c02442 100644 --- a/lib/configurators/aws/aws.go +++ b/lib/configurators/aws/aws.go @@ -174,7 +174,7 @@ var ( stsActions = []string{ "sts:AssumeRole", } - // rdsActions contains IAM actions for services.AWSMatcherRDS (RDS + // rdsActions contains IAM actions for types.AWSMatcherRDS (RDS // instances and Aurora clusters). rdsActions = databaseActions{ discovery: []string{"rds:DescribeDBInstances", "rds:DescribeDBClusters"}, @@ -183,7 +183,7 @@ var ( authBoundary: []string{"rds-db:connect"}, requireIAMEdit: true, } - // rdsProxyActions contains IAM actions for services.AWSMatcherRDSProxy. + // rdsProxyActions contains IAM actions for types.AWSMatcherRDSProxy. rdsProxyActions = databaseActions{ discovery: []string{ "rds:DescribeDBProxies", @@ -198,14 +198,14 @@ var ( authBoundary: []string{"rds-db:connect"}, requireIAMEdit: true, } - // redshiftActions contains IAM actions for services.AWSMatcherRedshift. + // redshiftActions contains IAM actions for types.AWSMatcherRedshift. redshiftActions = databaseActions{ discovery: []string{"redshift:DescribeClusters"}, metadata: []string{"redshift:DescribeClusters"}, authBoundary: []string{"redshift:GetClusterCredentials"}, requireIAMEdit: true, } - // redshiftServerlessActions contains IAM actions for services.AWSMatcherRedshiftServerless. + // redshiftServerlessActions contains IAM actions for types.AWSMatcherRedshiftServerless. redshiftServerlessActions = databaseActions{ discovery: []string{ "redshift-serverless:ListWorkgroups", @@ -218,7 +218,7 @@ var ( }, authBoundary: stsActions, } - // elastiCacheActions contains IAM actions for services.AWSMatcherElastiCache. + // elastiCacheActions contains IAM actions for types.AWSMatcherElastiCache. elastiCacheActions = databaseActions{ discovery: []string{ "elasticache:ListTagsForResource", @@ -237,7 +237,7 @@ var ( authBoundary: []string{"elasticache:Connect"}, requireIAMEdit: true, } - // memoryDBActions contains IAM actions for services.AWSMatcherMemoryDB. + // memoryDBActions contains IAM actions for types.AWSMatcherMemoryDB. memoryDBActions = databaseActions{ discovery: []string{ "memorydb:ListTags", @@ -261,7 +261,7 @@ var ( dynamodbActions = databaseActions{ authBoundary: stsActions, } - // opensearchActions contains IAM actions for services.AWSMatcherOpenSearch + // opensearchActions contains IAM actions for types.AWSMatcherOpenSearch opensearchActions = databaseActions{ discovery: []string{ "es:ListDomainNames", @@ -341,7 +341,7 @@ func (c *ConfiguratorConfig) CheckAndSetDefaults() error { if c.AWSSSMClients == nil { c.AWSSSMClients = make(map[string]ssmiface.SSMAPI) for _, matcher := range c.ServiceConfig.Discovery.AWSMatchers { - if !slices.Contains(matcher.Types, services.AWSMatcherEC2) { + if !slices.Contains(matcher.Types, types.AWSMatcherEC2) { continue } for _, region := range matcher.Regions { @@ -773,7 +773,7 @@ func getProxyAddrFromConfig(cfg *servicecfg.Config, flags configurators.Bootstra func buildSSMDocumentCreators(ssm map[string]ssmiface.SSMAPI, targetCfg targetConfig, proxyAddr string) []configurators.ConfiguratorAction { var creators []configurators.ConfiguratorAction for _, matcher := range targetCfg.awsMatchers { - if !slices.Contains(matcher.Types, services.AWSMatcherEC2) { + if !slices.Contains(matcher.Types, types.AWSMatcherEC2) { continue } for _, region := range matcher.Regions { @@ -792,7 +792,7 @@ func isEC2AutoDiscoveryEnabled(flags configurators.BootstrapFlags, matchers []ty if flags.ForceEC2Permissions { return true } - return isAutoDiscoveryEnabledForMatcher(services.AWSMatcherEC2, matchers) + return isAutoDiscoveryEnabledForMatcher(types.AWSMatcherEC2, matchers) } // hasRDSDatabases checks if the agent needs permission for @@ -801,7 +801,7 @@ func hasRDSDatabases(flags configurators.BootstrapFlags, targetCfg targetConfig) if flags.ForceRDSPermissions { return true } - return isAutoDiscoveryEnabledForMatcher(services.AWSMatcherRDS, targetCfg.awsMatchers) || + return isAutoDiscoveryEnabledForMatcher(types.AWSMatcherRDS, targetCfg.awsMatchers) || findEndpointIs(targetCfg.databases, isRDSEndpoint) } @@ -811,7 +811,7 @@ func hasRDSProxyDatabases(flags configurators.BootstrapFlags, targetCfg targetCo if flags.ForceRDSProxyPermissions { return true } - return isAutoDiscoveryEnabledForMatcher(services.AWSMatcherRDSProxy, targetCfg.awsMatchers) || + return isAutoDiscoveryEnabledForMatcher(types.AWSMatcherRDSProxy, targetCfg.awsMatchers) || findEndpointIs(targetCfg.databases, isRDSProxyEndpoint) } @@ -821,7 +821,7 @@ func hasRedshiftDatabases(flags configurators.BootstrapFlags, targetCfg targetCo if flags.ForceRedshiftPermissions { return true } - return isAutoDiscoveryEnabledForMatcher(services.AWSMatcherRedshift, targetCfg.awsMatchers) || + return isAutoDiscoveryEnabledForMatcher(types.AWSMatcherRedshift, targetCfg.awsMatchers) || findEndpointIs(targetCfg.databases, apiawsutils.IsRedshiftEndpoint) } @@ -831,7 +831,7 @@ func hasRedshiftServerlessDatabases(flags configurators.BootstrapFlags, targetCf if flags.ForceRedshiftServerlessPermissions { return true } - return isAutoDiscoveryEnabledForMatcher(services.AWSMatcherRedshiftServerless, targetCfg.awsMatchers) || + return isAutoDiscoveryEnabledForMatcher(types.AWSMatcherRedshiftServerless, targetCfg.awsMatchers) || findEndpointIs(targetCfg.databases, apiawsutils.IsRedshiftServerlessEndpoint) } @@ -841,7 +841,7 @@ func hasElastiCacheDatabases(flags configurators.BootstrapFlags, targetCfg targe if flags.ForceElastiCachePermissions { return true } - return isAutoDiscoveryEnabledForMatcher(services.AWSMatcherElastiCache, targetCfg.awsMatchers) || + return isAutoDiscoveryEnabledForMatcher(types.AWSMatcherElastiCache, targetCfg.awsMatchers) || findEndpointIs(targetCfg.databases, apiawsutils.IsElastiCacheEndpoint) } @@ -851,7 +851,7 @@ func hasMemoryDBDatabases(flags configurators.BootstrapFlags, targetCfg targetCo if flags.ForceMemoryDBPermissions { return true } - return isAutoDiscoveryEnabledForMatcher(services.AWSMatcherMemoryDB, targetCfg.awsMatchers) || + return isAutoDiscoveryEnabledForMatcher(types.AWSMatcherMemoryDB, targetCfg.awsMatchers) || findEndpointIs(targetCfg.databases, apiawsutils.IsMemoryDBEndpoint) } @@ -861,7 +861,7 @@ func hasOpenSearchDatabases(flags configurators.BootstrapFlags, targetCfg target if flags.ForceOpenSearchPermissions { return true } - return isAutoDiscoveryEnabledForMatcher(services.AWSMatcherOpenSearch, targetCfg.awsMatchers) || + return isAutoDiscoveryEnabledForMatcher(types.AWSMatcherOpenSearch, targetCfg.awsMatchers) || findDatabaseIs(targetCfg.databases, func(db *servicecfg.Database) bool { return db.Protocol == defaults.ProtocolOpenSearch }) @@ -942,7 +942,7 @@ func findAWSMatcherIs(matchers []types.AWSMatcher, is func(*types.AWSMatcher) bo // AWS roles. Currently limited to just the AWS database matchers. func supportsAWSAssumeRole(matcher types.AWSMatcher) bool { for _, matcherType := range matcher.Types { - if slices.Contains(services.SupportedAWSDatabaseMatchers, matcherType) { + if slices.Contains(types.SupportedAWSDatabaseMatchers, matcherType) { return true } } diff --git a/lib/configurators/aws/aws_test.go b/lib/configurators/aws/aws_test.go index eb09256dd5c..8b2790ab458 100644 --- a/lib/configurators/aws/aws_test.go +++ b/lib/configurators/aws/aws_test.go @@ -80,7 +80,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, }, }, }, @@ -110,7 +110,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, }, }, }, @@ -174,7 +174,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRedshift}, Regions: []string{"us-west-2"}}, }, }, }, @@ -201,7 +201,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRedshift}, Regions: []string{"us-west-2"}}, }, }, }, @@ -259,7 +259,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}}, }, }, }, @@ -410,7 +410,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherMemoryDB}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherMemoryDB}, Regions: []string{"us-west-2"}}, }, }, }, @@ -545,7 +545,7 @@ func TestAWSIAMDocuments(t *testing.T) { Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ { - Types: []string{services.AWSMatcherEC2}, + Types: []string{types.AWSMatcherEC2}, Regions: []string{"eu-central-1"}, Tags: map[string]utils.Strings{"*": []string{"*"}}, InstallParams: &config.InstallParams{ @@ -586,7 +586,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, }, }, }, @@ -597,7 +597,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, }, }, }, @@ -657,7 +657,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshiftServerless}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRedshiftServerless}, Regions: []string{"us-west-2"}}, }, }, }, @@ -757,7 +757,7 @@ func TestAWSIAMDocuments(t *testing.T) { Databases: config.Databases{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherOpenSearch}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherOpenSearch}, Regions: []string{"us-west-2"}}, }, }, }, @@ -831,8 +831,8 @@ func TestAWSIAMDocuments(t *testing.T) { }, }, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS}, Regions: []string{"us-west-2"}, AssumeRoleARN: role4}, - {Types: []string{services.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}, AssumeRoleARN: roleTarget.String(), ExternalID: "foo"}, + {Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-2"}, AssumeRoleARN: role4}, + {Types: []string{types.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}, AssumeRoleARN: roleTarget.String(), ExternalID: "foo"}, }, }, }, @@ -880,8 +880,8 @@ func TestAWSIAMDocuments(t *testing.T) { }, }, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS}, Regions: []string{"us-west-2"}, AssumeRoleARN: role4}, - {Types: []string{services.AWSMatcherRDS}, Regions: []string{"us-west-2"}, AssumeRoleARN: role5, ExternalID: "foo"}, + {Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-2"}, AssumeRoleARN: role4}, + {Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-2"}, AssumeRoleARN: role5, ExternalID: "foo"}, }, }, }, @@ -933,7 +933,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, }, }, }, @@ -951,7 +951,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, }, }, }, @@ -969,7 +969,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRedshift}, Regions: []string{"us-west-2"}}, }, }, }, @@ -987,7 +987,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshiftServerless}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRedshiftServerless}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1005,7 +1005,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1023,7 +1023,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherMemoryDB}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherMemoryDB}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1041,7 +1041,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherOpenSearch}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherOpenSearch}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1059,9 +1059,9 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, Regions: []string{"us-west-1"}}, - {Types: []string{services.AWSMatcherRedshift, services.AWSMatcherRDS, services.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, - {Types: []string{services.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}, AssumeRoleARN: role1, ExternalID: "foo"}, + {Types: []string{types.AWSMatcherRedshift}, Regions: []string{"us-west-1"}}, + {Types: []string{types.AWSMatcherRedshift, types.AWSMatcherRDS, types.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}, AssumeRoleARN: role1, ExternalID: "foo"}, }, }, }, @@ -1139,7 +1139,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1173,7 +1173,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1207,7 +1207,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRedshift}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1241,7 +1241,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshiftServerless}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherRedshiftServerless}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1265,7 +1265,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1319,7 +1319,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherMemoryDB}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherMemoryDB}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1363,7 +1363,7 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherOpenSearch}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherOpenSearch}, Regions: []string{"us-west-2"}}, }, }, }, @@ -1387,9 +1387,9 @@ func TestAWSIAMDocuments(t *testing.T) { Discovery: config.Discovery{ Service: config.Service{EnabledFlag: "true"}, AWSMatchers: []config.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, Regions: []string{"us-west-1"}}, - {Types: []string{services.AWSMatcherRedshift, services.AWSMatcherRDS, services.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, - {Types: []string{services.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}, AssumeRoleARN: role1, ExternalID: "foo"}, + {Types: []string{types.AWSMatcherRedshift}, Regions: []string{"us-west-1"}}, + {Types: []string{types.AWSMatcherRedshift, types.AWSMatcherRDS, types.AWSMatcherRDSProxy}, Regions: []string{"us-west-2"}}, + {Types: []string{types.AWSMatcherElastiCache}, Regions: []string{"us-west-2"}, AssumeRoleARN: role1, ExternalID: "foo"}, }, }, }, @@ -1922,7 +1922,7 @@ func TestExtractTargetConfig(t *testing.T) { // check discovery resources are not included Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, Databases: servicecfg.DatabasesConfig{ @@ -1933,11 +1933,11 @@ func TestExtractTargetConfig(t *testing.T) { {Name: "db4", AWS: servicecfg.DatabaseAWS{AssumeRoleARN: roleTarget.String()}}, }, AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS, services.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, - {Types: []string{services.AWSMatcherRDS, services.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role5, ExternalID: "foo"}}, - {Types: []string{services.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role6}}, - {Types: []string{services.AWSMatcherElastiCache}}, - {Types: []string{services.AWSMatcherRedshift}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDS, types.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, + {Types: []string{types.AWSMatcherRDS, types.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role5, ExternalID: "foo"}}, + {Types: []string{types.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role6}}, + {Types: []string{types.AWSMatcherElastiCache}}, + {Types: []string{types.AWSMatcherRedshift}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, }, @@ -1946,7 +1946,7 @@ func TestExtractTargetConfig(t *testing.T) { assumesAWSRoles: []string{role1}, databases: []*servicecfg.Database{{Name: "db4", AWS: servicecfg.DatabaseAWS{AssumeRoleARN: roleTarget.String()}}}, awsMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRedshift}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, }, @@ -1956,7 +1956,7 @@ func TestExtractTargetConfig(t *testing.T) { cfg: &servicecfg.Config{ Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, // check that database service resources are not included. @@ -1965,7 +1965,7 @@ func TestExtractTargetConfig(t *testing.T) { {Name: "db1", AWS: servicecfg.DatabaseAWS{AssumeRoleARN: roleTarget.String()}}, }, AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRedshift}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, }, @@ -1973,7 +1973,7 @@ func TestExtractTargetConfig(t *testing.T) { // identity field is ignored in want/got diff, see comment in test loop. assumesAWSRoles: []string{role1}, awsMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, }, @@ -1983,7 +1983,7 @@ func TestExtractTargetConfig(t *testing.T) { cfg: &servicecfg.Config{ Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, // check that database service resources are not included. @@ -1992,7 +1992,7 @@ func TestExtractTargetConfig(t *testing.T) { {Name: "db1", AWS: servicecfg.DatabaseAWS{AssumeRoleARN: roleTarget.String()}}, }, AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRedshift}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRedshift}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, }, @@ -2000,7 +2000,7 @@ func TestExtractTargetConfig(t *testing.T) { // identity field is ignored in want/got diff, see comment in test loop. assumesAWSRoles: []string{role1}, awsMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, }, @@ -2011,7 +2011,7 @@ func TestExtractTargetConfig(t *testing.T) { // check that discovery service resources are not included. Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherEC2}}, + {Types: []string{types.AWSMatcherEC2}}, }, }, Databases: servicecfg.DatabasesConfig{ @@ -2022,12 +2022,12 @@ func TestExtractTargetConfig(t *testing.T) { }, AWSMatchers: []types.AWSMatcher{ // rds/ec2 matcher's assume role should be added because rds assume role is supported. - {Types: []string{services.AWSMatcherRDS, services.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, + {Types: []string{types.AWSMatcherRDS, types.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, // ec2-only matcher's assume role should not be added because it's not supported. - {Types: []string{services.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role5}}, - {Types: []string{services.AWSMatcherRDS, services.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role6, ExternalID: "foo"}}, + {Types: []string{types.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role5}}, + {Types: []string{types.AWSMatcherRDS, types.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role6, ExternalID: "foo"}}, // matcher without assume role should be added to matchers - {Types: []string{services.AWSMatcherElastiCache}}, + {Types: []string{types.AWSMatcherElastiCache}}, }, ResourceMatchers: []services.ResourceMatcher{ // dynamic resources' assume role should be added. @@ -2040,7 +2040,7 @@ func TestExtractTargetConfig(t *testing.T) { assumesAWSRoles: []string{role1, role2, role3, role4, role6, role7}, databases: []*servicecfg.Database{{Name: "db3"}}, awsMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherElastiCache}}, + {Types: []string{types.AWSMatcherElastiCache}}, }, }, }, @@ -2050,9 +2050,9 @@ func TestExtractTargetConfig(t *testing.T) { cfg: &servicecfg.Config{ Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: role2}}, - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: role3, ExternalID: "foo"}}, - {Types: []string{services.AWSMatcherEC2}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: role2}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: role3, ExternalID: "foo"}}, + {Types: []string{types.AWSMatcherEC2}}, }, }, // check that database service resources are not included. @@ -2061,7 +2061,7 @@ func TestExtractTargetConfig(t *testing.T) { {Name: "db3"}, }, AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherElastiCache}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, + {Types: []string{types.AWSMatcherElastiCache}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, }, }, }, @@ -2069,7 +2069,7 @@ func TestExtractTargetConfig(t *testing.T) { // identity field is ignored in want/got diff, see comment in test loop. assumesAWSRoles: []string{role1, role2, role3}, awsMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherEC2}}, + {Types: []string{types.AWSMatcherEC2}}, }, }, }, @@ -2079,7 +2079,7 @@ func TestExtractTargetConfig(t *testing.T) { cfg: &servicecfg.Config{ Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, Databases: servicecfg.DatabasesConfig{ @@ -2087,15 +2087,15 @@ func TestExtractTargetConfig(t *testing.T) { {Name: "db1", AWS: servicecfg.DatabaseAWS{AssumeRoleARN: role2}}, }, AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, - {Types: []string{services.AWSMatcherEC2}}, + {Types: []string{types.AWSMatcherRDS}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, + {Types: []string{types.AWSMatcherEC2}}, }, }, }, want: targetConfig{ // identity field is ignored in want/got diff, see comment in test loop. awsMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherEC2}}, + {Types: []string{types.AWSMatcherEC2}}, }, assumesAWSRoles: []string{role1, role2, role4}, }, @@ -2106,7 +2106,7 @@ func TestExtractTargetConfig(t *testing.T) { cfg: &servicecfg.Config{ Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, Databases: servicecfg.DatabasesConfig{ @@ -2114,7 +2114,7 @@ func TestExtractTargetConfig(t *testing.T) { {Name: "db1", AWS: servicecfg.DatabaseAWS{AssumeRoleARN: role2}}, }, AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS, services.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, + {Types: []string{types.AWSMatcherRDS, types.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role4}}, }, }, }, @@ -2126,12 +2126,12 @@ func TestExtractTargetConfig(t *testing.T) { cfg: &servicecfg.Config{ Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, + {Types: []string{types.AWSMatcherRDSProxy}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}}, }, }, Databases: servicecfg.DatabasesConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS, services.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role1}}, + {Types: []string{types.AWSMatcherRDS, types.AWSMatcherEC2}, AssumeRole: &types.AssumeRole{RoleARN: role1}}, }, }, }, @@ -2146,19 +2146,19 @@ func TestExtractTargetConfig(t *testing.T) { cfg: &servicecfg.Config{ Discovery: servicecfg.DiscoveryConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDSProxy}}, + {Types: []string{types.AWSMatcherRDSProxy}}, }, }, Databases: servicecfg.DatabasesConfig{ AWSMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS, services.AWSMatcherEC2}}, + {Types: []string{types.AWSMatcherRDS, types.AWSMatcherEC2}}, }, }, }, want: targetConfig{ // identity field is ignored in want/got diff, see comment in test loop. awsMatchers: []types.AWSMatcher{ - {Types: []string{services.AWSMatcherRDS, services.AWSMatcherEC2}}, + {Types: []string{types.AWSMatcherRDS, types.AWSMatcherEC2}}, }, }, }, @@ -2204,7 +2204,7 @@ func TestIsTargetAssumeRole(t *testing.T) { "target in matchers": { target: roleTarget, matchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-1"}, AssumeRole: &types.AssumeRole{RoleARN: roleTarget.String()}, }}, @@ -2247,7 +2247,7 @@ func TestIsTargetAssumeRole(t *testing.T) { target: roleTarget, flags: configurators.BootstrapFlags{ForceAssumesRoles: role1}, matchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-west-1"}, AssumeRole: &types.AssumeRole{RoleARN: role1}, }}, diff --git a/lib/defaults/defaults.go b/lib/defaults/defaults.go index 7728fe3b192..61f7a276c18 100644 --- a/lib/defaults/defaults.go +++ b/lib/defaults/defaults.go @@ -890,35 +890,11 @@ func SearchSessionRange(clock clockwork.Clock, fromUTC, toUTC, recordingsSince s } const ( - // AWSInstallerDocument is the name of the default AWS document - // that will be called when executing the SSM command. - AWSInstallerDocument = "TeleportDiscoveryInstaller" - - // AWSAgentlessInstallerDocument is the name of the default AWS document - // that will be called when executing the SSM command . - AWSAgentlessInstallerDocument = "TeleportAgentlessDiscoveryInstaller" - - // IAMInviteTokenName is the name of the default Teleport IAM - // token to use when templating the script to be executed. - IAMInviteTokenName = "aws-discovery-iam-token" - - // SSHDConfigPath is the path to the sshd config file to modify - // when using the agentless installer - SSHDConfigPath = "/etc/ssh/sshd_config" - // HostnameLabel is the name of the label added to the sample SSH config generated by the teleport // node configure command. HostnameLabel = "hostname" ) -// AzureInviteTokenName is the name of the default token to use -// when templating the script to be executed on Azure. -const AzureInviteTokenName = "azure-discovery-token" - -// GCPInviteTokenName is the name of the default token to use -// when templating the script to be executed on GCP. -const GCPInviteTokenName = "gcp-discovery-token" - const ( // FilePermissions are safe default permissions to use when // creating files. diff --git a/lib/services/matchers.go b/lib/services/matchers.go index c18cdea9a09..0b6008e0110 100644 --- a/lib/services/matchers.go +++ b/lib/services/matchers.go @@ -297,103 +297,3 @@ func (m *MatchResourceFilter) IsSimple() bool { m.PredicateExpression == "" && len(m.Kinds) == 0 } - -const ( - // AWSMatcherEC2 is the AWS matcher type for EC2 instances. - AWSMatcherEC2 = "ec2" - // AWSMatcherEKS is the AWS matcher type for AWS Kubernetes. - AWSMatcherEKS = "eks" - // AWSMatcherRDS is the AWS matcher type for RDS databases. - AWSMatcherRDS = "rds" - // AWSMatcherRDSProxy is the AWS matcher type for RDS Proxy databases. - AWSMatcherRDSProxy = "rdsproxy" - // AWSMatcherRedshift is the AWS matcher type for Redshift databases. - AWSMatcherRedshift = "redshift" - // AWSMatcherRedshiftServerless is the AWS matcher type for Redshift Serverless databases. - AWSMatcherRedshiftServerless = "redshift-serverless" - // AWSMatcherElastiCache is the AWS matcher type for ElastiCache databases. - AWSMatcherElastiCache = "elasticache" - // AWSMatcherMemoryDB is the AWS matcher type for MemoryDB databases. - AWSMatcherMemoryDB = "memorydb" - // AWSMatcherOpenSearch is the AWS matcher type for OpenSearch databases. - AWSMatcherOpenSearch = "opensearch" -) - -// SupportedAWSMatchers is list of AWS services currently supported by the -// Teleport discovery service. -var SupportedAWSMatchers = append([]string{ - AWSMatcherEC2, - AWSMatcherEKS, -}, SupportedAWSDatabaseMatchers...) - -// SupportedAWSDatabaseMatchers is a list of the AWS databases currently -// supported by the Teleport discovery service. -var SupportedAWSDatabaseMatchers = []string{ - AWSMatcherRDS, - AWSMatcherRDSProxy, - AWSMatcherRedshift, - AWSMatcherRedshiftServerless, - AWSMatcherElastiCache, - AWSMatcherMemoryDB, - AWSMatcherOpenSearch, -} - -// RequireAWSIAMRolesAsUsersMatchers is a list of the AWS databases that -// require AWS IAM roles as database users. -// IMPORTANT: if you add database matchers for AWS keyspaces, OpenSearch, or -// DynamoDB discovery, add them here and in RequireAWSIAMRolesAsUsers in -// api/types. -var RequireAWSIAMRolesAsUsersMatchers = []string{ - AWSMatcherRedshiftServerless, -} - -const ( - // AzureMatcherVM is the Azure matcher type for Azure VMs. - AzureMatcherVM = "vm" - // AzureMatcherKubernetes is the Azure matcher type for Azure Kubernetes. - AzureMatcherKubernetes = "aks" - // AzureMatcherMySQL is the Azure matcher type for Azure MySQL databases. - AzureMatcherMySQL = "mysql" - // AzureMatcherPostgres is the Azure matcher type for Azure Postgres databases. - AzureMatcherPostgres = "postgres" - // AzureMatcherRedis is the Azure matcher type for Azure Cache for Redis databases. - AzureMatcherRedis = "redis" - // AzureMatcherSQLServer is the Azure matcher type for SQL Server databases. - AzureMatcherSQLServer = "sqlserver" -) - -// SupportedAzureMatchers is list of Azure services currently supported by the -// Teleport discovery service. -var SupportedAzureMatchers = []string{ - AzureMatcherVM, - AzureMatcherKubernetes, - AzureMatcherMySQL, - AzureMatcherPostgres, - AzureMatcherRedis, - AzureMatcherSQLServer, -} - -const ( - // GCPMatcherKubernetes is the GCP matcher type for GCP kubernetes. - GCPMatcherKubernetes = "gke" - // GCPMatcherCompute is the GCP matcher for GCP VMs. - GCPMatcherCompute = "gce" -) - -// SupportedGCPMatchers is list of GCP services currently supported by the -// Teleport discovery service. -var SupportedGCPMatchers = []string{ - GCPMatcherKubernetes, - GCPMatcherCompute, -} - -const ( - // KubernetesMatchersApp is app matcher type for Kubernetes services - KubernetesMatchersApp = "app" -) - -// SupportedKubernetesMatchers is a list of Kubernetes matchers supported by -// Teleport discovery service -var SupportedKubernetesMatchers = []string{ - KubernetesMatchersApp, -} diff --git a/lib/srv/db/watcher_test.go b/lib/srv/db/watcher_test.go index 339ab4b853d..ba07c980fbb 100644 --- a/lib/srv/db/watcher_test.go +++ b/lib/srv/db/watcher_test.go @@ -292,7 +292,7 @@ func TestWatcherCloudFetchers(t *testing.T) { redshiftServerlessDatabase.SetStatusAWS(redshiftServerlessDatabase.GetAWS()) setDiscoveryGroupLabel(redshiftServerlessDatabase, "") redshiftServerlessDatabase.SetOrigin(types.OriginCloud) - discovery.ApplyAWSDatabaseNameSuffix(redshiftServerlessDatabase, services.AWSMatcherRedshiftServerless) + discovery.ApplyAWSDatabaseNameSuffix(redshiftServerlessDatabase, types.AWSMatcherRedshiftServerless) // Test an Azure fetcher. azSQLServer, azSQLServerDatabase := makeAzureSQLServer(t, "discovery-azure", "group") setDiscoveryGroupLabel(azSQLServerDatabase, "") @@ -318,11 +318,11 @@ func TestWatcherCloudFetchers(t *testing.T) { }, AzureMatchers: []types.AzureMatcher{{ Subscriptions: []string{"sub"}, - Types: []string{services.AzureMatcherSQLServer}, + Types: []string{types.AzureMatcherSQLServer}, ResourceTags: types.Labels{types.Wildcard: []string{types.Wildcard}}, }}, AWSMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRDS, services.AWSMatcherRedshiftServerless}, + Types: []string{types.AWSMatcherRDS, types.AWSMatcherRedshiftServerless}, Regions: []string{"us-east-1"}, Tags: types.Labels{types.Wildcard: []string{types.Wildcard}}, }}, @@ -405,6 +405,6 @@ func makeAzureSQLServer(t *testing.T, name, group string) (*armsql.Server, types } database, err := services.NewDatabaseFromAzureSQLServer(server) require.NoError(t, err) - discovery.ApplyAzureDatabaseNameSuffix(database, services.AzureMatcherSQLServer) + discovery.ApplyAzureDatabaseNameSuffix(database, types.AzureMatcherSQLServer) return server, database } diff --git a/lib/srv/discovery/common/renaming.go b/lib/srv/discovery/common/renaming.go index 2709cbb451c..8acc72e7f29 100644 --- a/lib/srv/discovery/common/renaming.go +++ b/lib/srv/discovery/common/renaming.go @@ -22,7 +22,6 @@ import ( "strings" "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/lib/services" ) // ApplyAWSDatabaseNameSuffix applies the AWS Database Discovery name suffix to @@ -76,13 +75,13 @@ func ApplyAzureDatabaseNameSuffix(db types.Database, matcherType string) { // By subtyping the matcher type, we can ensure these names do not collide. func getDBMatcherSubtype(matcherType string, db types.Database) string { switch matcherType { - case services.AWSMatcherRDS: + case types.AWSMatcherRDS: if db.GetAWS().RDS.InstanceID == "" { // distinguish RDS instances from clusters by subtyping the RDS // matcher as "rds-aurora". return "aurora" } - case services.AzureMatcherRedis: + case types.AzureMatcherRedis: if db.GetAzure().Redis.ClusteringPolicy != "" { // distinguish Redis databases from Redis Enterprise database by // subtyping the redis matcher as "redis-enterprise". @@ -103,7 +102,7 @@ func ApplyEKSNameSuffix(cluster types.KubeCluster) { meta := cluster.GetAWSConfig() suffix := makeAWSDiscoverySuffix(kubeClusterNamePartValidator, cluster.GetName(), - services.AWSMatcherEKS, + types.AWSMatcherEKS, "", // no EKS subtype meta.Region, meta.AccountID, @@ -123,7 +122,7 @@ func ApplyAKSNameSuffix(cluster types.KubeCluster) { region, _ := cluster.GetLabel(types.DiscoveryLabelRegion) suffix := makeAzureDiscoverySuffix(kubeClusterNamePartValidator, cluster.GetName(), - services.AzureMatcherKubernetes, + types.AzureMatcherKubernetes, "", // no AKS subtype region, meta.ResourceGroup, @@ -143,7 +142,7 @@ func ApplyGKENameSuffix(cluster types.KubeCluster) { meta := cluster.GetGCPConfig() suffix := makeGCPDiscoverySuffix(kubeClusterNamePartValidator, cluster.GetName(), - services.GCPMatcherKubernetes, + types.GCPMatcherKubernetes, "", // no GKE subtype meta.Location, meta.ProjectID, diff --git a/lib/srv/discovery/common/renaming_test.go b/lib/srv/discovery/common/renaming_test.go index c11f3c4fa9f..1c19fb48f2f 100644 --- a/lib/srv/discovery/common/renaming_test.go +++ b/lib/srv/discovery/common/renaming_test.go @@ -191,7 +191,7 @@ func TestApplyAWSDatabaseNameSuffix(t *testing.T) { resource: database, renameFn: func(r types.ResourceWithLabels) { db := r.(types.Database) - ApplyAWSDatabaseNameSuffix(db, services.AWSMatcherRDS) + ApplyAWSDatabaseNameSuffix(db, types.AWSMatcherRDS) }, originalName: tt.dbName, nameOverrideLabel: overrideLabel, @@ -220,7 +220,7 @@ func TestApplyAzureDatabaseNameSuffix(t *testing.T) { region: "East US", // we normalize regions, so this should become "eastus". resourceGroup: "Some Group", subscriptionID: "11111111-2222-3333-4444-555555555555", - matcherType: services.AzureMatcherMySQL, + matcherType: types.AzureMatcherMySQL, wantRename: "some-db-mysql-eastus-Some-Group-11111111-2222-3333-4444-555555555555", makeDBFunc: makeAzureMySQLFlexDatabase, }, @@ -230,7 +230,7 @@ func TestApplyAzureDatabaseNameSuffix(t *testing.T) { region: "eastus", // use the normalized region. resourceGroup: "(parens are invalid)", subscriptionID: "11111111-2222-3333-4444-555555555555", - matcherType: services.AzureMatcherMySQL, + matcherType: types.AzureMatcherMySQL, wantRename: "some-db-mysql-eastus-11111111-2222-3333-4444-555555555555", makeDBFunc: makeAzureMySQLFlexDatabase, }, @@ -240,7 +240,7 @@ func TestApplyAzureDatabaseNameSuffix(t *testing.T) { region: "eastus", resourceGroup: "Some Group", subscriptionID: "11111111-2222-3333-4444-555555555555", - matcherType: services.AzureMatcherRedis, + matcherType: types.AzureMatcherRedis, wantRename: "some-db-redis-eastus-Some-Group-11111111-2222-3333-4444-555555555555", makeDBFunc: makeAzureRedisDB, }, @@ -250,7 +250,7 @@ func TestApplyAzureDatabaseNameSuffix(t *testing.T) { region: "eastus", resourceGroup: "Some Group", subscriptionID: "11111111-2222-3333-4444-555555555555", - matcherType: services.AzureMatcherRedis, + matcherType: types.AzureMatcherRedis, wantRename: "some-db-redis-enterprise-eastus-Some-Group-11111111-2222-3333-4444-555555555555", makeDBFunc: makeAzureRedisEnterpriseDB, }, diff --git a/lib/srv/discovery/discovery.go b/lib/srv/discovery/discovery.go index 8ac18b2a6c0..3c7beddd4d9 100644 --- a/lib/srv/discovery/discovery.go +++ b/lib/srv/discovery/discovery.go @@ -254,7 +254,7 @@ func New(ctx context.Context, cfg *Config) (*Server, error) { // initAWSWatchers starts AWS resource watchers based on types provided. func (s *Server) initAWSWatchers(matchers []types.AWSMatcher) error { ec2Matchers, otherMatchers := splitMatchers(matchers, func(matcherType string) bool { - return matcherType == services.AWSMatcherEC2 + return matcherType == types.AWSMatcherEC2 }) // start ec2 watchers @@ -302,7 +302,7 @@ func (s *Server) initAWSWatchers(matchers []types.AWSMatcher) error { for _, t := range matcher.Types { for _, region := range matcher.Regions { switch t { - case services.AWSMatcherEKS: + case types.AWSMatcherEKS: client, err := s.CloudClients.GetAWSEKSClient( s.ctx, region, @@ -345,7 +345,7 @@ func (s *Server) initKubeAppWatchers(matchers []types.KubernetesMatcher) error { } for _, matcher := range matchers { - if !slices.Contains(matcher.Types, services.KubernetesMatchersApp) { + if !slices.Contains(matcher.Types, types.KubernetesMatchersApp) { continue } @@ -368,7 +368,7 @@ func (s *Server) initKubeAppWatchers(matchers []types.KubernetesMatcher) error { // initAzureWatchers starts Azure resource watchers based on types provided. func (s *Server) initAzureWatchers(ctx context.Context, matchers []types.AzureMatcher) error { vmMatchers, otherMatchers := splitMatchers(matchers, func(matcherType string) bool { - return matcherType == services.AzureMatcherVM + return matcherType == types.AzureMatcherVM }) // VM watcher. @@ -404,7 +404,7 @@ func (s *Server) initAzureWatchers(ctx context.Context, matchers []types.AzureMa for _, subscription := range subscriptions { for _, t := range matcher.Types { switch t { - case services.AzureMatcherKubernetes: + case types.AzureMatcherKubernetes: kubeClient, err := s.CloudClients.GetAzureKubernetesClient(subscription) if err != nil { return trace.Wrap(err) @@ -436,7 +436,7 @@ func (s *Server) initGCPWatchers(ctx context.Context, matchers []types.GCPMatche } vmMatchers, otherMatchers := splitMatchers(matchers, func(matcherType string) bool { - return matcherType == services.GCPMatcherCompute + return matcherType == types.GCPMatcherCompute }) // VM watcher. @@ -462,7 +462,7 @@ func (s *Server) initGCPWatchers(ctx context.Context, matchers []types.GCPMatche for _, location := range matcher.Locations { for _, t := range matcher.Types { switch t { - case services.GCPMatcherKubernetes: + case types.GCPMatcherKubernetes: fetcher, err := fetchers.NewGKEFetcher(fetchers.GKEFetcherConfig{ Client: kubeClient, Location: location, diff --git a/lib/srv/discovery/discovery_test.go b/lib/srv/discovery/discovery_test.go index f587aa47b4d..6a09297a39f 100644 --- a/lib/srv/discovery/discovery_test.go +++ b/lib/srv/discovery/discovery_test.go @@ -1287,7 +1287,7 @@ func TestDiscoveryDatabase(t *testing.T) { { name: "discover AWS database", awsMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRedshift}, + Types: []string{types.AWSMatcherRedshift}, Tags: map[string]utils.Strings{types.Wildcard: {types.Wildcard}}, Regions: []string{"us-east-1"}, }}, @@ -1297,7 +1297,7 @@ func TestDiscoveryDatabase(t *testing.T) { { name: "discover AWS database with assumed role", awsMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Tags: map[string]utils.Strings{types.Wildcard: {types.Wildcard}}, Regions: []string{"us-west-1"}, AssumeRole: &role, @@ -1308,7 +1308,7 @@ func TestDiscoveryDatabase(t *testing.T) { { name: "discover Azure database", azureMatchers: []types.AzureMatcher{{ - Types: []string{services.AzureMatcherRedis}, + Types: []string{types.AzureMatcherRedis}, ResourceTags: map[string]utils.Strings{types.Wildcard: {types.Wildcard}}, Regions: []string{types.Wildcard}, ResourceGroups: []string{types.Wildcard}, @@ -1335,7 +1335,7 @@ func TestDiscoveryDatabase(t *testing.T) { }), }, awsMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRedshift}, + Types: []string{types.AWSMatcherRedshift}, Tags: map[string]utils.Strings{types.Wildcard: {types.Wildcard}}, Regions: []string{"us-east-1"}, }}, @@ -1354,7 +1354,7 @@ func TestDiscoveryDatabase(t *testing.T) { }), }, awsMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Tags: map[string]utils.Strings{types.Wildcard: {types.Wildcard}}, Regions: []string{"us-west-1"}, AssumeRole: &role, @@ -1374,7 +1374,7 @@ func TestDiscoveryDatabase(t *testing.T) { }), }, awsMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRedshift}, + Types: []string{types.AWSMatcherRedshift}, Tags: map[string]utils.Strings{"do-not-match": {"do-not-match"}}, Regions: []string{"us-east-1"}, }}, @@ -1402,7 +1402,7 @@ func TestDiscoveryDatabase(t *testing.T) { }), }, awsMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRedshift}, + Types: []string{types.AWSMatcherRedshift}, Tags: map[string]utils.Strings{"do-not-match": {"do-not-match"}}, Regions: []string{"us-east-1"}, }}, @@ -1521,7 +1521,7 @@ func makeRDSInstance(t *testing.T, name, region string, discoveryGroup string) ( staticLabels := database.GetStaticLabels() staticLabels[types.TeleportInternalDiscoveryGroupName] = discoveryGroup database.SetStaticLabels(staticLabels) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherRDS) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherRDS) return instance, database } @@ -1543,7 +1543,7 @@ func makeRedshiftCluster(t *testing.T, name, region string, discoveryGroup strin staticLabels := database.GetStaticLabels() staticLabels[types.TeleportInternalDiscoveryGroupName] = discoveryGroup database.SetStaticLabels(staticLabels) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherRedshift) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherRedshift) return cluster, database } @@ -1566,7 +1566,7 @@ func makeAzureRedisServer(t *testing.T, name, subscription, group, region string staticLabels := database.GetStaticLabels() staticLabels[types.TeleportInternalDiscoveryGroupName] = discoveryGroup database.SetStaticLabels(staticLabels) - common.ApplyAzureDatabaseNameSuffix(database, services.AzureMatcherRedis) + common.ApplyAzureDatabaseNameSuffix(database, types.AzureMatcherRedis) return resourceInfo, database } diff --git a/lib/srv/discovery/fetchers/db/aws_elasticache_test.go b/lib/srv/discovery/fetchers/db/aws_elasticache_test.go index b0a3e18e59e..6cc6bcc216c 100644 --- a/lib/srv/discovery/fetchers/db/aws_elasticache_test.go +++ b/lib/srv/discovery/fetchers/db/aws_elasticache_test.go @@ -57,7 +57,7 @@ func TestElastiCacheFetcher(t *testing.T) { TagsByARN: elasticacheTagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherElastiCache, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherElastiCache, "us-east-1", wildcardLabels), wantDatabases: append(elasticacheDatabasesProd, elasticacheDatabasesQA...), }, { @@ -68,7 +68,7 @@ func TestElastiCacheFetcher(t *testing.T) { TagsByARN: elasticacheTagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherElastiCache, "us-east-1", envProdLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherElastiCache, "us-east-1", envProdLabels), wantDatabases: elasticacheDatabasesProd, }, { @@ -79,7 +79,7 @@ func TestElastiCacheFetcher(t *testing.T) { TagsByARN: elasticacheTagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherElastiCache, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherElastiCache, "us-east-1", wildcardLabels), wantDatabases: elasticacheDatabasesProd, }, { @@ -90,7 +90,7 @@ func TestElastiCacheFetcher(t *testing.T) { TagsByARN: elasticacheTagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherElastiCache, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherElastiCache, "us-east-1", wildcardLabels), wantDatabases: elasticacheDatabasesProd, }, } @@ -109,14 +109,14 @@ func makeElastiCacheCluster(t *testing.T, name, region, env string, opts ...func if aws.BoolValue(cluster.ClusterEnabled) { database, err := services.NewDatabaseFromElastiCacheConfigurationEndpoint(cluster, extraLabels) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherElastiCache) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherElastiCache) return cluster, types.Databases{database}, tags } databases, err := services.NewDatabasesFromElastiCacheNodeGroups(cluster, extraLabels) require.NoError(t, err) for _, database := range databases { - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherElastiCache) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherElastiCache) } return cluster, databases, tags } diff --git a/lib/srv/discovery/fetchers/db/aws_memorydb_test.go b/lib/srv/discovery/fetchers/db/aws_memorydb_test.go index 8de7d2df634..4648c33409c 100644 --- a/lib/srv/discovery/fetchers/db/aws_memorydb_test.go +++ b/lib/srv/discovery/fetchers/db/aws_memorydb_test.go @@ -56,7 +56,7 @@ func TestMemoryDBFetcher(t *testing.T) { TagsByARN: memorydbTagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherMemoryDB, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherMemoryDB, "us-east-1", wildcardLabels), wantDatabases: types.Databases{memorydbDatabaseProd, memorydbDatabaseTest}, }, { @@ -67,7 +67,7 @@ func TestMemoryDBFetcher(t *testing.T) { TagsByARN: memorydbTagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherMemoryDB, "us-east-1", envProdLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherMemoryDB, "us-east-1", envProdLabels), wantDatabases: types.Databases{memorydbDatabaseProd}, }, { @@ -78,7 +78,7 @@ func TestMemoryDBFetcher(t *testing.T) { TagsByARN: memorydbTagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherMemoryDB, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherMemoryDB, "us-east-1", wildcardLabels), wantDatabases: types.Databases{memorydbDatabaseProd}, }, { @@ -89,7 +89,7 @@ func TestMemoryDBFetcher(t *testing.T) { TagsByARN: memorydbTagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherMemoryDB, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherMemoryDB, "us-east-1", wildcardLabels), wantDatabases: types.Databases{memorydbDatabaseProd}, }, } @@ -107,6 +107,6 @@ func makeMemoryDBCluster(t *testing.T, name, region, env string, opts ...func(*m database, err := services.NewDatabaseFromMemoryDBCluster(cluster, extraLabels) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherMemoryDB) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherMemoryDB) return cluster, database, tags } diff --git a/lib/srv/discovery/fetchers/db/aws_opensearch_test.go b/lib/srv/discovery/fetchers/db/aws_opensearch_test.go index e5b7464c780..3f7317a6c43 100644 --- a/lib/srv/discovery/fetchers/db/aws_opensearch_test.go +++ b/lib/srv/discovery/fetchers/db/aws_opensearch_test.go @@ -52,7 +52,7 @@ func TestOpenSearchFetcher(t *testing.T) { TagsByARN: tags, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherOpenSearch, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherOpenSearch, "us-east-1", wildcardLabels), wantDatabases: append(append(types.Databases{}, prodDBs...), testDBs...), }, { @@ -63,7 +63,7 @@ func TestOpenSearchFetcher(t *testing.T) { TagsByARN: tags, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherOpenSearch, "us-east-1", envProdLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherOpenSearch, "us-east-1", envProdLabels), wantDatabases: prodDBs, }, { @@ -74,7 +74,7 @@ func TestOpenSearchFetcher(t *testing.T) { TagsByARN: tags, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherOpenSearch, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherOpenSearch, "us-east-1", wildcardLabels), wantDatabases: prodDBs, }, { @@ -85,7 +85,7 @@ func TestOpenSearchFetcher(t *testing.T) { TagsByARN: tags, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherOpenSearch, "us-east-1", map[string]string{"endpoint-type": apiawsutils.OpenSearchDefaultEndpoint}), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherOpenSearch, "us-east-1", map[string]string{"endpoint-type": apiawsutils.OpenSearchDefaultEndpoint}), wantDatabases: types.Databases{prodDBs[0], prodCustomDBs[0]}, // domain with custom endpoint will still have default endpoint populated }, { @@ -96,7 +96,7 @@ func TestOpenSearchFetcher(t *testing.T) { TagsByARN: tags, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherOpenSearch, "us-east-1", map[string]string{"endpoint-type": apiawsutils.OpenSearchCustomEndpoint}), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherOpenSearch, "us-east-1", map[string]string{"endpoint-type": apiawsutils.OpenSearchCustomEndpoint}), wantDatabases: types.Databases{prodCustomDBs[1]}, // domain with custom endpoint will still have default endpoint populated }, { @@ -107,7 +107,7 @@ func TestOpenSearchFetcher(t *testing.T) { TagsByARN: tags, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherOpenSearch, "us-east-1", map[string]string{"endpoint-type": apiawsutils.OpenSearchVPCEndpoint}), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherOpenSearch, "us-east-1", map[string]string{"endpoint-type": apiawsutils.OpenSearchVPCEndpoint}), wantDatabases: prodVPCDBs, }, } @@ -128,7 +128,7 @@ func makeOpenSearchDomain(t *testing.T, tagMap map[string][]*opensearchservice.T require.NoError(t, err) for _, db := range databases { - common.ApplyAWSDatabaseNameSuffix(db, services.AWSMatcherOpenSearch) + common.ApplyAWSDatabaseNameSuffix(db, types.AWSMatcherOpenSearch) } return domain, databases } diff --git a/lib/srv/discovery/fetchers/db/aws_rds_proxy_test.go b/lib/srv/discovery/fetchers/db/aws_rds_proxy_test.go index f0f8ce91546..9ca72239413 100644 --- a/lib/srv/discovery/fetchers/db/aws_rds_proxy_test.go +++ b/lib/srv/discovery/fetchers/db/aws_rds_proxy_test.go @@ -47,7 +47,7 @@ func TestRDSDBProxyFetcher(t *testing.T) { DBProxyTargetPort: 9999, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherRDSProxy, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherRDSProxy, "us-east-1", wildcardLabels), wantDatabases: types.Databases{rdsProxyDatabaseVpc1, rdsProxyDatabaseVpc2, rdsProxyEndpointDatabaseVpc1, rdsProxyEndpointDatabaseVpc2}, }, { @@ -59,7 +59,7 @@ func TestRDSDBProxyFetcher(t *testing.T) { DBProxyTargetPort: 9999, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherRDSProxy, "us-east-1", map[string]string{"vpc-id": "vpc1"}), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherRDSProxy, "us-east-1", map[string]string{"vpc-id": "vpc1"}), wantDatabases: types.Databases{rdsProxyDatabaseVpc1, rdsProxyEndpointDatabaseVpc1}, }, } @@ -70,7 +70,7 @@ func makeRDSProxy(t *testing.T, name, region, vpcID string) (*rds.DBProxy, types rdsProxy := mocks.RDSProxy(name, region, vpcID) rdsProxyDatabase, err := services.NewDatabaseFromRDSProxy(rdsProxy, 9999, nil) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(rdsProxyDatabase, services.AWSMatcherRDSProxy) + common.ApplyAWSDatabaseNameSuffix(rdsProxyDatabase, types.AWSMatcherRDSProxy) return rdsProxy, rdsProxyDatabase } @@ -78,6 +78,6 @@ func makeRDSProxyCustomEndpoint(t *testing.T, rdsProxy *rds.DBProxy, name, regio rdsProxyEndpoint := mocks.RDSProxyCustomEndpoint(rdsProxy, name, region) rdsProxyEndpointDatabase, err := services.NewDatabaseFromRDSProxyCustomEndpoint(rdsProxy, rdsProxyEndpoint, 9999, nil) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(rdsProxyEndpointDatabase, services.AWSMatcherRDSProxy) + common.ApplyAWSDatabaseNameSuffix(rdsProxyEndpointDatabase, types.AWSMatcherRDSProxy) return rdsProxyEndpoint, rdsProxyEndpointDatabase } diff --git a/lib/srv/discovery/fetchers/db/aws_rds_test.go b/lib/srv/discovery/fetchers/db/aws_rds_test.go index 77f4a288021..9816919ca20 100644 --- a/lib/srv/discovery/fetchers/db/aws_rds_test.go +++ b/lib/srv/discovery/fetchers/db/aws_rds_test.go @@ -72,12 +72,12 @@ func TestRDSFetchers(t *testing.T) { }, inputMatchers: []types.AWSMatcher{ { - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-1"}, Tags: toTypeLabels(wildcardLabels), }, { - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-2"}, Tags: toTypeLabels(wildcardLabels), }, @@ -105,12 +105,12 @@ func TestRDSFetchers(t *testing.T) { }, inputMatchers: []types.AWSMatcher{ { - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-1"}, Tags: toTypeLabels(envProdLabels), }, { - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-2"}, Tags: toTypeLabels(envDevLabels), }, @@ -138,12 +138,12 @@ func TestRDSFetchers(t *testing.T) { }, inputMatchers: []types.AWSMatcher{ { - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-1"}, Tags: toTypeLabels(wildcardLabels), }, { - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-2"}, Tags: toTypeLabels(wildcardLabels), }, @@ -161,7 +161,7 @@ func TestRDSFetchers(t *testing.T) { }, }, inputMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-1"}, Tags: toTypeLabels(wildcardLabels), }}, @@ -177,7 +177,7 @@ func TestRDSFetchers(t *testing.T) { }, }, inputMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-1"}, Tags: toTypeLabels(wildcardLabels), }}, @@ -192,7 +192,7 @@ func TestRDSFetchers(t *testing.T) { }, }, inputMatchers: []types.AWSMatcher{{ - Types: []string{services.AWSMatcherRDS}, + Types: []string{types.AWSMatcherRDS}, Regions: []string{"us-east-1"}, Tags: toTypeLabels(wildcardLabels), }}, @@ -206,7 +206,7 @@ func makeRDSInstance(t *testing.T, name, region string, labels map[string]string instance := mocks.RDSInstance(name, region, labels, opts...) database, err := services.NewDatabaseFromRDSInstance(instance) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherRDS) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherRDS) return instance, database } @@ -214,7 +214,7 @@ func makeRDSCluster(t *testing.T, name, region string, labels map[string]string, cluster := mocks.RDSCluster(name, region, labels, opts...) database, err := services.NewDatabaseFromRDSCluster(cluster) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherRDS) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherRDS) return cluster, database } @@ -250,7 +250,7 @@ func makeRDSClusterWithExtraEndpoints(t *testing.T, name, region string, labels databases = append(databases, customDatabases...) for _, db := range databases { - common.ApplyAWSDatabaseNameSuffix(db, services.AWSMatcherRDS) + common.ApplyAWSDatabaseNameSuffix(db, types.AWSMatcherRDS) } return cluster, databases } diff --git a/lib/srv/discovery/fetchers/db/aws_redshift_serverless_test.go b/lib/srv/discovery/fetchers/db/aws_redshift_serverless_test.go index d2383d19d57..8f8d432f1fc 100644 --- a/lib/srv/discovery/fetchers/db/aws_redshift_serverless_test.go +++ b/lib/srv/discovery/fetchers/db/aws_redshift_serverless_test.go @@ -58,7 +58,7 @@ func TestRedshiftServerlessFetcher(t *testing.T) { TagsByARN: tagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherRedshiftServerless, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherRedshiftServerless, "us-east-1", wildcardLabels), wantDatabases: types.Databases{workgroupProdDB, workgroupDevDB, endpointProdDB, endpointProdDev}, }, { @@ -70,7 +70,7 @@ func TestRedshiftServerlessFetcher(t *testing.T) { TagsByARN: tagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherRedshiftServerless, "us-east-1", envProdLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherRedshiftServerless, "us-east-1", envProdLabels), wantDatabases: types.Databases{workgroupProdDB, endpointProdDB}, }, { @@ -82,7 +82,7 @@ func TestRedshiftServerlessFetcher(t *testing.T) { TagsByARN: tagsByARN, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherRedshiftServerless, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherRedshiftServerless, "us-east-1", wildcardLabels), wantDatabases: types.Databases{workgroupProdDB}, }, } @@ -94,7 +94,7 @@ func makeRedshiftServerlessWorkgroup(t *testing.T, name, region string, labels m tags := libcloudaws.LabelsToTags[redshiftserverless.Tag](labels) database, err := services.NewDatabaseFromRedshiftServerlessWorkgroup(workgroup, tags) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherRedshiftServerless) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherRedshiftServerless) return workgroup, database } @@ -103,6 +103,6 @@ func makeRedshiftServerlessEndpoint(t *testing.T, workgroup *redshiftserverless. tags := libcloudaws.LabelsToTags[redshiftserverless.Tag](labels) database, err := services.NewDatabaseFromRedshiftServerlessVPCEndpoint(endpoint, workgroup, tags) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherRedshiftServerless) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherRedshiftServerless) return endpoint, database } diff --git a/lib/srv/discovery/fetchers/db/aws_redshift_test.go b/lib/srv/discovery/fetchers/db/aws_redshift_test.go index 46636aa76c4..ae4ebeec04f 100644 --- a/lib/srv/discovery/fetchers/db/aws_redshift_test.go +++ b/lib/srv/discovery/fetchers/db/aws_redshift_test.go @@ -46,7 +46,7 @@ func TestRedshiftFetcher(t *testing.T) { Clusters: []*redshift.Cluster{redshiftUse1Prod, redshiftUse1Dev}, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherRedshift, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherRedshift, "us-east-1", wildcardLabels), wantDatabases: types.Databases{redshiftDatabaseUse1Prod, redshiftDatabaseUse1Dev}, }, { @@ -56,7 +56,7 @@ func TestRedshiftFetcher(t *testing.T) { Clusters: []*redshift.Cluster{redshiftUse1Prod, redshiftUse1Dev}, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherRedshift, "us-east-1", envProdLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherRedshift, "us-east-1", envProdLabels), wantDatabases: types.Databases{redshiftDatabaseUse1Prod}, }, { @@ -66,7 +66,7 @@ func TestRedshiftFetcher(t *testing.T) { Clusters: []*redshift.Cluster{redshiftUse1Prod, redshiftUse1Unavailable, redshiftUse1UnknownStatus}, }, }, - inputMatchers: makeAWSMatchersForType(services.AWSMatcherRedshift, "us-east-1", wildcardLabels), + inputMatchers: makeAWSMatchersForType(types.AWSMatcherRedshift, "us-east-1", wildcardLabels), wantDatabases: types.Databases{redshiftDatabaseUse1Prod, redshiftDatabaseUnknownStatus}, }, } @@ -78,7 +78,7 @@ func makeRedshiftCluster(t *testing.T, region, env string, opts ...func(*redshif database, err := services.NewDatabaseFromRedshiftCluster(cluster) require.NoError(t, err) - common.ApplyAWSDatabaseNameSuffix(database, services.AWSMatcherRedshift) + common.ApplyAWSDatabaseNameSuffix(database, types.AWSMatcherRedshift) return cluster, database } diff --git a/lib/srv/discovery/fetchers/db/azure_dbserver.go b/lib/srv/discovery/fetchers/db/azure_dbserver.go index 8247527c2ff..056524f5332 100644 --- a/lib/srv/discovery/fetchers/db/azure_dbserver.go +++ b/lib/srv/discovery/fetchers/db/azure_dbserver.go @@ -41,10 +41,10 @@ type azureDBServerPlugin struct{} func (p *azureDBServerPlugin) GetListClient(cfg *azureFetcherConfig, subID string) (azure.DBServersClient, error) { switch cfg.Type { - case services.AzureMatcherMySQL: + case types.AzureMatcherMySQL: client, err := cfg.AzureClients.GetAzureMySQLClient(subID) return client, trace.Wrap(err) - case services.AzureMatcherPostgres: + case types.AzureMatcherPostgres: client, err := cfg.AzureClients.GetAzurePostgresClient(subID) return client, trace.Wrap(err) default: diff --git a/lib/srv/discovery/fetchers/db/azure_dbserver_test.go b/lib/srv/discovery/fetchers/db/azure_dbserver_test.go index 99f96f5eb1c..b34d1f40a43 100644 --- a/lib/srv/discovery/fetchers/db/azure_dbserver_test.go +++ b/lib/srv/discovery/fetchers/db/azure_dbserver_test.go @@ -83,7 +83,7 @@ func TestAzureDBServerFetchers(t *testing.T) { { Subscriptions: []string{subscription1}, ResourceGroups: []string{group1}, - Types: []string{services.AzureMatcherMySQL, services.AzureMatcherPostgres}, + Types: []string{types.AzureMatcherMySQL, types.AzureMatcherPostgres}, Regions: []string{eastus}, ResourceTags: types.Labels{"env": []string{"prod"}}, }, @@ -121,7 +121,7 @@ func TestAzureDBServerFetchers(t *testing.T) { { Subscriptions: []string{"*"}, ResourceGroups: []string{"*"}, - Types: []string{services.AzureMatcherMySQL, services.AzureMatcherPostgres}, + Types: []string{types.AzureMatcherMySQL, types.AzureMatcherPostgres}, Regions: []string{"*"}, ResourceTags: types.Labels{"env": []string{"prod"}}, }, @@ -161,7 +161,7 @@ func TestAzureDBServerFetchers(t *testing.T) { { Subscriptions: []string{subscription1}, ResourceGroups: []string{"*"}, - Types: []string{services.AzureMatcherMySQL, services.AzureMatcherPostgres}, + Types: []string{types.AzureMatcherMySQL, types.AzureMatcherPostgres}, Regions: []string{eastus}, ResourceTags: types.Labels{"*": []string{"*"}}, }, @@ -195,7 +195,7 @@ func TestAzureDBServerFetchers(t *testing.T) { { Subscriptions: []string{subscription1}, ResourceGroups: []string{"*"}, - Types: []string{services.AzureMatcherMySQL, services.AzureMatcherPostgres}, + Types: []string{types.AzureMatcherMySQL, types.AzureMatcherPostgres}, Regions: []string{eastus}, ResourceTags: types.Labels{"*": []string{"*"}}, }, @@ -230,7 +230,7 @@ func TestAzureDBServerFetchers(t *testing.T) { { Subscriptions: []string{subscription1, subscription2}, ResourceGroups: []string{"*"}, - Types: []string{services.AzureMatcherMySQL, services.AzureMatcherPostgres}, + Types: []string{types.AzureMatcherMySQL, types.AzureMatcherPostgres}, Regions: []string{eastus, westus}, ResourceTags: types.Labels{"*": []string{"*"}}, }, @@ -269,7 +269,7 @@ func TestAzureDBServerFetchers(t *testing.T) { { Subscriptions: []string{subscription1}, ResourceGroups: []string{"foobar", group1, "baz"}, - Types: []string{services.AzureMatcherMySQL, services.AzureMatcherPostgres}, + Types: []string{types.AzureMatcherMySQL, types.AzureMatcherPostgres}, Regions: []string{eastus, westus}, ResourceTags: types.Labels{"*": []string{"*"}}, }, @@ -346,7 +346,7 @@ func makeAzureMySQLServer(t *testing.T, name, subscription, group, region string database, err := services.NewDatabaseFromAzureServer(azureDBServer) require.NoError(t, err) - common.ApplyAzureDatabaseNameSuffix(database, services.AzureMatcherMySQL) + common.ApplyAzureDatabaseNameSuffix(database, types.AzureMatcherMySQL) return server, database } @@ -382,7 +382,7 @@ func makeAzurePostgresServer(t *testing.T, name, subscription, group, region str database, err := services.NewDatabaseFromAzureServer(azureDBServer) require.NoError(t, err) - common.ApplyAzureDatabaseNameSuffix(database, services.AzureMatcherPostgres) + common.ApplyAzureDatabaseNameSuffix(database, types.AzureMatcherPostgres) return server, database } diff --git a/lib/srv/discovery/fetchers/db/azure_mysql_flex_test.go b/lib/srv/discovery/fetchers/db/azure_mysql_flex_test.go index 0f6c8220839..8be823427c1 100644 --- a/lib/srv/discovery/fetchers/db/azure_mysql_flex_test.go +++ b/lib/srv/discovery/fetchers/db/azure_mysql_flex_test.go @@ -37,7 +37,7 @@ func TestAzureMySQLFlexFetchers(t *testing.T) { azureSub := makeAzureSubscription(t, "sub123") azMySQLFlexServer, azMySQLFlexDB := makeAzureMySQLFlexServer(t, "mysql-flex", "sub123", "group 1", "East US", map[string]string{"env": "prod"}) azureMatchers := []types.AzureMatcher{{ - Types: []string{services.AzureMatcherMySQL}, + Types: []string{types.AzureMatcherMySQL}, ResourceTags: types.Labels{"env": []string{"prod"}}, Regions: []string{"eastus"}, }} @@ -87,6 +87,6 @@ func makeAzureMySQLFlexServer(t *testing.T, name, subscription, group, region st } database, err := services.NewDatabaseFromAzureMySQLFlexServer(server) require.NoError(t, err) - common.ApplyAzureDatabaseNameSuffix(database, services.AzureMatcherMySQL) + common.ApplyAzureDatabaseNameSuffix(database, types.AzureMatcherMySQL) return server, database } diff --git a/lib/srv/discovery/fetchers/db/azure_postgres_flex_test.go b/lib/srv/discovery/fetchers/db/azure_postgres_flex_test.go index af3e4956529..ad2ee438a68 100644 --- a/lib/srv/discovery/fetchers/db/azure_postgres_flex_test.go +++ b/lib/srv/discovery/fetchers/db/azure_postgres_flex_test.go @@ -37,7 +37,7 @@ func TestAzurePostgresFlexFetchers(t *testing.T) { azureSub := makeAzureSubscription(t, "sub123") azPostgresFlexServer, azPostgresFlexDB := makeAzurePostgresFlexServer(t, "postgres-flex", "sub123", "group 1", "East US", map[string]string{"env": "prod"}) azureMatchers := []types.AzureMatcher{{ - Types: []string{services.AzureMatcherPostgres}, + Types: []string{types.AzureMatcherPostgres}, ResourceTags: types.Labels{"env": []string{"prod"}}, Regions: []string{"eastus"}, }} @@ -87,6 +87,6 @@ func makeAzurePostgresFlexServer(t *testing.T, name, subscription, group, region } database, err := services.NewDatabaseFromAzurePostgresFlexServer(server) require.NoError(t, err) - common.ApplyAzureDatabaseNameSuffix(database, services.AzureMatcherPostgres) + common.ApplyAzureDatabaseNameSuffix(database, types.AzureMatcherPostgres) return server, database } diff --git a/lib/srv/discovery/fetchers/db/azure_redis_test.go b/lib/srv/discovery/fetchers/db/azure_redis_test.go index 3966c36aad2..3cafe010c90 100644 --- a/lib/srv/discovery/fetchers/db/azure_redis_test.go +++ b/lib/srv/discovery/fetchers/db/azure_redis_test.go @@ -47,7 +47,7 @@ func TestAzureRedisFetchers(t *testing.T) { azRedisEnterpriseCluster, azRedisEnterpriseDatabase, azRedisEnterpriseDB := makeAzureRedisEnterpriseCluster(t, "redis-enterprise", "sub", "group", "eastus", map[string]string{"env": "prod"}) azureMatchers := []types.AzureMatcher{{ - Types: []string{services.AzureMatcherRedis}, + Types: []string{types.AzureMatcherRedis}, ResourceTags: types.Labels{"env": []string{"prod"}}, Regions: []string{"eastus"}, }} @@ -88,7 +88,7 @@ func makeAzureRedisServer(t *testing.T, name, subscription, group, region string database, err := services.NewDatabaseFromAzureRedis(resourceInfo) require.NoError(t, err) - common.ApplyAzureDatabaseNameSuffix(database, services.AzureMatcherRedis) + common.ApplyAzureDatabaseNameSuffix(database, types.AzureMatcherRedis) return resourceInfo, database } @@ -115,6 +115,6 @@ func makeAzureRedisEnterpriseCluster(t *testing.T, cluster, subscription, group, database, err := services.NewDatabaseFromAzureRedisEnterprise(armCluster, armDatabase) require.NoError(t, err) - common.ApplyAzureDatabaseNameSuffix(database, services.AzureMatcherRedis) + common.ApplyAzureDatabaseNameSuffix(database, types.AzureMatcherRedis) return armCluster, armDatabase, database } diff --git a/lib/srv/discovery/fetchers/db/db.go b/lib/srv/discovery/fetchers/db/db.go index 2a756db943b..0105da1f0c3 100644 --- a/lib/srv/discovery/fetchers/db/db.go +++ b/lib/srv/discovery/fetchers/db/db.go @@ -34,20 +34,20 @@ type makeAzureFetcherFunc func(azureFetcherConfig) (common.Fetcher, error) var ( makeAWSFetcherFuncs = map[string][]makeAWSFetcherFunc{ - services.AWSMatcherRDS: {newRDSDBInstancesFetcher, newRDSAuroraClustersFetcher}, - services.AWSMatcherRDSProxy: {newRDSDBProxyFetcher}, - services.AWSMatcherRedshift: {newRedshiftFetcher}, - services.AWSMatcherRedshiftServerless: {newRedshiftServerlessFetcher}, - services.AWSMatcherElastiCache: {newElastiCacheFetcher}, - services.AWSMatcherMemoryDB: {newMemoryDBFetcher}, - services.AWSMatcherOpenSearch: {newOpenSearchFetcher}, + types.AWSMatcherRDS: {newRDSDBInstancesFetcher, newRDSAuroraClustersFetcher}, + types.AWSMatcherRDSProxy: {newRDSDBProxyFetcher}, + types.AWSMatcherRedshift: {newRedshiftFetcher}, + types.AWSMatcherRedshiftServerless: {newRedshiftServerlessFetcher}, + types.AWSMatcherElastiCache: {newElastiCacheFetcher}, + types.AWSMatcherMemoryDB: {newMemoryDBFetcher}, + types.AWSMatcherOpenSearch: {newOpenSearchFetcher}, } makeAzureFetcherFuncs = map[string][]makeAzureFetcherFunc{ - services.AzureMatcherMySQL: {newAzureMySQLFetcher, newAzureMySQLFlexServerFetcher}, - services.AzureMatcherPostgres: {newAzurePostgresFetcher, newAzurePostgresFlexServerFetcher}, - services.AzureMatcherRedis: {newAzureRedisFetcher, newAzureRedisEnterpriseFetcher}, - services.AzureMatcherSQLServer: {newAzureSQLServerFetcher, newAzureManagedSQLServerFetcher}, + types.AzureMatcherMySQL: {newAzureMySQLFetcher, newAzureMySQLFlexServerFetcher}, + types.AzureMatcherPostgres: {newAzurePostgresFetcher, newAzurePostgresFlexServerFetcher}, + types.AzureMatcherRedis: {newAzureRedisFetcher, newAzureRedisEnterpriseFetcher}, + types.AzureMatcherSQLServer: {newAzureSQLServerFetcher, newAzureManagedSQLServerFetcher}, } ) diff --git a/lib/srv/discovery/fetchers/kube_services.go b/lib/srv/discovery/fetchers/kube_services.go index 2d204752474..a68b3f039ed 100644 --- a/lib/srv/discovery/fetchers/kube_services.go +++ b/lib/srv/discovery/fetchers/kube_services.go @@ -166,7 +166,7 @@ func (f *KubeAppFetcher) Get(ctx context.Context) (types.ResourcesWithLabels, er service := service // Skip service if it has type annotation and it's not 'app' - if v, ok := service.GetAnnotations()[types.DiscoveryTypeLabel]; ok && v != services.KubernetesMatchersApp { + if v, ok := service.GetAnnotations()[types.DiscoveryTypeLabel]; ok && v != types.KubernetesMatchersApp { continue } diff --git a/lib/srv/server/ec2_watcher.go b/lib/srv/server/ec2_watcher.go index 86afb3417d2..4f76423bcef 100644 --- a/lib/srv/server/ec2_watcher.go +++ b/lib/srv/server/ec2_watcher.go @@ -31,7 +31,6 @@ import ( "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/cloud" awslib "github.com/gravitational/teleport/lib/cloud/aws" - "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/labels" ) @@ -131,7 +130,7 @@ func WithPollInterval(interval time.Duration) Option { // MakeEvents generates ResourceCreateEvents for these instances. func (instances *EC2Instances) MakeEvents() map[string]*usageeventsv1.ResourceCreateEvent { resourceType := types.DiscoveredResourceNode - if instances.DocumentName == defaults.AWSAgentlessInstallerDocument { + if instances.DocumentName == types.AWSAgentlessInstallerDocument { resourceType = types.DiscoveredResourceAgentlessNode } events := make(map[string]*usageeventsv1.ResourceCreateEvent, len(instances.Instances)) diff --git a/lib/utils/aws/aws.go b/lib/utils/aws/aws.go index 5a1e6339278..be9d5365f68 100644 --- a/lib/utils/aws/aws.go +++ b/lib/utils/aws/aws.go @@ -370,13 +370,13 @@ func BuildRoleARN(username, region, accountID string) (string, error) { if !IsPartialRoleARN(resource) { resource = fmt.Sprintf("role/%s", username) } - roleARN := &arn.ARN{ + roleARN := arn.ARN{ Partition: partition, Service: iam.ServiceName, AccountID: accountID, Resource: resource, } - if err := checkRoleARN(roleARN); err != nil { + if err := apiawsutils.CheckRoleARN(roleARN.String()); err != nil { return "", trace.Wrap(err) } return roleARN.String(), nil