XRootD
Loading...
Searching...
No Matches
XrdSciTokensAccess.hh
Go to the documentation of this file.
1
4
5#include <memory>
6#include <string>
7#include <string_view>
8#include <vector>
9
10#include <string.h>
11
15
16typedef std::vector<std::pair<Access_Operation, std::string>> AccessRulesRaw;
17
18// Class representing a rule in the administrator-provided mapfile.
19// All predicates must match for the rule to apply.
20struct MapRule
21{
22 MapRule(const std::string &sub,
23 const std::string &username,
24 const std::string &path_prefix,
25 const std::string &group,
26 const std::string &result)
27 : m_sub(sub),
28 m_username(username),
29 m_path_prefix(path_prefix),
30 m_group(group),
31 m_result(result)
32 {
33 //std::cerr << "Making a rule {sub=" << sub << ", username=" << username << ", path=" << path_prefix << ", group=" << group << ", result=" << name << "}" << std::endl;
34 }
35
36 const std::string match(const std::string &sub,
37 const std::string &username,
38 const std::string_view &req_path,
39 const std::vector<std::string> &groups) const
40 {
41 if (!m_sub.empty() && sub != m_sub) {return "";}
42
43 if (!m_username.empty() && username != m_username) {return "";}
44
45 if (!m_path_prefix.empty() &&
46 strncmp(req_path.data(), m_path_prefix.c_str(), m_path_prefix.size()))
47 {
48 return "";
49 }
50
51 if (!m_group.empty()) {
52 for (const auto &group : groups) {
53 if (group == m_group)
54 return m_result;
55 }
56 return "";
57 }
58 return m_result;
59 }
60
61 std::string m_sub;
62 std::string m_username;
63 std::string m_path_prefix;
64 std::string m_group;
65 std::string m_result;
66};
67
68// Control whether a given issuer is required for the paths it authorizes
69enum class AuthzSetting {
70 None, // Issuer's authorization is not necessary
71 Read, // Authorization from this issuer is necessary for reads.
72 Write, // Authorization from this issuer is necessary for writes.
73 All, // Authorization from this issuer is necessary for all operations.
74};
75
76// Controls what part of the token is used to determine a positive authorization.
77//
78// E.g., if IssuerAuthz::Group is set, then the positive authorization may be based
79// on the groups embedded in the token.
81 Capability = 0x01,
82 Group = 0x02,
83 Mapping = 0x04,
84 Default = 0x07
85};
86
87// Given a list of access rules, this class determines whether a requested operation / path
88// is permitted by the access rules.
89class SubpathMatch final {
90public:
91 SubpathMatch() = default;
93 : m_rules(rules)
94 {}
95
96 // Determine whether the known access rules permit the requested `oper` on `path`.
97 bool apply(Access_Operation oper, const std::string_view path) const {
98
99 for (const auto & rule : m_rules) {
100 // Skip rules that don't match the current operation
101 if (rule.first != oper)
102 continue;
103
104 // If the rule allows any path, allow the operation
105 if (rule.second == "/")
106 return true;
107
108 // Allow operation if path is a subdirectory of the rule's path
109 if (is_subdirectory(rule.second, path)) {
110 return true;
111 } else {
112 // Allow stat and mkdir of parent directories to comply with WLCG token specs
113 if (oper == AOP_Stat || oper == AOP_Mkdir)
114 if (is_subdirectory(path, rule.second))
115 return true;
116 }
117 }
118 return false;
119 }
120
121 bool empty() const {return m_rules.empty();} // Returns true if there are no rules to match
122
123 std::string str() const; // Returns a human-friendly representation of the access rules
124
125 size_t size() const {return m_rules.size();} // Returns the count of rules
126private:
127
128 AccessRulesRaw m_rules;
129};
130
138{
139public:
140 XrdAccRules(uint64_t expiry_time, const std::string &username, const std::string &token_subject,
141 const std::string &issuer, const std::vector<MapRule> &rules, const std::vector<std::string> &groups,
142 uint32_t authz_strategy, AuthzSetting acceptable_authz) :
143 m_authz_strategy(authz_strategy),
144 m_acceptable_authz(acceptable_authz),
145 m_expiry_time(expiry_time),
146 m_username(username),
147 m_token_subject(token_subject),
148 m_issuer(issuer),
149 m_map_rules(rules),
150 m_groups(groups)
151 {}
152
154
155 bool apply(Access_Operation oper, const std::string_view path) {
156 return m_matcher.apply(oper, path);
157 }
158
159 // Check to see if the access rules generated for this token have expired
160 bool expired() const;
161
162 void parse(const AccessRulesRaw &rules) {
163 m_matcher = SubpathMatch(rules);
164 }
165
166 std::string get_username(const std::string_view &req_path) const
167 {
168 for (const auto &rule : m_map_rules) {
169 std::string name = rule.match(m_token_subject, m_username, req_path, m_groups);
170 if (!name.empty()) {
171 return name;
172 }
173 }
174 return "";
175 }
176
177 const std::string str() const;
178
179 // Return the token's subject, an opaque unique string within the issuer's
180 // namespace. It may or may not be related to the username one should
181 // use within the authorization framework.
182 const std::string & get_token_subject() const {return m_token_subject;}
183 const std::string & get_default_username() const {return m_username;}
184 const std::string & get_issuer() const {return m_issuer;}
185
186 uint32_t get_authz_strategy() const {return m_authz_strategy;}
188 if (m_acceptable_authz == AuthzSetting::All) return true;
189 if (m_acceptable_authz == AuthzSetting::None) return false;
190
191 bool is_read = oper == AOP_Read || oper == AOP_Readdir || oper == AOP_Stat;
192 if (is_read) return m_acceptable_authz == AuthzSetting::Read;
193 else return m_acceptable_authz == AuthzSetting::Write;
194 }
195
196 size_t size() const {return m_matcher.size();}
197 const std::vector<std::string> &groups() const {return m_groups;}
198
199private:
200 const uint32_t m_authz_strategy;
201 const AuthzSetting m_acceptable_authz;
202 SubpathMatch m_matcher;
203 const uint64_t m_expiry_time{0};
204 const std::string m_username;
205 const std::string m_token_subject;
206 const std::string m_issuer;
207 const std::vector<MapRule> m_map_rules;
208 const std::vector<std::string> m_groups;
209};
210
211bool AuthorizesRequiredIssuers(Access_Operation client_oper, const std::string_view &path,
212 const std::vector<std::pair<std::unique_ptr<SubpathMatch>, std::string>> &required_issuers,
213 const std::vector<std::shared_ptr<XrdAccRules>> &access_rules_list);
214
Access_Operation
The following are supported operations.
@ AOP_Mkdir
mkdir()
@ AOP_Readdir
opendir()
@ AOP_Stat
exists(), stat()
@ AOP_Read
open() r/o, prepare()
static bool is_subdirectory(const std::string_view dir, const std::string_view subdir)
bool AuthorizesRequiredIssuers(Access_Operation client_oper, const std::string_view &path, const std::vector< std::pair< std::unique_ptr< SubpathMatch >, std::string > > &required_issuers, const std::vector< std::shared_ptr< XrdAccRules > > &access_rules_list)
std::vector< std::pair< Access_Operation, std::string > > AccessRulesRaw
@ Capability
size_t size() const
SubpathMatch(const AccessRulesRaw &rules)
SubpathMatch()=default
std::string str() const
bool apply(Access_Operation oper, const std::string_view path) const
const std::string & get_default_username() const
bool apply(Access_Operation oper, const std::string_view path)
const std::string & get_token_subject() const
bool expired() const
uint32_t get_authz_strategy() const
size_t size() const
void parse(const AccessRulesRaw &rules)
bool acceptable_authz(Access_Operation oper) const
const std::string & get_issuer() const
std::string get_username(const std::string_view &req_path) const
const std::string str() const
XrdAccRules(uint64_t expiry_time, const std::string &username, const std::string &token_subject, const std::string &issuer, const std::vector< MapRule > &rules, const std::vector< std::string > &groups, uint32_t authz_strategy, AuthzSetting acceptable_authz)
const std::vector< std::string > & groups() const
const std::string match(const std::string &sub, const std::string &username, const std::string_view &req_path, const std::vector< std::string > &groups) const
std::string m_sub
std::string m_group
std::string m_result
std::string m_path_prefix
std::string m_username
MapRule(const std::string &sub, const std::string &username, const std::string &path_prefix, const std::string &group, const std::string &result)