File: cert_provisioning_scheduler.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (293 lines) | stat: -rw-r--r-- 12,637 bytes parent folder | download | duplicates (6)
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
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_SCHEDULER_H_
#define CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_SCHEDULER_H_

#include <variant>
#include <vector>

#include "base/callback_list.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/ash/cert_provisioning/cert_provisioning_common.h"
#include "chrome/browser/ash/cert_provisioning/cert_provisioning_invalidator.h"
#include "chrome/browser/ash/cert_provisioning/cert_provisioning_platform_keys_helpers.h"
#include "chrome/browser/ash/platform_keys/platform_keys_service.h"
#include "chrome/browser/ash/policy/invalidation/affiliated_invalidation_service_provider.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
#include "chromeos/ash/components/network/network_state_handler_observer.h"
#include "components/invalidation/invalidation_listener.h"
#include "components/prefs/pref_change_registrar.h"

class Profile;
class PrefService;

namespace policy {
class CloudPolicyClient;
}  // namespace policy

namespace ash {

class NetworkStateHandler;

namespace cert_provisioning {

class CertProvisioningClient;
class CertProvisioningWorker;

using WorkerMap =
    std::map<CertProfileId, std::unique_ptr<CertProvisioningWorker>>;

using CertProfileSet = base::flat_set<CertProfile, CertProfileComparator>;

// Holds information about a worker which failed that is still useful (e.g. for
// UI) after the worker has been destroyed.
struct FailedWorkerInfo {
  FailedWorkerInfo();
  ~FailedWorkerInfo();
  FailedWorkerInfo(const FailedWorkerInfo&);
  FailedWorkerInfo& operator=(const FailedWorkerInfo&);

  // The ID of the certificate provisioning process.
  std::string process_id;
  // The state the worker had prior to switching to the failed state
  // (CertProvisioningWorkerState::kFailed).
  CertProvisioningWorkerState state_before_failure =
      CertProvisioningWorkerState::kInitState;
  // The DER-encoded X.509 SPKI.
  std::vector<uint8_t> public_key;
  // Human-readable certificate profile name (UTF-8).
  std::string cert_profile_name;
  // The time the worker was last updated, i.e. when it transferred to the
  // failed state.
  base::Time last_update_time;
  // Holds a message describing the reason for the failure.
  std::string failure_message;
};

// Interface for the scheduler for client certificate provisioning using device
// management.
class CertProvisioningScheduler {
 public:
  virtual ~CertProvisioningScheduler() = default;

  // Intended to be called when a user presses a button in certificate manager
  // UI. Retries the process of provisioning a specific certificate.
  // Returns "false" if `cert_profile_id` is not found and "true" otherwise.
  virtual bool UpdateOneWorker(const CertProfileId& cert_profile_id) = 0;
  virtual void UpdateAllWorkers() = 0;
  // Resets the process of provisioning a specific certificate.
  // Returns "false" if `cert_profile_id` is not found and "true" otherwise.
  virtual bool ResetOneWorker(const CertProfileId& cert_profile_id) = 0;

  // Returns all certificate provisioning workers that are currently active.
  virtual const WorkerMap& GetWorkers() const = 0;

  // Returns a |FailedWorkerInfo| for certificate provisioning processes that
  // failed and have not been restarted (yet).
  virtual const base::flat_map<CertProfileId, FailedWorkerInfo>&
  GetFailedCertProfileIds() const = 0;

