Manage Admin Accounts with FleetDM

Manage admin accounts effectively using FleetDM by implementing policies and scripts to control user permissions across macOS and Windows devices, ensuring compliance and security within your organization.

7 min read
  1. Lexicon
  2. Managing user and admin accounts in bulk
    1. Demote all users that are not username
      1. macOS Script template
      2. Windows Script template
    2. Create admin user username if not present
      1. macOS Script template
      2. Windows Script template
  3. Allowing privilege escalation through Privileges (macOS) and MakeMeAdmin (Windows)
    1. Privileges
      1. Policy that fails if Privileges is not installed
    2. Make Me Admin
      1. Policy that fails if MakeMeAdmin is not installed
    3. Queries
      1. Policy that fails if a username is not present on the Device
      2. Policy that fails if other user than username are admin on the device
      3. macOS
      4. Windows
      5. Query that gets all admins users of the Device
      6. Windows
      7. MacOs
      8. How to add a custom Software in FleetDM
      9. How to create a Policy in FleetDM
      10. How to upload a Script on FleetDM
      11. How to create an Automation that runs a script automatically based on a Policy result
      12. How to create an Automation that installs a software automatically based on a Policy result
    4. 📚 Tutorials

Lexicon

Query

  • A query is a way to request information about a device in a yes/no manner
  • Queries use SQL syntax to query data on any Device

Full documentation here https://fleetdm.com/guides/queries

Policy

  • Policies are tools that give us the ability to exeute an action based on the result of a Query
  • Policies are evaluated every hour (configurable)

Full documentation here https://fleetdm.com/securing/what-are-fleet-policies

Policy Automation

  • Policy automation is a way to trigger an action (script or software install) if a policy is failing on a Device
  • Fleet checks whether to trigger policy automations once per day by default.
  • Policy Automation requires a Policy to be created

Full documentation here https://fleetdm.com/guides/automations#basic-article

Managing user and admin accounts in bulk

