Slack: Disable Entra ID User using a slash command.

Efficiently managing user access is crucial for maintaining IT security and compliance. Automating the process of disabling Entra ID users through a Slack slash command offers several key advantages:

  • Speed and Efficiency: A single Slack command instantly triggers an Azure Runbook, eliminating manual steps and saving time.
  • Centralized Workflow: IT teams already use Slack for communication. Integrating user management into this familiar tool reduces context switching and streamlines operations.
  • Secure and Controlled Access: Restrictions ensure that only authorized personnel can use the command, minimizing the risk of misuse.
  • Audit and Logging: Azure Runbooks and Slack logs provide a clear audit trail of all actions taken, enhancing accountability and compliance.

Automating user disabling with Slack can significantly improve your IT team’s efficiency and security posture.

In this post we’ll go over the steps involved with setting up the Azure runbook to setting up your custom Slack application and slash command.  Let’s set this up! 


 

Prerequisites

Before we start, ensure you have the following:

  • Azure Subscription: With permissions to create and run Azure Automation accounts and Runbooks.
  • Microsoft Entra ID P1 or higher user license.
  • Slack Workspace: With admin access to create a custom app.
  • Microsoft Graph PowerShell Module: Installed in your Azure Automation Runbook. We’ll go over what modules are needed for this specific function.
  • Entra ID Admin Privileges: To review user account information.

 

Create an Azure Automation Account

You need to have an Azure Automation account setup with the Azure Portal.   Toggle the arrow below for step-by step instructions on setting up your account. 

  • Log in to the Azure Portal.
  • Navigate to Automation Accounts:
    • Search for “Automation Accounts” in the search bar.
    • Click + Create to set up a new Automation Account.
  • Provide the required details:
    • Subscription: Select your Azure subscription.
    • Resource Group: Choose or create a resource group.
    • Name: Enter a name for your Automation Account.
    • Region: Select your preferred region.
    • Click Next

  • Under Advanced, choose System Assigned under Managed Identities.  We will go over why this may be your best option later.
  • Networking tab, ensure you have public access enabled for your connectivity configuration.
  • Setup your Tags (Highly recommended for housekeeping).
  • Click Review + Create and then Create.

After your Automation Account has been created, Go to the resource.

 

Create the Azure Runbook

Let’s set up a new runbook.  Under the Process Automation blade, click the arrow to expand and choose Runbooks.

  • Next, click + Create to create a new runbook.

Provide the needed details

  • Click Create new.
  • Enter a name for your runbook.
  • Select PowerShell as the runbook type.
  • Choose ‘Select from existing’ for the runtime environment and select PowerShell-7.2 (or the latest release). This will be necessary to use the MS Graph API.
  • Add a description for your runbook.
  • Optionally, add tags to categorize your runbook.
  • Click Review + Create.
  • Once validation is complete, click Create.
  • Allow 2-3 minutes for the runbook to be created.

 

 

The runbook will need specific PowerShell modules that aren’t installed by default.

To add them:

  • Click the + Add a module button at the top.

 

 

  • Click ‘Browse from the gallery.’
  • Search for ‘Microsoft.Graph.Authentication’ in the module gallery.
  • Select the latest version of the module.
  • Click
  • Choose the latest runtime version for your module.
  • Click Import.

 

 

It might take around 2-4 minutes to import the Microsoft.Graph.Authentication module. You can check its progress by searching for it in the module gallery. Once it says Available, you’re ready to use it.  We need to add one more module, you can add this while the others are provisioning. 

Add these other modules: 

  • Microsoft.Graph.Users

Verify the status on the modules, once they say Available you are good to go.

 

 

To enable your runbook to read users login and password reset time stamps, we’ll need to grant it permission to the Azure subscription:

  • Go to Account Settings, choose Identity.
  • You’ll see a system-assigned managed identity is already enabled.
  • Click Add role assignment.
  • Set the scope to your Azure subscription.
  • Assign the Contributor role (or create a custom role with necessary permissions which is recommended).

 


 

 

Setup permission for your Object ID

We have one last permission step: Give our new managed identity permissions to create read users and be able to edit them, in this case, disable them.  Ensure you have the Object ID from your managed Identity from the steps above.

  • In a new tab, Go to the Azure portal.
  • Choose the Microsoft Entra ID blade
  • Expand Manage, choose Enterprise applications.
  • On the search bar, search for the Object ID you have copied.
  • An application should show up; click on the name.
  • Expand the Security area, choose Permissions, and you’ll notice no Permissions are set for your application.

To successfully disable a user, we’ll need to provide this application with a single Microsoft Graph permissions:

  • User.ReadWrite.All

