Assign a Policy to Many Computers (Bash and PowerShell)

This recipe creates a script that assigns a policy to many computers. The script searches for the computers to modify and then assigns the policy to each computer.

When you need to perform a task on many computers (hundreds or thousands), perform the work in small batches:

  1. Retrieve a small batch of computers.
  2. Assign the policy to each computer in the batch.
  3. Repeat until all computers are assigned the policy.

Small batches makes more efficient use of your Deep Security Manager resources. This recipe assigns a policy to all computers in small batches.

Before you begin

You should have already verified that your environment is set up to use the API using Bash or PowerShell.

jq for Bash

The Bash script uses jq to parse JSON data. To see if it is installed, open Terminal or your preferred command line tool and enter the following command:

jq --version

If jq is not found, visit their website to install it.

Required information

Gather the following information that you need to complete this recipe:

  • The URL of your Deep Security Manager
  • The secret key for your API key
  • The ID of the policy to assign

If you don't know the ID of the policy, you can use the Search for a Policy recipe to obtain it.

Bash

  1. Open Terminal or your preferred command line tool.
  2. Enter the following commands to store details about your request, replacing <YOUR URL> with the URL of your Deep Security Manager, and <YOUR SECRET KEY> with the secret from your API key:

    url=<YOUR URL>

    for example, url=https://192.168.1.100:4119 or url=https://example.com:4119

    secret=<YOUR SECRET KEY>

    for example, secret=5C58EADA-04BC-4ABC-45CF-B72925A0B674:aFBgpPV8eJQGaY2Dk0LmyQMD7nUGvyIDfIbIQo8Zgm8=

  3. Enter the following command to store the ID of the policy, replacing <YOUR POLCIY ID> with the ID of the computer:

    policyId=<YOUR POLICY ID>

    for example, policyId=1

  4. Copy and paste the following code that searches for computers in batches and assigns the policy to them:

    pagesize=10; idOfLastFound=0 ; \
    while [ $pagesize -gt 0 ]; do \
    echo -e "\nGetting a batch of computers..." 
    page=$(curl -X POST "$url/api/computers/search?expand=none" -H "api-secret-key: $secret" -H "api-version: v1" -H "Content-Type: application/json" -# \
    -d "{ \
    \"searchCriteria\": [{ \
    \"idValue\": \"$idOfLastFound\", \
    \"idTest\": \"greater-than\"}], \
    \"maxItems\": \"$pagesize\" \
    }" \
    -k | jq '.[]'); \
    pagesize=$(echo $page | jq length); \
    for (( i=0; i<$pagesize; i++)); do \
        computerId=$(echo $page | jq ".[$i][\"ID\"]"); \
        echo "Assigning policy to computer with ID $computerId"; \
        curl -X POST "$url/api/computers/${computerId}?expand=none" -H "api-secret-key: $secret" -H "api-version: v1" -H "Content-Type: application/json" -d "{ \"policyID\": \"$policyId\" }" -k -s -S -o /dev/null; \
    done; \
    idOfLastFound=$(echo $page | jq '.[-1]["ID"]'); \ done;

    The -k option is necessary only when your Deep Security Manager uses a self-signed certificate to establish TLS connections, which is not suitable for production environments.

Let's dig into that Bash script

This script is a bit more complicated than what we've done in other recipes, so let's recap what it does.

Most of the code executes in a loop where each iteration of the loop searches for a batch of computers and modifies them. The loop ends when the search returns no more computers. To begin, we define the size of the batch and set the computer ID to use as the basis of the search in the first iteration.

pagesize=10; idOfLastFound=0 ; \
while [ $pagesize -gt 0 ]; do \
...
done;

Inside the loop, we use cURL to search for a batch of computers. The search finds 10 computers that have an ID that is greater than the last ID found in the previous iteration. The result is piped to jq to obtain an array of computers.

page=$(curl -X POST "$url/api/computers/search?expand=none" -H "api-secret-key: $secret" -H "api-version: v1" -H "Content-Type: application/json" -# \
  -d "{ \
  \"searchCriteria\": [{ \
  \"idValue\": \"$idOfLastFound\", \
  \"idTest\": \"greater-than\"}], \
  \"maxItems\": \"$pagesize\" \
  }" \
  -k | jq '.[]'); \

Then, we find the number of computers that were returned.

   pagesize=$(echo $page | jq length); \ 

For each computer, we use cURL to assign the policy.

  for (( i=0; i<$pagesize; i++)); do \
    computerId=$(echo $page | jq ".[$i][\"ID\"]"); \
    echo "Assigning policy to computer with ID $computerId"; \
    curl -X POST "$url/api/computers/${computerId}?expand=none" -H "api-secret-key: $secret" -H "api-version: v1" -H "Content-Type: application/json" -d "{ \"policyID\": \"$policyId\" }" -k -s -S -o /dev/null; \
  done; \