Demote all users that are not username

  • Modify the script below, based on the OS
    • Replace the REPLACE_WITH_USERNAME to the username of the only admin you want to have on the device

    macOS Script template

    #!/bin/sh
    
    # This username will NOT be demoted, all other username will be
    USERNAME="REPLACE_WITH_USERNAME"
    
    demote_user() {
        local username="$1"
        if sudo dseditgroup -o edit -d "$username" -t user admin 2>/dev/null; then
            echo "Removed $username from admin group"
            return 0
        fi
        return 1
    }
    
    admin_users=$(dscl . -read /Groups/admin GroupMembership | cut -d' ' -f2-)
    
    for user in $admin_users; do
        # Skip if user matches USERNAME
        [ "$user" = "$USERNAME" ] && continue
        
        # Skip accounts starting with underscore and system accounts
        if [[ "$user" = _* ]] || ! dscl . -read /Users/"$user" UniqueID &>/dev/null || \
           [[ $(dscl . -read /Users/"$user" UniqueID | awk '{print $2}') -lt 500 ]]; then
            continue
        fi
        
        demote_user "$user"
    done

    Windows Script template

    
    # This username will NOT be demoted, all other users will be
    $USERNAME="REPLACE_WITH_USERNAME"
    
    # Verify the exempt user exists
    if (-not (Get-LocalUser -Name $USERNAME -ErrorAction SilentlyContinue)) {
        Write-Host "The exempt user '$USERNAME' does not exist. Exiting."
        exit 0
    }
    
    # Get the administrators group (works for different Windows localizations)
    $adminGroup = Get-LocalGroup -SID "S-1-5-32-544"
    $adminMembers = Get-LocalGroupMember -Group $adminGroup
    
    foreach ($member in $adminMembers) {
        # Extract just the memberUsername from the member object
        $memberUsername = $member.Name.Split('\')[-1]
    
        # Extract the RID (last part of the SID) and cast to integer
        $rid = [int]($member.SID.Value.Split('-')[-1])
    
        # Debugging Output
        Write-Host "DEBUG: Username=$memberUsername, User=$USERNAME UID=$rid"
    
        # Skip preserved user
        if ($memberUsername -eq $USERNAME) {
            Write-Host "Skipping preserved user: $memberUsername"
            continue
        }
    
        # Skip preserved user or accounts with UID < 1000
        if ($rid -lt 1000) {
            Write-Host "Skipping system account: $memberUsername (UID: $rid)"
            continue
        }
    
        try {
            # Attempt to demote the user
            Remove-LocalGroupMember -Group $adminGroup -Member $member.Name -ErrorAction Stop
            Write-Host "Successfully removed $memberUsername from the administrators group"
        }
        catch {
            Write-Host "ERROR: Failed to remove $memberUsername from the administrators group: $_"
        }
    }
    
    Write-Host "Admin demotion process completed successfully"
    
  • Copy paste the script content on a file in your file system and name it properly with .sh extention, example : macos_create_company_admin.sh
  • Upload the script file on your FleetDM instance
    • If needed, follow this Tutorial to learn how to upload a Script
  • Create a Policy using this Query, that fails if username is not present on the device, use the same username that you used in the script
    • If needed, follow this Tutorial to learn how create a Policy
  • Create an automation “Run Script” for this Policy
    • If needed, follow this Tutorial to learn how to create an Automation for a Policy
  • Done ✅  Policy and automation will run every hour
    • If needed, follow this Tutorial to learn how to upload a Script

Create admin user username if not present

  • Modify the script below, based on the OS
    • Replace the REPLACE_WITH_USERNAME
    • Replace the REPLACE_WITH_PASSWORD with a password strong enough that match the device’s password requirement

    macOS Script template

    #!/bin/sh
    ## Script to create a user on macOS, with SecureToken enabled
    # Configuration, set these variables manually
    Username="REPLACE_WITH_USERNAME"
    Password="REPLACE_WITH_PASSWORD"
    
    
    create_user() {
        local cmd_output
        cmd_output=$(sysadminctl -addUser "$Username" -password "$Password" -admin -fullName "$Username" 2>&1)
    
        if echo "$cmd_output" | grep -q "UID:"; then
            echo "Created user: $Username"
            return 0
        elif echo "$cmd_output" | grep -q "'$Username'"; then
            echo "User $Username already exists"
            return 0
        else
            echo "Error: User creation failed"
            echo "Debug output: $cmd_output"
            return 1
        fi
    }
    
    create_user || exit 1
    
    

    Windows Script template

    
    ## Script to create an admin user on Windows
    # Configuration, set these variables manually
    $Username = "REPLACE_WITH_USERNAME"
    $Password = "REPLACE_WITH_PASSWORD"
    
    [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
    
    function Get-LocalAdministratorsGroup {
        try {
            $adminSID = "S-1-5-32-544"
            $group = Get-LocalGroup | Where-Object { $_.SID -eq $adminSID }
            if (-not $group) {
                throw "Could not find administrators group"
            }
            return $group.Name
        }
        catch {
            throw "Failed to get administrators group: $_"
        }
    }
    
    # Input validation
    if ([string]::IsNullOrWhiteSpace($Username) -or [string]::IsNullOrWhiteSpace($Password)) {
        Write-Host "Error: Username and Password must be set"
        exit 1
    }
    
    try {
        # Check if user exists
        if (Get-LocalUser -Name $Username -ErrorAction SilentlyContinue) {
            Write-Host "Info: User $Username already exists"
            exit 0
        }
    
        Write-Host "Starting creation process for user: $Username"
    
        # Create user
        $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
        $params = @{
            Name = $Username
            Password = $SecurePassword
            FullName = $Username
            Description = "User created via Primo"
            AccountNeverExpires = $true
            PasswordNeverExpires = $true
            ErrorAction = 'Stop'
        }
        
        New-LocalUser @params
        $createdUser = Get-LocalUser -Name $Username -ErrorAction Stop
        Write-Host "User '$Username' created successfully"
    
        # Add to admin group
        $AdminGroup = Get-LocalAdministratorsGroup
        Add-LocalGroupMember -Group $AdminGroup -Member $Username -ErrorAction Stop
        
        $verify = Get-LocalGroupMember -Group $AdminGroup -ErrorAction Stop
        if ($verify.Name -match [regex]::Escape($Username)) {
            Write-Host "Successfully added '$Username' to administrators group ($AdminGroup)"
            exit 0
        } else {
            throw "Failed to verify user addition to administrators group"
        }
    }
    catch {
        Write-Host "Error: $_"
        exit 1
    }
  • Copy paste the script content on a file in your file system and name it properly with .sh or .ps1 extention, example : macos_create_company_admin.sh
  • Upload the script file on your FleetDM instance
    • If needed, follow this Tutorial to learn how to upload a Script
  • Create a Policy using this Query, that fails if username is not present on the device, use the same username that you used in the script
    • If needed, follow this Tutorial to learn how create a Policy from a Query
  • Create an automation “Run Script” for this Policy
    • If needed, follow this Tutorial to learn how to create an Automation for a Policy
  • Done ✅  Policy and automation will run every hour

Allowing privilege escalation through Privileges (macOS) and MakeMeAdmin (Windows)

Privileges

Link to doc: https://github.com/SAP/macOS-enterprise-privileges

Package:

Privileges_2.0.0.pkg 1.6 MB

Policy that fails if Privileges is not installed

SELECT 1 FROM apps where bundle_identifier like "corp.sap.privileges";

Make Me Admin

Link to doc: https://github.com/pseymour/MakeMeAdmin

Package:

MakeMeAdmin_2.3.0_x64_%281%29.msi 761.9 kB

Policy that fails if MakeMeAdmin is not installed

SELECT 1 FROM programs WHERE name LIKE 'Make Me Admin' AND publisher LIKE 'Sinclair Community College';

Queries

ℹ️
Important: Always review contents of policies & script before applying to your instance

Policy that fails if a username is not present on the Device

SELECT username from users where username like "username_goes_here"

Policy that fails if other user than username are admin on the device

  • Replace USERNAME_GOES_HERE in the query

macOS

SELECT 1
WHERE NOT EXISTS (
    SELECT 1 
    FROM users u 
    JOIN user_groups ug ON u.uid = ug.uid 
    WHERE ug.gid = 80 
    AND u.uid >= 500
    AND u.username NOT IN ('USERNAME_GOES_HERE')
   );

Windows

SELECT 1
WHERE NOT EXISTS (
    SELECT 1 
    FROM users u 
    JOIN user_groups ug ON u.uid = ug.uid 
    WHERE ug.gid = 545 
    AND u.username NOT IN ('USERNAME_GOES_HERE')
);

Query that gets all admins users of the Device

Windows

- group_sid (gid) 545 is the admin group Windows

SELECT u.username 
FROM users u
JOIN user_groups ug ON u.uid = ug.uid
WHERE ug.gid = 545;

MacOs

- group_id (gid) 80 is the admin group on MacOs

SELECT u.username 
FROM users u
JOIN user_groups ug ON u.uid = ug.uid
WHERE ug.gid = 80;

📚 Tutorials

How to add a custom Software in FleetDM

How to create a Policy in FleetDM

⚠️
A Query will be needed to create a Policy, refer to the Query library or create your own using Osquery documentation.

How to upload a Script on FleetDM

  • Go into Controls tab
  • Select the Script sub tab
  • Select the “No Team” team
  • Use Upload button to upload a file

How to create an Automation that runs a script automatically based on a Policy result

⚠️
A Policy is needed to be created first, follow this Tutorial to learn how to create a Policy
⚠️
Script needs to be uploaded first, follow this Tutorial to learn how to upload a script

How to create an Automation that installs a software automatically based on a Policy result

⚠️
A Policy is needed to be created first, follow this Tutorial to learn how to create a Policy
⚠️
Software needs to be uploaded first, follow this Tutorial to learn how to uploaded a software

Did this answer your question?