Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,16 @@ func applyDatabasesConfig(fc *FileConfig, cfg *service.Config) error {
Tags: matcher.Tags,
})
}
for _, matcher := range fc.Databases.AzureMatchers {
cfg.Databases.AzureMatchers = append(cfg.Databases.AzureMatchers,
services.AzureMatcher{
Subscriptions: matcher.Subscriptions,
ResourceGroups: matcher.ResourceGroups,
Types: matcher.Types,
Regions: matcher.Regions,
ResourceTags: matcher.ResourceTags,
})
}
for _, database := range fc.Databases.Databases {
staticLabels := make(map[string]string)
if database.StaticLabels != nil {
Expand Down
87 changes: 86 additions & 1 deletion lib/config/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func TestConfigReading(t *testing.T) {
require.True(t, conf.SSH.Enabled())
require.False(t, conf.Kube.Enabled())

// static config
// good config
conf, err = ReadFromFile(testConfigs.configFile)
require.NoError(t, err)
require.Empty(t, cmp.Diff(conf, &FileConfig{
Expand Down Expand Up @@ -419,6 +419,35 @@ func TestConfigReading(t *testing.T) {
},
},
},
AzureMatchers: []AzureMatcher{
{
Subscriptions: []string{"sub1", "sub2"},
ResourceGroups: []string{"rg1", "rg2"},
Types: []string{"mysql"},
Regions: []string{"eastus", "westus"},
ResourceTags: map[string]apiutils.Strings{
"a": {"b"},
},
},
{
Subscriptions: []string{"sub3", "sub4"},
ResourceGroups: []string{"rg3", "rg4"},
Types: []string{"postgres"},
Regions: []string{"centralus"},
ResourceTags: map[string]apiutils.Strings{
"c": {"d"},
},
},
{
Subscriptions: nil,
ResourceGroups: nil,
Types: []string{"mysql", "postgres"},
Regions: []string{"centralus"},
ResourceTags: map[string]apiutils.Strings{
"e": {"f"},
},
},
},
},
Metrics: Metrics{
Service: Service{
Expand Down Expand Up @@ -756,6 +785,29 @@ SREzU8onbBsjMg9QDiSf5oJLKvd/Ren+zGY7
require.Equal(t, 1, *cfg.Auth.KeyStore.SlotNumber)
require.Equal(t, "example_pin", cfg.Auth.KeyStore.Pin)
require.ElementsMatch(t, []string{"ca-pin-from-string", "ca-pin-from-file1", "ca-pin-from-file2"}, cfg.CAPins)

require.True(t, cfg.Databases.Enabled)
require.Empty(t, cmp.Diff(cfg.Databases.AzureMatchers,
[]services.AzureMatcher{
{
Subscriptions: []string{"sub1", "sub2"},
ResourceGroups: []string{"group1", "group2"},
Types: []string{"postgres", "mysql"},
Regions: []string{"eastus", "centralus"},
ResourceTags: map[string]apiutils.Strings{
"a": {"b"},
},
},
{
Subscriptions: nil,
ResourceGroups: nil,
Types: []string{"postgres", "mysql"},
Regions: []string{"westus"},
ResourceTags: map[string]apiutils.Strings{
"c": {"d"},
},
},
}))
}

// TestApplyConfigNoneEnabled makes sure that if a section is not enabled,
Expand Down Expand Up @@ -1276,6 +1328,33 @@ func makeConfigFixture() string {
Tags: map[string]apiutils.Strings{"c": {"d"}},
},
}
conf.Databases.AzureMatchers = []AzureMatcher{
{
Subscriptions: []string{"sub1", "sub2"},
ResourceGroups: []string{"rg1", "rg2"},
Types: []string{"mysql"},
Regions: []string{"eastus", "westus"},
ResourceTags: map[string]apiutils.Strings{
"a": {"b"},
},
},
{
Subscriptions: []string{"sub3", "sub4"},
ResourceGroups: []string{"rg3", "rg4"},
Types: []string{"postgres"},
Regions: []string{"centralus"},
ResourceTags: map[string]apiutils.Strings{
"c": {"d"},
},
},
{
Types: []string{"mysql", "postgres"},
Regions: []string{"centralus"},
ResourceTags: map[string]apiutils.Strings{
"e": {"f"},
},
},
}

// Metrics service.
conf.Metrics.EnabledFlag = "yes"
Expand Down Expand Up @@ -1934,6 +2013,12 @@ db_service:
regions: ["us-east-1", "us-west-1"]
tags:
'*': '*'
azure:
- subscriptions: ["foo", "bar"]
types: ["mysql", "postgres"]
regions: ["eastus", "westus"]
tags:
'*': '*'
databases:
- name: foo
protocol: postgres
Expand Down
16 changes: 16 additions & 0 deletions lib/config/fileconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,8 @@ type Databases struct {
ResourceMatchers []ResourceMatcher `yaml:"resources,omitempty"`
// AWSMatchers match AWS hosted databases.
AWSMatchers []AWSMatcher `yaml:"aws,omitempty"`
// AzureMatchers match Azure hosted databases.
AzureMatchers []AzureMatcher `yaml:"azure,omitempty"`
}

// ResourceMatcher matches cluster resources.
Expand All @@ -1193,6 +1195,20 @@ type AWSMatcher struct {
Tags map[string]apiutils.Strings `yaml:"tags,omitempty"`
}

// AzureMatcher matches Azure databases.
type AzureMatcher struct {
// Subscriptions are Azure subscriptions to query for resources.
Subscriptions []string `yaml:"subscriptions,omitempty"`
// ResourceGroups are Azure resource groups to query for resources.
ResourceGroups []string `yaml:"resource_groups,omitempty"`
// Types are Azure database types to match: "mysql", "postgres"
Types []string `yaml:"types,omitempty"`
// Regions are Azure locations to match for databases.
Regions []string `yaml:"regions,omitempty"`
// ResourceTags are Azure tags on resources to match.
ResourceTags map[string]apiutils.Strings `yaml:"tags,omitempty"`
}

// Database represents a single database proxied by the service.
type Database struct {
// Name is the name for the database proxy service.
Expand Down
17 changes: 17 additions & 0 deletions lib/config/testdata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,23 @@ proxy_service:
mysql_public_addr: mysql.example:3306
mongo_listen_addr: webhost:27017
mongo_public_addr: mongo.example:27017

db_service:
enabled: yes
resources:
- labels:
"*": "*"
azure:
- subscriptions: ["sub1", "sub2"]
resource_groups: ["group1", "group2"]
types: ["postgres", "mysql"]
regions: ["eastus", "centralus"]
tags:
"a": "b"
- types: ["postgres", "mysql"]
regions: ["westus"]
tags:
"c": "d"
`

// NoServicesConfigString is a configuration file with no services enabled
Expand Down
2 changes: 2 additions & 0 deletions lib/service/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,8 @@ type DatabasesConfig struct {
ResourceMatchers []services.ResourceMatcher
// AWSMatchers match AWS hosted databases.
AWSMatchers []services.AWSMatcher
// AzureMatchers match Azure hosted databases.
AzureMatchers []services.AzureMatcher
// Limiter limits the connection and request rates.
Limiter limiter.Config
}
Expand Down
4 changes: 3 additions & 1 deletion lib/service/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ func (process *TeleportProcess) shouldInitDatabases() bool {
databasesCfg := len(process.Config.Databases.Databases) > 0
resourceMatchersCfg := len(process.Config.Databases.ResourceMatchers) > 0
awsMatchersCfg := len(process.Config.Databases.AWSMatchers) > 0
anyCfg := databasesCfg || resourceMatchersCfg || awsMatchersCfg
azureMatchersCfg := len(process.Config.Databases.AzureMatchers) > 0
anyCfg := databasesCfg || resourceMatchersCfg || awsMatchersCfg || azureMatchersCfg

return process.Config.Databases.Enabled && anyCfg
}
Expand Down Expand Up @@ -215,6 +216,7 @@ func (process *TeleportProcess) initDatabaseService() (retErr error) {
CloudLabels: process.cloudLabels,
ResourceMatchers: process.Config.Databases.ResourceMatchers,
AWSMatchers: process.Config.Databases.AWSMatchers,
AzureMatchers: process.Config.Databases.AzureMatchers,
OnHeartbeat: process.onHeartbeat(teleport.ComponentDatabase),
LockWatcher: lockWatcher,
ConnectedProxyGetter: proxyGetter,
Expand Down
18 changes: 18 additions & 0 deletions lib/services/matchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ type AWSMatcher struct {
Tags types.Labels
}

// AzureMatcher matches Azure databases.
type AzureMatcher struct {
// Subscriptions are Azure subscriptions to query for resources.
Subscriptions []string
// ResourceGroups are Azure resource groups to query for resources.
ResourceGroups []string
// Types are Azure resource types to match, for example "mysql" or "postgres".
Types []string
// Regions are Azure regions to query for databases.
Regions []string
// ResourceTags are Azure tags to match.
ResourceTags types.Labels
}

// MatchResourceLabels returns true if any of the provided selectors matches the provided database.
func MatchResourceLabels(matchers []ResourceMatcher, resource types.ResourceWithLabels) bool {
for _, matcher := range matchers {
Expand Down Expand Up @@ -227,4 +241,8 @@ const (
AWSMatcherElastiCache = "elasticache"
// AWSMatcherMemoryDB is the AWS matcher type for MemoryDB databases.
AWSMatcherMemoryDB = "memorydb"
// AzureMatcherMySQL is the Azure matcher type for Azure MySQL databases.
AzureMatcherMySQL = "mysql"
// AzureMatcherPostgres is the Azure matcher type for Azure Postgres databases.
AzureMatcherPostgres = "postgres"
)
2 changes: 2 additions & 0 deletions lib/srv/db/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ type Config struct {
ResourceMatchers []services.ResourceMatcher
// AWSMatchers is a list of AWS databases matchers.
AWSMatchers []services.AWSMatcher
// AzureMatchers is a list of Azure databases matchers.
AzureMatchers []services.AzureMatcher
// Databases is a list of proxied databases from static configuration.
Databases types.Databases
// CloudLabels is a service that imports labels from a cloud provider. The labels are shared
Expand Down