Currently, PowerShell is the only method available to add these permissions.

The easiest way to do this is to open the Cloud Shell at the top of your Azure portal.

Run the following PowerShell Script. Make sure you replace **SUPERCOOLOBJECTID** on line 6 with the Object ID of the application you just searched for.

				
					Install-Module Microsoft.Graph -Scope CurrentUser


Connect-MgGraph -Scopes Application.Read.All, AppRoleAssignment.ReadWrite.All, RoleManagement.ReadWrite.Directory

$managedIdentityId = "SUPERCOOLOBJECTID"
$roleNames = @("User.ReadWrite.All")

$msgraph = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'"

foreach ($roleName in $roleNames) {
    $role = $Msgraph.AppRoles | Where-Object {$_.Value -eq $roleName}

    if ($role) {
        New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $managedIdentityId -PrincipalId $managedIdentityId -ResourceId $msgraph.Id -AppRoleId $role.Id
    }
    else {
        Write-Warning "Role $roleName not found in Microsoft Graph service principal roles."
    }
}

Disconnect-MgGraph
				
			

The Cloud console will run. Choose A for Yes to All to install all the required Graph modules to run your cmd.  This will run for a few minutes.

It will then prompt you to Sign into a web browser and enter a code.   Simply copy the URL (or you can click the URL) and type the code into your browser.

  • Enter the code to allow access. Click Next.

  • The next screen will ask you to sign into your account to verify.
  • After you log in, you will need to consent on behalf of your company to give permissions to the Graph Command Line Tools. If you are okay with this, click Accept.

You can now close the tab where you granted admin consent. Return to the tab where your Azure Cloud Shell is running. The permission grant process should be complete, and your cloud shell should be disconnected from Microsoft Graph.

To verify that the permissions have been added successfully:

  • Navigate back to the Permissions tab of your enterprise application.
  • You should now see the new application permissions listed, with admin consent already granted. 


Time to Create Encrypted Slack Token Variable

Before we add our PowerShell scrip to our Azure runbook, we will create an encrypted variable placeholder for our Slack OAuth token, or bot token.  We’ll get this from Slack, but while in Azure, let’s go ahead and set up the variable.

Find your Automation account that hosts the runbook you just created.  Under Shared Resources, click Variables.

  • Click + Add a variable
  • Choose the name.  We are choosing slack-bot-token. If you prefer something different, update the PowerShell script I’ve provided with the variable name. 
  • Type, choose String.
  • For the Value, put anything; we will return and update this. 
  • For Encrypted, choose Yes. 
  • Click Create

 

 


Setup the Azure Runbook PowerShell Script

Time to add the PowerShell script. Click the runbook and make sure you’re in the runbooks Overview view.

To edit your runbook:

  • Navigate to our runbook in the Azure portal.
  • Click ‘+ Edit’ and choose Edit in the portal.
  • Expand the Runbooks section on the left and select the correct runbook.
  • We’re ready to add our PowerShell script.

 

				
					param (
    [Parameter(Mandatory=$false)]
    [object] $WebhookData
)

# Import required modules
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users

# Function to get Slack group members
function Get-SlackGroupMembers {
    param (
        [string]$groupHandle,
        [string]$botToken
    )
    # Fetch usergroups using Slack API
    $userGroupList = Invoke-RestMethod -Uri "https://slack.com/api/usergroups.list" -Method Get -Headers @{
        "Authorization" = "Bearer $botToken"
    }

    if (-not $userGroupList.ok) {
        Write-Error "Full Slack response: $($userGroupList | ConvertTo-Json -Depth 10)"
        throw "Failed to fetch user groups: $($userGroupList.error)"
    }

    # Find the group ID for the given group handle
    $groupName = $groupHandle.TrimStart('@')
    $group = $userGroupList.usergroups | Where-Object { $_.handle -eq $groupName }
    if (-not $group) {
        throw "Group $groupHandle not found"
    }

    # Fetch members of the group
    $membersResponse = Invoke-RestMethod -Uri "https://slack.com/api/usergroups.users.list?usergroup=$($group.id)" -Method Get -Headers @{
        "Authorization" = "Bearer $botToken"
    }

    if (-not $membersResponse.ok) {
        Write-Error "Full Slack response: $($membersResponse | ConvertTo-Json -Depth 10)"
        throw "Failed to fetch group members: $($membersResponse.error)"
    }

    return $membersResponse.users
}

