components/policy/tools/fake_dmserver/chromeos_instructions.md
This document describes the tools and workflows for applying local policies to a
ChromeOS test device using fake_dmserver.
There are two primary ways to use these tools:
orchestrator.py script.blob_generator.py script
directly.Before you begin, you must disable root filesystem verification on your test device. This allows you to write the necessary configuration files.
Run these commands in a terminal on your DUT:
sudo /usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification \
--force && sudo reboot
After the device reboots, remount the filesystem as read-write for your current session:
sudo mount -o remount,rw /
This workflow uses the orchestrator.py script to automate the entire process
of generating policies, starting the server, configuring Chrome, and restarting
the UI.
Create a simple JSON file with the policies you want to test. A good location is
/usr/local/tmp/policies.json.
(See the section "How to Set Valid Policies" below for details on the file format.)
Execute the orchestrator script with the path to your policy file. It will handle everything else.
Run this command on the DUT:
python3 /usr/local/share/policy-test-tool/orchestrator.py \
/usr/local/tmp/policies.json
The script will start the server and restart the UI. You can then log in and
verify your policies at chrome://policy. The script will continue to watch
your policies.json file for changes.
This workflow is for users who want more control over the process. You will use the generator script to create the policy blob and then manually perform the necessary system actions.
Create a simple JSON file with the policies you want to test (e.g.,
/usr/local/tmp/policies.json).
Use the blob_generator.py script to convert your simple JSON into the format
fake_dmserver understands.
Run this command on the DUT:
# Make sure the output directory exists
mkdir -p /var/tmp/dmserver_data
python3 /usr/local/share/policy-test-tool/blob_generator.py \
--input-policies=/usr/local/tmp/policies.json \
--output-blob=/var/tmp/dmserver_data/policy.json \
--manual-map=/usr/local/share/policy-test-tool/manual_device_policy_proto_map.yaml
fake_dmserverManually start the fake_dmserver on the device, pointing it to your generated
policy blob. This command typically requires root permissions.
Run this command on the DUT:
# Start the server and take note of the host and port it prints out
/usr/local/libexec/chrome-binary-tests/fake_dmserver \
--policy-blob-path=/var/tmp/dmserver_data/policy.json
The server will output its address, for example:
{"host": "127.0.0.1", "port": 6112}.
Optional arguments:
--port=... to set the server port. Defaults to 6112.--client-state-path=... to tell fake_dmserver where to load/save its
internal state. Defaults to state.json in the same directory as your
policy-blob-path.Write a configuration file to tell Chrome to use your local server.
Run this command on the DUT (you will need to be root):
# Replace the URL with the host and port from the previous step
echo "--device-management-url=http://127.0.0.1:6112/device_management" \
>> /etc/chrome_dev.conf```
### Step 5: Restart the UI
Restart the Chrome UI to force it to reload the configuration and fetch the new
policies.
**Run this command on the DUT (you will need to be root):**
```bash
restart ui
policies.json)The policies.json file has a simple structure. The top-level keys are used to
configure the fake_dmserver itself, while the user and device sections
define the actual policies to be applied.
You can create this file manually, or you can generate it by following the steps in the converter script described in the next section.
user: (Object) A dictionary where keys are user policy names and values
are the policy values.device: (Object) A dictionary where keys are device policy names and
values are the policy values.policy_user: (String) The user ID (e.g., email address) to embed in
policy responses. This must match the user on the ChromeOS device, or the
policy will be rejected.managed_users: (Array of Strings) A list of users that the server should
treat as managed. Use "*" to treat all users as managed.device_affiliation_ids: (Array of Strings) A list of affiliation IDs for
the device.user_affiliation_ids: (Array of Strings) A list of affiliation IDs for
the user.directory_api_id: (String) The Directory API ID of the device.robot_api_auth_code: (String) The authorization code for the robot
account, used during enterprise enrollment.allow_set_device_attributes: (Boolean) If true, allows device
attributes to be set by the client. Defaults to true.use_universal_signing_keys: (Boolean) If true, the server will use a
universal test key to sign policy blobs. This is recommended for most local
testing scenarios.current_key_index: (Integer) The index of the signing key to use.request_errors: (Object) A dictionary to simulate server errors. The keys
are request types (e.g., "register", "policy") and the values are HTTP
error codes (e.g., 500).initial_enrollment_state: (Object) A dictionary defining the initial
state for zero-touch enrollment.policies.json{
"policy_user": "<user>@gmail.com",
"managed_users": ["*"],
"user": {
"AllowDinosaurEasterEgg": true,
"ShowHomeButton": true,
"HomepageLocation": "https://www.google.com",
"RestoreOnStartup": 1,
"URLBlocklist": [
"example.com",
"unwanted-site.org"
],
"ManagedBookmarks": "[{\"name\":\"Google Search\",\"url\":\"https://www.google.com\"},{\"name\":\"Internal Tools\",\"children\":[{\"name\":\"Moma\",\"url\":\"https://moma.corp.google.com\"},{\"name\":\"Critique\",\"url\":\"https://critique.corp.google.com\"}]},{\"name\":\"News\",\"url\":\"https://news.google.com\"}]"
},
"device": {
"DeviceGuestModeEnabled": true,
"DevicePolicyRefreshRate": 3600000,
"DeviceLocalAccounts": [
{
"account_id": "<user>@gmail.com",
"type": "KIOSK_IWA",
"isolated_kiosk_app": {
"update_manifest_url": "https://github.com/chromeos/iwa-sink/releases/latest/download/update.json",
"web_bundle_id": "aiv4bxauvcu3zvbu6r5yynoh4atkzqqaoeof5mwz54b4zfywcrjuoaacai"
}
}
],
"DeviceLocalAccountAutoLoginId": "<user>@gmail.com"
},
"use_universal_signing_keys": true
}
For full details on available policies and value formats, please refer to the [Chrome Enterprise policies documentation] (https://chromeenterprise.google.com/policies/).
The orchestrator.py script allows you to pass additional command-line flags
directly to Chrome using the --chrome-flags argument. This is useful for
enabling experimental features, debugging, or overriding default Chrome
behavior.
You can specify this argument multiple times for different flags:
python3 /usr/local/share/policy-test-tool/orchestrator.py \
/usr/local/tmp/policies.json \
--chrome-flags="--remote-debugging-port=9222" \
--chrome-flags="--enable-features=IsolatedWebAppDevMode"
chrome://policy dumpIf you want to replicate the policy state of an existing device, you can use the
policy_dump_converter.py script.
The JSON file you export from chrome://policy is different from the
simplified policies.json format required by these tools. The dump from
chrome://policy is a detailed report of the current state, including metadata
like policy scope, source, and whether it was successfully applied.
The policies.json format, on the other hand, is a simple, clean definition of
the policies you want to set. The converter script bridges this gap by
extracting only the necessary information (name, value, and scope) and
structuring it correctly for the fake_dmserver.
Step 1: Export Policies from Chrome
Navigate to chrome://policy on the device you want to copy policies from,
click "Export to JSON", and save the file.
Step 2: Run the Converter Script
Run the converter script on the DUT, providing the exported JSON, a path for the
new policies.json file, and the managed user's email.
python3 /usr/local/share/policy-test-tool/policy_dump_converter.py \
--input-dump=/path/to/your/policy_export.json \
--output-policies=/usr/local/tmp/policies.json \
[email protected]
Step 3: Use the Generated File
The newly created /usr/local/tmp/policies.json can now be used with the
orchestrator.py script as described in the "Automated
Usage" section.
If you see a warning like WARNING: Policy 'YourPolicyName' not found in protobuf schema. Skipping., it means the version of the policy-test-tool on
your device is older than the version of Chrome running on it.
To fix this:
policy-test-tool package to your DUT.This will update the policy definitions used by the tool to match the latest version of Chrome.
If you are developing a new policy that has not yet been landed in the Chromium source tree, the testing tools will not recognize it. To test it, you need to manually update the policy definitions in your local checkout before building the package.
policy_templates.jsonThis file is the source of truth for all Chrome policies. You need to add a definition for your new policy here.
Edit the file:
chromium/src/components/policy/resources/policy_templates.json
Add your policy definition to the policy_definitions list. Ensure the
name, type, schema, and supported_on fields are correct.
{
'name': 'MyNewAwesomePolicy',
'type': 'boolean',
'schema': { 'type': 'boolean' },
'supported_on': ['chrome_os:145-'],
'features': { 'dynamic_refresh': true, 'per_profile': true },
'example_value': true,
'caption': 'Enable My New Awesome Policy',
'desc': 'When this policy is enabled, it activates my new awesome feature.'
}
After updating the policy definitions, you must regenerate the
chrome_settings.proto file, which is used to build the Python modules.
chromium/src directory:
python3 components/policy/tools/generate_policy_source.py \
--chrome-settings-protobuf=components/policy/proto/chrome_settings.proto \
--policy-templates-file=components/policy/resources/policy_templates.json \
--target-platform="chrome_os"
Now that your local source code includes the new policy definition, you can
rebuild and deploy the policy-test-tool.
.proto
file.
emerge-<board> chromeos-base/policy-test-tool
cros deploy <DUT_IP> chromeos-base/policy-test-tool
You can now add your new policy to your policies.json file and use the
orchestrator script.
/usr/local/tmp/policies.json on the DUT and add your new policy
to the user or device section.python3 /usr/local/share/policy-test-tool/orchestrator.py \
/usr/local/tmp/policies.json
The tool will now recognize and apply your new policy.
If you are making changes to the policy-test-tool scripts themselves (e.g.,
orchestrator.py, blob_generator.py, policy_dump_converter.py), follow
these steps to test your changes on the DUT:
cros_workonOn your development machine, enable cros_workon for the policy-test-tool
package. This allows you to make changes to the source code and have them
reflected in the build.
cros_workon --board=<board> start chromeos-base/policy-test-tool
Edit the Python scripts in your local ChromiumOS checkout
(chromiumos/src/chromium/src/components/policy/tools/fake_dmserver/orchestrator.py,
chromiumos/src/chromium/src/components/policy/tools/fake_dmserver/blob_generator.py,
chromiumos/src/chromium/src/components/policy/tools/fake_dmserver/policy_dump_converter.py)
or directly on the DUT at /usr/local/share/policy-test-tool/.
After making your changes, rebuild and deploy the policy-test-tool package to
your DUT. This will install your modified scripts on the device.
emerge-<board> chromeos-base/policy-test-tool
cros deploy <DUT_IP> chromeos-base/policy-test-tool
Once deployed, your changes to the policy-test-tool scripts will be active on
the DUT. You can then run the orchestrator or other scripts as usual to test
your modifications.
python3 /usr/local/share/policy-test-tool/orchestrator.py \
/usr/local/tmp/policies.json