diff --git a/go.mod b/go.mod index f0e4fb7..6fda142 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,8 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/recoveryservices/armrecoveryservicesbackup v1.0.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/security/armsecurity v0.11.0 github.com/Azure/go-autorest/autorest/to v0.4.0 - github.com/ekristen/libnuke v0.12.0 + github.com/ekristen/libnuke v0.12.1-0.20240326234901-fabc1a06d086 + github.com/fatih/color v1.16.0 github.com/gotidy/ptr v1.4.0 github.com/hashicorp/go-azure-helpers v0.66.1 github.com/hashicorp/go-azure-sdk v0.20240125.1100331 @@ -34,7 +35,6 @@ require ( github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/color v1.16.0 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/protobuf v1.5.2 // indirect diff --git a/go.sum b/go.sum index 3d5fa9f..6d40310 100644 --- a/go.sum +++ b/go.sum @@ -76,10 +76,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/ekristen/libnuke v0.6.0 h1:VsNkdrprFfbFSsJnwQEynzww7JWR/icKox/sso7ucT0= -github.com/ekristen/libnuke v0.6.0/go.mod h1:WhYx7LDAkvkXwwfhWCASRn7fbifF8kfyhNsUj5zCCVs= -github.com/ekristen/libnuke v0.12.0 h1:Dsk+ckT9sh9QZTLq5m8kOA1KFJGJxSv0TLnfe3YeL1o= -github.com/ekristen/libnuke v0.12.0/go.mod h1:sBdA04l9IMMejQw5gO9k6o/a0GffSYhgZYaUSdRjIac= +github.com/ekristen/libnuke v0.12.1-0.20240326234901-fabc1a06d086 h1:fmTVIbAlYWmN8AyBfk6hBiPMZ7iUsxtUwJ6mnBDf0SU= +github.com/ekristen/libnuke v0.12.1-0.20240326234901-fabc1a06d086/go.mod h1:sBdA04l9IMMejQw5gO9k6o/a0GffSYhgZYaUSdRjIac= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -282,8 +280,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= diff --git a/pkg/azure/auth.go b/pkg/azure/auth.go index e331b08..d119710 100644 --- a/pkg/azure/auth.go +++ b/pkg/azure/auth.go @@ -2,15 +2,20 @@ package azure import ( "context" + "os" + + "github.com/sirupsen/logrus" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/hashicorp/go-azure-sdk/sdk/auth" "github.com/hashicorp/go-azure-sdk/sdk/auth/autorest" "github.com/hashicorp/go-azure-sdk/sdk/environments" - "github.com/sirupsen/logrus" - "os" ) -func ConfigureAuth(ctx context.Context, environment, tenantID, clientID, clientSecret, clientCertFile, clientFedTokenFile string) (*Authorizers, error) { +func ConfigureAuth( + ctx context.Context, + environment, tenantID, clientID, clientSecret, clientCertFile, clientFedTokenFile string) (*Authorizers, error) { env, err := environments.FromName(environment) if err != nil { return nil, err diff --git a/pkg/azure/tenant.go b/pkg/azure/tenant.go index 796f9a6..33cc747 100644 --- a/pkg/azure/tenant.go +++ b/pkg/azure/tenant.go @@ -3,14 +3,14 @@ package azure import ( "context" "fmt" - "github.com/gotidy/ptr" "slices" "time" + "github.com/gotidy/ptr" "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-05-01/resources" - "github.com/Azure/azure-sdk-for-go/services/subscription/mgmt/2020-09-01/subscription" + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-05-01/resources" //nolint:staticcheck + "github.com/Azure/azure-sdk-for-go/services/subscription/mgmt/2020-09-01/subscription" //nolint:staticcheck ) type Tenant struct { @@ -24,7 +24,10 @@ type Tenant struct { ResourceGroups map[string][]string } -func NewTenant(pctx context.Context, authorizers *Authorizers, tenantId string, subscriptionIds []string, locations []string) (*Tenant, error) { +func NewTenant( //nolint:gocyclo + pctx context.Context, authorizers *Authorizers, + tenantID string, subscriptionIDs, regions []string, +) (*Tenant, error) { ctx, cancel := context.WithTimeout(pctx, time.Second*15) defer cancel() @@ -33,7 +36,7 @@ func NewTenant(pctx context.Context, authorizers *Authorizers, tenantId string, tenant := &Tenant{ Authorizers: authorizers, - ID: tenantId, + ID: tenantID, TenantIds: make([]string, 0), SubscriptionIds: make([]string, 0), Locations: make(map[string][]string), @@ -62,7 +65,7 @@ func NewTenant(pctx context.Context, authorizers *Authorizers, tenantId string, return nil, err } for _, s := range list.Values() { - if len(subscriptionIds) > 0 && !slices.Contains(subscriptionIds, *s.SubscriptionID) { + if len(subscriptionIDs) > 0 && !slices.Contains(subscriptionIDs, *s.SubscriptionID) { logrus.Warnf("skipping subscription id: %s (reason: not requested)", *s.SubscriptionID) continue } @@ -74,15 +77,15 @@ func NewTenant(pctx context.Context, authorizers *Authorizers, tenantId string, groupsClient := resources.NewGroupsClient(*s.SubscriptionID) groupsClient.Authorizer = authorizers.Management - logrus.Info("configured locations", locations) + logrus.Debugf("configured regions: %v", regions) for list, err := groupsClient.List(ctx, "", nil); list.NotDone(); err = list.NextWithContext(ctx) { if err != nil { return nil, err } for _, g := range list.Values() { - // If the location isn't in the list of locations we want to include, skip it - if !slices.Contains(locations, ptr.ToString(g.Location)) { + // If the region isn't in the list of regions we want to include, skip it + if !slices.Contains(regions, ptr.ToString(g.Location)) && !slices.Contains(regions, "all") { continue } @@ -90,7 +93,6 @@ func NewTenant(pctx context.Context, authorizers *Authorizers, tenantId string, tenant.ResourceGroups[*s.SubscriptionID] = append(tenant.ResourceGroups[*s.SubscriptionID], *g.Name) } } - } } diff --git a/pkg/commands/list/list.go b/pkg/commands/list/list.go index 111b1b5..e561cbd 100644 --- a/pkg/commands/list/list.go +++ b/pkg/commands/list/list.go @@ -35,10 +35,8 @@ func execute(c *cli.Context) error { c = color.FgHiGreen } else if reg.Scope == nuke.Subscription { c = color.FgHiBlue - } else if reg.Scope == nuke.Subscription { + } else if reg.Scope == nuke.ResourceGroup { c = color.FgHiMagenta - } else { - } color.New(c).Printf(fmt.Sprintf("%s\n", string(reg.Scope))) } diff --git a/pkg/commands/nuke/command.go b/pkg/commands/nuke/command.go index dbdf9b4..3b16663 100644 --- a/pkg/commands/nuke/command.go +++ b/pkg/commands/nuke/command.go @@ -3,7 +3,6 @@ package nuke import ( "context" "fmt" - libscanner "github.com/ekristen/libnuke/pkg/scanner" "log" "slices" "strings" @@ -13,8 +12,10 @@ import ( "github.com/urfave/cli/v2" libconfig "github.com/ekristen/libnuke/pkg/config" + "github.com/ekristen/libnuke/pkg/filter" libnuke "github.com/ekristen/libnuke/pkg/nuke" "github.com/ekristen/libnuke/pkg/registry" + libscanner "github.com/ekristen/libnuke/pkg/scanner" "github.com/ekristen/libnuke/pkg/types" "github.com/ekristen/azure-nuke/pkg/azure" @@ -37,7 +38,7 @@ func (w *log2LogrusWriter) Write(b []byte) (int, error) { return n, nil } -func execute(c *cli.Context) error { +func execute(c *cli.Context) error { //nolint:funlen ctx, cancel := context.WithCancel(c.Context) defer cancel() @@ -87,6 +88,18 @@ func execute(c *cli.Context) error { return err } + // Region Filters + if len(filters[filter.Global]) == 0 { + filters[filter.Global] = []filter.Filter{} + } + if !slices.Contains(parsedConfig.Regions, "all") { + filters[filter.Global] = append(filters[filter.Global], filter.Filter{ + Property: "Location", + Type: filter.NotIn, + Values: parsedConfig.Regions, + }) + } + n := libnuke.New(params, filters, parsedConfig.Settings) n.SetRunSleep(5 * time.Second) @@ -125,29 +138,60 @@ func execute(c *cli.Context) error { nil, ) - if slices.Contains(parsedConfig.Regions, "global") { - if err := n.RegisterScanner(nuke.Tenant, libscanner.New("tenant/all", tenantResourceTypes, &nuke.ListerOpts{ + rgResourceTypes := types.ResolveResourceTypes( + registry.GetNamesForScope(nuke.ResourceGroup), + []types.Collection{ + n.Parameters.Includes, + parsedConfig.ResourceTypes.GetIncludes(), + tenantConfig.ResourceTypes.GetIncludes(), + }, + []types.Collection{ + n.Parameters.Excludes, + parsedConfig.ResourceTypes.Excludes, + tenantConfig.ResourceTypes.Excludes, + }, + nil, + nil, + ) + + if slices.Contains(parsedConfig.Regions, "global") || slices.Contains(parsedConfig.Regions, "all") { + if err := n.RegisterScanner(nuke.Tenant, libscanner.New("tenant", tenantResourceTypes, &nuke.ListerOpts{ Authorizers: authorizers, - TenantId: tenant.ID, + TenantID: tenant.ID, })); err != nil { return err } } logrus.Debug("registering scanner for tenant subscription resources") - for _, subscriptionId := range tenant.SubscriptionIds { + for _, subscriptionID := range tenant.SubscriptionIds { logrus.Debug("registering scanner for subscription resources") - parts := strings.Split(subscriptionId, "-") + parts := strings.Split(subscriptionID, "-") if err := n.RegisterScanner(nuke.Subscription, libscanner.New(fmt.Sprintf("sub/%s", parts[:1][0]), subResourceTypes, &nuke.ListerOpts{ Authorizers: tenant.Authorizers, - TenantId: tenant.ID, - SubscriptionId: subscriptionId, - Locations: parsedConfig.Regions, + TenantID: tenant.ID, + SubscriptionID: subscriptionID, + Regions: parsedConfig.Regions, })); err != nil { return err } } + for subscriptionID, resourceGroups := range tenant.ResourceGroups { + for _, rg := range resourceGroups { + logrus.Debug("registering scanner for resource group") + if err := n.RegisterScanner(nuke.ResourceGroup, libscanner.New(fmt.Sprintf("rg/%s", rg), rgResourceTypes, &nuke.ListerOpts{ + Authorizers: tenant.Authorizers, + TenantID: tenant.ID, + SubscriptionID: subscriptionID, + ResourceGroup: rg, + Regions: parsedConfig.Regions, + })); err != nil { + return err + } + } + } + logrus.Debug("running ...") return n.Run(c.Context) @@ -169,8 +213,9 @@ func init() { Usage: "exclude this specific resource (this overrides everything)", }, &cli.BoolFlag{ - Name: "quiet", - Usage: "hide filtered messages", + Name: "quiet", + Aliases: []string{"q"}, + Usage: "hide filtered messages", }, &cli.BoolFlag{ Name: "no-dry-run", diff --git a/pkg/config/config.go b/pkg/config/config.go index cdd3a20..7a716ae 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -2,8 +2,10 @@ package config import ( "fmt" - "github.com/ekristen/libnuke/pkg/config" + "github.com/sirupsen/logrus" + + "github.com/ekristen/libnuke/pkg/config" ) // New creates a new extended configuration from a file. This is necessary because we are extended the default diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 2c777e0..b968bf8 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -1,14 +1,16 @@ package config import ( + "io" + "testing" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + libconfig "github.com/ekristen/libnuke/pkg/config" "github.com/ekristen/libnuke/pkg/filter" "github.com/ekristen/libnuke/pkg/settings" "github.com/ekristen/libnuke/pkg/types" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - "io" - "testing" ) func TestLoadExampleConfig(t *testing.T) { diff --git a/pkg/nuke/resource.go b/pkg/nuke/resource.go index 494fe58..06a7e53 100644 --- a/pkg/nuke/resource.go +++ b/pkg/nuke/resource.go @@ -1,8 +1,11 @@ package nuke import ( - "github.com/ekristen/azure-nuke/pkg/azure" + "regexp" + "github.com/ekristen/libnuke/pkg/registry" + + "github.com/ekristen/azure-nuke/pkg/azure" ) const ( @@ -11,10 +14,23 @@ const ( ResourceGroup registry.Scope = "resource-group" ) +var ( + ResourceGroupRegex = regexp.MustCompile(`/resourceGroups/([^/]+)`) +) + type ListerOpts struct { Authorizers *azure.Authorizers - TenantId string - SubscriptionId string + TenantID string + SubscriptionID string ResourceGroup string - Locations []string + Regions []string +} + +func GetResourceGroupFromID(id string) *string { + matches := ResourceGroupRegex.FindStringSubmatch(id) + if len(matches) == 2 { + return &matches[1] + } + + return nil } diff --git a/resources/aad-group.go b/resources/aad-group.go index 5116c93..0e1bd0d 100644 --- a/resources/aad-group.go +++ b/resources/aad-group.go @@ -31,7 +31,7 @@ type AzureAdGroupLister struct { func (l AzureAdGroupLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", AzureAdGroupResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", AzureAdGroupResource).WithField("s", opts.SubscriptionID) client := msgraph.NewGroupsClient() client.BaseClient.Authorizer = opts.Authorizers.MicrosoftGraph @@ -43,18 +43,20 @@ func (l AzureAdGroupLister) List(_ context.Context, o interface{}) ([]resource.R ctx := context.Background() - groups, _, err := client.List(ctx, odata.Query{}) + entities, _, err := client.List(ctx, odata.Query{}) if err != nil { return nil, err } log.Trace("listing resources") - for _, group := range *groups { + for i := range *entities { + entity := &(*entities)[i] + resources = append(resources, &AzureAdGroup{ client: client, - id: group.ID(), - name: group.DisplayName, + id: entity.ID(), + name: entity.DisplayName, }) } diff --git a/resources/aad-user.go b/resources/aad-user.go index 156b624..bd606bb 100644 --- a/resources/aad-user.go +++ b/resources/aad-user.go @@ -34,7 +34,7 @@ type AzureADUserLister struct { func (l AzureADUserLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", AzureADUserResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", AzureADUserResource).WithField("s", opts.SubscriptionID) client := msgraph.NewUsersClient() client.BaseClient.Authorizer = opts.Authorizers.Graph @@ -44,19 +44,21 @@ func (l AzureADUserLister) List(ctx context.Context, o interface{}) ([]resource. log.Trace("attempting to list azure ad users") - users, _, err := client.List(ctx, odata.Query{}) + entities, _, err := client.List(ctx, odata.Query{}) if err != nil { return nil, err } log.Trace("listing resources") - for _, user := range *users { + for i := range *entities { + entity := &(*entities)[i] + resources = append(resources, &AzureADUser{ client: client, - id: user.ID(), - name: user.DisplayName, - upn: user.UserPrincipalName, + id: entity.ID(), + name: entity.DisplayName, + upn: entity.UserPrincipalName, }) } diff --git a/resources/app-service-plan.go b/resources/app-service-plan.go index 919fdec..28d7005 100644 --- a/resources/app-service-plan.go +++ b/resources/app-service-plan.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/web/mgmt/2021-03-01/web" + "github.com/Azure/azure-sdk-for-go/services/web/mgmt/2021-03-01/web" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const AppServicePlanResource = "AppServicePlan" func init() { registry.Register(®istry.Registration{ Name: AppServicePlanResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &AppServicePlanLister{}, }) } @@ -31,9 +31,9 @@ type AppServicePlanLister struct { func (l AppServicePlanLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", AppServicePlanResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", AppServicePlanResource).WithField("s", opts.SubscriptionID) - client := web.NewAppServicePlansClient(opts.SubscriptionId) + client := web.NewAppServicePlansClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 diff --git a/resources/application-certificate.go b/resources/application-certificate.go index 3c2ac9f..a25c186 100644 --- a/resources/application-certificate.go +++ b/resources/application-certificate.go @@ -29,7 +29,7 @@ type ApplicationCertificate struct { client *msgraph.ApplicationsClient id *string name *string - appId *string + appID *string } func (r *ApplicationCertificate) Filter() error { @@ -59,7 +59,7 @@ type ApplicationCertificateLister struct { func (l ApplicationCertificateLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", ApplicationCertificateResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", ApplicationCertificateResource).WithField("s", opts.SubscriptionID) client := msgraph.NewApplicationsClient() client.BaseClient.Authorizer = opts.Authorizers.Graph @@ -76,13 +76,15 @@ func (l ApplicationCertificateLister) List(ctx context.Context, o interface{}) ( log.Trace("listing application certificate") - for _, entity := range *entities { + for i := range *entities { + entity := &(*entities)[i] + for _, cred := range *entity.KeyCredentials { resources = append(resources, &ApplicationCertificate{ client: client, id: cred.KeyId, name: cred.DisplayName, - appId: entity.ID(), + appID: entity.ID(), }) } } diff --git a/resources/application-federated-credential.go b/resources/application-federated-credential.go index 7cba02d..7329ee1 100644 --- a/resources/application-federated-credential.go +++ b/resources/application-federated-credential.go @@ -29,7 +29,7 @@ type ApplicationFederatedCredential struct { client *msgraph.ApplicationsClient id *string name *string - appId *string + appID *string uniqueName *string } @@ -38,7 +38,7 @@ func (r *ApplicationFederatedCredential) Filter() error { } func (r *ApplicationFederatedCredential) Remove(ctx context.Context) error { - _, err := r.client.DeleteFederatedIdentityCredential(context.TODO(), *r.appId, *r.id) + _, err := r.client.DeleteFederatedIdentityCredential(context.TODO(), *r.appID, *r.id) return err } @@ -46,14 +46,14 @@ func (r *ApplicationFederatedCredential) Properties() types.Properties { properties := types.NewProperties() properties.Set("Name", *r.name) - properties.Set("AppID", *r.appId) + properties.Set("AppID", *r.appID) properties.Set("AppUniqueName", r.uniqueName) return properties } func (r *ApplicationFederatedCredential) String() string { - return *r.id + return *r.name } type ApplicationFederatedCredentialLister struct { @@ -62,7 +62,7 @@ type ApplicationFederatedCredentialLister struct { func (l ApplicationFederatedCredentialLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", ApplicationFederatedCredentialResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", ApplicationFederatedCredentialResource).WithField("s", opts.SubscriptionID) client := msgraph.NewApplicationsClient() client.BaseClient.Authorizer = opts.Authorizers.Graph @@ -81,7 +81,9 @@ func (l ApplicationFederatedCredentialLister) List(_ context.Context, o interfac log.Trace("listing application federated creds") - for _, entity := range *entities { + for i := range *entities { + entity := &(*entities)[i] + creds, _, err := client.ListFederatedIdentityCredentials(ctx, *entity.ID(), odata.Query{}) if err != nil { return nil, err @@ -91,7 +93,7 @@ func (l ApplicationFederatedCredentialLister) List(_ context.Context, o interfac client: client, id: cred.ID, name: cred.Name, - appId: entity.ID(), + appID: entity.ID(), uniqueName: entity.UniqueName, }) } diff --git a/resources/application-secret.go b/resources/application-secret.go index a64c1ad..ddc5770 100644 --- a/resources/application-secret.go +++ b/resources/application-secret.go @@ -29,7 +29,7 @@ type ApplicationSecret struct { client *msgraph.ApplicationsClient id *string name *string - appId *string + appID *string appName *string } @@ -61,7 +61,7 @@ type ApplicationSecretLister struct { func (l ApplicationSecretLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", ApplicationSecretResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", ApplicationSecretResource).WithField("s", opts.SubscriptionID) client := msgraph.NewApplicationsClient() client.BaseClient.Authorizer = opts.Authorizers.Graph @@ -78,13 +78,15 @@ func (l ApplicationSecretLister) List(ctx context.Context, o interface{}) ([]res log.Trace("listing application secrets") - for _, entity := range *entities { + for i := range *entities { + entity := &(*entities)[i] + for _, cred := range *entity.PasswordCredentials { resources = append(resources, &ApplicationSecret{ client: client, id: cred.KeyId, name: cred.DisplayName, - appId: entity.ID(), + appID: entity.ID(), appName: entity.DisplayName, }) } diff --git a/resources/application.go b/resources/application.go index d31993f..6c53eeb 100644 --- a/resources/application.go +++ b/resources/application.go @@ -32,7 +32,7 @@ type ApplicationLister struct { func (l ApplicationLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", ApplicationResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", ApplicationResource).WithField("s", opts.SubscriptionID) client := msgraph.NewApplicationsClient() client.BaseClient.Authorizer = opts.Authorizers.Graph @@ -49,7 +49,9 @@ func (l ApplicationLister) List(ctx context.Context, o interface{}) ([]resource. log.Trace("listing applications") - for _, entity := range *entities { + for i := range *entities { + entity := &(*entities)[i] + resources = append(resources, &Application{ client: client, id: entity.ID(), diff --git a/resources/budget.go b/resources/budget.go index f66e511..0babf20 100644 --- a/resources/budget.go +++ b/resources/budget.go @@ -33,7 +33,7 @@ type Budget struct { client *budgets.BudgetsClient name *string id *string - subscriptionId *string + subscriptionID *string } type BudgetLister struct{} @@ -41,7 +41,7 @@ type BudgetLister struct{} func (l BudgetLister) List(pctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", BudgetResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", BudgetResource).WithField("s", opts.SubscriptionID) resources := make([]resource.Resource, 0) @@ -50,9 +50,6 @@ func (l BudgetLister) List(pctx context.Context, o interface{}) ([]resource.Reso return nil, err } client.Client.Authorizer = opts.Authorizers.Management - //client.Authorizer = opts.Authorizers.Management - //client.RetryAttempts = 1 - //client.RetryDuration = time.Second * 2 log.Trace("attempting to list budgets for subscription") @@ -60,7 +57,7 @@ func (l BudgetLister) List(pctx context.Context, o interface{}) ([]resource.Reso defer cancel() list, err := client.List(ctx, commonids.ScopeId{ - Scope: fmt.Sprintf("/subscriptions/%s", opts.SubscriptionId), + Scope: fmt.Sprintf("/subscriptions/%s", opts.SubscriptionID), }) if err != nil { return nil, err @@ -73,7 +70,7 @@ func (l BudgetLister) List(pctx context.Context, o interface{}) ([]resource.Reso client: client, name: entry.Name, id: entry.Id, - subscriptionId: ptr.String(opts.SubscriptionId), // note: this is just the guid + subscriptionID: ptr.String(opts.SubscriptionID), // note: this is just the guid }) } @@ -87,7 +84,7 @@ func (r *Budget) Remove(ctx context.Context) error { defer cancel() _, err := r.client.Delete(ctx, budgets.ScopedBudgetId{ - Scope: fmt.Sprintf("/subscriptions/%s", ptr.ToString(r.subscriptionId)), + Scope: fmt.Sprintf("/subscriptions/%s", ptr.ToString(r.subscriptionID)), BudgetName: ptr.ToString(r.name), }) return err diff --git a/resources/container-registry.go b/resources/container-registry.go index 15132ae..07a42d8 100644 --- a/resources/container-registry.go +++ b/resources/container-registry.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2019-05-01/containerregistry" + "github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2019-05-01/containerregistry" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const ContainerRegistryResource = "ContainerRegistry" func init() { registry.Register(®istry.Registration{ Name: ContainerRegistryResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &ContainerRegistryLister{}, }) } @@ -29,6 +29,8 @@ type ContainerRegistry struct { client containerregistry.RegistriesClient name *string resourceGroup *string + region *string + tags map[string]*string } func (r *ContainerRegistry) Remove(ctx context.Context) error { @@ -41,6 +43,11 @@ func (r *ContainerRegistry) Properties() types.Properties { properties.Set("Name", *r.name) properties.Set("ResourceGroup", *r.resourceGroup) + properties.Set("Region", *r.region) + + for k, v := range r.tags { + properties.SetTag(&k, v) + } return properties } @@ -55,9 +62,9 @@ type ContainerRegistryLister struct { func (l ContainerRegistryLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", ContainerRegistryResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", ContainerRegistryResource).WithField("s", opts.SubscriptionID) - client := containerregistry.NewRegistriesClient(opts.SubscriptionId) + client := containerregistry.NewRegistriesClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -66,7 +73,7 @@ func (l ContainerRegistryLister) List(ctx context.Context, o interface{}) ([]res log.Trace("attempting to list container registries") - list, err := client.List(ctx) + list, err := client.ListByResourceGroup(ctx, opts.ResourceGroup) if err != nil { return nil, err } @@ -80,6 +87,8 @@ func (l ContainerRegistryLister) List(ctx context.Context, o interface{}) ([]res client: client, name: entity.Name, resourceGroup: &opts.ResourceGroup, + region: entity.Location, + tags: entity.Tags, }) } diff --git a/resources/disk.go b/resources/disk.go index 5aa8d0f..17eb646 100644 --- a/resources/disk.go +++ b/resources/disk.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-04-01/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-04-01/compute" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const DiskResource = "Disk" func init() { registry.Register(®istry.Registration{ Name: DiskResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &DiskLister{}, DependsOn: []string{ VirtualMachineResource, @@ -30,12 +30,14 @@ func init() { type Disk struct { client compute.DisksClient - name string - rg string + name *string + rg *string + region *string + tags map[string]*string } func (r *Disk) Remove(ctx context.Context) error { - _, err := r.client.Delete(ctx, r.rg, r.name) + _, err := r.client.Delete(ctx, *r.rg, *r.name) return err } @@ -49,7 +51,7 @@ func (r *Disk) Properties() types.Properties { } func (r *Disk) String() string { - return r.name + return *r.name } type DiskLister struct { @@ -58,9 +60,9 @@ type DiskLister struct { func (l DiskLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", DiskResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", DiskResource).WithField("s", opts.SubscriptionID) - client := compute.NewDisksClient(opts.SubscriptionId) + client := compute.NewDisksClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -81,8 +83,10 @@ func (l DiskLister) List(ctx context.Context, o interface{}) ([]resource.Resourc for _, g := range list.Values() { resources = append(resources, &Disk{ client: client, - name: *g.Name, - rg: opts.ResourceGroup, + name: g.Name, + rg: &opts.ResourceGroup, + region: g.Location, + tags: g.Tags, }) } diff --git a/resources/dns-zone.go b/resources/dns-zone.go index cc06084..3270c0a 100644 --- a/resources/dns-zone.go +++ b/resources/dns-zone.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns" + "github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const DNSZoneResource = "DNSZone" func init() { registry.Register(®istry.Registration{ Name: DNSZoneResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &DNSZoneLister{}, }) } @@ -33,12 +33,12 @@ func (l DNSZoneLister) List(ctx context.Context, o interface{}) ([]resource.Reso log := logrus.WithFields(logrus.Fields{ "r": DNSZoneResource, - "s": opts.SubscriptionId, + "s": opts.SubscriptionID, }) log.Trace("start") - client := dns.NewZonesClient(opts.SubscriptionId) + client := dns.NewZonesClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -58,10 +58,12 @@ func (l DNSZoneLister) List(ctx context.Context, o interface{}) ([]resource.Reso for _, g := range list.Values() { log.Trace("adding entity to list") resources = append(resources, &DNSZone{ - client: client, - name: g.Name, - location: g.Location, - rg: &opts.ResourceGroup, + rg: &opts.ResourceGroup, + + client: client, + name: g.Name, + region: g.Location, + tags: g.Tags, }) } @@ -76,10 +78,11 @@ func (l DNSZoneLister) List(ctx context.Context, o interface{}) ([]resource.Reso } type DNSZone struct { - client dns.ZonesClient - name *string - location *string - rg *string + client dns.ZonesClient + name *string + region *string + rg *string + tags map[string]*string } func (r *DNSZone) Remove(ctx context.Context) error { @@ -90,7 +93,13 @@ func (r *DNSZone) Remove(ctx context.Context) error { func (r *DNSZone) Properties() types.Properties { properties := types.NewProperties() - properties.Set("Name", *r.name) + properties.Set("Name", r.name) + properties.Set("ResourceGroup", r.rg) + properties.Set("Region", r.region) + + for k, v := range r.tags { + properties.SetTag(&k, v) + } return properties } diff --git a/resources/ip-allocation.go b/resources/ip-allocation.go index e8a64ec..9f65ec9 100644 --- a/resources/ip-allocation.go +++ b/resources/ip-allocation.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-05-01/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-05-01/network" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const IPAllocationResource = "IPAllocation" func init() { registry.Register(®istry.Registration{ Name: IPAllocationResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &IPAllocationLister{}, }) } @@ -31,9 +31,9 @@ type IPAllocationLister struct { func (l IPAllocationLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", IPAllocationResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", IPAllocationResource).WithField("s", opts.SubscriptionID) - client := network.NewIPAllocationsClient(opts.SubscriptionId) + client := network.NewIPAllocationsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -53,9 +53,11 @@ func (l IPAllocationLister) List(ctx context.Context, o interface{}) ([]resource log.Trace("list not done") for _, g := range list.Values() { resources = append(resources, &IPAllocation{ + rg: &opts.ResourceGroup, client: client, name: g.Name, - rg: &opts.ResourceGroup, + region: g.Location, + tags: g.Tags, }) } @@ -73,6 +75,8 @@ type IPAllocation struct { client network.IPAllocationsClient name *string rg *string + region *string + tags map[string]*string } func (r *IPAllocation) Remove(ctx context.Context) error { @@ -83,8 +87,13 @@ func (r *IPAllocation) Remove(ctx context.Context) error { func (r *IPAllocation) Properties() types.Properties { properties := types.NewProperties() - properties.Set("Name", *r.name) - properties.Set("ResourceGroup", *r.rg) + properties.Set("Name", r.name) + properties.Set("ResourceGroup", r.rg) + properties.Set("Region", r.region) + + for k, v := range r.tags { + properties.SetTag(&k, v) + } return properties } diff --git a/resources/key-vault.go b/resources/key-vault.go index 66cbc13..3212163 100644 --- a/resources/key-vault.go +++ b/resources/key-vault.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2019-09-01/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2019-09-01/keyvault" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const KeyVaultResource = "KeyVault" func init() { registry.Register(®istry.Registration{ Name: KeyVaultResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &KeyVaultLister{}, }) } @@ -31,9 +31,9 @@ type KeyVaultLister struct { func (l KeyVaultLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", KeyVaultResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", KeyVaultResource).WithField("s", opts.SubscriptionID) - client := keyvault.NewVaultsClient(opts.SubscriptionId) + client := keyvault.NewVaultsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -53,9 +53,12 @@ func (l KeyVaultLister) List(ctx context.Context, o interface{}) ([]resource.Res log.Trace("list not done") for _, g := range list.Values() { resources = append(resources, &KeyVault{ - client: client, - name: *g.Name, - rg: opts.ResourceGroup, + client: client, + name: g.Name, + region: g.Location, + rg: opts.ResourceGroup, + subscriptionID: opts.SubscriptionID, + tags: g.Tags, }) } @@ -70,13 +73,17 @@ func (l KeyVaultLister) List(ctx context.Context, o interface{}) ([]resource.Res } type KeyVault struct { - client keyvault.VaultsClient - name string - rg string + client keyvault.VaultsClient + name *string + region *string + rg string + subscriptionID string + tags map[string]*string } func (r *KeyVault) Remove(ctx context.Context) error { - _, err := r.client.Delete(ctx, r.rg, r.name) + _, err := r.client.Delete(ctx, r.rg, *r.name) + return err } @@ -84,10 +91,17 @@ func (r *KeyVault) Properties() types.Properties { properties := types.NewProperties() properties.Set("Name", r.name) + properties.Set("Region", r.region) + properties.Set("ResourceGroup", r.rg) + properties.Set("SubscriptionID", r.subscriptionID) + + for k, v := range r.tags { + properties.SetTag(&k, v) + } return properties } func (r *KeyVault) String() string { - return r.name + return *r.name } diff --git a/resources/network-interface.go b/resources/network-interface.go index ca0278d..db14b81 100644 --- a/resources/network-interface.go +++ b/resources/network-interface.go @@ -6,7 +6,9 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-05-01/network" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/networkinterfaces" + "github.com/hashicorp/go-azure-sdk/sdk/environments" "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +22,7 @@ const NetworkInterfaceResource = "NetworkInterface" func init() { registry.Register(®istry.Registration{ Name: NetworkInterfaceResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &NetworkInterfaceLister{}, }) } @@ -31,37 +33,37 @@ type NetworkInterfaceLister struct { func (l NetworkInterfaceLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", NetworkInterfaceResource).WithField("s", opts.SubscriptionId) + ctx, cancel := context.WithDeadline(ctx, time.Now().Add(30*time.Second)) + defer cancel() - client := network.NewInterfacesClient(opts.SubscriptionId) - client.Authorizer = opts.Authorizers.Management - client.RetryAttempts = 1 - client.RetryDuration = time.Second * 2 + log := logrus.WithField("r", NetworkInterfaceResource).WithField("s", opts.SubscriptionID) resources := make([]resource.Resource, 0) + client, err := networkinterfaces.NewNetworkInterfacesClientWithBaseURI(environments.AzurePublic().ResourceManager) + if err != nil { + return resources, err + } + client.Client.Authorizer = opts.Authorizers.Management + log.Trace("attempting to list network interfaces") - list, err := client.List(ctx, opts.ResourceGroup) + list, err := client.ListComplete(ctx, commonids.NewResourceGroupID(opts.SubscriptionID, opts.ResourceGroup)) if err != nil { return nil, err } log.Trace("listing ....") - for list.NotDone() { - log.Trace("list not done") - for _, g := range list.Values() { - resources = append(resources, &NetworkInterface{ - client: client, - name: g.Name, - rg: &opts.ResourceGroup, - }) - } - - if err := list.NextWithContext(ctx); err != nil { - return nil, err - } + for _, g := range list.Items { + resources = append(resources, &NetworkInterface{ + client: client, + name: g.Name, + region: g.Location, + tags: g.Tags, + rg: &opts.ResourceGroup, + subscriptionID: &opts.SubscriptionID, + }) } log.Trace("done listing network interfaces") @@ -70,21 +72,32 @@ func (l NetworkInterfaceLister) List(ctx context.Context, o interface{}) ([]reso } type NetworkInterface struct { - client network.InterfacesClient - name *string - rg *string + client *networkinterfaces.NetworkInterfacesClient + name *string + rg *string + region *string + subscriptionID *string + tags *map[string]string } func (r *NetworkInterface) Remove(ctx context.Context) error { - _, err := r.client.Delete(ctx, *r.rg, *r.name) + ctx, cancel := context.WithDeadline(ctx, time.Now().Add(30*time.Second)) + defer cancel() + + _, err := r.client.Delete(ctx, commonids.NewNetworkInterfaceID(*r.subscriptionID, *r.rg, *r.name)) return err } func (r *NetworkInterface) Properties() types.Properties { properties := types.NewProperties() - properties.Set("Name", *r.name) - properties.Set("ResourceGroup", *r.rg) + properties.Set("Name", r.name) + properties.Set("ResourceGroup", r.rg) + properties.Set("Region", r.region) + + for k, v := range *r.tags { + properties.SetTag(&k, v) + } return properties } diff --git a/resources/network-security-group.go b/resources/network-security-group.go index 7f5dcd7..e6e2a57 100644 --- a/resources/network-security-group.go +++ b/resources/network-security-group.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-05-01/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2022-05-01/network" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,16 +20,17 @@ const NetworkSecurityGroupResource = "NetworkSecurityGroup" func init() { registry.Register(®istry.Registration{ Name: NetworkSecurityGroupResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &NetworkSecurityGroupLister{}, }) } type NetworkSecurityGroup struct { - client network.SecurityGroupsClient - name *string - location *string - rg *string + client network.SecurityGroupsClient + name *string + region *string + rg *string + tags map[string]*string } func (r *NetworkSecurityGroup) Remove(ctx context.Context) error { @@ -40,8 +41,12 @@ func (r *NetworkSecurityGroup) Remove(ctx context.Context) error { func (r *NetworkSecurityGroup) Properties() types.Properties { properties := types.NewProperties() - properties.Set("Name", *r.name) - properties.Set("Location", *r.location) + properties.Set("Name", r.name) + properties.Set("Region", r.region) + + for k, v := range r.tags { + properties.SetTag(&k, v) + } return properties } @@ -56,9 +61,9 @@ type NetworkSecurityGroupLister struct { func (l NetworkSecurityGroupLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", NetworkSecurityGroupResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", NetworkSecurityGroupResource).WithField("s", opts.SubscriptionID) - client := network.NewSecurityGroupsClient(opts.SubscriptionId) + client := network.NewSecurityGroupsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -78,10 +83,11 @@ func (l NetworkSecurityGroupLister) List(ctx context.Context, o interface{}) ([] log.Trace("list not done") for _, g := range list.Values() { resources = append(resources, &NetworkSecurityGroup{ - client: client, - name: g.Name, - location: g.Location, - rg: &opts.ResourceGroup, + client: client, + name: g.Name, + region: g.Location, + rg: &opts.ResourceGroup, + tags: g.Tags, }) } diff --git a/resources/policy-assignment.go b/resources/policy-assignment.go index 9df0a23..f58a603 100644 --- a/resources/policy-assignment.go +++ b/resources/policy-assignment.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/preview/resources/mgmt/2021-06-01-preview/policy" + "github.com/Azure/azure-sdk-for-go/services/preview/resources/mgmt/2021-06-01-preview/policy" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -57,9 +57,9 @@ type PolicyAssignmentLister struct { func (l PolicyAssignmentLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", PolicyAssignmentResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", PolicyAssignmentResource).WithField("s", opts.SubscriptionID) - client := policy.NewAssignmentsClient(opts.SubscriptionId) + client := policy.NewAssignmentsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 diff --git a/resources/policy-definition.go b/resources/policy-definition.go index bd4f7eb..46747da 100644 --- a/resources/policy-definition.go +++ b/resources/policy-definition.go @@ -2,13 +2,12 @@ package resources import ( "context" - "fmt" "time" "github.com/gotidy/ptr" "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/preview/resources/mgmt/2021-06-01-preview/policy" + "github.com/Azure/azure-sdk-for-go/services/preview/resources/mgmt/2021-06-01-preview/policy" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -34,13 +33,6 @@ type PolicyDefinition struct { policyType string } -func (r *PolicyDefinition) Filter() error { - if r.policyType == "BuiltIn" || r.policyType == "Static" { - return fmt.Errorf("cannot delete policies with type %s", r.policyType) - } - return nil -} - func (r *PolicyDefinition) Remove(ctx context.Context) error { _, err := r.client.Delete(ctx, r.name) return err @@ -66,9 +58,9 @@ type PolicyDefinitionLister struct { func (l PolicyDefinitionLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", PolicyDefinitionResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", PolicyDefinitionResource).WithField("s", opts.SubscriptionID) - client := policy.NewDefinitionsClient(opts.SubscriptionId) + client := policy.NewDefinitionsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -87,6 +79,13 @@ func (l PolicyDefinitionLister) List(ctx context.Context, o interface{}) ([]reso for list.NotDone() { log.Trace("list not done") for _, g := range list.Values() { + // Filtering out BuiltIn Policy Definitions, because otherwise it needlessly adds 3000+ + // resources that have to get filtered out later. This instead does it optimistically here. + // Ideally we'd be able to use filter above, but it does not work. Thanks, Azure. :facepalm: + if g.PolicyType == "BuiltIn" || g.PolicyType == "Static" { + continue + } + resources = append(resources, &PolicyDefinition{ client: client, name: *g.Name, diff --git a/resources/private-dns-zone.go b/resources/private-dns-zone.go index dba5569..67ee3a5 100644 --- a/resources/private-dns-zone.go +++ b/resources/private-dns-zone.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" + "github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -26,10 +26,11 @@ func init() { } type PrivateDNSZone struct { - client privatedns.PrivateZonesClient - name *string - location *string - rg *string + client privatedns.PrivateZonesClient + name *string + region *string + rg *string + tags map[string]*string } func (r *PrivateDNSZone) Remove(ctx context.Context) error { @@ -40,8 +41,13 @@ func (r *PrivateDNSZone) Remove(ctx context.Context) error { func (r *PrivateDNSZone) Properties() types.Properties { properties := types.NewProperties() - properties.Set("Name", *r.name) - properties.Set("ResourceGroup", *r.rg) + properties.Set("Name", r.name) + properties.Set("ResourceGroup", r.rg) + properties.Set("Region", r.region) + + for k, v := range r.tags { + properties.SetTag(&k, v) + } return properties } @@ -58,12 +64,12 @@ func (l PrivateDNSZoneLister) List(ctx context.Context, o interface{}) ([]resour log := logrus.WithFields(logrus.Fields{ "r": PrivateDNSZoneResource, - "s": opts.SubscriptionId, + "s": opts.SubscriptionID, }) log.Trace("start") - client := privatedns.NewPrivateZonesClient(opts.SubscriptionId) + client := privatedns.NewPrivateZonesClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -83,10 +89,11 @@ func (l PrivateDNSZoneLister) List(ctx context.Context, o interface{}) ([]resour for _, g := range list.Values() { log.Trace("adding entity to list") resources = append(resources, &PrivateDNSZone{ - client: client, - name: g.Name, - location: g.Location, - rg: &opts.ResourceGroup, + client: client, + name: g.Name, + region: g.Location, + rg: &opts.ResourceGroup, + tags: g.Tags, }) } diff --git a/resources/public-ip-address.go b/resources/public-ip-address.go index 94a4203..16d8799 100644 --- a/resources/public-ip-address.go +++ b/resources/public-ip-address.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-05-01/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2022-05-01/network" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const PublicIPAddressesResource = "PublicIPAddresses" func init() { registry.Register(®istry.Registration{ Name: PublicIPAddressesResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &PublicIPAddressesLister{}, }) } @@ -29,6 +29,8 @@ type PublicIPAddresses struct { client network.PublicIPAddressesClient name *string rg *string + region *string + tags map[string]*string } func (r *PublicIPAddresses) Remove(ctx context.Context) error { @@ -41,6 +43,7 @@ func (r *PublicIPAddresses) Properties() types.Properties { properties.Set("Name", *r.name) properties.Set("ResourceGroup", *r.rg) + properties.Set("Region", *r.region) return properties } @@ -55,9 +58,9 @@ type PublicIPAddressesLister struct { func (l PublicIPAddressesLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", PublicIPAddressesResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", PublicIPAddressesResource).WithField("s", opts.SubscriptionID) - client := network.NewPublicIPAddressesClient(opts.SubscriptionId) + client := network.NewPublicIPAddressesClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -80,6 +83,8 @@ func (l PublicIPAddressesLister) List(ctx context.Context, o interface{}) ([]res client: client, name: g.Name, rg: &opts.ResourceGroup, + region: g.Location, + tags: g.Tags, }) } diff --git a/resources/recoveryservices-backup-policy.go b/resources/recoveryservices-backup-policy.go index 39a94fd..1a67097 100644 --- a/resources/recoveryservices-backup-policy.go +++ b/resources/recoveryservices-backup-policy.go @@ -25,7 +25,7 @@ const RecoveryServicesBackupPolicyResource = "RecoveryServicesBackupPolicy" func init() { registry.Register(®istry.Registration{ Name: RecoveryServicesBackupPolicyResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &RecoveryServicesBackupPolicyLister{}, DependsOn: []string{ RecoveryServicesBackupProtectedItemResource, @@ -38,9 +38,9 @@ type RecoveryServicesBackupPolicy struct { protectionsClient protectionpolicies.ProtectionPoliciesClient id *string name *string - location *string + region *string rg string - backupPolicyId protectionpolicies.BackupPolicyId + backupPolicyID protectionpolicies.BackupPolicyId } func (r *RecoveryServicesBackupPolicy) Filter() error { @@ -48,7 +48,7 @@ func (r *RecoveryServicesBackupPolicy) Filter() error { } func (r *RecoveryServicesBackupPolicy) Remove(ctx context.Context) error { - _, err := r.protectionsClient.Delete(ctx, r.backupPolicyId) + _, err := r.protectionsClient.Delete(ctx, r.backupPolicyID) return err } @@ -56,7 +56,7 @@ func (r *RecoveryServicesBackupPolicy) Properties() types.Properties { properties := types.NewProperties() properties.Set("Name", r.name) - properties.Set("Location", r.location) + properties.Set("Region", r.region) properties.Set("ResourceGroup", r.rg) return properties @@ -77,7 +77,7 @@ func (l RecoveryServicesBackupPolicyLister) List(ctx context.Context, o interfac log := logrus. WithField("r", RecoveryServicesBackupPolicyResource). - WithField("s", opts.SubscriptionId). + WithField("s", opts.SubscriptionID). WithField("rg", opts.ResourceGroup) log.Trace("creating client") @@ -88,12 +88,16 @@ func (l RecoveryServicesBackupPolicyLister) List(ctx context.Context, o interfac } vaultsClient.Client.Authorizer = opts.Authorizers.Management - client := backuppolicies.NewBackupPoliciesClientWithBaseURI("https://management.azure.com") // TODO: pass in the endpoint + // TODO: pass in the endpoint + client := + backuppolicies.NewBackupPoliciesClientWithBaseURI("https://management.azure.com") client.Client.Authorizer = opts.Authorizers.Management client.Client.RetryAttempts = 1 client.Client.RetryDuration = time.Second * 2 - protectionsClient := protectionpolicies.NewProtectionPoliciesClientWithBaseURI("https://management.azure.com") // TODO: pass in the endpoint + // TODO: pass in the endpoint + protectionsClient := + protectionpolicies.NewProtectionPoliciesClientWithBaseURI("https://management.azure.com") protectionsClient.Client.Authorizer = opts.Authorizers.Management protectionsClient.Client.RetryAttempts = 1 protectionsClient.Client.RetryDuration = time.Second * 2 @@ -102,14 +106,16 @@ func (l RecoveryServicesBackupPolicyLister) List(ctx context.Context, o interfac log.Trace("listing resources") - vaultsRes, err := vaultsClient.ListByResourceGroupComplete(ctx, commonids.NewResourceGroupID(opts.SubscriptionId, opts.ResourceGroup)) + vaultsRes, err := + vaultsClient.ListByResourceGroupComplete( + ctx, commonids.NewResourceGroupID(opts.SubscriptionID, opts.ResourceGroup)) if err != nil { return nil, err } for _, v := range vaultsRes.Items { - vaultId := backuppolicies.NewVaultID(opts.SubscriptionId, opts.ResourceGroup, ptr.ToString(v.Name)) - items, err := client.ListComplete(ctx, vaultId, backuppolicies.DefaultListOperationOptions()) + vaultID := backuppolicies.NewVaultID(opts.SubscriptionID, opts.ResourceGroup, ptr.ToString(v.Name)) + items, err := client.ListComplete(ctx, vaultID, backuppolicies.DefaultListOperationOptions()) if err != nil { return nil, err } @@ -120,9 +126,10 @@ func (l RecoveryServicesBackupPolicyLister) List(ctx context.Context, o interfac protectionsClient: protectionsClient, id: item.Id, name: item.Name, - location: item.Location, + region: item.Location, rg: opts.ResourceGroup, - backupPolicyId: protectionpolicies.NewBackupPolicyID(opts.SubscriptionId, opts.ResourceGroup, ptr.ToString(v.Name), ptr.ToString(item.Name)), + backupPolicyID: protectionpolicies.NewBackupPolicyID( + opts.SubscriptionID, opts.ResourceGroup, ptr.ToString(v.Name), ptr.ToString(item.Name)), }) } } diff --git a/resources/recoveryservices-backup-protecteditem.go b/resources/recoveryservices-backup-protecteditem.go index 86928a6..f606eba 100644 --- a/resources/recoveryservices-backup-protecteditem.go +++ b/resources/recoveryservices-backup-protecteditem.go @@ -25,7 +25,7 @@ const RecoveryServicesBackupProtectedItemResource = "RecoveryServicesBackupProte func init() { registry.Register(®istry.Registration{ Name: RecoveryServicesBackupProtectedItemResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &RecoveryServicesBackupProtectedItemLister{}, }) } @@ -36,7 +36,7 @@ type RecoveryServicesBackupProtectedItem struct { vaultName *string id *string name *string - location *string + region *string resourceGroup *string containerName *string backupFabric *string @@ -47,7 +47,9 @@ func (r *RecoveryServicesBackupProtectedItem) Filter() error { } func (r *RecoveryServicesBackupProtectedItem) Remove(ctx context.Context) error { - _, err := r.itemClient.Delete(ctx, to.String(r.vaultName), to.String(r.resourceGroup), to.String(r.backupFabric), to.String(r.containerName), to.String(r.name), nil) + _, err := r.itemClient.Delete( + ctx, to.String(r.vaultName), to.String(r.resourceGroup), + to.String(r.backupFabric), to.String(r.containerName), to.String(r.name), nil) return err } @@ -56,7 +58,7 @@ func (r *RecoveryServicesBackupProtectedItem) Properties() types.Properties { properties.Set("ID", r.id) properties.Set("Name", r.name) - properties.Set("Location", r.location) + properties.Set("Region", r.region) properties.Set("ResourceGroup", r.resourceGroup) properties.Set("VaultName", r.vaultName) properties.Set("ContainerName", r.containerName) @@ -81,21 +83,21 @@ func (l RecoveryServicesBackupProtectedItemLister) List(ctx context.Context, o i log := logrus. WithField("r", RecoveryServicesBackupProtectedItemResource). - WithField("s", opts.SubscriptionId). + WithField("s", opts.SubscriptionID). WithField("rg", opts.ResourceGroup) log.Trace("creating client") - vaultsClient, err := armrecoveryservices.NewVaultsClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + vaultsClient, err := armrecoveryservices.NewVaultsClient(opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } - client, err := armrecoveryservicesbackup.NewBackupProtectedItemsClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + client, err := armrecoveryservicesbackup.NewBackupProtectedItemsClient(opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } - protectedItems, err := armrecoveryservicesbackup.NewProtectedItemsClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + protectedItems, err := armrecoveryservicesbackup.NewProtectedItemsClient(opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } @@ -132,14 +134,13 @@ func (l RecoveryServicesBackupProtectedItemLister) List(ctx context.Context, o i vaultName: v.Name, id: i.ID, name: i.Name, - location: i.Location, + region: i.Location, resourceGroup: to.StringPtr(opts.ResourceGroup), containerName: to.StringPtr(containerName), backupFabric: to.StringPtr("Azure"), // TODO: this should be calculated }) } } - } } diff --git a/resources/recoveryservices-backup-protectioncontainer.go b/resources/recoveryservices-backup-protectioncontainer.go index 2d5d8c6..5fa7345 100644 --- a/resources/recoveryservices-backup-protectioncontainer.go +++ b/resources/recoveryservices-backup-protectioncontainer.go @@ -23,7 +23,7 @@ const RecoveryServicesBackupProtectionContainerResource = "RecoveryServicesBacku func init() { registry.Register(®istry.Registration{ Name: RecoveryServicesBackupProtectionContainerResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &RecoveryServicesBackupProtectionContainersLister{}, }) } @@ -33,7 +33,7 @@ type RecoveryServicesBackupProtectionContainers struct { pClient *armrecoveryservicesbackup.ProtectionContainersClient id *string name *string - location *string + region *string resourceGroup *string vaultName *string backupFabric *string @@ -52,7 +52,7 @@ func (r *RecoveryServicesBackupProtectionContainers) Properties() types.Properti properties := types.NewProperties() properties.Set("Name", r.name) - properties.Set("Location", r.location) + properties.Set("Region", r.region) properties.Set("ResourceGroup", r.resourceGroup) properties.Set("VaultName", r.vaultName) @@ -76,22 +76,28 @@ func (l RecoveryServicesBackupProtectionContainersLister) List(ctx context.Conte log := logrus. WithField("r", RecoveryServicesBackupProtectionContainerResource). - WithField("s", opts.SubscriptionId). + WithField("s", opts.SubscriptionID). WithField("rg", opts.ResourceGroup) log.Trace("creating client") - vaultsClient, err := armrecoveryservices.NewVaultsClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + vaultsClient, err := + armrecoveryservices.NewVaultsClient( + opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } - client, err := armrecoveryservicesbackup.NewBackupProtectionContainersClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + client, err := + armrecoveryservicesbackup.NewBackupProtectionContainersClient( + opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } - protectedContainers, err := armrecoveryservicesbackup.NewProtectionContainersClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + protectedContainers, err := + armrecoveryservicesbackup.NewProtectionContainersClient( + opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } @@ -106,7 +112,6 @@ func (l RecoveryServicesBackupProtectionContainersLister) List(ctx context.Conte } for _, v := range page.Value { - itemPager := client.NewListPager(to.String(v.Name), opts.ResourceGroup, nil) for itemPager.More() { page, err := itemPager.NextPage(ctx) @@ -121,13 +126,12 @@ func (l RecoveryServicesBackupProtectionContainersLister) List(ctx context.Conte vaultName: v.Name, id: i.ID, name: i.Name, - location: i.Location, + region: i.Location, resourceGroup: to.StringPtr(opts.ResourceGroup), backupFabric: to.StringPtr("Azure"), // TODO: this should be calculated }) } } - } } diff --git a/resources/recoveryservices-backup-protectionintent.go b/resources/recoveryservices-backup-protectionintent.go index 2044284..cf4ecd6 100644 --- a/resources/recoveryservices-backup-protectionintent.go +++ b/resources/recoveryservices-backup-protectionintent.go @@ -23,7 +23,7 @@ const RecoveryServicesBackupProtectionIntentResource = "RecoveryServicesBackupPr func init() { registry.Register(®istry.Registration{ Name: RecoveryServicesBackupProtectionIntentResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &RecoveryServicesBackupProtectionIntentLister{}, }) } @@ -33,7 +33,7 @@ type RecoveryServicesBackupProtectionIntent struct { pClient *armrecoveryservicesbackup.ProtectionIntentClient id *string name *string - location *string + region *string resourceGroup *string vaultName *string backupFabric *string @@ -52,7 +52,7 @@ func (r *RecoveryServicesBackupProtectionIntent) Properties() types.Properties { properties := types.NewProperties() properties.Set("Name", r.name) - properties.Set("Location", r.location) + properties.Set("Region", r.region) properties.Set("ResourceGroup", r.resourceGroup) properties.Set("VaultName", r.vaultName) @@ -75,22 +75,22 @@ func (l RecoveryServicesBackupProtectionIntentLister) List(ctx context.Context, log := logrus. WithField("r", RecoveryServicesBackupProtectionIntentResource). - WithField("s", opts.SubscriptionId). + WithField("s", opts.SubscriptionID). WithField("rg", opts.ResourceGroup) log.Trace("creating client") - vaultsClient, err := armrecoveryservices.NewVaultsClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + vaultsClient, err := armrecoveryservices.NewVaultsClient(opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } - client, err := armrecoveryservicesbackup.NewBackupProtectionIntentClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + client, err := armrecoveryservicesbackup.NewBackupProtectionIntentClient(opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } - protectedContainers, err := armrecoveryservicesbackup.NewProtectionIntentClient(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + protectedContainers, err := armrecoveryservicesbackup.NewProtectionIntentClient(opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return resources, err } @@ -105,7 +105,6 @@ func (l RecoveryServicesBackupProtectionIntentLister) List(ctx context.Context, } for _, v := range page.Value { - itemPager := client.NewListPager(to.String(v.Name), opts.ResourceGroup, nil) for itemPager.More() { page, err := itemPager.NextPage(ctx) @@ -120,13 +119,12 @@ func (l RecoveryServicesBackupProtectionIntentLister) List(ctx context.Context, vaultName: v.Name, id: i.ID, name: i.Name, - location: i.Location, + region: i.Location, resourceGroup: to.StringPtr(opts.ResourceGroup), backupFabric: to.StringPtr("Azure"), // TODO: this should be calculated }) } } - } } diff --git a/resources/recoveryservices-vault.go b/resources/recoveryservices-vault.go index 0511561..e52f8a2 100644 --- a/resources/recoveryservices-vault.go +++ b/resources/recoveryservices-vault.go @@ -23,7 +23,7 @@ const RecoveryServicesVaultResource = "RecoveryServicesVault" func init() { registry.Register(®istry.Registration{ Name: RecoveryServicesVaultResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &RecoveryServicesVaultLister{}, DependsOn: []string{ RecoveryServicesBackupProtectedItemResource, @@ -32,12 +32,12 @@ func init() { } type RecoveryServicesVault struct { - client *vaults.VaultsClient - vaultId vaults.VaultId - id *string - name *string - location string - rg string + client *vaults.VaultsClient + vaultID vaults.VaultId + id *string + name *string + region string + rg string } func (r *RecoveryServicesVault) Filter() error { @@ -45,7 +45,7 @@ func (r *RecoveryServicesVault) Filter() error { } func (r *RecoveryServicesVault) Remove(ctx context.Context) error { - _, err := r.client.Delete(ctx, r.vaultId) + _, err := r.client.Delete(ctx, r.vaultID) return err } @@ -53,7 +53,7 @@ func (r *RecoveryServicesVault) Properties() types.Properties { properties := types.NewProperties() properties.Set("Name", r.name) - properties.Set("Location", r.location) + properties.Set("Region", r.region) properties.Set("ResourceGroup", r.rg) return properties @@ -74,7 +74,7 @@ func (l RecoveryServicesVaultLister) List(ctx context.Context, o interface{}) ([ log := logrus. WithField("r", RecoveryServicesVaultResource). - WithField("s", opts.SubscriptionId). + WithField("s", opts.SubscriptionID). WithField("rg", opts.ResourceGroup) log.Trace("creating client") @@ -89,19 +89,19 @@ func (l RecoveryServicesVaultLister) List(ctx context.Context, o interface{}) ([ log.Trace("listing resources") - items, err := client.ListByResourceGroupComplete(ctx, commonids.NewResourceGroupID(opts.SubscriptionId, opts.ResourceGroup)) + items, err := client.ListByResourceGroupComplete(ctx, commonids.NewResourceGroupID(opts.SubscriptionID, opts.ResourceGroup)) if err != nil { return nil, err } for _, item := range items.Items { resources = append(resources, &RecoveryServicesVault{ - client: client, - id: item.Id, - name: item.Name, - location: item.Location, - vaultId: vaults.NewVaultID(opts.SubscriptionId, opts.ResourceGroup, ptr.ToString(item.Id)), - rg: opts.ResourceGroup, + client: client, + id: item.Id, + name: item.Name, + region: item.Location, + vaultID: vaults.NewVaultID(opts.SubscriptionID, opts.ResourceGroup, ptr.ToString(item.Id)), + rg: opts.ResourceGroup, }) } diff --git a/resources/resource-group.go b/resources/resource-group.go index fbf8362..5703c03 100644 --- a/resources/resource-group.go +++ b/resources/resource-group.go @@ -2,8 +2,6 @@ package resources import ( "context" - "fmt" - "slices" "time" "github.com/sirupsen/logrus" @@ -24,34 +22,24 @@ const ResourceGroupResource = "ResourceGroup" func init() { registry.Register(®istry.Registration{ Name: ResourceGroupResource, + Scope: nuke.Subscription, Lister: &ResourceGroupLister{}, - // Scope is set to ResourceGroup because we want to be able to query based on location and resource group - // which is not possible if we treat this as part of subscription because that's considered global. - Scope: nuke.Subscription, }) } type ResourceGroup struct { client *resourcegroups.ResourceGroupsClient name *string - location string - subscriptionId string + region string + subscriptionID string listerOpts *nuke.ListerOpts } -func (r *ResourceGroup) Filter() error { - if !slices.Contains(r.listerOpts.Locations, r.location) { - return fmt.Errorf("resource not in enabled region/location") - } - - return nil -} - func (r *ResourceGroup) Remove(ctx context.Context) error { ctx, cancel := context.WithDeadline(ctx, time.Now().Add(30*time.Second)) defer cancel() - _, err := r.client.Delete(ctx, commonids.NewResourceGroupID(r.subscriptionId, *r.name), resourcegroups.DefaultDeleteOperationOptions()) + _, err := r.client.Delete(ctx, commonids.NewResourceGroupID(r.subscriptionID, *r.name), resourcegroups.DefaultDeleteOperationOptions()) return err } @@ -59,8 +47,8 @@ func (r *ResourceGroup) Properties() types.Properties { properties := types.NewProperties() properties.Set("Name", r.name) - properties.Set("Location", r.location) - properties.Set("SubscriptionId", r.subscriptionId) + properties.Set("Region", r.region) + properties.Set("SubscriptionID", r.subscriptionID) return properties } @@ -80,7 +68,7 @@ func (l ResourceGroupLister) List(ctx context.Context, o interface{}) ([]resourc ctx, cancel := context.WithDeadline(ctx, time.Now().Add(30*time.Second)) defer cancel() - log := logrus.WithField("r", ResourceGroupResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", ResourceGroupResource).WithField("s", opts.SubscriptionID) client, err := resourcegroups.NewResourceGroupsClientWithBaseURI(environments.AzurePublic().ResourceManager) if err != nil { @@ -92,7 +80,7 @@ func (l ResourceGroupLister) List(ctx context.Context, o interface{}) ([]resourc log.Trace("attempting to list groups") - list, err := client.List(ctx, commonids.NewSubscriptionID(opts.SubscriptionId), resourcegroups.ListOperationOptions{}) + list, err := client.List(ctx, commonids.NewSubscriptionID(opts.SubscriptionID), resourcegroups.ListOperationOptions{}) if err != nil { return nil, err } @@ -103,8 +91,8 @@ func (l ResourceGroupLister) List(ctx context.Context, o interface{}) ([]resourc resources = append(resources, &ResourceGroup{ client: client, name: entity.Name, - location: entity.Location, - subscriptionId: opts.SubscriptionId, + region: entity.Location, + subscriptionID: opts.SubscriptionID, listerOpts: opts, }) } diff --git a/resources/security-alert.go b/resources/security-alert.go index 1febb39..d63ee3c 100644 --- a/resources/security-alert.go +++ b/resources/security-alert.go @@ -9,7 +9,7 @@ import ( "github.com/gotidy/ptr" "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v3.0/security" + "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v3.0/security" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ import ( const SecurityAlertResource = "SecurityAlert" -const SecurityAlertLocation = "/Microsoft.Security/locations/(?P.*)/alerts/" +const SecurityAlertLocation = "/Microsoft.Security/locations/(?P.*)/alerts/" func init() { registry.Register(®istry.Registration{ @@ -79,13 +79,13 @@ func (l SecurityAlertsLister) List(ctx context.Context, o interface{}) ([]resour log := logrus. WithField("r", SecurityAlertResource). - WithField("s", opts.SubscriptionId) + WithField("s", opts.SubscriptionID) log.Trace("creating client") locationRe := regexp.MustCompile(SecurityAlertLocation) - client := security.NewAlertsClient(opts.SubscriptionId) + client := security.NewAlertsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -102,7 +102,6 @@ func (l SecurityAlertsLister) List(ctx context.Context, o interface{}) ([]resour for list.NotDone() { log.Trace("listing not done") for _, g := range list.Values() { - matches := locationRe.FindStringSubmatch(ptr.ToString(g.ID)) resources = append(resources, &SecurityAlert{ client: client, diff --git a/resources/security-assessment.go b/resources/security-assessment.go index 3654fc1..60f255d 100644 --- a/resources/security-assessment.go +++ b/resources/security-assessment.go @@ -30,7 +30,7 @@ func init() { type SecurityAssessment struct { client *armsecurity.AssessmentsClient id *string - resourceId *string + resourceID *string name *string status *string } @@ -40,7 +40,7 @@ func (r *SecurityAssessment) Filter() error { } func (r *SecurityAssessment) Remove(ctx context.Context) error { - _, err := r.client.Delete(ctx, strings.TrimLeft(to.String(r.resourceId), "/"), to.String(r.name), nil) + _, err := r.client.Delete(ctx, strings.TrimLeft(to.String(r.resourceID), "/"), to.String(r.name), nil) return err } @@ -48,7 +48,7 @@ func (r *SecurityAssessment) Properties() types.Properties { properties := types.NewProperties() properties.Set("ID", r.id) - properties.Set("ResourceID", r.resourceId) + properties.Set("ResourceID", r.resourceID) properties.Set("Name", r.name) properties.Set("StatusCode", r.status) @@ -69,11 +69,11 @@ func (l SecurityAssessmentLister) List(ctx context.Context, o interface{}) ([]re log := logrus. WithField("r", SecurityAssessmentResource). - WithField("s", opts.SubscriptionId) + WithField("s", opts.SubscriptionID) log.Trace("creating client") - clientFactory, err := armsecurity.NewClientFactory(opts.SubscriptionId, opts.Authorizers.IdentityCreds, nil) + clientFactory, err := armsecurity.NewClientFactory(opts.SubscriptionID, opts.Authorizers.IdentityCreds, nil) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func (l SecurityAssessmentLister) List(ctx context.Context, o interface{}) ([]re log.Trace("listing resources") - pager := client.NewListPager(fmt.Sprintf("/subscriptions/%s", opts.SubscriptionId), nil) + pager := client.NewListPager(fmt.Sprintf("/subscriptions/%s", opts.SubscriptionID), nil) for pager.More() { log.Trace("listing not done") page, err := pager.NextPage(ctx) @@ -101,7 +101,7 @@ func (l SecurityAssessmentLister) List(ctx context.Context, o interface{}) ([]re parts := strings.Split(to.String(v.ID), "/providers/Microsoft.Security") resources = append(resources, &SecurityAssessment{ client: client, - resourceId: to.StringPtr(parts[0]), + resourceID: to.StringPtr(parts[0]), id: v.ID, name: v.Name, }) diff --git a/resources/security-pricing.go b/resources/security-pricing.go index c2b850e..caf9c81 100644 --- a/resources/security-pricing.go +++ b/resources/security-pricing.go @@ -7,7 +7,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v3.0/security" + "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v3.0/security" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -31,8 +31,7 @@ func init() { type SecurityPricing struct { client security.PricingsClient - id string - name string + name *string tier string } @@ -44,7 +43,7 @@ func (r *SecurityPricing) Filter() error { } func (r *SecurityPricing) Remove(ctx context.Context) error { - _, err := r.client.Update(ctx, r.name, security.Pricing{ + _, err := r.client.Update(ctx, *r.name, security.Pricing{ PricingProperties: &security.PricingProperties{ PricingTier: "Free", }, @@ -55,7 +54,6 @@ func (r *SecurityPricing) Remove(ctx context.Context) error { func (r *SecurityPricing) Properties() types.Properties { properties := types.NewProperties() - properties.Set("ID", r.id) properties.Set("Name", r.name) properties.Set("PricingTier", r.tier) @@ -63,7 +61,7 @@ func (r *SecurityPricing) Properties() types.Properties { } func (r *SecurityPricing) String() string { - return r.name + return *r.name } // ------------------------------------------------------------------- @@ -76,11 +74,11 @@ func (l SecurityPricingLister) List(ctx context.Context, o interface{}) ([]resou log := logrus. WithField("r", SecurityPricingResource). - WithField("s", opts.SubscriptionId) + WithField("s", opts.SubscriptionID) log.Trace("creating client") - client := security.NewPricingsClient(opts.SubscriptionId) + client := security.NewPricingsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -97,8 +95,7 @@ func (l SecurityPricingLister) List(ctx context.Context, o interface{}) ([]resou for _, price := range *list.Value { resources = append(resources, &SecurityPricing{ client: client, - id: *price.ID, - name: *price.Name, + name: price.Name, tier: string(price.PricingTier), }) } diff --git a/resources/security-workspace.go b/resources/security-workspace.go index 9e35ab1..e5a1ce4 100644 --- a/resources/security-workspace.go +++ b/resources/security-workspace.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v3.0/security" + "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v3.0/security" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -27,12 +27,12 @@ func init() { type SecurityWorkspace struct { client security.WorkspaceSettingsClient - name string - scope string + name *string + scope *string } func (r *SecurityWorkspace) Remove(ctx context.Context) error { - _, err := r.client.Delete(ctx, r.name) + _, err := r.client.Delete(ctx, *r.name) return err } @@ -46,7 +46,7 @@ func (r *SecurityWorkspace) Properties() types.Properties { } func (r *SecurityWorkspace) String() string { - return r.name + return *r.name } // ------------------------------------------------------------- @@ -59,11 +59,11 @@ func (l SecurityWorkspaceLister) List(ctx context.Context, o interface{}) ([]res log := logrus. WithField("r", SecurityWorkspaceResource). - WithField("s", opts.SubscriptionId) + WithField("s", opts.SubscriptionID) log.Trace("creating client") - client := security.NewWorkspaceSettingsClient(opts.SubscriptionId) + client := security.NewWorkspaceSettingsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -82,8 +82,8 @@ func (l SecurityWorkspaceLister) List(ctx context.Context, o interface{}) ([]res for _, g := range list.Values() { resources = append(resources, &SecurityWorkspace{ client: client, - name: *g.Name, - scope: *g.Scope, + name: g.Name, + scope: g.Scope, }) } diff --git a/resources/service-principal.go b/resources/service-principal.go index e2cb4ad..455e746 100644 --- a/resources/service-principal.go +++ b/resources/service-principal.go @@ -85,7 +85,7 @@ type ServicePrincipalsLister struct { func (l ServicePrincipalsLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", ServicePrincipalResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", ServicePrincipalResource).WithField("s", opts.SubscriptionID) client := msgraph.NewServicePrincipalsClient() client.BaseClient.Authorizer = opts.Authorizers.MicrosoftGraph @@ -102,7 +102,9 @@ func (l ServicePrincipalsLister) List(ctx context.Context, o interface{}) ([]res log.Trace("listing resource start") - for _, entity := range *entities { + for i := range *entities { + entity := &(*entities)[i] + // Filtering out Microsoft owned Service Principals, because otherwise it needlessly adds 3000+ // resources that have to get filtered out later. This instead does it optimistically here. // Ideally we'd be able to use odata.Query above, but it's not supported by the graph at this time. diff --git a/resources/ssh-key.go b/resources/ssh-key.go index 006b275..af6d631 100644 --- a/resources/ssh-key.go +++ b/resources/ssh-key.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-04-01/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-04-01/compute" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -26,11 +26,12 @@ func init() { } type SSHPublicKey struct { - client compute.SSHPublicKeysClient - name *string - rg *string - location *string - tags map[string]*string + client compute.SSHPublicKeysClient + rg *string + location *string + name *string + subscriptionID *string + tags map[string]*string } func (r *SSHPublicKey) Remove(ctx context.Context) error { @@ -44,6 +45,7 @@ func (r *SSHPublicKey) Properties() types.Properties { properties.Set("Name", r.name) properties.Set("Location", r.location) properties.Set("ResourceGroup", r.rg) + properties.Set("SubscriptionID", r.subscriptionID) for tag, value := range r.tags { properties.SetTag(&tag, value) @@ -64,9 +66,9 @@ type SSHPublicKeyLister struct { func (l SSHPublicKeyLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", SSHPublicKeyResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", SSHPublicKeyResource).WithField("s", opts.SubscriptionID) - client := compute.NewSSHPublicKeysClient(opts.SubscriptionId) + client := compute.NewSSHPublicKeysClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -88,7 +90,7 @@ func (l SSHPublicKeyLister) List(ctx context.Context, o interface{}) ([]resource resources = append(resources, &SSHPublicKey{ client: client, name: g.Name, - rg: &opts.ResourceGroup, + rg: nuke.GetResourceGroupFromID(*g.ID), location: g.Location, tags: g.Tags, }) diff --git a/resources/storage-account.go b/resources/storage-account.go index 5f59f5f..cb808e8 100644 --- a/resources/storage-account.go +++ b/resources/storage-account.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-09-01/storage" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-09-01/storage" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const StorageAccountResource = "StorageAccount" func init() { registry.Register(®istry.Registration{ Name: StorageAccountResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &StorageAccountLister{}, DependsOn: []string{ VirtualMachineResource, @@ -30,13 +30,14 @@ func init() { type StorageAccount struct { client storage.AccountsClient - name string + name *string rg string + region *string tags map[string]*string } func (r *StorageAccount) Remove(ctx context.Context) error { - _, err := r.client.Delete(ctx, r.rg, r.name) + _, err := r.client.Delete(ctx, r.rg, *r.name) return err } @@ -45,16 +46,17 @@ func (r *StorageAccount) Properties() types.Properties { properties.Set("Name", r.name) properties.Set("ResourceGroup", r.rg) + properties.Set("Region", r.region) - for tag, value := range r.tags { - properties.SetTag(&tag, value) + for k, v := range r.tags { + properties.SetTag(&k, v) } return properties } func (r *StorageAccount) String() string { - return r.name + return *r.name } // -------------------------------------- @@ -65,9 +67,9 @@ type StorageAccountLister struct { func (l StorageAccountLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", StorageAccountResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", StorageAccountResource).WithField("s", opts.SubscriptionID) - client := storage.NewAccountsClient(opts.SubscriptionId) + client := storage.NewAccountsClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -88,8 +90,9 @@ func (l StorageAccountLister) List(ctx context.Context, o interface{}) ([]resour for _, g := range list.Values() { resources = append(resources, &StorageAccount{ client: client, - name: *g.Name, + name: g.Name, rg: opts.ResourceGroup, + region: g.Location, }) } diff --git a/resources/virtual-machine.go b/resources/virtual-machine.go index b329e4e..54001f0 100644 --- a/resources/virtual-machine.go +++ b/resources/virtual-machine.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-04-01/compute" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-04-01/compute" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,19 +20,21 @@ const VirtualMachineResource = "VirtualMachine" func init() { registry.Register(®istry.Registration{ Name: VirtualMachineResource, + Scope: nuke.ResourceGroup, Lister: &VirtualMachineLister{}, - Scope: nuke.Subscription, }) } type VirtualMachine struct { - client compute.VirtualMachinesClient - name *string - resourceGroup *string + client compute.VirtualMachinesClient + name *string + rg *string + region *string + tags map[string]*string } func (r *VirtualMachine) Remove(ctx context.Context) error { - _, err := r.client.Delete(ctx, *r.resourceGroup, *r.name, &[]bool{true}[0]) + _, err := r.client.Delete(ctx, *r.rg, *r.name, &[]bool{true}[0]) return err } @@ -40,7 +42,12 @@ func (r *VirtualMachine) Properties() types.Properties { properties := types.NewProperties() properties.Set("Name", *r.name) - properties.Set("ResourceGroup", *r.resourceGroup) + properties.Set("ResourceGroup", *r.rg) + properties.Set("Region", *r.region) + + for k, v := range r.tags { + properties.SetTag(&k, v) + } return properties } @@ -57,9 +64,9 @@ type VirtualMachineLister struct { func (l VirtualMachineLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", VirtualMachineResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", VirtualMachineResource).WithField("s", opts.SubscriptionID) - client := compute.NewVirtualMachinesClient(opts.SubscriptionId) + client := compute.NewVirtualMachinesClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -79,9 +86,11 @@ func (l VirtualMachineLister) List(ctx context.Context, o interface{}) ([]resour log.Trace("list not done") for _, g := range list.Values() { resources = append(resources, &VirtualMachine{ - client: client, - name: g.Name, - resourceGroup: &opts.ResourceGroup, + client: client, + name: g.Name, + rg: &opts.ResourceGroup, + region: g.Location, + tags: g.Tags, }) } diff --git a/resources/virtual-network.go b/resources/virtual-network.go index 15c7f51..4813b01 100644 --- a/resources/virtual-network.go +++ b/resources/virtual-network.go @@ -6,7 +6,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-05-01/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-05-01/network" //nolint:staticcheck "github.com/ekristen/libnuke/pkg/registry" "github.com/ekristen/libnuke/pkg/resource" @@ -20,7 +20,7 @@ const VirtualNetworkResource = "VirtualNetwork" func init() { registry.Register(®istry.Registration{ Name: VirtualNetworkResource, - Scope: nuke.Subscription, + Scope: nuke.ResourceGroup, Lister: &VirtualNetworkLister{}, }) } @@ -31,9 +31,9 @@ type VirtualNetworkLister struct { func (l VirtualNetworkLister) List(ctx context.Context, o interface{}) ([]resource.Resource, error) { opts := o.(*nuke.ListerOpts) - log := logrus.WithField("r", VirtualNetworkResource).WithField("s", opts.SubscriptionId) + log := logrus.WithField("r", VirtualNetworkResource).WithField("s", opts.SubscriptionID) - client := network.NewVirtualNetworksClient(opts.SubscriptionId) + client := network.NewVirtualNetworksClient(opts.SubscriptionID) client.Authorizer = opts.Authorizers.Management client.RetryAttempts = 1 client.RetryDuration = time.Second * 2 @@ -55,6 +55,8 @@ func (l VirtualNetworkLister) List(ctx context.Context, o interface{}) ([]resour client: client, name: g.Name, rg: &opts.ResourceGroup, + region: g.Location, + tags: g.Tags, }) } @@ -74,6 +76,8 @@ type VirtualNetwork struct { client network.VirtualNetworksClient name *string rg *string + region *string + tags map[string]*string } func (r *VirtualNetwork) Remove(ctx context.Context) error { @@ -86,6 +90,11 @@ func (r *VirtualNetwork) Properties() types.Properties { properties.Set("Name", *r.name) properties.Set("ResourceGroup", *r.rg) + properties.Set("Region", *r.region) + + for k, v := range r.tags { + properties.SetTag(&k, v) + } return properties }