Finally, we find the ID of the last computer found to use as the basis of the search in the next iteration.

  idOfLastFound=$(echo $page | jq '.[-1][\"ID\"]'); \

PowerShell

  1. Open PowerShell.
  2. Enter the following command if your Deep Security Manager uses a self-signed certificate to establish TLS connections (which is not suitable in production environments).

    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { False }

  3. Enter the following command to use TLS 1.2, which the manager requires to create a secure connection:

    [Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::Tls12

  4. Enter the following commands to store details about your request, replacing <YOUR URL> with the URL of your Deep Security Manager, and <YOUR SECRET KEY> with the secret from your API key:

    • $url = "<YOUR URL>"

      for example, url=https://192.168.1.100:4119 or url=https://example.com:4119

    • $secret = "<YOUR API KEY SECRET>"

      for example, $secret="5C58EADA-04BC-4ABC-45CF-B72725A0B674:aFBgpPV8eJQGaY2Dk0LmyQMD7nUGvyIDfIbIQo8Zgm8="

    • $headers = @{api-version = v1; api-secret-key = $secret; 'Content-Type' = "application/json"}

  5. Enter the following command to store the ID of the policy, replacing <YOUR POLCIY ID> with the ID of the computer:

    $policyId = <YOUR POLICY ID>

    for example, $policyId = 1

  6. Copy and paste the following code that searches for computers in batches and assigns the policy to them:

    $pageSize = 10
    $idOfLastFound = 0
    while($pageSize -gt 0){
        Write-Output "Getting batch of computers..."
        $page = Invoke-RestMethod -Method 'Post' -Uri "$url/api/computers/search?expand=none" -Headers $headers -Body @"
        {"searchCriteria": [ 
            {
            "idTest": "greater-than", 
            "idValue": $idOfLastFound
            } 
        ],
        "maxItems": $pageSize}
    "@
        $pageSize = $page.computers.Length
        for ($i=0; $i -lt $pageSize; $i++){
            $id = $page.computers.Get($i).ID
            Write-Output "Setting policy for computer with ID $id" 
            Invoke-RestMethod -Method 'Post' -Uri "$url/api/computers/${id}?expand=none" -Headers $headers -Body @"
            {"policyID": "$policyId"} 
    "@ | Out-Null
        }
        if ($pageSize -gt 0 ) {
            $idOfLastFound = $page.computers.Get($pageSize - 1).ID
        }
    }

    If you receive the error message The underlying connection was closed: An unexpected error occurred on a send, close PowerShell, open PowerShell again, and try repeating steps.

Let's dig into that PowerShell script

This script is a bit more complicated than what we've done in other recipes, so let's recap what it does.

Most of the code executes in a loop where each iteration of the loop searches for a batch of computers and modifies them. The loop ends when the search returns no more computers. To begin, we define the size of the batch and set the computer ID to use as the basis of the search in the first iteration.

$pageSize = 10
$idOfLastFound = 0
while($pageSize -gt 0){
...
}

Inside the loop, we call Invoke-RestMethod to search for a batch of computers. The search finds 10 computers that have an ID that is greater than the last ID found in the previous iteration.

page=$(curl -X POST "$url/api/computers/search?expand=none" -H "api-secret-key: $secret" -H "api-version: v1" -H "Content-Type: application/json" -# \
  -d "{ \
  \"searchCriteria\": [{ \
  \"idValue\": \"$idOfLastFound\", \
  \"idTest\": \"greater-than\"}], \
  \"maxItems\": \"$pagesize\" \
  }" \
  -k | jq '.[]'); \

Then, we determine the number of computers that were returned.

$pageSize = $page.computers.Length

For each computer, we call Invoke-RestMethod to assign the policy.

for ($i=0; $i -lt $pageSize; $i++){
        $id = $page.computers.Get($i).ID
        Write-Output "Setting policy for computer with ID $id" 
        Invoke-RestMethod -Method 'Post' -Uri "$url/api/computers/${id}?expand=none" -Headers $headers -Body @"
        {"policyID": "$policyId"} 

Finally, we find the ID of the last computer found to use as the basis of the search in the next iteration.

$idOfLastFound = $page.computers.Get($pageSize - 1).ID

Notes

  • To change the size of the batch of computers that is processed, set the pagesize (Bash) or $pageSize (PowerShell) variable to a different value. The value of 10 is normally a conservative batch size.