try {
    # Initialize WebhookData parsing
    $WebhookBody = [System.Web.HttpUtility]::UrlDecode($WebhookData.RequestBody)
    
    # Convert the body to a hashtable
    $BodyParts = $WebhookBody -split '&'
    $WebhookParams = @{}
    foreach ($Part in $BodyParts) {
        $KeyValue = $Part -split '='
        if ($KeyValue.Count -eq 2) {
            $WebhookParams[$KeyValue[0]] = $KeyValue[1]
        }
    }

    # Extract the email address, response_url, and user_id
    $emailAddress = $WebhookParams['text'].Trim()
    $responseUrl = $WebhookParams['response_url']
    $userId = $WebhookParams['user_id']

    # Validate user is part of @it-team
    $slackBotToken = Get-AutomationVariable -Name "slack-bot-token" # Replace with your Slack bot token variable
    $botToken = $slackBotToken
    $groupHandle = "@it-team"

    $itTeamMembers = Get-SlackGroupMembers -groupHandle $groupHandle -botToken $botToken
    if (-not ($itTeamMembers -contains $userId)) {
        throw "Unauthorized user. You must be a member of $groupHandle to execute this command."
    }

    if ([string]::IsNullOrEmpty($emailAddress)) {
        throw "Email address not provided in the command"
    }

    Write-Output "Processing disable request for email: $emailAddress by user: $userId"

    # List of protected users
    $protectedUsers = @(
        "ceo@daveherrell.com",
        "cfo@daveherrell.com",
        "dave@daveherrell.com"
    )

    # Check if the entered email is in the protected list
    if ($protectedUsers -contains $emailAddress.ToLower()) {
        $responseText = "User $emailAddress cannot be disabled via Slack. Protection enabled."
        Write-Output $responseText
        # Send response back to Slack and exit the script
        $responsePayload = @{
            response_type = "in_channel"
            text = $responseText
        } | ConvertTo-Json -Depth 10 -Compress

        Invoke-RestMethod -Uri $responseUrl -Method Post -ContentType "application/json" -Body $responsePayload
        Write-Output "Response sent to Slack."
        return
    }

    # Connect to Microsoft Graph using managed identity
    Connect-MgGraph -Identity

    # Query and disable Microsoft Graph user
    try {
        $user = Get-MgUser -Filter "userPrincipalName eq '$emailAddress'" -Select "id"
        if ($null -eq $user) {
            $responseText = "User $emailAddress not found in Entra ID."
        }
        else {
            # Disable the user by setting accountEnabled to false
            Update-MgUser -UserId $user.Id -BodyParameter @{ "accountEnabled" = $false }
            $responseText = "User $emailAddress has been successfully disabled in Entra ID."
        }
    }
    catch {
        throw "Error disabling user: $($_.Exception.Message)"
    }
}
catch {
    $errorMessage = $_.Exception.Message
    Write-Error "Error occurred: $errorMessage"
    $responseText = "Error: $errorMessage"
}
finally {
    # Disconnect from Microsoft Graph
    Disconnect-MgGraph
}

# Send response back to Slack
try {
    $responsePayload = @{
        response_type = "in_channel"
        text = $responseText
    } | ConvertTo-Json -Depth 10 -Compress

    Invoke-RestMethod -Uri $responseUrl -Method Post -ContentType "application/json" -Body $responsePayload
    Write-Output "Response sent to Slack."
}
catch {
    Write-Error "Failed to send response to Slack: $($_.Exception.Message)"
}

				
			
  • Parameter Handling:

    • Accepts the webhook data from Slack, which includes the command arguments (EMAILADDRESS) and metadata like user_id and response_url.
  • Slack Group Validation:

    • Verifies that the user invoking the command is part of the @it-team group in Slack.
    • Uses the Slack API to retrieve group members and validate membership.
  • Protected Users List:

    • Maintains a list of users ([email protected], etc.) who are protected from being disabled via this command.
  • Microsoft Graph Integration:

    • Connects to Entra ID via Connect-MgGraph -Identity.
    • Locates the target user and disables them by setting the accountEnabled attribute to false.
  • Error Handling:

    • Catches and logs detailed errors at multiple stages of execution.
    • Provides user-friendly messages back to Slack if errors occur.
  • Slack Response:

    • Returns success, failure, or error messages to the Slack channel through response_url.

Click Save.  Click PublishIf you dont Publish the runbook it will stay in edit mode, Automation will not be able to work with the runbook.

 

 

Next step is to create a Webhook for the runbook.  Make sure you are in the runbook Overview.  You can tell by your breadcrumbs at the top, the should say something like: Home > Automation Accounts > Slack-Azure-Automation > Runbooks. 

