Skip to content

Commit

Permalink
feat: adds strike for checking automated backups against a db instance
Browse files Browse the repository at this point in the history
  • Loading branch information
grudra7714 committed Oct 21, 2023
1 parent b64066f commit 7588358
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 25 deletions.
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ var (
AvailableStrikes = map[string][]raidengine.Strike{
"CCC-Taxonomy": {
Strikes.SQLFeatures,
Strikes.AutomatedBackups,
// Strikes.VerticalScaling,
// Strikes.Replication,
// Strikes.MultiRegion,
// Strikes.AutomatedBackup,
// Strikes.BackupRecovery,
// Strikes.Encryption,
// Strikes.RBAC,
Expand Down
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ module github.com/krumIO/raid-rds
go 1.14

require (
github.com/aws/aws-sdk-go-v2 v1.21.2
github.com/aws/aws-sdk-go-v2/config v1.19.0
github.com/aws/aws-sdk-go-v2/credentials v1.13.43
github.com/aws/aws-sdk-go-v2/service/rds v1.57.0
github.com/hashicorp/go-hclog v1.2.0
github.com/privateerproj/privateer-sdk v0.0.6
github.com/spf13/cobra v1.4.0
Expand Down
31 changes: 31 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,32 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA=
github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM=
github.com/aws/aws-sdk-go-v2/config v1.19.0 h1:AdzDvwH6dWuVARCl3RTLGRc4Ogy+N7yLFxVxXe1ClQ0=
github.com/aws/aws-sdk-go-v2/config v1.19.0/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE=
github.com/aws/aws-sdk-go-v2/credentials v1.13.43 h1:LU8vo40zBlo3R7bAvBVy/ku4nxGEyZe9N8MqAeFTzF8=
github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 h1:PIktER+hwIG286DqXyvVENjgLTAwGgoeriLDD5C+YlQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 h1:nFBQlGtkbPzp/NjZLuFxRqmT91rLJkgvsEQs68h962Y=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 h1:JRVhO25+r3ar2mKGP7E0LDl8K9/G36gjlqca5iQbaqc=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 h1:hze8YsjSh8Wl1rYa1CJpRmXP21BvOBuc76YhW0HsuQ4=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 h1:WWZA/I2K4ptBS1kg0kV1JbBtG/umed0vwHRrmcr9z7k=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck=
github.com/aws/aws-sdk-go-v2/service/rds v1.57.0 h1:kUCf6QowN4v8Jz1LRCr9ar3vcrKJu5YtbAbdXUGvvF4=
github.com/aws/aws-sdk-go-v2/service/rds v1.57.0/go.mod h1:NNx09yR8B7z4I5xTt2rUq+5h2lmA9T9bbm7NME/74Ac=
github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 h1:JuPGc7IkOP4AaqcZSIcyqLpFSqBWK32rM9+a1g6u73k=
github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 h1:HFiiRkf1SdaAmV3/BHOFZ9DjFynPHj8G/UIO1lQS+fk=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3/go.mod h1:a7bHA82fyUXOm+ZSWKU6PIoBxrjSprdLoM8xPYvzYVg=
github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 h1:0BkLfgeDjfZnZ+MhB3ONb01u9pwFYTCZVhlsSSBvlbU=
github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ=
github.com/aws/smithy-go v1.15.0 h1:PS/durmlzvAFpQHDs4wi4sNNP9ExsqZh6IlfdHXgKK8=
github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
Expand Down Expand Up @@ -596,6 +622,10 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
Expand Down Expand Up @@ -1319,6 +1349,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
99 changes: 99 additions & 0 deletions strikes/AutomatedBackups.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package strikes

import (
"context"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/rds"
"github.com/privateerproj/privateer-sdk/raidengine"
"github.com/privateerproj/privateer-sdk/utils"
"github.com/spf13/viper"
)

// Todo/Roadmap: Features to evaluate implementing
// AutomatedBackup.go - AWS CLI - check backup interval

// This creates a database table
func (a *Strikes) AutomatedBackups() (strikeName string, result raidengine.StrikeResult) {
strikeName = "AutomatedBackups"
result = raidengine.StrikeResult{
Passed: false,
Description: "Check for automated backups against the specified RDS instance",
DocsURL: "https://www.github.com/krumIO/raid-rds",
ControlID: "CCC-Taxonomy-1",
Movements: make(map[string]raidengine.MovementResult),
}

// Movement
cfg, err := getAWSConfig()
if err != nil {
result.Message = err.Error()
return
}

rdsInstanceMovement := checkRDSInstanceMovement(cfg)
result.Movements["CheckForDBInstance"] = rdsInstanceMovement
if !rdsInstanceMovement.Passed {
result.Message = rdsInstanceMovement.Message
return
}

autmatedBackupsMovement := checkRDSAutomatedBackupMovement(cfg)
result.Movements["CheckForDBInstanceAutomatedBackups"] = autmatedBackupsMovement
if !autmatedBackupsMovement.Passed {
result.Message = autmatedBackupsMovement.Message
return
}

result.Passed = true
result.Message = "Completed Successfully"
return
}

func checkRDSInstanceMovement(cfg aws.Config) (result raidengine.MovementResult) {
// check if the instance is available
result = raidengine.MovementResult{
Description: "Check if the instance is available/exists",
Function: utils.CallerPath(0),
}

rdsClient := rds.NewFromConfig(cfg)
input := &rds.DescribeDBInstancesInput{
DBInstanceIdentifier: aws.String(viper.GetString("raids.RDS.config.aws_db_instance_identifier")),
}

instances, err := rdsClient.DescribeDBInstances(context.TODO(), input)
if err != nil {
// Handle error
result.Message = err.Error()
result.Passed = false
return
}
result.Passed = len(instances.DBInstances) > 0
return
}

func checkRDSAutomatedBackupMovement(cfg aws.Config) (result raidengine.MovementResult) {

result = raidengine.MovementResult{
Description: "Check if the instance has automated backups enabled",
Function: utils.CallerPath(0),
}

rdsClient := rds.NewFromConfig(cfg)
input := &rds.DescribeDBInstanceAutomatedBackupsInput{
DBInstanceIdentifier: aws.String(viper.GetString("raids.RDS.config.aws_db_instance_identifier")),
}

backups, err := rdsClient.DescribeDBInstanceAutomatedBackups(context.TODO(), input)
if err != nil {
// Handle error
result.Message = err.Error()
result.Passed = false
return
}

// Loop through the instances and print information
result.Passed = len(backups.DBInstanceAutomatedBackups) > 0
return
}
32 changes: 32 additions & 0 deletions strikes/AutomatedBackups_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package strikes

import (
"encoding/json"
"fmt"
"testing"

"github.com/spf13/viper"
)

func TestAutomatedBackup(t *testing.T) {
viper.AddConfigPath("../")
viper.SetConfigName("config")
viper.SetConfigType("yaml")
err := viper.ReadInConfig()

if err != nil {
fmt.Println("Config file not found...")
return
}

strikes := Strikes{}
strikeName, result := strikes.AutomatedBackups()

fmt.Println(strikeName)
b, err := json.MarshalIndent(result, "", " ")
if err != nil {
fmt.Println(err)
}
fmt.Print(string(b))
fmt.Println()
}
20 changes: 1 addition & 19 deletions strikes/SQLFeatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ import (
// Monitoring.go - check for enabled, req API/CLI
// Alerting.go - check for enabled, req API/CLI

func (a *Strikes) SetLogger(loggerName string) {
a.Log = raidengine.GetLogger(loggerName, false)
}

// This creates a database table
func (a *Strikes) SQLFeatures() (strikeName string, result raidengine.StrikeResult) {
strikeName = "SQLFeatures"
Expand Down Expand Up @@ -61,26 +57,12 @@ func (a *Strikes) SQLFeatures() (strikeName string, result raidengine.StrikeResu
return
}

func connectToDb() (result raidengine.MovementResult) {
result = raidengine.MovementResult{
Description: "The database host must be available and accepting connections",
Function: utils.CallerPath(0),
}
_, err := getConfig()
if err != nil {
result.Message = err.Error()
return
}
result.Passed = true
return
}

func createTable() (result raidengine.MovementResult) {
result = raidengine.MovementResult{
Description: "A table can be created in the database",
Function: utils.CallerPath(0),
}
name, err := getConfig()
name, err := getDBConfig()
if err != nil {
result.Message = err.Error()
return
Expand Down
47 changes: 42 additions & 5 deletions strikes/common.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package strikes

import (
"context"
"errors"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
hclog "github.com/hashicorp/go-hclog"
"github.com/privateerproj/privateer-sdk/raidengine"
"github.com/privateerproj/privateer-sdk/utils"
"github.com/spf13/viper"
)

Expand All @@ -15,12 +21,43 @@ type Movement struct {
Strike string
}

func getConfig() (string, error) {
if viper.IsSet("raids.RDS.config") && viper.IsSet("raids.RDS.config.database") {
func (a *Strikes) SetLogger(loggerName string) {
a.Log = raidengine.GetLogger(loggerName, false)
}

// Todo: return full config
// return viper.GetString("raids.RDS.config.database.host"), nil
func getDBConfig() (string, error) {
if viper.IsSet("raids.RDS.config") && viper.IsSet("raids.RDS.config.database") {
return "database_host_placeholder", nil
}
return "", errors.New("Database URL must be set in the config file (raids.RDS.config.database.host)")
return "", errors.New("database url must be set in the config file")
}

func getAWSConfig() (cfg aws.Config, err error) {
if viper.IsSet("raids.RDS.config") &&
viper.IsSet("raids.RDS.config.aws_access_key") &&
viper.IsSet("raids.RDS.config.aws_secret_key") {

access_key := viper.GetString("raids.RDS.config.aws_access_key")
secret_key := viper.GetString("raids.RDS.config.aws_secret_key")
session_key := viper.GetString("raids.RDS.config.aws_session_key")
region := viper.GetString("raids.RDS.config.aws_region")

creds := credentials.NewStaticCredentialsProvider(access_key, secret_key, session_key)
cfg, err = config.LoadDefaultConfig(context.TODO(), config.WithCredentialsProvider(creds), config.WithRegion(region))
}
return
}

func connectToDb() (result raidengine.MovementResult) {
result = raidengine.MovementResult{
Description: "The database host must be available and accepting connections",
Function: utils.CallerPath(0),
}
_, err := getDBConfig()
if err != nil {
result.Message = err.Error()
return
}
result.Passed = true
return
}

0 comments on commit 7588358

Please sign in to comment.