Chromium OS Enterprise DM server Setup

65 views
Skip to first unread message

Azlan Chenlong

unread,
Mar 13, 2026, 7:06:15 PMMar 13
to ChromiumOS Discussion
Hello, I am trying to test enterprise policies in a Chromium OS VM so that I can test an enterprise extension that I have been developing. 
I have been following this guide and this guide to configure a test account for enrollment using my own gmail account. However, during the enrollment process, it fails, and the fake_dmserver returns the following error: "Request failed with error code 400 (No signature for domain: gmail.com)". (see the screenshot below)

image.png

I have spent quite some time searching the documentation but I can't find anything talking about domain signatures. Is it possible that I missed a step or something?
Message has been deleted

Azlan Chenlong

unread,
Mar 13, 2026, 7:14:49 PMMar 13
to ChromiumOS Discussion, Azlan Chenlong
This was the screenshot from the previous post.
image.png

Kim Nilsson

unread,
Mar 15, 2026, 8:33:24 AMMar 15
to azlanc...@gmail.com, ChromiumOS Discussion
I did not know you could at all manage a Chromebook without a Workspace account.

/Kim
--
There is No Substitute!

Dylan Jurado

unread,
Mar 15, 2026, 9:51:21 AMMar 15
to there.is.no...@gmail.com, azlanc...@gmail.com, ChromiumOS Discussion
Hi Azlan,

To resolve the "No signature for domain" error and successfully manage your Chromium OS VM, you likely need to transition from using a standard Gmail account to a Google Workspace account.

The error occurs because the device management server requires a verified domain signature that a standard @gmail.com address cannot provide. Here are the steps to fix this:

1.  Use a Google Workspace Account: Enroll the device using an account associated with a custom domain managed through Google Workspace.
2.  Configure Domain Signatures: Ensure that the fake_dmserver or your test environment is configured to recognize the signing keys for your specific Workspace domain.
3.  Check Policy Files: Verify that your local policy configuration files match the domain you are using for enrollment.

Once you switch to a Workspace domain, the enrollment process should bypass the 400 error and allow you to test your enterprise extension with full management features.

Best regards,

Dylan J




--
--
ChromiumOS Discussion mailing list: chromium-...@chromium.org
View archives, change email options, or unsubscribe:
https://groups.google.com/a/chromium.org/group/chromium-os-discuss
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-os-dis...@chromium.org.

Azlan Chenlong

unread,
Mar 15, 2026, 8:25:14 PMMar 15
to ChromiumOS Discussion, Dylan Jurado, azlanc...@gmail.com, ChromiumOS Discussion, there.is.no...@gmail.com
Hi Dylan, thanks for the reply.

I have a workspace essentials account (the free version of the Google Workspace), but I'm not sure how to configure the fake_dmserver to recognize the signing keys for my workspace domain. I'm also not sure how to set up the sigining key for the workspace domain (are you talking about DKIM?).

I however did come across this page (shown below) in the admin dashboard. Do I need to verify my domain here? Because if I need to, I will have to start paying for a Enterprise Essentials plan, which I am trying to avoid since I just want to test my app. 
Screenshot_20260316_080427.png  

I also did try to enroll with the google workspace account, but because I cannot get the fake_dmserver to recognise my domain, I'm met with the same error:
Screenshot_20260316_080946.png

