Managing policies using secmanctl

Overview

Besides the definition of policies using the security.manager NEXT Manager UI you can also set policies for a service using the command line. The command line tool secmanctl provides commands that allow to apply policies on map services, manually or automated, from a local file system. The policies for a map service are set by using the ArcGIS Server Administrator Directory REST interface. Policies must comply with the rules of the policy format defined by security.manager NEXT.

Define and synchronize policies

Setting policies for map services of an ArcGIS Server using the command line comprises the following steps:

Step 1: Set up the policies

  1. Create a a working directory that will contain the policies for all map services you are going to manage.

    You can give it an arbitrary name but it may be good practice to call it like the ArcGIS Server host name, for example gis-test.

  2. Create a subfolder services.

  3. Follow the ArcGIS Server folder structure and create the policies file according to the service, e.g. SampleWorldCities.json.

  4. Define access policies in the JSON file of the service according to the policy JSON format.

The policies working directory is intended to manage all protected map services on an ArcGIS Server, similar to a database. To be able to track changes made to policies, or to backup the data, it is a good idea (though not required) to manage the folder in a version control system like Git.

After editing the files in gis-test/services/…​ you need to set the policies on an ArcGIS Server so security.manager NEXT can enforce them. This process of setting policies which are defined on a local file system is called synchronization and is described in step 3.

Before you can synchronize the policies, you need to acquire an ArcGIS Server token.

Step 2: Acquire an ArcGIS Server token

  1. Use secmanctl login to request a token for the ArcGIS Server you want to synchronize policies with.

    In case of a federated ArcGIS Server, you need to authenticate at ArcGIS Enterprise portal with a user who has administrative permissions and who has multi-factor authentication disabled.
    If you use an unfederated ArcGIS Server, you need an ArcGIS Server account with administrative permissions.

    $ secmanctl login -d https://gis-test.example.com:6443/arcgis -u adminuser
    
    ✔ Enter password: *********
    Login successful.
    Authenticated against: https://gis-test.example.com/portal
    Valid until:           2020-11-11T13:12:03.802Z
    Requires SSL:          Yes
    
    Bo54NHPSbHoclN-wGQXhwWIpO_jX2bxk4xhMh7GK31y9I_qpjJZy00qAV_QRylGsPfgO7fcMv_QJmvn4FB5s_8kK0JTVyi8rzmDofpz175KXhAuH0SbGVsuqNZgJadEfkUP3pHG1pXuADoxP9JAeQ3-F9_5Q2UzXhQYQJpvpjgw.

    The token is printed out as the last line of the output.

  2. Store it in a variable or just copy it to the clipboard to use it in subsequent commands.

There are multiple possibilities to pass a password. Execute secmanctl login --help to learn more about the options of the command.

Step 3: Synchronize the policies

  1. Use secmanctl sync with the --dry mode, to test the synchronization.

    The dry run does not change anything on ArcGIS Server.

  2. Use the command without --dry mode to synchronize the policies in your policies working directory with those have been set already on an ArcGIS Server.

Executing the command will update all map service policies on the server that differ from those defined locally. If there is a policies file found for a particular service, for which security.manager NEXT was not enabled before, it will be enabled when setting the policies file.

Synchronization is executed the following way:

$ secmanctl sync -f ./gis-test -d https://gis-test.example.com:6443/arcgis -t Bo54NHPSbHocl…
Synchronize './gis-test' to 'https://gis-test.example.com:6443/arcgis'

DIFFERENCE                CURRENT [-> DESIRED]
=======================   ================================
[<>] /SampleWorldCities   protected(modified) -> protected
[=>] admin/countries      unprotected -> protected

Applied 2 of 2 changes
Synchronization took 2.50 sec

[SUCCESS]

The command first prints a list of changes that will be applied before setting changed policies on ArcGIS Server. In the above example, the policies of the map services SampleWorldCities and admin/countries were updated. For SampleWorldCities the server-side policies were replaced by the local ones. For admin/countries, the command enabled security.manager NEXT and set the local policies on the ArcGIS Server.

Raising the verbosity level with -v and -vv will print a more detailed list, where also those services will be listed that won’t change.

Dry run

Especially when you made more complex changes to the policies it is a good choice to perform a "dry run" of the synchronization first. When executed in --dry mode, secmanctl sync does not change anything on the server or in your local filesystem but only checks for modifications and policy validation errors — and print them out.

