summaryrefslogtreecommitdiffstats
path: root/src/osd/OSDCap.h
blob: 394b1a72635c5b6015c2f1aff99e1d47b0007be6 (plain)
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
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 * OSDCaps: Hold the capabilities associated with a single authenticated
 * user key. These are specified by text strings of the form
 * "allow r" (which allows reading anything on the OSD)
 *  "allow rwx pool foo" (which allows full access to listed pools)
 * "allow *" (which allows full access to EVERYTHING)
 *
 * The full grammar is documented in the parser in OSDCap.cc.
 *
 * The OSD assumes that anyone with * caps is an admin and has full
 * message permissions. This means that only the monitor and the OSDs
 * should get *
 */

#ifndef CEPH_OSDCAP_H
#define CEPH_OSDCAP_H

#include <ostream>
using std::ostream;

#include "include/types.h"
#include "OpRequest.h"

#include <list>
#include <vector>
#include <boost/optional.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

static const __u8 OSD_CAP_R     = (1 << 1);      // read
static const __u8 OSD_CAP_W     = (1 << 2);      // write
static const __u8 OSD_CAP_CLS_R = (1 << 3);      // class read
static const __u8 OSD_CAP_CLS_W = (1 << 4);      // class write
static const __u8 OSD_CAP_X     = (OSD_CAP_CLS_R | OSD_CAP_CLS_W); // execute
static const __u8 OSD_CAP_ANY   = 0xff;          // *

struct osd_rwxa_t {
  __u8 val;

  // cppcheck-suppress noExplicitConstructor
  osd_rwxa_t(__u8 v = 0) : val(v) {}
  osd_rwxa_t& operator=(__u8 v) {
    val = v;
    return *this;
  }
  operator __u8() const {
    return val;
  }
};

ostream& operator<<(ostream& out, const osd_rwxa_t& p);

struct OSDCapSpec {
  osd_rwxa_t allow;
  std::string class_name;
  std::string method_name;

  OSDCapSpec() : allow(0) {}
  explicit OSDCapSpec(osd_rwxa_t v) : allow(v) {}
  OSDCapSpec(std::string class_name, std::string method_name)
    : allow(0), class_name(std::move(class_name)),
      method_name(std::move(method_name)) {}

  bool allow_all() const {
    return allow == OSD_CAP_ANY;
  }
};

ostream& operator<<(ostream& out, const OSDCapSpec& s);

struct OSDCapPoolNamespace {
  std::string pool_name;
  boost::optional<std::string> nspace = boost::none;

  OSDCapPoolNamespace() {
  }
  OSDCapPoolNamespace(const std::string& pool_name,
                      const boost::optional<std::string>& nspace = boost::none)
    : pool_name(pool_name), nspace(nspace) {
  }

  bool is_match(const std::string& pn, const std::string& ns) const;
  bool is_match_all() const;
};

ostream& operator<<(ostream& out, const OSDCapPoolNamespace& pns);

struct OSDCapPoolTag {
  typedef std::map<std::string, std::map<std::string, std::string> > app_map_t;
  std::string application;
  std::string key;
  std::string value;

  OSDCapPoolTag () {}
  OSDCapPoolTag(const std::string& application, const std::string& key,
		const std::string& value) :
    application(application), key(key), value(value) {}

  bool is_match(const app_map_t& app_map) const;
  bool is_match_all() const;
};
// adapt for parsing with boost::spirit::qi in OSDCapParser
BOOST_FUSION_ADAPT_STRUCT(OSDCapPoolTag,
			  (std::string, application)
			  (std::string, key)
			  (std::string, value))

ostream& operator<<(ostream& out, const OSDCapPoolTag& pt);

struct OSDCapMatch {
  typedef std::map<std::string, std::map<std::string, std::string> > app_map_t;
  OSDCapPoolNamespace pool_namespace;
  OSDCapPoolTag pool_tag;
  std::string object_prefix;

