blob: 1ca7c3ddc9f86ef7ee6e4f4c295b4dd3f47e2f66 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_ENTERPRISE_DATA_CONTROLS_RULE_H_
#define COMPONENTS_ENTERPRISE_DATA_CONTROLS_RULE_H_
#include <optional>
#include <string>
#include "base/strings/string_piece.h"
#include "base/values.h"
#include "components/enterprise/data_controls/action_context.h"
#include "components/enterprise/data_controls/condition.h"
#include "components/policy/core/common/schema.h"
namespace policy {
class PolicyErrorMap;
} // namespace policy
namespace data_controls {
// Constants used to parse sub-dictionaries of DLP policies that should map to
// an AttributesCondition.
inline constexpr char kRestrictionClipboard[] = "CLIPBOARD";
inline constexpr char kRestrictionScreenshot[] = "SCREENSHOT";
inline constexpr char kRestrictionPrinting[] = "PRINTING";
inline constexpr char kRestrictionPrivacyScreen[] = "PRIVACY_SCREEN";
inline constexpr char kRestrictionScreenShare[] = "SCREEN_SHARE";
inline constexpr char kRestrictionFiles[] = "FILES";
inline constexpr char kLevelAllow[] = "ALLOW";
inline constexpr char kLevelBlock[] = "BLOCK";
inline constexpr char kLevelWarn[] = "WARN";
inline constexpr char kLevelReport[] = "REPORT";
// Implementation of a Data Controls policy rule, which provides interfaces to
// evaluate its conditions to obtain verdicts and access other rule attributes.
// This class is a representation of the following JSON:
// {
// name: string,
// rule_id: string,
// description: string,
//
// sources: { See schema in attributes_condition.h }
// destinations: { See schema in attributes_condition.h }
//
// restrictions: [
// {
// class: CLIPBOARD|SCREENSHOT|PRINTING|PRIVACY_SCREEN|etc,
// level: ALLOW|BLOCK|REPORT|WARN
// }
// ]
// }
class Rule {
public:
// A restriction that can be set by Data Controls.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// When new entries are added, EnterpriseDlpPolicyRestriction enum in
// histograms/enums.xml should be updated.
enum class Restriction {
kUnknownRestriction = 0,
kClipboard = 1, // Restricts sharing the data via clipboard and
// drag-n-drop.
kScreenshot = 2, // Restricts taking screenshots and video captures of
// confidential screen content.
kPrinting = 3, // Restricts printing confidential screen content.
kPrivacyScreen = 4, // Enforces the Eprivacy screen when there's
// confidential content on the screen.
kScreenShare = 5, // Restricts screen sharing of confidential content
// through 3P extensions/websites.
kFiles = 6, // Restricts file operations, like copying, uploading
// or opening in an app.
kMaxValue = kFiles
};
// The enforcement level of the restriction set by Data Controls.
// Should be listed in the order of increased priority.
// When new entries are added, EnterpriseDlpPolicyLevel enum in
// histograms/enums.xml should be updated.
enum class Level {
kNotSet = 0, // Restriction level is not set.
kReport = 1, // Restriction level to only report on every action.
kWarn = 2, // Restriction level to warn the user on every action.
kBlock = 3, // Restriction level to block the user on every action.
kAllow = 4, // Restriction level to allow (no restriction).
kMaxValue = kAllow
};
// Returns nullopt if the passed JSON doesn't match the expected schema.
static std::optional<Rule> Create(const base::Value& value);
static std::optional<Rule> Create(const base::Value::Dict& value);
// Helpers to help conversions when parsing JSON.
static Restriction StringToRestriction(const std::string& restriction);
static Level StringToLevel(const std::string& level);
static const char* RestrictionToString(Restriction restriction);
static const char* LevelToString(Level level);
// Helpers used by Data Controls's policy handler to validate rules, and add
// relevant context to `errors. It is assumed `value` has had its schema
// validated by SchemaValidatingPolicyHandler.
static bool ValidateRuleValue(const char* policy_name,
const base::Value::Dict& value,
policy::PolicyErrorPath error_path,
policy::PolicyErrorMap* errors);
Rule(Rule&& other);
~Rule();
// Returns the `Level` to be applied to a given action.
Level GetLevel(Restriction restriction, const ActionContext& context) const;
const std::string& name() const;
const std::string& rule_id() const;
const std::string& description() const;
private:
Rule(std::string name,
std::string rule_id,
std::string description,
std::unique_ptr<const Condition> condition,
base::flat_map<Restriction, Level> restrictions);
// Helper to parse sub-fields controlling conditions and combine them into a
// single `Condition` object. This is called on the "root" level of the
// condition and recursively as needed.
static std::unique_ptr<const Condition> GetCondition(
const base::Value::Dict& value);
// Helper to parse sub-fields controlling conditions under "sources" and/or
// "destinations" and combine them into a single `Condition` object.
static std::unique_ptr<const Condition> GetSourcesAndDestinationsCondition(
const base::Value::Dict& value);
// Helper to parse the JSON list of conditions under a "and" or "or" key.
static std::vector<std::unique_ptr<const Condition>> GetListConditions(
const base::Value::List& value);
// Helper to parse the following JSON schema:
// {
// class: CLIPBOARD|SCREENSHOT|PRINTING|PRIVACY_SCREEN|etc,
// level: ALLOW|BLOCK|REPORT|WARN
// }
// For compatibility, unrecognized values are ignored and valid values are
// still included in the output.
static base::flat_map<Rule::Restriction, Rule::Level> GetRestrictions(
const base::Value::Dict& value);
// Helper called by `ValidateRuleValue` to populate errors related to mutually
// exclusive fields being used in a rule.
static void AddMutuallyExclusiveErrors(
const std::vector<base::StringPiece>& oneof_conditions,
const std::vector<base::StringPiece>& anyof_conditions,
const char* policy_name,
policy::PolicyErrorPath error_path,
policy::PolicyErrorMap* errors);
// Metadata fields directly taken from the rule's JSON.
const std::string name_;
const std::string rule_id_;
const std::string description_;
// The conditions that should trigger for the rule to apply. This should never
// be null.
std::unique_ptr<const Condition> condition_;
// The `Restriction` => `Level` mapping the rule should apply.
const base::flat_map<Restriction, Level> restrictions_;
};
} // namespace data_controls
#endif // COMPONENTS_ENTERPRISE_DATA_CONTROLS_RULE_H_