blob: 3c15cd7e6b0e902786527d3b7f6ae622c11b143e [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LOGIN_MANAGER_POLICY_SERVICE_H_
#define LOGIN_MANAGER_POLICY_SERVICE_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/memory/weak_ptr.h>
#include <brillo/errors/error.h>
#include <chromeos/dbus/service_constants.h>
#include "login_manager/proto_bindings/policy_descriptor.pb.h"
namespace enterprise_management {
class PolicyFetchResponse;
}
namespace login_manager {
class LoginMetrics;
class PolicyKey;
class PolicyStore;
// Whether policy signature must be checked in PolicyService::Store().
enum class SignatureCheck { kEnabled, kDisabled };
// Policies are namespaced by domain and component ID.
using PolicyNamespace = std::pair<PolicyDomain, std::string>;
// Returns the namespace for Chrome policies.
extern PolicyNamespace MakeChromePolicyNamespace();
// Manages policy storage and retrieval from underlying PolicyStores, thereby
// enforcing policy signatures against a given policy key. Also handles key
// rotations in case a new policy payload comes with an updated policy key.
// Policies are namespaced to allow storing different policy types (Chrome,
// extensions) with the same service. There is one store per namespace.
class PolicyService {
public:
// File name of Chrome policy.
static const char kChromePolicyFileName[];
// Prefix of the filename of extension policy. The full file name is suffixed
// by the extension ID.
static const char kExtensionsPolicyFileNamePrefix[];
// Prefix of the filename of sign-in extension policy. The full file name is
// suffixed by the extension ID.
static const char kSignInExtensionsPolicyFileNamePrefix[];
// Flags determining what do to with new keys in Store().
enum KeyInstallFlags {
KEY_NONE = 0, // No key changes allowed.
KEY_ROTATE = 1, // Existing key may be rotated.
KEY_INSTALL_NEW = 2, // Allow to install a key if none is present.
KEY_CLOBBER = 4, // OK to replace the existing key without any checks.
};
// Callback for asynchronous completion of a Store operation.
// On success, |error| is nullptr. Otherwise, it contains an instance
// with detailed info.
using Completion = base::Callback<void(brillo::ErrorPtr error)>;
// Delegate for notifications about key and policy getting persisted.
class Delegate {
public:
virtual ~Delegate() = default;
virtual void OnPolicyPersisted(bool success) = 0;
virtual void OnKeyPersisted(bool success) = 0;
};
// Constructor. |policy_dir| is the directory where policy is stored.
// |policy_key| is the key for policy validation.
// |metrics| is transferred to policy stores created by this instance.
// |resilient_chrome_policy_store| is used to decide if the policy store has
// to be created with backup files for resilience.
PolicyService(const base::FilePath& policy_dir,
PolicyKey* policy_key,
LoginMetrics* metrics,
bool resilient_chrome_policy_store);
PolicyService(const PolicyService&) = delete;
PolicyService& operator=(const PolicyService&) = delete;
virtual ~PolicyService();
// Stores a new policy under the namespace |ns|. If mandated by
// |signature_check|, verifies the passed-in policy blob against the policy
// key (if it exists), takes care of key rotation if required and persists
// everything to disk. The |key_flags| parameter determines what to do with a
// new key present in the policy, see KeyInstallFlags for possible values.
//
// Returns false on immediate errors. Otherwise, returns true and reports the
// status of the operation through |completion|.
virtual bool Store(const PolicyNamespace& ns,
const std::vector<uint8_t>& policy_blob,
int key_flags,
SignatureCheck signature_check,
const Completion& completion);
// Retrieves the current policy blob (does not verify the signature) from the
// namespace |ns|. Returns true on success.
virtual bool Retrieve(const PolicyNamespace& ns,
std::vector<uint8_t>* policy_blob);
// Deletes the policy for the namespace |ns|. This operation is only allowed
// if |ns| specifies a component policy namespace (e.g. extensions) and if the
// |signature_check| is disabled. Returns true on success.
virtual bool Delete(const PolicyNamespace& ns,
SignatureCheck signature_check);
// Returns a list of all component IDs in the given |domain| for which policy
// is stored. Returns an empty vector if |domain| does not support component
// IDs (e.g. POLICY_DOMAIN_CHROME).
virtual std::vector<std::string> ListComponentIds(PolicyDomain domain);
// Persists policy of the namespace |ns| to disk synchronously and passes
// |completion| and the result to OnPolicyPersisted().
virtual void PersistPolicy(const PolicyNamespace& ns,
const Completion& completion);
// Persists policy for all namespaces.
virtual void PersistAllPolicy();
// Sets the policystore for namespace |ns|. Deletes the previous store if it
// exists.
void SetStoreForTesting(const PolicyNamespace& ns,
std::unique_ptr<PolicyStore> store);
// Accessors for the delegate. PolicyService doesn't own the delegate, thus
// client code must make sure that the delegate pointer stays valid.
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
Delegate* delegate() { return delegate_; }
protected:
friend class PolicyServiceTest;
// Returns a pointer to the policy store for the given namespace |ns|. Creates
// the store if it does not exist yet and makes sure it's loaded or created.
PolicyStore* GetOrCreateStore(const PolicyNamespace& ns);
PolicyKey* key() { return policy_key_; }
void set_policy_key_for_test(PolicyKey* key) { policy_key_ = key; }
// Posts a task to run PersistKey().
void PostPersistKeyTask();
// Posts a task to run PersistPolicy().
void PostPersistPolicyTask(const PolicyNamespace& ns,
const Completion& completion);
// Store a policy blob under the namespace |ns|. This does the heavy lifting
// for Store(), making the signature checks, taking care of key changes and
// persisting policy and key data to disk.
bool StorePolicy(const PolicyNamespace& ns,
const enterprise_management::PolicyFetchResponse& policy,
int key_flags,
SignatureCheck signature_check,
const Completion& completion);
// Handles completion of a key storage operation, reporting the result to
// |delegate_|.
virtual void OnKeyPersisted(bool status);
// Finishes persisting policy, notifying |delegate_| and reporting the
// |dbus_error_code| through |completion|. |completion| may be null, and in
// that case the reporting part is not done. |dbus_error_code| is a dbus_error
// constant and can be a non-error, like kNone.
void OnPolicyPersisted(const Completion& completion,
const std::string& dbus_error_code);
// Owned by the caller. Passed to the policy stores at creation and used by
// device policy service.
LoginMetrics* metrics_ = nullptr;
private:
// Persists key() to disk synchronously and passes the result to
// OnKeyPersisted().
void PersistKey();
// Returns the file path of the policy for the given namespace |ns|.
base::FilePath GetPolicyPath(const PolicyNamespace& ns);
using ComponentIdFilter = bool (*)(const std::string& component_id);
// Returns the component ID parts of all policy filenames in |policy_dir_|
// that start with |policy_filename_prefix|. IDs where |filter| returns false
// are filtered out.
std::vector<std::string> FindComponentIds(
const std::string& policy_filename_prefix, ComponentIdFilter filter);
using PolicyStoreMap =
std::map<PolicyNamespace, std::unique_ptr<PolicyStore>>;
PolicyStoreMap policy_stores_;
base::FilePath policy_dir_;
PolicyKey* policy_key_ = nullptr;
bool resilient_chrome_policy_store_ = false;
Delegate* delegate_ = nullptr;
// Put at the last member, so that inflight weakptrs will be invalidated
// before other members' destruction.
base::WeakPtrFactory<PolicyService> weak_ptr_factory_;
};
} // namespace login_manager
#endif // LOGIN_MANAGER_POLICY_SERVICE_H_