From 1881caa8cfd0230fd7224f6e97be16990616e984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sat, 24 Jul 2021 16:39:53 +0200 Subject: [PATCH 01/27] firefox policies generator PoC. --- internal/policies/firefox/generator.go | 90 +++++++++++++++++ internal/policies/firefox/policies.json | 129 ++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 internal/policies/firefox/generator.go create mode 100644 internal/policies/firefox/policies.json diff --git a/internal/policies/firefox/generator.go b/internal/policies/firefox/generator.go new file mode 100644 index 0000000..528f678 --- /dev/null +++ b/internal/policies/firefox/generator.go @@ -0,0 +1,90 @@ +package firefox + +import ( + _ "embed" + "encoding/json" + "net/url" +) + +type Settings struct { + Bookmarks []string `json:"bookmarks"` + Extensions map[string]string `json:"extensions"` + DeveloperTools bool `json:"developer_tools"` +} + +//go:embed policies.json +var policiesJson string + +func Generate(settings Settings) (string, error) { + policiesObj := struct { + Policies map[string]interface{} `json:"policies"` + }{} + if err := json.Unmarshal([]byte(policiesJson), &policiesObj); err != nil { + return "", err + } + + // + // Bookmarks + // + + // Do not append + //Bookmarks := policiesObj.Policies["Bookmarks"].([]interface{}) + Bookmarks := []interface{}{} + + for _, URL := range settings.Bookmarks { + title := URL + + if u, err := url.Parse(URL); err == nil { + title = u.Hostname() + } + + Bookmarks = append(Bookmarks, map[string]interface{}{ + "Title": title, + "URL": URL, + //"Favicon": URL + "/favicon.ico", + "Folder": "Pages", + "Placement": "toolbar", + }) + } + + if len(settings.Bookmarks) > 0 { + policiesObj.Policies["Bookmarks"] = Bookmarks + } + + // + // Extensions + // + + // Do not append + //Extensions := policiesObj.Policies["ExtensionSettings"].(map[string]interface{}) + Extensions := map[string]interface{}{} + + // block all + Extensions["*"] = map[string]interface{}{ + "installation_mode": "blocked", + } + + for id, url := range settings.Extensions { + Extensions[id] = map[string]interface{}{ + "install_url": url, + "installation_mode": "force_installed", + } + } + + if len(settings.Extensions) > 0 { + policiesObj.Policies["ExtensionSettings"] = Extensions + } + + // + // DeveloperTools + // + + policiesObj.Policies["DisableDeveloperTools"] = settings.DeveloperTools + + data, err := json.MarshalIndent(policiesObj, "", " ") + if err != nil { + return "", err + } + + return string(data), nil +} diff --git a/internal/policies/firefox/policies.json b/internal/policies/firefox/policies.json new file mode 100644 index 0000000..ef4bdc1 --- /dev/null +++ b/internal/policies/firefox/policies.json @@ -0,0 +1,129 @@ +{ + "policies": { + "BlockAboutAddons": false, + "BlockAboutConfig": true, + "BlockAboutProfiles": true, + "BlockAboutSupport": true, + "Bookmarks": [ + { + "Title": "IPLeak", + "URL": "https://ipleak.net/", + "Favicon": "https://ipleak.net/favicon.ico", + "Folder": "Pages", + "Placement": "toolbar" + }, + { + "Title": "YouTube", + "URL": "https://www.youtube.com/", + "Favicon": "https://www.youtube.com/favicon.ico", + "Folder": "Pages", + "Placement": "toolbar" + }, + { + "Title": "Google", + "URL": "https://www.google.com/", + "Favicon": "https://www.google.com/favicon.ico", + "Folder": "Pages", + "Placement": "toolbar" + } + ], + "CaptivePortal": false, + "DisableAppUpdate": true, + "DisableBuiltinPDFViewer": true, + "DisableDeveloperTools": false, + "DisableFeedbackCommands": true, + "DisableFirefoxAccounts": true, + "DisableFirefoxScreenshots": true, + "DisableFirefoxStudies": true, + "DisableForgetButton": true, + "DisableMasterPasswordCreation": true, + "DisablePocket": true, + "DisablePrivateBrowsing": true, + "DisableProfileImport": true, + "DisableProfileRefresh": true, + "DisableSafeMode": true, + "DisableSetDesktopBackground": true, + "DisableSystemAddonUpdate": true, + "DisableTelemetry": true, + "DisplayBookmarksToolbar": false, + "DontCheckDefaultBrowser": true, + "EnableTrackingProtection": { + "Cryptomining": true, + "Fingerprinting": true, + "Value": true + }, + "ExtensionSettings": { + "*": { + "installation_mode": "blocked" + }, + "nordvpnproxy@nordvpn.com": { + "install_url": "https://addons.mozilla.org/firefox/downloads/latest/nordvpn-proxy-extension/latest.xpi", + "installation_mode": "force_installed" + }, + "uBlock0@raymondhill.net": { + "install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi", + "installation_mode": "force_installed" + } + }, + "ExtensionUpdate": false, + "FirefoxHome": { + "Highlights": false, + "Pocket": false, + "Search": true, + "Snippets": false, + "TopSites": true + }, + "FlashPlugin": {}, + "HardwareAcceleration": false, + "Homepage": { + "Additional": [], + "StartPage": "home" + }, + "NewTabPage": true, + "NoDefaultBookmarks": true, + "OfferToSaveLogins": false, + "OfferToSaveLoginsDefault": false, + "OverrideFirstRunPage": "", + "OverridePostUpdatePage": "", + "PasswordManagerEnabled": false, + "Permissions": { + "Camera": { + "BlockNewRequests": true + }, + "Location": { + "BlockNewRequests": true + }, + "Microphone": { + "BlockNewRequests": true + }, + "Notifications": { + "BlockNewRequests": true + } + }, + "Preferences": { + "browser.tabs.warnOnClose": false, + "browser.urlbar.suggest.bookmark": false, + "browser.urlbar.suggest.history": false, + "browser.urlbar.suggest.openpage": false, + "datareporting.policy.dataSubmissionPolicyBypassNotification": true, + "dom.disable_window_flip": true, + "dom.disable_window_move_resize": true, + "dom.event.contextmenu.enabled": false, + "extensions.getAddons.showPane": false, + "places.history.enabled": false, + "privacy.file_unique_origin": true, + "ui.key.menuAccessKeyFocuses": false + }, + "PromptForDownloadLocation": false, + "SanitizeOnShutdown": { + "Cache": true, + "Cookies": true, + "Downloads": true, + "FormData": true, + "History": true, + "OfflineApps": true, + "Sessions": true, + "SiteSettings": true + } + } +} From eb88bfd70ee0015a57738e881ce5c6f74a519ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sat, 24 Jul 2021 23:25:29 +0200 Subject: [PATCH 02/27] update policies + chromium. --- internal/policies/chromium/generator.go | 90 ++++++++++++++++++++++++ internal/policies/chromium/policies.json | 38 ++++++++++ internal/policies/firefox/generator.go | 87 ++++++++++------------- internal/policies/firefox/policies.json | 11 +-- internal/types/policies.go | 13 ++++ 5 files changed, 179 insertions(+), 60 deletions(-) create mode 100644 internal/policies/chromium/generator.go create mode 100644 internal/policies/chromium/policies.json create mode 100644 internal/types/policies.go diff --git a/internal/policies/chromium/generator.go b/internal/policies/chromium/generator.go new file mode 100644 index 0000000..2a0f372 --- /dev/null +++ b/internal/policies/chromium/generator.go @@ -0,0 +1,90 @@ +package chromium + +// https://chromeenterprise.google/policies/ + +import ( + _ "embed" + "encoding/json" + "fmt" + "m1k1o/neko_rooms/internal/types" +) + +//go:embed policies.json +var policiesJson string + +func Generate(policies types.Policies) (string, error) { + policiesTmpl := map[string]interface{}{} + if err := json.Unmarshal([]byte(policiesJson), &policiesTmpl); err != nil { + return "", err + } + + // + // Homepage + // + + if policies.Homepage != "" { + policiesTmpl["HomepageLocation"] = policies.Homepage + } + + // + // Extensions + // + + ExtensionInstallForcelist := []interface{}{} + for _, e := range policies.Extensions { + URL := e.URL + if URL == "" { + URL = "https://clients2.google.com/service/update2/crx" + } + + ExtensionInstallForcelist = append( + ExtensionInstallForcelist, + fmt.Sprintf("%s;%s", e.ID, URL), + ) + } + + ExtensionInstallWhitelist := []interface{}{} + for _, e := range policies.Extensions { + ExtensionInstallWhitelist = append( + ExtensionInstallWhitelist, + e.ID, + ) + } + + policiesTmpl["ExtensionInstallForcelist"] = ExtensionInstallForcelist + policiesTmpl["ExtensionInstallWhitelist"] = ExtensionInstallWhitelist + policiesTmpl["ExtensionInstallBlacklist"] = []interface{}{"*"} + + // + // Developer Tools + // + + if policies.DeveloperTools { + // Allow usage of the Developer Tools + policiesTmpl["DeveloperToolsAvailability"] = 1 + } else { + // Disallow usage of the Developer Tools + policiesTmpl["DeveloperToolsAvailability"] = 2 + } + + // + // Persistent Data + // + + if policies.PersistentData { + // Allow all sites to set local data + policiesTmpl["DefaultCookiesSetting"] = 1 + // Restore the last session + policiesTmpl["RestoreOnStartup"] = 1 + } else { + // Keep cookies for the duration of the session + policiesTmpl["DefaultCookiesSetting"] = 4 + } + + data, err := json.MarshalIndent(policiesTmpl, "", " ") + if err != nil { + return "", err + } + + return string(data), nil +} diff --git a/internal/policies/chromium/policies.json b/internal/policies/chromium/policies.json new file mode 100644 index 0000000..786c2b1 --- /dev/null +++ b/internal/policies/chromium/policies.json @@ -0,0 +1,38 @@ +{ + "HomepageLocation": "", + "AutoFillEnabled": false, + "AutofillAddressEnabled": false, + "AutofillCreditCardEnabled": false, + "BrowserSignin": 0, + "DefaultNotificationsSetting": 2, + "DeveloperToolsAvailability": 2, + "EditBookmarksEnabled": false, + "FullscreenAllowed": true, + "IncognitoModeAvailability": 1, + "SyncDisabled": true, + "AutoplayAllowed": true, + "BrowserAddPersonEnabled": false, + "BrowserGuestModeEnabled": false, + "DefaultPopupsSetting": 2, + "DownloadRestrictions": 3, + "VideoCaptureAllowed": true, + "AllowFileSelectionDialogs": false, + "PromptForDownloadLocation": false, + "BookmarkBarEnabled": false, + "PasswordManagerEnabled": false, + "URLBlacklist": [ + "file://*", + "chrome://policy" + ], + "ExtensionInstallForcelist": [ + "cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx", + "fjoaledfpmneenckfbpdfhkmimnjocfa;https://clients2.google.com/service/update2/crx" + ], + "ExtensionInstallWhitelist": [ + "cjpalhdlnbpafiamejdnhcphjbkeiagm", + "fjoaledfpmneenckfbpdfhkmimnjocfa" + ], + "ExtensionInstallBlacklist": [ + "*" + ] +} diff --git a/internal/policies/firefox/generator.go b/internal/policies/firefox/generator.go index 528f678..4f1fac7 100644 --- a/internal/policies/firefox/generator.go +++ b/internal/policies/firefox/generator.go @@ -1,87 +1,74 @@ package firefox +// https://github.com/mozilla/policy-templates/blob/master/README.md#homepage + import ( _ "embed" "encoding/json" - "net/url" + "m1k1o/neko_rooms/internal/types" ) -type Settings struct { - Bookmarks []string `json:"bookmarks"` - Extensions map[string]string `json:"extensions"` - DeveloperTools bool `json:"developer_tools"` -} - //go:embed policies.json var policiesJson string -func Generate(settings Settings) (string, error) { - policiesObj := struct { +func Generate(policies types.Policies) (string, error) { + policiesTmpl := struct { Policies map[string]interface{} `json:"policies"` }{} - if err := json.Unmarshal([]byte(policiesJson), &policiesObj); err != nil { + if err := json.Unmarshal([]byte(policiesJson), &policiesTmpl); err != nil { return "", err } // - // Bookmarks + // Homepage // - // Do not append - //Bookmarks := policiesObj.Policies["Bookmarks"].([]interface{}) - Bookmarks := []interface{}{} - - for _, URL := range settings.Bookmarks { - title := URL - - if u, err := url.Parse(URL); err == nil { - title = u.Hostname() + if policies.Homepage != "" { + policiesTmpl.Policies["Homepage"] = map[string]interface{}{ + "URL": policies.Homepage, + "StartPage": "homepage", } - - Bookmarks = append(Bookmarks, map[string]interface{}{ - "Title": title, - "URL": URL, - //"Favicon": URL + "/favicon.ico", - "Folder": "Pages", - "Placement": "toolbar", - }) - } - - if len(settings.Bookmarks) > 0 { - policiesObj.Policies["Bookmarks"] = Bookmarks } // // Extensions // - // Do not append - //Extensions := policiesObj.Policies["ExtensionSettings"].(map[string]interface{}) - Extensions := map[string]interface{}{} - - // block all - Extensions["*"] = map[string]interface{}{ + ExtensionSettings := map[string]interface{}{} + ExtensionSettings["*"] = map[string]interface{}{ "installation_mode": "blocked", } - for id, url := range settings.Extensions { - Extensions[id] = map[string]interface{}{ - "install_url": url, + for _, e := range policies.Extensions { + ExtensionSettings[e.ID] = map[string]interface{}{ + "install_url": e.URL, "installation_mode": "force_installed", } } - if len(settings.Extensions) > 0 { - policiesObj.Policies["ExtensionSettings"] = Extensions + policiesTmpl.Policies["ExtensionSettings"] = ExtensionSettings + + // + // Developer Tools + // + + policiesTmpl.Policies["DisableDeveloperTools"] = !policies.DeveloperTools + + // + // Persistent Data + // + + if policies.PersistentData { + Preferences := policiesTmpl.Policies["Preferences"].(map[string]interface{}) + Preferences["browser.urlbar.suggest.history"] = true + Preferences["places.history.enabled"] = true + policiesTmpl.Policies["Preferences"] = Preferences + policiesTmpl.Policies["SanitizeOnShutdown"] = false + } else { + policiesTmpl.Policies["SanitizeOnShutdown"] = true } - // - // DeveloperTools - // - - policiesObj.Policies["DisableDeveloperTools"] = settings.DeveloperTools - - data, err := json.MarshalIndent(policiesObj, "", " ") + data, err := json.MarshalIndent(policiesTmpl, "", " ") if err != nil { return "", err } diff --git a/internal/policies/firefox/policies.json b/internal/policies/firefox/policies.json index ef4bdc1..0a0132f 100644 --- a/internal/policies/firefox/policies.json +++ b/internal/policies/firefox/policies.json @@ -115,15 +115,6 @@ "ui.key.menuAccessKeyFocuses": false }, "PromptForDownloadLocation": false, - "SanitizeOnShutdown": { - "Cache": true, - "Cookies": true, - "Downloads": true, - "FormData": true, - "History": true, - "OfflineApps": true, - "Sessions": true, - "SiteSettings": true - } + "SanitizeOnShutdown": true } } diff --git a/internal/types/policies.go b/internal/types/policies.go new file mode 100644 index 0000000..973c989 --- /dev/null +++ b/internal/types/policies.go @@ -0,0 +1,13 @@ +package types + +type Policies struct { + Homepage string `json:"homepage"` + Extensions []Extension `json:"extensions"` + DeveloperTools bool `json:"developer_tools"` + PersistentData bool `json:"persistent_data"` +} + +type Extension struct { + ID string `json:"id"` + URL string `json:"url"` +} From b2a14c791659fa55a5c54301b73d4ffdedc5f75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sat, 24 Jul 2021 23:47:59 +0200 Subject: [PATCH 03/27] chromium policies parse. --- internal/policies/chromium/parser.go | 62 ++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 internal/policies/chromium/parser.go diff --git a/internal/policies/chromium/parser.go b/internal/policies/chromium/parser.go new file mode 100644 index 0000000..ec53d46 --- /dev/null +++ b/internal/policies/chromium/parser.go @@ -0,0 +1,62 @@ +package chromium + +// https://chromeenterprise.google/policies/ + +import ( + "encoding/json" + "m1k1o/neko_rooms/internal/types" + "strings" +) + +func Parse(policiesJson string) (*types.Policies, error) { + policies := types.Policies{} + + policiesTmpl := map[string]interface{}{} + if err := json.Unmarshal([]byte(policiesJson), &policiesTmpl); err != nil { + return nil, err + } + + // + // Homepage + // + + if homepage, ok := policiesTmpl["HomepageLocation"]; ok { + policies.Homepage = homepage.(string) + } + + // + // Extensions + // + + if extensions, ok := policiesTmpl["ExtensionInstallForcelist"]; ok { + policies.Extensions = []types.Extension{} + for _, val := range extensions.([]interface{}) { + s := strings.Split(val.(string), ";") + policies.Extensions = append( + policies.Extensions, + types.Extension{ + ID: s[0], + URL: s[1], + }, + ) + } + } + + // + // Developer Tools + // + + if val, ok := policiesTmpl["DeveloperToolsAvailability"]; ok { + policies.DeveloperTools = val.(float64) == 1 + } + + // + // Persistent Data + // + + if val, ok := policiesTmpl["DefaultCookiesSetting"]; ok { + policies.PersistentData = val.(float64) == 1 + } + + return &policies, nil +} From f07f8b0f4dcd282696aa806ffaaa60366c35810c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sat, 24 Jul 2021 23:57:11 +0200 Subject: [PATCH 04/27] firefox policies parse. --- internal/policies/firefox/parser.go | 77 +++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 internal/policies/firefox/parser.go diff --git a/internal/policies/firefox/parser.go b/internal/policies/firefox/parser.go new file mode 100644 index 0000000..fe30367 --- /dev/null +++ b/internal/policies/firefox/parser.go @@ -0,0 +1,77 @@ +package firefox + +// https://github.com/mozilla/policy-templates/blob/master/README.md#homepage + +import ( + _ "embed" + "encoding/json" + "m1k1o/neko_rooms/internal/types" +) + +func Parse(policiesJson string) (*types.Policies, error) { + policies := types.Policies{} + + policiesTmpl := struct { + Policies map[string]interface{} `json:"policies"` + }{} + if err := json.Unmarshal([]byte(policiesJson), &policiesTmpl); err != nil { + return nil, err + } + + // empty file + if policiesTmpl.Policies == nil { + return &policies, nil + } + + // + // Homepage + // + + if homepage, ok := policiesTmpl.Policies["Homepage"].(map[string]interface{}); ok { + if url, ok := homepage["URL"]; ok { + policies.Homepage = url.(string) + } + } + + // + // Extensions + // + + if extensions, ok := policiesTmpl.Policies["ExtensionSettings"]; ok { + policies.Extensions = []types.Extension{} + for id, val := range extensions.(map[string]interface{}) { + if id == "*" { + continue + } + + data := val.(map[string]interface{}) + url, _ := data["install_url"].(string) + + policies.Extensions = append( + policies.Extensions, + types.Extension{ + ID: id, + URL: url, + }, + ) + } + } + + // + // Developer Tools + // + + if val, ok := policiesTmpl.Policies["DisableDeveloperTools"]; ok { + policies.DeveloperTools = !val.(bool) + } + + // + // Persistent Data + // + + if val, ok := policiesTmpl.Policies["SanitizeOnShutdown"]; ok { + policies.PersistentData = !val.(bool) + } + + return &policies, nil +} From 3b363459e1d1cfd584c60a6ff757b5ac37a24436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 00:00:23 +0200 Subject: [PATCH 05/27] policies generator explicit. --- internal/policies/chromium/generator.go | 6 +++--- internal/policies/firefox/generator.go | 22 ++++++++-------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/internal/policies/chromium/generator.go b/internal/policies/chromium/generator.go index 2a0f372..b06ce83 100644 --- a/internal/policies/chromium/generator.go +++ b/internal/policies/chromium/generator.go @@ -22,9 +22,7 @@ func Generate(policies types.Policies) (string, error) { // Homepage // - if policies.Homepage != "" { - policiesTmpl["HomepageLocation"] = policies.Homepage - } + policiesTmpl["HomepageLocation"] = policies.Homepage // // Extensions @@ -79,6 +77,8 @@ func Generate(policies types.Policies) (string, error) { } else { // Keep cookies for the duration of the session policiesTmpl["DefaultCookiesSetting"] = 4 + // Open New Tab Page + policiesTmpl["RestoreOnStartup"] = 5 } data, err := json.MarshalIndent(policiesTmpl, "", " ") diff --git a/internal/policies/firefox/generator.go b/internal/policies/firefox/generator.go index 4f1fac7..b5d50cb 100644 --- a/internal/policies/firefox/generator.go +++ b/internal/policies/firefox/generator.go @@ -23,11 +23,9 @@ func Generate(policies types.Policies) (string, error) { // Homepage // - if policies.Homepage != "" { - policiesTmpl.Policies["Homepage"] = map[string]interface{}{ - "URL": policies.Homepage, - "StartPage": "homepage", - } + policiesTmpl.Policies["Homepage"] = map[string]interface{}{ + "URL": policies.Homepage, + "StartPage": "homepage", } // @@ -58,15 +56,11 @@ func Generate(policies types.Policies) (string, error) { // Persistent Data // - if policies.PersistentData { - Preferences := policiesTmpl.Policies["Preferences"].(map[string]interface{}) - Preferences["browser.urlbar.suggest.history"] = true - Preferences["places.history.enabled"] = true - policiesTmpl.Policies["Preferences"] = Preferences - policiesTmpl.Policies["SanitizeOnShutdown"] = false - } else { - policiesTmpl.Policies["SanitizeOnShutdown"] = true - } + Preferences := policiesTmpl.Policies["Preferences"].(map[string]interface{}) + Preferences["browser.urlbar.suggest.history"] = policies.PersistentData + Preferences["places.history.enabled"] = policies.PersistentData + policiesTmpl.Policies["Preferences"] = Preferences + policiesTmpl.Policies["SanitizeOnShutdown"] = !policies.PersistentData data, err := json.MarshalIndent(policiesTmpl, "", " ") if err != nil { From 99127861460d45908ff832cdc819f8a10539dc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 00:48:38 +0200 Subject: [PATCH 06/27] add policies config. --- internal/policies/config.go | 82 +++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 internal/policies/config.go diff --git a/internal/policies/config.go b/internal/policies/config.go new file mode 100644 index 0000000..14fcaa4 --- /dev/null +++ b/internal/policies/config.go @@ -0,0 +1,82 @@ +package policies + +import ( + "errors" + "m1k1o/neko_rooms/internal/policies/chromium" + "m1k1o/neko_rooms/internal/policies/firefox" + "m1k1o/neko_rooms/internal/types" +) + +type PolicyType string + +const ( + Chromium PolicyType = "chromium" + Firefox PolicyType = "friefox" +) + +type PoliciesConfig struct { + Type PolicyType + Path string +} + +func GetConfig(image string) *PoliciesConfig { + switch image { + case "m1k1o/neko:latest": + fallthrough + case "m1k1o/neko:firefox": + return &PoliciesConfig{ + Type: Firefox, + Path: "/usr/lib/firefox/distribution/policies.json", + } + case "m1k1o/neko:arm-firefox": + return &PoliciesConfig{ + Type: Firefox, + Path: "/usr/lib/firefox-esr/distribution/policies.json", + } + case "m1k1o/neko:chromium": + fallthrough + case "m1k1o/neko:arm-chromium": + fallthrough + case "m1k1o/neko:ungoogled-chromium": + return &PoliciesConfig{ + Type: Chromium, + Path: "/etc/chromium/policies/managed/policies.json", + } + case "m1k1o/neko:google-chrome": + return &PoliciesConfig{ + Type: Chromium, + Path: "/etc/opt/chrome/policies/managed/policies.json", + } + case "m1k1o/neko:brave": + return &PoliciesConfig{ + Type: Chromium, + Path: "/etc/brave/policies/managed/policies.json", + } + } + + return nil +} + +func Generate(policies types.Policies, policyType PolicyType) (string, error) { + if policyType == Chromium { + return chromium.Generate(policies) + } + + if policyType == Firefox { + return firefox.Generate(policies) + } + + return "", errors.New("unknown policy type") +} + +func Parse(policiesJson string, policyType PolicyType) (*types.Policies, error) { + if policyType == Chromium { + return chromium.Parse(policiesJson) + } + + if policyType == Firefox { + return firefox.Parse(policiesJson) + } + + return nil, errors.New("unknown policy type") +} From 97445b11e41494ceffcefa936565585742b4f13c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 01:53:14 +0200 Subject: [PATCH 07/27] add policies API. --- OpenApi.yml | 29 ++++++++++ client/src/api/.openapi-generator/VERSION | 2 +- client/src/api/api.ts | 56 +++++++++++++++++++ internal/room/manager.go | 66 +++++++++++++++++++++++ internal/types/room.go | 2 + 5 files changed, 154 insertions(+), 1 deletion(-) diff --git a/OpenApi.yml b/OpenApi.yml index 9fca958..5ce7ac1 100644 --- a/OpenApi.yml +++ b/OpenApi.yml @@ -330,6 +330,8 @@ components: type: array items: $ref: '#/components/schemas/RoomMount' + policies: + $ref: '#/components/schemas/Policies' RoomStats: type: object @@ -360,3 +362,30 @@ components: muted: type: boolean example: false + + Policies: + type: object + properties: + homepage: + type: string + example: https://google.com + extensions: + type: array + items: + $ref: '#/components/schemas/Extension' + developer_tools: + type: boolean + example: true + persistent_data: + type: boolean + example: false + + Extension: + type: object + properties: + id: + type: string + example: uBlock0@raymondhill.net + url: + type: string + example: https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi diff --git a/client/src/api/.openapi-generator/VERSION b/client/src/api/.openapi-generator/VERSION index 6555596..862529f 100644 --- a/client/src/api/.openapi-generator/VERSION +++ b/client/src/api/.openapi-generator/VERSION @@ -1 +1 @@ -5.2.0-SNAPSHOT \ No newline at end of file +5.2.1-SNAPSHOT \ No newline at end of file diff --git a/client/src/api/api.ts b/client/src/api/api.ts index bce8ee1..6d87e92 100644 --- a/client/src/api/api.ts +++ b/client/src/api/api.ts @@ -21,6 +21,56 @@ import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObj // @ts-ignore import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from './base'; +/** + * + * @export + * @interface Extension + */ +export interface Extension { + /** + * + * @type {string} + * @memberof Extension + */ + id?: string; + /** + * + * @type {string} + * @memberof Extension + */ + url?: string; +} +/** + * + * @export + * @interface Policies + */ +export interface Policies { + /** + * + * @type {string} + * @memberof Policies + */ + homepage?: string; + /** + * + * @type {Array} + * @memberof Policies + */ + extensions?: Array; + /** + * + * @type {boolean} + * @memberof Policies + */ + developer_tools?: boolean; + /** + * + * @type {boolean} + * @memberof Policies + */ + persistent_data?: boolean; +} /** * * @export @@ -245,6 +295,12 @@ export interface RoomSettings { * @memberof RoomSettings */ mounts?: Array; + /** + * + * @type {Policies} + * @memberof RoomSettings + */ + policies?: Policies; } /** * diff --git a/internal/room/manager.go b/internal/room/manager.go index e1d8ab7..33b9d85 100644 --- a/internal/room/manager.go +++ b/internal/room/manager.go @@ -21,6 +21,7 @@ import ( "github.com/rs/zerolog/log" "m1k1o/neko_rooms/internal/config" + "m1k1o/neko_rooms/internal/policies" "m1k1o/neko_rooms/internal/types" "m1k1o/neko_rooms/internal/utils" ) @@ -194,6 +195,47 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro env = append(env, fmt.Sprintf("NEKO_NAT1TO1=%s", strings.Join(manager.config.NAT1To1IPs, ","))) } + // browser policies + if settings.Policies != nil { + if !manager.config.StorageEnabled { + return "", fmt.Errorf("policies cannot be specified, because storage is disabled or unavailable") + } + + policyConfig := policies.GetConfig(settings.NekoImage) + if policyConfig == nil { + return "", fmt.Errorf("policy config for this image does not exist") + } + + policyJson, err := policies.Generate(*settings.Policies, policyConfig.Type) + if err != nil { + return "", err + } + + // create policy path (+ also get host path) + policyPath := fmt.Sprintf("/%s-%s-policy.json", roomName, policyConfig.Type) + templateInternalPath := path.Join(manager.config.StorageInternal, templateStoragePath) + policyInternalPath := path.Join(templateInternalPath, policyPath) + + // create dir if does not exist + if _, err := os.Stat(templateInternalPath); os.IsNotExist(err) { + if err := os.MkdirAll(templateInternalPath, os.ModePerm); err != nil { + return "", err + } + } + + // write policy to file + if err := os.WriteFile(policyInternalPath, []byte(policyJson), 0644); err != nil { + return "", err + } + + // mount policy file + settings.Mounts = append(settings.Mounts, types.RoomMount{ + Type: types.MountTemplate, + HostPath: policyPath, + ContainerPath: policyConfig.Path, + }) + } + mounts := []dockerMount.Mount{} for _, mount := range settings.Mounts { readOnly := false @@ -396,11 +438,35 @@ func (manager *RoomManagerCtx) GetSettings(id string) (*types.RoomSettings, erro }) } + var policiesData *types.Policies + policyConfig := policies.GetConfig(nekoImage) + if policyConfig != nil { + var policyMount *types.RoomMount + for _, mount := range mounts { + if mount.ContainerPath == policyConfig.Path { + policyMount = &mount + break + } + } + + // TODO: Refactor. + if policyMount != nil { + if _, err := os.Stat(policyMount.HostPath); !os.IsNotExist(err) { + if data, err := os.ReadFile(policyMount.HostPath); err == nil { + if pData, err := policies.Parse(string(data), policyConfig.Type); err == nil { + policiesData = pData + } + } + } + } + } + settings := types.RoomSettings{ Name: roomName, NekoImage: nekoImage, MaxConnections: epr.Max - epr.Min + 1, Mounts: mounts, + Policies: policiesData, } err = settings.FromEnv(container.Config.Env) diff --git a/internal/types/room.go b/internal/types/room.go index f6808af..f06c323 100644 --- a/internal/types/room.go +++ b/internal/types/room.go @@ -75,6 +75,8 @@ type RoomSettings struct { Envs map[string]string `json:"envs"` Mounts []RoomMount `json:"mounts"` + + Policies *Policies `json:"policies,omitempty"` } func (settings *RoomSettings) ToEnv() []string { From a37c0ec134e77948ba9601fb9e04a1e47e8b8ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 01:55:04 +0200 Subject: [PATCH 08/27] add policies to create and settings. --- client/src/components/RoomInfo.vue | 13 ++++++ client/src/components/RoomsCreate.vue | 57 ++++++++++++++++++++++++++- client/src/store/state.ts | 9 +++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/client/src/components/RoomInfo.vue b/client/src/components/RoomInfo.vue index 9d582ba..3e78d87 100644 --- a/client/src/components/RoomInfo.vue +++ b/client/src/components/RoomInfo.vue @@ -154,6 +154,19 @@ + +
Policies
+ + + +
none
diff --git a/client/src/components/RoomsCreate.vue b/client/src/components/RoomsCreate.vue index f94e18b..be7844d 100644 --- a/client/src/components/RoomsCreate.vue +++ b/client/src/components/RoomsCreate.vue @@ -208,7 +208,7 @@ mdi-close - +

