Skip to content

Commit 647bf49

Browse files
committed
Rewrite to function-msgraph
- User Validation - Group Membership - Group Object IDs - Service Principal Details
1 parent ea32a03 commit 647bf49

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1132
-2688
lines changed

README.md

Lines changed: 175 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,223 @@
1-
# function-azresourcegraph
2-
[![CI](https://github.com/upbound/function-azresourcegraph/actions/workflows/ci.yml/badge.svg)](https://github.com/upbound/function-azresourcegraph/actions/workflows/ci.yml)
1+
# function-msgraph
32

4-
A function to query [Azure Resource Graph][azresourcegraph]
3+
A Crossplane composition function for querying the Microsoft Graph API.
54

6-
## Usage
5+
## Overview
76

8-
See the [examples][examples] for a variety of practical and testable use cases demonstrating this Function.
7+
The `function-msgraph` provides read-only access to Microsoft Graph API endpoints, allowing Crossplane compositions to:
98

10-
Example pipeline step:
9+
1. Validate Azure AD User Existence
10+
2. Get Group Membership
11+
3. Get Group Object IDs
12+
4. Get Service Principal Details
1113

12-
```yaml
13-
pipeline:
14-
- step: query-azresourcegraph
15-
functionRef:
16-
name: function-azresourcegraph
17-
input:
18-
apiVersion: azresourcegraph.fn.crossplane.io/v1alpha1
19-
kind: Input
20-
query: "Resources | project name, location, type, id| where type =~ 'Microsoft.Compute/virtualMachines' | order by name desc"
21-
target: "status.azResourceGraphQueryResult"
22-
credentials:
23-
- name: azure-creds
24-
source: Secret
25-
secretRef:
26-
namespace: upbound-system
27-
name: azure-account-creds
28-
```
14+
The function supports throttling mitigation with the `skipQueryWhenTargetHasData` flag to avoid unnecessary API calls.
2915

30-
The Azure Credentials Secret structure is fully compatible with the standard
31-
[Azure Official Provider][azop]
16+
## Usage
3217

33-
Example XR status after e2e query:
18+
Add the function to your Crossplane installation:
3419

3520
```yaml
36-
apiVersion: example.crossplane.io/v1
37-
kind: XR
21+
apiVersion: pkg.crossplane.io/v1beta1
22+
kind: Function
3823
metadata:
39-
...
40-
status:
41-
azResourceGraphQueryResult:
42-
- id: /subscriptions/f403a412-959c-4214-8c4d-ad5598f149cc/resourceGroups/us-vm-zxqnj-s2jdb/providers/Microsoft.Compute/virtualMachines/us-vm-zxqnj-2h59v
43-
location: centralus
44-
name: us-vm-zxqnj-2h59v
45-
type: microsoft.compute/virtualmachines
46-
- id: /subscriptions/f403a412-959c-4214-8c4d-ad5598f149cc/resourceGroups/us-vm-lzbpt-tdv2h/providers/Microsoft.Compute/virtualMachines/us-vm-lzbpt-fgcds
47-
location: centralus
48-
name: us-vm-lzbpt-fgcds
49-
type: microsoft.compute/virtualmachines
24+
name: function-msgraph
25+
spec:
26+
package: xpkg.upbound.io/upbound/function-msgraph:v0.1.0
5027
```
5128
52-
### QueryRef
53-
54-
Rather than specifying a direct query string as shown in the example above,
55-
the function allows referencing a query from any arbitrary field within the Context or Status.
29+
### Azure Credentials
5630
57-
#### Context Query Reference
31+
Create an Azure service principal with appropriate permissions to access Microsoft Graph API:
5832
59-
* Simple context field reference
6033
```yaml
61-
queryRef: "context.azResourceGraphQuery"
34+
apiVersion: v1
35+
kind: Secret
36+
metadata:
37+
name: azure-account-creds
38+
namespace: crossplane-system
39+
type: Opaque
40+
stringData:
41+
credentials: |
42+
{
43+
"clientId": "your-client-id",
44+
"clientSecret": "your-client-secret",
45+
"subscriptionId": "your-subscription-id",
46+
"tenantId": "your-tenant-id"
47+
}
6248
```
6349
64-
* Get data from Environment
65-
```yaml
66-
queryRef: "context.[apiextensions.crossplane.io/environment].azResourceGraphQuery"
67-
```
50+
The service principal needs the following Microsoft Graph API permissions:
51+
- User.Read.All (for user validation)
52+
- Group.Read.All (for group operations)
53+
- Application.Read.All (for service principal details)
6854
69-
#### XR Status Query Reference
55+
## Examples
7056
71-
* Simple XR Status field reference
72-
```yaml
73-
queryRef: "status.azResourceGraphQuery"
74-
```
57+
### Validate Azure AD Users
7558
76-
* Get data from nested field in XR status. Use brackets if key contains dots.
7759
```yaml
78-
queryRef: "status.[fancy.key.with.dots].azResourceGraphQuery"
60+
apiVersion: example.crossplane.io/v1
61+
kind: Composition
62+
metadata:
63+
name: user-validation-example
64+
spec:
65+
compositeTypeRef:
66+
apiVersion: example.crossplane.io/v1
67+
kind: XR
68+
pipeline:
69+
- step: validate-user
70+
functionRef:
71+
name: function-msgraph
72+
input:
73+
apiVersion: msgraph.fn.crossplane.io/v1alpha1
74+
kind: Input
75+
queryType: UserValidation
76+
users:
77+
78+
79+
target: "status.validatedUsers"
80+
skipQueryWhenTargetHasData: true
81+
credentials:
82+
- name: azure-creds
83+
source: Secret
84+
secretRef:
85+
namespace: crossplane-system
86+
name: azure-account-creds
7987
```
8088
81-
### Targets
82-
83-
Function supports publishing Query Results to different locations.
89+
### Get Group Membership
8490
85-
#### Context Target
86-
87-
* Simple Context field target
8891
```yaml
89-
target: "context.azResourceGraphQueryResult"
90-
```
91-
92-
* Put results into Environment key
93-
```yaml
94-
target: "context.[apiextensions.crossplane.io/environment].azResourceGraphQuery"
92+
apiVersion: example.crossplane.io/v1
93+
kind: Composition
94+
metadata:
95+
name: group-membership-example
96+
spec:
97+
compositeTypeRef:
98+
apiVersion: example.crossplane.io/v1
99+
kind: XR
100+
pipeline:
101+
- step: get-group-members
102+
functionRef:
103+
name: function-msgraph
104+
input:
105+
apiVersion: msgraph.fn.crossplane.io/v1alpha1
106+
kind: Input
107+
queryType: GroupMembership
108+
group: "Developers"
109+
# The function will automatically select standard fields:
110+
# - id, displayName, mail, userPrincipalName, appId, description
111+
target: "status.groupMembers"
112+
skipQueryWhenTargetHasData: true
113+
credentials:
114+
- name: azure-creds
115+
source: Secret
116+
secretRef:
117+
namespace: crossplane-system
118+
name: azure-account-creds
95119
```
96120
97-
#### XR Status Target
121+
### Get Group Object IDs
98122
99-
* Simple XR status field target
100123
```yaml
101-
target: "status.azResourceGraphQueryResult"
102-
```
103-
104-
* Put query results to nested field under XR status. Use brackets if key contains dots
105-
```yaml
106-
target: "status.[fancy.key.with.dots].azResourceGraphQueryResult"
124+
apiVersion: example.crossplane.io/v1
125+
kind: Composition
126+
metadata:
127+
name: group-objectids-example
128+
spec:
129+
compositeTypeRef:
130+
apiVersion: example.crossplane.io/v1
131+
kind: XR
132+
pipeline:
133+
- step: get-group-objectids
134+
functionRef:
135+
name: function-msgraph
136+
input:
137+
apiVersion: msgraph.fn.crossplane.io/v1alpha1
138+
kind: Input
139+
queryType: GroupObjectIDs
140+
groups:
141+
- "Developers"
142+
- "Operations"
143+
- "Security"
144+
target: "status.groupObjectIDs"
145+
skipQueryWhenTargetHasData: true
146+
credentials:
147+
- name: azure-creds
148+
source: Secret
149+
secretRef:
150+
namespace: crossplane-system
151+
name: azure-account-creds
107152
```
108153
109-
## Mitigating Azure API throttling
110-
111-
If you encounter Azure API throttling, you can reduce the number of queries
112-
using the optional `skipQueryWhenTargetHasData` flag:
154+
### Get Service Principal Details
113155
114156
```yaml
115-
- step: query-azresourcegraph
157+
apiVersion: example.crossplane.io/v1
158+
kind: Composition
159+
metadata:
160+
name: service-principal-example
161+
spec:
162+
compositeTypeRef:
163+
apiVersion: example.crossplane.io/v1
164+
kind: XR
165+
pipeline:
166+
- step: get-service-principal-details
116167
functionRef:
117-
name: function-azresourcegraph
168+
name: function-msgraph
118169
input:
119-
apiVersion: azresourcegraph.fn.crossplane.io/v1beta1
170+
apiVersion: msgraph.fn.crossplane.io/v1alpha1
120171
kind: Input
121-
query: "Resources | project name, location, type, id| where type =~ 'Microsoft.Compute/virtualMachines' | order by name desc"
122-
target: "status.azResourceGraphQueryResult"
123-
skipQueryWhenTargetHasData: true # Optional: Set to true to skip query if target already contains data
172+
queryType: ServicePrincipalDetails
173+
servicePrincipals:
174+
- "MyServiceApp"
175+
- "ApiConnector"
176+
target: "status.servicePrincipalDetails"
177+
skipQueryWhenTargetHasData: true
178+
credentials:
179+
- name: azure-creds
180+
source: Secret
181+
secretRef:
182+
namespace: crossplane-system
183+
name: azure-account-creds
124184
```
125185
126-
Use this option carefully, as it may lead to stale query results over time.
186+
## Input Configuration Options
127187
128-
## Explicit Subscriptions scope
188+
| Field | Type | Description |
189+
|-------|------|-------------|
190+
| `queryType` | string | Required. Type of query to perform. Valid values: `UserValidation`, `GroupMembership`, `GroupObjectIDs`, `ServicePrincipalDetails` |
191+
| `users` | []string | List of user principal names (email IDs) for user validation |
192+
| `group` | string | Single group name for group membership queries |
193+
| `groups` | []string | List of group names for group object ID queries |
194+
| `servicePrincipals` | []string | List of service principal names |
195+
| `queryRef` | string | Optional. Reference to retrieve the query from status or context. Format: `status.<field>` or `context.<field>` |
196+
| `target` | string | Required. Where to store the query results. Can be `status.<field>` or `context.<field>` |
197+
| `skipQueryWhenTargetHasData` | bool | Optional. When true, will skip the query if the target already has data |
129198

130-
It is possible to specify explicit subscriptions scope and override the one that
131-
is coming from credentials
199+
## Result Targets
200+
201+
Results can be stored in either XR Status or Composition Context:
132202

133203
```yaml
134-
kind: Input
135-
query: "Resources | project name, location, type, id| where type =~ 'Microsoft.Compute/virtualMachines' | order by name desc"
136-
subscriptions:
137-
- 00000000-0000-0000-0000-000000000001
138-
- 00000000-0000-0000-0000-000000000002
139-
target: "status.azResourceGraphQueryResult"
140-
```
204+
# Store in XR Status
205+
target: "status.results"
141206
142-
There is also possible to use references from status and context.
207+
# Store in nested XR Status
208+
target: "status.nested.field.results"
143209
210+
# Store in Composition Context
211+
target: "context.results"
144212
145-
```yaml
146-
subscriptionsRef: status.subscriptions
213+
# Store in Environment
214+
target: "context.[apiextensions.crossplane.io/environment].results"
147215
```
148216

149-
```yaml
150-
subscriptionsRef: "context.[apiextensions.crossplane.io/environment].subscriptions"
151-
```
217+
## References
152218

153-
[azresourcegraph]: https://learn.microsoft.com/en-us/azure/governance/resource-graph/
154-
[azop]: https://marketplace.upbound.io/providers/upbound/provider-family-azure/latest
155-
[examples]: ./example
219+
- [Microsoft Graph API Overview](https://learn.microsoft.com/en-us/graph/api/overview?view=graph-rest-1.0)
220+
- [User validation](https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=go)
221+
- [Group membership](https://learn.microsoft.com/en-us/graph/api/group-list-members?view=graph-rest-1.0&tabs=go)
222+
- [Group listing](https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0&tabs=go)
223+
- [Service principal listing](https://learn.microsoft.com/en-us/graph/api/serviceprincipal-list?view=graph-rest-1.0&tabs=http)

0 commit comments

Comments
 (0)