-
-
Notifications
You must be signed in to change notification settings - Fork 358
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* s3 access point support * s3 access point support
- Loading branch information
1 parent
31edbae
commit 24f6c4a
Showing
13 changed files
with
723 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/s3control" | ||
"github.com/gruntwork-io/cloud-nuke/config" | ||
"github.com/gruntwork-io/cloud-nuke/logging" | ||
"github.com/gruntwork-io/cloud-nuke/report" | ||
"github.com/gruntwork-io/cloud-nuke/util" | ||
"github.com/gruntwork-io/go-commons/errors" | ||
) | ||
|
||
func (ap *S3AccessPoint) getAll(c context.Context, configObj config.Config) ([]*string, error) { | ||
accountID, ok := c.Value(util.AccountIdKey).(string) | ||
if !ok { | ||
logging.Errorf("unable to read the account-id from context") | ||
return nil, errors.WithStackTrace(fmt.Errorf("unable to lookup the account id")) | ||
} | ||
|
||
// set the account id in object as this is mandatory to nuke an access point | ||
ap.AccountID = aws.String(accountID) | ||
|
||
var accessPoints []*string | ||
err := ap.Client.ListAccessPointsPages(&s3control.ListAccessPointsInput{ | ||
AccountId: ap.AccountID, | ||
}, func(lapo *s3control.ListAccessPointsOutput, lastPage bool) bool { | ||
for _, accessPoint := range lapo.AccessPointList { | ||
if configObj.S3AccessPoint.ShouldInclude(config.ResourceValue{ | ||
Name: accessPoint.Name, | ||
}) { | ||
accessPoints = append(accessPoints, accessPoint.Name) | ||
} | ||
} | ||
return !lastPage | ||
}) | ||
return accessPoints, errors.WithStackTrace(err) | ||
} | ||
|
||
func (ap *S3AccessPoint) nukeAll(identifiers []*string) error { | ||
if len(identifiers) == 0 { | ||
logging.Debugf("No Access point(s) to nuke in region %s", ap.Region) | ||
return nil | ||
} | ||
|
||
logging.Debugf("Deleting all Access points in region %s", ap.Region) | ||
var deleted []*string | ||
|
||
for _, id := range identifiers { | ||
|
||
_, err := ap.Client.DeleteAccessPoint(&s3control.DeleteAccessPointInput{ | ||
AccountId: ap.AccountID, | ||
Name: id, | ||
}) | ||
|
||
// Record status of this resource | ||
e := report.Entry{ | ||
Identifier: aws.StringValue(id), | ||
ResourceType: "S3 Access point", | ||
Error: err, | ||
} | ||
report.Record(e) | ||
|
||
if err != nil { | ||
logging.Debugf("[Failed] %s", err) | ||
} else { | ||
deleted = append(deleted, id) | ||
logging.Debugf("Deleted S3 access point: %s", aws.StringValue(id)) | ||
} | ||
} | ||
|
||
logging.Debugf("[OK] %d S3 Access point(s) deleted in %s", len(deleted), ap.Region) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/s3control" | ||
"github.com/aws/aws-sdk-go/service/s3control/s3controliface" | ||
"github.com/gruntwork-io/cloud-nuke/config" | ||
"github.com/gruntwork-io/cloud-nuke/telemetry" | ||
"github.com/gruntwork-io/cloud-nuke/util" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
type mocks3AccessPoint struct { | ||
s3controliface.S3ControlAPI | ||
ListAccessPointsOutput s3control.ListAccessPointsOutput | ||
DeleteAccessPointOutput s3control.DeleteAccessPointOutput | ||
} | ||
|
||
func (m mocks3AccessPoint) ListAccessPointsPages(_ *s3control.ListAccessPointsInput, fn func(*s3control.ListAccessPointsOutput, bool) bool) error { | ||
fn(&m.ListAccessPointsOutput, true) | ||
return nil | ||
} | ||
func (m mocks3AccessPoint) DeleteAccessPoint(_ *s3control.DeleteAccessPointInput) (*s3control.DeleteAccessPointOutput, error) { | ||
return &m.DeleteAccessPointOutput, nil | ||
} | ||
|
||
func TestS3AccessPoint_GetAll(t *testing.T) { | ||
telemetry.InitTelemetry("cloud-nuke", "") | ||
t.Parallel() | ||
|
||
testName01 := "test-access-point-01" | ||
testName02 := "test-access-point-02" | ||
|
||
ctx := context.Background() | ||
ctx = context.WithValue(ctx, util.AccountIdKey, "test-account-id") | ||
|
||
ap := S3AccessPoint{ | ||
Client: mocks3AccessPoint{ | ||
ListAccessPointsOutput: s3control.ListAccessPointsOutput{ | ||
AccessPointList: []*s3control.AccessPoint{ | ||
{ | ||
Name: aws.String(testName01), | ||
}, | ||
{ | ||
Name: aws.String(testName02), | ||
}, | ||
}, | ||
}, | ||
}, | ||
AccountID: aws.String("test-account-id"), | ||
} | ||
|
||
tests := map[string]struct { | ||
configObj config.ResourceType | ||
expected []string | ||
}{ | ||
"emptyFilter": { | ||
configObj: config.ResourceType{}, | ||
expected: []string{testName01, testName02}, | ||
}, | ||
"nameExclusionFilter": { | ||
configObj: config.ResourceType{ | ||
ExcludeRule: config.FilterRule{ | ||
NamesRegExp: []config.Expression{{ | ||
RE: *regexp.MustCompile(testName01), | ||
}}}, | ||
}, | ||
expected: []string{testName02}, | ||
}, | ||
} | ||
for name, tc := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
|
||
names, err := ap.getAll(ctx, config.Config{ | ||
S3AccessPoint: tc.configObj, | ||
}) | ||
require.NoError(t, err) | ||
require.Equal(t, tc.expected, aws.StringValueSlice(names)) | ||
}) | ||
} | ||
} | ||
|
||
func TestS3AccessPoint_NukeAll(t *testing.T) { | ||
telemetry.InitTelemetry("cloud-nuke", "") | ||
t.Parallel() | ||
|
||
rc := S3AccessPoint{ | ||
Client: mocks3AccessPoint{ | ||
DeleteAccessPointOutput: s3control.DeleteAccessPointOutput{}, | ||
}, | ||
} | ||
|
||
err := rc.nukeAll([]*string{aws.String("test")}) | ||
require.NoError(t, err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
|
||
awsgo "github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/session" | ||
"github.com/aws/aws-sdk-go/service/s3control" | ||
"github.com/aws/aws-sdk-go/service/s3control/s3controliface" | ||
"github.com/gruntwork-io/cloud-nuke/config" | ||
"github.com/gruntwork-io/go-commons/errors" | ||
) | ||
|
||
type S3AccessPoint struct { | ||
BaseAwsResource | ||
Client s3controliface.S3ControlAPI | ||
Region string | ||
AccessPoints []string | ||
AccountID *string | ||
} | ||
|
||
func (ap *S3AccessPoint) Init(session *session.Session) { | ||
ap.Client = s3control.New(session) | ||
} | ||
|
||
func (ap *S3AccessPoint) ResourceName() string { | ||
return "s3-ap" | ||
} | ||
|
||
func (ap *S3AccessPoint) ResourceIdentifiers() []string { | ||
return ap.AccessPoints | ||
} | ||
|
||
func (ap *S3AccessPoint) MaxBatchSize() int { | ||
return 5 | ||
} | ||
|
||
func (ap *S3AccessPoint) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) { | ||
identifiers, err := ap.getAll(c, configObj) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ap.AccessPoints = awsgo.StringValueSlice(identifiers) | ||
return ap.AccessPoints, nil | ||
} | ||
|
||
func (ap *S3AccessPoint) Nuke(identifiers []string) error { | ||
if err := ap.nukeAll(awsgo.StringSlice(identifiers)); err != nil { | ||
return errors.WithStackTrace(err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/s3control" | ||
"github.com/gruntwork-io/cloud-nuke/config" | ||
"github.com/gruntwork-io/cloud-nuke/logging" | ||
"github.com/gruntwork-io/cloud-nuke/report" | ||
"github.com/gruntwork-io/cloud-nuke/util" | ||
"github.com/gruntwork-io/go-commons/errors" | ||
) | ||
|
||
func (ap *S3MultiRegionAccessPoint) getAll(c context.Context, configObj config.Config) ([]*string, error) { | ||
accountID, ok := c.Value(util.AccountIdKey).(string) | ||
if !ok { | ||
logging.Errorf("unable to read the account-id from context") | ||
return nil, errors.WithStackTrace(fmt.Errorf("unable to lookup the account id")) | ||
} | ||
|
||
// set the account id in object as this is mandatory to nuke an access point | ||
ap.AccountID = aws.String(accountID) | ||
|
||
var accessPoints []*string | ||
err := ap.Client.ListMultiRegionAccessPointsPages(&s3control.ListMultiRegionAccessPointsInput{ | ||
AccountId: ap.AccountID, | ||
}, func(lapo *s3control.ListMultiRegionAccessPointsOutput, lastPage bool) bool { | ||
for _, accessPoint := range lapo.AccessPoints { | ||
if configObj.S3MultiRegionAccessPoint.ShouldInclude(config.ResourceValue{ | ||
Name: accessPoint.Name, | ||
Time: accessPoint.CreatedAt, | ||
}) { | ||
accessPoints = append(accessPoints, accessPoint.Name) | ||
} | ||
} | ||
return !lastPage | ||
}) | ||
if err != nil { | ||
logging.Errorf("[FAILED] Multi region access point listing - %v", err) | ||
} | ||
return accessPoints, errors.WithStackTrace(err) | ||
} | ||
|
||
func (ap *S3MultiRegionAccessPoint) nukeAll(identifiers []*string) error { | ||
if len(identifiers) == 0 { | ||
logging.Debugf("No Multi region access point(s) to nuke in region %s", ap.Region) | ||
return nil | ||
} | ||
|
||
logging.Debugf("Deleting all Multi region access points in region %s", ap.Region) | ||
var deleted []*string | ||
|
||
for _, id := range identifiers { | ||
|
||
_, err := ap.Client.DeleteMultiRegionAccessPoint(&s3control.DeleteMultiRegionAccessPointInput{ | ||
AccountId: ap.AccountID, | ||
Details: &s3control.DeleteMultiRegionAccessPointInput_{ | ||
Name: id, | ||
}, | ||
}) | ||
|
||
// Record status of this resource | ||
e := report.Entry{ | ||
Identifier: aws.StringValue(id), | ||
ResourceType: "S3 Multi Region Access point", | ||
Error: err, | ||
} | ||
report.Record(e) | ||
|
||
if err != nil { | ||
logging.Debugf("[Failed] %s", err) | ||
} else { | ||
deleted = append(deleted, id) | ||
logging.Debugf("Deleted S3 Multi region access point: %s", aws.StringValue(id)) | ||
} | ||
} | ||
|
||
logging.Debugf("[OK] %d S3 Multi region access point(s) deleted in %s", len(deleted), ap.Region) | ||
|
||
return nil | ||
} |
Oops, something went wrong.