Oh, and for reference, This is my policy.json file:
{
  "policy_user": "az...@akitavault.com",
  "managed_users": [
    "*"
  ],
  "user": {
    "AllowDinosaurEasterEgg": false,
    "AllowedLocalAuthFactors": [],
    "ArcBackupRestoreServiceEnabled": 0,
    "ArcEnabled": true,
    "ArcGoogleLocationServicesEnabled": 0,
    "ArcPolicy": "{\"applications\":[],\"playStoreMode\":\"BLACKLIST\"}",
    "CaptivePortalAuthenticationIgnoresProxy": false,
    "CastReceiverEnabled": false,
    "ChromeOsMultiProfileUserBehavior": "primary-only",
    "ClassManagementEnabled": "disabled",
    "DnsOverHttpsMode": "off",
    "EasyUnlockAllowed": false,
    "EmojiPickerGifSupportEnabled": false,
    "EmojiSuggestionEnabled": false,
    "FastPairEnabled": false,
    "FocusModeSoundsEnabled": "disabled",
    "GenAiDefaultSettings": 1,
    "GoogleWorkspaceCloudUpload": "disallowed",
    "InstantTetheringAllowed": true,
    "LoginDisplayPasswordButtonEnabled": false,
    "MandatoryExtensionsForIncognitoNavigation": [],
    "MicrosoftOfficeCloudUpload": "disallowed",
    "MicrosoftOneDriveAccountRestrictions": [
      "organizations"
    ],
    "MicrosoftOneDriveMount": "disallowed",
    "NTLMShareAuthenticationEnabled": false,
    "NTPCustomBackgroundEnabled": true,
    "NearbyShareAllowed": false,
    "NetBiosShareDiscoveryEnabled": false,
    "OrcaEnabled": false,
    "OsColorMode": "light",
    "PhoneHubAllowed": false,
    "PinUnlockAutosubmitEnabled": false,
    "QuickOfficeForceFileDownloadEnabled": false,
    "QuickUnlockModeAllowlist": [],
    "RecoveryFactorBehavior": false,
    "ShowAiIntroScreenEnabled": false,
    "ShowCastSessionsStartedByOtherDevices": false,
    "ShowDisplaySizeScreenEnabled": false,
    "ShowFullUrlsInAddressBar": false,
    "ShowGeminiIntroScreenEnabled": false,
    "ShowHumanPresenceSensorScreenEnabled": false,
    "ShowTouchpadScrollScreenEnabled": false,
    "SmsMessagesAllowed": true,
    "SuggestedContentEnabled": false,
    "SystemTerminalSshAllowed": false,
    "UnaffiliatedDeviceArcAllowed": false,
    "UserBorealisAllowed": false,
    "WifiSyncAndroidAllowed": false
  },
  "device": {
    "DeviceGuestModeEnabled": false
  }
}



I would greatly appreciate it if you could let me know how to generate a signing key for my domain and how to make the fake_dmserver recognize that signing key. (and just to clarify, this fake_dmserver is found in the Chromium OS image at /usr/local/libexec/chrome-binary-tests/fake_dmserver
Looking forward to your reply. Thank you!

Regards,
Azlan Chenlong

Dylan Jurado

unread,
Mar 15, 2026, 8:26:51 PMMar 15
to Azlan Chenlong, ChromiumOS Discussion, there.is.no...@gmail.com
I will look into this and get back to you.

Dylan Jurado

unread,
Mar 15, 2026, 8:27:40 PMMar 15
to Azlan Chenlong, ChromiumOS Discussion, there.is.no...@gmail.com
Hi Azlan,

The "No signature for domain" error in fake_dmserver usually means the server doesn't have a private key to sign the policy response for the domain you are using (akitavault.com). This is independent of DKIM or your Workspace dashboard settings.

To resolve this with the fake_dmserver found in the Chromium OS image, follow these steps:

1.  Generate a Signing Key: You need to provide an RSA private key to the server. You can generate one using OpenSSL:
    openssl genrsa -out [key_name].pem 2048

2.  Launch fake_dmserver with the Key: When you run the fake_dmserver binary, you must use the --policy_key flag (or a similar flag depending on the specific version) to point to your .pem file. For example:
    ./fake_dmserver --policy_key=[path/to/key_name].pem --policy_user=az...@akitavault.com

3.  Verify the Domain in policy.json: Ensure the policy_user in your policy.json matches the domain of the account you are trying to enroll. Since your file already lists az...@akitavault.com, the server just needs that private key to sign the response for that specific domain.

You shouldn't need to upgrade to a paid Enterprise Essentials plan for this local testing, as fake_dmserver is designed to bypass the need for actual Google infrastructure by signing the policies locally.

Best regards,

Dylan J

Azlan Chenlong

unread,
Mar 15, 2026, 9:10:39 PMMar 15
to ChromiumOS Discussion, Dylan Jurado, ChromiumOS Discussion, there.is.no...@gmail.com, Azlan Chenlong
Hi Dylan,

Thank you for your quick reply. I can't seem to find the right flag for the fake_dmserver. I tried "--policy_key" and "--policy-key" but I am still getting the same error. There is also no "--help" so I don't know what flag to use. 
I also tried "--policy-verification-key" which I found in the Chromium OS Source Code but it also doesn't work. (I didn't comment out CHECK_IS_TEST() in cloud_policy_validator.cc because I can't find that file and don't intend to compile it)
I think I am using the latest version of fake_dmserver. My chromium version is 147.0.7710.0-r1591974.

Regards,
Azlan Chenlong

Dylan Jurado

unread,
Mar 15, 2026, 10:10:57 PMMar 15
to Azlan Chenlong, ChromiumOS Discussion, there.is.no...@gmail.com
Hi Azlan,

Since those flags aren't working, it’s possible the version of fake_dmserver you are using expects the keys in a specific directory rather than via a command-line flag.

Please try the following:

