Monday, November 27, 2023

How to Export Azure AD users to a CSV File with PowerShell script?

The script will download the following Attributes: 


1 ID
2 First name
3 Last name
4 Display name
5 User principal name
6 Email address
7 Job Title
8 Manager display name
9 Manager user principal name
10 Department
11 Company
12 Office
13 Employee ID
14 Mobile
15 Phone
16 Street
17 City
18 Postal code
19 State
20 Country
21 User type
22 On-Premises sync
23 Account status
24 Account created on
25 Last log in
26 Licensed
27 MFA status 



Step 1. Install Microsoft Graph PowerShell Module 


Run PowerShell as administrator. Run the command Install-Module PowershellGet -Force


Step 2. Connect to Microsoft Graph Explorer using  PowerShell

Connect to Azure Active Directory (AAD) with Microsoft Graph PowerShell.

PS C:\> Connect-MgGraph -Scopes "User.Read.All", "UserAuthenticationMethod.Read.All", "AuditLog.Read.All"

Note: Global Administrator right required. 

Step 3. Execute the below script. 

<#

    .SYNOPSIS

    Export-AADUsers.ps1


# Connect to Microsoft Graph API

Connect-MgGraph -Scopes "User.Read.All", "UserAuthenticationMethod.Read.All", "AuditLog.Read.All"


# Create variable for the date stamp

$LogDate = Get-Date -f yyyyMMddhhmm


# Define CSV file export location variable

$Csvfile = "C:\temp\AllAADUsers_$LogDate.csv"


# Define the Get-AllMgUsers function

Function Get-AllMgUsers {

    process {

        # Retrieve users using the Microsoft Graph API with property

        $propertyParams = @{

            All            = $true

            # Uncomment below if you have Azure AD P1/P2 to get last log in date

            # Property = 'SignInActivity'

            ExpandProperty = 'manager'

        }


        $users = Get-MgBetaUser @propertyParams

        $totalUsers = $users.Count


        # Initialize progress counter

        $progress = 0


        # Collect and loop through all users

        foreach ($index in 0..($totalUsers - 1)) {

            $user = $users[$index]


            # Update progress counter

            $progress++

            

           # Calculate percentage complete

            $percentComplete = ($progress / $totalUsers) * 100


            # Define progress bar parameters

            $progressParams = @{

                Activity        = "Processing Users"

                Status          = "User $($index + 1) of $totalUsers - $($user.userPrincipalName) - $($percentComplete -as [int])% Complete"

                PercentComplete = $percentComplete

            }

            

            # Display progress bar

            Write-Progress @progressParams


            # Get manager information

            $managerDN = $user.Manager.AdditionalProperties.displayName

            $managerUPN = $user.Manager.AdditionalProperties.userPrincipalName


            # Create an object to store user properties

            $userObject = [PSCustomObject]@{

                "ID"                          = $user.id

                "First name"                  = $user.givenName

                "Last name"                   = $user.surname

                "Display name"                = $user.displayName

                "User principal name"         = $user.userPrincipalName

                "Email address"               = $user.mail

                "Job title"                   = $user.jobTitle

                "Manager display name"        = $managerDN

                "Manager user principal name" = $managerUPN

                "Department"                  = $user.department

                "Company"                     = $user.companyName

                "Office"                      = $user.officeLocation

                "Employee ID"                 = $user.employeeID

                "Mobile"                      = $user.mobilePhone

                "Phone"                       = $user.businessPhones -join ','

                "Street"                      = $user.streetAddress

                "City"                        = $user.city

                "Postal code"                 = $user.postalCode

                "State"                       = $user.state

                "Country"                     = $user.country

                "User type"                   = $user.userType

                "On-Premises sync"            = if ($user.onPremisesSyncEnabled) { "enabled" } else { "disabled" }

                "Account status"              = if ($user.accountEnabled) { "enabled" } else { "disabled" }

                "Account Created on"          = $user.createdDateTime

                # Uncomment below if you have Azure AD P1/P2 to get last log in date

                # "Last log in"                 = if ($user.SignInActivity.LastSignInDateTime) { $user.SignInActivity.LastSignInDateTime } else { "No log in" }

                "Licensed"                    = if ($user.assignedLicenses.Count -gt 0) { "Yes" } else { "No" }

                "MFA status"                  = "-"

                "Email authentication"        = "-"

                "FIDO2 authentication"        = "-"

                "Microsoft Authenticator App" = "-"

                "Password authentication"     = "-"

                "Phone authentication"        = "-"

                "Software Oath"               = "-"

                "Temporary Access Pass"       = "-"

                "Windows Hello for Business"  = "-"

            }


            $MFAData = Get-MgBetaUserAuthenticationMethod -UserId $user.userPrincipalName


            # Check authentication methods for each user

            foreach ($method in $MFAData) {

                Switch ($method.AdditionalProperties["@odata.type"]) {

                    "#microsoft.graph.emailAuthenticationMethod" {

                        $userObject."Email authentication" = $true

                        $userObject."MFA status" = "Enabled"

                    }

                    "#microsoft.graph.fido2AuthenticationMethod" {

                        $userObject."FIDO2 authentication" = $true

                        $userObject."MFA status" = "Enabled"

                    }

                    "#microsoft.graph.microsoftAuthenticatorAuthenticationMethod" {

                        $userObject."Microsoft Authenticator App" = $true

                        $userObject."MFA status" = "Enabled"

                    }

                    "#microsoft.graph.passwordAuthenticationMethod" {

                        $userObject."Password authentication" = $true

                        # When only the password is set, then MFA is disabled.

                        if ($userObject."MFA status" -ne "Enabled") {

                            $userObject."MFA status" = "Disabled"

                        }

                    }

                    "#microsoft.graph.phoneAuthenticationMethod" {

                        $userObject."Phone authentication" = $true

                        $userObject."MFA status" = "Enabled"

                    }

                    "#microsoft.graph.softwareOathAuthenticationMethod" {

                        $userObject."Software Oath" = $true

                        $userObject."MFA status" = "Enabled"

                    }

                    "#microsoft.graph.temporaryAccessPassAuthenticationMethod" {

                        $userObject."Temporary Access Pass" = $true

                        $userObject."MFA status" = "Enabled"

                    }

                    "#microsoft.graph.windowsHelloForBusinessAuthenticationMethod" {

                        $userObject."Windows Hello for Business" = $true

                        $userObject."MFA status" = "Enabled"

                    }

                }

            }


            # Output the user object

            $userObject

        }

    }

}


# Export users to CSV

Get-AllMgUsers | Sort-Object "Display name" | Export-Csv -Path $Csvfile -NoTypeInformation -Encoding UTF8 #-Delimiter ";"



Note : The File will be downloaded to the "C:\Temp"


Disclaimer:  Please do test the script in Test Environment before Production. 



is it good idea to have azure AD connect and SQL installed on the same server?





Whether it's a good idea to have Azure AD Connect and SQL Server on the same server depends on various factors, including the size of your environment, resource availability, and your organization's specific requirements. Here are some considerations to help you make an informed decision:

  1. Resource Utilization:

    • Both Azure AD Connect and SQL Server can be resource-intensive applications. Ensure that the server has sufficient CPU, memory, and disk resources to handle the load generated by both services. If the server is adequately provisioned, co-locating them may be reasonable.
  2. Simplicity vs. Scalability:

    • Co-locating services simplifies management and reduces the overall server footprint. However, if your organization is growing rapidly, or if you have a large number of users and objects to synchronize, it might be more scalable to separate Azure AD Connect and SQL Server onto dedicated servers.
  3. Backup and Recovery:

    • Consider the backup and recovery strategy for the SQL Server database used by Azure AD Connect. Ensure that your backup plan is robust and can quickly restore data in case of a failure.
  4. Security Considerations:

    • Evaluate security requirements for both Azure AD Connect and SQL Server. Ensure that the appropriate security measures, such as firewall configurations and permissions, are in place to protect each service.
  5. High Availability:

    • If high availability is a critical requirement for your environment, co-locating may not be the best option. In a high-availability scenario, you might want to distribute services across multiple servers to reduce the risk of a single point of failure.
  6. Monitoring and Troubleshooting:

    • Implement monitoring solutions to track the performance and health of both Azure AD Connect and SQL Server. This will aid in troubleshooting issues and optimizing the performance of each service.
  7. Future Growth:

    • Consider your organization's growth plans. If you anticipate significant growth in terms of users, objects, or complexity, you might want to design your infrastructure to accommodate future scalability requirements.
  8. Best Practices:

    • Follow best practices recommended by Microsoft for both Azure AD Connect and SQL Server installations. This includes reviewing system requirements, configuration settings, and security considerations.

Ultimately, the decision to co-locate Azure AD Connect and SQL Server depends on your organization's specific needs, available resources, and future plans. It's a trade-off between simplicity and scalability, and there isn't a one-size-fits-all answer. If in doubt, consulting with your IT team or seeking advice from Microsoft support can provide tailored guidance based on your unique environment.

Saturday, February 4, 2023

Attribute mapping in Azure AD Connect


You can use the cloud sync attribute mapping feature to map attributes between your on-premises user or group objects and the objects in Azure AD.