Skip to content

[Cloud Asset Inventory] Add extra resource fields #1 - #6991

Merged
kubasobon merged 8 commits into
elastic:mainfrom
kubasobon:asset-discovery/missing-aws-fields
Jul 6, 2026
Merged

kubasobon merged 8 commits into
elastic:mainfrom
kubasobon:asset-discovery/missing-aws-fields

Conversation

@kubasobon

@kubasobon kubasobon commented Jun 26, 2026 •

Copy link
Copy Markdown
Member

Summary

Follow-up to InfoSec's review of #6991. Adds the remaining EC2 and ELB
fields InfoSec needs to retire their custom AWS CLI scripts for the FedRAMP
asset inventory. All new fields land in entity.attributes.* (non-ECS,
UpperCamelCase) — no ECS mapping change required.

Tracking: https://github.com/elastic/security-team/issues/17750

Changes

EC2 (entity.attributes):

  • ImageId, Platform, VpcId, SubnetId, State, RoleArn
  • Owner, CostCenter — resolved case-insensitively from instance tags

ELB v1 + v2 (entity.attributes):

  • LoadBalancerType — v2 reports the real type; v1 reports classic
  • AccountID
  • State — v2 only (State.Code); classic ELB exposes no state field
  • IPAddresses — NLB static IPs; ALB/classic are DNS-only (empty)
  • OwnerTag — required adding DescribeTags to both ELB Client
    interfaces and providers (batched to the 20-item AWS limit)

Notes

  • No elastic/integrations change: entity.attributes is flattened, so
    new keys need no mapping and there's no migration.
  • No new asset classifications, so ASSETS.md is unchanged. Route53 and
    EKS (also requested in the review) are separate follow-up PRs.
  • Mocks regenerated; unit tests cover EC2 attributes and the ELB
    Type/State/IPAddresses/OwnerTag flow end-to-end.

@mergify

This comment was marked as resolved.

kubasobon and others added 3 commits June 26, 2026 17:12
- gci: align map key spacing in fetcher_elb.go
- prealloc: preallocate routes slice in rds/provider.go
- revive: remove trailing empty line in azurefetcher groups loop
- revive: add default case to type switch in fetcher_resource_graph.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follow-up to InfoSec review of the missing-AWS-fields PR. Surfaces
additional EC2 and ELB fields into entity.attributes (non-ECS,
UpperCamelCase) so the Asset Discovery integration can replace the
custom AWS CLI scripts.

EC2:
- ImageId, Platform, VpcId, SubnetId, State, RoleArn from the instance
- Owner, CostCenter looked up case-insensitively from tags

ELB v1 + v2:
- LoadBalancerType (v2 real type; v1 "classic"), AccountID
- State (v2 only; classic ELB has no state field)
- IPAddresses (NLB static IPs; ALB/classic are DNS-only)
- OwnerTag via new DescribeTags plumbing on both providers
@kubasobon kubasobon changed the title [Cloud Asset Inventory] Add extra resource fields [Cloud Asset Inventory] Add extra resource fields #1 Jul 3, 2026