Dry run of the sync command
$ secmanctl sync -f ./gis-test -d https://gis-test.example.com:6443/arcgis -t Bo54NHPSbHocl… --dry
[DRY RUN] Nothing will be changed in this execution of 'sync'
Synchronize './gis-test' to 'https://gis-test.example.com:6443/arcgis'

DIFFERENCE                CURRENT [-> DESIRED]
=======================   ================================
[<>] /SampleWorldCities   protected(modified) -> protected

Applied 1 of 1 changes
Synchronization took 937 ms

[SUCCESS]

In the above example, the set policies (server-side) for /SampleWorldCities don’t match the local policies. All other services have a matching state.

Once you’re fine with the things that would happen, run the same command without the --dry option to apply the actual changes.

Solving common tasks

Validating local policy files

The --dry option can be used to check the local policy files for syntactical correctness. Before setting policies by using secmanctl apply or secmanctl sync the JSON policy files of the policies working directory are validated. Invalid files will not be set on the ArcGIS Server and validation errors will be shown accordingly in the output of the command.

The following example shows the output of the apply command in case of an invalid JSON file.

$ secmanctl apply -i us_airports_invalid.json -d https://gis-test.example.com:6443/arcgis -t MghzyNeWubQtTgZfMQTx8rasda.. -s us_airports --dry
[DRY RUN] Nothing will be changed in this execution of 'apply'

DIFFERENCE                CURRENT [-> DESIRED]
=======================   ================================
[ER] /us_airports.json    invalid

No changes found
[ERROR]
Errors occurred during analysis of changes:
    '/us_airports_invalid.json':
        Error: Validation error: Undefined restriction 'DOES_NOT_EXIST'.

Operation failed, please check the output above.

Backup policies from an ArcGIS Server

Source and target of the sync command can be reversed by using the --reverse option to download policies from an ArcGIS Server and store them locally. This may be handy for making a backup of the current state of the policies from the ArcGIS Server.

Do not use the --reverse option to synchronize policies from an ArcGIS Server with your local policies working directory otherwise existing policies are overwritten.

The following listing shows the usage of the --reverse option:

$ secmanctl sync --reverse -f ./gis-test -d https://gis-test.example.com:6443/arcgis -t MghzyNeWubQtTgZfMQTx8ras..
Synchronize 'https://gis-test.example.com:6443/arcgis' to './gis-test'

DIFFERENCE                CURRENT [-> DESIRED]
=======================   ================================
[=>] /SampleWorldCities   unprotected -> protected
[=>] water/wells          unprotected -> protected
[=>] water/bassins        unprotected -> protected

Applied 3 of 3 changes
Synchronization took 674 ms

[SUCCESS]

As a result of the execution of this command, three policy files are downloaded and stored within the given folder.

Apply policies for selected folders

The sync command offers the --include-folders option to operate on selected folders when synchronizing with the ArcGIS Server.

The following example demonstrates how to synchronize just the water folder.

$ secmanctl sync -v -f ./gis-test -d https://gis.example.com:6443/arcgis -t MghzyNeWubQtTgZfMQTx8rasda.. --dry --include-folders water
[DRY RUN] Nothing will be changed in this execution of 'sync'
Synchronize './gis-test' to 'https://gis-test.example.com:6443/arcgis'

DIFFERENCE                CURRENT [-> DESIRED]
===================   ================================
[<>] water/wells      protected(modified) -> protected
[<>] water/bassins    protected(modified) -> protected

Applied 2 of 2 changes

[SUCCESS]
By specifying --include-folders / it is also possible to synchronize only those services that are directly located below the root directory.

Using the option --include-folders becomes handy, especially when combining it with the --delete option. This way, only permissions which are located on the ArcGIS Server within the specified directory are deleted during synchronization.

Enable offline editing for a protected feature service

Create the configuration file <servicename>.conf.json for a protected feature service. The file must lie next to the feature service’s policy file in the working directory. Add the following json content

{
    "soi.supportReplicas": true
}

Run the sync command to apply configuration along with the policy on the server.

$ secmanctl sync -f ./gis-test -d https://gis-test.example.com:6443/arcgis -t MghzyNeWubQtTgZfMQTx8rasda.. --dry

Synchronize './gis-test' to 'https://gis-test.example.com:6443/arcgis'

DIFFERENCE                          CURRENT [-> DESIRED]
================================    ================================
[<>] sandbox/aviation_editing       protected(modified) -> protected

Applied 1 of 1 changes
Synchronization took 953 ms

[SUCCESS]
Additional information:
    'sandbox/aviation_editing':
        Note: Replica support was set to 'true'