In the left side, expand out the Resources blade, choose Webhooks.

 

 

  • Click the + Add Webhook.  Note: if you dont see this or if it’s greyed out, you havent Published your runbook yet.  The runbook has to be published before you can create a webhook for it
  • Choose the Create new webhook option first. 

 

  • Set the Name of your Webhook. 
  • Make sure Enabled is set to Yes.
  • Set your expiration date/time.  The defaults is set for a year.
  • Copy the Webhook URLMake sure you do this before clicking OK.  This is the only time you will see this again and you need it.  Copy it somewhere secure to later use within your Slack app. 
  • Click Ok.

 

 

This will take you back to the Add Webhook Screen. 

  • Choose Parameters and run settings. 
  • Make sure there is nothing in the value for the WEBHOOKDATA, just click OK. 
  • Click Create. 

 

 

You should now see your Webhook created, expiration date, last triggered and status.


 

 

 

Time to Setup the Slack Application and Slash Command

We need to setup our custom Slack application and slash command that will trigger things.  You must be a Slack administrator or at least have the correct permissions to do this.

 

 

  • Next, Name your App and choose your Workspace that app will be triggered in.

 

 

Next, we’ll setup the slash command.  This is how user will interact with our application within Slack.

  • Choose, Create New Command.
  • Choose the Command that will trigger the app. I’m using /users-disable.
  • For the Request URL, past your Azure runbook webhook that you copied and saved.
  • Create a Short description.  Handy to let users know what this command will be doing.
  • Create a Usage Hint.  We are using [Email Address] this gets appended to the use info to let them know the format you expect.
  • Click Create.

 

 

Since we are setting restrictions as to who can run this slash command, we’ll need to give our Slack application permission to read users names and what Slack groups they are a member of.

  • Click the OAuth & Permissions to the left under Features.
  • Scroll down to Scopes.
  • Click Add an OAuth Scope.
  • Search for the following and add them:
    • users.read
    • usergroups.read
  • These should automatically save to the application. 

 

 

  • Under Settings, Basic Information
  • Scroll down to Display Information and update.
    • Create the App Name 
    • Short Description 
    • App Icon 
    • Background Color
    • Long Description. 
  • Click Save Changes at the bottom

 

 

Last two steps, next we need to publish, or Install this application to our Slack instance. 

  • Under Settings, choose Install App.
  • Click to Install to your Slack environment. 

 

 

This will pop up a validation to Allow the application and the permissions you setup for it.  Review and click Allow

 

 

After you click Allow you will see a newly created Bot OAuth Token.  This token starts with xoxb-XXXX. copy this token, we’ll need to add this to our Automation variable. 


 

Update Automation Variable

  • Go back to the Azure Portal.   
  • Find the Automation account you setup
  • Under the Share Resources click on Variables
  • Click the Variable we created, slack-bot-token in our instance. 
  • Click Edit Value
  • Copy the OAuth token from Slack to the Value field.  
  • Click Save

 

 


 

Let’s Test Our Slack Slash Command!

In any channel you can start the command by entering a slash “/” which will bring up the commands that are available.  You can enter in a few more letters after the slash to narrow it down faster.  In our case we’re looking for “/users-disable”. 

Enter the slash command along with the email of the test user you wish to retrieve info about.

 

 

Click enter to trigger the command.  This will take a minute.  In about 1-2 minutes you will see a verification of the user account getting disabled: 

 

 

If you go back to your Azure runbook, you will see run information and if it was completed successfully, any errors, exceptions and more. 

 

 

When we check out the Entra ID user within the Azure portal we should see the account account has been disabled.

 

 

We placed a restriction in our PowerShell script to make sure only the members of Slack group ‘it-team” can run this.  So a user that tries to run this slash command without being in this particular group will see something like this: 

 

 

We also placed a restriction of who can not be disabled.  We did this as a basic list, you can adjust the PowerShell script to use Azure groups for a more dynamic approach.   If the slash command is ran against one of our restricted users, even if person that triggers it is a member of our it-team Slack group.  They will receive an alert like that and the script will stop. 

 


 

IT teams can significantly streamline their workflows and bolster security by seamlessly integrating Entra ID management with Slack using slash commands. This innovative approach eliminates the need for manual intervention, reducing the potential for human error and saving valuable time.

The underlying PowerShell script, fortified with stringent permissions and restrictions, ensures that only authorized personnel can execute critical user management tasks. This robust security measure mitigates risks and safeguards sensitive information.

By adopting this efficient solution, IT teams can empower themselves to manage user access precisely and quickly. This, in turn, contributes to a more secure and compliant IT environment.

 

I hope you found this helpful!