@romulets romulets left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Biggest question is about the lifecycle event which we don't extract

}
if i.IamInstanceProfile != nil {
if v := pointers.Deref(i.IamInstanceProfile.Arn); v != "" {
attrs["RoleArn"] = v

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is IamInstanceProfile.Arn directly understandable from a ec2 instance attributes.RoleArn? Isn't it better perhaps to be more explicit on the naming?

Just asking, I'm ok with your call.

@kubasobon kubasobon Jul 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IamInstanceProfile.Arn is a not strictly a Role ARN, according to AWS docs - it's a Identity Profile attached to the EC2 (which contains the role).

Comment thread internal/inventory/asset.go Outdated

// Lifecycle holds non-ECS lifecycle timestamps for an asset (non-ECS fields use UpperCamelCase).
type Lifecycle struct {
CreatedAt *time.Time `json:"CreatedAt,omitempty"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/elastic/kibana/blob/main/x-pack/solutions/security/plugins/entity_store/common/domain/definitions/common_fields.ts#L140-L156

This field is not extracted. If we extract, I'm not sure we should have it capitalised, it doesn't follow the other fields

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm aware. It's an untracked non-ECS, but I'm adding it to the integration on InfoSec's ask. It's not entity's creation date, but the resource's.

// timestamp. Values may arrive as time.Time (from typed SDK providers) or as RFC3339 strings
// (from the Resource Graph JSON response). Returns nil when no creation time is found.
func extractAzureCreatedAt(properties map[string]any) *time.Time {
for _, key := range []string{"createdTime", "timeCreated", "creationTime", "creationDate"} {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is interesting lol. I won't challenge because I know how azure is, but not super ideal haha

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that's just Azure being Azure 😅

if err != nil {
p.log.Errorf("Could not get route table for subnet %s of DB %s. Error: %v", *subnet.SubnetIdentifier, *dbInstance.DBInstanceIdentifier, err)
} else {
routes := make([]Route, 0, len(routeTableForSubnet.Routes))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memory thanks you

@kubasobon
kubasobon requested a review from romulets July 6, 2026 15:00
@mergify

mergify Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@kubasobon
kubasobon added this pull request to the merge queue Jul 6, 2026
Merged via the queue into elastic:main with commit a25d3cb Jul 6, 2026
12 checks passed
@kubasobon
kubasobon deleted the asset-discovery/missing-aws-fields branch July 6, 2026 16:46
gsarantid pushed a commit to gsarantid/cloudbeat that referenced this pull request Jul 6, 2026
…elastic#7183)

## Summary

Follow-up to InfoSec's review of elastic#6991: adds two AWS asset types the
FedRAMP inventory needs but cloudbeat didn't emit — **Route53 DNS
records** and **EKS clusters**. Both are greenfield providers +
fetchers. All resource-specific fields land in `entity.attributes.*`
(non-ECS, flattened), so no integration mapping change is required.

Tracking: elastic/security-team#17750
Merge after: elastic#6991

## Route53 (`awslib/route53`)

- New global provider (`ListHostedZones` → `ListResourceRecordSets`,
paginated); one asset per record set, carrying its parent zone.
- `entity.attributes`: `Type`, `ResourceRecords`, `Weight`, `Region`,
`ZoneID`, `ZoneName`, `AliasTargetDNS`, `AliasTargetZoneId`,
`HealthCheckId`.
- Classification: `{Infrastructure, "AWS Route53 DNS Record"}`. Region
reported as `global`. Records have no creation time in the SDK, so no
`CreatedAt`.

## EKS (`awslib/eks`)

- New regional provider (`ListClusters` → `DescribeCluster` per
cluster); one asset per cluster.
- `entity.attributes`: `Status`, `Version`, `Endpoint`, `RoleArn`,
`PlatformVersion`, `EndpointPublicAccess`, `EndpointPrivateAccess`,
`OwnerTag`; plus `entity.lifecycle.CreatedAt`.
- Classification: `{Orchestrator, "AWS EKS Cluster"}` (consistent with
GCP GKE).

## Notes

- **Dependency bump:** adding the EKS SDK pulled a core bump —
`aws-sdk-go-v2` 1.41.1→1.42.1, `smithy-go` 1.24.0→1.27.3, and two
indirect internal modules. Whole repo builds and tests pass.
- **ASSETS.md / spreadsheet:** regenerated (AWS coverage 21→23/85). The
`cloud_assets.xlsx` "EKS Cluster" row was moved from Infrastructure to
Orchestrator to match the classification (and GKE); the Route53 and EKS
"Updated Type" cells were filled so the generator marks them
implemented.
- **No `elastic/integrations` change:** `entity.attributes` is flattened
(arbitrary keys) and `entity.lifecycle.CreatedAt` +
`entity.type`/`sub_type` are already mapped by the 1.7.0 PR (#19795).

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants