mozilla / policy-templates

Policy Templates for Firefox
Mozilla Public License 2.0
1.14k stars 406 forks source link

Add policies Types for JavaScript/TypeScript project #1095

Open qupig opened 5 months ago

qupig commented 5 months ago

I would like to do this by writing the policies template with type checking in a JavaScript file and then generating the policies.json or org.mozilla.firefox.plist file directly. (I'm not familiar with Windows Group Policy, but maybe it works as well.)

Type checking helps us write correct template object, or can be used to build front-end GUI interfaces.

The json and plist conversion can be easily done using plutil that comes with macOS:

# json -> plist
plutil -convert xml1 "policies.json" -o "org.mozilla.firefox.plist"
# json -> binary plist
plutil -convert binary1 "policies.json" -o "org.mozilla.firefox.plist"
# plist -> json
plutil -convert json "org.mozilla.firefox.plist" -o "policies.json"

I've tried using this example policies.json to write the Types definition.

But what I'm interested in is, how is this file generated?

It's not a legal JSON file, but more like an interface defined in TypeScript, except it uses some actual strings as examples.

Is there already a hidden project used to generate the example files that already contains those Type definitions?

Or would the project be interested in receiving contributions to add Type definitions and/or conversion tools?

I just hope that we don’t reinvent the wheel, or that creating a wheel can help more developers/users with the same needs.

mkaply commented 5 months ago

That file is a sample file that's not intended to be used directly until it's modified.

For booleans, it shows both options.

This would normally be generated by hand based on the info in the template docs.

Someone built an addon to do this as well

https://addons.mozilla.org/en-US/firefox/addon/enterprise-policy-generator/

qupig commented 5 months ago

That file is a sample file that's not intended to be used directly until it's modified. For booleans, it shows both options.

Yes, I know, that takes a lot of conversion, and I've noticed some errors.

This would normally be generated by hand based on the info in the template docs.

Oh, and thanks for the work you put into this, it would be nice to have some automated processes.

https://addons.mozilla.org/en-US/firefox/addon/enterprise-policy-generator/

Good to know, I checked out the project and it produces some meta data policies.js, that's nice, but it seems the project stopped being updated about 4 years ago?


I was just thinking about something simple that would be helpful for this project, maybe just some cli utils.

By the way, I just performed some simple transformations on it (unfinished):

policy-templates.d.ts ```ts /** * @see {@link https://mozilla.github.io/policy-templates/#preferences Preferences} */ interface Preferences { Type?: "number" | "boolean" | "string"; Value: number | boolean | string; Status: "default" | "locked" | "user" | "clear"; } /** * @see {@link https://github.com/mozilla/policy-templates/blob/master/linux/policies.json} */ interface PolicyTemplate { policies?: { /** example: "managedfirefox.com,example.com" */ AllowedDomainsForApps?: string; AppAutoUpdate?: boolean; /** example: "106." */ AppUpdatePin?: string; /** example: "https://yoursite.com" */ AppUpdateURL?: string; Authentication?: { /** example: ["mydomain.com", "https://myotherdomain.com"] */ SPNEGO?: string[]; /** example: ["mydomain.com", "https://myotherdomain.com"] */ Delegated?: string[]; /** example: ["mydomain.com", "https://myotherdomain.com"] */ NTLM?: string[]; AllowNonFQDN?: { SPNEGO?: boolean; NTLM?: boolean; }; AllowProxies?: { SPNEGO?: boolean; NTLM?: boolean; }; Locked?: boolean; PrivateBrowsing?: boolean; }; AutoLaunchProtocolsFromOrigins?: [ { /** example: "zoommtg" */ protocol?: string; /** example: ["https://somesite.zoom.us"] */ allowed_origins?: string[]; } ]; BackgroundAppUpdate?: boolean; BlockAboutAddons?: boolean; BlockAboutConfig?: boolean; BlockAboutProfiles?: boolean; BlockAboutSupport?: boolean; Bookmarks?: [ { /** example: "Example" */ Title?: string; /** example: "https://example.com" */ URL?: string; /** example: "https://example.com/favicon.ico" */ Favicon?: string; Placement?: "toolbar" | "menu"; /** example: "FolderName" */ Folder?: string; } ]; CaptivePortal?: boolean; Certificates?: { /** example: ["cert1.der", "/home/username/cert2.pem"] */ Install?: string[]; }; Containers?: { Default?: [ { /** example: "My container" */ name?: string; /** example: "pet" */ icon?: string; /** example: "turquoise" */ color?: string; } ]; }; Cookies?: { /** example: ["http://example.org/"] */ Allow?: string[]; /** example: ["http://example.edu/"] */ AllowSession?: string[]; /** example: ["http://example.edu/"] */ Block?: string[]; Default?: boolean; AcceptThirdParty?: "always" | "never" | "from-visited"; ExpireAtSessionEnd?: boolean; RejectTracker?: boolean; Locked?: boolean; Behavior?: | "accept" | "reject-foreign" | "reject" | "limit-foreign" | "reject-tracker" | "reject-tracker-and-partition-foreign"; BehaviorPrivateBrowsing?: | "accept" | "reject-foreign" | "reject" | "limit-foreign" | "reject-tracker" | "reject-tracker-and-partition-foreign"; }; /** example: "${home}/Downloads" */ DefaultDownloadDirectory?: string; DisableAppUpdate?: boolean; DisableBuiltinPDFViewer?: boolean; DisabledCiphers?: { CIPHER_NAME?: boolean; }; DisableDeveloperTools?: boolean; DisableFeedbackCommands?: boolean; DisableFirefoxAccounts?: boolean; DisableFirefoxScreenshots?: boolean; DisableFirefoxStudies?: boolean; DisableForgetButton?: boolean; DisableFormHistory?: boolean; DisableMasterPasswordCreation?: boolean; DisablePasswordReveal?: boolean; DisablePocket?: boolean; DisablePrivateBrowsing?: boolean; DisableProfileImport?: boolean; DisableProfileRefresh?: boolean; DisableSafeMode?: boolean; DisableSecurityBypass?: { InvalidCertificate?: boolean; SafeBrowsing?: boolean; }; DisableSetDesktopBackground?: boolean; DisableSystemAddonUpdate?: boolean; DisableTelemetry?: boolean; DisplayBookmarksToolbar?: "always" | "never" | "newtab"; DisplayMenuBar?: "always" | "never" | "default-on" | "default-off"; DNSOverHTTPS?: { Enabled?: boolean; /** example: "URL_TO_ALTERNATE_PROVIDER" */ ProviderURL?: string; Locked?: boolean; /** example: ["example.com"] */ ExcludedDomains?: string[]; }; DontCheckDefaultBrowser?: boolean; /** example: "${home}/Downloads" */ DownloadDirectory?: string; EnableTrackingProtection?: { Value?: boolean; Locked?: boolean; Cryptomining?: boolean; Fingerprinting?: boolean; EmailTracking?: boolean; /** example: ["https://example.com"] */ Exceptions?: string[]; }; EncryptedMediaExtensions?: { Enabled?: boolean; Locked?: boolean; }; ExemptDomainFileTypePairsFromFileTypeDownloadWarnings?: [ { /** example: "jnlp" */ file_extension?: string; /** example: ["example.com"] */ domains?: string[]; } ]; Extensions?: { Install?: [ "https://addons.mozilla.org/firefox/downloads/somefile.xpi", "//path/to/xpi" ]; /** example: ["bad_addon_id@mozilla.org"] */ Uninstall?: string[]; /** example: ["addon_id@mozilla.org"] */ Locked?: string[]; }; ExtensionSettings?: { "*": { /** example: "Custom error message." */ blocked_install_message?: string; /** example: ["https://yourwebsite.com/*"] */ install_sources?: string[]; /** example: "blocked" */ installation_mode?: string; /** example: ["extension"] */ allowed_types?: string[]; }; "uBlock0@raymondhill.net": { /** example: "force_installed" */ installation_mode?: string; /** example: "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi" */ install_url?: string; }; "https-everywhere@eff.org": { /** example: "allowed" */ installation_mode?: string; }; }; ExtensionUpdate?: boolean; FirefoxHome?: { Search?: boolean; TopSites?: boolean; SponsoredTopSites?: boolean; Highlights?: boolean; Pocket?: boolean; SponsoredPocket?: boolean; Snippets?: boolean; Locked?: boolean; }; FirefoxSuggest?: { WebSuggestions?: boolean; SponsoredSuggestions?: boolean; ImproveSuggest?: boolean; Locked?: boolean; }; GoToIntranetSiteForSingleWordEntryInAddressBar?: boolean; Handlers?: { mimeTypes?: { "application/msword": { /** example: "useSystemDefault" */ action?: string; ask?: false; }; }; schemes?: { mailto?: { /** example: "useHelperApp" */ action?: string; ask?: boolean; handlers?: [ { /** example: "Gmail" */ name?: string; /** example: "https://mail.google.com/mail/?extsrc=mailto&url=%s" */ uriTemplate?: string; } ]; }; }; extensions?: { pdf?: { /** example: "useHelperApp" */ action?: string; ask?: boolean; handlers?: [ { /** example: "Adobe Acrobat" */ name?: string; /** example: "/usr/bin/acroread" */ path?: string; } ]; }; }; }; HardwareAcceleration?: boolean; Homepage?: { /** example: "http://example.com/" */ URL?: string; Locked?: boolean; /** example: ["http://example.org/", "http://example.edu/"] */ Additional?: string[]; StartPage?: "none" | "homepage" | "previous-session" | "homepage-locked"; }; InstallAddonsPermission?: { /** example: ["http://example.org/", "http://example.edu/"] */ Allow?: string[]; Default?: boolean; }; LegacySameSiteCookieBehaviorEnabled?: boolean; /** example: ["example.org", "example.edu"] */ LegacySameSiteCookieBehaviorEnabledForDomainList?: string[]; /** example: ["http://example.org/", "http://example.edu/"] */ LocalFileLinks?: string[]; ManagedBookmarks?: [ { /** example: "My managed bookmarks folder" */ toplevel_name?: string; }, { /** example: "example.com" */ url?: string; /** example: "Example" */ name?: string; }, { /** example: "Mozilla links" */ name?: string; children?: [ { /** example: "https://mozilla.org" */ url?: string; /** example: "Mozilla.org" */ name?: string; }, { /** example: "https://support.mozilla.org/" */ url?: string; /** example: "SUMO" */ name?: string; } ]; } ]; NetworkPrediction?: boolean; NewTabPage?: boolean; NoDefaultBookmarks?: boolean; OfferToSaveLogins?: boolean; OfferToSaveLoginsDefault?: boolean; /** example: "http://example.org" */ OverrideFirstRunPage?: string; /** example: "http://example.org" */ OverridePostUpdatePage?: string; PasswordManagerEnabled?: boolean; /** example: ["https://example.org", "https://example.edu"] */ PasswordManagerExceptions?: string[]; PDFjs?: { Enabled?: boolean; EnablePermissions?: boolean; }; Permissions?: { Camera?: { /** example: ["https://example.org", "https://example.org:1234"] */ Allow?: string[]; /** example: ["https://example.edu"] */ Block?: string[]; BlockNewRequests?: boolean; Locked?: boolean; }; Microphone?: { /** example: ["https://example.org"] */ Allow?: string[]; /** example: ["https://example.edu"] */ Block?: string[]; BlockNewRequests?: boolean; Locked?: boolean; }; Location?: { /** example: ["https://example.org"] */ Allow?: string[]; /** example: ["https://example.edu"] */ Block?: string[]; BlockNewRequests?: boolean; Locked?: boolean; }; Notifications?: { /** example: ["https://example.org"] */ Allow?: string[]; /** example: ["https://example.edu"] */ Block?: string[]; BlockNewRequests?: boolean; Locked?: boolean; }; Autoplay?: { /** example: ["https://example.org"] */ Allow?: string[]; /** example: ["https://example.edu"] */ Block?: string[]; Default?: "allow-audio-video" | "block-audio" | "block-audio-video"; Locked?: boolean; }; }; PictureInPicture?: { Enabled?: boolean; Locked?: boolean; }; PopupBlocking?: { /** example: ["http://example.org/", "http://example.edu/"] */ Allow?: string[]; Default?: boolean; Locked?: boolean; }; Preferences?: { [x: string]: Preferences }; PrimaryPassword?: boolean; PrintingEnabled?: boolean; PromptForDownloadLocation?: boolean; Proxy?: { Mode?: "none" | "system" | "manual" | "autoDetect" | "autoConfig"; Locked?: boolean; /** example: "hostname" */ HTTPProxy?: string; UseHTTPProxyForAllProtocols?: boolean; /** example: "hostname" */ SSLProxy?: string; /** example: "hostname" */ FTPProxy?: string; /** example: "hostname" */ SOCKSProxy?: string; SOCKSVersion?: 4 | 5; /** example: "" */ Passthrough?: string; /** example: "URL_TO_AUTOCONFIG" */ AutoConfigURL?: string; AutoLogin?: boolean; UseProxyForDNS?: boolean; }; /** example: "de,en-US" */ RequestedLocales?: string; SanitizeOnShutdown?: { Cache?: boolean; Cookies?: boolean; Downloads?: boolean; FormData?: boolean; History?: boolean; Sessions?: boolean; SiteSettings?: boolean; OfflineApps?: boolean; Locked?: boolean; }; SearchEngines?: { Add?: [ { /** example: "Example1" */ Name?: string; /** example: "https://www.example.org/q={searchTerms}" */ URLTemplate?: string; Method?: "GET" | "POST"; /** example: "https://www.example.org/favicon.ico" */ IconURL?: string; /** example: "example" */ Alias?: string; /** example: "Description" */ Description?: string; /** example: "name=value&q={searchTerms}" */ PostData?: string; /** example: "https://www.example.org/suggestions/q={searchTerms}" */ SuggestURLTemplate?: string; } ]; /** example: "NAME_OF_SEARCH_ENGINE" */ Default?: string; PreventInstalls?: boolean; /** example: ["NAME_OF_SEARCH_ENGINE"] */ Remove?: string[]; }; SearchSuggestEnabled?: boolean; SecurityDevices?: { /** example: "PATH_TO_LIBRARY_FOR_DEVICE" */ NAME_OF_DEVICE?: string; }; ShowHomeButton?: boolean; SSLVersionMax?: "tls1" | "tls1.1" | "tls1.2" | "tls1.3"; SSLVersionMin?: "tls1" | "tls1.1" | "tls1.2" | "tls1.3"; SupportMenu?: { /** example: "Support Menu" */ Title?: string; /** example: "http://example.com/support" */ URL?: string; /** example: "S" */ AccessKey?: string; }; StartDownloadsInTempDirectory?: boolean; UserMessaging?: { WhatsNew?: boolean; ExtensionRecommendations?: boolean; FeatureRecommendations?: boolean; UrlbarInterventions?: boolean; SkipOnboarding?: boolean; MoreFromMozilla?: boolean; Locked?: boolean; }; UseSystemPrintDialog?: boolean; WebsiteFilter?: { /** example: [""] */ Block?: string[]; /** example: ["http://example.org/*"] */ Exceptions?: string[]; }; }; } ```
mkaply commented 5 months ago

So you're thinking this would be a separate file in github?

qupig commented 5 months ago

So you're thinking this would be a separate file in github?

I don't know. What do you think? If that helps people use the repo and get continued updates, why not?

But more importantly, I don't want anyone to increase their workload by maintaining this file individually.

So I'd like to have a set of source data there for generating these types, demo templates, or even the documentation.

Essentially I hope to reduce the workload of this repo and make it more usable by people.

It's not that easy to create anything useful from a document, and it's easy to make mistakes by repeating templates by hand.

Specifically, I might want create a generator similar to the project below that generates the required file types from upstream source data and is sustainably maintained.

https://github.com/Lusito/webextension-polyfill-ts#news-this-has-changed-to-be-a-pure-generator-project

Making an external project or extension may be easy, but keeping it up to date with upstream is not easy unless we embed it into a CI/CD workflow.

qupig commented 5 months ago

So it looks like the required upstream source data is at: policies-schema.json

mkaply commented 5 months ago

I love this idea. Policies-schema.json definitely has all the information we need in it.

I'll support you however I can.

Right now my release work is very manual and anything I could automate would be great.