Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
46 changes: 23 additions & 23 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/projectdiscovery/cloudlist

go 1.24.0

toolchain go1.24.1
toolchain go1.24.2

require (
git.arvancloud.ir/arvancloud/cdn-go-sdk v0.12.1
Expand Down Expand Up @@ -34,7 +34,7 @@ require (
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.14
github.com/stretchr/testify v1.10.0
golang.org/x/oauth2 v0.30.0
google.golang.org/api v0.232.0
google.golang.org/api v0.240.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.30.0
k8s.io/apimachinery v0.30.0
Expand All @@ -43,7 +43,7 @@ require (

require (
aead.dev/minisign v0.2.0 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/compute/metadata v0.7.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
Expand Down Expand Up @@ -89,7 +89,7 @@ require (
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/cronexpr v1.1.0 // indirect
Expand Down Expand Up @@ -151,18 +151,18 @@ require (
github.com/zcalusic/sysinfo v1.0.2 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/term v0.31.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.29.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect
google.golang.org/grpc v1.72.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.26.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.33.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.66.6 // indirect
Expand All @@ -187,7 +187,7 @@ require (
require (
cloud.google.com/go v0.120.0 // indirect
cloud.google.com/go/accesscontextmanager v1.9.6 // indirect
cloud.google.com/go/auth v0.16.1 // indirect
cloud.google.com/go/auth v0.16.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/iam v1.5.2 // indirect
cloud.google.com/go/longrunning v0.6.7 // indirect
Expand Down Expand Up @@ -232,13 +232,13 @@ require (
github.com/zmap/zcrypto v0.0.0-20230422215203-9a665e1e9968 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/metric v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/sync v0.14.0 // indirect
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
golang.org/x/sync v0.15.0 // indirect
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect
)
92 changes: 46 additions & 46 deletions go.sum

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions internal/runner/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Options struct {
Providers goflags.StringSlice // Providers specifies what providers to fetch assets for.
Id goflags.StringSlice // Id specifies what id's to fetch assets for.
Services goflags.StringSlice // Services specifies what services to fetch assets for a provider.
ExtendedMetadata bool // ExtendedMetadata enables extended metadata for providers.
ProviderConfig string // ProviderConfig is the location of the provider config file.
DisableUpdateCheck bool // DisableUpdateCheck disable automatic update check
}
Expand Down Expand Up @@ -82,6 +83,7 @@ func ParseOptions() *Options {
flagSet.StringSliceVar(&options.Id, "id", nil, "display results for given ids (comma-separated)", goflags.NormalizedStringSliceOptions),
flagSet.BoolVar(&options.Hosts, "host", false, "display only hostnames in results"),
flagSet.BoolVar(&options.IPAddress, "ip", false, "display only ips in results"),
flagSet.BoolVar(&options.ExtendedMetadata, "extended-metadata", false, "enable extended metadata for providers"),
flagSet.StringSliceVarP(&options.Services, "service", "s", nil, "query and display results from given service (comma-separated)) (default "+strings.Join(defaultServies, ",")+")", goflags.CommaSeparatedStringSliceOptions),
flagSet.BoolVarP(&options.ExcludePrivate, "exclude-private", "ep", false, "exclude private ips in cli output"),
)
Expand Down
4 changes: 4 additions & 0 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ func (r *Runner) Enumerate() {
if len(services) > 0 {
item["services"] = strings.Join(services, ",")
}
if r.options.ExtendedMetadata {
item["extended_metadata"] = "true"
}

// Validate and only pass the correct items to input
if len(r.options.Providers) != 0 || len(r.options.Id) != 0 {
if len(r.options.Providers) != 0 && !Contains(r.options.Providers, item["provider"]) {
Expand Down
154 changes: 154 additions & 0 deletions pkg/providers/aws/alb.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package aws
import (
"context"
"fmt"
"strings"
"sync"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
Expand Down Expand Up @@ -62,12 +64,20 @@ func (ep *elbV2Provider) listELBV2Resources(albClient *elbv2.ELBV2, ec2Client *e

for _, lb := range loadBalancers {
albDNS := *lb.DNSName

// Extract metadata for this load balancer
var metadata map[string]string
if ep.options.ExtendedMetadata {
metadata = ep.getLoadBalancerMetadata(lb, albClient)
}

resource := &schema.Resource{
Provider: "aws",
ID: *lb.LoadBalancerName,
DNSName: albDNS,
Public: true,
Service: ep.name(),
Metadata: metadata,
}
list.Append(resource)

Expand Down Expand Up @@ -102,12 +112,19 @@ func (ep *elbV2Provider) listELBV2Resources(albClient *elbv2.ELBV2, ec2Client *e
for _, reservation := range instanceOutput.Reservations {
for _, instance := range reservation.Instances {
if instance.PrivateIpAddress != nil {
// Extract metadata for target instance
var targetMetadata map[string]string
if ep.options.ExtendedMetadata {
targetMetadata = ep.getTargetInstanceMetadata(instance, target, tg, lb)
}

resource := &schema.Resource{
Provider: "aws",
ID: instanceID,
PrivateIpv4: *instance.PrivateIpAddress,
Public: false,
Service: ep.name(),
Metadata: targetMetadata,
}
list.Append(resource)
}
Expand Down Expand Up @@ -168,3 +185,140 @@ func (ep *elbV2Provider) getElbV2AndEc2Clients(region *string) ([]*elbv2.ELBV2,
}
return albClients, ec2Clients
}

func (ep *elbV2Provider) getLoadBalancerMetadata(lb *elbv2.LoadBalancer, albClient *elbv2.ELBV2) map[string]string {
metadata := make(map[string]string)

schema.AddMetadata(metadata, "load_balancer_name", lb.LoadBalancerName)
schema.AddMetadata(metadata, "type", lb.Type)
schema.AddMetadata(metadata, "scheme", lb.Scheme)
schema.AddMetadata(metadata, "dns_name", lb.DNSName)
schema.AddMetadata(metadata, "hosted_zone_id", lb.CanonicalHostedZoneId)
schema.AddMetadata(metadata, "vpc_id", lb.VpcId)
schema.AddMetadata(metadata, "ip_address_type", lb.IpAddressType)
schema.AddMetadata(metadata, "customer_owned_ipv4_pool", lb.CustomerOwnedIpv4Pool)

if lb.LoadBalancerArn != nil {
arn := aws.StringValue(lb.LoadBalancerArn)
metadata["arn"] = arn

// Extract owner ID from ARN (format: arn:aws:elasticloadbalancing:region:account-id:loadbalancer/app/name/id)
if arnComponents := parseARN(arn); arnComponents != nil && arnComponents.AccountID != "" {
metadata["owner_id"] = arnComponents.AccountID
}
}

if lb.State != nil {
schema.AddMetadata(metadata, "state", lb.State.Code)
schema.AddMetadata(metadata, "state_reason", lb.State.Reason)
}

if lb.CreatedTime != nil {
metadata["created_time"] = lb.CreatedTime.Format(time.RFC3339)
}

if len(lb.AvailabilityZones) > 0 {
var azs []string
var subnets []string
for _, az := range lb.AvailabilityZones {
if az.ZoneName != nil {
azs = append(azs, aws.StringValue(az.ZoneName))
}
if az.SubnetId != nil {
subnets = append(subnets, aws.StringValue(az.SubnetId))
}
}
if len(azs) > 0 {
metadata["availability_zones"] = strings.Join(azs, ",")
}
if len(subnets) > 0 {
metadata["subnet_ids"] = strings.Join(subnets, ",")
}
}
schema.AddMetadataList(metadata, "security_groups", lb.SecurityGroups)
if lb.LoadBalancerArn != nil {
if listeners, err := albClient.DescribeListeners(&elbv2.DescribeListenersInput{
LoadBalancerArn: lb.LoadBalancerArn,
}); err == nil && listeners.Listeners != nil {
schema.AddMetadataInt(metadata, "listener_count", len(listeners.Listeners))

var ports []string
var protocols []string
for _, listener := range listeners.Listeners {
if listener.Port != nil {
ports = append(ports, fmt.Sprintf("%d", aws.Int64Value(listener.Port)))
}
if listener.Protocol != nil {
protocols = append(protocols, aws.StringValue(listener.Protocol))
}
}
if len(ports) > 0 {
metadata["listener_ports"] = strings.Join(ports, ",")
}
if len(protocols) > 0 {
metadata["listener_protocols"] = strings.Join(protocols, ",")
}
}
}
if lb.LoadBalancerArn != nil {
if tagOutput, err := albClient.DescribeTags(&elbv2.DescribeTagsInput{
ResourceArns: []*string{lb.LoadBalancerArn},
}); err == nil && tagOutput.TagDescriptions != nil && len(tagOutput.TagDescriptions) > 0 {
for _, tagDesc := range tagOutput.TagDescriptions {
if tagString := buildELBv2TagString(tagDesc.Tags); tagString != "" {
metadata["tags"] = tagString
break
}
}
}
}

return metadata
}

func (ep *elbV2Provider) getTargetInstanceMetadata(instance *ec2.Instance, target *elbv2.TargetHealthDescription, tg *elbv2.TargetGroup, lb *elbv2.LoadBalancer) map[string]string {
metadata := make(map[string]string)

schema.AddMetadata(metadata, "instance_id", instance.InstanceId)
schema.AddMetadata(metadata, "instance_type", instance.InstanceType)
schema.AddMetadata(metadata, "private_dns_name", instance.PrivateDnsName)

if instance.State != nil {
schema.AddMetadata(metadata, "instance_state", instance.State.Name)
}
if target.Target != nil && target.Target.Port != nil {
metadata["target_port"] = fmt.Sprintf("%d", aws.Int64Value(target.Target.Port))
}
if target.TargetHealth != nil {
schema.AddMetadata(metadata, "health_state", target.TargetHealth.State)
schema.AddMetadata(metadata, "health_reason", target.TargetHealth.Reason)
schema.AddMetadata(metadata, "health_description", target.TargetHealth.Description)
}
schema.AddMetadata(metadata, "target_group_name", tg.TargetGroupName)
schema.AddMetadata(metadata, "target_type", tg.TargetType)
schema.AddMetadata(metadata, "load_balancer_name", lb.LoadBalancerName)
if lb.LoadBalancerArn != nil {
arn := aws.StringValue(lb.LoadBalancerArn)

if arnComponents := parseARN(arn); arnComponents != nil && arnComponents.AccountID != "" {
metadata["owner_id"] = arnComponents.AccountID
}
}
if len(instance.Tags) > 0 {
if tagString := buildTagString(instance.Tags); tagString != "" {
metadata["instance_tags"] = tagString
}
}
return metadata
}

func buildELBv2TagString(tags []*elbv2.Tag) string {
var tagPairs []string
for _, tag := range tags {
if tag.Key != nil && tag.Value != nil {
tagPairs = append(tagPairs, fmt.Sprintf("%s=%s",
aws.StringValue(tag.Key), aws.StringValue(tag.Value)))
}
}
return strings.Join(tagPairs, ",")
}
Loading
Loading