  OSDCapMatch() {}
  explicit OSDCapMatch(const OSDCapPoolTag& pt) : pool_tag(pt) {}
  explicit OSDCapMatch(const OSDCapPoolNamespace& pns) : pool_namespace(pns) {}
  OSDCapMatch(const OSDCapPoolNamespace& pns, const std::string& pre)
    : pool_namespace(pns), object_prefix(pre) {}
  OSDCapMatch(const std::string& pl, const std::string& pre)
    : pool_namespace(pl), object_prefix(pre) {}
  OSDCapMatch(const std::string& pl, const std::string& ns,
              const std::string& pre)
    : pool_namespace(pl, ns), object_prefix(pre) {}
  OSDCapMatch(const std::string& dummy, const std::string& app,
	      const std::string& key, const std::string& val)
    : pool_tag(app, key, val) {}
  OSDCapMatch(const std::string& ns, const OSDCapPoolTag& pt)
    : pool_namespace("", ns), pool_tag(pt) {}

  /**
   * check if given request parameters match our constraints
   *
   * @param pool_name pool name
   * @param nspace_name namespace name
   * @param object object name
   * @return true if we match, false otherwise
   */
  bool is_match(const std::string& pool_name, const std::string& nspace_name,
                const app_map_t& app_map,
		const std::string& object) const;
  bool is_match_all() const;
};

ostream& operator<<(ostream& out, const OSDCapMatch& m);


struct OSDCapProfile {
  std::string name;
  OSDCapPoolNamespace pool_namespace;

  OSDCapProfile() {
  }
  OSDCapProfile(const std::string& name,
                const std::string& pool_name,
                const boost::optional<std::string>& nspace = boost::none)
    : name(name), pool_namespace(pool_name, nspace) {
  }

  inline bool is_valid() const {
    return !name.empty();
  }
};

ostream& operator<<(ostream& out, const OSDCapProfile& m);

struct OSDCapGrant {
  OSDCapMatch match;
  OSDCapSpec spec;
  OSDCapProfile profile;
  std::string network;
  entity_addr_t network_parsed;
  unsigned network_prefix = 0;
  bool network_valid = true;

  // explicit grants that a profile grant expands to; populated as
  // needed by expand_profile() and cached here.
  std::list<OSDCapGrant> profile_grants;

  OSDCapGrant() {}
  OSDCapGrant(const OSDCapMatch& m, const OSDCapSpec& s,
	      boost::optional<std::string> n = {})
    : match(m), spec(s) {
    if (n) {
      set_network(*n);
    }
  }
  explicit OSDCapGrant(const OSDCapProfile& profile,
		       boost::optional<std::string> n = {})
    : profile(profile) {
    if (n) {
      set_network(*n);
    }
    expand_profile();
  }

  void set_network(const std::string& n);

  bool allow_all() const;
  bool is_capable(const std::string& pool_name, const std::string& ns,
		  const OSDCapPoolTag::app_map_t& application_metadata,
                  const std::string& object, bool op_may_read, bool op_may_write,
                  const std::vector<OpInfo::ClassInfo>& classes,
		  const entity_addr_t& addr,
                  std::vector<bool>* class_allowed) const;

  void expand_profile();
};

ostream& operator<<(ostream& out, const OSDCapGrant& g);


struct OSDCap {
  std::vector<OSDCapGrant> grants;

  OSDCap() {}
  explicit OSDCap(std::vector<OSDCapGrant> g) : grants(std::move(g)) {}

  bool allow_all() const;
  void set_allow_all();
  bool parse(const std::string& str, ostream *err=NULL);

  /**
   * check if we are capable of something
   *
   * This method actually checks a description of a particular operation against
   * what the capability has specified.  Currently that is just rwx with matches
   * against pool, and object name prefix.
   *
   * @param pool_name name of the pool we are accessing
   * @param ns name of the namespace we are accessing
   * @param object name of the object we are accessing
   * @param op_may_read whether the operation may need to read
   * @param op_may_write whether the operation may need to write
   * @param classes (class-name, rd, wr, allowed-flag) tuples
   * @return true if the operation is allowed, false otherwise
   */
  bool is_capable(const std::string& pool_name, const std::string& ns,
		  const OSDCapPoolTag::app_map_t& application_metadata,
		  const std::string& object, bool op_may_read, bool op_may_write,
		  const std::vector<OpInfo::ClassInfo>& classes,
		  const entity_addr_t& addr) const;
};

inline std::ostream& operator<<(std::ostream& out, const OSDCap& cap) 
{
  return out << "osdcap" << cap.grants;
}

#endif