Bug 1549730 - Add guardrails for Remote Settings preferences r=glasserc

Differential Revision: https://phabricator.services.mozilla.com/D31043

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mathieu Leplatre 2019-05-14 20:45:03 +00:00
Родитель ff22bbc199
Коммит 64e548abb4
7 изменённых файлов: 22 добавлений и 25 удалений

Просмотреть файл

@ -2725,9 +2725,7 @@ pref("security.strict_security_checks.enabled", false);
// Remote settings preferences
pref("services.settings.poll_interval", 86400); // 24H
pref("services.settings.server", "https://firefox.settings.services.mozilla.com/v1");
pref("services.settings.changes.path", "/buckets/monitor/collections/changes/records");
pref("services.settings.default_bucket", "main");
pref("services.settings.default_signer", "remote-settings.content-signature.mozilla.org");
// The percentage of clients who will report uptake telemetry as
// events instead of just a histogram. This only applies on Release;

Просмотреть файл

@ -35,8 +35,6 @@ const TELEMETRY_COMPONENT = "remotesettings";
XPCOMUtils.defineLazyPreferenceGetter(this, "gServerURL",
"services.settings.server");
XPCOMUtils.defineLazyPreferenceGetter(this, "gChangesPath",
"services.settings.changes.path");
/**
* cacheProxy returns an object Proxy that will memoize properties of the target.
@ -255,7 +253,7 @@ class RemoteSettingsClient extends EventEmitter {
async sync(options) {
// We want to know which timestamp we are expected to obtain in order to leverage
// cache busting. We don't provide ETag because we don't want a 304.
const { changes } = await Utils.fetchLatestChanges(gServerURL + gChangesPath, {
const { changes } = await Utils.fetchLatestChanges(gServerURL, {
filters: {
collection: this.collectionName,
bucket: this.bucketName,

Просмотреть файл

@ -12,6 +12,7 @@ const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm")
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
var Utils = {
CHANGES_PATH: "/buckets/monitor/collections/changes/records",
/**
* Check if local data exist for the specified client.
@ -43,7 +44,7 @@ var Utils = {
/**
* Fetch the list of remote collections and their timestamp.
* @param {String} url The poll URL (eg. `http://${server}{pollingEndpoint}`)
* @param {String} serverUrl The server URL (eg. `https://server.org/v1`)
* @param {int} expectedTimestamp The timestamp that the server is supposed to return.
* We obtained it from the Megaphone notification payload,
* and we use it only for cache busting (Bug 1497159).
@ -51,8 +52,9 @@ var Utils = {
* by the server (eg. `"123456789"`).
* @param {Object} filters
*/
async fetchLatestChanges(url, options = {}) {
async fetchLatestChanges(serverUrl, options = {}) {
const { expectedTimestamp, lastEtag = "", filters = {} } = options;
//
// Fetch the list of changes objects from the server that looks like:
// {"data":[
@ -63,6 +65,8 @@ var Utils = {
// "collection":"certificates"
// }]}
let url = serverUrl + Utils.CHANGES_PATH;
// Use ETag to obtain a `304 Not modified` when no change occurred,
// and `?_since` parameter to only keep entries that weren't processed yet.
const headers = {};

Просмотреть файл

@ -33,13 +33,11 @@ const PREF_SETTINGS_BRANCH = "services.settings.";
const PREF_SETTINGS_SERVER = "server";
const PREF_SETTINGS_DEFAULT_SIGNER = "default_signer";
const PREF_SETTINGS_SERVER_BACKOFF = "server.backoff";
const PREF_SETTINGS_CHANGES_PATH = "changes.path";
const PREF_SETTINGS_LAST_UPDATE = "last_update_seconds";
const PREF_SETTINGS_LAST_ETAG = "last_etag";
const PREF_SETTINGS_CLOCK_SKEW_SECONDS = "clock_skew_seconds";
const PREF_SETTINGS_LOAD_DUMP = "load_dump";
// Telemetry identifiers.
const TELEMETRY_COMPONENT = "remotesettings";
const TELEMETRY_SOURCE_POLL = "settings-changes-monitoring";
@ -48,11 +46,13 @@ const TELEMETRY_SOURCE_SYNC = "settings-sync";
// Push broadcast id.
const BROADCAST_ID = "remote-settings/monitor_changes";
// Signer to be used when not specified (see Ci.nsIContentSignatureVerifier).
const DEFAULT_SIGNER = "remote-settings.content-signature.mozilla.org";
XPCOMUtils.defineLazyGetter(this, "gPrefs", () => {
return Services.prefs.getBranch(PREF_SETTINGS_BRANCH);
});
XPCOMUtils.defineLazyPreferenceGetter(this, "gServerURL", PREF_SETTINGS_BRANCH + PREF_SETTINGS_SERVER);
XPCOMUtils.defineLazyPreferenceGetter(this, "gChangesPath", PREF_SETTINGS_BRANCH + PREF_SETTINGS_CHANGES_PATH);
/**
* Default entry filtering function, in charge of excluding remote settings entries
@ -84,10 +84,9 @@ function remoteSettingsFunction() {
let _invalidatePolling = false;
// If not explicitly specified, use the default signer.
const defaultSigner = gPrefs.getCharPref(PREF_SETTINGS_DEFAULT_SIGNER);
const defaultOptions = {
bucketNamePref: PREF_SETTINGS_DEFAULT_BUCKET,
signerName: defaultSigner,
signerName: DEFAULT_SIGNER,
filterFunc: jexlFilterFunc,
};
@ -112,12 +111,6 @@ function remoteSettingsFunction() {
return _clients.get(collectionName);
};
Object.defineProperty(remoteSettings, "pollingEndpoint", {
get() {
return gServerURL + gChangesPath;
},
});
/**
* Internal helper to retrieve existing instances of clients or new instances
* with default options if possible, or `null` if bucket/collection are unknown.
@ -186,7 +179,7 @@ function remoteSettingsFunction() {
let pollResult;
try {
pollResult = await Utils.fetchLatestChanges(remoteSettings.pollingEndpoint, { expectedTimestamp, lastEtag });
pollResult = await Utils.fetchLatestChanges(gServerURL, { expectedTimestamp, lastEtag });
} catch (e) {
// Report polling error to Uptake Telemetry.
let reportStatus;
@ -291,7 +284,7 @@ function remoteSettingsFunction() {
* known remote settings collections.
*/
remoteSettings.inspect = async () => {
const { changes, currentEtag: serverTimestamp } = await Utils.fetchLatestChanges(remoteSettings.pollingEndpoint);
const { changes, currentEtag: serverTimestamp } = await Utils.fetchLatestChanges(gServerURL);
const collections = await Promise.all(changes.map(async (change) => {
const { bucket, collection, last_modified: serverTimestamp } = change;
@ -314,11 +307,12 @@ function remoteSettingsFunction() {
return {
serverURL: gServerURL,
pollingEndpoint: gServerURL + Utils.CHANGES_PATH,
serverTimestamp,
localTimestamp: gPrefs.getCharPref(PREF_SETTINGS_LAST_ETAG, null),
lastCheck: gPrefs.getIntPref(PREF_SETTINGS_LAST_UPDATE, 0),
mainBucket: Services.prefs.getCharPref(PREF_SETTINGS_DEFAULT_BUCKET),
defaultSigner,
defaultSigner: DEFAULT_SIGNER,
collections: collections.filter(c => !!c),
};
};

Просмотреть файл

@ -2,4 +2,6 @@
resource services-settings resource://gre/modules/services-settings/
# Schedule polling of remote settings changes
category update-timer RemoteSettingsComponents @mozilla.org/services/settings;1,getService,services-settings-poll-changes,services.settings.poll_interval,86400
# (default 24H, max 72H)
# see syntax https://searchfox.org/mozilla-central/rev/cc280c4be94ff8cf64a27cc9b3d6831ffa49fa45/toolkit/components/timermanager/UpdateTimerManager.jsm#155
category update-timer RemoteSettingsComponents @mozilla.org/services/settings;1,getService,services-settings-poll-changes,services.settings.poll_interval,86400,259200

Просмотреть файл

@ -104,10 +104,10 @@ add_task(async function test_support_of_preferences_filters() {
filter_expression: '"services.settings.last_etag"|preferenceValue == 42',
}, {
willMatch: true,
filter_expression: '"services.settings.changes.path"|preferenceExists == true',
filter_expression: '"services.settings.default_bucket"|preferenceExists == true',
}, {
willMatch: true,
filter_expression: '"services.settings.changes.path"|preferenceIsUserSet == false',
filter_expression: '"services.settings.default_bucket"|preferenceIsUserSet == false',
}, {
willMatch: true,
filter_expression: '"services.settings.last_etag"|preferenceIsUserSet == true',

Просмотреть файл

@ -12,6 +12,7 @@ const {
remoteSettingsBroadcastHandler,
BROADCAST_ID,
} = ChromeUtils.import("resource://services-settings/remote-settings.js");
const { Utils } = ChromeUtils.import("resource://services-settings/Utils.jsm");
const { TelemetryTestUtils } = ChromeUtils.import("resource://testing-common/TelemetryTestUtils.jsm");
@ -27,7 +28,7 @@ const DB_NAME = "remote-settings";
// Telemetry report result.
const TELEMETRY_HISTOGRAM_POLL_KEY = "settings-changes-monitoring";
const TELEMETRY_HISTOGRAM_SYNC_KEY = "settings-sync";
const CHANGES_PATH = "/v1/buckets/monitor/collections/changes/records";
const CHANGES_PATH = "/v1" + Utils.CHANGES_PATH;
var server;