Technical Tip: How to create an enrollment bundle or code for each imported LDAP user
| Description | This article describes how to create an enrollment bundle or code for each imported LDAP user. |
| Scope | FortiDLP. |
| Solution | The Reveal Agent can automatically associate events from from machines logged in with domain user accounts to their corresponding user passport imported from LDAP assuming the Security Identifiers (SIDs) have been correctly imported.
For users who do not make use of Windows domains in their environment, Fortinet recommends creating an enrollment bundle or code for each user and enrolling each personal machine with this unique token. This way any events from that machine will be automatically associated with the corresponding user passport.
Fortinet has written scripts that are able to interact with the Reveal platform APIs to generate an enrollment code for each imported user and output it to the command line as a CSV file. These codes can then be distributed to the correct users' machines either automatically or manually:
PowerShell:
<# .SYNOPSIS Creates or updates enrollment codes for each Reveal user in the existing DB
.DESCRIPTION Creates or updates enrollment codes for each Reveal user in the existing DB
.PARAMETER UpdateExisting Resets remaining users and expiry time for existing tokens
.EXAMPLE PS C:\> .\perUSerEnrollmentCodes.ps1 #>
<# perUserEnrollmentCodes (c) 2022-12-06 Next DLP #>
param ( [switch]$UpdateExising = $false )
$serverAddress = "eu.reveal.nextdlp.com" $token = $env:EU_TOKEN $type = 'application/json' $Headers=@{ 'Authorization' = "Bearer $token" }
$body = @{ filter = @("name=*") include_labels = $True }
$url = "https://$serverAddress/api/v2/users/search" $result = (Invoke-RestMethod -URI $url -Headers $Headers -Method Post -Body (ConvertTo-Json $body) -ContentType $type) $users = $result.users while ($result.next_page_cursor -ne "") { $c = $result.next_page_cursor Write-Host "New page: $c" $url = "https://$serverAddress/api/v2/users/search?cursor=$c" $result = (Invoke-RestMethod -URI $url -Headers $Headers -Method Post -Body (ConvertTo-Json $body) -ContentType $type) $users += $result.users } $count = ($users | measure).Count write-host "Total users = $count"
$url = "https://$serverAddress/api/v1/enrollment/tokens" $result = (Invoke-RestMethod -URI $url -Headers $Headers -Method Get) $tokens = $result.tokens #$tokens
Write-Output "user,enrollment_code" $datenow = (Get-Date).ToString("yyyy-MM-dd") $7daysfromnow = (Get-Date).AddDays(7).ToString("yyyy-MM-ddT12:00:00.000Z") $users | foreach { $user = $_ $userid = $user.uuid $username = $user.name $validtoken = $false $existingtoken = ($tokens -match $_.uuid) if ($existingtoken){ $existingtoken | foreach { $revoked = $_.revocation_info $tokenid = $_.id $code = $_.code $exp = $_.expiry $uses = $_.remaining_uses if ($code -and -not $revoked) { $validtoken = $true Write-Host "User $userid ($username) has token $tokenid already, expiry $exp, uses $uses" write-Output "$username, $code" if($UpdateExising){ $updateUrl = "https://$serverAddress/api/v1/enrollment/tokens/$tokenid" $updateBody = @{ description = "$username - Updated by script $datenow" expiry = $7daysfromnow remaining_uses = 1 } $result = (Invoke-RestMethod -URI $updateUrl -Headers $Headers -Method Put -Body (ConvertTo-Json $updateBody) -ContentType $type) } } } } if (-not $validtoken) { Write-Host "User $userid ($username) has no valid token, creating" $newTokenUrl = "https://$serverAddress/api/v1/enrollment/tokens" $newTokenBody = @{ description = "$username - Created by script $datenow" expiry = $7daysfromnow juid = $userid remaining_uses = 1 } $result = (Invoke-RestMethod -URI $newTokenUrl -Headers $Headers -Method Post -Body (ConvertTo-Json $newTokenBody) -ContentType $type) $newcode = $result.code write-Output "$username, $newcode" } }
Python 3:
# COPYRIGHT NEXT DLP 2022 # Python script for making enrollment codes for users without enrollment codes. # Optionally for users with existing enrollment codes, the expiry date can be set # to 7 days from now and the remaining uses set to 1. # Outputs user_enrollment.csv with user names and their corresponding enrollment tokens.
import json import os import requests import csv from datetime import datetime from datetime import timedelta
# Set access_token to the API token from your instance # This is currently set to look for the API token in an # environment variable with the name "TOKEN_ENVIRONMENT_VARIABLE" # For security reasons, Jazz recommend that you do not store the API token in the script directly access_token = os.environ['API_ACCESS_TOKEN']
# Set to the https address of your jazz front end server_address = "https://tenantname.reveal.nextdlp.com"
# Set to "True" for setting the expiry date to 7 days from now and setting remaining # uses to 1, for users who already have enrollment tokens. update_existing = True
# Time operations datenow = datetime.now() sevendayslater = datetime.now() + timedelta(days=7) sevendayslater = sevendayslater.strftime("%Y-%m-%dT%H:%M:%S.000Z")
# API configuration for obtaining a list of users type = "application/json" headers = {'authorization':'bearer '+ access_token}
body = { "filter": [ "name=*" ], "include_labels": True}
url1 = "https://" + server_address + "/api/v2/users/search"
result1 = requests.get(url1,params=body, headers=headers) content = json.loads(result1.content) cursor = content['next_page_cursor'] users = content['users']
while cursor != "": url2 = "https://"+server_address+"/api/v2/users/search?cursor=" + cursor result2 = requests.get(url2,params=body, headers=headers) content2 = json.loads(result2.content) cursor = content2['next_page_cursor'] users += content2['users']
users_count = len(users) + 1
# API configuration for obtaining enrollment information url3 = "https://" + server_address + "/api/v1/enrollment/tokens" result3 = requests.get(url3, headers=headers) content3 = json.loads(result3.content) tokens = content3['tokens']
# Initalising list to store user_enrollment pairs user_enrollment = []
for user in users: valid_token = False for token in tokens:
# If a user's uuid matches a juid in enrollment info if user['uuid'] in token['juid']:
# If the token has not been revoked and an enrollment code exists if token['revocation_info'] == None and token['code'] != "": valid_token = True print("User " + user['uuid'] + " (" + user['name'] + ") has token " + str(token['id']) + " already, expiry " + token['expiry'] + ", uses " +str(token['remaining_uses'])) break
if update_existing == True and valid_token == True:
# API configuration for setting expiry date to 7 days from now and # remaining uses = 1 update_url = "https://" + server_address + "/api/v1/enrollment/tokens/" + token['id'] update_body = { "description" : user['name']+ ' - Updated by script ' + str(datenow), "expiry" : sevendayslater, "remaining_uses" : 1 } update_result = requests.put(update_url,json = update_body, headers=headers) print("The expiry date of this token has been updated to 7 days from now.")
# Append list user_enrollment.append([user['name'],token['code']])
elif valid_token == False:
print("User " + user['uuid'] + " (" + user['name'] + ") has no valid token, creating")
# API configuration for making new enrollment token, and setting # expiry date to 7 days from now and remaining uses = 1 new_token_url = "https://" + server_address + "/api/v1/enrollment/tokens" new_token_body = { "description" : user['name'] + "- Created by script at " + str(datenow), "expiry" : sevendayslater, "juid" : user['uuid'], "remaining_uses" : 1 } new_token_result = requests.post(new_token_url,json=new_token_body, headers=headers) new_token_content = json.loads(new_token_result.content)
print("A new code " + new_token_content['code'] + " has been made for " + user['name'] + ".")
# Append list user_enrollment.append([user['name'],token['code']])
# List to pass to .csv file columns = ['User','Enrollment code']
# Writing results to .csv file with open('user_enrollment.csv', 'w',newline='') as f: write = csv.writer(f) write.writerow(columns) |