Skip to content

Commit

Permalink
Use deletion protection on ALBs and databases
Browse files Browse the repository at this point in the history
  • Loading branch information
ipmb committed Mar 29, 2022
1 parent 395cc1f commit 7dce53d
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 8 deletions.
4 changes: 4 additions & 0 deletions stacks/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func (a *AccountStack) SetStack(stack *cloudformation.Stack) {
a.Stack = stack
}

func (*AccountStack) PostCreate(_ *session.Session) error {
return nil
}

func (*AccountStack) PreDelete(_ *session.Session) error {
return nil
}
Expand Down
4 changes: 4 additions & 0 deletions stacks/app_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ func (a *AppStack) SetStack(stack *cloudformation.Stack) {
a.Stack = stack
}

func (*AppStack) PostCreate(_ *session.Session) error {
return nil
}

func (*AppStack) PreDelete(_ *session.Session) error {
return nil
}
Expand Down
31 changes: 29 additions & 2 deletions stacks/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"net"
"sort"
"strconv"
"strings"

"github.com/AlecAivazis/survey/v2"
Expand All @@ -13,7 +14,9 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
)

Expand Down Expand Up @@ -165,8 +168,32 @@ func (a *ClusterStack) SetStack(stack *cloudformation.Stack) {
a.Stack = stack
}

func (*ClusterStack) PreDelete(_ *session.Session) error {
return nil
// SetDeletionProtection toggles the deletion protection flag on the load balancer
func (a *ClusterStack) SetDeletionProtection(sess *session.Session, value bool) error {
elbSvc := elbv2.New(sess)
lbARN, err := bridge.GetStackOutput(a.Stack.Outputs, "LoadBalancerArn")
if err != nil {
return err
}
logrus.WithFields(logrus.Fields{"value": value}).Debug("setting load balancer deletion protection")
_, err = elbSvc.ModifyLoadBalancerAttributes(&elbv2.ModifyLoadBalancerAttributesInput{
LoadBalancerArn: lbARN,
Attributes: []*elbv2.LoadBalancerAttribute{
{
Key: aws.String("deletion_protection.enabled"),
Value: aws.String(strconv.FormatBool(value)),
},
},
})
return err
}

func (a *ClusterStack) PostCreate(sess *session.Session) error {
return a.SetDeletionProtection(sess, true)
}

func (a *ClusterStack) PreDelete(sess *session.Session) error {
return a.SetDeletionProtection(sess, false)
}

func (*ClusterStack) PostDelete(_ *session.Session, _ *string) error {
Expand Down
4 changes: 4 additions & 0 deletions stacks/custom_domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ func (a *CustomDomainStack) SetStack(stack *cloudformation.Stack) {
a.Stack = stack
}

func (*CustomDomainStack) PostCreate(_ *session.Session) error {
return nil
}

func (*CustomDomainStack) PreDelete(_ *session.Session) error {
return nil
}
Expand Down
30 changes: 24 additions & 6 deletions stacks/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,19 @@ func (a *DatabaseStack) SetStack(stack *cloudformation.Stack) {
a.Stack = stack
}

// PreDelete will remove deletion protection on the stack
func (a *DatabaseStack) PreDelete(sess *session.Session) error {
// SetDeletionProtection toggles the deletion protection flag on the database instance or cluster
func (a *DatabaseStack) SetDeletionProtection(sess *session.Session, value bool) error {
rdsSvc := rds.New(sess)
DBID, err1 := bridge.GetStackOutput(a.Stack.Outputs, "DBId")
DBType, err2 := bridge.GetStackOutput(a.Stack.Outputs, "DBType")
// If stack failed to complete successfully, we may not have a DB instance to modify
if DBID != nil && DBType != nil {
input := rds.ModifyDBInstanceInput{
DBInstanceIdentifier: DBID,
DeletionProtection: aws.Bool(false),
DeletionProtection: &value,
ApplyImmediately: aws.Bool(true),
}
logrus.WithFields(logrus.Fields{"identifier": DBID}).Debug("disabling RDS deletion protection")
logrus.WithFields(logrus.Fields{"identifier": DBID, "value": value}).Debug("setting RDS deletion protection")
if *DBType == "instance" {
_, err := rdsSvc.ModifyDBInstance(&input)
return err
Expand All @@ -194,15 +194,33 @@ func (a *DatabaseStack) PreDelete(sess *session.Session) error {
}
return fmt.Errorf("unexpected DB type %s", *DBType)
}
// if we get an error trying to set deletion protection, return it
// just log errors trying to turn it off because the instance/cluster may not exist
// in the case of a stack failure
if err1 != nil {
logrus.WithFields(logrus.Fields{"error": err1}).Debug("unable to lookup Cloudformation outputs to disable RDS deletion protection")
logrus.WithFields(logrus.Fields{"error": err1}).Debug("unable to lookup Cloudformation outputs to set RDS deletion protection")
if value {
return err1
}
}
if err2 != nil {
logrus.WithFields(logrus.Fields{"error": err2}).Debug("unable to lookup Cloudformation outputs to disable RDS deletion protection")
logrus.WithFields(logrus.Fields{"error": err2}).Debug("unable to lookup Cloudformation outputs to set RDS deletion protection")
if value {
return err2
}
}
return nil
}

// PreDelete will remove deletion protection on the stack
func (a *DatabaseStack) PreDelete(sess *session.Session) error {
return a.SetDeletionProtection(sess, false)
}

func (a *DatabaseStack) PostCreate(sess *session.Session) error {
return a.SetDeletionProtection(sess, true)
}

func (*DatabaseStack) PostDelete(_ *session.Session, _ *string) error {
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions stacks/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Stack interface {
Tags(name *string) []*cloudformation.Tag
Capabilities() []*string
TemplateURL(release *string) *string
PostCreate(sess *session.Session) error
PreDelete(sess *session.Session) error
PostDelete(sess *session.Session, name *string) error
}
Expand Down Expand Up @@ -169,6 +170,7 @@ func CreateStack(sess *session.Session, s Stack, name, release *string) error {
return fmt.Errorf("stack creation failed: %s", *cfnStack.StackStatus)
}
s.SetStack(cfnStack)
s.PostCreate(sess)
return nil
}

Expand Down
4 changes: 4 additions & 0 deletions stacks/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ func (a *RedisStack) SetStack(stack *cloudformation.Stack) {
a.Stack = stack
}

func (*RedisStack) PostCreate(_ *session.Session) error {
return nil
}

func (*RedisStack) PreDelete(_ *session.Session) error {
return nil
}
Expand Down
4 changes: 4 additions & 0 deletions stacks/region.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ func (a *RegionStack) SetStack(stack *cloudformation.Stack) {
a.Stack = stack
}

func (*RegionStack) PostCreate(_ *session.Session) error {
return nil
}

func (*RegionStack) PreDelete(_ *session.Session) error {
return nil
}
Expand Down
4 changes: 4 additions & 0 deletions stacks/review_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ func (a *ReviewAppStack) SetStack(stack *cloudformation.Stack) {
a.Stack = stack
}

func (*ReviewAppStack) PostCreate(_ *session.Session) error {
return nil
}

func (*ReviewAppStack) PreDelete(_ *session.Session) error {
return nil
}
Expand Down

0 comments on commit 7dce53d

Please sign in to comment.