Reference group ids using property expressions in policy files

The JSON output format of the groups command can help to write readable policies. This is especially helpful when protecting a federated ArcGIS Server because in this case you need to use the technical group IDs inside a policy instead of their more readable names.

The following example shows the output of the groups command with the --json option.

$ secmanctl groups -d https://gis-test.example.com:6443/arcgis -t MghzyNeWubQtTgZfMQTx8rasda.. --json

{
    "any_user": "enhancedSecurity_any",
    "authenticated_users": "enhancedSecurity_authenticated",
    "dezernat_a": "49537170bc3041e1b291d7146290d51c",
    "featured_maps_and_apps": "345c76ba732a4a7bac4227bb6c3aa701",
    "others": "84ac890b7627461e8b0dd0376bb8a0c2"
}

The output can be used to declare properties in policy files. Once declared, they can be referenced from other locations.

The following example references the ID of group dezernat_a by using the expression ${dezernat_a}.

{
  "properties": {
      "dezernat_a": "49537170bc3041e1b291d7146290d51c",
      "featured_maps_and_apps": "345c76ba732a4a7bac4227bb6c3aa701",
      "others": "84ac890b7627461e8b0dd0376bb8a0c2"
  },
  "policies": [
      {
          "layers": ["0", "1"],
          "roles": ["${dezernat_a}"]
      }
  ]
}

The sharing properties feature allows to reference group names declared in a shared properties.json file. In this case it makes sense to use a common prefix for groups like group_. The option --json-key-pattern helps to generate the keys more flexible.

$ secmanctl groups -d https://gis-test.example.com:6443/arcgis -t MghzyNeWubQtTgZfMQTx8rasda.. --json --json-key-pattern 'group_{title}'

{
    "group_any_user": "enhancedSecurity_any",
    "group_authenticated_users": "enhancedSecurity_authenticated",
    "group_dezernat_a": "49537170bc3041e1b291d7146290d51c",
    "group_featured_maps_and_apps": "345c76ba732a4a7bac4227bb6c3aa701",
    "group_others": "84ac890b7627461e8b0dd0376bb8a0c2"
}

Redirecting the output to a file

During the processing of commands, information is written to the standard output stdout. Errors are written to stderr.

stdout and stderr can be redirected to files (examples for Microsoft Windows):

  • Redirect the output of stdout to a file

    • secmanctl…​ > out.txt

    • All normal information are written to the file out.txt but errors are not.

  • Redirect the outputs of stdout and stderr to a file

    • secmanctl…​ > out.txt 2>&1

    • In this way, the outputs of both data streams are written to the file out.txt.

Accepting custom TLS/SSL certificates

The security.manager NEXT CLI is based on Node.js which - like some browsers - maintains its own set of trusted root CA (certificate authority) certificates. To add a custom certificate to this set (such as a company internal CA certificate), use the NODE_EXTRA_CA_CERTS environment variable . The variable accepts the path to a file containing one or more PEM encoded certificates.

Example (Linux shell)
$ NODE_EXTRA_CA_CERTS=/path/to/certs.pem secmanctl login -d $SERVER
Example (Windows Command Prompt)
> set NODE_EXTRA_CA_CERTS=C:\path\to\certs.pem
> secmanctl.exe login -d %SERVER%

Automate setting of policies

To execute secmanctl apply or secmanctl sync an authentication token for the ArcGIS Server is required. This token can be obtained using secmanctl login.

If you want to automate the execution of the commands, e.g. in the context of a build pipeline, you can execute the login command and pass the received token to the following call of apply or sync.

The following listing shows an example of a batch file as it can be used under Microsoft Windows:

automate_sync.bat
@echo off
rem Script Variables
set secmanctl=".\bin\secmanctl.exe"
set SERVER="https://gis-test.example.com:6443/arcgis"
set ROOT=".\gis-test"

rem login
call %secmanctl% login -d %SERVER% -u admin -p pw.txt --plain > token.txt
set /p TOKEN=<token.txt
del token.txt

rem sync
call %secmanctl% sync -d %SERVER% -f %ROOT% -t %TOKEN%

For a shell script under Linux an automated login can be implemented analogously:

automate_sync.sh
# Script Variables
secmanctl="./bin/secmanctl"
SERVER="https://gis-test.example.com:6443/arcgis"
ROOT="./gis-test"

#login
TOKEN=$($secmanctl login -d $SERVER -u admin -p pw.txt --plain)

# sync
$secmanctl sync -d $SERVER -f $ROOT -t $TOKEN