Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ on:

env:
# Common versions
GO_VERSION: '1.25.10'
GOLANGCI_VERSION: 'v2.8.0'
GO_VERSION: '1.26.0'
GOLANGCI_VERSION: 'v2.12.2'
DOCKER_BUILDX_VERSION: 'v0.23.0'

# These environment variables are important to the Crossplane CLI install.sh
Expand Down
89 changes: 50 additions & 39 deletions fn.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,24 @@ const (
LastQueryTimestampsField = "lastQueryTimestamps"
)

const (
// Microsoft Graph field names used in query projections ($select) and in the
// maps returned for query results.
fieldDisplayName = "displayName"
fieldAppID = "appId"
fieldDescription = "description"
fieldMail = "mail"
fieldUserPrincipalName = "userPrincipalName"
fieldType = "type"
)

const (
// Member type discriminators returned for group members.
userType = "user"
servicePrincipalType = "servicePrincipal"
unknownType = "unknown"
)

// GraphQueryInterface defines the methods required for querying Microsoft Graph API.
type GraphQueryInterface interface {
graphQuery(ctx context.Context, azureCreds map[string]string, in *v1beta1.Input) (interface{}, error)
Expand Down Expand Up @@ -526,7 +544,7 @@ func (g *GraphQuery) validateUsers(ctx context.Context, client *msgraphsdk.Graph
requestConfig.QueryParameters.Filter = &filterValue

// Use standard fields for user validation
requestConfig.QueryParameters.Select = []string{"id", "displayName", "userPrincipalName", "mail"}
requestConfig.QueryParameters.Select = []string{"id", fieldDisplayName, fieldUserPrincipalName, fieldMail}

// Execute the query
result, err := client.Users().Get(ctx, requestConfig)
Expand All @@ -538,10 +556,10 @@ func (g *GraphQuery) validateUsers(ctx context.Context, client *msgraphsdk.Graph
if result.GetValue() != nil {
for _, user := range result.GetValue() {
userMap := map[string]interface{}{
"id": ptr.Deref(user.GetId(), ""),
"displayName": ptr.Deref(user.GetDisplayName(), ""),
"userPrincipalName": ptr.Deref(user.GetUserPrincipalName(), ""),
"mail": ptr.Deref(user.GetMail(), ""),
"id": ptr.Deref(user.GetId(), ""),
fieldDisplayName: ptr.Deref(user.GetDisplayName(), ""),
fieldUserPrincipalName: ptr.Deref(user.GetUserPrincipalName(), ""),
fieldMail: ptr.Deref(user.GetMail(), ""),
}
results = append(results, userMap)
}
Expand Down Expand Up @@ -617,7 +635,7 @@ func (g *GraphQuery) extractDisplayName(member models.DirectoryObjectable, membe
additionalData := member.GetAdditionalData()

// Try to get from additional data first
if displayNameVal, exists := additionalData["displayName"]; exists && displayNameVal != nil {
if displayNameVal, exists := additionalData[fieldDisplayName]; exists && displayNameVal != nil {
if displayName, ok := displayNameVal.(string); ok {
return displayName
}
Expand Down Expand Up @@ -657,22 +675,22 @@ func (g *GraphQuery) extractStringProperty(additionalData map[string]interface{}
func (g *GraphQuery) extractUserProperties(member models.DirectoryObjectable, additionalData map[string]interface{}, memberMap map[string]interface{}) {
if user, ok := member.(models.Userable); ok {
if mail := ptr.Deref(user.GetMail(), ""); mail != "" {
memberMap["mail"] = mail
memberMap[fieldMail] = mail
}
if upn := ptr.Deref(user.GetUserPrincipalName(), ""); upn != "" {
memberMap["userPrincipalName"] = upn
memberMap[fieldUserPrincipalName] = upn
}
}

// Fall back to additionalData when the typed getters did not provide a value.
if _, ok := memberMap["mail"]; !ok {
if mail, found := g.extractStringProperty(additionalData, "mail"); found {
memberMap["mail"] = mail
if _, ok := memberMap[fieldMail]; !ok {
if mail, found := g.extractStringProperty(additionalData, fieldMail); found {
memberMap[fieldMail] = mail
}
}
if _, ok := memberMap["userPrincipalName"]; !ok {
if upn, found := g.extractStringProperty(additionalData, "userPrincipalName"); found {
memberMap["userPrincipalName"] = upn
if _, ok := memberMap[fieldUserPrincipalName]; !ok {
if upn, found := g.extractStringProperty(additionalData, fieldUserPrincipalName); found {
memberMap[fieldUserPrincipalName] = upn
}
}
}
Expand All @@ -682,27 +700,20 @@ func (g *GraphQuery) extractUserProperties(member models.DirectoryObjectable, ad
func (g *GraphQuery) extractServicePrincipalProperties(member models.DirectoryObjectable, additionalData map[string]interface{}, memberMap map[string]interface{}) {
if sp, ok := member.(models.ServicePrincipalable); ok {
if appID := ptr.Deref(sp.GetAppId(), ""); appID != "" {
memberMap["appId"] = appID
memberMap[fieldAppID] = appID
}
}

// Fall back to additionalData when the typed getter did not provide a value.
if _, ok := memberMap["appId"]; !ok {
if appID, found := g.extractStringProperty(additionalData, "appId"); found {
memberMap["appId"] = appID
if _, ok := memberMap[fieldAppID]; !ok {
if appID, found := g.extractStringProperty(additionalData, fieldAppID); found {
memberMap[fieldAppID] = appID
}
}
}

// processMember extracts member information into a map
func (g *GraphQuery) processMember(member models.DirectoryObjectable) map[string]interface{} {
// Define constants for member types
const (
userType = "user"
servicePrincipalType = "servicePrincipal"
unknownType = "unknown"
)

memberID := ptr.Deref(member.GetId(), "")
additionalData := member.GetAdditionalData()

Expand All @@ -715,14 +726,14 @@ func (g *GraphQuery) processMember(member models.DirectoryObjectable) map[string
memberType := unknownType

// Check properties that indicate user type
_, hasUserPrincipalName := g.extractStringProperty(additionalData, "userPrincipalName")
_, hasMail := g.extractStringProperty(additionalData, "mail")
_, hasUserPrincipalName := g.extractStringProperty(additionalData, fieldUserPrincipalName)
_, hasMail := g.extractStringProperty(additionalData, fieldMail)
if hasUserPrincipalName || hasMail {
memberType = userType
}

// Check properties that indicate service principal type
_, hasAppID := g.extractStringProperty(additionalData, "appId")
_, hasAppID := g.extractStringProperty(additionalData, fieldAppID)
if hasAppID {
memberType = servicePrincipalType
}
Expand All @@ -736,10 +747,10 @@ func (g *GraphQuery) processMember(member models.DirectoryObjectable) map[string
}

// Add type to member info
memberMap["type"] = memberType
memberMap[fieldType] = memberType

// Extract display name
memberMap["displayName"] = g.extractDisplayName(member, memberID)
memberMap[fieldDisplayName] = g.extractDisplayName(member, memberID)

// Extract type-specific properties
switch memberType {
Expand Down Expand Up @@ -809,7 +820,7 @@ func (g *GraphQuery) getGroupObjectIDs(ctx context.Context, client *msgraphsdk.G
requestConfig.QueryParameters.Filter = &filterValue

// Use standard fields for group object IDs
requestConfig.QueryParameters.Select = []string{"id", "displayName", "description"}
requestConfig.QueryParameters.Select = []string{"id", fieldDisplayName, fieldDescription}

groupResult, err := client.Groups().Get(ctx, requestConfig)
if err != nil {
Expand All @@ -819,9 +830,9 @@ func (g *GraphQuery) getGroupObjectIDs(ctx context.Context, client *msgraphsdk.G
if groupResult.GetValue() != nil && len(groupResult.GetValue()) > 0 {
for _, group := range groupResult.GetValue() {
groupMap := map[string]interface{}{
"id": ptr.Deref(group.GetId(), ""),
"displayName": ptr.Deref(group.GetDisplayName(), ""),
"description": ptr.Deref(group.GetDescription(), ""),
"id": ptr.Deref(group.GetId(), ""),
fieldDisplayName: ptr.Deref(group.GetDisplayName(), ""),
fieldDescription: ptr.Deref(group.GetDescription(), ""),
}
results = append(results, groupMap)
}
Expand Down Expand Up @@ -854,7 +865,7 @@ func (g *GraphQuery) getServicePrincipalDetails(ctx context.Context, client *msg
requestConfig.QueryParameters.Filter = &filterValue

// Use standard fields for service principals
requestConfig.QueryParameters.Select = []string{"id", "appId", "displayName", "description"}
requestConfig.QueryParameters.Select = []string{"id", fieldAppID, fieldDisplayName, fieldDescription}

spResult, err := client.ServicePrincipals().Get(ctx, requestConfig)
if err != nil {
Expand All @@ -864,10 +875,10 @@ func (g *GraphQuery) getServicePrincipalDetails(ctx context.Context, client *msg
if spResult.GetValue() != nil && len(spResult.GetValue()) > 0 {
for _, sp := range spResult.GetValue() {
spMap := map[string]interface{}{
"id": ptr.Deref(sp.GetId(), ""),
"appId": ptr.Deref(sp.GetAppId(), ""),
"displayName": ptr.Deref(sp.GetDisplayName(), ""),
"description": ptr.Deref(sp.GetDescription(), ""),
"id": ptr.Deref(sp.GetId(), ""),
fieldAppID: ptr.Deref(sp.GetAppId(), ""),
fieldDisplayName: ptr.Deref(sp.GetDisplayName(), ""),
fieldDescription: ptr.Deref(sp.GetDescription(), ""),
}
results = append(results, spMap)
}
Expand Down
Loading
Loading