diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 014862f63f..e339cf544e 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -54,6 +54,7 @@ mgroup Mpim natgateway networkinterface +nodegroup nodepool nullgroup nullstring diff --git a/providers/aws/resources/aws.lr b/providers/aws/resources/aws.lr index d3cee473c2..e353ee0e0e 100644 --- a/providers/aws/resources/aws.lr +++ b/providers/aws/resources/aws.lr @@ -2988,6 +2988,36 @@ aws.eks { clusters() []aws.eks.cluster } +// Amazon EKS managed node group +private aws.eks.nodegroup @defaults("name scalingConfig.DesiredSize diskSize status") { + // Name for the EKS node group + name string + // ARN for the EKS node group + arn() string + // Region for the EKS node group + region string + // Time when the EKS node group was created + createdAt() time + // Status for the EKS node group + status() string + // Capacity type for the EKS node group (ON_DEMAND, SPOT) + capacityType() string + // Scaling configuration for the EKS node group + scalingConfig() dict + // Instance types for the EKS node group + instanceTypes() []string + // AMI type for the EKS node group + amiType() string + // IAM role for the EKS node group + nodeRole() aws.iam.role + // Disk size for the EKS node group + diskSize() int + // Kubernetes labels applied to the EKS node group + labels() map[string]string + // Tags for the EKS node group + tags() map[string]string +} + // Amazon EKS cluster private aws.eks.cluster @defaults("arn version status") { // Name of the cluster @@ -3016,4 +3046,6 @@ private aws.eks.cluster @defaults("arn version status") { resourcesVpcConfig dict // Cluster creation timestamp createdAt time + // List of EKS node groups + nodeGroups() []aws.eks.nodegroup } diff --git a/providers/aws/resources/aws.lr.go b/providers/aws/resources/aws.lr.go index 3df057e883..86441846ca 100644 --- a/providers/aws/resources/aws.lr.go +++ b/providers/aws/resources/aws.lr.go @@ -710,6 +710,10 @@ func init() { // to override args, implement: initAwsEks(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) Create: createAwsEks, }, + "aws.eks.nodegroup": { + // to override args, implement: initAwsEksNodegroup(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) + Create: createAwsEksNodegroup, + }, "aws.eks.cluster": { // to override args, implement: initAwsEksCluster(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) Create: createAwsEksCluster, @@ -4199,6 +4203,45 @@ var getDataFields = map[string]func(r plugin.Resource) *plugin.DataRes{ "aws.eks.clusters": func(r plugin.Resource) *plugin.DataRes { return (r.(*mqlAwsEks).GetClusters()).ToDataRes(types.Array(types.Resource("aws.eks.cluster"))) }, + "aws.eks.nodegroup.name": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetName()).ToDataRes(types.String) + }, + "aws.eks.nodegroup.arn": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetArn()).ToDataRes(types.String) + }, + "aws.eks.nodegroup.region": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetRegion()).ToDataRes(types.String) + }, + "aws.eks.nodegroup.createdAt": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetCreatedAt()).ToDataRes(types.Time) + }, + "aws.eks.nodegroup.status": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetStatus()).ToDataRes(types.String) + }, + "aws.eks.nodegroup.capacityType": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetCapacityType()).ToDataRes(types.String) + }, + "aws.eks.nodegroup.scalingConfig": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetScalingConfig()).ToDataRes(types.Dict) + }, + "aws.eks.nodegroup.instanceTypes": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetInstanceTypes()).ToDataRes(types.Array(types.String)) + }, + "aws.eks.nodegroup.amiType": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetAmiType()).ToDataRes(types.String) + }, + "aws.eks.nodegroup.nodeRole": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetNodeRole()).ToDataRes(types.Resource("aws.iam.role")) + }, + "aws.eks.nodegroup.diskSize": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetDiskSize()).ToDataRes(types.Int) + }, + "aws.eks.nodegroup.labels": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetLabels()).ToDataRes(types.Map(types.String, types.String)) + }, + "aws.eks.nodegroup.tags": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksNodegroup).GetTags()).ToDataRes(types.Map(types.String, types.String)) + }, "aws.eks.cluster.name": func(r plugin.Resource) *plugin.DataRes { return (r.(*mqlAwsEksCluster).GetName()).ToDataRes(types.String) }, @@ -4238,6 +4281,9 @@ var getDataFields = map[string]func(r plugin.Resource) *plugin.DataRes{ "aws.eks.cluster.createdAt": func(r plugin.Resource) *plugin.DataRes { return (r.(*mqlAwsEksCluster).GetCreatedAt()).ToDataRes(types.Time) }, + "aws.eks.cluster.nodeGroups": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlAwsEksCluster).GetNodeGroups()).ToDataRes(types.Array(types.Resource("aws.eks.nodegroup"))) + }, } func GetData(resource plugin.Resource, field string, args map[string]*llx.RawData) *plugin.DataRes { @@ -9498,6 +9544,62 @@ var setDataFields = map[string]func(r plugin.Resource, v *llx.RawData) bool { r.(*mqlAwsEks).Clusters, ok = plugin.RawToTValue[[]interface{}](v.Value, v.Error) return }, + "aws.eks.nodegroup.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).__id, ok = v.Value.(string) + return + }, + "aws.eks.nodegroup.name": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).Name, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.arn": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).Arn, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.region": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).Region, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.createdAt": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).CreatedAt, ok = plugin.RawToTValue[*time.Time](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.status": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).Status, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.capacityType": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).CapacityType, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.scalingConfig": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).ScalingConfig, ok = plugin.RawToTValue[interface{}](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.instanceTypes": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).InstanceTypes, ok = plugin.RawToTValue[[]interface{}](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.amiType": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).AmiType, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.nodeRole": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).NodeRole, ok = plugin.RawToTValue[*mqlAwsIamRole](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.diskSize": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).DiskSize, ok = plugin.RawToTValue[int64](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.labels": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).Labels, ok = plugin.RawToTValue[map[string]interface{}](v.Value, v.Error) + return + }, + "aws.eks.nodegroup.tags": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksNodegroup).Tags, ok = plugin.RawToTValue[map[string]interface{}](v.Value, v.Error) + return + }, "aws.eks.cluster.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { r.(*mqlAwsEksCluster).__id, ok = v.Value.(string) return @@ -9554,6 +9656,10 @@ var setDataFields = map[string]func(r plugin.Resource, v *llx.RawData) bool { r.(*mqlAwsEksCluster).CreatedAt, ok = plugin.RawToTValue[*time.Time](v.Value, v.Error) return }, + "aws.eks.cluster.nodeGroups": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlAwsEksCluster).NodeGroups, ok = plugin.RawToTValue[[]interface{}](v.Value, v.Error) + return + }, } func SetData(resource plugin.Resource, field string, val *llx.RawData) error { @@ -24732,6 +24838,147 @@ func (c *mqlAwsEks) GetClusters() *plugin.TValue[[]interface{}] { }) } +// mqlAwsEksNodegroup for the aws.eks.nodegroup resource +type mqlAwsEksNodegroup struct { + MqlRuntime *plugin.Runtime + __id string + mqlAwsEksNodegroupInternal + Name plugin.TValue[string] + Arn plugin.TValue[string] + Region plugin.TValue[string] + CreatedAt plugin.TValue[*time.Time] + Status plugin.TValue[string] + CapacityType plugin.TValue[string] + ScalingConfig plugin.TValue[interface{}] + InstanceTypes plugin.TValue[[]interface{}] + AmiType plugin.TValue[string] + NodeRole plugin.TValue[*mqlAwsIamRole] + DiskSize plugin.TValue[int64] + Labels plugin.TValue[map[string]interface{}] + Tags plugin.TValue[map[string]interface{}] +} + +// createAwsEksNodegroup creates a new instance of this resource +func createAwsEksNodegroup(runtime *plugin.Runtime, args map[string]*llx.RawData) (plugin.Resource, error) { + res := &mqlAwsEksNodegroup{ + MqlRuntime: runtime, + } + + err := SetAllData(res, args) + if err != nil { + return res, err + } + + if res.__id == "" { + res.__id, err = res.id() + if err != nil { + return nil, err + } + } + + if runtime.HasRecording { + args, err = runtime.ResourceFromRecording("aws.eks.nodegroup", res.__id) + if err != nil || args == nil { + return res, err + } + return res, SetAllData(res, args) + } + + return res, nil +} + +func (c *mqlAwsEksNodegroup) MqlName() string { + return "aws.eks.nodegroup" +} + +func (c *mqlAwsEksNodegroup) MqlID() string { + return c.__id +} + +func (c *mqlAwsEksNodegroup) GetName() *plugin.TValue[string] { + return &c.Name +} + +func (c *mqlAwsEksNodegroup) GetArn() *plugin.TValue[string] { + return plugin.GetOrCompute[string](&c.Arn, func() (string, error) { + return c.arn() + }) +} + +func (c *mqlAwsEksNodegroup) GetRegion() *plugin.TValue[string] { + return &c.Region +} + +func (c *mqlAwsEksNodegroup) GetCreatedAt() *plugin.TValue[*time.Time] { + return plugin.GetOrCompute[*time.Time](&c.CreatedAt, func() (*time.Time, error) { + return c.createdAt() + }) +} + +func (c *mqlAwsEksNodegroup) GetStatus() *plugin.TValue[string] { + return plugin.GetOrCompute[string](&c.Status, func() (string, error) { + return c.status() + }) +} + +func (c *mqlAwsEksNodegroup) GetCapacityType() *plugin.TValue[string] { + return plugin.GetOrCompute[string](&c.CapacityType, func() (string, error) { + return c.capacityType() + }) +} + +func (c *mqlAwsEksNodegroup) GetScalingConfig() *plugin.TValue[interface{}] { + return plugin.GetOrCompute[interface{}](&c.ScalingConfig, func() (interface{}, error) { + return c.scalingConfig() + }) +} + +func (c *mqlAwsEksNodegroup) GetInstanceTypes() *plugin.TValue[[]interface{}] { + return plugin.GetOrCompute[[]interface{}](&c.InstanceTypes, func() ([]interface{}, error) { + return c.instanceTypes() + }) +} + +func (c *mqlAwsEksNodegroup) GetAmiType() *plugin.TValue[string] { + return plugin.GetOrCompute[string](&c.AmiType, func() (string, error) { + return c.amiType() + }) +} + +func (c *mqlAwsEksNodegroup) GetNodeRole() *plugin.TValue[*mqlAwsIamRole] { + return plugin.GetOrCompute[*mqlAwsIamRole](&c.NodeRole, func() (*mqlAwsIamRole, error) { + if c.MqlRuntime.HasRecording { + d, err := c.MqlRuntime.FieldResourceFromRecording("aws.eks.nodegroup", c.__id, "nodeRole") + if err != nil { + return nil, err + } + if d != nil { + return d.Value.(*mqlAwsIamRole), nil + } + } + + return c.nodeRole() + }) +} + +func (c *mqlAwsEksNodegroup) GetDiskSize() *plugin.TValue[int64] { + return plugin.GetOrCompute[int64](&c.DiskSize, func() (int64, error) { + return c.diskSize() + }) +} + +func (c *mqlAwsEksNodegroup) GetLabels() *plugin.TValue[map[string]interface{}] { + return plugin.GetOrCompute[map[string]interface{}](&c.Labels, func() (map[string]interface{}, error) { + return c.labels() + }) +} + +func (c *mqlAwsEksNodegroup) GetTags() *plugin.TValue[map[string]interface{}] { + return plugin.GetOrCompute[map[string]interface{}](&c.Tags, func() (map[string]interface{}, error) { + return c.tags() + }) +} + // mqlAwsEksCluster for the aws.eks.cluster resource type mqlAwsEksCluster struct { MqlRuntime *plugin.Runtime @@ -24750,6 +24997,7 @@ type mqlAwsEksCluster struct { NetworkConfig plugin.TValue[interface{}] ResourcesVpcConfig plugin.TValue[interface{}] CreatedAt plugin.TValue[*time.Time] + NodeGroups plugin.TValue[[]interface{}] } // createAwsEksCluster creates a new instance of this resource @@ -24840,3 +25088,19 @@ func (c *mqlAwsEksCluster) GetResourcesVpcConfig() *plugin.TValue[interface{}] { func (c *mqlAwsEksCluster) GetCreatedAt() *plugin.TValue[*time.Time] { return &c.CreatedAt } + +func (c *mqlAwsEksCluster) GetNodeGroups() *plugin.TValue[[]interface{}] { + return plugin.GetOrCompute[[]interface{}](&c.NodeGroups, func() ([]interface{}, error) { + if c.MqlRuntime.HasRecording { + d, err := c.MqlRuntime.FieldResourceFromRecording("aws.eks.cluster", c.__id, "nodeGroups") + if err != nil { + return nil, err + } + if d != nil { + return d.Value.([]interface{}), nil + } + } + + return c.nodeGroups() + }) +} diff --git a/providers/aws/resources/aws.lr.manifest.yaml b/providers/aws/resources/aws.lr.manifest.yaml index ece8b481f0..c93c4d3665 100755 --- a/providers/aws/resources/aws.lr.manifest.yaml +++ b/providers/aws/resources/aws.lr.manifest.yaml @@ -1497,6 +1497,8 @@ resources: Use the `aws.eks` resource to assess the configuration of Amazon Elastic Kubernetes Service (EKS). fields: clusters: {} + nodeGroups: + min_mondoo_version: 9.0.0 min_mondoo_version: 5.31.0 platform: name: @@ -1513,6 +1515,8 @@ resources: logging: {} name: {} networkConfig: {} + nodeGroups: + min_mondoo_version: 9.0.0 platformVersion: {} region: {} resourcesVpcConfig: {} @@ -1524,6 +1528,27 @@ resources: platform: name: - aws + aws.eks.nodegroup: + fields: + amiType: {} + arn: {} + autoscalingGroups: {} + capacityType: {} + createdAt: {} + diskSize: {} + instanceTypes: {} + labels: {} + name: {} + nodeRole: {} + region: {} + scalingConfig: {} + status: {} + tags: {} + is_private: true + min_mondoo_version: 9.0.0 + platform: + name: + - aws aws.elasticache: docs: desc: | diff --git a/providers/aws/resources/aws_eks.go b/providers/aws/resources/aws_eks.go index 326e37a4b3..5872cba59b 100644 --- a/providers/aws/resources/aws_eks.go +++ b/providers/aws/resources/aws_eks.go @@ -5,11 +5,16 @@ package resources import ( "context" + "sync" + "time" + + ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types" "github.com/aws/aws-sdk-go-v2/service/eks" "github.com/aws/aws-sdk-go/aws" "github.com/rs/zerolog/log" "go.mondoo.com/cnquery/v11/llx" + "go.mondoo.com/cnquery/v11/providers-sdk/v1/plugin" "go.mondoo.com/cnquery/v11/providers-sdk/v1/util/convert" "go.mondoo.com/cnquery/v11/providers-sdk/v1/util/jobpool" "go.mondoo.com/cnquery/v11/providers/aws/connection" @@ -123,3 +128,182 @@ func (a *mqlAwsEks) getClusters(conn *connection.AwsConnection) []*jobpool.Job { func (a *mqlAwsEksCluster) id() (string, error) { return a.Arn.Data, nil } + +func (a *mqlAwsEksCluster) nodeGroups() ([]interface{}, error) { + conn := a.MqlRuntime.Connection.(*connection.AwsConnection) + regionVal := a.Region.Data + log.Debug().Msgf("eks>getNodegroups>calling aws with region %s", regionVal) + + svc := conn.Eks(regionVal) + ctx := context.Background() + res := []interface{}{} + + nodeGroupsRes, err := svc.ListNodegroups(ctx, &eks.ListNodegroupsInput{ClusterName: aws.String(a.Name.Data)}) + if err != nil { + if Is400AccessDeniedError(err) { + log.Warn().Str("region", regionVal).Msg("error accessing region for AWS API") + return res, nil + } + return nil, err + } + + if nodeGroupsRes == nil { + return nil, nil + } + + for i := range nodeGroupsRes.Nodegroups { + nodegroup := nodeGroupsRes.Nodegroups[i] + args := map[string]*llx.RawData{ + "name": llx.StringData(nodegroup), + "region": llx.StringData(regionVal), + } + + mqlNg, err := CreateResource(a.MqlRuntime, "aws.eks.nodegroup", args) + if err != nil { + return nil, err + } + mqlNg.(*mqlAwsEksNodegroup).clusterName = a.Name.Data + mqlNg.(*mqlAwsEksNodegroup).region = regionVal + res = append(res, mqlNg) + } + return res, nil +} + +type mqlAwsEksNodegroupInternal struct { + details *ekstypes.Nodegroup + region string + lock sync.Mutex + clusterName string +} + +func (a *mqlAwsEksNodegroup) id() (string, error) { + return a.Arn.Data, nil +} + +func (a *mqlAwsEksNodegroup) fetchDetails() (*ekstypes.Nodegroup, error) { + if a.details != nil { + return a.details, nil + } + a.lock.Lock() + defer a.lock.Unlock() + conn := a.MqlRuntime.Connection.(*connection.AwsConnection) + ctx := context.Background() + svc := conn.Eks(a.region) + desc, err := svc.DescribeNodegroup(ctx, &eks.DescribeNodegroupInput{NodegroupName: aws.String(a.Name.Data), ClusterName: aws.String(a.clusterName)}) + if err != nil { + return nil, err + } + a.details = desc.Nodegroup + return desc.Nodegroup, nil +} + +func (a *mqlAwsEksNodegroup) arn() (string, error) { + ng, err := a.fetchDetails() + if err != nil { + return "", err + } + return *ng.NodegroupArn, nil +} + +func (a *mqlAwsEksNodegroup) capacityType() (string, error) { + ng, err := a.fetchDetails() + if err != nil { + return "", err + } + return string(ng.CapacityType), nil +} + +func (a *mqlAwsEksNodegroup) status() (string, error) { + ng, err := a.fetchDetails() + if err != nil { + return "", err + } + return string(ng.Status), nil +} + +func (a *mqlAwsEksNodegroup) amiType() (string, error) { + ng, err := a.fetchDetails() + if err != nil { + return "", err + } + return string(ng.AmiType), nil +} + +func (a *mqlAwsEksNodegroup) diskSize() (int64, error) { + ng, err := a.fetchDetails() + if err != nil { + return 0, err + } + return int64(*ng.DiskSize), nil +} + +func (a *mqlAwsEksNodegroup) createdAt() (*time.Time, error) { + ng, err := a.fetchDetails() + if err != nil { + return nil, err + } + return ng.CreatedAt, nil +} + +func (a *mqlAwsEksNodegroup) scalingConfig() (map[string]interface{}, error) { + ng, err := a.fetchDetails() + if err != nil { + return nil, err + } + return convert.JsonToDict(ng.ScalingConfig) +} + +func (a *mqlAwsEksNodegroup) instanceTypes() ([]interface{}, error) { + ng, err := a.fetchDetails() + if err != nil { + return nil, err + } + s := []interface{}{} + for i := range ng.InstanceTypes { + s = append(s, ng.InstanceTypes[i]) + } + return s, nil +} + +func (a *mqlAwsEksNodegroup) labels() (map[string]interface{}, error) { + ng, err := a.fetchDetails() + if err != nil { + return nil, err + } + new := make(map[string]interface{}) + for k, v := range ng.Labels { + new[k] = v + } + return new, nil +} + +func (a *mqlAwsEksNodegroup) tags() (map[string]interface{}, error) { + ng, err := a.fetchDetails() + if err != nil { + return nil, err + } + new := make(map[string]interface{}) + for k, v := range ng.Labels { + new[k] = v + } + return new, nil +} + +func (a *mqlAwsEksNodegroup) nodeRole() (*mqlAwsIamRole, error) { + ng, err := a.fetchDetails() + if err != nil { + return nil, err + } + if ng.NodeRole == nil { + a.NodeRole.State = plugin.StateIsNull | plugin.StateIsSet + return nil, nil + } + mqlIam, err := NewResource(a.MqlRuntime, "aws.iam.role", + map[string]*llx.RawData{ + "arn": llx.StringDataPtr(ng.NodeRole), + }) + if err != nil { + return nil, err + } + return mqlIam.(*mqlAwsIamRole), nil +} diff --git a/providers/aws/resources/aws_iam.go b/providers/aws/resources/aws_iam.go index 721006ba27..27526e0330 100644 --- a/providers/aws/resources/aws_iam.go +++ b/providers/aws/resources/aws_iam.go @@ -10,6 +10,7 @@ import ( "fmt" "net/url" "strconv" + "strings" "time" "github.com/aws/aws-sdk-go-v2/aws/arn" @@ -1217,8 +1218,19 @@ func initAwsIamRole(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[ svc := conn.Iam("") ctx := context.Background() + var rolename string + if args["name"] == nil && args["arn"] != nil { + a, err := arn.Parse(args["arn"].Value.(string)) + if err != nil { + return nil, nil, err + } + rolename = strings.TrimPrefix(a.Resource, "role/") + } if args["name"] != nil { - rolename := args["name"].Value.(string) + rolename = args["name"].Value.(string) + } + + if rolename != "" { resp, err := svc.GetRole(ctx, &iam.GetRoleInput{ RoleName: &rolename, })