1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
|
// Copyright 2012 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_POLICY_CORE_COMMON_CLOUD_DEVICE_MANAGEMENT_SERVICE_H_
#define COMPONENTS_POLICY_CORE_COMMON_CLOUD_DEVICE_MANAGEMENT_SERVICE_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/dm_auth.h"
#include "components/policy/policy_export.h"
#include "services/network/public/cpp/simple_url_loader.h"
namespace base {
class SequencedTaskRunner;
}
namespace network {
class SharedURLLoaderFactory;
}
namespace policy {
// Used in the Enterprise.DMServerRequestSuccess histogram, shows how many
// retries we had to do to execute the DeviceManagementRequestJob.
enum class DMServerRequestSuccess {
// No retries happened, the request succeeded for the first try.
kRequestNoRetry = 0,
// 1..kMaxRetries: number of retries. kMaxRetries is the maximum number of
// retries allowed, defined in the .cc file.
// The request failed (too many retries or non-retryable error).
kRequestFailed = 10,
// The server responded with an error.
kRequestError = 11,
kMaxValue = kRequestError,
};
// The device management service is responsible for everything related to
// communication with the device management server. It creates the backends
// objects that the device management policy provider and friends use to issue
// requests.
class POLICY_EXPORT DeviceManagementService {
public:
// HTTP Error Codes of the DM Server with their concrete meanings in the
// context of the DM Server communication.
static constexpr int kSuccess = 200;
static constexpr int kInvalidArgument = 400;
static constexpr int kInvalidAuthCookieOrDMToken = 401;
static constexpr int kMissingLicenses = 402;
static constexpr int kDeviceManagementNotAllowed = 403;
static constexpr int kInvalidURL =
404; // This error is not coming from the GFE.
static constexpr int kInvalidSerialNumber = 405;
static constexpr int kDomainMismatch = 406;
static constexpr int kDeviceIdConflict = 409;
static constexpr int kDeviceNotFound = 410;
static constexpr int kPendingApproval = 412;
static constexpr int kRequestTooLarge = 413;
static constexpr int kConsumerAccountWithPackagedLicense = 417;
static constexpr int kInvalidPackagedDeviceForKiosk = 418;
static constexpr int kOrgUnitEnrollmentLimitExceeded = 419;
static constexpr int kTooManyRequests = 429;
static constexpr int kInternalServerError = 500;
static constexpr int kServiceUnavailable = 503;
static constexpr int kPolicyNotFound = 902;
static constexpr int kDeprovisioned = 903;
static constexpr int kArcDisabled = 904;
static constexpr int kInvalidDomainlessCustomer = 905;
static constexpr int kTosHasNotBeenAccepted = 906;
static constexpr int kIllegalAccountForPackagedEDULicense = 907;
// Number of times to retry on ERR_NETWORK_CHANGED errors.
static const int kMaxRetries = 3;
// Obtains the parameters used to contact the server.
// This allows creating the DeviceManagementService early and getting these
// parameters later. Passing the parameters directly in the ctor isn't
// possible because some aren't ready during startup. http://crbug.com/302798
class POLICY_EXPORT Configuration {
public:
virtual ~Configuration() = default;
// Server at which to contact the service (DMServer).
virtual std::string GetDMServerUrl() const = 0;
// Agent reported in the "agent" query parameter.
virtual std::string GetAgentParameter() const = 0;
// The platform reported in the "platform" query parameter.
virtual std::string GetPlatformParameter() const = 0;
// Server at which to contact the real time reporting service.
virtual std::string GetRealtimeReportingServerUrl() const = 0;
// Server endpoint for encrypted events.
virtual std::string GetEncryptedReportingServerUrl() const = 0;
};
// A DeviceManagementService job manages network requests to the device
// management and real-time reporting services. Jobs are created by calling
// CreateJob() and specifying a JobConfiguration. Jobs can be canceled by
// deleting the returned Job object.
//
// If network requests fail, the Job will retry them.
//
// JobConfiguration is the interface used by callers to specify parameters
// of network requests. This object is not immutable and may be changed after
// a call to OnBeforeRetry(). DeviceManagementService calls the GetXXX
// methods again to create a new network request for each retry.
class JobConfiguration;
class POLICY_EXPORT Job {
public:
enum RetryMethod {
// No retry required for this request.
NO_RETRY,
// Should retry immediately (no delay).
RETRY_IMMEDIATELY,
// Should retry after a delay.
RETRY_WITH_DELAY
};
virtual ~Job() = default;
};
class JobImpl;
// JobForTesting is a test API to access jobs.
// See also |FakeDeviceManagementService|.
class POLICY_EXPORT JobForTesting {
public:
JobForTesting();
explicit JobForTesting(JobImpl* job_impl);
JobForTesting(const JobForTesting&);
JobForTesting(JobForTesting&&) noexcept;
JobForTesting& operator=(const JobForTesting&);
JobForTesting& operator=(JobForTesting&&) noexcept;
~JobForTesting();
bool IsActive() const;
void Deactivate();
// TODO(rbock) make return type const.
JobConfiguration* GetConfigurationForTesting() const;
Job::RetryMethod SetResponseForTesting(
// TODO(rbock) change type to net::Error
int net_error,
int response_code,
const std::string& response_body,
const std::string& mime_type,
bool was_fetched_via_proxy);
private:
base::WeakPtr<JobImpl> job_impl_;
};
class POLICY_EXPORT JobConfiguration {
public:
// Describes the job type. (Integer values are stated explicitly to
// facilitate reading of logs.)
// TYPE_INVALID is used only in tests so that they can EXPECT the correct
// job type has been used. Otherwise, tests would need to initially set
// the type to something like TYPE_AUTO_ENROLLMENT, and then it would not
// be possible to EXPECT the job type in auto enrollment tests.
enum JobType {
TYPE_INVALID = -1,
TYPE_AUTO_ENROLLMENT = 0,
TYPE_REGISTRATION = 1,
TYPE_API_AUTH_CODE_FETCH = 2,
TYPE_POLICY_FETCH = 3,
TYPE_UNREGISTRATION = 4,
TYPE_UPLOAD_CERTIFICATE = 5,
TYPE_DEVICE_STATE_RETRIEVAL = 6,
TYPE_UPLOAD_STATUS = 7,
TYPE_REMOTE_COMMANDS = 8,
TYPE_ATTRIBUTE_UPDATE_PERMISSION = 9,
TYPE_ATTRIBUTE_UPDATE = 10,
TYPE_GCM_ID_UPDATE = 11,
TYPE_ANDROID_MANAGEMENT_CHECK = 12,
TYPE_CERT_BASED_REGISTRATION = 13,
TYPE_ACTIVE_DIRECTORY_ENROLL_PLAY_USER = 14,
TYPE_ACTIVE_DIRECTORY_PLAY_ACTIVITY = 15,
/* TYPE_REQUEST_LICENSE_TYPES = 16, */
/*Deprecated, CloudPolicyClient no longer uses it.
TYPE_UPLOAD_APP_INSTALL_REPORT = 17,*/
TYPE_BROWSER_REGISTRATION = 18,
TYPE_CHROME_DESKTOP_REPORT = 19,
TYPE_INITIAL_ENROLLMENT_STATE_RETRIEVAL = 20,
TYPE_UPLOAD_POLICY_VALIDATION_REPORT = 21,
TYPE_UPLOAD_REAL_TIME_REPORT = 22,
TYPE_REQUEST_SAML_URL = 23,
TYPE_CHROME_OS_USER_REPORT = 24,
TYPE_CERT_PROVISIONING_REQUEST = 25,
TYPE_PSM_HAS_DEVICE_STATE_REQUEST = 26,
TYPE_UPLOAD_ENCRYPTED_REPORT = 27,
TYPE_CHECK_USER_ACCOUNT = 28,
TYPE_UPLOAD_EUICC_INFO = 29,
TYPE_BROWSER_UPLOAD_PUBLIC_KEY = 30,
TYPE_CHROME_PROFILE_REPORT = 31,
TYPE_OIDC_REGISTRATION = 32,
TYPE_TOKEN_BASED_DEVICE_REGISTRATION = 33,
TYPE_UPLOAD_FM_REGISTRATION_TOKEN = 34,
TYPE_POLICY_AGENT_REGISTRATION = 35,
TYPE_DETERMINE_PROMOTION_ELIGIBILITY = 36,
};
// The set of HTTP query parameters of the request.
using ParameterMap = std::map<std::string, std::string>;
// Convert the job type into a string.
static std::string GetJobTypeAsString(JobType type);
virtual ~JobConfiguration() = default;
virtual JobType GetType() = 0;
virtual const DMAuth& GetAuth() const = 0;
virtual const ParameterMap& GetQueryParams() = 0;
// Gets the factory to create URL fetchers for requests.
virtual scoped_refptr<network::SharedURLLoaderFactory>
GetUrlLoaderFactory() = 0;
// Gets the payload to send in requests.
virtual std::string GetPayload() = 0;
// The content type of the payload.
virtual std::string GetContentType() = 0;
// Whether the request will forward user cookies or not.
virtual bool AreCookiesUsed() = 0;
// Returns the network annotation to assign to requests.
virtual net::NetworkTrafficAnnotationTag GetTrafficAnnotationTag() = 0;
// Returns a properly initialized resource for requests.
virtual std::unique_ptr<network::ResourceRequest> GetResourceRequest(
bool bypass_proxy,
int last_error) = 0;
// Returns whether UMA histograms should be recorded. If this is false
// then GetUmaName() is invalid.
virtual bool ShouldRecordUma() const = 0;
// Returns the the UMA histogram to record stats about the network request.
virtual std::string GetUmaName() = 0;
// Returns the RetryMethod the configuration considers appropriate given the
// response from the server. The response_code is the http response, and the
// response_body is the response returned by the server (it may be empty
// depending on the response_code).
// Note this method will not be called on a net_error, because the
// assumption is that this configuration is deciding to retry based on a
// server response, and there is no server response in that case.
virtual Job::RetryMethod ShouldRetry(int response_code,
const std::string& response_body) = 0;
// Prepare this job for a network request retry.
virtual void OnBeforeRetry(int response_code,
const std::string& response_body) = 0;
// Called when a result is available for the request (possibly after
// retries). If |net_error| is net::OK, |response_code| will be set to the
// HTTP response code.
virtual void OnURLLoadComplete(Job* job,
int net_error,
int response_code,
const std::string& response_body) = 0;
virtual std::optional<base::TimeDelta> GetTimeoutDuration() = 0;
};
explicit DeviceManagementService(
std::unique_ptr<Configuration> configuration);
DeviceManagementService(const DeviceManagementService&) = delete;
DeviceManagementService& operator=(const DeviceManagementService&) = delete;
virtual ~DeviceManagementService();
// Creates and queues/starts a new Job.
virtual std::unique_ptr<Job> CreateJob(
std::unique_ptr<JobConfiguration> config);
// Schedules a task to run |Initialize| after |delay_milliseconds| had passed.
void ScheduleInitialization(int64_t delay_milliseconds);
// Makes the service stop all requests.
void Shutdown();
const Configuration* configuration() const { return configuration_.get(); }
// Sets the retry delay to a shorter time to prevent browser tests from
// timing out.
static void SetRetryDelayForTesting(long retryDelayMs);
protected:
// Creates a new Job without starting it.
// Used by `FakeDeviceManagementService` to avoid queueing/starting of
// jobs in tests.
std::pair<std::unique_ptr<Job>, JobForTesting> CreateJobForTesting(
std::unique_ptr<JobConfiguration> config);
const scoped_refptr<base::SequencedTaskRunner> GetTaskRunnerForTesting() {
return task_runner_;
}
private:
using JobQueue = std::vector<base::WeakPtr<JobImpl>>;
// Starts processing any queued jobs.
void Initialize();
// If called before |Initialize| this queues job.
// Otherwise it starts the job.
void AddJob(JobImpl* job);
base::WeakPtr<DeviceManagementService> GetWeakPtr();
// Moves jobs from the queued state to the pending state and starts them.
// This should only be called when DeviceManagementService is already
// initialized.
void StartQueuedJobs();
// A Configuration implementation that is used to obtain various parameters
// used to talk to the device management server.
std::unique_ptr<Configuration> configuration_;
// Jobs that are added, but not started yet.
JobQueue queued_jobs_;
// If this service is initialized, incoming requests get started instantly.
// If it is not initialized, incoming requests are queued.
bool initialized_;
// TaskRunner used to schedule retry attempts.
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
// Used to run delayed tasks (e.g. |Initialize()|).
base::WeakPtrFactory<DeviceManagementService> weak_ptr_factory_{this};
};
// Base class used to implement job configurations.
class POLICY_EXPORT JobConfigurationBase
: public DeviceManagementService::JobConfiguration {
public:
JobConfigurationBase(const JobConfigurationBase&) = delete;
JobConfigurationBase& operator=(const JobConfigurationBase&) = delete;
// DeviceManagementService::JobConfiguration:
JobType GetType() override;
const ParameterMap& GetQueryParams() override;
scoped_refptr<network::SharedURLLoaderFactory> GetUrlLoaderFactory() override;
net::NetworkTrafficAnnotationTag GetTrafficAnnotationTag() override;
std::unique_ptr<network::ResourceRequest> GetResourceRequest(
bool bypass_proxy,
int last_error) override;
bool ShouldRecordUma() const override;
DeviceManagementService::Job::RetryMethod ShouldRetry(
int response_code,
const std::string& response_body) override;
std::optional<base::TimeDelta> GetTimeoutDuration() override;
std::string GetContentType() override;
bool AreCookiesUsed() override;
void set_use_cookies(bool use_cookies) { use_cookies_ = use_cookies; }
protected:
JobConfigurationBase(JobType type,
DMAuth auth_data,
std::optional<std::string> oauth_token,
bool use_cookies,
scoped_refptr<network::SharedURLLoaderFactory> factory);
~JobConfigurationBase() override;
// Adds the query parameter to the network request's URL. If the parameter
// already exists its value is replaced.
void AddParameter(const std::string& name, const std::string& value);
const DMAuth& GetAuth() const override;
// Derived classes should return the base URL for the request.
virtual GURL GetURL(int last_error) const = 0;
// Timeout for job request
std::optional<base::TimeDelta> timeout_;
private:
JobType type_;
scoped_refptr<network::SharedURLLoaderFactory> factory_;
// Auth data that will be passed as 'Authorization' header. Both |auth_data_|
// and |oauth_token_| can be specified for one request.
DMAuth auth_data_;
// OAuth token that will be passed as a query parameter. Both |auth_data_|
// and |oauth_token_| can be specified for one request.
std::optional<std::string> oauth_token_;
// Will allow using cookies as part of the request when true. Cookies can
// be used in combination with other auth models, the order of precedence
// will be determined server-side.
bool use_cookies_;
// Query parameters for the network request.
ParameterMap query_params_;
};
} // namespace policy
#endif // COMPONENTS_POLICY_CORE_COMMON_CLOUD_DEVICE_MANAGEMENT_SERVICE_H_
|