# Unix SMB/CIFS implementation. Tests for smb manipulation # Copyright (C) David Mulder 2018 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os, grp, pwd, re import errno from samba import gpo, tests from samba.gp.gpclass import register_gp_extension, list_gp_extensions, \ unregister_gp_extension, GPOStorage, get_gpo_list from samba.param import LoadParm from samba.gp.gpclass import check_refresh_gpo_list, check_safe_path, \ check_guid, parse_gpext_conf, atomic_write_conf, get_deleted_gpos_list from subprocess import Popen, PIPE from tempfile import NamedTemporaryFile, TemporaryDirectory from samba.gp import gpclass # Disable privilege dropping for testing gpclass.drop_privileges = lambda _, func, *args : func(*args) from samba.gp.gp_sec_ext import gp_krb_ext from samba.gp.gp_scripts_ext import gp_scripts_ext, gp_user_scripts_ext from samba.gp.gp_sudoers_ext import gp_sudoers_ext from samba.gp.vgp_sudoers_ext import vgp_sudoers_ext from samba.gp.vgp_symlink_ext import vgp_symlink_ext from samba.gp.gpclass import gp_inf_ext from samba.gp.gp_smb_conf_ext import gp_smb_conf_ext from samba.gp.vgp_files_ext import vgp_files_ext from samba.gp.vgp_openssh_ext import vgp_openssh_ext from samba.gp.vgp_startup_scripts_ext import vgp_startup_scripts_ext from samba.gp.vgp_motd_ext import vgp_motd_ext from samba.gp.vgp_issue_ext import vgp_issue_ext from samba.gp.vgp_access_ext import vgp_access_ext from samba.gp.gp_gnome_settings_ext import gp_gnome_settings_ext from samba.gp import gp_cert_auto_enroll_ext as cae from samba.gp.gp_firefox_ext import gp_firefox_ext from samba.gp.gp_chromium_ext import gp_chromium_ext from samba.gp.gp_firewalld_ext import gp_firewalld_ext from samba.credentials import Credentials from samba.gp.gp_msgs_ext import gp_msgs_ext from samba.gp.gp_centrify_sudoers_ext import gp_centrify_sudoers_ext from samba.gp.gp_centrify_crontab_ext import gp_centrify_crontab_ext, \ gp_user_centrify_crontab_ext from samba.gp.gp_drive_maps_ext import gp_drive_maps_user_ext from samba.common import get_bytes from samba.dcerpc import preg from samba.ndr import ndr_pack import codecs from shutil import copyfile import xml.etree.ElementTree as etree import hashlib from samba.gp_parse.gp_pol import GPPolParser from glob import glob from configparser import ConfigParser from samba.gp.gpclass import get_dc_hostname, expand_pref_variables from samba import Ldb import ldb as _ldb from samba.auth import system_session import json from shutil import which import requests from cryptography import x509 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.serialization import Encoding from datetime import datetime, timedelta, timezone from samba.samba3 import param as s3param def dummy_certificate(): name = x509.Name([ x509.NameAttribute(x509.NameOID.COMMON_NAME, os.environ.get('SERVER')) ]) cons = x509.BasicConstraints(ca=True, path_length=0) now = datetime.now(tz=timezone.utc) key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) cert = ( x509.CertificateBuilder() .subject_name(name) .issuer_name(name) .public_key(key.public_key()) .serial_number(1000) .not_valid_before(now) .not_valid_after(now + timedelta(seconds=300)) .add_extension(cons, False) .sign(key, hashes.SHA256(), default_backend()) ) return cert.public_bytes(encoding=Encoding.DER) # Dummy requests structure for Certificate Auto Enrollment class dummy_requests(object): class exceptions(object): ConnectionError = Exception def __init__(self, want_exception=False): self.want_exception = want_exception def get(self, url=None, params=None): if self.want_exception: raise self.exceptions.ConnectionError dummy = requests.Response() dummy._content = dummy_certificate() dummy.headers = {'Content-Type': 'application/x-x509-ca-cert'} return dummy realm = os.environ.get('REALM') policies = realm + '/POLICIES' realm = realm.lower() poldir = r'\\{0}\sysvol\{0}\Policies'.format(realm) # the first part of the base DN varies by testenv. Work it out from the realm base_dn = 'DC={0},DC=samba,DC=example,DC=com'.format(realm.split('.')[0]) dspath = 'CN=Policies,CN=System,' + base_dn gpt_data = '[General]\nVersion=%d' gnome_test_reg_pol = \ br""" GNOME Settings\Lock Down Settings Lock Down Enabled Extensions 1 GNOME Settings\Lock Down Settings Lock Down Specific Settings 1 GNOME Settings\Lock Down Settings Disable Printing 1 GNOME Settings\Lock Down Settings Disable File Saving 1 GNOME Settings\Lock Down Settings Disable Command-Line Access 1 GNOME Settings\Lock Down Settings Disallow Login Using a Fingerprint 1 GNOME Settings\Lock Down Settings Disable User Logout 1 GNOME Settings\Lock Down Settings Disable User Switching 1 GNOME Settings\Lock Down Settings Disable Repartitioning 1 GNOME Settings\Lock Down Settings Whitelisted Online Accounts 1 GNOME Settings\Lock Down Settings Compose Key 1 GNOME Settings\Lock Down Settings Dim Screen when User is Idle 1 GNOME Settings\Lock Down Settings Enabled Extensions 1 GNOME Settings\Lock Down Settings\Compose Key Key Name Right Alt GNOME Settings\Lock Down Settings\Dim Screen when User is Idle Delay 300 GNOME Settings\Lock Down Settings\Dim Screen when User is Idle Dim Idle Brightness 30 GNOME Settings\Lock Down Settings\Enabled Extensions **delvals. GNOME Settings\Lock Down Settings\Enabled Extensions myextension1@myname.example.com myextension1@myname.example.com GNOME Settings\Lock Down Settings\Enabled Extensions myextension2@myname.example.com myextension2@myname.example.com GNOME Settings\Lock Down Settings\Lock Down Specific Settings **delvals. GNOME Settings\Lock Down Settings\Lock Down Specific Settings /org/gnome/desktop/background/picture-uri /org/gnome/desktop/background/picture-uri GNOME Settings\Lock Down Settings\Lock Down Specific Settings /org/gnome/desktop/background/picture-options /org/gnome/desktop/background/picture-options GNOME Settings\Lock Down Settings\Lock Down Specific Settings /org/gnome/desktop/background/primary-color /org/gnome/desktop/background/primary-color GNOME Settings\Lock Down Settings\Lock Down Specific Settings /org/gnome/desktop/background/secondary-color /org/gnome/desktop/background/secondary-color GNOME Settings\Lock Down Settings\Whitelisted Online Accounts **delvals. GNOME Settings\Lock Down Settings\Whitelisted Online Accounts google google """ auto_enroll_reg_pol = \ br""" Software\Policies\Microsoft\Cryptography\AutoEnrollment AEPolicy 7 Software\Policies\Microsoft\Cryptography\AutoEnrollment OfflineExpirationPercent 10 Software\Policies\Microsoft\Cryptography\AutoEnrollment OfflineExpirationStoreNames MY """ auto_enroll_unchecked_reg_pol = \ br""" Software\Policies\Microsoft\Cryptography\AutoEnrollment AEPolicy 0 Software\Policies\Microsoft\Cryptography\AutoEnrollment OfflineExpirationPercent 10 Software\Policies\Microsoft\Cryptography\AutoEnrollment OfflineExpirationStoreNames MY """ advanced_enroll_reg_pol = \ br""" Software\Policies\Microsoft\Cryptography **DeleteKeys Software\Policies\Microsoft\Cryptography\PolicyServers Software\Policies\Microsoft\Cryptography\AutoEnrollment AEPolicy 7 Software\Policies\Microsoft\Cryptography\AutoEnrollment OfflineExpirationPercent 25 Software\Policies\Microsoft\Cryptography\AutoEnrollment OfflineExpirationStoreNames MY Software\Policies\Microsoft\Cryptography\PolicyServers {5AD0BE6D-3393-4940-BFC3-6E19555A8919} Software\Policies\Microsoft\Cryptography\PolicyServers Flags 0 Software\Policies\Microsoft\Cryptography\PolicyServers\37c9dc30f207f27f61a2f7c3aed598a6e2920b54 URL LDAP: Software\Policies\Microsoft\Cryptography\PolicyServers\37c9dc30f207f27f61a2f7c3aed598a6e2920b54 PolicyID %s Software\Policies\Microsoft\Cryptography\PolicyServers\37c9dc30f207f27f61a2f7c3aed598a6e2920b54 FriendlyName Example Software\Policies\Microsoft\Cryptography\PolicyServers\37c9dc30f207f27f61a2f7c3aed598a6e2920b54 Flags 16 Software\Policies\Microsoft\Cryptography\PolicyServers\37c9dc30f207f27f61a2f7c3aed598a6e2920b54 AuthFlags 2 Software\Policies\Microsoft\Cryptography\PolicyServers\37c9dc30f207f27f61a2f7c3aed598a6e2920b54 Cost 2147483645 Software\Policies\Microsoft\Cryptography\PolicyServers\144bdbb8e4717c26e408f3c9a0cb8d6cfacbcbbe URL https://example2.com/ADPolicyProvider_CEP_Certificate/service.svc/CEP Software\Policies\Microsoft\Cryptography\PolicyServers\144bdbb8e4717c26e408f3c9a0cb8d6cfacbcbbe PolicyID %s Software\Policies\Microsoft\Cryptography\PolicyServers\144bdbb8e4717c26e408f3c9a0cb8d6cfacbcbbe FriendlyName Example2 Software\Policies\Microsoft\Cryptography\PolicyServers\144bdbb8e4717c26e408f3c9a0cb8d6cfacbcbbe Flags 16 Software\Policies\Microsoft\Cryptography\PolicyServers\144bdbb8e4717c26e408f3c9a0cb8d6cfacbcbbe AuthFlags 8 Software\Policies\Microsoft\Cryptography\PolicyServers\144bdbb8e4717c26e408f3c9a0cb8d6cfacbcbbe Cost 10 Software\Policies\Microsoft\Cryptography\PolicyServers\20d46e856e9b9746c0b1265c328f126a7b3283a9 URL https://example0.com/ADPolicyProvider_CEP_Kerberos/service.svc/CEP Software\Policies\Microsoft\Cryptography\PolicyServers\20d46e856e9b9746c0b1265c328f126a7b3283a9 PolicyID %s Software\Policies\Microsoft\Cryptography\PolicyServers\20d46e856e9b9746c0b1265c328f126a7b3283a9 FriendlyName Example0 Software\Policies\Microsoft\Cryptography\PolicyServers\20d46e856e9b9746c0b1265c328f126a7b3283a9 Flags 16 Software\Policies\Microsoft\Cryptography\PolicyServers\20d46e856e9b9746c0b1265c328f126a7b3283a9 AuthFlags 2 Software\Policies\Microsoft\Cryptography\PolicyServers\20d46e856e9b9746c0b1265c328f126a7b3283a9 Cost 1 Software\Policies\Microsoft\Cryptography\PolicyServers\855b5246433a48402ac4f5c3427566df26ccc9ac URL https://example1.com/ADPolicyProvider_CEP_Kerberos/service.svc/CEP Software\Policies\Microsoft\Cryptography\PolicyServers\855b5246433a48402ac4f5c3427566df26ccc9ac PolicyID %s Software\Policies\Microsoft\Cryptography\PolicyServers\855b5246433a48402ac4f5c3427566df26ccc9ac FriendlyName Example1 Software\Policies\Microsoft\Cryptography\PolicyServers\855b5246433a48402ac4f5c3427566df26ccc9ac Flags 16 Software\Policies\Microsoft\Cryptography\PolicyServers\855b5246433a48402ac4f5c3427566df26ccc9ac AuthFlags 2 Software\Policies\Microsoft\Cryptography\PolicyServers\855b5246433a48402ac4f5c3427566df26ccc9ac Cost 1 """ firefox_reg_pol = \ b""" Software\\Policies\\Mozilla\\Firefox ExtensionSettings { "*": { "blocked_install_message": "Custom error message.", "install_sources": ["about:addons","https://addons.mozilla.org/"], "installation_mode": "blocked", "allowed_types": ["extension"] }, "uBlock0@raymondhill.net": { "installation_mode": "force_installed", "install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi" }, "https-everywhere@eff.org": { "installation_mode": "allowed" } } Software\\Policies\\Mozilla\\Firefox ExtensionUpdate 1 Software\\Policies\\Mozilla\\Firefox SearchSuggestEnabled 1 Software\\Policies\\Mozilla\\Firefox AppAutoUpdate 1 Software\\Policies\\Mozilla\\Firefox AppUpdateURL https://yoursite.com Software\\Policies\\Mozilla\\Firefox BlockAboutAddons 1 Software\\Policies\\Mozilla\\Firefox BlockAboutConfig 1 Software\\Policies\\Mozilla\\Firefox BlockAboutProfiles 1 Software\\Policies\\Mozilla\\Firefox BlockAboutSupport 1 Software\\Policies\\Mozilla\\Firefox CaptivePortal 1 Software\\Policies\\Mozilla\\Firefox DefaultDownloadDirectory ${home}/Downloads Software\\Policies\\Mozilla\\Firefox DisableAppUpdate 1 Software\\Policies\\Mozilla\\Firefox DisableBuiltinPDFViewer 1 Software\\Policies\\Mozilla\\Firefox DisableDefaultBrowserAgent 1 Software\\Policies\\Mozilla\\Firefox DisableDeveloperTools 1 Software\\Policies\\Mozilla\\Firefox DisableFeedbackCommands 1 Software\\Policies\\Mozilla\\Firefox DisableFirefoxAccounts 1 Software\\Policies\\Mozilla\\Firefox DisableFirefoxScreenshots 1 Software\\Policies\\Mozilla\\Firefox DisableFirefoxStudies 1 Software\\Policies\\Mozilla\\Firefox DisableForgetButton 1 Software\\Policies\\Mozilla\\Firefox DisableFormHistory 1 Software\\Policies\\Mozilla\\Firefox DisableMasterPasswordCreation 1 Software\\Policies\\Mozilla\\Firefox DisablePasswordReveal 1 Software\\Policies\\Mozilla\\Firefox DisablePocket 1 Software\\Policies\\Mozilla\\Firefox DisablePrivateBrowsing 1 Software\\Policies\\Mozilla\\Firefox DisableProfileImport 1 Software\\Policies\\Mozilla\\Firefox DisableProfileRefresh 1 Software\\Policies\\Mozilla\\Firefox DisableSafeMode 1 Software\\Policies\\Mozilla\\Firefox DisableSetDesktopBackground 1 Software\\Policies\\Mozilla\\Firefox DisableSystemAddonUpdate 1 Software\\Policies\\Mozilla\\Firefox DisableTelemetry 1 Software\\Policies\\Mozilla\\Firefox DisplayBookmarksToolbar 1 Software\\Policies\\Mozilla\\Firefox DisplayMenuBar default-on Software\\Policies\\Mozilla\\Firefox DontCheckDefaultBrowser 1 Software\\Policies\\Mozilla\\Firefox DownloadDirectory ${home}/Downloads Software\\Policies\\Mozilla\\Firefox Handlers { "mimeTypes": { "application/msword": { "action": "useSystemDefault", "ask": true } }, "schemes": { "mailto": { "action": "useHelperApp", "ask": true, "handlers": [{ "name": "Gmail", "uriTemplate": "https://mail.google.com/mail/?extsrc=mailto&url=%s" }] } }, "extensions": { "pdf": { "action": "useHelperApp", "ask": true, "handlers": [{ "name": "Adobe Acrobat", "path": "/usr/bin/acroread" }] } } } Software\\Policies\\Mozilla\\Firefox HardwareAcceleration 1 Software\\Policies\\Mozilla\\Firefox ManagedBookmarks [ { "toplevel_name": "My managed bookmarks folder" }, { "url": "example.com", "name": "Example" }, { "name": "Mozilla links", "children": [ { "url": "https://mozilla.org", "name": "Mozilla.org" }, { "url": "https://support.mozilla.org/", "name": "SUMO" } ] } ] Software\\Policies\\Mozilla\\Firefox NetworkPrediction 1 Software\\Policies\\Mozilla\\Firefox NewTabPage 1 Software\\Policies\\Mozilla\\Firefox NoDefaultBookmarks 1 Software\\Policies\\Mozilla\\Firefox OfferToSaveLogins 1 Software\\Policies\\Mozilla\\Firefox OfferToSaveLoginsDefault 1 Software\\Policies\\Mozilla\\Firefox OverrideFirstRunPage http://example.org Software\\Policies\\Mozilla\\Firefox OverridePostUpdatePage http://example.org Software\\Policies\\Mozilla\\Firefox PasswordManagerEnabled 1 Software\\Policies\\Mozilla\\Firefox Preferences { "accessibility.force_disabled": { "Value": 1, "Status": "default" }, "browser.cache.disk.parent_directory": { "Value": "SOME_NATIVE_PATH", "Status": "user" }, "browser.tabs.warnOnClose": { "Value": false, "Status": "locked" } } Software\\Policies\\Mozilla\\Firefox PrimaryPassword 1 Software\\Policies\\Mozilla\\Firefox PromptForDownloadLocation 1 Software\\Policies\\Mozilla\\Firefox\\RequestedLocales **delvals. Software\\Policies\\Mozilla\\Firefox\\RequestedLocales 1 de Software\\Policies\\Mozilla\\Firefox\\RequestedLocales 2 en-US Software\\Policies\\Mozilla\\Firefox SSLVersionMax tls1.3 Software\\Policies\\Mozilla\\Firefox SSLVersionMin tls1.3 Software\\Policies\\Mozilla\\Firefox SearchBar unified Software\\Policies\\Mozilla\\Firefox\\Authentication Locked 1 Software\\Policies\\Mozilla\\Firefox\\Authentication PrivateBrowsing 1 Software\\Policies\\Mozilla\\Firefox\\Authentication\\AllowNonFQDN NTLM 1 Software\\Policies\\Mozilla\\Firefox\\Authentication\\AllowNonFQDN SPNEGO 1 Software\\Policies\\Mozilla\\Firefox\\Authentication\\AllowProxies NTLM 1 Software\\Policies\\Mozilla\\Firefox\\Authentication\\AllowProxies SPNEGO 1 Software\\Policies\\Mozilla\\Firefox\\Authentication\\Delegated **delvals. Software\\Policies\\Mozilla\\Firefox\\Authentication\\Delegated 1 mydomain.com Software\\Policies\\Mozilla\\Firefox\\Authentication\\Delegated 1 https://myotherdomain.com Software\\Policies\\Mozilla\\Firefox\\Authentication\\NTLM **delvals. Software\\Policies\\Mozilla\\Firefox\\Authentication\\NTLM 1 mydomain.com Software\\Policies\\Mozilla\\Firefox\\Authentication\\NTLM 1 https://myotherdomain.com Software\\Policies\\Mozilla\\Firefox\\Authentication\\SPNEGO **delvals. Software\\Policies\\Mozilla\\Firefox\\Authentication\\SPNEGO 1 mydomain.com Software\\Policies\\Mozilla\\Firefox\\Authentication\\SPNEGO 1 https://myotherdomain.com Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\1 Title Example Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\1 URL https://example.com Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\1 Favicon https://example.com/favicon.ico Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\1 Placement menu Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\1 Folder FolderName Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\10 Title Samba Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\10 URL www.samba.org Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\10 Favicon Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\10 Placement toolbar Software\\Policies\\Mozilla\\Firefox\\Bookmarks\\10 Folder Software\\Policies\\Mozilla\\Firefox\\Cookies AcceptThirdParty never Software\\Policies\\Mozilla\\Firefox\\Cookies Default 1 Software\\Policies\\Mozilla\\Firefox\\Cookies ExpireAtSessionEnd 1 Software\\Policies\\Mozilla\\Firefox\\Cookies Locked 1 Software\\Policies\\Mozilla\\Firefox\\Cookies RejectTracker 1 Software\\Policies\\Mozilla\\Firefox\\Cookies\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\Cookies\\Allow 1 http://example.org/ Software\\Policies\\Mozilla\\Firefox\\Cookies\\AllowSession **delvals. Software\\Policies\\Mozilla\\Firefox\\Cookies\\AllowSession 1 http://example.edu/ Software\\Policies\\Mozilla\\Firefox\\Cookies\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\Cookies\\Block 1 http://example.edu/ Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_DHE_RSA_WITH_AES_128_CBC_SHA 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_DHE_RSA_WITH_AES_256_CBC_SHA 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_RSA_WITH_3DES_EDE_CBC_SHA 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_RSA_WITH_AES_128_CBC_SHA 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_RSA_WITH_AES_128_GCM_SHA256 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_RSA_WITH_AES_256_CBC_SHA 1 Software\\Policies\\Mozilla\\Firefox\\DisabledCiphers TLS_RSA_WITH_AES_256_GCM_SHA384 1 Software\\Policies\\Mozilla\\Firefox\\DisableSecurityBypass InvalidCertificate 1 Software\\Policies\\Mozilla\\Firefox\\DisableSecurityBypass SafeBrowsing 1 Software\\Policies\\Mozilla\\Firefox\\DNSOverHTTPS Enabled 1 Software\\Policies\\Mozilla\\Firefox\\DNSOverHTTPS Locked 1 Software\\Policies\\Mozilla\\Firefox\\DNSOverHTTPS ProviderURL URL_TO_ALTERNATE_PROVIDER Software\\Policies\\Mozilla\\Firefox\\DNSOverHTTPS\\ExcludedDomains **delvals. Software\\Policies\\Mozilla\\Firefox\\DNSOverHTTPS\\ExcludedDomains 1 example.com Software\\Policies\\Mozilla\\Firefox\\EnableTrackingProtection Value 1 Software\\Policies\\Mozilla\\Firefox\\EnableTrackingProtection Cryptomining 1 Software\\Policies\\Mozilla\\Firefox\\EnableTrackingProtection Fingerprinting 1 Software\\Policies\\Mozilla\\Firefox\\EnableTrackingProtection Locked 1 Software\\Policies\\Mozilla\\Firefox\\EnableTrackingProtection\\Exceptions **delvals. Software\\Policies\\Mozilla\\Firefox\\EnableTrackingProtection\\Exceptions 1 https://example.com Software\\Policies\\Mozilla\\Firefox\\EncryptedMediaExtensions Enabled 1 Software\\Policies\\Mozilla\\Firefox\\EncryptedMediaExtensions Locked 1 Software\\Policies\\Mozilla\\Firefox\\Extensions\\Install **delvals. Software\\Policies\\Mozilla\\Firefox\\Extensions\\Install 1 https://addons.mozilla.org/firefox/downloads/somefile.xpi Software\\Policies\\Mozilla\\Firefox\\Extensions\\Install 2 //path/to/xpi Software\\Policies\\Mozilla\\Firefox\\Extensions\\Locked **delvals. Software\\Policies\\Mozilla\\Firefox\\Extensions\\Locked 1 addon_id@mozilla.org Software\\Policies\\Mozilla\\Firefox\\Extensions\\Uninstall **delvals. Software\\Policies\\Mozilla\\Firefox\\Extensions\\Uninstall 1 bad_addon_id@mozilla.org Software\\Policies\\Mozilla\\Firefox\\FirefoxHome Search 1 Software\\Policies\\Mozilla\\Firefox\\FirefoxHome TopSites 1 Software\\Policies\\Mozilla\\Firefox\\FirefoxHome Highlights 1 Software\\Policies\\Mozilla\\Firefox\\FirefoxHome Pocket 1 Software\\Policies\\Mozilla\\Firefox\\FirefoxHome Snippets 1 Software\\Policies\\Mozilla\\Firefox\\FirefoxHome Locked 1 Software\\Policies\\Mozilla\\Firefox\\FlashPlugin Default 1 Software\\Policies\\Mozilla\\Firefox\\FlashPlugin Locked 1 Software\\Policies\\Mozilla\\Firefox\\FlashPlugin\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\FlashPlugin\\Allow 1 http://example.org/ Software\\Policies\\Mozilla\\Firefox\\FlashPlugin\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\FlashPlugin\\Block 1 http://example.edu/ Software\\Policies\\Mozilla\\Firefox\\Homepage StartPage homepage Software\\Policies\\Mozilla\\Firefox\\Homepage URL http://example.com/ Software\\Policies\\Mozilla\\Firefox\\Homepage Locked 1 Software\\Policies\\Mozilla\\Firefox\\Homepage\\Additional **delvals. Software\\Policies\\Mozilla\\Firefox\\Homepage\\Additional 1 http://example.org/ Software\\Policies\\Mozilla\\Firefox\\Homepage\\Additional 2 http://example.edu/ Software\\Policies\\Mozilla\\Firefox\\InstallAddonsPermission Default 1 Software\\Policies\\Mozilla\\Firefox\\InstallAddonsPermission\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\InstallAddonsPermission\\Allow 1 http://example.org/ Software\\Policies\\Mozilla\\Firefox\\InstallAddonsPermission\\Allow 2 http://example.edu/ Software\\Policies\\Mozilla\\Firefox\\LocalFileLinks **delvals. Software\\Policies\\Mozilla\\Firefox\\LocalFileLinks 1 http://example.org/ Software\\Policies\\Mozilla\\Firefox\\LocalFileLinks 2 http://example.edu/ Software\\Policies\\Mozilla\\Firefox\\PDFjs EnablePermissions 1 Software\\Policies\\Mozilla\\Firefox\\PDFjs Enabled 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Autoplay Default block-audio Software\\Policies\\Mozilla\\Firefox\\Permissions\\Autoplay Locked 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Autoplay\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Autoplay\\Allow 1 https://example.org Software\\Policies\\Mozilla\\Firefox\\Permissions\\Autoplay\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Autoplay\\Block 1 https://example.edu Software\\Policies\\Mozilla\\Firefox\\Permissions\\Camera BlockNewRequests 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Camera Locked 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Camera\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Camera\\Allow 1 https://example.org Software\\Policies\\Mozilla\\Firefox\\Permissions\\Camera\\Allow 2 https://example.org:1234 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Camera\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Camera\\Block 1 https://example.edu Software\\Policies\\Mozilla\\Firefox\\Permissions\\Location BlockNewRequests 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Location Locked 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Location\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Location\\Allow 1 https://example.org Software\\Policies\\Mozilla\\Firefox\\Permissions\\Location\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Location\\Block 1 https://example.edu Software\\Policies\\Mozilla\\Firefox\\Permissions\\Microphone BlockNewRequests 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Microphone Locked 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Microphone\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Microphone\\Allow 1 https://example.org Software\\Policies\\Mozilla\\Firefox\\Permissions\\Microphone\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Microphone\\Block 1 https://example.edu Software\\Policies\\Mozilla\\Firefox\\Permissions\\Notifications BlockNewRequests 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Notifications Locked 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\Notifications\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Notifications\\Allow 1 https://example.org Software\\Policies\\Mozilla\\Firefox\\Permissions\\Notifications\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\Notifications\\Block 1 https://example.edu Software\\Policies\\Mozilla\\Firefox\\Permissions\\VirtualReality BlockNewRequests 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\VirtualReality Locked 1 Software\\Policies\\Mozilla\\Firefox\\Permissions\\VirtualReality\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\VirtualReality\\Allow 1 https://example.org Software\\Policies\\Mozilla\\Firefox\\Permissions\\VirtualReality\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\Permissions\\VirtualReality\\Block 1 https://example.edu Software\\Policies\\Mozilla\\Firefox\\PictureInPicture Enabled 1 Software\\Policies\\Mozilla\\Firefox\\PictureInPicture Locked 1 Software\\Policies\\Mozilla\\Firefox\\PopupBlocking Default 1 Software\\Policies\\Mozilla\\Firefox\\PopupBlocking Locked 1 Software\\Policies\\Mozilla\\Firefox\\PopupBlocking\\Allow **delvals. Software\\Policies\\Mozilla\\Firefox\\PopupBlocking\\Allow 1 http://example.org/ Software\\Policies\\Mozilla\\Firefox\\PopupBlocking\\Allow 2 http://example.edu/ Software\\Policies\\Mozilla\\Firefox\\Proxy Locked 1 Software\\Policies\\Mozilla\\Firefox\\Proxy Mode autoDetect Software\\Policies\\Mozilla\\Firefox\\Proxy HTTPProxy hostname Software\\Policies\\Mozilla\\Firefox\\Proxy UseHTTPProxyForAllProtocols 1 Software\\Policies\\Mozilla\\Firefox\\Proxy SSLProxy hostname Software\\Policies\\Mozilla\\Firefox\\Proxy FTPProxy hostname Software\\Policies\\Mozilla\\Firefox\\Proxy SOCKSProxy hostname Software\\Policies\\Mozilla\\Firefox\\Proxy SOCKSVersion 5 Software\\Policies\\Mozilla\\Firefox\\Proxy Passthrough <local> Software\\Policies\\Mozilla\\Firefox\\Proxy AutoConfigURL URL_TO_AUTOCONFIG Software\\Policies\\Mozilla\\Firefox\\Proxy AutoLogin 1 Software\\Policies\\Mozilla\\Firefox\\Proxy UseProxyForDNS 1 Software\\Policies\\Mozilla\\Firefox SanitizeOnShutdown 1 Software\\Policies\\Mozilla\\Firefox\\SearchEngines Default Google Software\\Policies\\Mozilla\\Firefox\\SearchEngines PreventInstalls 1 Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Add\\1 Name Example1 Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Add\\1 URLTemplate https://www.example.org/q={searchTerms} Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Add\\1 Method POST Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Add\\1 IconURL https://www.example.org/favicon.ico Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Add\\1 Alias example Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Add\\1 Description Description Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Add\\1 SuggestURLTemplate https://www.example.org/suggestions/q={searchTerms} Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Add\\1 PostData name=value&q={searchTerms} Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Remove **delvals. Software\\Policies\\Mozilla\\Firefox\\SearchEngines\\Remove 1 Bing Software\\Policies\\Mozilla\\Firefox\\SupportMenu Title Support Menu Software\\Policies\\Mozilla\\Firefox\\SupportMenu URL http://example.com/support Software\\Policies\\Mozilla\\Firefox\\SupportMenu AccessKey S Software\\Policies\\Mozilla\\Firefox\\UserMessaging ExtensionRecommendations 1 Software\\Policies\\Mozilla\\Firefox\\UserMessaging FeatureRecommendations 1 Software\\Policies\\Mozilla\\Firefox\\UserMessaging WhatsNew 1 Software\\Policies\\Mozilla\\Firefox\\UserMessaging UrlbarInterventions 1 Software\\Policies\\Mozilla\\Firefox\\UserMessaging SkipOnboarding 1 Software\\Policies\\Mozilla\\Firefox\\WebsiteFilter\\Block **delvals. Software\\Policies\\Mozilla\\Firefox\\WebsiteFilter\\Block 1 <all_urls> Software\\Policies\\Mozilla\\Firefox\\WebsiteFilter\\Exceptions **delvals. Software\\Policies\\Mozilla\\Firefox\\WebsiteFilter\\Exceptions 1 http://example.org/* Software\\Policies\\Mozilla\\Firefox AllowedDomainsForApps managedfirefox.com,example.com Software\\Policies\\Mozilla\\Firefox BackgroundAppUpdate 1 Software\\Policies\\Mozilla\\Firefox\\Certificates ImportEnterpriseRoots 1 Software\\Policies\\Mozilla\\Firefox\\Certificates\\Install **delvals. Software\\Policies\\Mozilla\\Firefox\\Certificates\\Install 1 cert1.der Software\\Policies\\Mozilla\\Firefox\\Certificates\\Install 2 /home/username/cert2.pem Software\\Policies\\Mozilla\\Firefox\\SecurityDevices NAME_OF_DEVICE PATH_TO_LIBRARY_FOR_DEVICE Software\\Policies\\Mozilla\\Firefox ShowHomeButton 1 Software\\Policies\\Mozilla\\Firefox AutoLaunchProtocolsFromOrigins [{"protocol": "zoommtg", "allowed_origins": ["https://somesite.zoom.us"]}] """ firefox_json_expected = \ """ { "policies": { "AppAutoUpdate": true, "AllowedDomainsForApps": "managedfirefox.com,example.com", "AppUpdateURL": "https://yoursite.com", "Authentication": { "SPNEGO": [ "mydomain.com", "https://myotherdomain.com" ], "Delegated": [ "mydomain.com", "https://myotherdomain.com" ], "NTLM": [ "mydomain.com", "https://myotherdomain.com" ], "AllowNonFQDN": { "SPNEGO": true, "NTLM": true }, "AllowProxies": { "SPNEGO": true, "NTLM": true }, "Locked": true, "PrivateBrowsing": true }, "AutoLaunchProtocolsFromOrigins": [ { "protocol": "zoommtg", "allowed_origins": [ "https://somesite.zoom.us" ] } ], "BackgroundAppUpdate": true, "BlockAboutAddons": true, "BlockAboutConfig": true, "BlockAboutProfiles": true, "BlockAboutSupport": true, "Bookmarks": [ { "Title": "Example", "URL": "https://example.com", "Favicon": "https://example.com/favicon.ico", "Placement": "menu", "Folder": "FolderName" }, { "Title": "Samba", "URL": "www.samba.org", "Favicon": "", "Placement": "toolbar", "Folder": "" } ], "CaptivePortal": true, "Certificates": { "ImportEnterpriseRoots": true, "Install": [ "cert1.der", "/home/username/cert2.pem" ] }, "Cookies": { "Allow": [ "http://example.org/" ], "AllowSession": [ "http://example.edu/" ], "Block": [ "http://example.edu/" ], "Default": true, "AcceptThirdParty": "never", "ExpireAtSessionEnd": true, "RejectTracker": true, "Locked": true }, "DisableSetDesktopBackground": true, "DisableMasterPasswordCreation": true, "DisableAppUpdate": true, "DisableBuiltinPDFViewer": true, "DisabledCiphers": { "TLS_DHE_RSA_WITH_AES_128_CBC_SHA": true, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA": true, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": true, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": true, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": true, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": true, "TLS_RSA_WITH_AES_128_CBC_SHA": true, "TLS_RSA_WITH_AES_256_CBC_SHA": true, "TLS_RSA_WITH_3DES_EDE_CBC_SHA": true, "TLS_RSA_WITH_AES_128_GCM_SHA256": true, "TLS_RSA_WITH_AES_256_GCM_SHA384": true }, "DisableDefaultBrowserAgent": true, "DisableDeveloperTools": true, "DisableFeedbackCommands": true, "DisableFirefoxScreenshots": true, "DisableFirefoxAccounts": true, "DisableFirefoxStudies": true, "DisableForgetButton": true, "DisableFormHistory": true, "DisablePasswordReveal": true, "DisablePocket": true, "DisablePrivateBrowsing": true, "DisableProfileImport": true, "DisableProfileRefresh": true, "DisableSafeMode": true, "DisableSecurityBypass": { "InvalidCertificate": true, "SafeBrowsing": true }, "DisableSystemAddonUpdate": true, "DisableTelemetry": true, "DisplayBookmarksToolbar": true, "DisplayMenuBar": "default-on", "DNSOverHTTPS": { "Enabled": true, "ProviderURL": "URL_TO_ALTERNATE_PROVIDER", "Locked": true, "ExcludedDomains": [ "example.com" ] }, "DontCheckDefaultBrowser": true, "EnableTrackingProtection": { "Value": true, "Locked": true, "Cryptomining": true, "Fingerprinting": true, "Exceptions": [ "https://example.com" ] }, "EncryptedMediaExtensions": { "Enabled": true, "Locked": true }, "Extensions": { "Install": [ "https://addons.mozilla.org/firefox/downloads/somefile.xpi", "//path/to/xpi" ], "Uninstall": [ "bad_addon_id@mozilla.org" ], "Locked": [ "addon_id@mozilla.org" ] }, "ExtensionSettings": { "*": { "blocked_install_message": "Custom error message.", "install_sources": [ "about:addons", "https://addons.mozilla.org/" ], "installation_mode": "blocked", "allowed_types": [ "extension" ] }, "uBlock0@raymondhill.net": { "installation_mode": "force_installed", "install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi" }, "https-everywhere@eff.org": { "installation_mode": "allowed" } }, "ExtensionUpdate": true, "FlashPlugin": { "Allow": [ "http://example.org/" ], "Block": [ "http://example.edu/" ], "Default": true, "Locked": true }, "Handlers": { "mimeTypes": { "application/msword": { "action": "useSystemDefault", "ask": true } }, "schemes": { "mailto": { "action": "useHelperApp", "ask": true, "handlers": [ { "name": "Gmail", "uriTemplate": "https://mail.google.com/mail/?extsrc=mailto&url=%s" } ] } }, "extensions": { "pdf": { "action": "useHelperApp", "ask": true, "handlers": [ { "name": "Adobe Acrobat", "path": "/usr/bin/acroread" } ] } } }, "FirefoxHome": { "Search": true, "TopSites": true, "Highlights": true, "Pocket": true, "Snippets": true, "Locked": true }, "HardwareAcceleration": true, "Homepage": { "URL": "http://example.com/", "Locked": true, "Additional": [ "http://example.org/", "http://example.edu/" ], "StartPage": "homepage" }, "InstallAddonsPermission": { "Allow": [ "http://example.org/", "http://example.edu/" ], "Default": true }, "LocalFileLinks": [ "http://example.org/", "http://example.edu/" ], "ManagedBookmarks": [ { "toplevel_name": "My managed bookmarks folder" }, { "url": "example.com", "name": "Example" }, { "name": "Mozilla links", "children": [ { "url": "https://mozilla.org", "name": "Mozilla.org" }, { "url": "https://support.mozilla.org/", "name": "SUMO" } ] } ], "PrimaryPassword": true, "NoDefaultBookmarks": true, "OfferToSaveLogins": true, "OfferToSaveLoginsDefault": true, "OverrideFirstRunPage": "http://example.org", "OverridePostUpdatePage": "http://example.org", "PasswordManagerEnabled": true, "PSFjs": { "Enabled": true, "EnablePermissions": true }, "Permissions": { "Camera": { "Allow": [ "https://example.org", "https://example.org:1234" ], "Block": [ "https://example.edu" ], "BlockNewRequests": true, "Locked": true }, "Microphone": { "Allow": [ "https://example.org" ], "Block": [ "https://example.edu" ], "BlockNewRequests": true, "Locked": true }, "Location": { "Allow": [ "https://example.org" ], "Block": [ "https://example.edu" ], "BlockNewRequests": true, "Locked": true }, "Notifications": { "Allow": [ "https://example.org" ], "Block": [ "https://example.edu" ], "BlockNewRequests": true, "Locked": true }, "Autoplay": { "Allow": [ "https://example.org" ], "Block": [ "https://example.edu" ], "Default": "block-audio", "Locked": true }, "VirtualReality": { "Allow": [ "https://example.org" ], "Block": [ "https://example.edu" ], "BlockNewRequests": true, "Locked": true } }, "PictureInPicture": { "Enabled": true, "Locked": true }, "PopupBlocking": { "Allow": [ "http://example.org/", "http://example.edu/" ], "Default": true, "Locked": true }, "Preferences": { "accessibility.force_disabled": { "Value": 1, "Status": "default" }, "browser.cache.disk.parent_directory": { "Value": "SOME_NATIVE_PATH", "Status": "user" }, "browser.tabs.warnOnClose": { "Value": false, "Status": "locked" } }, "PromptForDownloadLocation": true, "Proxy": { "Mode": "autoDetect", "Locked": true, "HTTPProxy": "hostname", "UseHTTPProxyForAllProtocols": true, "SSLProxy": "hostname", "FTPProxy": "hostname", "SOCKSProxy": "hostname", "SOCKSVersion": 5, "Passthrough": "", "AutoConfigURL": "URL_TO_AUTOCONFIG", "AutoLogin": true, "UseProxyForDNS": true }, "SanitizeOnShutdown": true, "SearchEngines": { "Add": [ { "Name": "Example1", "URLTemplate": "https://www.example.org/q={searchTerms}", "Method": "POST", "IconURL": "https://www.example.org/favicon.ico", "Alias": "example", "Description": "Description", "PostData": "name=value&q={searchTerms}", "SuggestURLTemplate": "https://www.example.org/suggestions/q={searchTerms}" } ], "Remove": [ "Bing" ], "Default": "Google", "PreventInstalls": true }, "SearchSuggestEnabled": true, "SecurityDevices": { "NAME_OF_DEVICE": "PATH_TO_LIBRARY_FOR_DEVICE" }, "ShowHomeButton": true, "SSLVersionMax": "tls1.3", "SSLVersionMin": "tls1.3", "SupportMenu": { "Title": "Support Menu", "URL": "http://example.com/support", "AccessKey": "S" }, "UserMessaging": { "WhatsNew": true, "ExtensionRecommendations": true, "FeatureRecommendations": true, "UrlbarInterventions": true, "SkipOnboarding": true }, "WebsiteFilter": { "Block": [ "" ], "Exceptions": [ "http://example.org/*" ] }, "DefaultDownloadDirectory": "${home}/Downloads", "DownloadDirectory": "${home}/Downloads", "NetworkPrediction": true, "NewTabPage": true, "RequestedLocales": ["de", "en-US"], "SearchBar": "unified" } } """ chromium_reg_pol = \ br""" Software\Policies\Google\Chrome AbusiveExperienceInterventionEnforce 1 Software\Policies\Google\Chrome AccessibilityImageLabelsEnabled 0 Software\Policies\Google\Chrome AdditionalDnsQueryTypesEnabled 1 Software\Policies\Google\Chrome AdsSettingForIntrusiveAdsSites 1 Software\Policies\Google\Chrome AdvancedProtectionAllowed 1 Software\Policies\Google\Chrome AllowCrossOriginAuthPrompt 0 Software\Policies\Google\Chrome AllowDeletingBrowserHistory 1 Software\Policies\Google\Chrome AllowDinosaurEasterEgg 0 Software\Policies\Google\Chrome AllowFileSelectionDialogs 1 Software\Policies\Google\Chrome AllowSyncXHRInPageDismissal 0 Software\Policies\Google\Chrome AllowedDomainsForApps managedchrome.com,example.com Software\Policies\Google\Chrome AlternateErrorPagesEnabled 1 Software\Policies\Google\Chrome AlternativeBrowserPath ${ie} Software\Policies\Google\Chrome AlwaysOpenPdfExternally 1 Software\Policies\Google\Chrome AmbientAuthenticationInPrivateModesEnabled 0 Software\Policies\Google\Chrome AppCacheForceEnabled 0 Software\Policies\Google\Chrome ApplicationLocaleValue en Software\Policies\Google\Chrome AudioCaptureAllowed 0 Software\Policies\Google\Chrome AudioProcessHighPriorityEnabled 1 Software\Policies\Google\Chrome AudioSandboxEnabled 1 Software\Policies\Google\Chrome AuthNegotiateDelegateAllowlist foobar.example.com Software\Policies\Google\Chrome AuthSchemes basic,digest,ntlm,negotiate Software\Policies\Google\Chrome AuthServerAllowlist *.example.com,example.com Software\Policies\Google\Chrome AutoLaunchProtocolsFromOrigins [{"allowed_origins": ["example.com", "http://www.example.com:8080"], "protocol": "spotify"}, {"allowed_origins": ["https://example.com", "https://.mail.example.com"], "protocol": "teams"}, {"allowed_origins": ["*"], "protocol": "outlook"}] Software\Policies\Google\Chrome AutofillAddressEnabled 0 Software\Policies\Google\Chrome AutofillCreditCardEnabled 0 Software\Policies\Google\Chrome AutoplayAllowed 1 Software\Policies\Google\Chrome BackgroundModeEnabled 1 Software\Policies\Google\Chrome BasicAuthOverHttpEnabled 0 Software\Policies\Google\Chrome BlockExternalExtensions 1 Software\Policies\Google\Chrome BlockThirdPartyCookies 0 Software\Policies\Google\Chrome BookmarkBarEnabled 1 Software\Policies\Google\Chrome BrowserAddPersonEnabled 1 Software\Policies\Google\Chrome BrowserGuestModeEnabled 1 Software\Policies\Google\Chrome BrowserGuestModeEnforced 1 Software\Policies\Google\Chrome BrowserLabsEnabled 0 Software\Policies\Google\Chrome BrowserNetworkTimeQueriesEnabled 1 Software\Policies\Google\Chrome BrowserSignin 2 Software\Policies\Google\Chrome BrowserSwitcherChromePath ${chrome} Software\Policies\Google\Chrome BrowserSwitcherDelay 10000 Software\Policies\Google\Chrome BrowserSwitcherEnabled 1 Software\Policies\Google\Chrome BrowserSwitcherExternalGreylistUrl http://example.com/greylist.xml Software\Policies\Google\Chrome BrowserSwitcherExternalSitelistUrl http://example.com/sitelist.xml Software\Policies\Google\Chrome BrowserSwitcherKeepLastChromeTab 0 Software\Policies\Google\Chrome BrowserSwitcherUseIeSitelist 1 Software\Policies\Google\Chrome BrowserThemeColor #FFFFFF Software\Policies\Google\Chrome BrowsingDataLifetime [{"data_types": ["browsing_history"], "time_to_live_in_hours": 24}, {"data_types": ["password_signin", "autofill"], "time_to_live_in_hours": 12}] Software\Policies\Google\Chrome BuiltInDnsClientEnabled 1 Software\Policies\Google\Chrome CECPQ2Enabled 1 Software\Policies\Google\Chrome ChromeCleanupEnabled 1 Software\Policies\Google\Chrome ChromeCleanupReportingEnabled 1 Software\Policies\Google\Chrome ChromeVariations 1 Software\Policies\Google\Chrome ClickToCallEnabled 1 Software\Policies\Google\Chrome CloudManagementEnrollmentMandatory 1 Software\Policies\Google\Chrome CloudManagementEnrollmentToken 37185d02-e055-11e7-80c1-9a214cf093ae Software\Policies\Google\Chrome CloudPolicyOverridesPlatformPolicy 0 Software\Policies\Google\Chrome CloudPrintProxyEnabled 1 Software\Policies\Google\Chrome CloudPrintSubmitEnabled 1 Software\Policies\Google\Chrome CloudUserPolicyMerge 1 Software\Policies\Google\Chrome CommandLineFlagSecurityWarningsEnabled 1 Software\Policies\Google\Chrome ComponentUpdatesEnabled 1 Software\Policies\Google\Chrome DNSInterceptionChecksEnabled 1 Software\Policies\Google\Chrome DefaultBrowserSettingEnabled 1 Software\Policies\Google\Chrome DefaultCookiesSetting 1 Software\Policies\Google\Chrome DefaultFileHandlingGuardSetting 2 Software\Policies\Google\Chrome DefaultFileSystemReadGuardSetting 2 Software\Policies\Google\Chrome DefaultFileSystemWriteGuardSetting 2 Software\Policies\Google\Chrome DefaultGeolocationSetting 1 Software\Policies\Google\Chrome DefaultImagesSetting 1 Software\Policies\Google\Chrome DefaultInsecureContentSetting 2 Software\Policies\Google\Chrome DefaultJavaScriptSetting 1 Software\Policies\Google\Chrome DefaultNotificationsSetting 2 Software\Policies\Google\Chrome DefaultPopupsSetting 1 Software\Policies\Google\Chrome DefaultPrinterSelection { "kind": "cloud", "idPattern": ".*public", "namePattern": ".*Color" } Software\Policies\Google\Chrome DefaultSearchProviderContextMenuAccessAllowed 1 Software\Policies\Google\Chrome DefaultSearchProviderEnabled 1 Software\Policies\Google\Chrome DefaultSearchProviderIconURL https://search.my.company/favicon.ico Software\Policies\Google\Chrome DefaultSearchProviderImageURL https://search.my.company/searchbyimage/upload Software\Policies\Google\Chrome DefaultSearchProviderImageURLPostParams content={imageThumbnail},url={imageURL},sbisrc={SearchSource} Software\Policies\Google\Chrome DefaultSearchProviderKeyword mis Software\Policies\Google\Chrome DefaultSearchProviderName My Intranet Search Software\Policies\Google\Chrome DefaultSearchProviderNewTabURL https://search.my.company/newtab Software\Policies\Google\Chrome DefaultSearchProviderSearchURL https://search.my.company/search?q={searchTerms} Software\Policies\Google\Chrome DefaultSearchProviderSearchURLPostParams q={searchTerms},ie=utf-8,oe=utf-8 Software\Policies\Google\Chrome DefaultSearchProviderSuggestURL https://search.my.company/suggest?q={searchTerms} Software\Policies\Google\Chrome DefaultSearchProviderSuggestURLPostParams q={searchTerms},ie=utf-8,oe=utf-8 Software\Policies\Google\Chrome DefaultSensorsSetting 2 Software\Policies\Google\Chrome DefaultSerialGuardSetting 2 Software\Policies\Google\Chrome DefaultWebBluetoothGuardSetting 2 Software\Policies\Google\Chrome DefaultWebUsbGuardSetting 2 Software\Policies\Google\Chrome DeveloperToolsAvailability 2 Software\Policies\Google\Chrome Disable3DAPIs 0 Software\Policies\Google\Chrome DisableAuthNegotiateCnameLookup 0 Software\Policies\Google\Chrome DisablePrintPreview 0 Software\Policies\Google\Chrome DisableSafeBrowsingProceedAnyway 1 Software\Policies\Google\Chrome DisableScreenshots 1 Software\Policies\Google\Chrome DiskCacheDir ${user_home}/Chrome_cache Software\Policies\Google\Chrome DiskCacheSize 104857600 Software\Policies\Google\Chrome DnsOverHttpsMode off Software\Policies\Google\Chrome DnsOverHttpsTemplates https://dns.example.net/dns-query{?dns} Software\Policies\Google\Chrome DownloadDirectory /home/${user_name}/Downloads Software\Policies\Google\Chrome DownloadRestrictions 2 Software\Policies\Google\Chrome EditBookmarksEnabled 0 Software\Policies\Google\Chrome EnableAuthNegotiatePort 0 Software\Policies\Google\Chrome EnableDeprecatedPrivetPrinting 1 Software\Policies\Google\Chrome EnableMediaRouter 1 Software\Policies\Google\Chrome EnableOnlineRevocationChecks 0 Software\Policies\Google\Chrome EnterpriseHardwarePlatformAPIEnabled 1 Software\Policies\Google\Chrome ExtensionSettings {"*": {"allowed_types": ["hosted_app"], "blocked_install_message": "Custom error message.", "blocked_permissions": ["downloads", "bookmarks"], "install_sources": ["https://company-intranet/chromeapps"], "installation_mode": "blocked", "runtime_allowed_hosts": ["*://good.example.com"], "runtime_blocked_hosts": ["*://*.example.com"]}, "abcdefghijklmnopabcdefghijklmnop": {"blocked_permissions": ["history"], "installation_mode": "allowed", "minimum_version_required": "1.0.1", "toolbar_pin": "force_pinned"}, "bcdefghijklmnopabcdefghijklmnopa": {"allowed_permissions": ["downloads"], "installation_mode": "force_installed", "runtime_allowed_hosts": ["*://good.example.com"], "runtime_blocked_hosts": ["*://*.example.com"], "update_url": "https://example.com/update_url"}, "cdefghijklmnopabcdefghijklmnopab": {"blocked_install_message": "Custom error message.", "installation_mode": "blocked"}, "defghijklmnopabcdefghijklmnopabc,efghijklmnopabcdefghijklmnopabcd": {"blocked_install_message": "Custom error message.", "installation_mode": "blocked"}, "fghijklmnopabcdefghijklmnopabcde": {"blocked_install_message": "Custom removal message.", "installation_mode": "removed"}, "ghijklmnopabcdefghijklmnopabcdef": {"installation_mode": "force_installed", "override_update_url": true, "update_url": "https://example.com/update_url"}, "update_url:https://www.example.com/update.xml": {"allowed_permissions": ["downloads"], "blocked_permissions": ["wallpaper"], "installation_mode": "allowed"}} Software\Policies\Google\Chrome ExternalProtocolDialogShowAlwaysOpenCheckbox 1 Software\Policies\Google\Chrome FetchKeepaliveDurationSecondsOnShutdown 1 Software\Policies\Google\Chrome ForceEphemeralProfiles 1 Software\Policies\Google\Chrome ForceGoogleSafeSearch 0 Software\Policies\Google\Chrome ForceYouTubeRestrict 0 Software\Policies\Google\Chrome FullscreenAllowed 1 Software\Policies\Google\Chrome GloballyScopeHTTPAuthCacheEnabled 0 Software\Policies\Google\Chrome HardwareAccelerationModeEnabled 1 Software\Policies\Google\Chrome HeadlessMode 2 Software\Policies\Google\Chrome HideWebStoreIcon 1 Software\Policies\Google\Chrome HomepageIsNewTabPage 1 Software\Policies\Google\Chrome HomepageLocation https://www.chromium.org Software\Policies\Google\Chrome ImportAutofillFormData 1 Software\Policies\Google\Chrome ImportBookmarks 1 Software\Policies\Google\Chrome ImportHistory 1 Software\Policies\Google\Chrome ImportHomepage 1 Software\Policies\Google\Chrome ImportSavedPasswords 1 Software\Policies\Google\Chrome ImportSearchEngine 1 Software\Policies\Google\Chrome IncognitoModeAvailability 1 Software\Policies\Google\Chrome InsecureFormsWarningsEnabled 1 Software\Policies\Google\Chrome InsecurePrivateNetworkRequestsAllowed 0 Software\Policies\Google\Chrome IntensiveWakeUpThrottlingEnabled 1 Software\Policies\Google\Chrome IntranetRedirectBehavior 1 Software\Policies\Google\Chrome IsolateOrigins https://example.com/,https://othersite.org/ Software\Policies\Google\Chrome ManagedBookmarks [{"toplevel_name": "My managed bookmarks folder"}, {"name": "Google", "url": "google.com"}, {"name": "Youtube", "url": "youtube.com"}, {"children": [{"name": "Chromium", "url": "chromium.org"}, {"name": "Chromium Developers", "url": "dev.chromium.org"}], "name": "Chrome links"}] Software\Policies\Google\Chrome ManagedConfigurationPerOrigin [{"managed_configuration_hash": "asd891jedasd12ue9h", "managed_configuration_url": "https://gstatic.google.com/configuration.json", "origin": "https://www.google.com"}, {"managed_configuration_hash": "djio12easd89u12aws", "managed_configuration_url": "https://gstatic.google.com/configuration2.json", "origin": "https://www.example.com"}] Software\Policies\Google\Chrome MaxConnectionsPerProxy 32 Software\Policies\Google\Chrome MaxInvalidationFetchDelay 10000 Software\Policies\Google\Chrome MediaRecommendationsEnabled 1 Software\Policies\Google\Chrome MediaRouterCastAllowAllIPs 0 Software\Policies\Google\Chrome MetricsReportingEnabled 1 Software\Policies\Google\Chrome NTPCardsVisible 1 Software\Policies\Google\Chrome NTPCustomBackgroundEnabled 1 Software\Policies\Google\Chrome NativeMessagingUserLevelHosts 0 Software\Policies\Google\Chrome NetworkPredictionOptions 1 Software\Policies\Google\Chrome NewTabPageLocation https://www.chromium.org Software\Policies\Google\Chrome PasswordLeakDetectionEnabled 1 Software\Policies\Google\Chrome PasswordManagerEnabled 1 Software\Policies\Google\Chrome PasswordProtectionChangePasswordURL https://mydomain.com/change_password.html Software\Policies\Google\Chrome PasswordProtectionWarningTrigger 1 Software\Policies\Google\Chrome PaymentMethodQueryEnabled 1 Software\Policies\Google\Chrome PolicyAtomicGroupsEnabled 1 Software\Policies\Google\Chrome PolicyRefreshRate 3600000 Software\Policies\Google\Chrome PrintHeaderFooter 0 Software\Policies\Google\Chrome PrintPreviewUseSystemDefaultPrinter 0 Software\Policies\Google\Chrome PrintRasterizationMode 1 Software\Policies\Google\Chrome PrintingAllowedBackgroundGraphicsModes enabled Software\Policies\Google\Chrome PrintingBackgroundGraphicsDefault enabled Software\Policies\Google\Chrome PrintingEnabled 1 Software\Policies\Google\Chrome PrintingPaperSizeDefault {"custom_size": {"height": 297000, "width": 210000}, "name": "custom"} Software\Policies\Google\Chrome ProfilePickerOnStartupAvailability 0 Software\Policies\Google\Chrome PromotionalTabsEnabled 0 Software\Policies\Google\Chrome PromptForDownloadLocation 0 Software\Policies\Google\Chrome ProxySettings {"ProxyBypassList": "https://www.example1.com,https://www.example2.com,https://internalsite/", "ProxyMode": "direct", "ProxyPacUrl": "https://internal.site/example.pac", "ProxyServer": "123.123.123.123:8080", "ProxyServerMode": 2} Software\Policies\Google\Chrome QuicAllowed 1 Software\Policies\Google\Chrome RelaunchNotification 1 Software\Policies\Google\Chrome RelaunchNotificationPeriod 604800000 Software\Policies\Google\Chrome RemoteAccessHostAllowClientPairing 0 Software\Policies\Google\Chrome RemoteAccessHostAllowFileTransfer 0 Software\Policies\Google\Chrome RemoteAccessHostAllowRelayedConnection 0 Software\Policies\Google\Chrome RemoteAccessHostAllowRemoteAccessConnections 0 Software\Policies\Google\Chrome RemoteAccessHostAllowUiAccessForRemoteAssistance 1 Software\Policies\Google\Chrome RemoteAccessHostFirewallTraversal 0 Software\Policies\Google\Chrome RemoteAccessHostMaximumSessionDurationMinutes 1200 Software\Policies\Google\Chrome RemoteAccessHostRequireCurtain 0 Software\Policies\Google\Chrome RemoteAccessHostUdpPortRange 12400-12409 Software\Policies\Google\Chrome RendererCodeIntegrityEnabled 0 Software\Policies\Google\Chrome RequireOnlineRevocationChecksForLocalAnchors 0 Software\Policies\Google\Chrome RestoreOnStartup 4 Software\Policies\Google\Chrome RestrictSigninToPattern .*@example\.com Software\Policies\Google\Chrome RoamingProfileLocation ${roaming_app_data}\chrome-profile Software\Policies\Google\Chrome RoamingProfileSupportEnabled 1 Software\Policies\Google\Chrome SSLErrorOverrideAllowed 1 Software\Policies\Google\Chrome SSLVersionMin tls1 Software\Policies\Google\Chrome SafeBrowsingExtendedReportingEnabled 1 Software\Policies\Google\Chrome SafeBrowsingForTrustedSourcesEnabled 0 Software\Policies\Google\Chrome SafeBrowsingProtectionLevel 2 Software\Policies\Google\Chrome SafeSitesFilterBehavior 0 Software\Policies\Google\Chrome SavingBrowserHistoryDisabled 1 Software\Policies\Google\Chrome ScreenCaptureAllowed 0 Software\Policies\Google\Chrome ScrollToTextFragmentEnabled 0 Software\Policies\Google\Chrome SearchSuggestEnabled 1 Software\Policies\Google\Chrome SharedArrayBufferUnrestrictedAccessAllowed 1 Software\Policies\Google\Chrome SharedClipboardEnabled 1 Software\Policies\Google\Chrome ShowAppsShortcutInBookmarkBar 0 Software\Policies\Google\Chrome ShowCastIconInToolbar 0 Software\Policies\Google\Chrome ShowFullUrlsInAddressBar 0 Software\Policies\Google\Chrome ShowHomeButton 1 Software\Policies\Google\Chrome SignedHTTPExchangeEnabled 1 Software\Policies\Google\Chrome SigninInterceptionEnabled 1 Software\Policies\Google\Chrome SitePerProcess 1 Software\Policies\Google\Chrome SpellCheckServiceEnabled 0 Software\Policies\Google\Chrome SpellcheckEnabled 0 Software\Policies\Google\Chrome SuppressDifferentOriginSubframeDialogs 1 Software\Policies\Google\Chrome SuppressUnsupportedOSWarning 1 Software\Policies\Google\Chrome SyncDisabled 1 Software\Policies\Google\Chrome TargetBlankImpliesNoOpener 0 Software\Policies\Google\Chrome TaskManagerEndProcessEnabled 1 Software\Policies\Google\Chrome ThirdPartyBlockingEnabled 0 Software\Policies\Google\Chrome TotalMemoryLimitMb 2048 Software\Policies\Google\Chrome TranslateEnabled 1 Software\Policies\Google\Chrome TripleDESEnabled 0 Software\Policies\Google\Chrome UrlKeyedAnonymizedDataCollectionEnabled 1 Software\Policies\Google\Chrome UserAgentClientHintsEnabled 1 Software\Policies\Google\Chrome UserDataDir ${users}/${user_name}/Chrome Software\Policies\Google\Chrome UserDataSnapshotRetentionLimit 3 Software\Policies\Google\Chrome UserFeedbackAllowed 1 Software\Policies\Google\Chrome VideoCaptureAllowed 0 Software\Policies\Google\Chrome WPADQuickCheckEnabled 1 Software\Policies\Google\Chrome WebAppInstallForceList [{"create_desktop_shortcut": true, "default_launch_container": "window", "url": "https://www.google.com/maps"}, {"default_launch_container": "tab", "url": "https://docs.google.com"}, {"default_launch_container": "window", "fallback_app_name": "Editor", "url": "https://docs.google.com/editor"}] Software\Policies\Google\Chrome WebRtcAllowLegacyTLSProtocols 0 Software\Policies\Google\Chrome WebRtcEventLogCollectionAllowed 1 Software\Policies\Google\Chrome WebRtcIPHandling default Software\Policies\Google\Chrome WebRtcUdpPortRange 10000-11999 Software\Policies\Google\Chrome WebUsbAllowDevicesForUrls [{"devices": [{"product_id": 5678, "vendor_id": 1234}], "urls": ["https://google.com"]}] Software\Policies\Google\Chrome WindowOcclusionEnabled 1 Software\Policies\Google\Chrome\AlternativeBrowserParameters 1 -foreground Software\Policies\Google\Chrome\AlternativeBrowserParameters 2 -new-window Software\Policies\Google\Chrome\AlternativeBrowserParameters 3 ${url} Software\Policies\Google\Chrome\AlternativeBrowserParameters 4 -profile Software\Policies\Google\Chrome\AlternativeBrowserParameters 5 %HOME%\browser_profile Software\Policies\Google\Chrome\AudioCaptureAllowedUrls 1 https://www.example.com/ Software\Policies\Google\Chrome\AudioCaptureAllowedUrls 2 https://[*.]example.edu/ Software\Policies\Google\Chrome\AutoOpenAllowedForURLs 1 example.com Software\Policies\Google\Chrome\AutoOpenAllowedForURLs 2 https://ssl.server.com Software\Policies\Google\Chrome\AutoOpenAllowedForURLs 3 hosting.com/good_path Software\Policies\Google\Chrome\AutoOpenAllowedForURLs 4 https://server:8080/path Software\Policies\Google\Chrome\AutoOpenAllowedForURLs 5 .exact.hostname.com Software\Policies\Google\Chrome\AutoOpenFileTypes 1 exe Software\Policies\Google\Chrome\AutoOpenFileTypes 2 txt Software\Policies\Google\Chrome\AutoSelectCertificateForUrls 1 {"pattern":"https://www.example.com","filter":{"ISSUER":{"CN":"certificate issuer name", "L": "certificate issuer location", "O": "certificate issuer org", "OU": "certificate issuer org unit"}, "SUBJECT":{"CN":"certificate subject name", "L": "certificate subject location", "O": "certificate subject org", "OU": "certificate subject org unit"}}} Software\Policies\Google\Chrome\AutoplayAllowlist 1 https://www.example.com Software\Policies\Google\Chrome\AutoplayAllowlist 2 [*.]example.edu Software\Policies\Google\Chrome\BrowserSwitcherChromeParameters 1 --force-dark-mode Software\Policies\Google\Chrome\BrowserSwitcherUrlGreylist 1 ie.com Software\Policies\Google\Chrome\BrowserSwitcherUrlGreylist 2 !open-in-chrome.ie.com Software\Policies\Google\Chrome\BrowserSwitcherUrlGreylist 3 foobar.com/ie-only/ Software\Policies\Google\Chrome\BrowserSwitcherUrlList 1 ie.com Software\Policies\Google\Chrome\BrowserSwitcherUrlList 2 !open-in-chrome.ie.com Software\Policies\Google\Chrome\BrowserSwitcherUrlList 3 foobar.com/ie-only/ Software\Policies\Google\Chrome\CertificateTransparencyEnforcementDisabledForCas 1 sha256/AAAAAAAAAAAAAAAAAAAAAA== Software\Policies\Google\Chrome\CertificateTransparencyEnforcementDisabledForCas 2 sha256//////////////////////w== Software\Policies\Google\Chrome\CertificateTransparencyEnforcementDisabledForLegacyCas 1 sha256/AAAAAAAAAAAAAAAAAAAAAA== Software\Policies\Google\Chrome\CertificateTransparencyEnforcementDisabledForLegacyCas 2 sha256//////////////////////w== Software\Policies\Google\Chrome\CertificateTransparencyEnforcementDisabledForUrls 1 example.com Software\Policies\Google\Chrome\CertificateTransparencyEnforcementDisabledForUrls 2 .example.com Software\Policies\Google\Chrome\ClearBrowsingDataOnExitList 1 browsing_history Software\Policies\Google\Chrome\ClearBrowsingDataOnExitList 2 download_history Software\Policies\Google\Chrome\ClearBrowsingDataOnExitList 3 cookies_and_other_site_data Software\Policies\Google\Chrome\ClearBrowsingDataOnExitList 4 cached_images_and_files Software\Policies\Google\Chrome\ClearBrowsingDataOnExitList 5 password_signin Software\Policies\Google\Chrome\ClearBrowsingDataOnExitList 6 autofill Software\Policies\Google\Chrome\ClearBrowsingDataOnExitList 7 site_settings Software\Policies\Google\Chrome\ClearBrowsingDataOnExitList 8 hosted_app_data Software\Policies\Google\Chrome\CookiesAllowedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\CookiesAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\CookiesBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\CookiesBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\CookiesSessionOnlyForUrls 1 https://www.example.com Software\Policies\Google\Chrome\CookiesSessionOnlyForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\DefaultSearchProviderAlternateURLs 1 https://search.my.company/suggest#q={searchTerms} Software\Policies\Google\Chrome\DefaultSearchProviderAlternateURLs 2 https://search.my.company/suggest/search#q={searchTerms} Software\Policies\Google\Chrome\DefaultSearchProviderEncodings 1 UTF-8 Software\Policies\Google\Chrome\DefaultSearchProviderEncodings 2 UTF-16 Software\Policies\Google\Chrome\DefaultSearchProviderEncodings 3 GB2312 Software\Policies\Google\Chrome\DefaultSearchProviderEncodings 4 ISO-8859-1 Software\Policies\Google\Chrome\EnableExperimentalPolicies 1 ExtensionInstallAllowlist Software\Policies\Google\Chrome\EnableExperimentalPolicies 2 ExtensionInstallBlocklist Software\Policies\Google\Chrome\ExplicitlyAllowedNetworkPorts 1 10080 Software\Policies\Google\Chrome\ExtensionAllowedTypes 1 hosted_app Software\Policies\Google\Chrome\ExtensionInstallAllowlist 1 extension_id1 Software\Policies\Google\Chrome\ExtensionInstallAllowlist 2 extension_id2 Software\Policies\Google\Chrome\ExtensionInstallBlocklist 1 extension_id1 Software\Policies\Google\Chrome\ExtensionInstallBlocklist 2 extension_id2 Software\Policies\Google\Chrome\ExtensionInstallForcelist 1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;https://clients2.google.com/service/update2/crx Software\Policies\Google\Chrome\ExtensionInstallForcelist 2 abcdefghijklmnopabcdefghijklmnop Software\Policies\Google\Chrome\ExtensionInstallSources 1 https://corp.mycompany.com/* Software\Policies\Google\Chrome\FileHandlingAllowedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\FileHandlingAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\FileHandlingBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\FileHandlingBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\FileSystemReadAskForUrls 1 https://www.example.com Software\Policies\Google\Chrome\FileSystemReadAskForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\FileSystemReadBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\FileSystemReadBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\FileSystemWriteAskForUrls 1 https://www.example.com Software\Policies\Google\Chrome\FileSystemWriteAskForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\FileSystemWriteBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\FileSystemWriteBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\ForcedLanguages 1 en-US Software\Policies\Google\Chrome\HSTSPolicyBypassList 1 meet Software\Policies\Google\Chrome\ImagesAllowedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\ImagesAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\ImagesBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\ImagesBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\InsecureContentAllowedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\InsecureContentAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\InsecureContentBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\InsecureContentBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\InsecurePrivateNetworkRequestsAllowedForUrls 1 http://www.example.com:8080 Software\Policies\Google\Chrome\InsecurePrivateNetworkRequestsAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\JavaScriptAllowedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\JavaScriptAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\JavaScriptBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\JavaScriptBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\LegacySameSiteCookieBehaviorEnabledForDomainList 1 www.example.com Software\Policies\Google\Chrome\LegacySameSiteCookieBehaviorEnabledForDomainList 2 [*.]example.edu Software\Policies\Google\Chrome\LookalikeWarningAllowlistDomains 1 foo.example.com Software\Policies\Google\Chrome\LookalikeWarningAllowlistDomains 2 example.org Software\Policies\Google\Chrome\NativeMessagingAllowlist 1 com.native.messaging.host.name1 Software\Policies\Google\Chrome\NativeMessagingAllowlist 2 com.native.messaging.host.name2 Software\Policies\Google\Chrome\NativeMessagingBlocklist 1 com.native.messaging.host.name1 Software\Policies\Google\Chrome\NativeMessagingBlocklist 2 com.native.messaging.host.name2 Software\Policies\Google\Chrome\NotificationsAllowedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\NotificationsAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\NotificationsBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\NotificationsBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\OverrideSecurityRestrictionsOnInsecureOrigin 1 http://testserver.example.com/ Software\Policies\Google\Chrome\OverrideSecurityRestrictionsOnInsecureOrigin 2 *.example.org Software\Policies\Google\Chrome\PasswordProtectionLoginURLs 1 https://mydomain.com/login.html Software\Policies\Google\Chrome\PasswordProtectionLoginURLs 2 https://login.mydomain.com Software\Policies\Google\Chrome\PolicyDictionaryMultipleSourceMergeList 1 ExtensionSettings Software\Policies\Google\Chrome\PolicyListMultipleSourceMergeList 1 ExtensionInstallAllowlist Software\Policies\Google\Chrome\PolicyListMultipleSourceMergeList 2 ExtensionInstallBlocklist Software\Policies\Google\Chrome\PopupsAllowedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\PopupsAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\PopupsBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\PopupsBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\PrinterTypeDenyList 1 cloud Software\Policies\Google\Chrome\PrinterTypeDenyList 2 privet Software\Policies\Google\Chrome\RemoteAccessHostClientDomainList 1 my-awesome-domain.com Software\Policies\Google\Chrome\RemoteAccessHostClientDomainList 2 my-auxiliary-domain.com Software\Policies\Google\Chrome\RemoteAccessHostDomainList 1 my-awesome-domain.com Software\Policies\Google\Chrome\RemoteAccessHostDomainList 2 my-auxiliary-domain.com Software\Policies\Google\Chrome\RestoreOnStartupURLs 1 https://example.com Software\Policies\Google\Chrome\RestoreOnStartupURLs 2 https://www.chromium.org Software\Policies\Google\Chrome\SSLErrorOverrideAllowedForOrigins 1 https://www.example.com Software\Policies\Google\Chrome\SSLErrorOverrideAllowedForOrigins 2 [*.]example.edu Software\Policies\Google\Chrome\SafeBrowsingAllowlistDomains 1 mydomain.com Software\Policies\Google\Chrome\SafeBrowsingAllowlistDomains 2 myuniversity.edu Software\Policies\Google\Chrome\SecurityKeyPermitAttestation 1 https://example.com Software\Policies\Google\Chrome\SensorsAllowedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\SensorsAllowedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\SensorsBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\SensorsBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\SerialAskForUrls 1 https://www.example.com Software\Policies\Google\Chrome\SerialAskForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\SerialBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\SerialBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\SpellcheckLanguage 1 fr Software\Policies\Google\Chrome\SpellcheckLanguage 2 es Software\Policies\Google\Chrome\SpellcheckLanguageBlocklist 1 fr Software\Policies\Google\Chrome\SpellcheckLanguageBlocklist 2 es Software\Policies\Google\Chrome\SyncTypesListDisabled 1 bookmarks Software\Policies\Google\Chrome\URLAllowlist 1 example.com Software\Policies\Google\Chrome\URLAllowlist 2 https://ssl.server.com Software\Policies\Google\Chrome\URLAllowlist 3 hosting.com/good_path Software\Policies\Google\Chrome\URLAllowlist 4 https://server:8080/path Software\Policies\Google\Chrome\URLAllowlist 5 .exact.hostname.com Software\Policies\Google\Chrome\URLBlocklist 1 example.com Software\Policies\Google\Chrome\URLBlocklist 2 https://ssl.server.com Software\Policies\Google\Chrome\URLBlocklist 3 hosting.com/bad_path Software\Policies\Google\Chrome\URLBlocklist 4 https://server:8080/path Software\Policies\Google\Chrome\URLBlocklist 5 .exact.hostname.com Software\Policies\Google\Chrome\URLBlocklist 6 file://* Software\Policies\Google\Chrome\URLBlocklist 7 custom_scheme:* Software\Policies\Google\Chrome\URLBlocklist 8 * Software\Policies\Google\Chrome\VideoCaptureAllowedUrls 1 https://www.example.com/ Software\Policies\Google\Chrome\VideoCaptureAllowedUrls 2 https://[*.]example.edu/ Software\Policies\Google\Chrome\WebRtcLocalIpsAllowedUrls 1 https://www.example.com Software\Policies\Google\Chrome\WebRtcLocalIpsAllowedUrls 2 *example.com* Software\Policies\Google\Chrome\WebUsbAskForUrls 1 https://www.example.com Software\Policies\Google\Chrome\WebUsbAskForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\WebUsbBlockedForUrls 1 https://www.example.com Software\Policies\Google\Chrome\WebUsbBlockedForUrls 2 [*.]example.edu Software\Policies\Google\Chrome\Recommended AlternateErrorPagesEnabled 1 Software\Policies\Google\Chrome\Recommended ApplicationLocaleValue en Software\Policies\Google\Chrome\Recommended AutofillAddressEnabled 0 Software\Policies\Google\Chrome\Recommended AutofillCreditCardEnabled 0 Software\Policies\Google\Chrome\Recommended BackgroundModeEnabled 1 Software\Policies\Google\Chrome\Recommended BlockThirdPartyCookies 0 Software\Policies\Google\Chrome\Recommended BookmarkBarEnabled 1 Software\Policies\Google\Chrome\Recommended DefaultDownloadDirectory /home/${user_name}/Downloads Software\Policies\Google\Chrome\Recommended DownloadDirectory /home/${user_name}/Downloads Software\Policies\Google\Chrome\Recommended DownloadRestrictions 2 Software\Policies\Google\Chrome\Recommended HomepageIsNewTabPage 1 Software\Policies\Google\Chrome\Recommended HomepageLocation https://www.chromium.org Software\Policies\Google\Chrome\Recommended ImportAutofillFormData 1 Software\Policies\Google\Chrome\Recommended ImportBookmarks 1 Software\Policies\Google\Chrome\Recommended ImportHistory 1 Software\Policies\Google\Chrome\Recommended ImportSavedPasswords 1 Software\Policies\Google\Chrome\Recommended ImportSearchEngine 1 Software\Policies\Google\Chrome\Recommended MetricsReportingEnabled 1 Software\Policies\Google\Chrome\Recommended NetworkPredictionOptions 1 Software\Policies\Google\Chrome\Recommended PasswordLeakDetectionEnabled 1 Software\Policies\Google\Chrome\Recommended PasswordManagerEnabled 1 Software\Policies\Google\Chrome\Recommended PrintHeaderFooter 0 Software\Policies\Google\Chrome\Recommended PrintPreviewUseSystemDefaultPrinter 0 Software\Policies\Google\Chrome\Recommended RegisteredProtocolHandlers [{"default": true, "protocol": "mailto", "url": "https://mail.google.com/mail/?extsrc=mailto&url=%s"}] Software\Policies\Google\Chrome\Recommended RestoreOnStartup 4 Software\Policies\Google\Chrome\Recommended SafeBrowsingForTrustedSourcesEnabled 0 Software\Policies\Google\Chrome\Recommended SafeBrowsingProtectionLevel 2 Software\Policies\Google\Chrome\Recommended SearchSuggestEnabled 1 Software\Policies\Google\Chrome\Recommended ShowFullUrlsInAddressBar 0 Software\Policies\Google\Chrome\Recommended ShowHomeButton 1 Software\Policies\Google\Chrome\Recommended SpellCheckServiceEnabled 0 Software\Policies\Google\Chrome\Recommended TranslateEnabled 1 Software\Policies\Google\Chrome\Recommended\RestoreOnStartupURLs 1 https://example.com Software\Policies\Google\Chrome\Recommended\RestoreOnStartupURLs 2 https://www.chromium.org """ chromium_json_expected_managed = \ b""" { "FileSystemWriteAskForUrls": [ "https://www.example.com", "[*.]example.edu" ], "InsecureContentBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "DefaultSearchProviderImageURLPostParams": "content={imageThumbnail},url={imageURL},sbisrc={SearchSource}", "BrowserAddPersonEnabled": true, "DefaultSearchProviderImageURL": "https://search.my.company/searchbyimage/upload", "ShowHomeButton": true, "ClearBrowsingDataOnExitList": [ "browsing_history", "download_history", "cookies_and_other_site_data", "cached_images_and_files", "password_signin", "autofill", "site_settings", "hosted_app_data" ], "JavaScriptAllowedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "AmbientAuthenticationInPrivateModesEnabled": 0, "AllowFileSelectionDialogs": true, "PrintingAllowedBackgroundGraphicsModes": "enabled", "DnsOverHttpsTemplates": "https://dns.example.net/dns-query{?dns}", "ComponentUpdatesEnabled": true, "RemoteAccessHostAllowRemoteAccessConnections": false, "WindowOcclusionEnabled": true, "PrintPreviewUseSystemDefaultPrinter": false, "AutoLaunchProtocolsFromOrigins": [ { "allowed_origins": [ "example.com", "http://www.example.com:8080" ], "protocol": "spotify" }, { "allowed_origins": [ "https://example.com", "https://.mail.example.com" ], "protocol": "teams" }, { "allowed_origins": [ "*" ], "protocol": "outlook" } ], "ManagedConfigurationPerOrigin": [ { "origin": "https://www.google.com", "managed_configuration_hash": "asd891jedasd12ue9h", "managed_configuration_url": "https://gstatic.google.com/configuration.json" }, { "origin": "https://www.example.com", "managed_configuration_hash": "djio12easd89u12aws", "managed_configuration_url": "https://gstatic.google.com/configuration2.json" } ], "SyncTypesListDisabled": [ "bookmarks" ], "SecurityKeyPermitAttestation": [ "https://example.com" ], "DefaultSearchProviderSearchURL": "https://search.my.company/search?q={searchTerms}", "MetricsReportingEnabled": true, "MaxInvalidationFetchDelay": 10000, "AudioProcessHighPriorityEnabled": true, "ExtensionInstallForcelist": [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;https://clients2.google.com/service/update2/crx", "abcdefghijklmnopabcdefghijklmnop" ], "ExternalProtocolDialogShowAlwaysOpenCheckbox": true, "CookiesBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "BrowserSwitcherExternalSitelistUrl": "http://example.com/sitelist.xml", "AudioCaptureAllowedUrls": [ "https://www.example.com/", "https://[*.]example.edu/" ], "NTPCustomBackgroundEnabled": true, "BlockExternalExtensions": true, "BrowserSwitcherChromeParameters": [ "--force-dark-mode" ], "SafeSitesFilterBehavior": 0, "EnableOnlineRevocationChecks": false, "ImagesBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "InsecureFormsWarningsEnabled": true, "RelaunchNotificationPeriod": 604800000, "TotalMemoryLimitMb": 2048, "CloudManagementEnrollmentMandatory": true, "ClickToCallEnabled": true, "AppCacheForceEnabled": false, "UrlKeyedAnonymizedDataCollectionEnabled": true, "FullscreenAllowed": true, "AuthSchemes": "basic,digest,ntlm,negotiate", "PasswordLeakDetectionEnabled": true, "AuthServerAllowlist": "*.example.com,example.com", "AllowSyncXHRInPageDismissal": false, "PasswordProtectionChangePasswordURL": "https://mydomain.com/change_password.html", "MaxConnectionsPerProxy": 32, "RemoteAccessHostMaximumSessionDurationMinutes": 1200, "RemoteAccessHostAllowFileTransfer": false, "PrintRasterizationMode": 1, "CertificateTransparencyEnforcementDisabledForLegacyCas": [ "sha256/AAAAAAAAAAAAAAAAAAAAAA==", "sha256//////////////////////w==" ], "DefaultWebBluetoothGuardSetting": 2, "AutoplayAllowed": true, "BrowserSwitcherUrlList": [ "ie.com", "!open-in-chrome.ie.com", "foobar.com/ie-only/" ], "CertificateTransparencyEnforcementDisabledForUrls": [ "example.com", ".example.com" ], "SpellcheckLanguageBlocklist": [ "fr", "es" ], "PrintHeaderFooter": false, "ShowAppsShortcutInBookmarkBar": false, "SerialAskForUrls": [ "https://www.example.com", "[*.]example.edu" ], "ImagesAllowedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "ProfilePickerOnStartupAvailability": 0, "CommandLineFlagSecurityWarningsEnabled": true, "QuicAllowed": true, "IntensiveWakeUpThrottlingEnabled": true, "WPADQuickCheckEnabled": true, "SensorsAllowedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "NTPCardsVisible": true, "DefaultSearchProviderAlternateURLs": [ "https://search.my.company/suggest#q={searchTerms}", "https://search.my.company/suggest/search#q={searchTerms}" ], "DisableSafeBrowsingProceedAnyway": true, "DefaultFileSystemWriteGuardSetting": 2, "DefaultSearchProviderSuggestURL": "https://search.my.company/suggest?q={searchTerms}", "SSLErrorOverrideAllowed": true, "CloudPrintProxyEnabled": true, "BrowserSwitcherUrlGreylist": [ "ie.com", "!open-in-chrome.ie.com", "foobar.com/ie-only/" ], "BrowserNetworkTimeQueriesEnabled": true, "WebUsbAllowDevicesForUrls": [ { "urls": [ "https://google.com" ], "devices": [ { "vendor_id": 1234, "product_id": 5678 } ] } ], "TaskManagerEndProcessEnabled": true, "SuppressDifferentOriginSubframeDialogs": true, "UserDataDir": "${users}/${user_name}/Chrome", "CookiesAllowedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "SuppressUnsupportedOSWarning": true, "RequireOnlineRevocationChecksForLocalAnchors": false, "BrowsingDataLifetime": [ { "data_types": [ "browsing_history" ], "time_to_live_in_hours": 24 }, { "data_types": [ "password_signin", "autofill" ], "time_to_live_in_hours": 12 } ], "FileHandlingBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "AudioCaptureAllowed": false, "PromotionalTabsEnabled": false, "ShowFullUrlsInAddressBar": false, "EnableMediaRouter": true, "BrowserSwitcherDelay": 10000, "AllowDinosaurEasterEgg": false, "ImportSearchEngine": true, "PrintingBackgroundGraphicsDefault": "enabled", "TripleDESEnabled": false, "AutoplayAllowlist": [ "https://www.example.com", "[*.]example.edu" ], "RemoteAccessHostUdpPortRange": "12400-12409", "DefaultSearchProviderIconURL": "https://search.my.company/favicon.ico", "BrowserSwitcherChromePath": "${chrome}", "InsecureContentAllowedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "DefaultSearchProviderSearchURLPostParams": "q={searchTerms},ie=utf-8,oe=utf-8", "ForceGoogleSafeSearch": false, "UserFeedbackAllowed": true, "ForceYouTubeRestrict": 0, "ApplicationLocaleValue": "en", "RoamingProfileSupportEnabled": true, "AlternativeBrowserPath": "${ie}", "AlternativeBrowserParameters": [ "-foreground", "-new-window", "${url}", "-profile", "%HOME%\\\\browser_profile" ], "AdvancedProtectionAllowed": true, "EditBookmarksEnabled": false, "DefaultPrinterSelection": "{ \\"kind\\": \\"cloud\\", \\"idPattern\\": \\".*public\\", \\"namePattern\\": \\".*Color\\" }", "SSLVersionMin": "tls1", "SharedArrayBufferUnrestrictedAccessAllowed": true, "DefaultSerialGuardSetting": 2, "DefaultPopupsSetting": 1, "IntranetRedirectBehavior": 1, "RendererCodeIntegrityEnabled": false, "BrowserGuestModeEnforced": true, "HSTSPolicyBypassList": [ "meet" ], "DefaultWebUsbGuardSetting": 2, "CECPQ2Enabled": true, "RemoteAccessHostDomainList": [ "my-awesome-domain.com", "my-auxiliary-domain.com" ], "URLBlocklist": [ "example.com", "https://ssl.server.com", "hosting.com/bad_path", "https://server:8080/path", ".exact.hostname.com", "file://*", "custom_scheme:*", "*" ], "IsolateOrigins": "https://example.com/,https://othersite.org/", "ExtensionAllowedTypes": [ "hosted_app" ], "NativeMessagingBlocklist": [ "com.native.messaging.host.name1", "com.native.messaging.host.name2" ], "ExtensionSettings": { "abcdefghijklmnopabcdefghijklmnop": { "blocked_permissions": [ "history" ], "minimum_version_required": "1.0.1", "toolbar_pin": "force_pinned", "installation_mode": "allowed" }, "bcdefghijklmnopabcdefghijklmnopa": { "runtime_blocked_hosts": [ "*://*.example.com" ], "allowed_permissions": [ "downloads" ], "update_url": "https://example.com/update_url", "runtime_allowed_hosts": [ "*://good.example.com" ], "installation_mode": "force_installed" }, "update_url:https://www.example.com/update.xml": { "allowed_permissions": [ "downloads" ], "blocked_permissions": [ "wallpaper" ], "installation_mode": "allowed" }, "cdefghijklmnopabcdefghijklmnopab": { "blocked_install_message": "Custom error message.", "installation_mode": "blocked" }, "*": { "blocked_permissions": [ "downloads", "bookmarks" ], "installation_mode": "blocked", "runtime_blocked_hosts": [ "*://*.example.com" ], "blocked_install_message": "Custom error message.", "allowed_types": [ "hosted_app" ], "runtime_allowed_hosts": [ "*://good.example.com" ], "install_sources": [ "https://company-intranet/chromeapps" ] }, "defghijklmnopabcdefghijklmnopabc,efghijklmnopabcdefghijklmnopabcd": { "blocked_install_message": "Custom error message.", "installation_mode": "blocked" }, "fghijklmnopabcdefghijklmnopabcde": { "blocked_install_message": "Custom removal message.", "installation_mode": "removed" }, "ghijklmnopabcdefghijklmnopabcdef": { "update_url": "https://example.com/update_url", "override_update_url": true, "installation_mode": "force_installed" } }, "FileSystemReadAskForUrls": [ "https://www.example.com", "[*.]example.edu" ], "SpellCheckServiceEnabled": false, "ExtensionInstallSources": [ "https://corp.mycompany.com/*" ], "PrinterTypeDenyList": [ "cloud", "privet" ], "SharedClipboardEnabled": true, "BlockThirdPartyCookies": false, "MediaRouterCastAllowAllIPs": false, "DnsOverHttpsMode": "off", "SyncDisabled": true, "LookalikeWarningAllowlistDomains": [ "foo.example.com", "example.org" ], "UserDataSnapshotRetentionLimit": 3, "SafeBrowsingProtectionLevel": 2, "ScrollToTextFragmentEnabled": false, "ImportBookmarks": true, "DefaultBrowserSettingEnabled": true, "DefaultSearchProviderEnabled": true, "AdditionalDnsQueryTypesEnabled": true, "PolicyRefreshRate": 3600000, "PrintingPaperSizeDefault": { "custom_size": { "width": 210000, "height": 297000 }, "name": "custom" }, "RestoreOnStartup": 4, "PasswordProtectionWarningTrigger": 1, "ChromeCleanupEnabled": true, "AbusiveExperienceInterventionEnforce": true, "BasicAuthOverHttpEnabled": false, "EnableAuthNegotiatePort": false, "DefaultGeolocationSetting": 1, "PolicyDictionaryMultipleSourceMergeList": [ "ExtensionSettings" ], "AllowedDomainsForApps": "managedchrome.com,example.com", "DisableAuthNegotiateCnameLookup": false, "IncognitoModeAvailability": 1, "ChromeVariations": 1, "DefaultSearchProviderNewTabURL": "https://search.my.company/newtab", "SavingBrowserHistoryDisabled": true, "SpellcheckEnabled": false, "FileSystemWriteBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "BuiltInDnsClientEnabled": true, "SSLErrorOverrideAllowedForOrigins": [ "https://www.example.com", "[*.]example.edu" ], "WebRtcIPHandling": "default", "DefaultNotificationsSetting": 2, "PopupsAllowedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "TranslateEnabled": true, "DefaultSearchProviderEncodings": [ "UTF-8", "UTF-16", "GB2312", "ISO-8859-1" ], "DownloadRestrictions": 2, "PromptForDownloadLocation": false, "DisablePrintPreview": false, "NetworkPredictionOptions": 1, "FileSystemReadBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "AutoOpenFileTypes": [ "exe", "txt" ], "DownloadDirectory": "/home/${user_name}/Downloads", "ImportHomepage": true, "GloballyScopeHTTPAuthCacheEnabled": false, "CloudManagementEnrollmentToken": "37185d02-e055-11e7-80c1-9a214cf093ae", "ThirdPartyBlockingEnabled": false, "AdsSettingForIntrusiveAdsSites": 1, "FetchKeepaliveDurationSecondsOnShutdown": 1, "BookmarkBarEnabled": true, "DisableScreenshots": true, "AccessibilityImageLabelsEnabled": false, "RemoteAccessHostAllowUiAccessForRemoteAssistance": true, "PopupsBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "DefaultFileSystemReadGuardSetting": 2, "BrowserSignin": 2, "WebRtcAllowLegacyTLSProtocols": false, "PasswordManagerEnabled": true, "SafeBrowsingExtendedReportingEnabled": true, "CloudPolicyOverridesPlatformPolicy": false, "InsecurePrivateNetworkRequestsAllowedForUrls": [ "http://www.example.com:8080", "[*.]example.edu" ], "RelaunchNotification": 1, "AlwaysOpenPdfExternally": true, "DefaultFileHandlingGuardSetting": 2, "ForceEphemeralProfiles": true, "PasswordProtectionLoginURLs": [ "https://mydomain.com/login.html", "https://login.mydomain.com" ], "BrowserSwitcherExternalGreylistUrl": "http://example.com/greylist.xml", "BrowserGuestModeEnabled": true, "MediaRecommendationsEnabled": true, "WebRtcLocalIpsAllowedUrls": [ "https://www.example.com", "*example.com*" ], "DeveloperToolsAvailability": 2, "DNSInterceptionChecksEnabled": true, "DefaultSearchProviderContextMenuAccessAllowed": true, "RemoteAccessHostRequireCurtain": false, "PaymentMethodQueryEnabled": true, "HomepageLocation": "https://www.chromium.org", "WebUsbAskForUrls": [ "https://www.example.com", "[*.]example.edu" ], "RemoteAccessHostAllowClientPairing": false, "ProxySettings": { "ProxyMode": "direct", "ProxyPacUrl": "https://internal.site/example.pac", "ProxyServer": "123.123.123.123:8080", "ProxyServerMode": 2, "ProxyBypassList": "https://www.example1.com,https://www.example2.com,https://internalsite/" }, "AutofillCreditCardEnabled": false, "FileHandlingAllowedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "ChromeCleanupReportingEnabled": true, "AlternateErrorPagesEnabled": true, "WebRtcEventLogCollectionAllowed": true, "AutoSelectCertificateForUrls": [ "{\\"pattern\\":\\"https://www.example.com\\",\\"filter\\":{\\"ISSUER\\":{\\"CN\\":\\"certificate issuer name\\", \\"L\\": \\"certificate issuer location\\", \\"O\\": \\"certificate issuer org\\", \\"OU\\": \\"certificate issuer org unit\\"}, \\"SUBJECT\\":{\\"CN\\":\\"certificate subject name\\", \\"L\\": \\"certificate subject location\\", \\"O\\": \\"certificate subject org\\", \\"OU\\": \\"certificate subject org unit\\"}}}" ], "PolicyListMultipleSourceMergeList": [ "ExtensionInstallAllowlist", "ExtensionInstallBlocklist" ], "CertificateTransparencyEnforcementDisabledForCas": [ "sha256/AAAAAAAAAAAAAAAAAAAAAA==", "sha256//////////////////////w==" ], "CookiesSessionOnlyForUrls": [ "https://www.example.com", "[*.]example.edu" ], "SitePerProcess": true, "RemoteAccessHostFirewallTraversal": false, "DefaultSearchProviderSuggestURLPostParams": "q={searchTerms},ie=utf-8,oe=utf-8", "BackgroundModeEnabled": true, "DefaultJavaScriptSetting": 1, "ForcedLanguages": [ "en-US" ], "ManagedBookmarks": [ { "toplevel_name": "My managed bookmarks folder" }, { "url": "google.com", "name": "Google" }, { "url": "youtube.com", "name": "Youtube" }, { "children": [ { "url": "chromium.org", "name": "Chromium" }, { "url": "dev.chromium.org", "name": "Chromium Developers" } ], "name": "Chrome links" } ], "Disable3DAPIs": false, "CloudPrintSubmitEnabled": true, "DefaultCookiesSetting": 1, "ExtensionInstallBlocklist": [ "extension_id1", "extension_id2" ], "URLAllowlist": [ "example.com", "https://ssl.server.com", "hosting.com/good_path", "https://server:8080/path", ".exact.hostname.com" ], "ExplicitlyAllowedNetworkPorts": [ "10080" ], "HomepageIsNewTabPage": true, "SensorsBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "BrowserLabsEnabled": false, "NotificationsAllowedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "NativeMessagingUserLevelHosts": false, "AuthNegotiateDelegateAllowlist": "foobar.example.com", "CloudUserPolicyMerge": true, "OverrideSecurityRestrictionsOnInsecureOrigin": [ "http://testserver.example.com/", "*.example.org" ], "HideWebStoreIcon": true, "SafeBrowsingForTrustedSourcesEnabled": false, "NewTabPageLocation": "https://www.chromium.org", "DiskCacheSize": 104857600, "BrowserSwitcherUseIeSitelist": true, "WebRtcUdpPortRange": "10000-11999", "EnterpriseHardwarePlatformAPIEnabled": true, "AutoOpenAllowedForURLs": [ "example.com", "https://ssl.server.com", "hosting.com/good_path", "https://server:8080/path", ".exact.hostname.com" ], "NativeMessagingAllowlist": [ "com.native.messaging.host.name1", "com.native.messaging.host.name2" ], "DefaultSearchProviderName": "My Intranet Search", "JavaScriptBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "EnableExperimentalPolicies": [ "ExtensionInstallAllowlist", "ExtensionInstallBlocklist" ], "SafeBrowsingAllowlistDomains": [ "mydomain.com", "myuniversity.edu" ], "AutofillAddressEnabled": false, "AllowCrossOriginAuthPrompt": false, "SpellcheckLanguage": [ "fr", "es" ], "VideoCaptureAllowed": false, "ScreenCaptureAllowed": false, "VideoCaptureAllowedUrls": [ "https://www.example.com/", "https://[*.]example.edu/" ], "ImportHistory": true, "ShowCastIconInToolbar": false, "RestoreOnStartupURLs": [ "https://example.com", "https://www.chromium.org" ], "LegacySameSiteCookieBehaviorEnabledForDomainList": [ "www.example.com", "[*.]example.edu" ], "PrintingEnabled": true, "ImportSavedPasswords": true, "EnableDeprecatedPrivetPrinting": true, "InsecurePrivateNetworkRequestsAllowed": false, "HeadlessMode": 2, "PolicyAtomicGroupsEnabled": true, "HardwareAccelerationModeEnabled": true, "AllowDeletingBrowserHistory": true, "DefaultSearchProviderKeyword": "mis", "ExtensionInstallAllowlist": [ "extension_id1", "extension_id2" ], "WebAppInstallForceList": [ { "url": "https://www.google.com/maps", "create_desktop_shortcut": true, "default_launch_container": "window" }, { "url": "https://docs.google.com", "default_launch_container": "tab" }, { "url": "https://docs.google.com/editor", "fallback_app_name": "Editor", "default_launch_container": "window" } ], "DiskCacheDir": "${user_home}/Chrome_cache", "SignedHTTPExchangeEnabled": true, "SearchSuggestEnabled": true, "BrowserThemeColor": "#FFFFFF", "RestrictSigninToPattern": ".*@example\\\\.com", "DefaultInsecureContentSetting": 2, "DefaultSensorsSetting": 2, "AudioSandboxEnabled": true, "RemoteAccessHostAllowRelayedConnection": false, "RoamingProfileLocation": "${roaming_app_data}\\\\chrome-profile", "UserAgentClientHintsEnabled": true, "TargetBlankImpliesNoOpener": false, "BrowserSwitcherKeepLastChromeTab": false, "RemoteAccessHostClientDomainList": [ "my-awesome-domain.com", "my-auxiliary-domain.com" ], "NotificationsBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "SerialBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "DefaultImagesSetting": 1, "SigninInterceptionEnabled": true, "WebUsbBlockedForUrls": [ "https://www.example.com", "[*.]example.edu" ], "ImportAutofillFormData": true, "BrowserSwitcherEnabled": true } """ chromium_json_expected_recommended = \ b""" { "BackgroundModeEnabled": true, "RestoreOnStartup": 4, "RegisteredProtocolHandlers": [ { "default": true, "url": "https://mail.google.com/mail/?extsrc=mailto&url=%s", "protocol": "mailto" } ], "ShowHomeButton": true, "PrintHeaderFooter": false, "SafeBrowsingForTrustedSourcesEnabled": false, "ShowFullUrlsInAddressBar": false, "MetricsReportingEnabled": true, "SpellCheckServiceEnabled": false, "ImportSearchEngine": true, "DownloadRestrictions": 2, "NetworkPredictionOptions": 1, "DownloadDirectory": "/home/${user_name}/Downloads", "TranslateEnabled": true, "AutofillAddressEnabled": false, "BookmarkBarEnabled": true, "PrintPreviewUseSystemDefaultPrinter": false, "ApplicationLocaleValue": "en", "ImportHistory": true, "RestoreOnStartupURLs": [ "https://example.com", "https://www.chromium.org" ], "PasswordManagerEnabled": true, "ImportSavedPasswords": true, "DefaultDownloadDirectory": "/home/${user_name}/Downloads", "PasswordLeakDetectionEnabled": true, "SearchSuggestEnabled": true, "AlternateErrorPagesEnabled": true, "HomepageIsNewTabPage": true, "ImportAutofillFormData": true, "BlockThirdPartyCookies": false, "AutofillCreditCardEnabled": false, "HomepageLocation": "https://www.chromium.org", "SafeBrowsingProtectionLevel": 2, "ImportBookmarks": true } """ firewalld_reg_pol = \ br""" Software\Policies\Samba\Unix Settings\Firewalld Zones 1 Software\Policies\Samba\Unix Settings\Firewalld Rules 1 Software\Policies\Samba\Unix Settings\Firewalld\Rules Rules {"work": [{"rule": {"family": "ipv4"}, "source address": "172.25.1.7", "service name": "ftp", "reject": {}}]} Software\Policies\Samba\Unix Settings\Firewalld\Zones **delvals. Software\Policies\Samba\Unix Settings\Firewalld\Zones work work Software\Policies\Samba\Unix Settings\Firewalld\Zones home home """ drive_maps_xml = b""" """ empty_multi_sz_reg_pol = \ br""" KeyName ValueName """ multiple_values_multi_sz_reg_pol = \ br""" KeyName ValueName Value1 Value2 Value3 """ def days2rel_nttime(val): seconds = 60 minutes = 60 hours = 24 sam_add = 10000000 return -(val * seconds * minutes * hours * sam_add) def gpupdate(lp, arg): gpupdate = lp.get('gpo update command') gpupdate.append(arg) p = Popen(gpupdate, stdout=PIPE, stderr=PIPE) stdoutdata, stderrdata = p.communicate() print(stderrdata) return p.returncode def gpupdate_force(lp): return gpupdate(lp, '--force') def gpupdate_unapply(lp): return gpupdate(lp, '--unapply') def rsop(lp): return gpupdate(lp, '--rsop') def stage_file(path, data): dirname = os.path.dirname(path) if not os.path.exists(dirname): try: os.makedirs(dirname) except OSError as e: if not (e.errno == errno.EEXIST and os.path.isdir(dirname)): return False if os.path.exists(path): os.rename(path, '%s.bak' % path) with NamedTemporaryFile(delete=False, dir=os.path.dirname(path)) as f: f.write(get_bytes(data)) os.rename(f.name, path) os.chmod(path, 0o644) return True def unstage_file(path): backup = '%s.bak' % path if os.path.exists(backup): os.rename(backup, path) elif os.path.exists(path): os.remove(path) class GPOTests(tests.TestCase): def setUp(self): super().setUp() self.server = os.environ["SERVER"] self.dc_account = self.server.upper() + '$' self.lp = s3param.get_context() self.lp.load_default() self.creds = self.insta_creds(template=self.get_credentials()) def test_gpo_list(self): global poldir, dspath gpos = get_gpo_list(self.server, self.creds, self.lp, self.creds.get_username()) guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' names = ['Local Policy', guid] file_sys_paths = [None, '%s\\%s' % (poldir, guid)] ds_paths = [None, 'CN=%s,%s' % (guid, dspath)] for i in range(0, len(gpos)): self.assertEqual(gpos[i].name, names[i], 'The gpo name did not match expected name %s' % gpos[i].name) self.assertEqual(gpos[i].file_sys_path, file_sys_paths[i], 'file_sys_path did not match expected %s' % gpos[i].file_sys_path) self.assertEqual(gpos[i].ds_path, ds_paths[i], 'ds_path did not match expected %s' % gpos[i].ds_path) def test_gpt_version(self): global gpt_data local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' gpo_path = os.path.join(local_path, policies, guid) old_vers = gpo.gpo_get_sysvol_gpt_version(gpo_path)[1] with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt: gpt.write(gpt_data % 42) self.assertEqual(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], 42, 'gpo_get_sysvol_gpt_version() did not return the expected version') with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt: gpt.write(gpt_data % old_vers) self.assertEqual(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], old_vers, 'gpo_get_sysvol_gpt_version() did not return the expected version') def test_check_refresh_gpo_list(self): cache = self.lp.cache_path('gpo_cache') gpos = get_gpo_list(self.server, self.creds, self.lp, self.creds.get_username()) check_refresh_gpo_list(self.server, self.lp, self.creds, gpos) self.assertTrue(os.path.exists(cache), 'GPO cache %s was not created' % cache) guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' gpt_ini = os.path.join(cache, policies, guid, 'GPT.INI') self.assertTrue(os.path.exists(gpt_ini), 'GPT.INI was not cached for %s' % guid) def test_check_refresh_gpo_list_malicious_paths(self): # the path cannot contain .. path = '/usr/local/samba/var/locks/sysvol/../../../../../../root/' self.assertRaises(OSError, check_safe_path, path) self.assertEqual(check_safe_path('/etc/passwd'), 'etc/passwd') self.assertEqual(check_safe_path('\\\\etc/\\passwd'), 'etc/passwd') # there should be no backslashes used to delineate paths before = 'sysvol/' + realm + '\\Policies/' \ '{31B2F340-016D-11D2-945F-00C04FB984F9}\\GPT.INI' after = realm + '/Policies/' \ '{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI' result = check_safe_path(before) self.assertEqual(result, after, 'check_safe_path() didn\'t' ' correctly convert \\ to /') def test_check_safe_path_typesafe_name(self): path = '\\\\toady.suse.de\\SysVol\\toady.suse.de\\Policies\\' \ '{31B2F340-016D-11D2-945F-00C04FB984F9}\\GPT.INI' expected_path = 'toady.suse.de/Policies/' \ '{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI' result = check_safe_path(path) self.assertEqual(result, expected_path, 'check_safe_path unable to detect variable case sysvol components') def test_gpt_ext_register(self): this_path = os.path.dirname(os.path.realpath(__file__)) samba_path = os.path.realpath(os.path.join(this_path, '../../../')) ext_path = os.path.join(samba_path, 'python/samba/gp/gp_sec_ext.py') ext_guid = '{827D319E-6EAC-11D2-A4EA-00C04F79F83A}' ret = register_gp_extension(ext_guid, 'gp_access_ext', ext_path, smb_conf=self.lp.configfile, machine=True, user=False) self.assertTrue(ret, 'Failed to register a gp ext') gp_exts = list_gp_extensions(self.lp.configfile) self.assertTrue(ext_guid in gp_exts.keys(), 'Failed to list gp exts') self.assertEqual(gp_exts[ext_guid]['DllName'], ext_path, 'Failed to list gp exts') unregister_gp_extension(ext_guid) gp_exts = list_gp_extensions(self.lp.configfile) self.assertTrue(ext_guid not in gp_exts.keys(), 'Failed to unregister gp exts') self.assertTrue(check_guid(ext_guid), 'Failed to parse valid guid') self.assertFalse(check_guid('AAAAAABBBBBBBCCC'), 'Parsed invalid guid') lp, parser = parse_gpext_conf(self.lp.configfile) self.assertTrue(lp and parser, 'parse_gpext_conf() invalid return') parser.add_section('test_section') parser.set('test_section', 'test_var', ext_guid) atomic_write_conf(lp, parser) lp, parser = parse_gpext_conf(self.lp.configfile) self.assertTrue('test_section' in parser.sections(), 'test_section not found in gpext.conf') self.assertEqual(parser.get('test_section', 'test_var'), ext_guid, 'Failed to find test variable in gpext.conf') parser.remove_section('test_section') atomic_write_conf(lp, parser) def test_gp_log_get_applied(self): local_path = self.lp.get('path', 'sysvol') guids = ['{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}'] gpofile = '%s/' + realm + '/Policies/%s/MACHINE/Microsoft/' \ 'Windows NT/SecEdit/GptTmpl.inf' stage = '[System Access]\nMinimumPasswordAge = 998\n' cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) for guid in guids: gpttmpl = gpofile % (local_path, guid) ret = stage_file(gpttmpl, stage) self.assertTrue(ret, 'Could not create the target %s' % gpttmpl) ret = gpupdate_force(self.lp) self.assertEqual(ret, 0, 'gpupdate force failed') gp_db = store.get_gplog(self.dc_account) applied_guids = gp_db.get_applied_guids() self.assertEqual(len(applied_guids), 2, 'The guids were not found') self.assertIn(guids[0], applied_guids, '%s not in applied guids' % guids[0]) self.assertIn(guids[1], applied_guids, '%s not in applied guids' % guids[1]) applied_settings = gp_db.get_applied_settings(applied_guids) for policy in applied_settings: self.assertIn('System Access', policy[1], 'System Access policies not set') self.assertIn('minPwdAge', policy[1]['System Access'], 'minPwdAge policy not set') if policy[0] == guids[0]: self.assertEqual(int(policy[1]['System Access']['minPwdAge']), days2rel_nttime(1), 'minPwdAge policy not set') elif policy[0] == guids[1]: self.assertEqual(int(policy[1]['System Access']['minPwdAge']), days2rel_nttime(998), 'minPwdAge policy not set') gpos = get_gpo_list(self.server, self.creds, self.lp, self.dc_account) del_gpos = get_deleted_gpos_list(gp_db, gpos[:-1]) self.assertEqual(len(del_gpos), 1, 'Returned delete gpos is incorrect') self.assertEqual(guids[-1], del_gpos[0][0], 'GUID for delete gpo is incorrect') self.assertIn('System Access', del_gpos[0][1], 'System Access policies not set for removal') self.assertIn('minPwdAge', del_gpos[0][1]['System Access'], 'minPwdAge policy not set for removal') for guid in guids: gpttmpl = gpofile % (local_path, guid) unstage_file(gpttmpl) ret = gpupdate_unapply(self.lp) self.assertEqual(ret, 0, 'gpupdate unapply failed') def test_process_group_policy(self): local_path = self.lp.cache_path('gpo_cache') guids = ['{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}'] gpofile = '%s/' + policies + '/%s/MACHINE/MICROSOFT/' \ 'WINDOWS NT/SECEDIT/GPTTMPL.INF' cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_krb_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Include MaxClockSkew to ensure we don't fail on a key we ignore stage = '[Kerberos Policy]\nMaxTicketAge = %d\nMaxClockSkew = 5' opts = [100, 200] for i in range(0, 2): gpttmpl = gpofile % (local_path, guids[i]) ret = stage_file(gpttmpl, stage % opts[i]) self.assertTrue(ret, 'Could not create the target %s' % gpttmpl) # Process all gpos ext.process_group_policy([], gpos) ret = store.get_int('kdc:user_ticket_lifetime') self.assertEqual(ret, opts[1], 'Higher priority policy was not set') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) ret = store.get_int('kdc:user_ticket_lifetime') self.assertEqual(ret, None, 'MaxTicketAge should not have applied') # Process just the first gpo ext.process_group_policy([], gpos[:-1]) ret = store.get_int('kdc:user_ticket_lifetime') self.assertEqual(ret, opts[0], 'Lower priority policy was not set') # Remove policy ext.process_group_policy(del_gpos, []) for guid in guids: gpttmpl = gpofile % (local_path, guid) unstage_file(gpttmpl) def test_gp_scripts(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_scripts_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) reg_key = b'Software\\Policies\\Samba\\Unix Settings' sections = { b'%s\\Daily Scripts' % reg_key : '.cron.daily', b'%s\\Monthly Scripts' % reg_key : '.cron.monthly', b'%s\\Weekly Scripts' % reg_key : '.cron.weekly', b'%s\\Hourly Scripts' % reg_key : '.cron.hourly' } for keyname in sections.keys(): # Stage the Registry.pol file with test data stage = preg.file() e = preg.entry() e.keyname = keyname e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'echo hello world' stage.num_entries = 1 stage.entries = [e] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Process all gpos, with temp output directory with TemporaryDirectory(sections[keyname]) as dname: ext.process_group_policy([], gpos, dname) scripts = os.listdir(dname) self.assertEqual(len(scripts), 1, 'The %s script was not created' % keyname.decode()) out, _ = Popen([os.path.join(dname, scripts[0])], stdout=PIPE).communicate() self.assertIn(b'hello world', out, '%s script execution failed' % keyname.decode()) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) self.assertEqual(len(os.listdir(dname)), 0, 'Unapply failed to cleanup scripts') # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_sudoers(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_sudoers_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data stage = preg.file() e = preg.entry() e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights' e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'fakeu ALL=(ALL) NOPASSWD: ALL' stage.num_entries = 1 stage.entries = [e] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) sudoers = os.listdir(dname) self.assertEqual(len(sudoers), 1, 'The sudoer file was not created') self.assertIn(e.data, open(os.path.join(dname, sudoers[0]), 'r').read(), 'The sudoers entry was not applied') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) self.assertEqual(len(os.listdir(dname)), 0, 'Unapply failed to cleanup scripts') # Unstage the Registry.pol file unstage_file(reg_pol) def test_vgp_sudoers(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' manifest = os.path.join(local_path, policies, guid, 'MACHINE', 'VGP/VTLA/SUDO/SUDOERSCONFIGURATION/MANIFEST.XML') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = vgp_sudoers_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the manifest.xml file with test data stage = etree.Element('vgppolicy') policysetting = etree.Element('policysetting') stage.append(policysetting) version = etree.Element('version') version.text = '1' policysetting.append(version) data = etree.Element('data') sudoers_entry = etree.Element('sudoers_entry') command = etree.Element('command') command.text = 'ALL' sudoers_entry.append(command) user = etree.Element('user') user.text = 'ALL' sudoers_entry.append(user) principal_list = etree.Element('listelement') principal = etree.Element('principal') principal.text = 'fakeu' principal.attrib['type'] = 'user' group = etree.Element('principal') group.text = 'fakeg' group.attrib['type'] = 'group' principal_list.append(principal) principal_list.append(group) sudoers_entry.append(principal_list) data.append(sudoers_entry) # Ensure an empty principal doesn't cause a crash sudoers_entry = etree.SubElement(data, 'sudoers_entry') command = etree.SubElement(sudoers_entry, 'command') command.text = 'ALL' user = etree.SubElement(sudoers_entry, 'user') user.text = 'ALL' # Ensure having dispersed principals still works sudoers_entry = etree.SubElement(data, 'sudoers_entry') command = etree.SubElement(sudoers_entry, 'command') command.text = 'ALL' user = etree.SubElement(sudoers_entry, 'user') user.text = 'ALL' listelement = etree.SubElement(sudoers_entry, 'listelement') principal = etree.SubElement(listelement, 'principal') principal.text = 'fakeu2' principal.attrib['type'] = 'user' listelement = etree.SubElement(sudoers_entry, 'listelement') group = etree.SubElement(listelement, 'principal') group.text = 'fakeg2' group.attrib['type'] = 'group' policysetting.append(data) ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Process all gpos, with temp output directory data = 'fakeu,fakeg% ALL=(ALL) NOPASSWD: ALL' data2 = 'fakeu2,fakeg2% ALL=(ALL) NOPASSWD: ALL' data_no_principal = 'ALL ALL=(ALL) NOPASSWD: ALL' with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) sudoers = os.listdir(dname) self.assertEqual(len(sudoers), 3, 'The sudoer file was not created') output = open(os.path.join(dname, sudoers[0]), 'r').read() + \ open(os.path.join(dname, sudoers[1]), 'r').read() + \ open(os.path.join(dname, sudoers[2]), 'r').read() self.assertIn(data, output, 'The sudoers entry was not applied') self.assertIn(data2, output, 'The sudoers entry was not applied') self.assertIn(data_no_principal, output, 'The sudoers entry was not applied') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) self.assertEqual(len(os.listdir(dname)), 0, 'Unapply failed to cleanup scripts') # Unstage the Registry.pol file unstage_file(manifest) def test_gp_inf_ext_utf(self): cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() ext = gp_inf_ext(self.lp, machine_creds, machine_creds.get_username(), store) test_data = '[Kerberos Policy]\nMaxTicketAge = 99\n' with NamedTemporaryFile() as f: with codecs.open(f.name, 'w', 'utf-16') as w: w.write(test_data) try: inf_conf = ext.read(f.name) except UnicodeDecodeError: self.fail('Failed to parse utf-16') self.assertIn('Kerberos Policy', inf_conf.keys(), 'Kerberos Policy was not read from the file') self.assertEqual(inf_conf.get('Kerberos Policy', 'MaxTicketAge'), '99', 'MaxTicketAge was not read from the file') with NamedTemporaryFile() as f: with codecs.open(f.name, 'w', 'utf-8') as w: w.write(test_data) inf_conf = ext.read(f.name) self.assertIn('Kerberos Policy', inf_conf.keys(), 'Kerberos Policy was not read from the file') self.assertEqual(inf_conf.get('Kerberos Policy', 'MaxTicketAge'), '99', 'MaxTicketAge was not read from the file') def test_rsop(self): cache_dir = self.lp.get('cache directory') local_path = self.lp.cache_path('gpo_cache') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) gp_extensions = [] gp_extensions.append(gp_krb_ext) gp_extensions.append(gp_scripts_ext) gp_extensions.append(gp_sudoers_ext) gp_extensions.append(gp_smb_conf_ext) gp_extensions.append(gp_msgs_ext) # Create registry stage data reg_pol = os.path.join(local_path, policies, '%s/MACHINE/REGISTRY.POL') reg_stage = preg.file() e = preg.entry() e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Daily Scripts' e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'echo hello world' e2 = preg.entry() e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights' e2.valuename = b'Software\\Policies\\Samba\\Unix Settings' e2.type = 1 e2.data = b'fakeu ALL=(ALL) NOPASSWD: ALL' e3 = preg.entry() e3.keyname = 'Software\\Policies\\Samba\\smb_conf\\apply group policies' e3.type = 4 e3.data = 1 e3.valuename = 'apply group policies' e4 = preg.entry() e4.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages' e4.valuename = b'issue' e4.type = 1 e4.data = b'Welcome to \\s \\r \\l' reg_stage.num_entries = 4 reg_stage.entries = [e, e2, e3, e4] # Create krb stage date gpofile = os.path.join(local_path, policies, '%s/MACHINE/MICROSOFT/' \ 'WINDOWS NT/SECEDIT/GPTTMPL.INF') krb_stage = '[Kerberos Policy]\nMaxTicketAge = 99\n' \ '[System Access]\nMinimumPasswordAge = 998\n' for g in [g for g in gpos if g.file_sys_path]: ret = stage_file(gpofile % g.name, krb_stage) self.assertTrue(ret, 'Could not create the target %s' % (gpofile % g.name)) ret = stage_file(reg_pol % g.name, ndr_pack(reg_stage)) self.assertTrue(ret, 'Could not create the target %s' % (reg_pol % g.name)) for ext in gp_extensions: ext = ext(self.lp, machine_creds, machine_creds.get_username(), store) ret = ext.rsop(g) self.assertEqual(len(ret.keys()), 1, 'A single policy should have been displayed') # Check the Security Extension if type(ext) == gp_krb_ext: self.assertIn('Kerberos Policy', ret.keys(), 'Kerberos Policy not found') self.assertIn('MaxTicketAge', ret['Kerberos Policy'], 'MaxTicketAge setting not found') self.assertEqual(ret['Kerberos Policy']['MaxTicketAge'], '99', 'MaxTicketAge was not set to 99') # Check the Scripts Extension elif type(ext) == gp_scripts_ext: self.assertIn('Daily Scripts', ret.keys(), 'Daily Scripts not found') self.assertIn('echo hello world', ret['Daily Scripts'], 'Daily script was not created') # Check the Sudoers Extension elif type(ext) == gp_sudoers_ext: self.assertIn('Sudo Rights', ret.keys(), 'Sudoers not found') self.assertIn('fakeu ALL=(ALL) NOPASSWD: ALL', ret['Sudo Rights'], 'Sudoers policy not created') # Check the smb.conf Extension elif type(ext) == gp_smb_conf_ext: self.assertIn('smb.conf', ret.keys(), 'apply group policies was not applied') self.assertIn(e3.valuename, ret['smb.conf'], 'apply group policies was not applied') self.assertEqual(ret['smb.conf'][e3.valuename], e3.data, 'apply group policies was not set') # Check the Messages Extension elif type(ext) == gp_msgs_ext: self.assertIn('/etc/issue', ret, 'Login Prompt Message not applied') self.assertEqual(ret['/etc/issue'], e4.data, 'Login Prompt Message not set') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') unstage_file(gpofile % g.name) unstage_file(reg_pol % g.name) def test_gp_unapply(self): cache_dir = self.lp.get('cache directory') local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) gp_extensions = [] gp_extensions.append(gp_krb_ext) gp_extensions.append(gp_scripts_ext) gp_extensions.append(gp_sudoers_ext) # Create registry stage data reg_pol = os.path.join(local_path, policies, '%s/MACHINE/REGISTRY.POL') reg_stage = preg.file() e = preg.entry() e.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Daily Scripts' e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'echo hello world' e2 = preg.entry() e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights' e2.valuename = b'Software\\Policies\\Samba\\Unix Settings' e2.type = 1 e2.data = b'fakeu ALL=(ALL) NOPASSWD: ALL' reg_stage.num_entries = 2 reg_stage.entries = [e, e2] # Create krb stage date gpofile = os.path.join(local_path, policies, '%s/MACHINE/MICROSOFT/' \ 'WINDOWS NT/SECEDIT/GPTTMPL.INF') krb_stage = '[Kerberos Policy]\nMaxTicketAge = 99\n' ret = stage_file(gpofile % guid, krb_stage) self.assertTrue(ret, 'Could not create the target %s' % (gpofile % guid)) ret = stage_file(reg_pol % guid, ndr_pack(reg_stage)) self.assertTrue(ret, 'Could not create the target %s' % (reg_pol % guid)) # Process all gpos, with temp output directory remove = [] with TemporaryDirectory() as dname: for ext in gp_extensions: ext = ext(self.lp, machine_creds, machine_creds.get_username(), store) if type(ext) == gp_krb_ext: ext.process_group_policy([], gpos) ret = store.get_int('kdc:user_ticket_lifetime') self.assertEqual(ret, 99, 'Kerberos policy was not set') elif type(ext) in [gp_scripts_ext, gp_sudoers_ext]: ext.process_group_policy([], gpos, dname) gp_db = store.get_gplog(machine_creds.get_username()) applied_settings = gp_db.get_applied_settings([guid]) for _, fname in applied_settings[-1][-1][str(ext)].items(): fname = fname.split(':')[-1] self.assertIn(dname, fname, 'Test file not created in tmp dir') self.assertTrue(os.path.exists(fname), 'Test file not created') remove.append(fname) # Unapply policy, and ensure policies are removed gpupdate_unapply(self.lp) for fname in remove: self.assertFalse(os.path.exists(fname), 'Unapply did not remove test file') ret = store.get_int('kdc:user_ticket_lifetime') self.assertNotEqual(ret, 99, 'Kerberos policy was not unapplied') unstage_file(gpofile % guid) unstage_file(reg_pol % guid) def test_smb_conf_ext(self): local_path = self.lp.cache_path('gpo_cache') guids = ['{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}'] reg_pol = os.path.join(local_path, policies, guids[0], 'MACHINE/REGISTRY.POL') reg_pol2 = os.path.join(local_path, policies, guids[1], 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) entries = [] e = preg.entry() e.keyname = 'Software\\Policies\\Samba\\smb_conf\\template homedir' e.type = 1 e.data = '/home/samba/%D/%U' e.valuename = 'template homedir' entries.append(e) e = preg.entry() e.keyname = 'Software\\Policies\\Samba\\smb_conf\\apply group policies' e.type = 4 e.data = 1 e.valuename = 'apply group policies' entries.append(e) e = preg.entry() e.keyname = 'Software\\Policies\\Samba\\smb_conf\\ldap timeout' e.type = 4 e.data = 9999 e.valuename = 'ldap timeout' entries.append(e) stage = preg.file() stage.num_entries = len(entries) stage.entries = entries ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Failed to create the Registry.pol file') # Stage the other Registry.pol entries = [] e = preg.entry() e.keyname = 'Software\\Policies\\Samba\\smb_conf\\apply group policies' e.type = 4 e.data = 0 e.valuename = 'apply group policies' entries.append(e) stage = preg.file() stage.num_entries = len(entries) stage.entries = entries ret = stage_file(reg_pol2, ndr_pack(stage)) self.assertTrue(ret, 'Failed to create the Registry.pol file') with NamedTemporaryFile(suffix='_smb.conf') as f: copyfile(self.lp.configfile, f.name) lp = LoadParm(f.name) # Initialize the group policy extension ext = gp_smb_conf_ext(lp, machine_creds, machine_creds.get_username(), store) ext.process_group_policy([], gpos) lp = LoadParm(f.name) template_homedir = lp.get('template homedir') self.assertEqual(template_homedir, '/home/samba/%D/%U', 'template homedir was not applied') apply_group_policies = lp.get('apply group policies') self.assertFalse(apply_group_policies, 'apply group policies was not applied') ldap_timeout = lp.get('ldap timeout') self.assertEqual(ldap_timeout, 9999, 'ldap timeout was not applied') # Force apply with removal of second GPO gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = gp_db.get_applied_settings([guids[1]]) gpos = [gpo for gpo in gpos if gpo.name != guids[1]] ext.process_group_policy(del_gpos, gpos) lp = LoadParm(f.name) template_homedir = lp.get('template homedir') self.assertEqual(template_homedir, '/home/samba/%D/%U', 'template homedir was not applied') apply_group_policies = lp.get('apply group policies') self.assertTrue(apply_group_policies, 'apply group policies was not applied') ldap_timeout = lp.get('ldap timeout') self.assertEqual(ldap_timeout, 9999, 'ldap timeout was not applied') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) lp = LoadParm(f.name) template_homedir = lp.get('template homedir') self.assertEqual(template_homedir, self.lp.get('template homedir'), 'template homedir was not unapplied') apply_group_policies = lp.get('apply group policies') self.assertEqual(apply_group_policies, self.lp.get('apply group policies'), 'apply group policies was not unapplied') ldap_timeout = lp.get('ldap timeout') self.assertEqual(ldap_timeout, self.lp.get('ldap timeout'), 'ldap timeout was not unapplied') # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_motd(self): local_path = self.lp.cache_path('gpo_cache') guids = ['{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}'] reg_pol = os.path.join(local_path, policies, guids[0], 'MACHINE/REGISTRY.POL') reg_pol2 = os.path.join(local_path, policies, guids[1], 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_msgs_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data stage = preg.file() e1 = preg.entry() e1.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages' e1.valuename = b'motd' e1.type = 1 e1.data = b'Have a lot of fun!' stage.num_entries = 2 e2 = preg.entry() e2.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages' e2.valuename = b'issue' e2.type = 1 e2.data = b'Welcome to \\s \\r \\l' stage.entries = [e1, e2] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Stage the other Registry.pol stage = preg.file() e3 = preg.entry() e3.keyname = b'Software\\Policies\\Samba\\Unix Settings\\Messages' e3.valuename = b'motd' e3.type = 1 e3.data = b'This should overwrite the first policy' stage.num_entries = 1 stage.entries = [e3] ret = stage_file(reg_pol2, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol2) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) motd_file = os.path.join(dname, 'motd') self.assertTrue(os.path.exists(motd_file), 'Message of the day file not created') data = open(motd_file, 'r').read() self.assertEqual(data, e3.data, 'Message of the day not applied') issue_file = os.path.join(dname, 'issue') self.assertTrue(os.path.exists(issue_file), 'Login Prompt Message file not created') data = open(issue_file, 'r').read() self.assertEqual(data, e2.data, 'Login Prompt Message not applied') # Force apply with removal of second GPO gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = gp_db.get_applied_settings([guids[1]]) gpos = [gpo for gpo in gpos if gpo.name != guids[1]] ext.process_group_policy(del_gpos, gpos, dname) self.assertTrue(os.path.exists(motd_file), 'Message of the day file not created') data = open(motd_file, 'r').read() self.assertEqual(data, e1.data, 'Message of the day not applied') issue_file = os.path.join(dname, 'issue') self.assertTrue(os.path.exists(issue_file), 'Login Prompt Message file not created') data = open(issue_file, 'r').read() self.assertEqual(data, e2.data, 'Login Prompt Message not applied') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unapply policy, and ensure the test files are removed del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) data = open(motd_file, 'r').read() self.assertFalse(data, 'Message of the day file not removed') data = open(issue_file, 'r').read() self.assertFalse(data, 'Login Prompt Message file not removed') # Unstage the Registry.pol file unstage_file(reg_pol) def test_vgp_symlink(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' manifest = os.path.join(local_path, policies, guid, 'MACHINE', 'VGP/VTLA/UNIX/SYMLINK/MANIFEST.XML') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = vgp_symlink_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) with TemporaryDirectory() as dname: test_source = os.path.join(dname, 'test.source') test_target = os.path.join(dname, 'test.target') # Stage the manifest.xml file with test data stage = etree.Element('vgppolicy') policysetting = etree.Element('policysetting') stage.append(policysetting) version = etree.Element('version') version.text = '1' policysetting.append(version) data = etree.Element('data') file_properties = etree.Element('file_properties') source = etree.Element('source') source.text = test_source file_properties.append(source) target = etree.Element('target') target.text = test_target file_properties.append(target) data.append(file_properties) policysetting.append(data) ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Create test source test_source_data = 'hello world!' with open(test_source, 'w') as w: w.write(test_source_data) # Process all gpos, with temp output directory ext.process_group_policy([], gpos) self.assertTrue(os.path.exists(test_target), 'The test symlink was not created') self.assertTrue(os.path.islink(test_target), 'The test file is not a symlink') self.assertIn(test_source_data, open(test_target, 'r').read(), 'Reading from symlink does not produce source data') # Unapply the policy, ensure removal gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) self.assertFalse(os.path.exists(test_target), 'The test symlink was not delete') # Verify RSOP ret = ext.rsop([g for g in gpos if g.name == guid][0]) self.assertIn('ln -s %s %s' % (test_source, test_target), list(ret.values())[0]) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unstage the manifest.xml file unstage_file(manifest) def test_vgp_files(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' manifest = os.path.join(local_path, policies, guid, 'MACHINE', 'VGP/VTLA/UNIX/FILES/MANIFEST.XML') source_file = os.path.join(os.path.dirname(manifest), 'TEST.SOURCE') source_data = '#!/bin/sh\necho hello world' ret = stage_file(source_file, source_data) self.assertTrue(ret, 'Could not create the target %s' % source_file) cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = vgp_files_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the manifest.xml file with test data with TemporaryDirectory() as dname: stage = etree.Element('vgppolicy') policysetting = etree.Element('policysetting') stage.append(policysetting) version = etree.Element('version') version.text = '1' policysetting.append(version) data = etree.Element('data') file_properties = etree.SubElement(data, 'file_properties') source = etree.SubElement(file_properties, 'source') source.text = os.path.basename(source_file).lower() target = etree.SubElement(file_properties, 'target') target.text = os.path.join(dname, 'test.target') user = etree.SubElement(file_properties, 'user') user.text = pwd.getpwuid(os.getuid()).pw_name group = etree.SubElement(file_properties, 'group') group.text = grp.getgrgid(os.getgid()).gr_name # Request permissions of 755 permissions = etree.SubElement(file_properties, 'permissions') permissions.set('type', 'user') etree.SubElement(permissions, 'read') etree.SubElement(permissions, 'write') etree.SubElement(permissions, 'execute') permissions = etree.SubElement(file_properties, 'permissions') permissions.set('type', 'group') etree.SubElement(permissions, 'read') etree.SubElement(permissions, 'execute') permissions = etree.SubElement(file_properties, 'permissions') permissions.set('type', 'other') etree.SubElement(permissions, 'read') etree.SubElement(permissions, 'execute') policysetting.append(data) ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Process all gpos, with temp output directory ext.process_group_policy([], gpos) self.assertTrue(os.path.exists(target.text), 'The target file does not exist') self.assertEqual(os.stat(target.text).st_mode & 0o777, 0o755, 'The target file permissions are incorrect') self.assertEqual(open(target.text).read(), source_data, 'The target file contents are incorrect') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) self.assertFalse(os.path.exists(target.text), 'The target file was not removed') # Test rsop g = [g for g in gpos if g.name == guid][0] ret = ext.rsop(g) self.assertIn(target.text, list(ret.values())[0][0], 'The target file was not listed by rsop') self.assertIn('-rwxr-xr-x', list(ret.values())[0][0], 'The target permissions were not listed by rsop') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unstage the manifest and source files unstage_file(manifest) unstage_file(source_file) def test_vgp_openssh(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' manifest = os.path.join(local_path, policies, guid, 'MACHINE', 'VGP/VTLA/SSHCFG/SSHD/MANIFEST.XML') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = vgp_openssh_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the manifest.xml file with test data stage = etree.Element('vgppolicy') policysetting = etree.Element('policysetting') stage.append(policysetting) version = etree.Element('version') version.text = '1' policysetting.append(version) data = etree.Element('data') configfile = etree.Element('configfile') configsection = etree.Element('configsection') sectionname = etree.Element('sectionname') configsection.append(sectionname) kvpair = etree.Element('keyvaluepair') key = etree.Element('key') key.text = 'AddressFamily' kvpair.append(key) value = etree.Element('value') value.text = 'inet6' kvpair.append(value) configsection.append(kvpair) configfile.append(configsection) data.append(configfile) policysetting.append(data) ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Process all gpos, with temp output directory data = 'AddressFamily inet6' with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) conf = os.listdir(dname) self.assertEqual(len(conf), 1, 'The conf file was not created') gp_cfg = os.path.join(dname, conf[0]) self.assertIn(data, open(gp_cfg, 'r').read(), 'The sshd_config entry was not applied') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) self.assertFalse(os.path.exists(gp_cfg), 'Unapply failed to cleanup config') # Unstage the Registry.pol file unstage_file(manifest) def test_vgp_startup_scripts(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' manifest = os.path.join(local_path, policies, guid, 'MACHINE', 'VGP/VTLA/UNIX/SCRIPTS/STARTUP/MANIFEST.XML') test_script = os.path.join(os.path.dirname(manifest), 'TEST.SH') test_data = '#!/bin/sh\necho $@ hello world' ret = stage_file(test_script, test_data) self.assertTrue(ret, 'Could not create the target %s' % test_script) cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = vgp_startup_scripts_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the manifest.xml file with test data stage = etree.Element('vgppolicy') policysetting = etree.SubElement(stage, 'policysetting') version = etree.SubElement(policysetting, 'version') version.text = '1' data = etree.SubElement(policysetting, 'data') listelement = etree.SubElement(data, 'listelement') script = etree.SubElement(listelement, 'script') script.text = os.path.basename(test_script).lower() parameters = etree.SubElement(listelement, 'parameters') parameters.text = '-n' hash = etree.SubElement(listelement, 'hash') hash.text = \ hashlib.md5(open(test_script, 'rb').read()).hexdigest().upper() run_as = etree.SubElement(listelement, 'run_as') run_as.text = 'root' ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) files = os.listdir(dname) self.assertEqual(len(files), 1, 'The target script was not created') entry = '@reboot %s %s %s' % (run_as.text, test_script, parameters.text) self.assertIn(entry, open(os.path.join(dname, files[0]), 'r').read(), 'The test entry was not found') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) files = os.listdir(dname) self.assertEqual(len(files), 0, 'The target script was not removed') # Test rsop g = [g for g in gpos if g.name == guid][0] ret = ext.rsop(g) self.assertIn(entry, list(ret.values())[0][0], 'The target entry was not listed by rsop') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unstage the manifest.xml and script files unstage_file(manifest) # Stage the manifest.xml file for run once scripts etree.SubElement(listelement, 'run_once') run_as.text = pwd.getpwuid(os.getuid()).pw_name ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Process all gpos, with temp output directory # A run once script will be executed immediately, # instead of creating a cron job with TemporaryDirectory() as dname: test_file = '%s/TESTING.txt' % dname test_data = '#!/bin/sh\ntouch %s' % test_file ret = stage_file(test_script, test_data) self.assertTrue(ret, 'Could not create the target %s' % test_script) ext.process_group_policy([], gpos, dname) files = os.listdir(dname) self.assertEqual(len(files), 1, 'The test file was not created') self.assertEqual(files[0], os.path.basename(test_file), 'The test file was not created') # Unlink the test file and ensure that processing # policy again does not recreate it. os.unlink(test_file) ext.process_group_policy([], gpos, dname) files = os.listdir(dname) self.assertEqual(len(files), 0, 'The test file should not have been created') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) # Test rsop entry = 'Run once as: %s `%s %s`' % (run_as.text, test_script, parameters.text) g = [g for g in gpos if g.name == guid][0] ret = ext.rsop(g) self.assertIn(entry, list(ret.values())[0][0], 'The target entry was not listed by rsop') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unstage the manifest.xml and script files unstage_file(manifest) # Stage the manifest.xml file for a script without parameters stage = etree.Element('vgppolicy') policysetting = etree.SubElement(stage, 'policysetting') version = etree.SubElement(policysetting, 'version') version.text = '1' data = etree.SubElement(policysetting, 'data') listelement = etree.SubElement(data, 'listelement') script = etree.SubElement(listelement, 'script') script.text = os.path.basename(test_script).lower() hash = etree.SubElement(listelement, 'hash') hash.text = \ hashlib.md5(open(test_script, 'rb').read()).hexdigest().upper() run_as = etree.SubElement(listelement, 'run_as') run_as.text = 'root' ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: try: ext.process_group_policy([], gpos, dname) except Exception as e: self.fail(str(e)) files = os.listdir(dname) self.assertEqual(len(files), 1, 'The target script was not created') entry = '@reboot %s %s' % (run_as.text, test_script) self.assertIn(entry, open(os.path.join(dname, files[0]), 'r').read(), 'The test entry was not found') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) files = os.listdir(dname) self.assertEqual(len(files), 0, 'The target script was not removed') # Test rsop g = [g for g in gpos if g.name == guid][0] ret = ext.rsop(g) self.assertIn(entry, list(ret.values())[0][0], 'The target entry was not listed by rsop') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unstage the manifest.xml and script files unstage_file(manifest) unstage_file(test_script) def test_vgp_motd(self): local_path = self.lp.cache_path('gpo_cache') guids = ['{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}'] manifest = os.path.join(local_path, policies, guids[0], 'MACHINE', 'VGP/VTLA/UNIX/MOTD/MANIFEST.XML') manifest2 = os.path.join(local_path, policies, guids[1], 'MACHINE', 'VGP/VTLA/UNIX/MOTD/MANIFEST.XML') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = vgp_motd_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the manifest.xml file with test data stage = etree.Element('vgppolicy') policysetting = etree.SubElement(stage, 'policysetting') version = etree.SubElement(policysetting, 'version') version.text = '1' data = etree.SubElement(policysetting, 'data') filename = etree.SubElement(data, 'filename') filename.text = 'motd' text = etree.SubElement(data, 'text') text.text = 'This is the message of the day' ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Stage the other manifest.xml stage = etree.Element('vgppolicy') policysetting = etree.SubElement(stage, 'policysetting') version = etree.SubElement(policysetting, 'version') version.text = '1' data = etree.SubElement(policysetting, 'data') filename = etree.SubElement(data, 'filename') filename.text = 'motd' text2 = etree.SubElement(data, 'text') text2.text = 'This should overwrite the first policy' ret = stage_file(manifest2, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest2) # Process all gpos, with temp output directory with NamedTemporaryFile() as f: ext.process_group_policy([], gpos, f.name) self.assertTrue(os.path.exists(f.name), 'Message of the day file not created') data = open(f.name, 'r').read() self.assertEqual(data, text2.text, 'Message of the day not applied') # Force apply with removal of second GPO gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = gp_db.get_applied_settings([guids[1]]) gpos = [gpo for gpo in gpos if gpo.name != guids[1]] ext.process_group_policy(del_gpos, gpos, f.name) self.assertEqual(open(f.name, 'r').read(), text.text, 'The motd was not applied') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], f.name) self.assertNotEqual(open(f.name, 'r').read(), text.text, 'The motd was not unapplied') # Unstage the manifest files unstage_file(manifest) unstage_file(manifest2) def test_vgp_issue(self): local_path = self.lp.cache_path('gpo_cache') guids = ['{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}'] manifest = os.path.join(local_path, policies, guids[0], 'MACHINE', 'VGP/VTLA/UNIX/ISSUE/MANIFEST.XML') manifest2 = os.path.join(local_path, policies, guids[1], 'MACHINE', 'VGP/VTLA/UNIX/ISSUE/MANIFEST.XML') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = vgp_issue_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the manifest.xml file with test data stage = etree.Element('vgppolicy') policysetting = etree.SubElement(stage, 'policysetting') version = etree.SubElement(policysetting, 'version') version.text = '1' data = etree.SubElement(policysetting, 'data') filename = etree.SubElement(data, 'filename') filename.text = 'issue' text = etree.SubElement(data, 'text') text.text = 'Welcome to Samba!' ret = stage_file(manifest, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest) # Stage the other manifest.xml stage = etree.Element('vgppolicy') policysetting = etree.SubElement(stage, 'policysetting') version = etree.SubElement(policysetting, 'version') version.text = '1' data = etree.SubElement(policysetting, 'data') filename = etree.SubElement(data, 'filename') filename.text = 'issue' text2 = etree.SubElement(data, 'text') text2.text = 'This test message overwrites the first' ret = stage_file(manifest2, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % manifest2) # Process all gpos, with temp output directory with NamedTemporaryFile() as f: ext.process_group_policy([], gpos, f.name) self.assertEqual(open(f.name, 'r').read(), text2.text, 'The issue was not applied') # Force apply with removal of second GPO gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = gp_db.get_applied_settings([guids[1]]) gpos = [gpo for gpo in gpos if gpo.name != guids[1]] ext.process_group_policy(del_gpos, gpos, f.name) self.assertEqual(open(f.name, 'r').read(), text.text, 'The issue was not applied') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], f.name) self.assertNotEqual(open(f.name, 'r').read(), text.text, 'The issue was not unapplied') # Unstage the manifest.xml file unstage_file(manifest) def test_vgp_access(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' allow = os.path.join(local_path, policies, guid, 'MACHINE', 'VGP/VTLA/VAS/HOSTACCESSCONTROL/ALLOW/MANIFEST.XML') deny = os.path.join(local_path, policies, guid, 'MACHINE', 'VGP/VTLA/VAS/HOSTACCESSCONTROL/DENY/MANIFEST.XML') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension winbind_sep = self.lp.get('winbind separator') self.addCleanup(self.lp.set, 'winbind separator', winbind_sep) self.lp.set('winbind separator', '+') ext = vgp_access_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the manifest.xml allow file stage = etree.Element('vgppolicy') policysetting = etree.SubElement(stage, 'policysetting') version = etree.SubElement(policysetting, 'version') version.text = '2' apply_mode = etree.SubElement(policysetting, 'apply_mode') apply_mode.text = 'merge' data = etree.SubElement(policysetting, 'data') # Add an allowed user listelement = etree.SubElement(data, 'listelement') otype = etree.SubElement(listelement, 'type') otype.text = 'USER' entry = etree.SubElement(listelement, 'entry') entry.text = 'goodguy@%s' % realm adobject = etree.SubElement(listelement, 'adobject') name = etree.SubElement(adobject, 'name') name.text = 'goodguy' domain = etree.SubElement(adobject, 'domain') domain.text = realm otype = etree.SubElement(adobject, 'type') otype.text = 'user' # Add an allowed group groupattr = etree.SubElement(data, 'groupattr') groupattr.text = 'samAccountName' listelement = etree.SubElement(data, 'listelement') otype = etree.SubElement(listelement, 'type') otype.text = 'GROUP' entry = etree.SubElement(listelement, 'entry') entry.text = '%s\\goodguys' % realm dn = etree.SubElement(listelement, 'dn') dn.text = 'CN=goodguys,CN=Users,%s' % base_dn adobject = etree.SubElement(listelement, 'adobject') name = etree.SubElement(adobject, 'name') name.text = 'goodguys' domain = etree.SubElement(adobject, 'domain') domain.text = realm otype = etree.SubElement(adobject, 'type') otype.text = 'group' ret = stage_file(allow, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % allow) # Stage the manifest.xml deny file stage = etree.Element('vgppolicy') policysetting = etree.SubElement(stage, 'policysetting') version = etree.SubElement(policysetting, 'version') version.text = '2' apply_mode = etree.SubElement(policysetting, 'apply_mode') apply_mode.text = 'merge' data = etree.SubElement(policysetting, 'data') # Add a denied user listelement = etree.SubElement(data, 'listelement') otype = etree.SubElement(listelement, 'type') otype.text = 'USER' entry = etree.SubElement(listelement, 'entry') entry.text = 'badguy@%s' % realm adobject = etree.SubElement(listelement, 'adobject') name = etree.SubElement(adobject, 'name') name.text = 'badguy' domain = etree.SubElement(adobject, 'domain') domain.text = realm otype = etree.SubElement(adobject, 'type') otype.text = 'user' # Add a denied group groupattr = etree.SubElement(data, 'groupattr') groupattr.text = 'samAccountName' listelement = etree.SubElement(data, 'listelement') otype = etree.SubElement(listelement, 'type') otype.text = 'GROUP' entry = etree.SubElement(listelement, 'entry') entry.text = '%s\\badguys' % realm dn = etree.SubElement(listelement, 'dn') dn.text = 'CN=badguys,CN=Users,%s' % base_dn adobject = etree.SubElement(listelement, 'adobject') name = etree.SubElement(adobject, 'name') name.text = 'badguys' domain = etree.SubElement(adobject, 'domain') domain.text = realm otype = etree.SubElement(adobject, 'type') otype.text = 'group' ret = stage_file(deny, etree.tostring(stage)) self.assertTrue(ret, 'Could not create the target %s' % deny) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) conf = os.listdir(dname) # There will be 2 files, the policy file and the deny file self.assertEqual(len(conf), 2, 'The conf file was not created') # Ignore the DENY_ALL conf file gp_cfg = os.path.join(dname, [c for c in conf if '_gp_DENY_ALL.conf' not in c][0]) # Check the access config for the correct access.conf entries print('Config file %s found' % gp_cfg) data = open(gp_cfg, 'r').read() self.assertIn('+:%s+goodguy:ALL' % realm, data) self.assertIn('+:%s+goodguys:ALL' % realm, data) self.assertIn('-:%s+badguy:ALL' % realm, data) self.assertIn('-:%s+badguys:ALL' % realm, data) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) self.assertFalse(os.path.exists(gp_cfg), 'Unapply failed to cleanup config') # Unstage the manifest.pol files unstage_file(allow) unstage_file(deny) def test_gnome_settings(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_gnome_settings_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data parser = GPPolParser() parser.load_xml(etree.fromstring(gnome_test_reg_pol.strip())) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) local_db = os.path.join(dname, 'etc/dconf/db/local.d') self.assertTrue(os.path.isdir(local_db), 'Local db dir not created') def db_check(name, data, count=1): db = glob(os.path.join(local_db, '*-%s' % name)) self.assertEqual(len(db), count, '%s not created' % name) file_contents = ConfigParser() file_contents.read(db) for key in data.keys(): self.assertTrue(file_contents.has_section(key), 'Section %s not found' % key) options = data[key] for k, v in options.items(): v_content = file_contents.get(key, k) self.assertEqual(v_content, v, '%s: %s != %s' % (key, v_content, v)) def del_db_check(name): db = glob(os.path.join(local_db, '*-%s' % name)) self.assertEqual(len(db), 0, '%s not deleted' % name) locks = os.path.join(local_db, 'locks') self.assertTrue(os.path.isdir(local_db), 'Locks dir not created') def lock_check(name, items, count=1): lock = glob(os.path.join(locks, '*%s' % name)) self.assertEqual(len(lock), count, '%s lock not created' % name) file_contents = [] for i in range(count): file_contents.extend(open(lock[i], 'r').read().split('\n')) for data in items: self.assertIn(data, file_contents, '%s lock not created' % data) def del_lock_check(name): lock = glob(os.path.join(locks, '*%s' % name)) self.assertEqual(len(lock), 0, '%s lock not deleted' % name) # Check the user profile user_profile = os.path.join(dname, 'etc/dconf/profile/user') self.assertTrue(os.path.exists(user_profile), 'User profile not created') # Enable the compose key data = { 'org/gnome/desktop/input-sources': { 'xkb-options': '[\'compose:ralt\']' } } db_check('input-sources', data) items = ['/org/gnome/desktop/input-sources/xkb-options'] lock_check('input-sources', items) # Dim screen when user is idle data = { 'org/gnome/settings-daemon/plugins/power': { 'idle-dim': 'true', 'idle-brightness': '30' } } db_check('power', data) data = { 'org/gnome/desktop/session': { 'idle-delay': 'uint32 300' } } db_check('session', data) items = ['/org/gnome/settings-daemon/plugins/power/idle-dim', '/org/gnome/settings-daemon/plugins/power/idle-brightness', '/org/gnome/desktop/session/idle-delay'] lock_check('power-saving', items) # Lock down specific settings bg_locks = ['/org/gnome/desktop/background/picture-uri', '/org/gnome/desktop/background/picture-options', '/org/gnome/desktop/background/primary-color', '/org/gnome/desktop/background/secondary-color'] lock_check('group-policy', bg_locks) # Lock down enabled extensions data = { 'org/gnome/shell': { 'enabled-extensions': '[\'myextension1@myname.example.com\', \'myextension2@myname.example.com\']', 'development-tools': 'false' } } db_check('extensions', data) items = [ '/org/gnome/shell/enabled-extensions', '/org/gnome/shell/development-tools' ] lock_check('extensions', items) # Disallow login using a fingerprint data = { 'org/gnome/login-screen': { 'enable-fingerprint-authentication': 'false' } } db_check('fingerprintreader', data) items = ['/org/gnome/login-screen/enable-fingerprint-authentication'] lock_check('fingerprintreader', items) # Disable user logout and user switching data = { 'org/gnome/desktop/lockdown': { 'disable-log-out': 'true', 'disable-user-switching': 'true' } } db_check('logout', data, 2) items = ['/org/gnome/desktop/lockdown/disable-log-out', '/org/gnome/desktop/lockdown/disable-user-switching'] lock_check('logout', items, 2) # Disable repartitioning actions = os.path.join(dname, 'etc/share/polkit-1/actions') udisk2 = glob(os.path.join(actions, 'org.freedesktop.[u|U][d|D]isks2.policy')) self.assertEqual(len(udisk2), 1, 'udisk2 policy not created') udisk2_tree = etree.fromstring(open(udisk2[0], 'r').read()) actions = udisk2_tree.findall('action') md = 'org.freedesktop.udisks2.modify-device' action = [a for a in actions if a.attrib['id'] == md] self.assertEqual(len(action), 1, 'modify-device not found') defaults = action[0].find('defaults') self.assertTrue(defaults is not None, 'modify-device defaults not found') allow_any = defaults.find('allow_any').text self.assertEqual(allow_any, 'no', 'modify-device allow_any not set to no') allow_inactive = defaults.find('allow_inactive').text self.assertEqual(allow_inactive, 'no', 'modify-device allow_inactive not set to no') allow_active = defaults.find('allow_active').text self.assertEqual(allow_active, 'yes', 'modify-device allow_active not set to yes') # Disable printing data = { 'org/gnome/desktop/lockdown': { 'disable-printing': 'true' } } db_check('printing', data) items = ['/org/gnome/desktop/lockdown/disable-printing'] lock_check('printing', items) # Disable file saving data = { 'org/gnome/desktop/lockdown': { 'disable-save-to-disk': 'true' } } db_check('filesaving', data) items = ['/org/gnome/desktop/lockdown/disable-save-to-disk'] lock_check('filesaving', items) # Disable command-line access data = { 'org/gnome/desktop/lockdown': { 'disable-command-line': 'true' } } db_check('cmdline', data) items = ['/org/gnome/desktop/lockdown/disable-command-line'] lock_check('cmdline', items) # Allow or disallow online accounts data = { 'org/gnome/online-accounts': { 'whitelisted-providers': '[\'google\']' } } db_check('goa', data) items = ['/org/gnome/online-accounts/whitelisted-providers'] lock_check('goa', items) # Verify RSOP does not fail ext.rsop([g for g in gpos if g.name == guid][0]) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) del_db_check('input-sources') del_lock_check('input-sources') del_db_check('power') del_db_check('session') del_lock_check('power-saving') del_lock_check('group-policy') del_db_check('extensions') del_lock_check('extensions') del_db_check('fingerprintreader') del_lock_check('fingerprintreader') del_db_check('logout') del_lock_check('logout') actions = os.path.join(dname, 'etc/share/polkit-1/actions') udisk2 = glob(os.path.join(actions, 'org.freedesktop.[u|U][d|D]isks2.policy')) self.assertEqual(len(udisk2), 0, 'udisk2 policy not deleted') del_db_check('printing') del_lock_check('printing') del_db_check('filesaving') del_lock_check('filesaving') del_db_check('cmdline') del_lock_check('cmdline') del_db_check('goa') del_lock_check('goa') # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_cert_auto_enroll_ext_without_ndes(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension cae.requests = dummy_requests(want_exception=True) ext = cae.gp_cert_auto_enroll_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data parser = GPPolParser() parser.load_xml(etree.fromstring(auto_enroll_reg_pol.strip())) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Write the dummy CA entry, Enrollment Services, and Templates Entries admin_creds = Credentials() admin_creds.set_username(os.environ.get('DC_USERNAME')) admin_creds.set_password(os.environ.get('DC_PASSWORD')) admin_creds.set_realm(os.environ.get('REALM')) hostname = get_dc_hostname(machine_creds, self.lp) url = 'ldap://%s' % hostname ldb = Ldb(url=url, session_info=system_session(), lp=self.lp, credentials=admin_creds) # Write the dummy CA confdn = 'CN=Public Key Services,CN=Services,CN=Configuration,%s' % base_dn ca_cn = '%s-CA' % hostname.replace('.', '-') certa_dn = 'CN=%s,CN=Certification Authorities,%s' % (ca_cn, confdn) ldb.add({'dn': certa_dn, 'objectClass': 'certificationAuthority', 'authorityRevocationList': ['XXX'], 'cACertificate': dummy_certificate(), 'certificateRevocationList': ['XXX'], }) # Write the dummy pKIEnrollmentService enroll_dn = 'CN=%s,CN=Enrollment Services,%s' % (ca_cn, confdn) ldb.add({'dn': enroll_dn, 'objectClass': 'pKIEnrollmentService', 'cACertificate': dummy_certificate(), 'certificateTemplates': ['Machine'], 'dNSHostName': hostname, }) # Write the dummy pKICertificateTemplate template_dn = 'CN=Machine,CN=Certificate Templates,%s' % confdn ldb.add({'dn': template_dn, 'objectClass': 'pKICertificateTemplate', }) with TemporaryDirectory() as dname: try: ext.process_group_policy([], gpos, dname, dname) except Exception as e: self.fail(str(e)) ca_crt = os.path.join(dname, '%s.crt' % ca_cn) self.assertTrue(os.path.exists(ca_crt), 'Root CA certificate was not requested') machine_crt = os.path.join(dname, '%s.Machine.crt' % ca_cn) self.assertTrue(os.path.exists(machine_crt), 'Machine certificate was not requested') machine_key = os.path.join(dname, '%s.Machine.key' % ca_cn) self.assertTrue(os.path.exists(machine_key), 'Machine key was not generated') # Verify RSOP does not fail ext.rsop([g for g in gpos if g.name == guid][0]) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) self.assertFalse(os.path.exists(ca_crt), 'Root CA certificate was not removed') self.assertFalse(os.path.exists(machine_crt), 'Machine certificate was not removed') self.assertFalse(os.path.exists(machine_key), 'Machine key was not removed') out, _ = Popen(['getcert', 'list-cas'], stdout=PIPE).communicate() self.assertNotIn(get_bytes(ca_cn), out, 'CA was not removed') out, _ = Popen(['getcert', 'list'], stdout=PIPE).communicate() self.assertNotIn(b'Machine', out, 'Machine certificate not removed') self.assertNotIn(b'Workstation', out, 'Workstation certificate not removed') # Remove the dummy CA, pKIEnrollmentService, and pKICertificateTemplate ldb.delete(certa_dn) ldb.delete(enroll_dn) ldb.delete(template_dn) # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_cert_auto_enroll_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension cae.requests = dummy_requests() ext = cae.gp_cert_auto_enroll_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data parser = GPPolParser() parser.load_xml(etree.fromstring(auto_enroll_reg_pol.strip())) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Write the dummy CA entry, Enrollment Services, and Templates Entries admin_creds = Credentials() admin_creds.set_username(os.environ.get('DC_USERNAME')) admin_creds.set_password(os.environ.get('DC_PASSWORD')) admin_creds.set_realm(os.environ.get('REALM')) hostname = get_dc_hostname(machine_creds, self.lp) url = 'ldap://%s' % hostname ldb = Ldb(url=url, session_info=system_session(), lp=self.lp, credentials=admin_creds) # Write the dummy CA confdn = 'CN=Public Key Services,CN=Services,CN=Configuration,%s' % base_dn ca_cn = '%s-CA' % hostname.replace('.', '-') certa_dn = 'CN=%s,CN=Certification Authorities,%s' % (ca_cn, confdn) ldb.add({'dn': certa_dn, 'objectClass': 'certificationAuthority', 'authorityRevocationList': ['XXX'], 'cACertificate': b'0\x82\x03u0\x82\x02]\xa0\x03\x02\x01\x02\x02\x10I', 'certificateRevocationList': ['XXX'], }) # Write the dummy pKIEnrollmentService enroll_dn = 'CN=%s,CN=Enrollment Services,%s' % (ca_cn, confdn) ldb.add({'dn': enroll_dn, 'objectClass': 'pKIEnrollmentService', 'cACertificate': b'0\x82\x03u0\x82\x02]\xa0\x03\x02\x01\x02\x02\x10I', 'certificateTemplates': ['Machine'], 'dNSHostName': hostname, }) # Write the dummy pKICertificateTemplate template_dn = 'CN=Machine,CN=Certificate Templates,%s' % confdn ldb.add({'dn': template_dn, 'objectClass': 'pKICertificateTemplate', }) with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname, dname) ca_crt = os.path.join(dname, '%s.crt' % ca_cn) self.assertTrue(os.path.exists(ca_crt), 'Root CA certificate was not requested') machine_crt = os.path.join(dname, '%s.Machine.crt' % ca_cn) self.assertTrue(os.path.exists(machine_crt), 'Machine certificate was not requested') machine_key = os.path.join(dname, '%s.Machine.key' % ca_cn) self.assertTrue(os.path.exists(machine_key), 'Machine key was not generated') # Subsequent apply should react to new certificate templates os.environ['CEPCES_SUBMIT_SUPPORTED_TEMPLATES'] = 'Machine,Workstation' self.addCleanup(os.environ.pop, 'CEPCES_SUBMIT_SUPPORTED_TEMPLATES') ext.process_group_policy([], gpos, dname, dname) self.assertTrue(os.path.exists(ca_crt), 'Root CA certificate was not requested') self.assertTrue(os.path.exists(machine_crt), 'Machine certificate was not requested') self.assertTrue(os.path.exists(machine_key), 'Machine key was not generated') workstation_crt = os.path.join(dname, '%s.Workstation.crt' % ca_cn) self.assertTrue(os.path.exists(workstation_crt), 'Workstation certificate was not requested') workstation_key = os.path.join(dname, '%s.Workstation.key' % ca_cn) self.assertTrue(os.path.exists(workstation_key), 'Workstation key was not generated') # Verify RSOP does not fail ext.rsop([g for g in gpos if g.name == guid][0]) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy by staging pol file with auto-enroll unchecked parser.load_xml(etree.fromstring(auto_enroll_unchecked_reg_pol.strip())) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) ext.process_group_policy([], gpos, dname, dname) self.assertFalse(os.path.exists(ca_crt), 'Root CA certificate was not removed') self.assertFalse(os.path.exists(machine_crt), 'Machine certificate was not removed') self.assertFalse(os.path.exists(machine_key), 'Machine key was not removed') self.assertFalse(os.path.exists(workstation_crt), 'Workstation certificate was not removed') self.assertFalse(os.path.exists(workstation_key), 'Workstation key was not removed') # Reapply policy by staging the enabled pol file parser.load_xml(etree.fromstring(auto_enroll_reg_pol.strip())) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) ext.process_group_policy([], gpos, dname, dname) self.assertTrue(os.path.exists(ca_crt), 'Root CA certificate was not requested') self.assertTrue(os.path.exists(machine_crt), 'Machine certificate was not requested') self.assertTrue(os.path.exists(machine_key), 'Machine key was not generated') self.assertTrue(os.path.exists(workstation_crt), 'Workstation certificate was not requested') self.assertTrue(os.path.exists(workstation_key), 'Workstation key was not generated') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) self.assertFalse(os.path.exists(ca_crt), 'Root CA certificate was not removed') self.assertFalse(os.path.exists(machine_crt), 'Machine certificate was not removed') self.assertFalse(os.path.exists(machine_key), 'Machine key was not removed') self.assertFalse(os.path.exists(workstation_crt), 'Workstation certificate was not removed') self.assertFalse(os.path.exists(workstation_key), 'Workstation key was not removed') out, _ = Popen(['getcert', 'list-cas'], stdout=PIPE).communicate() self.assertNotIn(get_bytes(ca_cn), out, 'CA was not removed') out, _ = Popen(['getcert', 'list'], stdout=PIPE).communicate() self.assertNotIn(b'Machine', out, 'Machine certificate not removed') self.assertNotIn(b'Workstation', out, 'Workstation certificate not removed') # Remove the dummy CA, pKIEnrollmentService, and pKICertificateTemplate ldb.delete(certa_dn) ldb.delete(enroll_dn) ldb.delete(template_dn) # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_user_scripts_ext(self): local_path = self.lp.cache_path('gpo_cache') guids = ['{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}'] reg_pol = os.path.join(local_path, policies, guids[0], 'USER/REGISTRY.POL') reg_pol2 = os.path.join(local_path, policies, guids[1], 'USER/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_user_scripts_ext(self.lp, machine_creds, os.environ.get('DC_USERNAME'), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) reg_key = b'Software\\Policies\\Samba\\Unix Settings' sections = { b'%s\\Daily Scripts' % reg_key : b'@daily', b'%s\\Monthly Scripts' % reg_key : b'@monthly', b'%s\\Weekly Scripts' % reg_key : b'@weekly', b'%s\\Hourly Scripts' % reg_key : b'@hourly' } for keyname in sections.keys(): # Stage the Registry.pol file with test data stage = preg.file() e = preg.entry() e.keyname = keyname e.valuename = b'Software\\Policies\\Samba\\Unix Settings' e.type = 1 e.data = b'echo hello world' stage.num_entries = 1 stage.entries = [e] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Stage the other Registry.pol stage = preg.file() e2 = preg.entry() e2.keyname = keyname e2.valuename = b'Software\\Policies\\Samba\\Unix Settings' e2.type = 1 e2.data = b'echo this is a second policy' stage.num_entries = 1 stage.entries = [e2] ret = stage_file(reg_pol2, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol2) # Process all gpos, intentionally skipping the privilege drop ext.process_group_policy([], gpos) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() entry = b'%s %s' % (sections[keyname], e.data.encode()) self.assertIn(entry, crontab, 'The crontab entry was not installed') entry2 = b'%s %s' % (sections[keyname], e2.data.encode()) self.assertIn(entry2, crontab, 'The crontab entry was not installed') # Force apply with removal of second GPO gp_db = store.get_gplog(os.environ.get('DC_USERNAME')) del_gpos = gp_db.get_applied_settings([guids[1]]) rgpos = [gpo for gpo in gpos if gpo.name != guids[1]] ext.process_group_policy(del_gpos, rgpos) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() # Ensure the first entry remains, and the second entry is removed self.assertIn(entry, crontab, 'The first crontab entry was not found') self.assertNotIn(entry2, crontab, 'The second crontab entry was still present') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() self.assertNotIn(entry, crontab, 'Unapply failed to cleanup crontab entry') # Unstage the Registry.pol files unstage_file(reg_pol) unstage_file(reg_pol2) def test_gp_firefox_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_firefox_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data parser = GPPolParser() parser.load_xml(etree.fromstring(firefox_reg_pol.strip())) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) policies_file = os.path.join(dname, 'policies.json') with open(policies_file, 'r') as r: policy_data = json.load(r) expected_policy_data = json.loads(firefox_json_expected) self.assertIn('policies', policy_data, 'Policies were not applied') self.assertEqual(expected_policy_data['policies'].keys(), policy_data['policies'].keys(), 'Firefox policies are missing') for name in expected_policy_data['policies'].keys(): self.assertEqual(expected_policy_data['policies'][name], policy_data['policies'][name], 'Policies were not applied') # Check that modifying the policy will enforce the correct settings entries = [e for e in parser.pol_file.entries if e.valuename != 'AppUpdateURL'] for e in entries: if e.valuename == 'AppAutoUpdate': e.data = 0 parser.pol_file.entries = entries parser.pol_file.num_entries = len(entries) # Stage the Registry.pol file with altered test data unstage_file(reg_pol) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Enforce the altered policy ext.process_group_policy([], gpos) # Check that the App Update policy was altered with open(policies_file, 'r') as r: policy_data = json.load(r) self.assertIn('policies', policy_data, 'Policies were not applied') keys = list(expected_policy_data['policies'].keys()) keys.remove('AppUpdateURL') keys.sort() policy_keys = list(policy_data['policies'].keys()) policy_keys.sort() self.assertEqual(keys, policy_keys, 'Firefox policies are incorrect') for name in policy_data['policies'].keys(): self.assertNotEqual(name, 'AppUpdateURL', 'Failed to remove AppUpdateURL policy') if name == 'AppAutoUpdate': self.assertEqual(False, policy_data['policies'][name], 'Failed to alter AppAutoUpdate policy') continue self.assertEqual(expected_policy_data['policies'][name], policy_data['policies'][name], 'Policies were not applied') # Verify RSOP does not fail ext.rsop([g for g in gpos if g.name == guid][0]) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unapply the policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) if os.path.exists(policies_file): data = json.load(open(policies_file, 'r')) if 'policies' in data.keys(): self.assertEqual(len(data['policies'].keys()), 0, 'The policy was not unapplied') # Initialize the cache with old style existing policies, # ensure they are overwritten. old_cache = {'policies': {}} ext.cache_add_attribute(guid, 'policies.json', json.dumps(old_cache)) with open(policies_file, 'w') as w: w.write(firefox_json_expected) # Overwrite policy ext.process_group_policy([], gpos) # Check that policy was overwritten with open(policies_file, 'r') as r: policy_data = json.load(r) self.assertIn('policies', policy_data, 'Policies were not applied') policy_keys = list(policy_data['policies'].keys()) policy_keys.sort() self.assertEqual(keys, policy_keys, 'Firefox policies are incorrect') for name in policy_data['policies'].keys(): self.assertNotEqual(name, 'AppUpdateURL', 'Failed to remove AppUpdateURL policy') if name == 'AppAutoUpdate': self.assertEqual(False, policy_data['policies'][name], 'Failed to overwrite AppAutoUpdate policy') continue self.assertEqual(expected_policy_data['policies'][name], policy_data['policies'][name], 'Policies were not applied') # Unapply the policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) if os.path.exists(policies_file): data = json.load(open(policies_file, 'r')) if 'policies' in data.keys(): self.assertEqual(len(data['policies'].keys()), 0, 'The policy was not unapplied') # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_chromium_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_chromium_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data parser = GPPolParser() parser.load_xml(etree.fromstring(chromium_reg_pol.strip())) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) managed = os.path.join(dname, 'managed') managed_files = os.listdir(managed) self.assertEqual(len(managed_files), 1, 'Chromium policies are missing') managed_file = os.path.join(managed, managed_files[0]) with open(managed_file, 'r') as r: managed_data = json.load(r) recommended = os.path.join(dname, 'recommended') recommended_files = os.listdir(recommended) self.assertEqual(len(recommended_files), 1, 'Chromium policies are missing') recommended_file = os.path.join(recommended, recommended_files[0]) with open(recommended_file, 'r') as r: recommended_data = json.load(r) expected_managed_data = json.loads(chromium_json_expected_managed) expected_recommended_data = \ json.loads(chromium_json_expected_recommended) self.maxDiff = None self.assertEqual(sorted(expected_managed_data.keys()), sorted(managed_data.keys()), 'Chromium policies are missing') for name in expected_managed_data.keys(): self.assertEqual(expected_managed_data[name], managed_data[name], 'Policies were not applied') self.assertEqual(expected_recommended_data.keys(), recommended_data.keys(), 'Chromium policies are missing') for name in expected_recommended_data.keys(): self.assertEqual(expected_recommended_data[name], recommended_data[name], 'Policies were not applied') # Ensure modifying the policy does not generate extra policy files unstage_file(reg_pol) # Change a managed entry: parser.pol_file.entries[0].data = 0 # Change a recommended entry: parser.pol_file.entries[-1].data = b'https://google.com' ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) ext.process_group_policy([], gpos, dname) managed_files = os.listdir(managed) self.assertEqual(len(managed_files), 1, 'Number of Chromium policies is incorrect') omanaged_file = managed_file managed_file = os.path.join(managed, managed_files[0]) self.assertNotEqual(omanaged_file, managed_file, 'The managed Chromium file did not change') recommended_files = os.listdir(recommended) self.assertEqual(len(recommended_files), 1, 'Number of Chromium policies is incorrect') orecommended_file = recommended_file recommended_file = os.path.join(recommended, recommended_files[0]) self.assertNotEqual(orecommended_file, recommended_file, 'The recommended Chromium file did not change') # Verify RSOP does not fail ext.rsop([g for g in gpos if g.name == guid][0]) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unapply the policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) managed = os.path.join(managed, managed_files[0]) if os.path.exists(managed): data = json.load(open(managed, 'r')) self.assertEqual(len(data.keys()), 0, 'The policy was not unapplied') recommended = os.path.join(recommended, recommended_files[0]) if os.path.exists(recommended): data = json.load(open(recommended, 'r')) self.assertEqual(len(data.keys()), 0, 'The policy was not unapplied') # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_firewalld_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_firewalld_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data parser = GPPolParser() parser.load_xml(etree.fromstring(firewalld_reg_pol.strip())) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) ext.process_group_policy([], gpos) # Check that the policy was applied firewall_cmd = which('firewall-cmd') cmd = [firewall_cmd, '--get-zones'] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() self.assertIn(b'work', out, 'Failed to apply zones') self.assertIn(b'home', out, 'Failed to apply zones') cmd = [firewall_cmd, '--zone=work', '--list-interfaces'] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() self.assertIn(b'eth0', out, 'Failed to set interface on zone') cmd = [firewall_cmd, '--zone=home', '--list-interfaces'] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() self.assertIn(b'eth0', out, 'Failed to set interface on zone') cmd = [firewall_cmd, '--zone=work', '--list-rich-rules'] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() # Firewalld will report the rule one of two ways: rules = [b'rule family=ipv4 source address=172.25.1.7 ' + b'service name=ftp reject', b'rule family="ipv4" source address="172.25.1.7" ' + b'service name="ftp" reject'] self.assertIn(out.strip(), rules, 'Failed to set rich rule') # Check that modifying the policy will enforce the correct settings entries = [e for e in parser.pol_file.entries if e.data != 'home'] self.assertEqual(len(entries), len(parser.pol_file.entries)-1, 'Failed to remove the home zone entry') parser.pol_file.entries = entries parser.pol_file.num_entries = len(entries) # Stage the Registry.pol file with altered test data unstage_file(reg_pol) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Enforce the altered policy ext.process_group_policy([], gpos) # Check that the home zone was removed cmd = [firewall_cmd, '--get-zones'] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() self.assertIn(b'work', out, 'Failed to apply zones') self.assertNotIn(b'home', out, 'Failed to apply zones') # Verify RSOP does not fail ext.rsop([g for g in gpos if g.name == guid][0]) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unapply the policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) # Check that the policy was unapplied cmd = [firewall_cmd, '--get-zones'] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() self.assertNotIn(b'work', out, 'Failed to unapply zones') self.assertNotIn(b'home', out, 'Failed to unapply zones') # Unstage the Registry.pol file unstage_file(reg_pol) def test_advanced_gp_cert_auto_enroll_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension cae.requests = dummy_requests() ext = cae.gp_cert_auto_enroll_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) admin_creds = Credentials() admin_creds.set_username(os.environ.get('DC_USERNAME')) admin_creds.set_password(os.environ.get('DC_PASSWORD')) admin_creds.set_realm(os.environ.get('REALM')) hostname = get_dc_hostname(machine_creds, self.lp) url = 'ldap://%s' % hostname ldb = Ldb(url=url, session_info=system_session(), lp=self.lp, credentials=admin_creds) # Stage the Registry.pol file with test data res = ldb.search('', _ldb.SCOPE_BASE, '(objectClass=*)', ['rootDomainNamingContext']) self.assertTrue(len(res) == 1, 'rootDomainNamingContext not found') res2 = ldb.search(res[0]['rootDomainNamingContext'][0], _ldb.SCOPE_BASE, '(objectClass=*)', ['objectGUID']) self.assertTrue(len(res2) == 1, 'objectGUID not found') objectGUID = b'{%s}' % \ cae.octet_string_to_objectGUID(res2[0]['objectGUID'][0]).upper().encode() parser = GPPolParser() parser.load_xml(etree.fromstring(advanced_enroll_reg_pol.strip() % (objectGUID, objectGUID, objectGUID, objectGUID))) ret = stage_file(reg_pol, ndr_pack(parser.pol_file)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Write the dummy CA entry confdn = 'CN=Public Key Services,CN=Services,CN=Configuration,%s' % base_dn ca_cn = '%s-CA' % hostname.replace('.', '-') certa_dn = 'CN=%s,CN=Certification Authorities,%s' % (ca_cn, confdn) ldb.add({'dn': certa_dn, 'objectClass': 'certificationAuthority', 'authorityRevocationList': ['XXX'], 'cACertificate': b'0\x82\x03u0\x82\x02]\xa0\x03\x02\x01\x02\x02\x10I', 'certificateRevocationList': ['XXX'], }) # Write the dummy pKIEnrollmentService enroll_dn = 'CN=%s,CN=Enrollment Services,%s' % (ca_cn, confdn) ldb.add({'dn': enroll_dn, 'objectClass': 'pKIEnrollmentService', 'cACertificate': b'0\x82\x03u0\x82\x02]\xa0\x03\x02\x01\x02\x02\x10I', 'certificateTemplates': ['Machine'], 'dNSHostName': hostname, }) # Write the dummy pKICertificateTemplate template_dn = 'CN=Machine,CN=Certificate Templates,%s' % confdn ldb.add({'dn': template_dn, 'objectClass': 'pKICertificateTemplate', }) with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname, dname) ca_list = [ca_cn, 'example0-com-CA', 'example1-com-CA', 'example2-com-CA'] for ca in ca_list: ca_crt = os.path.join(dname, '%s.crt' % ca) self.assertTrue(os.path.exists(ca_crt), 'Root CA certificate was not requested') machine_crt = os.path.join(dname, '%s.Machine.crt' % ca) self.assertTrue(os.path.exists(machine_crt), 'Machine certificate was not requested') machine_key = os.path.join(dname, '%s.Machine.key' % ca) self.assertTrue(os.path.exists(machine_key), 'Machine key was not generated') # Subsequent apply should react to new certificate templates os.environ['CEPCES_SUBMIT_SUPPORTED_TEMPLATES'] = 'Machine,Workstation' self.addCleanup(os.environ.pop, 'CEPCES_SUBMIT_SUPPORTED_TEMPLATES') ext.process_group_policy([], gpos, dname, dname) for ca in ca_list: self.assertTrue(os.path.exists(ca_crt), 'Root CA certificate was not requested') self.assertTrue(os.path.exists(machine_crt), 'Machine certificate was not requested') self.assertTrue(os.path.exists(machine_key), 'Machine key was not generated') workstation_crt = os.path.join(dname, '%s.Workstation.crt' % ca) self.assertTrue(os.path.exists(workstation_crt), 'Workstation certificate was not requested') workstation_key = os.path.join(dname, '%s.Workstation.key' % ca) self.assertTrue(os.path.exists(workstation_key), 'Workstation key was not generated') # Verify RSOP does not fail ext.rsop([g for g in gpos if g.name == guid][0]) # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, [], dname) self.assertFalse(os.path.exists(ca_crt), 'Root CA certificate was not removed') self.assertFalse(os.path.exists(machine_crt), 'Machine certificate was not removed') self.assertFalse(os.path.exists(machine_key), 'Machine key was not removed') self.assertFalse(os.path.exists(workstation_crt), 'Workstation certificate was not removed') self.assertFalse(os.path.exists(workstation_key), 'Workstation key was not removed') out, _ = Popen(['getcert', 'list-cas'], stdout=PIPE).communicate() for ca in ca_list: self.assertNotIn(get_bytes(ca), out, 'CA was not removed') out, _ = Popen(['getcert', 'list'], stdout=PIPE).communicate() self.assertNotIn(b'Machine', out, 'Machine certificate not removed') self.assertNotIn(b'Workstation', out, 'Workstation certificate not removed') # Remove the dummy CA, pKIEnrollmentService, and pKICertificateTemplate ldb.delete(certa_dn) ldb.delete(enroll_dn) ldb.delete(template_dn) # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_centrify_sudoers_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_centrify_sudoers_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data stage = preg.file() e1 = preg.entry() e1.keyname = b'Software\\Policies\\Centrify\\UnixSettings' e1.valuename = b'sudo.enabled' e1.type = 4 e1.data = 1 e2 = preg.entry() e2.keyname = b'Software\\Policies\\Centrify\\UnixSettings\\SuDo' e2.valuename = b'1' e2.type = 1 e2.data = b'fakeu ALL=(ALL) NOPASSWD: ALL' stage.num_entries = 2 stage.entries = [e1, e2] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) sudoers = os.listdir(dname) self.assertEqual(len(sudoers), 1, 'The sudoer file was not created') sudoers_file = os.path.join(dname, sudoers[0]) self.assertIn(e2.data, open(sudoers_file, 'r').read(), 'The sudoers entry was not applied') # Remove the sudoers file, and make sure a re-apply puts it back os.unlink(sudoers_file) ext.process_group_policy([], gpos, dname) sudoers = os.listdir(dname) self.assertEqual(len(sudoers), 1, 'The sudoer file was not recreated') sudoers_file = os.path.join(dname, sudoers[0]) self.assertIn(e2.data, open(sudoers_file, 'r').read(), 'The sudoers entry was not reapplied') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) self.assertEqual(len(os.listdir(dname)), 0, 'Unapply failed to cleanup scripts') # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_centrify_crontab_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' reg_pol = os.path.join(local_path, policies, guid, 'MACHINE/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_centrify_crontab_ext(self.lp, machine_creds, machine_creds.get_username(), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data stage = preg.file() e = preg.entry() e.keyname = \ b'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries' e.valuename = b'Command1' e.type = 1 e.data = b'17 * * * * root echo hello world' stage.num_entries = 1 stage.entries = [e] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Process all gpos, with temp output directory with TemporaryDirectory() as dname: ext.process_group_policy([], gpos, dname) cron_entries = os.listdir(dname) self.assertEqual(len(cron_entries), 1, 'Cron entry not created') fname = os.path.join(dname, cron_entries[0]) data = open(fname, 'rb').read() self.assertIn(get_bytes(e.data), data, 'Cron entry is missing') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy gp_db = store.get_gplog(machine_creds.get_username()) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) self.assertEqual(len(os.listdir(dname)), 0, 'Unapply failed to cleanup script') # Unstage the Registry.pol file unstage_file(reg_pol) def test_gp_user_centrify_crontab_ext(self): local_path = self.lp.cache_path('gpo_cache') guids = ['{31B2F340-016D-11D2-945F-00C04FB984F9}', '{6AC1786C-016F-11D2-945F-00C04FB984F9}'] reg_pol = os.path.join(local_path, policies, guids[0], 'USER/REGISTRY.POL') reg_pol2 = os.path.join(local_path, policies, guids[1], 'USER/REGISTRY.POL') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_user_centrify_crontab_ext(self.lp, machine_creds, os.environ.get('DC_USERNAME'), store) gpos = get_gpo_list(self.server, machine_creds, self.lp, machine_creds.get_username()) # Stage the Registry.pol file with test data stage = preg.file() e = preg.entry() e.keyname = \ b'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries' e.valuename = b'Command1' e.type = 1 e.data = b'17 * * * * echo hello world' stage.num_entries = 1 stage.entries = [e] ret = stage_file(reg_pol, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol) # Stage the other Registry.pol stage = preg.file() e2 = preg.entry() e2.keyname = \ b'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries' e2.valuename = b'Command1' e2.type = 1 e2.data = b'17 * * * * echo this is a second policy' stage.num_entries = 1 stage.entries = [e2] ret = stage_file(reg_pol2, ndr_pack(stage)) self.assertTrue(ret, 'Could not create the target %s' % reg_pol2) # Process all gpos, intentionally skipping the privilege drop ext.process_group_policy([], gpos) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() self.assertIn(get_bytes(e.data), crontab, 'The crontab entry was not installed') self.assertIn(get_bytes(e2.data), crontab, 'The crontab entry was not installed') # Force apply with removal of second GPO gp_db = store.get_gplog(os.environ.get('DC_USERNAME')) del_gpos = gp_db.get_applied_settings([guids[1]]) gpos = [gpo for gpo in gpos if gpo.name != guids[1]] ext.process_group_policy(del_gpos, gpos) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() # Ensure the first entry remains, and the second entry is removed self.assertIn(get_bytes(e.data), crontab, 'The first crontab entry was not found') self.assertNotIn(get_bytes(e2.data), crontab, 'The second crontab entry was still present') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Remove policy del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() self.assertNotIn(get_bytes(e.data), crontab, 'Unapply failed to cleanup crontab entry') # Unstage the Registry.pol files unstage_file(reg_pol) unstage_file(reg_pol2) def test_gp_drive_maps_user_ext(self): local_path = self.lp.cache_path('gpo_cache') guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}' xml_path = os.path.join(local_path, policies, guid, 'USER/PREFERENCES/DRIVES/DRIVES.XML') cache_dir = self.lp.get('cache directory') store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb')) machine_creds = Credentials() machine_creds.guess(self.lp) machine_creds.set_machine_account() # Initialize the group policy extension ext = gp_drive_maps_user_ext(self.lp, machine_creds, os.environ.get('DC_USERNAME'), store) ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds) if ads.connect(): gpos = ads.get_gpo_list(machine_creds.get_username()) # Stage the Drives.xml file with test data ret = stage_file(xml_path, drive_maps_xml) self.assertTrue(ret, 'Could not create the target %s' % xml_path) # Process all gpos, intentionally skipping the privilege drop ext.process_group_policy([], gpos) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() entry = b'@hourly gio mount smb://example.com/test' self.assertIn(entry, crontab, 'The crontab entry was not installed') # Check that a call to gpupdate --rsop also succeeds ret = rsop(self.lp) self.assertEqual(ret, 0, 'gpupdate --rsop failed!') # Unstage the Drives.xml unstage_file(xml_path) # Modify the policy and ensure it is updated xml_conf = etree.fromstring(drive_maps_xml.strip()) drives = xml_conf.findall('Drive') props = drives[0].find('Properties') props.attrib['action'] = 'D' ret = stage_file(xml_path, etree.tostring(xml_conf, encoding='unicode')) self.assertTrue(ret, 'Could not create the target %s' % xml_path) # Process all gpos, intentionally skipping the privilege drop ext.process_group_policy([], gpos) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() self.assertNotIn(entry+b'\n', crontab, 'The old crontab entry was not removed') entry = entry + b' --unmount' self.assertIn(entry, crontab, 'The crontab entry was not installed') # Remove policy gp_db = store.get_gplog(os.environ.get('DC_USERNAME')) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() self.assertNotIn(entry, crontab, 'Unapply failed to cleanup crontab entry') # Unstage the Drives.xml unstage_file(xml_path) # Modify the policy to set 'run once', ensure there is no cron entry xml_conf = etree.fromstring(drive_maps_xml.strip()) drives = xml_conf.findall('Drive') filters = etree.SubElement(drives[0], 'Filters') etree.SubElement(filters, 'FilterRunOnce') ret = stage_file(xml_path, etree.tostring(xml_conf, encoding='unicode')) self.assertTrue(ret, 'Could not create the target %s' % xml_path) # Process all gpos, intentionally skipping the privilege drop ext.process_group_policy([], gpos) # Dump the fake crontab setup for testing p = Popen(['crontab', '-l'], stdout=PIPE) crontab, _ = p.communicate() entry = b'@hourly gio mount smb://example.com/test' self.assertNotIn(entry, crontab, 'The crontab entry was added despite run-once request') # Remove policy gp_db = store.get_gplog(os.environ.get('DC_USERNAME')) del_gpos = get_deleted_gpos_list(gp_db, []) ext.process_group_policy(del_gpos, []) # Unstage the Drives.xml unstage_file(xml_path) def test_expand_pref_variables(self): cache_path = self.lp.cache_path(os.path.join('gpo_cache')) gpt_path = 'TEST' username = 'test_uname' test_vars = { 'AppDataDir': os.path.expanduser('~/.config'), 'ComputerName': self.lp.get('netbios name'), 'DesktopDir': os.path.expanduser('~/Desktop'), 'DomainName': self.lp.get('realm'), 'GptPath': os.path.join(cache_path, check_safe_path(gpt_path).upper()), 'LogonDomain': self.lp.get('realm'), 'LogonUser': username, 'SystemDrive': '/', 'TempDir': '/tmp' } for exp_var, val in test_vars.items(): self.assertEqual(expand_pref_variables('%%%s%%' % exp_var, gpt_path, self.lp, username), val, 'Failed to expand variable %s' % exp_var) # With the time variables, we can't test for an exact time, so let's do # simple checks instead. time_vars = ['DateTime', 'DateTimeEx', 'LocalTime', 'LocalTimeEx', 'TimeStamp'] for time_var in time_vars: self.assertNotEqual(expand_pref_variables('%%%s%%' % time_var, gpt_path, self.lp, username), None, 'Failed to expand variable %s' % time_var) # Here we test to ensure undefined preference variables cause an error. # The reason for testing these is to ensure we don't apply nonsense # policies when they can't be defined. Also, these tests will fail if # one of these is implemented in the future (forcing us to write a test # anytime these are implemented). undef_vars = ['BinaryComputerSid', 'BinaryUserSid', 'CommonAppdataDir', 'CommonDesktopDir', 'CommonFavoritesDir', 'CommonProgramsDir', 'CommonStartUpDir', 'CurrentProccessId', 'CurrentThreadId', 'FavoritesDir', 'GphPath', 'GroupPolicyVersion', 'LastDriveMapped', 'LastError', 'LastErrorText', 'LdapComputerSid', 'LdapUserSid', 'LogonServer', 'LogonUserSid', 'MacAddress', 'NetPlacesDir', 'OsVersion', 'ProgramFilesDir', 'ProgramsDir', 'RecentDocumentsDir', 'ResultCode', 'ResultText', 'ReversedComputerSid', 'ReversedUserSid', 'SendToDir', 'StartMenuDir', 'StartUpDir', 'SystemDir', 'TraceFile', 'WindowsDir' ] for undef_var in undef_vars: try: expand_pref_variables('%%%s%%' % undef_var, gpt_path, self.lp) except NameError: pass else: self.fail('Undefined variable %s caused no error' % undef_var) def test_parser_roundtrip_empty_multi_sz(self): with TemporaryDirectory() as dname: reg_pol_xml = os.path.join(dname, 'REGISTRY.POL.XML') parser = GPPolParser() try: parser.load_xml(etree.fromstring(empty_multi_sz_reg_pol.strip())) except Exception as e: self.fail(str(e)) parser.write_xml(reg_pol_xml) with open(reg_pol_xml, 'r') as f: pol_xml_data = f.read() # Strip whitespace characters due to indentation differences expected_xml_data = re.sub(r"\s+", "", empty_multi_sz_reg_pol.decode(), flags=re.UNICODE) actual_xml_data = re.sub(r"\s+", "", pol_xml_data, flags=re.UNICODE) self.assertEqual(expected_xml_data, actual_xml_data, 'XML data mismatch') def test_parser_roundtrip_multiple_values_multi_sz(self): with TemporaryDirectory() as dname: reg_pol_xml = os.path.join(dname, 'REGISTRY.POL.XML') parser = GPPolParser() try: parser.load_xml(etree.fromstring(multiple_values_multi_sz_reg_pol.strip())) except Exception as e: self.fail(str(e)) parser.write_xml(reg_pol_xml) with open(reg_pol_xml, 'r') as f: pol_xml_data = f.read() # Strip whitespace characters due to indentation differences expected_xml_data = re.sub(r"\s+", "", multiple_values_multi_sz_reg_pol.decode(), flags=re.UNICODE) actual_xml_data = re.sub(r"\s+", "", pol_xml_data, flags=re.UNICODE) self.assertEqual(expected_xml_data, actual_xml_data, 'XML data mismatch')