Skip to content

Commit

Permalink
chore(metrics): Export RDS Certificate Authority attributes
Browse files Browse the repository at this point in the history
- The CA identifier is exposed as `ca_certificate_identifier` attribute of the `rds_instance_info` metric
- The Unix timestamp of the expiration date of the CA certificate is exposed in the `rds_ca_certificate_valid_until` gauge.

For the `rds-ca-2019` RDS CA, values are:
```
rds_instance_info{aws_account_id="012345678901",aws_region="eu-west-1",ca_certificate_identifier="rds-ca-2019",dbidentifier="rds-1",...}
rds_ca_certificate_valid_until{aws_account_id="012345678901",aws_region="eu-west-1",dbidentifier="rds-1"} 1.72434653e+09
```
  • Loading branch information
chtitux committed Nov 21, 2023
1 parent a8a8164 commit 80e0a53
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ It collect key metrics about:
| rds_allocated_storage_bytes | `aws_account_id`, `aws_region`, `dbidentifier` | Allocated storage |
| rds_api_call_total | `api`, `aws_account_id`, `aws_region` | Number of call to AWS API |
| rds_backup_retention_period_seconds | `aws_account_id`, `aws_region`, `dbidentifier` | Automatic DB snapshots retention period |
| rds_ca_certificate_valid_until | `aws_account_id`, `aws_region`, `dbidentifier` | Timestamp of the expiration of the Instance certificate |
| rds_cpu_usage_percent_average | `aws_account_id`, `aws_region`, `dbidentifier` | Instance CPU used |
| rds_database_connections_average | `aws_account_id`, `aws_region`, `dbidentifier` | The number of client network connections to the database instance |
| rds_dbload_average | `aws_account_id`, `aws_region`, `dbidentifier` | Number of active sessions for the DB engine |
Expand Down
37 changes: 34 additions & 3 deletions internal/app/exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ type rdsCollector struct {
usageManualSnapshots *prometheus.Desc
exporterBuildInformation *prometheus.Desc
transactionLogsDiskUsage *prometheus.Desc
certificateValidTill *prometheus.Desc
}

