From bb251e5e6066d4eb89cdb70f682dfe7a88030a13 Mon Sep 17 00:00:00 2001 From: Ahmed Abdelhalim Date: Mon, 24 Nov 2025 22:16:43 +0100 Subject: Add initial firefox role implementation with only GNOME support for pass --- roles/firefox/defaults/main.yml | 124 +++++++++++++++++++++++++ roles/firefox/meta/argument_specs.yml | 136 ++++++++++++++++++++++++++++ roles/firefox/meta/main.yml | 21 +++++ roles/firefox/tasks/install_browserpass.yml | 48 ++++++++++ roles/firefox/tasks/install_passff.yml | 44 +++++++++ roles/firefox/tasks/main.yml | 45 +++++++++ roles/firefox/vars/archlinux.yml | 6 ++ roles/firefox/vars/debian.yml | 7 ++ 8 files changed, 431 insertions(+) create mode 100644 roles/firefox/defaults/main.yml create mode 100644 roles/firefox/meta/argument_specs.yml create mode 100644 roles/firefox/meta/main.yml create mode 100644 roles/firefox/tasks/install_browserpass.yml create mode 100644 roles/firefox/tasks/install_passff.yml create mode 100644 roles/firefox/tasks/main.yml create mode 100644 roles/firefox/vars/archlinux.yml create mode 100644 roles/firefox/vars/debian.yml (limited to 'roles/firefox') diff --git a/roles/firefox/defaults/main.yml b/roles/firefox/defaults/main.yml new file mode 100644 index 00000000..dc53080f --- /dev/null +++ b/roles/firefox/defaults/main.yml @@ -0,0 +1,124 @@ +--- +# Check firefox policies documentation at: +# https://mozilla.github.io/policy-templates/ +# The policies override dictionary can be used to override the default policies. +# This is merged with the _firefox_policies_default dictionary, +# and converted into JSON format using a Jinja2 tojson filter. +firefox_policies_override: {} +firefox_extra_extensions: {} + +# Default extensions to be installed in Firefox. +firefox_default_extensions: + "*": + installation_mode: "allowed" # options: allowed, blocked, force_installed, normal_installed + allowed_types: + - "extension" + - "theme" + - "dictionary" + - "locale" + # Get the guid using `curl -s "https://addons.mozilla.org/api/v5/addons/addon/{slug}/" | jq '.guid'` + # where the {slug} is found on the https://addons.mozilla.org/en-US/firefox/ search. + "uBlock0@raymondhill.net": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi" + "{d7742d87-e61d-4b78-b8a1-b469842139fa}": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/vimium-ff/latest.xpi" + "jid1-MnnxcxisBPnSXQ@jetpack": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi" + "woop-NoopscooPsnSXQ@jetpack": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/privacy-possum/latest.xpi" + "languagetool-webextension@languagetool.org": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/languagetool/latest.xpi" + +# Default (sensible) policies for Firefox. +firefox_default_policies: + AutofillAddressEnabled: true + AutofillCreditCardEnabled: false + BlockAboutAddons: false + BlockAboutConfig: false + BlockAboutProfiles: false + BlockAboutSupport: false + CaptivePortal: true + DisableDeveloperTools: false + DisableEncryptedClientHello: false + DisableFeedbackCommands: true + DisableFirefoxAccounts: false + DisableFirefoxScreenshots: true + DisableFirefoxStudies: true + DisablePasswordReveal: false + DisableProfileImport: true + DisableProfileRefresh: true + DisableSafeMode: false + DisableTelemetry: true + DisablePocket: true + DisplayBookmarksToolbar: "always" # options: always, never, newtab + DisplayMenuBar: "default-on" # options: always, never, default-on, default-off + DNSOverHTTPS: + Enabled: true + Fallback: true + DontCheckDefaultBrowser: true + EnableTrackingProtection: + Value: true + Category: "strict" # options: standard, strict + ExtensionSettings: + "{{ firefox_default_extensions | combine(firefox_extra_extensions) }}" + FirefoxHome: + Search: true + TopSites: true + SponsoredTopSites: false + SponsoredPocket: false + SponsoredStories: false + Highlights: true + Pocket: false + Stories: false + Snippets: true + Locked: false + FirefoxSuggest: + WebSuggestions: false + SponsoredSuggestions: false + ImproveSuggest: false + Locked: false + GenerativeAI: + Enabled: false + Locked: false + Homepage: + StartupPage: "homepage" # options: none, homepage, previous-session, homepage-locked + HttpsOnlyMode: "enabled" # options: allowed, disallowed, enabled, force_enabled + LegacyProfiles: false + PasswordManagerEnabled: false + PictureInPicture: + Enabled: true + PostQuantumKeyAgreementEnabled: true + PrintingEnabled: true + PrivateBrowsingModeAvailability: 0 # options: 0 (enabled), 1 (disabled), 2 (forced) + RequestedLocales: + - "en-US" + - "de" + SearchBar: "unified" # options: unified, separate + SearchEngines: + Default: "DuckDuckGo" + PreventInstalls: true + Remove: + - "Bing" + - "Ecosia" + - "Amazon" + - "eBay" + - "Twitter" + - "Wikipedia (en)" + SearchSuggestEnabled: true + ShowHomeButton: false + SkipTermsOfUse: true + TranslateEnabled: true + UserMessaging: + ExtensionRecommendations: false + FeatureRecommendations: false + UrlbarInterventions: false + SkipOnboarding: true + MoreFromMozilla: false + FirfoxLabs: false + UseSystemPrintDialog: true + VisualSearchEnabled: true diff --git a/roles/firefox/meta/argument_specs.yml b/roles/firefox/meta/argument_specs.yml new file mode 100644 index 00000000..ebae7a94 --- /dev/null +++ b/roles/firefox/meta/argument_specs.yml @@ -0,0 +1,136 @@ +--- +# NOTE: The defaults below are sensible role defaults and are not meant to be changed directly. +# Use the override variables (firefox_policies_override, firefox_extra_extensions) to customize behavior. +argument_specs: + main: + short_description: "Configure firefox settings and policies" + description: "Configure firefox settings and policies" + options: + firefox_policies_override: + type: "dict" + description: "Override default firefox policies" + default: {} + firefox_extra_extensions: + type: "dict" + description: "Extra firefox extensions to install via policies (added to the default extensions)" + default: {} + firefox_default_extensions: + # Default extensions to be installed in Firefox via policies + # - uBlock Origin + # - Vimium FF + # - Privacy Badger + # - Privacy Possum + # - LanguageTool + type: "dict" + description: "Default firefox extensions configurations to install via policies" + default: + "*": + installation_mode: "allowed" + allowed_types: + - "extension" + - "theme" + - "dictionary" + - "locale" + "uBlock0@raymondhill.net": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi" + "{d7742d87-e61d-4b78-b8a1-b469842139fa}": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/vimium-ff/latest.xpi" + "jid1-MnnxcxisBPnSXQ@jetpack": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi" + "woop-NoopscooPsnSXQ@jetpack": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/privacy-possum/latest.xpi" + "languagetool-webextension@languagetool.org": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/languagetool/latest.xpi" + firefox_default_policies: + type: "dict" + description: "Default (sensible) policies for Firefox" + default: + AutofillAddressEnabled: true + AutofillCreditCardEnabled: false + BlockAboutAddons: false + BlockAboutConfig: false + BlockAboutProfiles: false + BlockAboutSupport: false + CaptivePortal: true + DisableDeveloperTools: false + DisableEncryptedClientHello: false + DisableFeedbackCommands: true + DisableFirefoxAccounts: false + DisableFirefoxScreenshots: true + DisableFirefoxStudies: true + DisablePasswordReveal: false + DisableProfileImport: true + DisableProfileRefresh: true + DisableSafeMode: false + DisableTelemetry: true + DisablePocket: true + DisplayBookmarksToolbar: "always" + DisplayMenuBar: "default-on" + DNSOverHTTPS: + Enabled: true + Fallback: true + DontCheckDefaultBrowser: true + EnableTrackingProtection: + Value: true + Category: "strict" + FirefoxHome: + Search: true + TopSites: true + SponsoredTopSites: false + SponsoredPocket: false + SponsoredStories: false + Highlights: true + Pocket: false + Stories: false + Snippets: true + Locked: false + FirefoxSuggest: + WebSuggestions: false + SponsoredSuggestions: false + ImproveSuggest: false + Locked: false + GenerativeAI: + Enabled: false + Locked: false + Homepage: + StartupPage: "homepage" + HttpsOnlyMode: "enabled" + LegacyProfiles: false + PasswordManagerEnabled: false + PictureInPicture: + Enabled: true + PostQuantumKeyAgreementEnabled: true + PrintingEnabled: true + PrivateBrowsingModeAvailability: 0 + RequestedLocales: + - "en-US" + - "de" + SearchBar: "unified" + SearchEngines: + Default: "DuckDuckGo" + PreventInstalls: true + Remove: + - "Bing" + - "Ecosia" + - "Amazon" + - "eBay" + - "Twitter" + - "Wikipedia (en)" + SearchSuggestEnabled: true + ShowHomeButton: false + SkipTermsOfUse: true + TranslateEnabled: true + UserMessaging: + ExtensionRecommendations: false + FeatureRecommendations: false + UrlbarInterventions: false + SkipOnboarding: true + MoreFromMozilla: false + FirfoxLabs: false + UseSystemPrintDialog: true + VisualSearchEnabled: true diff --git a/roles/firefox/meta/main.yml b/roles/firefox/meta/main.yml new file mode 100644 index 00000000..3da12597 --- /dev/null +++ b/roles/firefox/meta/main.yml @@ -0,0 +1,21 @@ +--- +dependencies: + - role: "sed" + - role: "python" + - role: "bash" +galaxy_info: + author: "a14m" + description: "Configure firefox settings and policies." + company: "kartoffeln.work GmbH." + license: "MIT" + min_ansible_version: "2.18" + platforms: + - name: "ArchLinux" + versions: + - "all" + - name: "Ubuntu" + versions: + - "noble" + - name: "Debian" + versions: + - "bookworm" diff --git a/roles/firefox/tasks/install_browserpass.yml b/roles/firefox/tasks/install_browserpass.yml new file mode 100644 index 00000000..50d6cef2 --- /dev/null +++ b/roles/firefox/tasks/install_browserpass.yml @@ -0,0 +1,48 @@ +--- +- name: "Add browserpass to default extensions" + ansible.builtin.set_fact: + firefox_default_extensions: "{{ firefox_default_extensions | combine(firefox_browserpass_extension) }}" + vars: + firefox_browserpass_extension: + "browserpass@maximbaz.com": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/browserpass-ce/latest.xpi" + +- name: "Ensure browserpass native messaging host is installed" + become: true + ansible.builtin.package: + name: "{{ firefox_browserpass_packages }}" + state: "present" + +- name: "Create native messaging hosts directory" + become: true + ansible.builtin.file: + path: "/usr/lib/mozilla/native-messaging-hosts" + state: "directory" + mode: "0755" + +- name: "Create browserpass native messaging hosts file" + become: true + ansible.builtin.copy: + dest: "/usr/lib/mozilla/native-messaging-hosts/com.github.browserpass.native.json" + mode: "0644" + content: | + { + "name": "com.github.browserpass.native", + "description": "Browserpass native component for the Firefox extension", + "path": "/usr/lib/browserpass/browserpass-wrapper", + "type": "stdio", + "allowed_extensions": ["browserpass@maximbaz.com"] + } + +- name: "Create browserpass-native wrapper" + become: true + ansible.builtin.copy: + dest: "/usr/lib/browserpass/browserpass-wrapper" + mode: "0755" + content: | + #!/bin/sh + # NOTE: this uses the dotfiles pinentry-wrapper which forces the usage of GUI pinentry in this case. + # REF: https://git.sr.ht/~a14m/.rc/tree/94b355aa0ce648e3d41bfa7ef76611e3650523d2/item/.gnupg/pinentry-wrapper + export PINENTRY_USER_DATA=gnome + exec /usr/lib/browserpass/browserpass-native "$@" diff --git a/roles/firefox/tasks/install_passff.yml b/roles/firefox/tasks/install_passff.yml new file mode 100644 index 00000000..70f3f397 --- /dev/null +++ b/roles/firefox/tasks/install_passff.yml @@ -0,0 +1,44 @@ +--- +- name: "Add passff to default extensions" + ansible.builtin.set_fact: + firefox_default_extensions: "{{ firefox_default_extensions | combine(firefox_passff_extension) }}" + vars: + firefox_passff_extension: + "passff@invicem.pro": + installation_mode: "force_installed" + install_url: "https://addons.mozilla.org/firefox/downloads/latest/passff/latest.xpi" + +- name: "Ensure passff native messaging host is installed" + become: true + ansible.builtin.shell: | + set -euo pipefail + curl -sSL https://codeberg.org/PassFF/passff-host/releases/download/latest/install_host_app.sh | bash -s -- firefox + args: + creates: "/usr/lib/mozilla/native-messaging-hosts/pro.invicem.passff.json" + executable: "/bin/bash" + +- name: "Create browserpass native messaging hosts file" + become: true + ansible.builtin.copy: + dest: "/usr/lib/mozilla/native-messaging-hosts/passff.json" + mode: "0644" + content: | + { + "name": "passff", + "description": "Host for communicating with zx2c4 pass", + "path": "/usr/lib/mozilla/native-messaging-hosts/passff-wrapper", + "type": "stdio", + "allowed_extensions": [ "passff@invicem.pro" ] + } + +- name: "Create passff wrapper" + become: true + ansible.builtin.copy: + dest: "/usr/lib/mozilla/native-messaging-hosts/passff-wrapper" + mode: "0755" + content: | + #!/bin/sh + # NOTE: this uses the dotfiles pinentry-wrapper which forces the usage of GUI pinentry in this case. + # REF: https://git.sr.ht/~a14m/.rc/tree/94b355aa0ce648e3d41bfa7ef76611e3650523d2/item/.gnupg/pinentry-wrapper + export PINENTRY_USER_DATA=gnome + exec /usr/lib/mozilla/native-messaging-hosts/passff.py "$@" diff --git a/roles/firefox/tasks/main.yml b/roles/firefox/tasks/main.yml new file mode 100644 index 00000000..be6c3e40 --- /dev/null +++ b/roles/firefox/tasks/main.yml @@ -0,0 +1,45 @@ +--- +- name: "Include OS-specific variables" + ansible.builtin.include_vars: "{{ ansible_os_family | lower }}.yml" + +- name: "Ensure firefox is installed" + become: true + ansible.builtin.package: + name: "{{ firefox_package }}" + state: "present" + +- name: "Create Firefox profile" + ansible.builtin.command: "firefox --headless -no-remote -CreateProfile {{ ansible_env.USER }}-profile" + args: + creates: "{{ firefox_folder }}/*{{ ansible_env.USER }}-profile/prefs.js" + +- name: "Install browserpass extension for Firefox" + ansible.builtin.include_tasks: "install_browserpass.yml" + when: firefox_install_browserpass | default(false) + +# NOTE: passff extension is using sed during install and python to run +# That's why the firefox role depends on these roles +- name: "Install passff extension for Firefox" + ansible.builtin.include_tasks: "install_passff.yml" + when: firefox_install_passff | default(false) + +- name: "Create policies directory" + become: true + ansible.builtin.file: + path: "/etc/firefox/policies" + state: "directory" + mode: "0755" + +- name: "Set firefox_policies fact" + ansible.builtin.set_fact: + firefox_policies: "{{ firefox_default_policies | combine(firefox_policies_override) }}" + +- name: "Create Firefox policies file" + become: true + ansible.builtin.copy: + dest: "/etc/firefox/policies/policies.json" + mode: "0644" + content: | + { + "policies": {{ firefox_policies | tojson(indent=4) }} + } diff --git a/roles/firefox/vars/archlinux.yml b/roles/firefox/vars/archlinux.yml new file mode 100644 index 00000000..54fc1838 --- /dev/null +++ b/roles/firefox/vars/archlinux.yml @@ -0,0 +1,6 @@ +--- +firefox_package: "firefox" +firefox_folder: "{{ ansible_env.HOME }}/.mozilla/firefox" + +firefox_browserpass_packages: + - "browserpass" diff --git a/roles/firefox/vars/debian.yml b/roles/firefox/vars/debian.yml new file mode 100644 index 00000000..7f624e48 --- /dev/null +++ b/roles/firefox/vars/debian.yml @@ -0,0 +1,7 @@ +--- +firefox_package: "firefox" +firefox_folder: "{{ ansible_env.HOME }}/snap/firefox/common/.mozilla/firefox" + +firefox_browserpass_packages: + - "webext-browserpass" + - "pinentry-gnome3" -- cgit v1.2.3