Skip to content

Conversation

@manas-metron
Copy link

@manas-metron manas-metron commented Jun 27, 2025

Summary by CodeRabbit

  • New Features

    • Added commands to list Intune managed devices and their compliance information, including options for detailed compliance settings and filtering.
    • Introduced support for retrieving Intune device configuration and compliance states.
    • Added new data models and enumerations for Intune device management, compliance, and configuration states.
  • Chores

    • Updated ignore rules to exclude certain workflow files and scripts from version control.

…etron-azurehound-enhancement-metronlabs

Files are causing a conflict because newly created files were added but the deleted files were not removed.
# Test the current implementation

Build the app using:

go build -ldflags="-s -w -X github.com/bloodhoundad/azurehound/v2/constants.Version=dev-intune"

Then test using added JWT token after these commands:

./azurehound list intune-devices --jwt JWT_TOKEN
./azurehound list intune-data --jwt JWT_TOKEN
./azurehound list intune-compliance --jwt JWT_TOKEN
Add
1. client id
2. client secret &
3. tenant id
for the script to work.
@coderabbitai
Copy link

coderabbitai bot commented Jun 27, 2025

Walkthrough

This change introduces comprehensive Intune integration, adding new commands to list Intune managed devices and their compliance states. It defines Intune-specific enums and data models, extends the Azure client interface with Intune methods, and implements asynchronous, concurrent data retrieval for Intune devices, compliance, and configuration states. The .gitignore is also updated.

Changes

File(s) Change Summary
.gitignore Added rules to ignore .github directory, specific workflow files, and get_token.ps1.
client/client.go Extended AzureClient interface with three Intune-related methods for device, compliance, and configuration retrieval.
client/intune_devices.go Implements asynchronous methods on azureClient for listing Intune devices and fetching compliance/configuration states.
cmd/list-intune-compliance.go Adds new intune-compliance command with concurrent, detailed compliance data collection and streaming.
cmd/list-intune-devices.go Adds new intune-devices command to stream Intune managed devices, with context and error handling.
enums/intune.go Introduces Intune-specific enums for device kinds, compliance states, enrollment types, management agents, and operating systems.
models/intune/models.go Defines Intune data models: ManagedDevice, ComplianceState, ComplianceSettingState, ConfigurationState, and related structs.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant AzureClient
    participant IntuneAPI

    User->>CLI: Run "intune-devices" or "intune-compliance"
    CLI->>AzureClient: Connect and authenticate
    CLI->>AzureClient: ListIntuneManagedDevices(params)
    AzureClient->>IntuneAPI: GET /managedDevices
    IntuneAPI-->>AzureClient: Stream paginated device data
    AzureClient-->>CLI: Stream ManagedDevice objects

    alt intune-compliance (detailed)
        CLI->>AzureClient: GetIntuneDeviceCompliance(deviceId)
        AzureClient->>IntuneAPI: GET /managedDevices/{id}/compliance
        IntuneAPI-->>AzureClient: Compliance data
        AzureClient-->>CLI: Stream ComplianceState objects
    end

    CLI-->>User: Output device/compliance data
Loading

Poem

🐇
Hopping through Intune fields anew,
Devices and compliance in my view!
With enums and models, I now explore,
Listing Windows, configs, and so much more.
Async streams and channels—what a delight!
Intune integration, shining bright.
—A happy rabbit, coding through the night.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Nitpick comments (6)
cmd/list-intune-devices.go (1)

49-51: Consider making the OS filter configurable.

The hard-coded Windows filter limits flexibility. Consider making this configurable via command-line flags to support other operating systems.