func NewCollector(logger slog.Logger, collectorConfiguration Configuration, awsAccountID string, awsRegion string, rdsClient rdsClient, ec2Client EC2Client, cloudWatchClient cloudWatchClient, servicequotasClient servicequotasClient) *rdsCollector {
Expand Down Expand Up @@ -126,7 +127,7 @@ func NewCollector(logger slog.Logger, collectorConfiguration Configuration, awsA
),
information: prometheus.NewDesc("rds_instance_info",
"RDS instance information",
[]string{"aws_account_id", "aws_region", "dbidentifier", "dbi_resource_id", "instance_class", "engine", "engine_version", "storage_type", "multi_az", "deletion_protection", "role", "source_dbidentifier", "pending_modified_values", "pending_maintenance", "performance_insights_enabled"}, nil,
[]string{"aws_account_id", "aws_region", "dbidentifier", "dbi_resource_id", "instance_class", "engine", "engine_version", "storage_type", "multi_az", "deletion_protection", "role", "source_dbidentifier", "pending_modified_values", "pending_maintenance", "performance_insights_enabled", "ca_certificate_identifier"}, nil,
),
maxAllocatedStorage: prometheus.NewDesc("rds_max_allocated_storage_bytes",
"Upper limit in gibibytes to which Amazon RDS can automatically scale the storage of the DB instance",
Expand Down Expand Up @@ -240,6 +241,10 @@ func NewCollector(logger slog.Logger, collectorConfiguration Configuration, awsA
"Disk space used by transaction logs (only on PostgreSQL)",
[]string{"aws_account_id", "aws_region", "dbidentifier"}, nil,
),
certificateValidTill: prometheus.NewDesc("rds_certificate_expiry_timestamp_seconds",
"Timestamp of the expiration of the Instance certificate",
[]string{"aws_account_id", "aws_region", "dbidentifier"}, nil,
),
quotaDBInstances: prometheus.NewDesc("rds_quota_max_dbinstances_average",
"Maximum number of RDS instances allowed in the AWS account",
[]string{"aws_account_id", "aws_region"}, nil,
Expand Down Expand Up @@ -415,13 +420,39 @@ func (c *rdsCollector) Collect(ch chan<- prometheus.Metric) {
// RDS metrics
ch <- prometheus.MustNewConstMetric(c.apiCall, prometheus.CounterValue, c.counters.rdsAPIcalls, c.awsAccountID, c.awsRegion, "rds")
for dbidentifier, instance := range c.metrics.rds.Instances {
ch <- prometheus.MustNewConstMetric(c.allocatedStorage, prometheus.GaugeValue, float64(instance.AllocatedStorage), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.information, prometheus.GaugeValue, 1, c.awsAccountID, c.awsRegion, dbidentifier, instance.DbiResourceID, instance.DBInstanceClass, instance.Engine, instance.EngineVersion, instance.StorageType, strconv.FormatBool(instance.MultiAZ), strconv.FormatBool(instance.DeletionProtection), instance.Role, instance.SourceDBInstanceIdentifier, strconv.FormatBool(instance.PendingModifiedValues), instance.PendingMaintenanceAction, strconv.FormatBool(instance.PerformanceInsightsEnabled))
ch <- prometheus.MustNewConstMetric(
c.allocatedStorage,
prometheus.GaugeValue,
float64(instance.AllocatedStorage),
c.awsAccountID, c.awsRegion, dbidentifier,
)
ch <- prometheus.MustNewConstMetric(
c.information,
prometheus.GaugeValue,
1,
c.awsAccountID,
c.awsRegion,
dbidentifier,
instance.DbiResourceID,
instance.DBInstanceClass,
instance.Engine,
instance.EngineVersion,
instance.StorageType,
strconv.FormatBool(instance.MultiAZ),
strconv.FormatBool(instance.DeletionProtection),
instance.Role,
instance.SourceDBInstanceIdentifier,
strconv.FormatBool(instance.PendingModifiedValues),
instance.PendingMaintenanceAction,
strconv.FormatBool(instance.PerformanceInsightsEnabled),
instance.CACertificateIdentifier,
)
ch <- prometheus.MustNewConstMetric(c.maxAllocatedStorage, prometheus.GaugeValue, float64(instance.MaxAllocatedStorage), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.maxIops, prometheus.GaugeValue, float64(instance.MaxIops), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.status, prometheus.GaugeValue, float64(instance.Status), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.storageThroughput, prometheus.GaugeValue, float64(instance.StorageThroughput), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.backupRetentionPeriod, prometheus.GaugeValue, float64(instance.BackupRetentionPeriod), c.awsAccountID, c.awsRegion, dbidentifier)
ch <- prometheus.MustNewConstMetric(c.certificateValidTill, prometheus.GaugeValue, float64(instance.CertificateValidTill.Unix()), c.awsAccountID, c.awsRegion, dbidentifier)

if instance.LogFilesSize != nil {
ch <- prometheus.MustNewConstMetric(c.logFilesSize, prometheus.GaugeValue, float64(*instance.LogFilesSize), c.awsAccountID, c.awsRegion, dbidentifier)
Expand Down
5 changes: 5 additions & 0 deletions internal/app/rds/rds.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"reflect"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
aws_rds "github.com/aws/aws-sdk-go-v2/service/rds"
Expand Down Expand Up @@ -48,6 +49,8 @@ type RdsInstanceMetrics struct {
IAMDatabaseAuthenticationEnabled bool
Role string
SourceDBInstanceIdentifier string
CACertificateIdentifier string
CertificateValidTill time.Time
}

const (
Expand Down Expand Up @@ -272,6 +275,8 @@ func (r *RDSFetcher) computeInstanceMetrics(dbInstance aws_rds_types.DBInstance,
Status: GetDBInstanceStatusCode(*dbInstance.DBInstanceStatus),
StorageThroughput: converter.MegaBytesToBytes(storageThroughput),
StorageType: *dbInstance.StorageType,
CACertificateIdentifier: *dbInstance.CACertificateIdentifier,
CertificateValidTill: *dbInstance.CertificateDetails.ValidTill,
}

return metrics, nil
Expand Down
15 changes: 15 additions & 0 deletions internal/app/rds/rds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"reflect"
"testing"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
aws_rds "github.com/aws/aws-sdk-go-v2/service/rds"
Expand Down Expand Up @@ -55,6 +56,16 @@ func randomString(length int) string {
return fmt.Sprintf("%x", buf)
}

func newRdsCertificateDetails() *aws_rds_types.CertificateDetails {
return &aws_rds_types.CertificateDetails{
CAIdentifier: aws.String("rds-ca-2019"),
ValidTill: aws.Time(time.Date(
2024, time.August, 22,
17, 8, 50, 0, time.UTC,
)),
}
}

func newRdsInstance() *aws_rds_types.DBInstance {
DBInstanceIdentifier := randomString(10)

Expand All @@ -75,6 +86,8 @@ func newRdsInstance() *aws_rds_types.DBInstance {
PerformanceInsightsEnabled: aws.Bool(true),
PubliclyAccessible: true,
StorageType: aws.String("gp3"),
CACertificateIdentifier: aws.String("rds-ca-2019"),
CertificateDetails: newRdsCertificateDetails(),
}
}

Expand Down Expand Up @@ -108,6 +121,8 @@ func TestGetMetrics(t *testing.T) {
assert.Equal(t, rdsInstance.PubliclyAccessible, m.PubliclyAccessible, "PubliclyAccessible mismatch")
assert.Equal(t, *rdsInstance.DbiResourceId, m.DbiResourceID, "DbiResourceId mismatch")
assert.Equal(t, *rdsInstance.DBInstanceClass, m.DBInstanceClass, "DBInstanceIdentifier mismatch")
assert.Equal(t, *rdsInstance.CACertificateIdentifier, m.CACertificateIdentifier, "CACertificateIdentifier mismatch")
assert.Equal(t, *rdsInstance.CertificateDetails.ValidTill, m.CertificateValidTill, "CertificateValidTill mismatch")
}

func TestGP2StorageType(t *testing.T) {
Expand Down

0 comments on commit 80e0a53

Please sign in to comment.