1.  Check for a Keys Directory: Look for a directory named keys or policy_keys in the same folder as the fake_dmserver binary. If it doesn't exist, create it and place your [key_name].pem file inside.
2.  Rename the Key File: Try renaming your private key to match the domain exactly, for example: akitavault.com.pem.
3.  Use the --policy_dir Flag: Try using the --policy_dir flag to point to the directory containing both your policy.json and your .pem key.
    ./fake_dmserver --policy_dir=[path/to/directory]
4.  Environment Variables: Check if the server expects the key path through an environment variable like POLICY_KEY_PATH.

If none of those work, could you run strings /usr/local/libexec/chrome-binary-tests/fake_dmserver | grep policy? This might reveal the exact flag names or file paths the binary is hardcoded to look for.

Best regards,

Dylan J

Dylan

Azlan Chenlong

unread,
Mar 15, 2026, 11:21:24 PMMar 15
to ChromiumOS Discussion, Dylan Jurado, ChromiumOS Discussion, there.is.no...@gmail.com, Azlan Chenlong
Hi Dylan, 

I ran strings /usr/local/libexec/chrome-binary-tests/fake_dmserver | grep policy, but I didn't find any useful information. So here's what I did:

I went to check the logs:
2026-03-16T02:28:26.700087Z INFO fake_dmserver[2839:2842]: [components/policy/test_support/embedded_policy_test_server.cc:202] Request URL: http://127.0.0.1:6112/device_management?retry=false&agent=Chromium+147.0.7710.0(026928068ef02ee9
d0287203db95fe106485f08e-refs%2Fheads%2Fmain%40%7B%231591974%7D)&apptype=Chrome&critical=true&deviceid=8ef3a930-21c1-4b11-8cf6-8415391b3e87&devicetype=2&oauth_token=&platform=Linux%2CCrOS%2Camd64-generic%7Cx86_64%2Cunknown%7C16604.0.0&r
equest=policy
2026-03-16T02:28:26.700134Z INFO fake_dmserver[2839:2842]: [components/policy/test_support/request_handler_for_policy.cc:162] PolicyFetchRequest: { policy_type: 'google/chromeos/device' }
2026-03-16T02:28:26.700151Z INFO fake_dmserver[2839:2842]: [components/policy/test_support/request_handler_for_policy.cc:180] Processing cloud policy.
2026-03-16T02:28:26.700788Z ERROR fake_dmserver[2839:2842]: [components/policy/test_support/embedded_policy_test_server.cc:75] Request failed with error code 400 (No signature for domain: akitavault.com): http://127.0.0.1:6112/device_ma
nagement?retry=false&agent=Chromium+147.0.7710.0(026928068ef02ee9d0287203db95fe106485f08e-refs%2Fheads%2Fmain%40%7B%231591974%7D)&apptype=Chrome&critical=true&deviceid=8ef3a930-21c1-4b11-8cf6-8415391b3e87&devicetype=2&oauth_token=&platf
orm=Linux%2CCrOS%2Camd64-generic%7Cx86_64%2Cunknown%7C16604.0.0&request=policy


And I saw that request_handler_for_policy.cc was the last file the log came from before it failed. So I went to look at the source code for fake_dmserver and found that it calls the GetSignatureForDomain() function from signature_provider.cc refers to a signatures_ map which is a initialised via SignatureProvider which calls InitSigningKeys to build the map:
void InitSigningKeys(std::vector<SignatureProvider::SigningKey>* signing_keys) {
  signing_keys->push_back(SignatureProvider::SigningKey(
      DecodePrivateKey(kSigningKey1),
      {
          {SignatureProvider::kTestDomain1, Decode64(kTestDomain1Signature1)},
          {SignatureProvider::kTestDomain2, Decode64(kTestDomain2Signature1)},
          {SignatureProvider::kTestDomain3, Decode64(kTestDomain3Signature1)},
      }));

  signing_keys->push_back(SignatureProvider::SigningKey(
      DecodePrivateKey(kSigningKey2),
      {
          {SignatureProvider::kTestDomain1, Decode64(kTestDomain1Signature2)},
          {SignatureProvider::kTestDomain2, Decode64(kTestDomain2Signature2)},
          {SignatureProvider::kTestDomain3, Decode64(kTestDomain3Signature2)},
      }));
}

And therefore, my conclusion is that the domain to domain signature mappings are hard coded and can't be changed at runtime. This is a possible bug. But I don't know enough C++ to be sure if I read this code correctly. Thus I would like your thoughts on this, and who you think we might be able to approach for help. (I am inclined to believe that this hard coded test domain is chromepolicytest.com which is one of the results in the strings command you asked me to try. )

I look forward to your reply.

Regards, 
Azlan Chenlong

Reply all
Reply to author
Forward
0 new messages