| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A composition function that runs read-only queries against AWS APIs and exposes the results as structured data to downstream composition steps (function-python, function-kcl, go-templating, patch-and-transform, etc.) — available regions, AZs, AMI lookups, caller identity, service quotas, and existing resources by tag. It is the AWS analog of function-azresourcegraph (Azure) and function-msgraph (Microsoft Graph).
Each composition pipeline step supplies an Input selecting a queryType. The result is written to target (status.<field> or context.<field>).
Service-metadata (direct EC2/STS/Service Quotas calls — no account setup):
| queryType | Returns |
|---|---|
| GetCallerIdentity | {account, arn, userId} |
| DescribeRegions | [{name, endpoint, optInStatus}] |
| DescribeAvailabilityZones | [{name, zoneId, state, regionName, zoneType, groupName}] |
| DescribeImages | [{imageId, name, ownerId, creationDate, architecture, state, rootDeviceType, description}] |
| DescribeRouteTables | [{routeTableId, vpcId, ownerId, associations[{routeTableAssociationId, routeTableId, subnetId, gatewayId, main, state}], routes[{destinationCidrBlock, destinationIpv6CidrBlock, destinationPrefixListId, gatewayId, natGatewayId, transitGatewayId, vpcPeeringConnectionId, egressOnlyInternetGatewayId, carrierGatewayId, localGatewayId, coreNetworkArn, instanceId, networkInterfaceId, origin, state}], tags{}}]. Carries the main association ID, which no CloudFormation schema models. filters required: vpc-id, route-table-id, association.subnet-id, tag:<key>. |
| DescribeSubnets | [{subnetId, subnetArn, vpcId, ownerId, availabilityZone, availabilityZoneId, cidrBlock, state, defaultForAz, mapPublicIpOnLaunch, availableIpAddressCount, ipv6Native, ipv6CidrBlockAssociationSet[{associationId, ipv6CidrBlock, state}], tags{}}]. Returns only live subnets, unlike the Tagging API. filters required: vpc-id, subnet-id, availability-zone, tag:<key>. |
| DescribeSecurityGroupRules | [{securityGroupRuleId, securityGroupRuleArn, groupId, groupOwnerId, isEgress, ipProtocol, fromPort, toPort, cidrIpv4, cidrIpv6, prefixListId, referencedGroupId, referencedGroupUserId, referencedGroupVpcId, description, tags{}}]. filters required: group-id, security-group-rule-id, tag:<key> - this operation does not accept vpc-id. |
| ListServiceQuotas | [{quotaCode, quotaName, value, unit, adjustable, globalQuota}] (all quotas for a serviceCode) |
| GetServiceQuota | {quotaCode, quotaName, value, unit, adjustable, globalQuota} (a single quota; needs serviceCode+quotaCode) |
Existing-resource inventory (generic, no Config/Resource-Explorer setup):
| queryType | Backend | Returns |
|---|---|---|
| ListResources | AWS Cloud Control | [{identifier, properties{…}}] for any CloudFormation-modeled type; each resource is hydrated via GetResource for full attributes + tags (set parameters.hydrate=false for identifiers only). Filter client-side via filters. |
| GetResources | Resource Groups Tagging API | [{arn, tags{}}] — server-side tag/type filtering |
Rule of thumb: IDs by tag → GetResources; attributes / full inventory of a type → ListResources; EC2 identifiers CloudFormation does not model, or an authoritative VPC-scoped read → the direct Describe* query types.
On absent values, the direct EC2 describes take two deliberate policies. Fields AWS always returns are projected with their zero value (isEgress: false, main: false, cidrBlock: ""). Fields that are genuinely optional are omitted rather than faked: fromPort/toPort are absent on a rule that has no ports, and referencedGroup* only appears on a group-referencing rule. Omitting is the honest choice - fromPort: 0 is a real port - so guard in templates ({{ if .fromPort }}) rather than assuming the key exists. Note real EC2 does send fromPort: -1, toPort: -1 for an all-protocol rule, so a truly absent port is rarer than it looks.
apiVersion: aws.fn.crossplane.io/v1beta1
kind: Input
queryType: <one of the above> # required
region: eu-central-1 # or regionRef: spec.region (status./context./spec.)
filters: # or filtersRef: <path> (status./context./spec.)
- name: "tag:Environment"
values: ["prod"]
parameters: # or parametersRef: <path>; scalar args per queryType:
# allRegions, allAvailabilityZones (bool); owners, imageIds (csv) [EC2]
# serviceCode, quotaCode [Service Quotas]
# typeName, resourceModel, roleArn, hydrate (default true) [Cloud Control]
# resourceTypeFilters (csv) [Tagging API]
typeName: "AWS::EC2::VPC"
target: status.prodVpcs # required; status.* or context.*
skipQueryWhenTargetHasData: true # optional
queryIntervalMinutes: 10 # optional throttle
identity: # optional; defaults to Secret
source: Secret # Secret | IRSA | WebIdentity | PodIdentity
assumeRoleChain:
- roleARN: arn:aws:iam::222222222222:role/crossplane-readonlyDynamic queries: regionRef, filtersRef, and parametersRef resolve their value from a status./context./spec. path at runtime (overriding the static field), so a prior pipeline step or the XR can drive the query — the AWS analog of azresourcegraph's queryRef/subscriptionsRef.
Mirrors provider-upjet-aws — the credentials Secret is a shared-credentials INI byte-identical to the AWS provider's Secret source, so existing secrets are reusable. Supported identity.source values: Secret (default), IRSA, WebIdentity (token via Secret or filesystem), PodIdentity, plus an assumeRoleChain. See example/README.md for the full matrix and a DeploymentRuntimeConfig for IRSA/PodIdentity.
Validates a composition against real AWS in seconds — the fastest way to try a query.
# 1. Put working AWS credentials in example/secrets/aws-creds.yaml: base64 of an
# AWS shared-credentials INI, under the "credentials" key. For example:
# printf '[default]\naws_access_key_id = AKIA...\naws_secret_access_key = ...\n' | base64
# 2. Run the function locally.
go run . --insecure --debug &
# 3. Render any example (see example/ for one composition per queryType).
crossplane render example/xr.yaml example/composition.yaml example/functions.yaml \
--function-credentials=example/secrets/aws-creds.yaml -rcThe rendered XR shows the query result under status (here, status.allAvailableRegions).
# 1. Install the function. Replace the tag with a released version (or your own
# pushed package).
kubectl apply -f - <<'EOF'
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: function-aws-query
spec:
package: xpkg.upbound.io/upbound/function-aws-query:v0.1.0
EOF
# 2. Create the credentials Secret in your control plane's system namespace.
# It must match the secretRef in the composition (name + namespace). Reuse the
# same secret you already use for provider-aws, or create one from a file:
kubectl -n crossplane-system create secret generic aws-creds \
--from-file=credentials="$HOME/.aws/credentials"
# 3. Apply the API definition, the composition, and an example resource.
kubectl apply -f example/definition.yaml
kubectl apply -f example/composition.yaml
kubectl apply -f example/xr.yaml
# 4. Confirm the AWS query result lands on the resource's status.
kubectl get xaccount example-account -o yamlFor IRSA / Pod Identity instead of a Secret, attach a DeploymentRuntimeConfig to the Function (see example/deploymentruntimeconfig.yaml) and set identity.source: IRSA (or PodIdentity) — no Secret needed.
# Run code generation - see input/generate.go
go generate ./...
# Run tests - see fn_test.go and aws_test.go
go test -v ./...
# Lint
golangci-lint run
# Build the function's runtime image and package
docker build . --tag=runtime
crossplane xpkg build -f package --embed-runtime-image=runtimeSee example/README.md for the full per-queryType render matrix and the authentication-source reference.
| Back | FazBrowse Home | New Git URL |