GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: test/unittests/../../cvmfs/webapi/macaroon.h Lines: 7 7 100.0 %
Date: 2018-10-07 00:43:30 Branches: 0 0 - %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System
3
 */
4
5
#ifndef CVMFS_WEBAPI_MACAROON_H_
6
#define CVMFS_WEBAPI_MACAROON_H_
7
8
#include <ctime>
9
#include <string>
10
11
#include "hash.h"
12
#include "json_document.h"
13
#include "util/single_copy.h"
14
15
namespace cipher {
16
class AbstractKeyDatabase;
17
class Key;
18
}
19
20
21
/**
22
 * An implementation of Macaroons: http://research.google.com/pubs/pub41892.html
23
 * Macaroons are tamper-proof authorization tokens with attenuations and
24
 * third-party caveats.
25
 *
26
 * Macaroons are issued by the octopus lease server in form of a lease.  The
27
 * lease server shares separate keys with each of the release manager machines
28
 * and with the storage relay.  Leases are targeted for the storage relay.  The
29
 * release manager machine is seen as a third party that signs off the hash of
30
 * the change packs.
31
 *
32
 * The following caveats are supported for the octopus server:
33
 *  - expiry time
34
 *  - fully qualified repository name
35
 *  - cvmfs sub tree
36
 *  - Required 3rd party (release manager magine) caveat: hash of change pack,
37
 *    request type (transaction start, new data packet, commit).
38
 *
39
 * Note that the in-memory representation does not fully mirror the JSON
40
 * representation.  The availability of the cryptographic keys depends on the
41
 * lifecycle of the macaroon.  As for the lifecyclt, a macaroon is
42
 *   -# created at the lease server ("ExportPrimary") that has access to both
43
 *      the shared secret key of the storage gateway and the shared secret key
44
 *      of the release manager machine;
45
 *   -# parsed on the release manager machine (publisher) that decrypts the
46
 *      "cld" field containing the random key used for 3rd-party caveats;
47
 *   -# attenuated on the release manager machin by 3rd-party caveats (begin
48
 *      transaction, change set hash, another change set hash, ..., publish
49
 *      transaction); multiple macaroons with different 3rd-party caveats are
50
 *      created here ("ExportDerived");
51
 *   -# parsed and verified on the storage relay using the private key from step
52
 *      1 and the "vld" field with the encrypted random key used for 3rd-party
53
 *      caveats.
54
 */
55
class Macaroon : SingleCopy {
56
 public:
57
  enum VerifyFailures {
58
    kFailOk = 0,
59
    kFailBadJson,
60
    kFailBadMacaroon,
61
    kFailBadPrimarySignature,
62
    kFailBad3rdPartySignature,
63
    kFailUnknownKey,
64
    kFailDecrypt,
65
    kFailExpired,
66
    kFailBadRootPath,
67
    kFailReplay,
68
    kFailUnknown,
69
  };
70
71
  enum PublishOperation {
72
    kPublishNoop = 0,
73
    kPublishTransaction,
74
    kPublishChangePack,
75
    kPublishCommit,
76
  };
77
78
  Macaroon(const std::string &key_id_storage,
79
           const cipher::Key *secret_key_storage,
80
           const std::string &key_id_publisher,
81
           const cipher::Key *secret_key_publisher);
82
  static Macaroon *ParseOnPublisher(const std::string &json,
83
                                    cipher::AbstractKeyDatabase *key_db,
84
                                    VerifyFailures *failure_code);
85
  static Macaroon *ParseOnStorage(const std::string &json,
86
                                  cipher::AbstractKeyDatabase *key_db,
87
                                  VerifyFailures *failure_code);
88
  ~Macaroon();
89
90
14
  void set_ttl(const unsigned ttl_s) {
91
14
    expiry_utc_ = time(NULL) + ttl_s;
92
14
  }
93
  void set_root_path(const std::string &root_path) { root_path_ = root_path; }
94
  void set_fqrn(const std::string &fqrn) { fqrn_ = fqrn; }
95
  void set_origin(const std::string &origin) { origin_ = origin; }
96
  void set_target(const std::string &target) { target_hint_ = target; }
97
  void set_publisher_hint(const std::string &hint) { publisher_hint_ = hint; }
98
99
  void set_payload_hash(const shash::Any &hash) { payload_hash_ = hash; }
100
14
  void set_publish_operation(PublishOperation op) { publish_operation_ = op; }
101
14
  void set_ttl_operation(const unsigned ttl_s) {
102
14
    expiry_utc_operation_ = time(NULL) + ttl_s;
103
14
  }
104
105
  std::string ExportPrimary();
106
  std::string ExportAttenuated();
107
108
 private:
109
  Macaroon();
110
  void ComputePrimaryHmac();
111
  void Compute3rdPartyHmac();
112
  std::string ExportPrimaryFields();
113
  std::string Export3rdPartyFields();
114
  bool CreateFromJson(JSON *json);
115
  bool Create3rdPartyFromJson(JSON *json);
116
  VerifyFailures ExtractOnetimeKey(const std::string &key_onetime4me,
117
                                   const cipher::Key &my_secret_key);
118
119
  /**
120
   * The unique identifier of the macaroon.  Serves also as transaction id: this
121
   * macaroon can only be used for a single transaction - change set - publish
122
   * cycle.
123
   */
124
  std::string random_nonce_;
125
126
  /**
127
   * The signing key used for the initial HMAC.  This is a key shared by the
128
   * lease service and the storage gateway (target service).
129
   */
130
  std::string key_id_storage_;
131
132
  /**
133
   * The key shared between the lease server and the release manager machine.
134
   * Used by the release manager machine to sign the 3rd party caveats.
135
   */
136
  std::string key_id_publisher_;
137
138
  /**
139
   * The key shared with the target service (storage relay).  Should match the
140
   * key_id_storage_.  NULL if created from JSON document.
141
   */
142
  const cipher::Key *secret_key_storage_;
143
144
  /**
145
   * The key shared with the release manager machine.  Should match the
146
   * key_id_publisher_.  NULL if created from JSON document.
147
   */
148
  const cipher::Key *secret_key_publisher_;
149
150
  /**
151
   * The machine that issued the macaroon
152
   */
153
  std::string origin_;
154
155
  /**
156
   * Location hint to the target service: storage relay or lease service.
157
   */
158
  std::string target_hint_;
159
160
  /**
161
   * If the macaroon is created from a JSON snippet, the hmac_ is stored here.
162
   * Otherwise the macaroon was created from scratch with the secret key and
163
   * hmac_ is empty.
164
   */
165
  shash::Any hmac_primary_;
166
167
  // Caveats
168
169
  /**
170
   * Time to live for this macaroon
171
   */
172
  time_t expiry_utc_;
173
174
  /**
175
   * Repository name
176
   */
177
  std::string fqrn_;
178
179
  /**
180
   * Sub part of the name space
181
   */
182
  std::string root_path_;
183
184
185
  // 3rd-party caveat, slightly simplified: no target hint, no assertion
186
187
  /**
188
   * Hint to the release manager machine.
189
   */
190
  std::string publisher_hint_;
191
192
  /**
193
   * The root key for the 3rd party caveats.  Random and unique to a macaroon.
194
   * The macaroon owns this key.
195
   */
196
  cipher::Key *key_onetime_;
197
198
  /**
199
   * The random key specific to this macaroon encrypted for the publisher.
200
   */
201
  std::string key_onetime4storage_;
202
203
  /**
204
   * The random key specific to this macaroon encrypted for the publisher.
205
   */
206
  std::string key_onetime4publisher_;
207
208
  /**
209
   * A message from the release manager machine to the storage relay about the
210
   * the operation that this macaroon discharges.
211
   */
212
  PublishOperation publish_operation_;
213
214
  /**
215
   * The time to live for the specific operation discharged by the macaroon.
216
   * This should be shorter than the macaroon's life time in expiry_utc_.
217
   */
218
  time_t expiry_utc_operation_;
219
220
  /**
221
   * Empty unless sent from release manager machine to the storage relay.  In
222
   * the latter case it is the hash of the change pack signed off by the release
223
   * manager machine.  Note that the release manager machine and the storage
224
   * relay do not share a key.  Only the lease service and the storage relay
225
   * share a key.
226
   */
227
  shash::Any payload_hash_;
228
229
  /**
230
   * The hmac protecting the caveats set by the release manager machine.
231
   */
232
  shash::Any hmac_3rd_party_;
233
};
234
235
#endif  // CVMFS_WEBAPI_MACAROON_H_