+var (
+    osFilter string
+)
+
+func init() {
+    listIntuneDevicesCmd.Flags().StringVar(&osFilter, "os", "Windows", "Filter by operating system (Windows, iOS, Android, macOS)")
+    listRootCmd.AddCommand(listIntuneDevicesCmd)
+}

 func listIntuneDevices(ctx context.Context, client client.AzureClient) <-chan interface{} {
     var (
         out    = make(chan interface{})
         params = query.GraphParams{
-            Filter: "operatingSystem eq 'Windows'", // Focus on Windows devices for BloodHound
+            Filter: fmt.Sprintf("operatingSystem eq '%s'", osFilter),
         }
     )
client/intune_devices.go (1)

18-18: Consider making the default Top value configurable.

The hard-coded value of 999 may not be optimal for all scenarios. Consider making this configurable or using a more reasonable default.

-        params.Top = 999
+        params.Top = 100 // More reasonable default, or make configurable
models/intune/models.go (3)

13-13: Inconsistent field naming: use "ID" instead of "Id" for Go conventions.

Go convention is to use "ID" for identifier fields, not "Id". This applies to multiple fields in the structs.

-	Id                    string    `json:"id"`
+	ID                    string    `json:"id"`
-	AzureADDeviceId      string    `json:"azureADDeviceId"`
+	AzureADDeviceID      string    `json:"azureADDeviceId"`

Apply similar changes to other structs in this file.

Also applies to: 21-21


28-36: Consider consolidating similar struct patterns.

The ComplianceState and ConfigurationState structs share very similar field patterns (ID, DeviceID, DeviceName, State, Version, SettingStates). Consider creating a base struct or using composition to reduce duplication.

+// BaseDeviceState represents common fields for device state structures
+type BaseDeviceState struct {
+	ID         string    `json:"id"`
+	DeviceID   string    `json:"deviceId"`
+	DeviceName string    `json:"deviceName"`
+	State      string    `json:"state"`
+	Version    int       `json:"version"`
+}
+
// ComplianceState represents device compliance information
type ComplianceState struct {
+	BaseDeviceState
-	Id                                     string    `json:"id"`
-	DeviceId                              string    `json:"deviceId"`
-	DeviceName                            string    `json:"deviceName"`
	ComplianceGracePeriodExpirationDateTime time.Time `json:"complianceGracePeriodExpirationDateTime"`
-	State                                 string    `json:"state"`
-	Version                               int       `json:"version"`
	SettingStates                         []ComplianceSettingState `json:"settingStates"`
}

Also applies to: 46-54


12-25: Add struct field documentation for better maintainability.

The struct fields would benefit from inline documentation explaining their purpose, especially for fields like EnrollmentType, ManagementAgent, and JoinType which may have specific meanings in the Intune context.

// ManagedDevice represents an Intune managed device
type ManagedDevice struct {
-	Id                    string    `json:"id"`
-	DeviceName           string    `json:"deviceName"`
-	OperatingSystem      string    `json:"operatingSystem"`
-	OSVersion            string    `json:"osVersion"`
-	ComplianceState      string    `json:"complianceState"`
-	LastSyncDateTime     time.Time `json:"lastSyncDateTime"`
-	EnrollmentType       string    `json:"enrollmentType"`
-	ManagementAgent      string    `json:"managementAgent"`
-	AzureADDeviceId      string    `json:"azureADDeviceId"`
-	UserPrincipalName    string    `json:"userPrincipalName"`
-	DeviceEnrollmentType string    `json:"deviceEnrollmentType"`
-	JoinType             string    `json:"joinType"`
+	ID                    string    `json:"id"`                    // Unique identifier for the device
+	DeviceName           string    `json:"deviceName"`           // Display name of the device
+	OperatingSystem      string    `json:"operatingSystem"`      // Operating system type (Windows, iOS, etc.)
+	OSVersion            string    `json:"osVersion"`            // Operating system version
+	ComplianceState      string    `json:"complianceState"`      // Current compliance status
+	LastSyncDateTime     time.Time `json:"lastSyncDateTime"`     // Last time device synced with Intune
+	EnrollmentType       string    `json:"enrollmentType"`       // How the device was enrolled
+	ManagementAgent      string    `json:"managementAgent"`      // Agent managing the device
+	AzureADDeviceID      string    `json:"azureADDeviceId"`      // Azure AD device identifier
+	UserPrincipalName    string    `json:"userPrincipalName"`    // UPN of the device user
+	DeviceEnrollmentType string    `json:"deviceEnrollmentType"` // Type of device enrollment
+	JoinType             string    `json:"joinType"`             // How device is joined to Azure AD
}
cmd/list-intune-compliance.go (1)

101-103: Hard-coded Windows filter limits functionality.

The function hard-codes filtering to Windows devices only, which limits the tool's flexibility for organizations with mixed device environments.

func getComplianceTargetDevices(ctx context.Context, client client.AzureClient) <-chan intune.ManagedDevice {
	var (
		out    = make(chan intune.ManagedDevice)
		params = query.GraphParams{
-			Filter: "operatingSystem eq 'Windows'",
+			// Allow filtering by OS through command line parameter if needed
+			// Filter: "operatingSystem eq 'Windows'",
		}
	)

Consider adding a command-line flag for OS filtering:

var targetOS string

func init() {
    listIntuneComplianceCmd.Flags().StringVar(&targetOS, "os", "Windows", "Filter by operating system")
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc3ed0f and 5fcda19.

📒 Files selected for processing (8)
  • .gitignore (1 hunks)
  • client/client.go (2 hunks)
  • client/intune_devices.go (1 hunks)
  • cmd/list-intune-compliance.go (1 hunks)
  • cmd/list-intune-devices.go (1 hunks)
  • enums/intune.go (1 hunks)
  • get_token.ps1 (1 hunks)
  • models/intune/models.go (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
client/client.go (2)
client/query/params.go (1)
  • GraphParams (109-120)
models/intune/models.go (3)
  • ManagedDevice (12-25)
  • ComplianceState (28-36)
  • ConfigurationState (46-54)
client/intune_devices.go (4)
client/query/params.go (2)
  • GraphParams (109-120)
  • Top (42-42)
client/client.go (1)
  • AzureResult (95-98)
models/intune/models.go (3)
  • ManagedDevice (12-25)
  • ComplianceState (28-36)
  • ConfigurationState (46-54)
constants/misc.go (1)
  • GraphApiVersion (43-43)
cmd/list-intune-devices.go (5)
panicrecovery/panic_recovery.go (2)
  • HandleBubbledPanic (14-26)
  • PanicRecovery (29-33)
client/client.go (1)
  • AzureClient (218-231)
client/query/params.go (1)
  • GraphParams (109-120)
cmd/utils.go (1)
  • NewAzureWrapper (437-442)
enums/intune.go (1)
  • KindAZIntuneDevice (5-5)
enums/intune.go (2)
enums/kind.go (1)
  • Kind (20-20)
models/intune/models.go (1)
  • ComplianceState (28-36)
🔇 Additional comments (10)
.gitignore (1)

235-238: Good security practice: Excluding sensitive files.

Properly excluding the token script and GitHub workflows from version control helps prevent accidental commits of sensitive configuration.

client/client.go (2)

35-35: LGTM: Proper import addition for Intune models.

The import for Intune models is correctly added to support the new interface methods.


226-230: LGTM: Well-designed interface extensions.

The new Intune methods follow consistent patterns with existing interface methods:

  • Accept context and query parameters
  • Return channels for async streaming
  • Use clear, descriptive naming
  • Maintain type safety with generics
cmd/list-intune-devices.go (2)

31-44: LGTM: Proper command structure and error handling.

The command implementation follows established patterns with:

  • Proper context cancellation setup
  • Signal handling for graceful shutdown
  • Appropriate logging and timing
  • Panic recovery handling

66-66: To verify where NewAzureWrapper is defined and whether an import is actually required, let’s locate its declaration and check the packages:

#!/bin/bash
# 1. Find all occurrences of NewAzureWrapper (definition and calls)
rg -n "NewAzureWrapper"

# 2. Confirm package declarations for the two files
grep -R "package " -n cmd/list-intune-devices.go cmd/utils.go
client/intune_devices.go (1)

24-34: LGTM: Well-structured API method implementation.

The ListIntuneManagedDevices method follows established patterns with proper endpoint construction and async channel-based results.

enums/intune.go (4)

4-9: Verify Kind constant naming consistency with existing patterns.

The Kind constants follow a specific naming pattern with "AZ" prefix. Ensure this aligns with existing Kind enumerations in the codebase.

#!/bin/bash
# Description: Check existing Kind constant patterns in the codebase
# Expected: Find similar naming patterns to ensure consistency

# Search for existing Kind constants to verify naming pattern
ast-grep --pattern 'const (
  $$$
  Kind$_ Kind = $_
  $$$
)'

# Also check for any existing AZ-prefixed Kind constants
rg -A 10 -B 2 'Kind.*=.*"AZ'

14-21: Validate ComplianceState enum values against Microsoft Graph API.

The compliance state values should match exactly what Microsoft Graph API returns to avoid mapping issues.

What are the valid compliance state values for Microsoft Intune devices in Microsoft Graph API?

47-52: Verify OperatingSystem enum values and consider adding missing platforms.

The enum includes major platforms but might be missing some that Intune supports (like Linux distributions).

What operating system values does Microsoft Graph API return for Intune managed devices?

26-32: Consider adding WindowsBulkEnrollment and other enrollment types.

The EnrollmentType enum might be missing some common Intune enrollment types. Verify completeness against the Microsoft Graph API documentation.

What are all the possible enrollment types for Microsoft Intune devices according to Microsoft Graph API deviceEnrollmentType property?

@SpecterOps SpecterOps deleted a comment from github-actions bot Jul 10, 2025
@github-actions
Copy link

CLA Assistant Lite bot:
Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
cmd/list-intune-compliance.go (1)

117-117: Consider making the operating system filter configurable.

The filter is hardcoded to only Windows devices, which may be too restrictive. Consider adding a flag to allow filtering by different operating systems or removing the OS filter entirely to support all managed devices.

-	params = query.GraphParams{
-		Filter: "operatingSystem eq 'Windows'",
-	}
+	params = query.GraphParams{}
+	
+	// Add OS filter if needed - could be made configurable
+	if operatingSystem := "Windows"; operatingSystem != "" {
+		params.Filter = fmt.Sprintf("operatingSystem eq '%s'", operatingSystem)
+	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fcda19 and bff0f20.

📒 Files selected for processing (2)
  • client/intune_devices.go (1 hunks)
  • cmd/list-intune-compliance.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • client/intune_devices.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
cmd/list-intune-compliance.go (7)
models/intune/models.go (1)
  • ManagedDevice (12-25)
panicrecovery/panic_recovery.go (2)
  • HandleBubbledPanic (14-26)
  • PanicRecovery (29-33)
client/client.go (1)
  • AzureClient (218-231)
pipeline/pipeline.go (1)
  • Demux (109-141)
config/config.go (1)
  • ColStreamCount (308-317)
cmd/utils.go (1)
  • NewAzureWrapper (437-442)
enums/intune.go (1)
  • KindAZIntuneCompliance (8-8)
🔇 Additional comments (5)
cmd/list-intune-compliance.go (5)

164-192: Well-implemented concurrent processing pattern.

The use of pipeline.Demux to split device processing across multiple streams with proper synchronization using sync.WaitGroup is excellent. The panic recovery and context cancellation handling are also correctly implemented.


194-234: Excellent error handling and fallback mechanism.

The improved error handling addresses previous concerns perfectly. The hasError flag with immediate break on first error, followed by fallback logic after the loop, ensures robust error recovery while preventing unnecessary processing.


25-33: ID collision prevention successfully implemented.

The use of time.Now().UnixNano() in the ID generation effectively prevents the collision issues identified in previous reviews while maintaining uniqueness across multiple invocations.


46-59: Robust input validation implementation.

The PreRunE validation function effectively prevents invalid compliance state values from being processed, addressing the security concerns from previous reviews.


123-138: Security validation successfully implemented.

The validation map approach effectively prevents injection attacks while maintaining clean filter construction. The early return on invalid state prevents further processing with malicious input.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants