Have you ever needed to automate the management of computer extension attributes in Entra AD? Look no further! The Extension Attributes Automation Worker Service is here to help you streamline this process.
This service is designed to automate the management of extension attributes in Entra AD, reducing manual effort and potential errors. It leverages the power of .NET Core and widely adopted NuGet packages to provide a robust solution for your automation needs. This project is part of a larger automation framework that aims to simplify data processing tasks, making it easier for you to manage your Entra AD environment.
Entra AD (Active Directory) is a cloud-based identity and access management service from Microsoft. It allows organizations to manage user identities and access to resources securely. Extension attributes are custom attributes that can be added to Entra AD objects, such as users and computers, to store additional information. These attributes can be used for various purposes, such as storing metadata or integrating with other systems or more simply to store create dynamic groups based on these attributes.
Entra AD Connect is a tool that synchronizes on-premises directories with Entra AD, allowing organizations to manage their identities in a hybrid environment. However, it has limitations when it comes to synchronizing certain attributes, such as computer extension attributes.
Unfortunately, Entra AD Connect does not synchronize computer extension attributes, which can lead to manual effort and potential errors when managing these attributes. The Extension Attributes Automation Worker Service automates the management of these attributes, ensuring that they are kept up to date and reducing the need for manual intervention. Values for extension attributes can be set based on existing AD computer object attributes, such as the distinguuished name, location, or other relevant information already present in the AD computer object.
The Extension Attributes Automation Worker Service is a an application designed to work mainly as a Windows service to automate the process of managing computer extension attributes in Entra AD. This service is part of a larger automation framework that aims to streamline data processing tasks. This project is built in C# and the .NET Core 9.0 framework leveraging largely adopted NuGet packages like Microsoft.Extensions.Hosting, Quartz.Net and Serilog.
- The solution can run either as standalone console application, either running as a Windows service, allowing it to operate in the background without user intervention
- The solution enables to map all computer extension attributes to existing AD computer object attributes, leveraging regular expressions to extract, if needed, specific values from the existing AD computer object attributes
- It can be configured to run at specified intervals, ensuring that extension attributes are updated regularly leveraging Quartz.Net, a very efficient and largely adopted NuGet package
- Given the nature of the application, it is designed to be run on a Windows server, but it can also be run on any machine that supports .NET Core 9.0
- This solution aims to fill the gap of the Entra AD Connect to synchronize computer extension attributes. To do that it automates the management of extension attributes in Entra AD, leveraging current AD Computer object attributes, reducing manual effort and potential errors.
- The service is designed to be extensible, allowing for future enhancements and additional features.
To run this solution, you need to have the following prerequisites in place:
To run this service, you need to have .NET Core 9.0 or later installed on your machine. You can download the latest version of .NET Core from the official .NET website.
-
Download the installer for your operating system.
-
Run the installer and follow the instructions to install .NET Core.
-
Verify the installation by opening a terminal and running the following command:
dotnet --version
the expected output should be similar to:
9.0.201
If you see a version number, it means .NET Core is installed correctly. If you see an error message, please check the installation instructions again or refer to the official documentation. This should display the version of .NET Core installed on your machine.
To use this service, you need to create an Entra AD App Registration with the necessary permissions to manage extension attributes.
To create the Entra AD app registration follow these steps:
-
Go to the Azure portal.
-
Navigate to "Azure Active Directory" > "App registrations".
-
Click on "New registration".
-
Fill in the required fields:
-
Name: Enter a name for your app registration (e.g., "ExtensionAttributesAutomationWorker").
-
Supported account types: Choose the appropriate option based on your organization's needs.
-
Redirect URI: Leave this blank for now.
-
Click "Register" to create the app registration.
-
After the app registration is created, navigate to "Certificates & secrets".
To authenticate the service, you can either create a client secret or upload a certificate. You can choose one of the following methods:
Though using a client secret is not recommended for production environments, it can be used for testing purposes. To create a client secret, follow these steps:
-
Click on "New client secret" to create a new client secret.
-
Fill in the required fields:
-
Description: Enter a description for the client secret (e.g., "Worker Service Secret").
-
Expires: Choose an expiration period for the secret.
-
Click "Add" to create the client secret.
-
Copy the value of the client secret and store it securely, as you will need it later.
-
Use this method if you want to use a certificate for authentication. This is the recommended approach for production environments, as it provides better security and management of credentials.
- Open PowerShell as an administrator.
- Run the following command to create a self-signed certificate:
$cert = New-SelfSignedCertificate -DnsName "ExtensionAttributesAutomationWorker" -CertStoreLocation "cert:\LocalMachine\My"
This command creates a self-signed certificate with the specified name and stores it in the local machine's certificate store. Important to note that the machine holds the private key of the certificate, so you need to export the certificate with the private key to a .pfx file:
- Export the certificate to a .cer file:
$certPath = "C:\path\to\your\certificate.cer" Export-Certificate -Cert $cert -FilePath $certPath
-
This command exports the certificate to the specified file path.
-
Upload the certificate to the Azure portal:
-
Go back to the Azure portal and navigate to your app registration.
-
Click on "Certificates & secrets" in the left menu.
-
Click on "Upload certificate" and select the .cer file you exported earlier.
-
Click "Add" to upload the certificate.
-
Navigate to "API permissions" and click on "Add a permission".
-
Choose "Microsoft Graph" and select "Application permissions".
-
Search for the following permissions and select them:
Device.ReadWrite.All
-
Click "Add permissions" to add the selected permissions.
-
Click on "Grant admin consent for [Your Organization]" to grant the permissions.
-
Confirm the action when prompted.
-
-
Remove any unnecessary permissions to ensure the principle of least privilege is followed.
-
For example, if you see the following permission, remove it:
User.Read.All
-
Click on the three dots (ellipsis) next to the permission.
-
Select the permission and click on "Remove permission" to remove it.
-
-
Navigate to "Overview" and copy the "Application (client) ID" and "Directory (tenant) ID". You will need these values later.
-
Store the "Application (client) ID", "Directory (tenant) ID", and the client secret securely, as you will need them to configure the service.
-
To use this solution, as already mentioned, you can run it either as a standalone console application or as a Windows service. The service can be configured to run at specified intervals, ensuring that extension attributes are updated regularly.
Before proceeding, make sure you have the following information ready:
- The "Application (client) ID" and "Directory (tenant) ID" from the Entra AD App Registration.
- The client secret or the certificate thumbprint you created earlier.
- The Entra AD tenant ID.
- The extension attribute names you want to manage (e.g.,
extensionAttribute1
,extensionAttribute2
, etc.). - The values you want to set for the extension attributes based on existing AD computer object attributes.
- The desired interval for the service to run (e.g., every 5 minutes, every hour, etc.).
- The desired logging level (e.g., Information, Warning, Error).
- The desired logging output folder path.
- The desired logging output file name prefix.
- The desired export path for the CSV files keeping the history of the changes made to the extension attributes.
- The desired export file name prefix for the CSV files.
All of the above information can be configured in ad-hoc configuration files located in the project root directory. These files are structured in a way that allows you to easily modify the settings without needing to change the code. The solution includes three configuration files to manage different aspects of the solution without inadvertently modifying unwanted configuration files:
appsettings.json
: Contains the main configuration settings for the service, including Entra AD App Registration details, extension attribute names, etc.logging.json
: Contains the logging configuration settings, including the desired logging level and output folder path.schedule.json
: Contains the scheduling configuration settings, including the desired interval for the service to run, based on Quartz.NET cron expressions.
This file contains the main configuration settings for the service. You can modify the values as needed to match your environment and requirements.
-
AppSettings: Contains the main settings for the service, including:
- ExportPath: The path where the CSV files will be exported. Make sure this path exists and is accessible by the service.
- ExportFileNamePrefix: The prefix for the exported CSV files. The service will append a timestamp to this prefix to create unique file names.
- ExtensionAttributeMappings: An array of mappings between Entra AD extension attributes and existing AD computer object attributes. Each mapping includes:
- extensionAttribute: The name of the extension attribute in Entra AD (e.g.,
extensionAttribute1
,extensionAttribute2
, etc.). - computerAttribute: The name of the existing AD computer object attribute to use as the source for the extension attribute value (e.g.,
distinguishedName
,company
, etc.). - regex: A regular expression pattern to extract a specific value from the existing AD computer object attribute. This is optional and can be left empty if not needed.
- extensionAttribute: The name of the extension attribute in Entra AD (e.g.,
-
EntraADHelperSettings: Contains the settings for the Entra AD helper, including:
- TokenEndpoint: The endpoint for obtaining an access token for Entra AD.
- TokenExpirationBuffer: The buffer time in minutes before the token expires.
- ClientId: The client ID of the Entra AD App Registration.
- ClientSecret: The client secret of the Entra AD App Registration. Leave this empty if using a certificate.
- TenantId: The tenant ID of your Entra AD.
- UseClientSecret: Set to
true
if using a client secret,false
if using a certificate. - CertificateThumbprint: The thumbprint of the certificate used for authentication. Leave this empty if using a client secret.
- AttributesToLoad: An array of attributes to load from Entra AD. Modify this list based on your requirements.
- PageSize: The number of records to retrieve per page when querying Entra AD.
- ClientTimeout: The timeout value for the Entra AD API requests.
- ADHelperSettings: Contains the settings for the AD helper, including:
- RootOrganizationaUnitDN: The distinguished name of the root organizational unit in your AD.
- AttributesToLoad: An array of attributes to load from AD. Modify this list based on your requirements.
- PageSize: The number of records to retrieve per page when querying AD.
- ClientTimeout: The timeout value for the AD API requests.
- ExcludedOUs: An array of organizational units to exclude from processing. Modify this list based on your requirements.
For complete configuration, you can use the following example as a reference:
{
"AppSettings": {
"ExportPath": "C:\\Windows\\Temp\\RGP\\ExtensionAttributes\\Export",
"ExportFileNamePrefix": "RGP.DevicesProcessed",
"ExtensionAttributeMappings": [
{
"extensionAttribute": "extensionAttribute1",
"computerAttribute": "distinguishedName",
"regex": "(?<=OU=)(?<departmentOUName>[^,]+)(?=,OU=(?i:Locations))"
},
{
"extensionAttribute": "extensionAttribute2",
"computerAttribute": "company",
"regex": ""
},
{
"extensionAttribute": "extensionAttribute3",
"computerAttribute": "location",
"regex": ""
},
{
"extensionAttribute": "extensionAttribute4",
"computerAttribute": "department",
"regex": ""
}
]
},
"EntraADHelperSettings": {
"TokenEndpoint": "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token",
"TokenExpirationBuffer": 15,
"ClientId": "d0cb9f7a-742b-47c0-3212-1f9bcc8322c9",
"ClientSecret": "",
"TenantId": "d6dbad84-5922-4700-1234-c7068c37c884",
"UseClientSecret": false,
"CertificateThumbprint": "95fc8568eb1c4adc19f339fc75ae52a90bf4efdf",
"AttributesToLoad": [
"id",
"deviceId",
"accountEnabled",
"approximateLastSignInDateTime",
"displayName",
"trustType",
"location",
"department"
],
"PageSize": 1000,
"ClientTimeout": 60000
},
"ADHelperSettings": {
"RootOrganizationaUnitDN": "OU=Locations,OU=Computers,OU=LAB,DC=msintune,DC=lab",
"AttributesToLoad": [
"cn",
"distinguishedName",
"operatingSystem",
"operatingSystemVersion"
],
"PageSize": 1000,
"ClientTimeout": 30000,
"ExcludedOUs": [
"OU=CESENA,OU=Locations,OU=Computers,OU=LAB,DC=msintune,DC=lab",
"OU=FORLI,OU=Locations,OU=Computers,OU=LAB,DC=msintune,DC=lab"
]
}
}
This file contains the logging configuration settings for the service. You can modify the values as needed to match your environment and requirements. The logging configuration is based on Serilog, a popular logging library for .NET applications. The configuration includes settings for the logging level, output folder path, and file name prefix.
-
MinimumLevel: The minimum logging level for the service. You can set this to
Information
,Warning
,Error
, etc., based on your needs. -
WriteTo: The output settings for the logs. In this case, it is configured to write logs to a file.
-
File: The file settings for the log output. You can modify the following properties:
- Path: The path where the log files will be saved. Make sure this path exists and is accessible by the service.
- FileNamePrefix: The prefix for the log file names. The service will append a timestamp to this prefix to create unique file names.
- RollingInterval: The interval for rolling over the log files. You can set this to
Day
,Hour
, etc., based on your needs. - RetainedFileCountLimit: The maximum number of log files to retain. Older files will be deleted when this limit is reached.
For convenience we recommend not to change the configuration except for log file path and eventually the FileNamePrefix but leave remainder configuration as is. In addition set the
rollingInterval
toDay
and theretainedFileCountLimit
to 5, so that you can keep a history of the last 5 days of logs. For complete configuration, you can use the following example as a reference:{ "Serilog": { "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], "MinimumLevel": { "Default": "Debug", "Override": { "Microsoft": "Warning", "System": "Warning", "Azure.Identity": "Information", "Quartz": "Debug", "ADHelper": "Information", "EntraADHelper": "Information" } }, "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], "WriteTo": [ { "Name": "Console", "Args": { "theme": "Serilog.Sinks.SystemConsole.Themes.SystemConsoleTheme::Literate, Serilog.Sinks.Console", "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] \t [{SourceContext}] {Message:lj} {NewLine}{Exception}" } }, { "Name": "File", "Args": { "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} \t [{Level}] \t [{SourceContext}] \t {Properties} {Message}{NewLine}{Exception}", "path": "C:\\Temp\\Automation\\RGP.Automation.Worker.log", "encoding": "System.Text.UTF8Encoding", // utf-8, utf-16, utf-32" "rollingInterval": "Day", "rollOnFileSizeLimit": true, "retainedFileCountLimit": 5, "fileSizeLimitBytes": 10485760, "flushToDiskInterval": 1 } } ] } }
This file contains the scheduling configuration settings for the service. You can modify the values as needed to match your environment and requirements. The scheduling configuration is based on Quartz.NET, a powerful and flexible scheduling library for .NET applications. The configuration includes settings for the desired interval for the service to run, based on Quartz.NET cron expressions.
-
CronExpression: The cron expression that defines the schedule for the service. You can modify this expression to set the desired interval for the service to run. For example:
0 0/5 * * * ?
- Every 5 minutes0 0 12 * * ?
- Every day at noon0 0 8-18 ? * MON-FRI
- Every hour from 8 AM to 6 PM on weekdays For complete configuration, you can use the following example as a reference:
{ "Quartz": { "CronExpression": "0 0/5 * * * ?" } }
For a complete list of cron expressions and their meanings, you can refer to:
- Quartz.NET Cron Trigger documentation
- CronMaker website
- Cron Expression Generator & Explainer - Quartz
For reference, the complete configuration for the Quartz.NET scheduler can be found in the
schedule.json
file. This includes settings for the Quartz scheduler instance, thread pool, job store, and job details.{ "Quartz": { "QuartzScheduler": { "quartz.scheduler.instanceName": "RGP.ExtensionAttributes.Automation.Worker", "quartz.scheduler.instanceId": "AUTO", "quartz.threadPool.type": "Quartz.Simpl.SimpleThreadPool, Quartz", "quartz.threadPool.threadCount": "10", "quartz.threadPool.threadPriority": "Normal", "quartz.jobStore.misfireThreshold": "60000", "quartz.jobStore.type": "Quartz.Simpl.RAMJobStore, Quartz", "quartz.jobStore.clustered": "false" }, "QuartzJobs": [ { "JobName": "SetComputerExtensionAttributeJob", "JobDescription": "Set computer ExtensionAttribute to the name of parent OU", "JobGroup": "SetComputerExtensionAttributeGroup", "JobType": "RGP.Automation.Worker.Jobs.SetComputerExtensionAttributeJob, RGP.Automation.Worker", "TriggerName": "SetComputerExtensionAttributeTrigger", "TriggerGroup": "SetComputerExtensionAttributeTriggerGroup", "CronExpression": "* 0/5 * ? * * *" } ] } }
To install the Extension Attributes Automation Worker Service, follow these steps:
-
Ensure you have the required prerequisites installed on your machine, including .NET Core 9.0 or later and the Entra AD App Registration.
-
You can download either the whole project from GitHub if you want to modify the code or just the binary files if you want to run the service as is.
-
if you prefer to download binary files follow the instructions in the Download the Binary Files section.
-
If you want to modify the code, follow the instructions in the Building the Project section.
Binary files can be downloaded from releases section of the GitHub repository. You can download the latest release from the following link:
-
Clone the repository:
git clone https://github.com/robgrame/ExtensionAttributes.Automation.git
-
Download the project from GitHub.
-
Uncompress the downloaded file into a folder.
-
Copy the contents of the folder into a desired location on your machine.
-
Open a terminal and navigate to the project directory.
-
Build the project:
dotnet build .\ExtensionAttributes.Automation.sln
-
Upon successful build, navigate to the
bin\Debug\net9.0
directory. -
You should see a bunch of files including the following files:
ExtensionAttributes.WorkerSvc.exe
appsettings.json
logging.json
schedule.json
-
modify the configuration files as needed to match your environment and requirements as described in the Usage section.
-
Copy the content of the
\bin
folder to the desired location where you want to run the service.
To run the solution as a console application, follow these steps:
-
Open a terminal.
-
Navigate to the directory where the binary files are located.
-
Run the following command to start the service:
.\ExtensionAttributes.WorkerSvc.exe -c
-
The application will start running in the console, and you will see log messages indicating its running activity.
-
To stop the application, press
Ctrl + C
in the console window. -
The application will stop running, and you will see log messages indicating its stopping activity.
-
To run the application in the background, you should use the
-s
option as described in the Running as a Windows Service section.
-
To run the solution as a Windows service, follow these steps:
- Open a terminal with administrative privileges.
- Navigate to the directory where the binary files are located
- Change current direcory to
\Setup
:cd .\Setup
- Within
\Setup
folder edit theInstall.cmd
file to set the desired service name and display name. You can also modify the service description and other settings as needed, such as the installation destination and service principal.@echo off set INSTALL_DESTINATION=%programfiles%\RGP\ExtensionAttributes.Worker set SERVICE_NAME=ExtensionAttributesWorkerSvc set SERVICE_DISPLAY_NAME=Extension Attributes WorkerSvc SET SERVICE_DESCRIPTION=Set Entra AD Device extensionAttributes based on AD Computer attributes set PRINCIPAL=LocalSystem set EXE_NAME=ExtensionAttributes.WorkerSvc.exe -s echo. echo 0. Installing service... sc.exe create %SERVICE_NAME% binpath= "%INSTALL_DESTINATION%\%EXE_NAME%" obj= %PRINCIPAL% DisplayName= "%SERVICE_DISPLAY_NAME%" start= auto sc.exe description %SERVICE_NAME% "%SERVICE_DESCRIPTION%" if ERRORLEVEL 1 goto error sc.exe failure %SERVICE_NAME% reset=0 actions=restart/60000/restart/60000/run/1000 net start %SERVICE_NAME% echo. echo Installation completed and service started. exit 0 :error echo Unable to install service. Error code: %ERRORLEVEL%. Make sure to run this script as ADMINISTRATOR. 1>&2 echo. exit 1 ```
- When successfully modified
Install.cmd
batch file run the following command to install the service:.\Install.cmd
Contributions are welcome! Please follow these steps to contribute:
- Fork the repository.
- Create a new branch:
git checkout -b feature-branch
- Make your changes and commit them:
git commit -m "Description of changes"
- Push to the branch:
git push origin feature-branch
- Create a pull request.
This project is licensed under the GPL 3.0. See the GPL license details file for more details.
For any questions or feedback, you can reach me at roberto@gramellini.net
- Version 1.0.0: Initial release of the Extension Attributes Automation Worker Service.
- Version 1.1.0: Added support for running as a Windows service and improved logging capabilities.
- Version 1.1.7: Fixed issues with Entra AD token expiration and improved error handling.
- The service may not handle all edge cases when processing extension attributes. Please report any issues you encounter.
- Add support for additional extension attributes and custom mappings.
- Implement a user interface for easier configuration and management of the service.
- Add support for other platforms (e.g., Linux) to run the service.
- Implement a notification system to alert users of any issues or errors encountered by the service.
- Add support for more advanced scheduling options, such as event-based triggers or custom intervals.
- Implement a backup and restore feature for extension attributes.
- Add support for monitoring and reporting on the status of extension attributes.
- Implement a web-based dashboard for real-time monitoring and management of extension attributes.
- Add support for integration with other automation frameworks or tools.
- Implement a plugin system to allow for custom extensions and functionality.
- Add support for multi-tenancy to allow the service to manage extension attributes across multiple Entra AD tenants.
- Implement a REST API for programmatic access to the service and its functionality.
- Add support for additional authentication methods, such as OAuth2 or OpenID Connect.
- Implement a more robust error handling and retry mechanism for API calls.
- Add support for logging to external systems, such as Azure Monitor or Splunk.
- Implement a configuration management system to allow for dynamic updates to the service configuration without restarting the service.
- Add support for localization and internationalization to allow the service to be used in different languages and regions.
- Implement a testing framework to ensure the service is thoroughly tested and validated before deployment.
- Microsoft Graph API documentation
- Quartz.NET documentation
- Serilog documentation
- Microsoft Entra AD documentation
- Microsoft Entra AD Connect documentation
- Microsoft Entra AD App Registration documentation
- Microsoft Entra AD extension attributes documentation
- Microsoft Entra AD Graph API documentation
- Microsoft Entra AD PowerShell documentation
- Microsoft Entra AD Graph API Explorer
- Microsoft Entra AD Graph API SDK for .NET
If you encounter any issues or have questions about the service, please open an issue on the GitHub repository. We will do our best to address your concerns and provide assistance.
-
Q: What is the purpose of this service?
-
A: The Extension Attributes Automation Worker Service automates the management of computer extension attributes in Entra AD, reducing manual effort and potential errors.
-
Q: How does the service work?
-
A: The service retrieves existing AD computer object attributes and sets the corresponding extension attributes in Entra AD based on the configured mappings.
-
Q: Can I run the service on any machine?
-
A: The service is designed to run on Windows machines, but it can also be run on any machine that supports .NET Core 9.0.
-
Q: How do I configure the service?
-
A: You can configure the service using the
appsettings.json
,logging.json
, andschedule.json
files. Modify the values as needed to match your environment and requirements. -
Q: How do I run the service?
-
A: You can run the service as a console application or as a Windows service. Follow the instructions in the Usage section for more details.
-
Q: How do I stop the service?
-
A: If running as a console application, press
Ctrl + C
in the console window. If running as a Windows service, you can stop it using the Services management console or by running the commandnet stop ExtensionAttributesWorkerSvc
in a terminal with administrative privileges. -
Q: How do I check the logs?
-
A: The logs are saved in the specified output folder path in the
logging.json
file. You can open the log files using any text editor to view the logs. -
Q: How do I contribute to the project?
-
A: Contributions are welcome! Please follow the instructions in the Contributing section to submit your changes.
-
Q: How do I report an issue?
-
A: If you encounter any issues or have questions about the service, please open an issue on the GitHub repository. We will do our best to address your concerns and provide assistance.
-
Q: How do I get support?
-
A: If you need support, please open an issue on the GitHub repository or contact me at roberto@gramellini.net
-
-
We welcome your feedback! If you have any suggestions, comments, or questions about the service, please feel free to reach out to us. Your feedback is valuable and helps us improve the service for everyone.
Thank you for using the Extension Attributes Automation Worker Service! We hope it helps you automate the management of computer extension attributes in Entra AD and simplifies your workflow.