  // Saves the |callback| to call it when the "visible state" of the scheduler
  // changes, i.e.
  // (*) the list of active workers changes,
  // (*) the list of recently failed workers changes,
  // (*) the state of a worker changes.
  // (As long as the returned subscription is alive.)
  virtual base::CallbackListSubscription AddObserver(
      base::RepeatingClosure callback) = 0;
};

// This class is a part of certificate provisioning feature. It tracks updates
// of |RequiredClientCertificateForUser|, |RequiredClientCertificateForDevice|
// policies and creates one CertProvisioningWorker for every policy entry.
// Should work on the UI thread because it interacts with PlatformKeysService
// and some methods are called from the UI to populate certificate manager
// settings page.
class CertProvisioningSchedulerImpl
    : public CertProvisioningScheduler,
      public NetworkStateHandlerObserver,
      public platform_keys::PlatformKeysServiceObserver {
 public:
  static std::unique_ptr<CertProvisioningScheduler>
  CreateUserCertProvisioningScheduler(Profile* profile);
  static std::unique_ptr<CertProvisioningScheduler>
  CreateDeviceCertProvisioningScheduler(
      policy::CloudPolicyClient* cloud_policy_client,
      std::variant<policy::AffiliatedInvalidationServiceProvider*,
                   invalidation::InvalidationListener*>
          invalidation_service_provider_or_listener);

  CertProvisioningSchedulerImpl(
      CertScope cert_scope,
      Profile* profile,
      PrefService* pref_service,
      std::unique_ptr<CertProvisioningClient> cert_provisioning_client,
      platform_keys::PlatformKeysService* platform_keys_service,
      NetworkStateHandler* network_state_handler,
      std::unique_ptr<CertProvisioningInvalidatorFactory> invalidator_factory);
  ~CertProvisioningSchedulerImpl() override;

  CertProvisioningSchedulerImpl(const CertProvisioningSchedulerImpl&) = delete;
  CertProvisioningSchedulerImpl& operator=(
      const CertProvisioningSchedulerImpl&) = delete;

  // CertProvisioningScheduler:
  bool UpdateOneWorker(const CertProfileId& cert_profile_id) override;
  void UpdateAllWorkers() override;
  bool ResetOneWorker(const CertProfileId& cert_profile_id) override;
  const WorkerMap& GetWorkers() const override;
  const base::flat_map<CertProfileId, FailedWorkerInfo>&
  GetFailedCertProfileIds() const override;
  base::CallbackListSubscription AddObserver(
      base::RepeatingClosure callback) override;

  // Invoked when the CertProvisioningWorker corresponding to |profile| reached
  // its final state.
  // Public so it can be called from tests.
  void OnProfileFinished(CertProfile profile,
                         std::string process_id,
                         CertProvisioningWorkerState state);

  // Called when any state visible from the outside has changed.
  // Public so it can be called from tests.
  void OnVisibleStateChanged();

 private:
  void ScheduleInitialUpdate();
  void ScheduleDailyUpdate();
  // Posts delayed task to call UpdateOneWorkerImpl.
  void ScheduleRetry(const CertProfileId& profile_id);
  void ScheduleRenewal(const CertProfileId& profile_id, base::TimeDelta delay);

  void InitialUpdateCerts();
  void DeleteCertsWithoutPolicy();
  void OnDeleteCertsWithoutPolicyDone(chromeos::platform_keys::Status status);
  void CancelWorkersWithoutPolicy(const std::vector<CertProfile>& profiles);
  void CleanVaKeysIfIdle();
  void OnCleanVaKeysIfIdleDone(bool delete_result);
  void RegisterForPrefsChanges();

  void InitiateRenewal(const CertProfileId& cert_profile_id);
  void UpdateOneWorkerImpl(const CertProfileId& cert_profile_id);
  void UpdateWorkerList(std::vector<CertProfile> profiles);
  void UpdateWorkerListWithExistingCerts(
      std::vector<CertProfile> profiles,
      base::flat_map<CertProfileId, scoped_refptr<net::X509Certificate>>
          existing_certs_with_ids,
      chromeos::platform_keys::Status status);

  void OnPrefsChange();
  void DailyUpdateWorkers();
  void DeserializeWorkers();

  // Creates a new worker for |profile| if there is no at the moment.
  // Recreates a worker if existing one has a different version of the profile.
  // Continues an existing worker if it is in a waiting state.
  void ProcessProfile(const CertProfile& profile);

  std::optional<CertProfile> GetOneCertProfile(
      const CertProfileId& cert_profile_id);
  std::vector<CertProfile> GetCertProfiles();

  void CreateCertProvisioningWorker(CertProfile profile);
  CertProvisioningWorker* FindWorker(CertProfileId profile_id);
  // Adds |worker| to |workers_| and returns an unowned pointer to |worker|.
  // Triggers a state change notification.
  CertProvisioningWorker* AddWorkerToMap(
      std::unique_ptr<CertProvisioningWorker> worker);
  // Removes the element referenced by |worker_iter| from |workers_|.
  // Triggers a state change notification if send_visible_state_changed_update
  // is true.
  void RemoveWorkerFromMap(WorkerMap::iterator worker_iter,
                           bool send_visible_state_changed_update);

  // Returns true if the process can be continued (if it's not required to
  // wait).
  bool MaybeWaitForInternetConnection();
  void WaitForInternetConnection();
  void OnNetworkChange(const NetworkState* network);
  // NetworkStateHandlerObserver
  void DefaultNetworkChanged(const NetworkState* network) override;
  void NetworkConnectionStateChanged(const NetworkState* network) override;

  void UpdateFailedCertProfiles(const CertProvisioningWorker& worker);

  // PlatformKeysServiceObserver
  void OnPlatformKeysServiceShutDown() override;

  // Called by |hold_back_updates_timer_| when the notifications should be sent
  // again. Notifies observers if there were any events during the hold back
  // period.
  void OnHoldBackUpdatesTimerExpired();
  // Notifies each observer from |observers_| that the state has changed.
  void NotifyObserversVisibleStateChanged();

  CertScope cert_scope_ = CertScope::kUser;
  // |profile_| can be nullptr for the device-wide instance of
  // CertProvisioningScheduler.
  raw_ptr<Profile> profile_ = nullptr;
  raw_ptr<PrefService> pref_service_ = nullptr;
  const char* pref_name_ = nullptr;
  std::unique_ptr<CertProvisioningClient> cert_provisioning_client_;
  // |platform_keys_service_| can be nullptr if it has been shut down.
  raw_ptr<platform_keys::PlatformKeysService> platform_keys_service_ = nullptr;
  raw_ptr<NetworkStateHandler> network_state_handler_ = nullptr;
  base::ScopedObservation<NetworkStateHandler, NetworkStateHandlerObserver>
      network_state_handler_observer_{this};

  PrefChangeRegistrar pref_change_registrar_;
  WorkerMap workers_;
  // Contains cert profile ids that will be renewed before next daily update.
  // Helps to prevent creation of more than one delayed task for renewal. When
  // the renewal starts for a profile id, it is removed from the set.
  base::flat_set<CertProfileId> scheduled_renewals_;
  // Collection of cert profile ids that failed recently. They will not be
  // retried until next |DailyUpdateWorkers|. FailedWorkerInfo contains some
  // extra information about the failure. Profiles that failed with
  // kInconsistentDataError will not be stored into this collection.
  base::flat_map<CertProfileId, FailedWorkerInfo> failed_cert_profiles_;
  // Equals true if the last attempt to update certificates failed because there
  // was no internet connection.
  bool is_waiting_for_online_ = false;

  // Contains profiles that should be updated after the current update batch
  // run, because an update for them was triggered during the current run.
  CertProfileSet queued_profiles_to_update_;

  LatestCertsWithIdsGetter certs_with_ids_getter_;
  CertDeleter cert_deleter_;
  std::unique_ptr<CertProvisioningInvalidatorFactory> invalidator_factory_;

  // Observers that are observing this CertProvisioningSchedulerImpl.
  base::RepeatingClosureList observers_;
  // True when a task for notifying observers about a state change has been
  // scheduled but not executed yet.
  bool notify_observers_pending_ = false;
  // When this timer is running, notifications should not be sent until it
  // fires. Used to prevent spamming the observers if many events happen in
  // rapid succession.
  base::OneShotTimer hold_back_updates_timer_;
  // When this is true, an update should be sent to the UI when
  // |hold_back_updates_timer_| fires.
  bool update_after_hold_back_ = false;

  base::ScopedObservation<platform_keys::PlatformKeysService,
                          platform_keys::PlatformKeysServiceObserver>
      scoped_platform_keys_service_observation_{this};

  base::WeakPtrFactory<CertProvisioningSchedulerImpl> weak_factory_{this};
};

}  // namespace cert_provisioning
}  // namespace ash

#endif  // CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_SCHEDULER_H_