{"id":24637932,"url":"https://github.com/upbound/function-azresourcegraph","last_synced_at":"2026-01-16T08:01:28.311Z","repository":{"id":271927832,"uuid":"896097685","full_name":"upbound/function-azresourcegraph","owner":"upbound","description":"Function for making queries to Azure Resource Graph API","archived":false,"fork":false,"pushed_at":"2026-01-13T13:16:03.000Z","size":296,"stargazers_count":6,"open_issues_count":5,"forks_count":3,"subscribers_count":13,"default_branch":"main","last_synced_at":"2026-01-13T15:58:40.897Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/upbound.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-29T14:38:59.000Z","updated_at":"2026-01-13T13:14:20.000Z","dependencies_parsed_at":"2025-01-10T20:22:54.144Z","dependency_job_id":"c47a527c-98ab-489b-967d-8eceda4f8fb8","html_url":"https://github.com/upbound/function-azresourcegraph","commit_stats":null,"previous_names":["upbound/function-azresourcegraph"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/upbound/function-azresourcegraph","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/upbound%2Ffunction-azresourcegraph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/upbound%2Ffunction-azresourcegraph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/upbound%2Ffunction-azresourcegraph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/upbound%2Ffunction-azresourcegraph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/upbound","download_url":"https://codeload.github.com/upbound/function-azresourcegraph/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/upbound%2Ffunction-azresourcegraph/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28478047,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T06:30:42.265Z","status":"ssl_error","status_checked_at":"2026-01-16T06:30:16.248Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-25T10:12:34.849Z","updated_at":"2026-01-16T08:01:28.240Z","avatar_url":"https://github.com/upbound.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# function-azresourcegraph\n[![CI](https://github.com/upbound/function-azresourcegraph/actions/workflows/ci.yml/badge.svg)](https://github.com/upbound/function-azresourcegraph/actions/workflows/ci.yml)\n\nA function to query [Azure Resource Graph][azresourcegraph]\n\n## Usage\n\nSee the [examples][examples] for a variety of practical and testable use cases demonstrating this Function.\n\nExample pipeline step:\n\n```yaml\n  pipeline:\n  - step: query-azresourcegraph\n    functionRef:\n      name: function-azresourcegraph\n    input:\n      apiVersion: azresourcegraph.fn.crossplane.io/v1alpha1\n      kind: Input\n      query: \"Resources | project name, location, type, id| where type =~ 'Microsoft.Compute/virtualMachines' | order by name desc\"\n      target: \"status.azResourceGraphQueryResult\"\n    credentials:\n      - name: azure-creds\n        source: Secret\n        secretRef:\n          namespace: upbound-system\n          name: azure-account-creds\n```\n\nThe Azure Credentials Secret structure is fully compatible with the standard\n[Azure Official Provider][azop]\n\nExample XR status after e2e query:\n\n```yaml\napiVersion: example.crossplane.io/v1\nkind: XR\nmetadata:\n...\nstatus:\n  azResourceGraphQueryResult:\n  - id: /subscriptions/f403a412-959c-4214-8c4d-ad5598f149cc/resourceGroups/us-vm-zxqnj-s2jdb/providers/Microsoft.Compute/virtualMachines/us-vm-zxqnj-2h59v\n    location: centralus\n    name: us-vm-zxqnj-2h59v\n    type: microsoft.compute/virtualmachines\n  - id: /subscriptions/f403a412-959c-4214-8c4d-ad5598f149cc/resourceGroups/us-vm-lzbpt-tdv2h/providers/Microsoft.Compute/virtualMachines/us-vm-lzbpt-fgcds\n    location: centralus\n    name: us-vm-lzbpt-fgcds\n    type: microsoft.compute/virtualmachines\n```\n\n### QueryRef\n\nRather than specifying a direct query string as shown in the example above,\nthe function allows referencing a query from any arbitrary field within the Context or Status.\n\n#### Context Query Reference\n\n* Simple context field reference\n```yaml\n      queryRef: \"context.azResourceGraphQuery\"\n```\n\n* Get data from Environment\n```yaml\n      queryRef: \"context.[apiextensions.crossplane.io/environment].azResourceGraphQuery\"\n```\n\n#### XR Status Query Reference\n\n* Simple XR Status field reference\n```yaml\n      queryRef: \"status.azResourceGraphQuery\"\n```\n\n* Get data from nested field in XR status. Use brackets if key contains dots.\n```yaml\n      queryRef: \"status.[fancy.key.with.dots].azResourceGraphQuery\"\n```\n\n### Targets\n\nFunction supports publishing Query Results to different locations.\n\n#### Context Target\n\n* Simple Context field target\n```yaml\n      target: \"context.azResourceGraphQueryResult\"\n```\n\n* Put results into Environment key\n```yaml\n      target: \"context.[apiextensions.crossplane.io/environment].azResourceGraphQuery\"\n```\n\n#### XR Status Target\n\n* Simple XR status field target\n```yaml\n      target: \"status.azResourceGraphQueryResult\"\n```\n\n* Put query results to nested field under XR status. Use brackets if key contains dots\n```yaml\n      target: \"status.[fancy.key.with.dots].azResourceGraphQueryResult\"\n```\n\n## Mitigating Azure API throttling\n\nIf you encounter Azure API throttling, you can reduce the number of queries\nusing the optional `skipQueryWhenTargetHasData` flag:\n\n```yaml\n  - step: query-azresourcegraph\n    functionRef:\n      name: function-azresourcegraph\n    input:\n      apiVersion: azresourcegraph.fn.crossplane.io/v1beta1\n      kind: Input\n      query: \"Resources | project name, location, type, id| where type =~ 'Microsoft.Compute/virtualMachines' | order by name desc\"\n      target: \"status.azResourceGraphQueryResult\"\n      skipQueryWhenTargetHasData: true # Optional: Set to true to skip query if target already contains data\n```\n\nUse this option carefully, as it may lead to stale query results over time.\n\n## Explicit Subscriptions scope\n\nIt is possible to specify explicit subscriptions scope and override the one that\nis coming from credentials\n\n```yaml\n      kind: Input\n      query: \"Resources | project name, location, type, id| where type =~ 'Microsoft.Compute/virtualMachines' | order by name desc\"\n      subscriptions:\n        - 00000000-0000-0000-0000-000000000001\n        - 00000000-0000-0000-0000-000000000002\n      target: \"status.azResourceGraphQueryResult\"\n```\n\nThere is also possible to use references from status and context.\n\n\n```yaml\nsubscriptionsRef: status.subscriptions\n```\n\n```yaml\nsubscriptionsRef: \"context.[apiextensions.crossplane.io/environment].subscriptions\"\n```\n\n## Round-robin Service Principal Authentication\n\nTo further mitigate Azure ARM throttling, you can now use multiple service principals with automatic round-robin selection. This distributes load across multiple identities and reduces the likelihood of hitting rate limits.\n\n### Multiple Service Principals\n\nConfigure multiple service principals in your credentials secret as a JSON array:\n\n```yaml\ncredentials:\n  - name: azure-creds\n    source: Secret\n    secretRef:\n      namespace: upbound-system\n      name: azure-account-creds\n```\n\nWith the secret containing:\n\n```json\n[\n  {\n    \"subscriptionId\": \"sub-id\",\n    \"tenantId\": \"tenant-id\",\n    \"clientId\": \"client-1\",\n    \"clientSecret\": \"secret-1\"\n  },\n  {\n    \"subscriptionId\": \"sub-id\",\n    \"tenantId\": \"tenant-id\",\n    \"clientId\": \"client-2\",\n    \"clientSecret\": \"secret-2\"\n  }\n]\n```\n\n### How Round-Robin Works\n\n- Each reconciliation cycle automatically selects the next service principal\n- Load is distributed evenly across all configured service principals\n- The function cycles through: SP-0 → SP-1 → SP-2 → SP-0 → SP-1 → SP-2...\n- Single service principal format is still supported for backward compatibility\n\n### Benefits\n\n- **Prevents Throttling**: Distributes API calls across multiple service principals\n- **Load Balancing**: Evenly distributes workload\n- **Easy Scaling**: Add more service principals without code changes\n- **Backward Compatible**: Existing single service principal configurations work unchanged\n\n[azresourcegraph]: https://learn.microsoft.com/en-us/azure/governance/resource-graph/\n[azop]: https://marketplace.upbound.io/providers/upbound/provider-family-azure/latest\n[examples]: ./example\n\n## Workload Identity Authentication\nAKS cluster needs to have workload identity enabled.\nThe managed identity needs to have the Federated Identity Credential created: https://azure.github.io/azure-workload-identity/docs/topics/federated-identity-credential.html.\n\n\u0026#x26a0;\u0026#xfe0f;\nDoes not support Multiple Service Principals with Round-Robin\n\n### Credentials secret:\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: azure-account-creds\n  namespace: crossplane-system\ntype: Opaque\nstringData:\n  credentials: |\n    {\n      \"clientId\": \"your-client-id\", # optional, defaults to AZURE_CLIENT_ID injected by Azure Workload Identity\n      \"tenantId\": \"your-tenant-id\", # optional, defaults to AZURE_TENANT_ID injected by Azure Workload Identity\n      \"subscriptionId\": \"your-subscription-id\" # optional, if both subscriptionId and Explicit Subscriptions scope is not defined defaults to tenant-scope search\n      \"federatedTokenFile\": \"/var/run/secrets/azure/tokens/azure-identity-token\"\n    }\n```\n\n#### Function\n```yaml\napiVersion: pkg.crossplane.io/v1\nkind: Function\nmetadata:\n  name: upbound-function-azresourcegraph\nspec:\n  package: xpkg.upbound.io/upbound/function-azresourcegraph:v0.10.0\n  runtimeConfigRef:\n    apiVersion: pkg.crossplane.io/v1beta1\n    kind: DeploymentRuntimeConfig\n    name: upbound-function-azresourcegraph\n```\n\n#### DeploymentRuntimeConfig\n```yaml\napiVersion: pkg.crossplane.io/v1beta1\nkind: DeploymentRuntimeConfig\nmetadata:\n  name: upbound-function-azresourcegraph\nspec: \n  deploymentTemplate:\n    spec:\n      selector:\n        matchLabels:\n          azure.workload.identity/use: \"true\"\n          pkg.crossplane.io/function: \"upbound-function-azresourcegraph\"\n      template:\n        metadata:\n          labels:\n            azure.workload.identity/use: \"true\"\n            pkg.crossplane.io/function: \"upbound-function-azresourcegraph\"\n        spec:\n          containers:\n          - name: package-runtime\n            volumeMounts:\n            - mountPath: /var/run/secrets/azure/tokens\n              name: azure-identity-token\n              readOnly: true\n          serviceAccountName: \"upbound-function-azresourcegraph\"\n          volumes:\n          - name: azure-identity-token\n            projected:\n              sources:\n              - serviceAccountToken:\n                  audience: api://AzureADTokenExchange\n                  expirationSeconds: 3600\n                  path: azure-identity-token\n  serviceAccountTemplate:\n    metadata:\n      annotations:\n        azure.workload.identity/client-id: \"your-client-id\"\n      name: \"upbound-function-azresourcegraph\"\n```\n\n## Using Different Credentials\n\n### Using ServicePrincipal credentials\n\n#### Explicitly\n```yaml\napiVersion: azresourcegraph.fn.crossplane.io/v1beta1\nkind: Input\nidentity:\n  type: AzureServicePrincipalCredentials\n```\n\n#### Default\n```yaml\napiVersion: azresourcegraph.fn.crossplane.io/v1beta1\nkind: Input\n```\n\n### Using Workload Identity Credentials\n```yaml\napiVersion: azresourcegraph.fn.crossplane.io/v1beta1\nkind: Input\nidentity:\n  type: AzureWorkloadIdentityCredentials\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fupbound%2Ffunction-azresourcegraph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fupbound%2Ffunction-azresourcegraph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fupbound%2Ffunction-azresourcegraph/lists"}