Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(iotsitewise): add portal, project, gateway, dashboard, asset, asset model and access policy #420

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions resources/iotsitewise-access-policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package resources

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iotsitewise"

"github.com/ekristen/libnuke/pkg/registry"
"github.com/ekristen/libnuke/pkg/resource"
"github.com/ekristen/libnuke/pkg/types"

"github.com/ekristen/aws-nuke/v3/pkg/nuke"
)

const IoTSiteWiseAccessPolicyResource = "IoTSiteWiseAccessPolicy"

func init() {
registry.Register(&registry.Registration{
Name: IoTSiteWiseAccessPolicyResource,
Scope: nuke.Account,
Lister: &IoTSiteWiseAccessPolicyLister{},
})
}

type IoTSiteWiseAccessPolicyLister struct{}

func (l *IoTSiteWiseAccessPolicyLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) { //nolint:gocyclo
opts := o.(*nuke.ListerOpts)

svc := iotsitewise.New(opts.Session)
resources := make([]resource.Resource, 0)

// Policies can be attached either to portal or projects
// List portal and portal policies
listPortalsParams := &iotsitewise.ListPortalsInput{
MaxResults: aws.Int64(25),
}
for {
listPortalsResp, err := svc.ListPortals(listPortalsParams)
if err != nil {
return nil, err
}
for _, portalItem := range listPortalsResp.PortalSummaries {
// Got portals
listProjectsParams := &iotsitewise.ListProjectsInput{
PortalId: portalItem.Id,
MaxResults: aws.Int64(25),
}

// List portal policies
listPortalPoliciesParam := &iotsitewise.ListAccessPoliciesInput{
ResourceId: portalItem.Id,
ResourceType: &([]string{string(iotsitewise.ResourceTypePortal)}[0]),
MaxResults: aws.Int64(25),
}

for {
listPortalPoliciesResp, err := svc.ListAccessPolicies(listPortalPoliciesParam)
if err != nil {
return nil, err
}
for _, item := range listPortalPoliciesResp.AccessPolicySummaries {
resources = append(resources, &IoTSiteWiseAccessPolicy{
svc: svc,
ID: item.Id,
})
}

if listPortalPoliciesResp.NextToken == nil {
break
}

listPortalPoliciesParam.NextToken = listPortalPoliciesResp.NextToken
}

// will also search inside projects
for {
listProjectsResp, err := svc.ListProjects(listProjectsParams)
if err != nil {
return nil, err
}
for _, projectItem := range listProjectsResp.ProjectSummaries {
// List project policies
listProjectPoliciesParams := &iotsitewise.ListAccessPoliciesInput{
ResourceId: projectItem.Id,
ResourceType: &([]string{string(iotsitewise.ResourceTypeProject)}[0]),
MaxResults: aws.Int64(25),
}

for {
listProjectPoliciesResp, err := svc.ListAccessPolicies(listProjectPoliciesParams)
if err != nil {
return nil, err
}
for _, item := range listProjectPoliciesResp.AccessPolicySummaries {
resources = append(resources, &IoTSiteWiseAccessPolicy{
svc: svc,
ID: item.Id,
})
}

if listProjectPoliciesResp.NextToken == nil {
break
}

listProjectPoliciesParams.NextToken = listProjectPoliciesResp.NextToken
}
}

if listProjectsResp.NextToken == nil {
break
}

listProjectsParams.NextToken = listProjectsResp.NextToken
}
}

if listPortalsResp.NextToken == nil {
break
}

listPortalsParams.NextToken = listPortalsResp.NextToken
}

return resources, nil
}

type IoTSiteWiseAccessPolicy struct {
svc *iotsitewise.IoTSiteWise
ID *string
}

func (r *IoTSiteWiseAccessPolicy) Properties() types.Properties {
return types.NewPropertiesFromStruct(r)
}

func (r *IoTSiteWiseAccessPolicy) Remove(_ context.Context) error {
_, err := r.svc.DeleteAccessPolicy(&iotsitewise.DeleteAccessPolicyInput{
AccessPolicyId: r.ID,
})

return err
}

func (r *IoTSiteWiseAccessPolicy) String() string {
return *r.ID
}
95 changes: 95 additions & 0 deletions resources/iotsitewise-asset-model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package resources

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iotsitewise"

"github.com/ekristen/libnuke/pkg/registry"
"github.com/ekristen/libnuke/pkg/resource"
"github.com/ekristen/libnuke/pkg/types"

"github.com/ekristen/aws-nuke/v3/pkg/nuke"
)

const IoTSiteWiseAssetModelResource = "IoTSiteWiseAssetModel"

func init() {
registry.Register(&registry.Registration{
Name: IoTSiteWiseAssetModelResource,
Scope: nuke.Account,
Lister: &IoTSiteWiseAssetModelLister{},
DependsOn: []string{
IoTSiteWiseAssetResource,
},
})
}

type IoTSiteWiseAssetModelLister struct{}

func (l *IoTSiteWiseAssetModelLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) {
opts := o.(*nuke.ListerOpts)

svc := iotsitewise.New(opts.Session)
resources := make([]resource.Resource, 0)

params := &iotsitewise.ListAssetModelsInput{
MaxResults: aws.Int64(25),
}

for {
resp, err := svc.ListAssetModels(params)
if err != nil {
return nil, err
}
for _, item := range resp.AssetModelSummaries {
tagResp, err := svc.ListTagsForResource(
&iotsitewise.ListTagsForResourceInput{
ResourceArn: item.Arn,
})
if err != nil {
return nil, err
}

resources = append(resources, &IoTSiteWiseAssetModel{
svc: svc,
ID: item.Id,
Name: item.Name,
Status: item.Status.State,
Tags: tagResp.Tags,
})
}

if resp.NextToken == nil {
break
}

params.NextToken = resp.NextToken
}

return resources, nil
}

type IoTSiteWiseAssetModel struct {
svc *iotsitewise.IoTSiteWise
ID *string
Name *string
Status *string
Tags map[string]*string
}

func (r *IoTSiteWiseAssetModel) Properties() types.Properties {
return types.NewPropertiesFromStruct(r)
}

func (r *IoTSiteWiseAssetModel) Remove(_ context.Context) error {
_, err := r.svc.DeleteAssetModel(&iotsitewise.DeleteAssetModelInput{
AssetModelId: r.ID,
})
return err
}

func (r *IoTSiteWiseAssetModel) String() string {
return *r.ID
}
146 changes: 146 additions & 0 deletions resources/iotsitewise-asset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package resources

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iotsitewise"

"github.com/ekristen/libnuke/pkg/registry"
"github.com/ekristen/libnuke/pkg/resource"
"github.com/ekristen/libnuke/pkg/types"

"github.com/ekristen/aws-nuke/v3/pkg/nuke"
)

const IoTSiteWiseAssetResource = "IoTSiteWiseAsset"

func init() {
registry.Register(&registry.Registration{
Name: IoTSiteWiseAssetResource,
Scope: nuke.Account,
Lister: &IoTSiteWiseAssetLister{},
})
}

type IoTSiteWiseAssetLister struct{}

func (l *IoTSiteWiseAssetLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) {
opts := o.(*nuke.ListerOpts)

svc := iotsitewise.New(opts.Session)
resources := make([]resource.Resource, 0)

assetModelSummaries, err := ListAssetModels(svc)
if err != nil {
return nil, err
}

for _, assetModelSummary := range assetModelSummaries {
params := &iotsitewise.ListAssetsInput{
AssetModelId: assetModelSummary.Id,
MaxResults: aws.Int64(25),
}

for {
resp, err := svc.ListAssets(params)
if err != nil {
return nil, err
}
for _, item := range resp.AssetSummaries {
tagResp, err := svc.ListTagsForResource(
&iotsitewise.ListTagsForResourceInput{
ResourceArn: item.Arn,
})
if err != nil {
return nil, err
}

resources = append(resources, &IoTSiteWiseAsset{
svc: svc,
ID: item.Id,
Name: item.Name,
Status: item.Status.State,
Tags: tagResp.Tags,
})
}

if resp.NextToken == nil {
break
}

params.NextToken = resp.NextToken
}
}

return resources, nil
}

// Utility function to get models, allowing to scan for assets
func ListAssetModels(svc *iotsitewise.IoTSiteWise) ([]*iotsitewise.AssetModelSummary, error) {
resources := make([]*iotsitewise.AssetModelSummary, 0)
params := &iotsitewise.ListAssetModelsInput{
MaxResults: aws.Int64(25),
}
for {
resp, err := svc.ListAssetModels(params)
if err != nil {
return nil, err
}
resources = append(resources, resp.AssetModelSummaries...)
if resp.NextToken == nil {
break
}
params.NextToken = resp.NextToken
}
return resources, nil
}

type IoTSiteWiseAsset struct {
svc *iotsitewise.IoTSiteWise
ID *string
Name *string
Status *string
Tags map[string]*string
}

func (r *IoTSiteWiseAsset) Properties() types.Properties {
return types.NewPropertiesFromStruct(r)
}

func (r *IoTSiteWiseAsset) Remove(_ context.Context) error {
associatedAssets, err := r.svc.ListAssociatedAssets(&iotsitewise.ListAssociatedAssetsInput{
AssetId: r.ID,
})
if err != nil {
return err
}
assetDescription, err := r.svc.DescribeAsset(&iotsitewise.DescribeAssetInput{
AssetId: r.ID,
})
if err != nil {
return err
}

// If asset is associated, dissociate before delete
for _, assetHierarchy := range assetDescription.AssetHierarchies {
for _, childAsset := range associatedAssets.AssetSummaries {
// Could fail if hierarchy it not the correct one, ignore it
_, _ = r.svc.DisassociateAssets(&iotsitewise.DisassociateAssetsInput{
AssetId: r.ID,
ChildAssetId: childAsset.Id,
HierarchyId: assetHierarchy.Id,
})
}
}

_, err = r.svc.DeleteAsset(&iotsitewise.DeleteAssetInput{
AssetId: r.ID,
})

return err
}

func (r *IoTSiteWiseAsset) String() string {
return *r.ID
}
Loading