Mounts

mdi-plus
@@ -252,6 +252,59 @@

+ +
+ + +

+ Browser policies (experimental) +

+ +
+ + + + + + + + + + + + + + + + + + @@ -305,6 +358,7 @@ export default class RoomsCreate extends Vue { private videoPipelineEnabled = false private audioPipelineEnabled = false private broadcastPipelineEnabled = false + private policiesEnabled = false private loading = false private data: RoomSettings = { ...this.$store.state.defaultRoomSettings } @@ -407,6 +461,7 @@ export default class RoomsCreate extends Vue { // eslint-disable-next-line broadcast_pipeline: this.broadcastPipelineEnabled ? this.data.broadcast_pipeline : '', envs, + policies: this.policiesEnabled ? this.data.policies : undefined, }) this.Clear() this.$emit('finished', true) diff --git a/client/src/store/state.ts b/client/src/store/state.ts index d10cd89..c2a1b90 100644 --- a/client/src/store/state.ts +++ b/client/src/store/state.ts @@ -42,6 +42,15 @@ export const state = { envs: {}, // eslint-disable-next-line mounts: [], + + policies: { + homepage: "https://google.com/?hl=en", + extensions: [], + // eslint-disable-next-line + developer_tools: false, + // eslint-disable-next-line + persistent_data: false, + } } as RoomSettings, videoCodecs: [ "VP8", From 77e204f1cd690f3b7477b9d380c378a9303df23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 02:01:32 +0200 Subject: [PATCH 09/27] update policy read to internal path. --- internal/room/manager.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/room/manager.go b/internal/room/manager.go index 33b9d85..855360a 100644 --- a/internal/room/manager.go +++ b/internal/room/manager.go @@ -450,9 +450,10 @@ func (manager *RoomManagerCtx) GetSettings(id string) (*types.RoomSettings, erro } // TODO: Refactor. - if policyMount != nil { - if _, err := os.Stat(policyMount.HostPath); !os.IsNotExist(err) { - if data, err := os.ReadFile(policyMount.HostPath); err == nil { + if policyMount != nil && policyMount.Type == types.MountTemplate { + templateInternalPath := path.Join(manager.config.StorageInternal, templateStoragePath, policyMount.HostPath) + if _, err := os.Stat(templateInternalPath); !os.IsNotExist(err) { + if data, err := os.ReadFile(templateInternalPath); err == nil { if pData, err := policies.Parse(string(data), policyConfig.Type); err == nil { policiesData = pData } From 36d3f146118ad6c8294733be93a54648f5d85778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 12:38:09 +0200 Subject: [PATCH 10/27] client: split policies. --- client/src/components/RoomsCreate.vue | 15 ++++++++++----- client/src/store/state.ts | 18 +++++++++--------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/client/src/components/RoomsCreate.vue b/client/src/components/RoomsCreate.vue index be7844d..bba6a94 100644 --- a/client/src/components/RoomsCreate.vue +++ b/client/src/components/RoomsCreate.vue @@ -269,14 +269,14 @@ ({ key, val, })) } diff --git a/client/src/store/state.ts b/client/src/store/state.ts index c2a1b90..c55786d 100644 --- a/client/src/store/state.ts +++ b/client/src/store/state.ts @@ -2,6 +2,7 @@ import { RoomsConfig, RoomEntry, RoomSettings, + Policies, } from '@/api/index' export const state = { @@ -42,16 +43,15 @@ export const state = { envs: {}, // eslint-disable-next-line mounts: [], - - policies: { - homepage: "https://google.com/?hl=en", - extensions: [], - // eslint-disable-next-line - developer_tools: false, - // eslint-disable-next-line - persistent_data: false, - } } as RoomSettings, + defaultPolicies: { + homepage: "https://google.com/?hl=en", + extensions: [], + // eslint-disable-next-line + developer_tools: false, + // eslint-disable-next-line + persistent_data: false, + } as Policies, videoCodecs: [ "VP8", "VP9", From a215f184ddf4eb3ad2e8fa5fe74cea8c04e1636b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 12:38:57 +0200 Subject: [PATCH 11/27] mount profile on persistent data. --- internal/policies/config.go | 30 ++++++++++++++++++------------ internal/room/manager.go | 9 +++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/internal/policies/config.go b/internal/policies/config.go index 14fcaa4..5f17ddd 100644 --- a/internal/policies/config.go +++ b/internal/policies/config.go @@ -15,8 +15,9 @@ const ( ) type PoliciesConfig struct { - Type PolicyType - Path string + Type PolicyType + Path string + Profile string } func GetConfig(image string) *PoliciesConfig { @@ -25,13 +26,15 @@ func GetConfig(image string) *PoliciesConfig { fallthrough case "m1k1o/neko:firefox": return &PoliciesConfig{ - Type: Firefox, - Path: "/usr/lib/firefox/distribution/policies.json", + Type: Firefox, + Path: "/usr/lib/firefox/distribution/policies.json", + Profile: "/home/neko/.mozilla/firefox/profile.default", } case "m1k1o/neko:arm-firefox": return &PoliciesConfig{ - Type: Firefox, - Path: "/usr/lib/firefox-esr/distribution/policies.json", + Type: Firefox, + Path: "/usr/lib/firefox-esr/distribution/policies.json", + Profile: "/home/neko/.mozilla/firefox/profile.default", } case "m1k1o/neko:chromium": fallthrough @@ -39,18 +42,21 @@ func GetConfig(image string) *PoliciesConfig { fallthrough case "m1k1o/neko:ungoogled-chromium": return &PoliciesConfig{ - Type: Chromium, - Path: "/etc/chromium/policies/managed/policies.json", + Type: Chromium, + Path: "/etc/chromium/policies/managed/policies.json", + Profile: "/home/neko/.config/chromium", } case "m1k1o/neko:google-chrome": return &PoliciesConfig{ - Type: Chromium, - Path: "/etc/opt/chrome/policies/managed/policies.json", + Type: Chromium, + Path: "/etc/opt/chrome/policies/managed/policies.json", + Profile: "/home/neko/.config/google-chrome", } case "m1k1o/neko:brave": return &PoliciesConfig{ - Type: Chromium, - Path: "/etc/brave/policies/managed/policies.json", + Type: Chromium, + Path: "/etc/brave/policies/managed/policies.json", + Profile: "/home/neko/.config/brave", } } diff --git a/internal/room/manager.go b/internal/room/manager.go index 855360a..b2d22e1 100644 --- a/internal/room/manager.go +++ b/internal/room/manager.go @@ -234,6 +234,15 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro HostPath: policyPath, ContainerPath: policyConfig.Path, }) + + // mount persistent folder + if settings.Policies.PersistentData && policyConfig.Profile != "" { + settings.Mounts = append(settings.Mounts, types.RoomMount{ + Type: types.MountPrivate, + HostPath: "/profile", + ContainerPath: policyConfig.Profile, + }) + } } mounts := []dockerMount.Mount{} From bc2a5bef6ce9a347fe764bd2fca4cbbe8ad81529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 12:39:13 +0200 Subject: [PATCH 12/27] do not mount duplicate mounts. --- internal/room/manager.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/room/manager.go b/internal/room/manager.go index b2d22e1..fd19d8e 100644 --- a/internal/room/manager.go +++ b/internal/room/manager.go @@ -245,8 +245,14 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro } } + paths := map[string]bool{} mounts := []dockerMount.Mount{} for _, mount := range settings.Mounts { + // ignore duplicates + if _, ok := paths[mount.ContainerPath]; ok { + continue + } + readOnly := false hostPath := filepath.Clean(mount.HostPath) @@ -309,6 +315,8 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro }, }, ) + + paths[mount.ContainerPath] = true } config := &container.Config{ From e56594fb4ccb70d2efa6235b87954de26e14097a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 13:29:45 +0200 Subject: [PATCH 13/27] remove homepage from policies. --- internal/policies/chromium/generator.go | 6 ------ internal/policies/chromium/parser.go | 8 -------- internal/policies/firefox/generator.go | 19 ++++++++++--------- internal/policies/firefox/parser.go | 10 ---------- internal/types/policies.go | 1 - 5 files changed, 10 insertions(+), 34 deletions(-) diff --git a/internal/policies/chromium/generator.go b/internal/policies/chromium/generator.go index b06ce83..72d36ef 100644 --- a/internal/policies/chromium/generator.go +++ b/internal/policies/chromium/generator.go @@ -18,12 +18,6 @@ func Generate(policies types.Policies) (string, error) { return "", err } - // - // Homepage - // - - policiesTmpl["HomepageLocation"] = policies.Homepage - // // Extensions // diff --git a/internal/policies/chromium/parser.go b/internal/policies/chromium/parser.go index ec53d46..c873f1e 100644 --- a/internal/policies/chromium/parser.go +++ b/internal/policies/chromium/parser.go @@ -16,14 +16,6 @@ func Parse(policiesJson string) (*types.Policies, error) { return nil, err } - // - // Homepage - // - - if homepage, ok := policiesTmpl["HomepageLocation"]; ok { - policies.Homepage = homepage.(string) - } - // // Extensions // diff --git a/internal/policies/firefox/generator.go b/internal/policies/firefox/generator.go index b5d50cb..a956c0f 100644 --- a/internal/policies/firefox/generator.go +++ b/internal/policies/firefox/generator.go @@ -19,15 +19,6 @@ func Generate(policies types.Policies) (string, error) { return "", err } - // - // Homepage - // - - policiesTmpl.Policies["Homepage"] = map[string]interface{}{ - "URL": policies.Homepage, - "StartPage": "homepage", - } - // // Extensions // @@ -62,6 +53,16 @@ func Generate(policies types.Policies) (string, error) { policiesTmpl.Policies["Preferences"] = Preferences policiesTmpl.Policies["SanitizeOnShutdown"] = !policies.PersistentData + if policies.PersistentData { + policiesTmpl.Policies["Homepage"] = map[string]interface{}{ + "StartPage": "previous-session", + } + } else { + policiesTmpl.Policies["Homepage"] = map[string]interface{}{ + "StartPage": "homepage", + } + } + data, err := json.MarshalIndent(policiesTmpl, "", " ") if err != nil { return "", err diff --git a/internal/policies/firefox/parser.go b/internal/policies/firefox/parser.go index fe30367..9594794 100644 --- a/internal/policies/firefox/parser.go +++ b/internal/policies/firefox/parser.go @@ -23,16 +23,6 @@ func Parse(policiesJson string) (*types.Policies, error) { return &policies, nil } - // - // Homepage - // - - if homepage, ok := policiesTmpl.Policies["Homepage"].(map[string]interface{}); ok { - if url, ok := homepage["URL"]; ok { - policies.Homepage = url.(string) - } - } - // // Extensions // diff --git a/internal/types/policies.go b/internal/types/policies.go index 973c989..49e602c 100644 --- a/internal/types/policies.go +++ b/internal/types/policies.go @@ -1,7 +1,6 @@ package types type Policies struct { - Homepage string `json:"homepage"` Extensions []Extension `json:"extensions"` DeveloperTools bool `json:"developer_tools"` PersistentData bool `json:"persistent_data"` From 4815e2aa6270c67b4f14d7b4fbbc708a2c6feb56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 14:37:39 +0200 Subject: [PATCH 14/27] profile dir name with browser. --- internal/room/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/room/manager.go b/internal/room/manager.go index fd19d8e..930c418 100644 --- a/internal/room/manager.go +++ b/internal/room/manager.go @@ -239,7 +239,7 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro if settings.Policies.PersistentData && policyConfig.Profile != "" { settings.Mounts = append(settings.Mounts, types.RoomMount{ Type: types.MountPrivate, - HostPath: "/profile", + HostPath: fmt.Sprintf("/%s-profile", policyConfig.Type), ContainerPath: policyConfig.Profile, }) } From 63f1c40cab89008a154387f51c774209ae3a8030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Sun, 25 Jul 2021 14:52:21 +0200 Subject: [PATCH 15/27] policies: remove homepage from API. --- OpenApi.yml | 3 --- client/src/api/api.ts | 6 ------ client/src/components/RoomInfo.vue | 1 - client/src/components/RoomsCreate.vue | 11 ++--------- 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/OpenApi.yml b/OpenApi.yml index 5ce7ac1..2d73cb7 100644 --- a/OpenApi.yml +++ b/OpenApi.yml @@ -366,9 +366,6 @@ components: Policies: type: object properties: - homepage: - type: string - example: https://google.com extensions: type: array items: diff --git a/client/src/api/api.ts b/client/src/api/api.ts index 6d87e92..fc546f6 100644 --- a/client/src/api/api.ts +++ b/client/src/api/api.ts @@ -46,12 +46,6 @@ export interface Extension { * @interface Policies */ export interface Policies { - /** - * - * @type {string} - * @memberof Policies - */ - homepage?: string; /** * * @type {Array} diff --git a/client/src/components/RoomInfo.vue b/client/src/components/RoomInfo.vue index 3e78d87..e6735be 100644 --- a/client/src/components/RoomInfo.vue +++ b/client/src/components/RoomInfo.vue @@ -159,7 +159,6 @@ -
Policies
- +
Browser policy
+ From fe29e2c221222d821dd4c1401c6e438597a62df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Tue, 27 Jul 2021 20:40:36 +0200 Subject: [PATCH 20/27] fix typos. --- OpenApi.yml | 2 +- internal/types/policies.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenApi.yml b/OpenApi.yml index e51f31f..0c0151e 100644 --- a/OpenApi.yml +++ b/OpenApi.yml @@ -371,7 +371,7 @@ components: enum: [ firefox, chromium ] path: type: string - example: /home/neko/.mozilla/firefox/profile.default + example: /usr/lib/firefox/distribution/policies.json content: $ref: '#/components/schemas/BrowserPolicyContent' diff --git a/internal/types/policies.go b/internal/types/policies.go index 86f7f88..b39aa0e 100644 --- a/internal/types/policies.go +++ b/internal/types/policies.go @@ -4,7 +4,7 @@ type BrowserPolicyType string const ( ChromiumBrowserPolicy BrowserPolicyType = "chromium" - FirefoxBrowserPolicy BrowserPolicyType = "friefox" + FirefoxBrowserPolicy BrowserPolicyType = "firefox" ) type BrowserPolicy struct { From 767566d40d017d39f8d4cbf0ddcec5a7cbff4d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Tue, 27 Jul 2021 21:14:49 +0200 Subject: [PATCH 21/27] policies create from state. --- client/src/components/RoomsCreate.vue | 131 +++++++++++++++----------- client/src/store/state.ts | 113 ++++++++++++++++++++-- 2 files changed, 182 insertions(+), 62 deletions(-) diff --git a/client/src/components/RoomsCreate.vue b/client/src/components/RoomsCreate.vue index a647443..fff9ae6 100644 --- a/client/src/components/RoomsCreate.vue +++ b/client/src/components/RoomsCreate.vue @@ -257,60 +257,58 @@

- Browser policies (experimental) + Browser policy

- - - - - + + +

Not available!

+

Browser policy is not available for this image.

+
@@ -339,7 +337,9 @@ import { Vue, Component, Ref } from 'vue-property-decorator' import { RoomSettings, - Policies, + BrowserPolicyContent, + BrowserPolicyExtension, + BrowserPolicyTypeEnum, } from '@/api/index' export type VForm = Vue & { @@ -365,11 +365,11 @@ export default class RoomsCreate extends Vue { private videoPipelineEnabled = false private audioPipelineEnabled = false private broadcastPipelineEnabled = false - private policiesEnabled = false + private browserPolicyEnabled = false private loading = false private data: RoomSettings = { ...this.$store.state.defaultRoomSettings } - private policies: Policies = { ...this.$store.state.defaultPolicies } + private browserPolicyContent: BrowserPolicyContent = { ...this.$store.state.defaultBrowserPolicyContent } private envList: { key: string; val: string }[] = [] // eslint-disable-next-line @@ -431,6 +431,28 @@ export default class RoomsCreate extends Vue { ] } + get browserPolicyConfig() { + const nekoImage = this.data.neko_image + if (!nekoImage) return undefined + + return this.$store.state.browserPolicyConfig.find(({ images }: { images: string[] }): boolean => images.includes(nekoImage)) + } + + get browserPolicyExtensions() { + const config = this.browserPolicyConfig + if (!config) return [] + + return this.$store.state.browserPolicyExtensions.map(({ text, value }: { + text: string; + value: Record; + }) => { + return { + text, + value: value[config.type as BrowserPolicyTypeEnum], + } + }) + } + addEnv() { Vue.set(this, 'envList', [ ...this.envList, { key: '', val: '' } ]) } @@ -469,7 +491,12 @@ export default class RoomsCreate extends Vue { // eslint-disable-next-line broadcast_pipeline: this.broadcastPipelineEnabled ? this.data.broadcast_pipeline : '', envs, - policies: this.policiesEnabled ? this.policies : undefined, + // eslint-disable-next-line + browser_policy: this.browserPolicyEnabled && this.browserPolicyConfig ? { + type: this.browserPolicyConfig.type, + path: this.browserPolicyConfig.path, + content: this.browserPolicyContent + } : undefined, }) this.Clear() this.$emit('finished', true) @@ -499,9 +526,7 @@ export default class RoomsCreate extends Vue { // eslint-disable-next-line neko_image: this.nekoImages[0], } - this.policies = { - ...this.$store.state.defaultPolicies, - } + this.browserPolicyContent = { ...this.$store.state.defaultBrowserPolicyContent } this.envList = Object.entries({...this.data.envs}).map(([ key, val ]) => ({ key, val, })) } diff --git a/client/src/store/state.ts b/client/src/store/state.ts index c55786d..8094975 100644 --- a/client/src/store/state.ts +++ b/client/src/store/state.ts @@ -2,10 +2,30 @@ import { RoomsConfig, RoomEntry, RoomSettings, - Policies, + BrowserPolicyContent, + BrowserPolicyTypeEnum, + BrowserPolicyExtension, } from '@/api/index' +export interface BrowserPolicyConfig { + type: BrowserPolicyTypeEnum; + path: string; + profile: string; + images: string[]; +} + +export interface BrowserPolicyExtensions { + type: BrowserPolicyTypeEnum; + path: string; + profile: string; + images: string[]; +} + export const state = { + // + // rooms + // + roomsConfig: {} as RoomsConfig, rooms: [] as RoomEntry[], defaultRoomSettings: { @@ -44,14 +64,6 @@ export const state = { // eslint-disable-next-line mounts: [], } as RoomSettings, - defaultPolicies: { - homepage: "https://google.com/?hl=en", - extensions: [], - // eslint-disable-next-line - developer_tools: false, - // eslint-disable-next-line - persistent_data: false, - } as Policies, videoCodecs: [ "VP8", "VP9", @@ -104,6 +116,89 @@ export const state = { "640x400@60", "640x360@60" ] as string[], + + // + // browser policy + // + + browserPolicyConfig: [ + { + type: BrowserPolicyTypeEnum.firefox, + path: '/usr/lib/firefox/distribution/policies.json', + profile: '/home/neko/.mozilla/firefox/profile.default', + images: [ 'm1k1o/neko:latest', 'm1k1o/neko:firefox' ], + }, + { + type: BrowserPolicyTypeEnum.firefox, + path: '/usr/lib/firefox-esr/distribution/policies.json', + profile: '/home/neko/.mozilla/firefox/profile.default', + images: [ 'm1k1o/neko:arm-firefox' ], + }, + { + type: BrowserPolicyTypeEnum.chromium, + path: '/etc/chromium/policies/managed/policies.json', + profile: '/home/neko/.config/chromium', + images: [ 'm1k1o/neko:chromium', 'm1k1o/neko:arm-chromium', 'm1k1o/neko:ungoogled-chromium' ], + }, + { + type: BrowserPolicyTypeEnum.chromium, + path: '/etc/opt/chrome/policies/managed/policies.json', + profile: '/home/neko/.config/google-chrome', + images: [ 'm1k1o/neko:google-chrome' ], + }, + { + type: BrowserPolicyTypeEnum.chromium, + path: '/etc/brave/policies/managed/policies.json', + profile: '/home/neko/.config/brave', + images: [ 'm1k1o/neko:brave' ], + }, + ] as BrowserPolicyConfig[], + browserPolicyExtensions: [ + { + text: 'uBlock Origin', + value: { + [BrowserPolicyTypeEnum.firefox]: { + id: 'uBlock0@raymondhill.net', + url: 'https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi', + } as BrowserPolicyExtension, + [BrowserPolicyTypeEnum.chromium]: { + id: 'cjpalhdlnbpafiamejdnhcphjbkeiagm', + } as BrowserPolicyExtension, + }, + }, + { + text: 'NordVPN', + value: { + [BrowserPolicyTypeEnum.firefox]: { + id: 'nordvpnproxy@nordvpn.com', + url: 'https://addons.mozilla.org/firefox/downloads/latest/nordvpn-proxy-extension/latest.xpi', + } as BrowserPolicyExtension, + [BrowserPolicyTypeEnum.chromium]: { + id: 'fjoaledfpmneenckfbpdfhkmimnjocfa', + } as BrowserPolicyExtension, + }, + }, + { + text: 'SponsorBlock for YouTube', + value: { + [BrowserPolicyTypeEnum.firefox]: { + id: 'sponsorBlocker@ajay.app', + url: 'https://addons.mozilla.org/firefox/downloads/latest/sponsorblock/latest.xpi', + } as BrowserPolicyExtension, + [BrowserPolicyTypeEnum.chromium]: { + id: 'mnjggcdmjocbbbhaepdhchncahnbgone', + } as BrowserPolicyExtension, + }, + }, + ], + defaultBrowserPolicyContent: { + homepage: "https://google.com/?hl=en", + extensions: [], + // eslint-disable-next-line + developer_tools: false, + // eslint-disable-next-line + persistent_data: false, + } as BrowserPolicyContent, } export type State = typeof state From 6b8e77d20aeec6f81490935938da0f147565eba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Tue, 27 Jul 2021 21:17:03 +0200 Subject: [PATCH 22/27] fix memory error. --- internal/room/manager.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/room/manager.go b/internal/room/manager.go index c853776..f7a041d 100644 --- a/internal/room/manager.go +++ b/internal/room/manager.go @@ -472,8 +472,10 @@ func (manager *RoomManagerCtx) GetSettings(id string) (*types.RoomSettings, erro var browserPolicy *types.BrowserPolicy if labels.BrowserPolicy != nil { - browserPolicy.Type = labels.BrowserPolicy.Type - browserPolicy.Path = labels.BrowserPolicy.Path + browserPolicy = &types.BrowserPolicy{ + Type: labels.BrowserPolicy.Type, + Path: labels.BrowserPolicy.Path, + } var policyMount *types.RoomMount for _, mount := range mounts { From 0a44aceda0572bd6f6e3984bd63154a05f42c766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Tue, 27 Jul 2021 21:31:54 +0200 Subject: [PATCH 23/27] extensions for settings show. --- client/src/components/RoomInfo.vue | 32 ++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/client/src/components/RoomInfo.vue b/client/src/components/RoomInfo.vue index 0bdd56e..4d59c0a 100644 --- a/client/src/components/RoomInfo.vue +++ b/client/src/components/RoomInfo.vue @@ -165,7 +165,7 @@