Directory: | cvmfs/ |
---|---|
File: | cvmfs/authz/authz_session.h |
Date: | 2025-02-09 02:34:19 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 20 | 20 | 100.0% |
Branches: | 6 | 8 | 75.0% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * This file is part of the CernVM File System. | ||
3 | */ | ||
4 | |||
5 | #ifndef CVMFS_AUTHZ_AUTHZ_SESSION_H_ | ||
6 | #define CVMFS_AUTHZ_AUTHZ_SESSION_H_ | ||
7 | |||
8 | #include <inttypes.h> | ||
9 | #include <pthread.h> | ||
10 | #include <unistd.h> | ||
11 | |||
12 | #include <string> | ||
13 | |||
14 | #include "authz/authz.h" | ||
15 | #include "gtest/gtest_prod.h" | ||
16 | #include "smallhash.h" | ||
17 | #include "statistics.h" | ||
18 | #include "util/murmur.hxx" | ||
19 | #include "util/single_copy.h" | ||
20 | |||
21 | class AuthzFetcher; | ||
22 | |||
23 | // TODO(jblomer): add audit log | ||
24 | |||
25 | /** | ||
26 | * The authorization manager maintains a list of sessions (sid and its birthday) | ||
27 | * and their associated credentials. It is used to pass the credentials to the | ||
28 | * download module and to control access to the repository. Every credential | ||
29 | * has a membership (a string) associated with it. The credential is thereby | ||
30 | * confirmed to be a member of the specified group. The group/membership can | ||
31 | * be anything, for instance a role in a certificate. It is stored in the cvmfs | ||
32 | * root file catalog. | ||
33 | * | ||
34 | * An AuthzFetcher is used to gather credentials that are not cached. Note that | ||
35 | * the credentials are fetched using original pid/uid/gid but cached under the | ||
36 | * session. | ||
37 | */ | ||
38 | class AuthzSessionManager : SingleCopy { | ||
39 | FRIEND_TEST(T_AuthzSession, GetPidInfo); | ||
40 | FRIEND_TEST(T_AuthzSession, LookupAuthzData); | ||
41 | FRIEND_TEST(T_AuthzSession, LookupSessionKey); | ||
42 | |||
43 | public: | ||
44 | static AuthzSessionManager *Create(AuthzFetcher *authz_fetcher, | ||
45 | perf::Statistics *statistics); | ||
46 | ~AuthzSessionManager(); | ||
47 | |||
48 | AuthzToken *GetTokenCopy(const pid_t pid, const std::string &membership); | ||
49 | bool IsMemberOf(const pid_t pid, const std::string &membership); | ||
50 | |||
51 | /** | ||
52 | * When the membership string in the root file catalog changes, all entries in | ||
53 | * the cache become invalid because they only vouch for the previous | ||
54 | * membership entry. This function is called by MountPoint::ReEvaluateAuthz. | ||
55 | */ | ||
56 | void ClearSessionCache(); | ||
57 | |||
58 | private: | ||
59 | /** | ||
60 | * Sweep caches from old entries not more often than every 5 seconds. | ||
61 | */ | ||
62 | static const unsigned kSweepInterval = 5; | ||
63 | |||
64 | /** | ||
65 | * Pid to session information is cached for 2 minutes. | ||
66 | */ | ||
67 | static const unsigned kPidLifetime = 120; | ||
68 | |||
69 | /** | ||
70 | * Extended information on a PID. | ||
71 | */ | ||
72 | struct PidKey { | ||
73 | 1082 | PidKey() : pid(-1), uid(-1), gid(-1), sid(-1), pid_bday(0), deadline(0) { } | |
74 | pid_t pid; | ||
75 | uid_t uid; | ||
76 | gid_t gid; | ||
77 | pid_t sid; | ||
78 | uint64_t pid_bday; | ||
79 | uint64_t deadline; | ||
80 | |||
81 | 151 | bool operator ==(const PidKey &other) const { | |
82 |
2/2✓ Branch 0 taken 143 times.
✓ Branch 1 taken 8 times.
|
294 | return (pid == other.pid) && |
83 |
1/2✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
|
294 | (pid_bday == other.pid_bday); |
84 | } | ||
85 | |||
86 | 126 | bool operator !=(const PidKey &other) const { | |
87 | 126 | return !(*this == other); | |
88 | } | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * Extended information on an SID. | ||
93 | */ | ||
94 | struct SessionKey { | ||
95 | 2108 | SessionKey() : sid(-1), sid_bday(0) { } | |
96 | pid_t sid; | ||
97 | uint64_t sid_bday; | ||
98 | |||
99 | 1112 | bool operator ==(const SessionKey &other) const { | |
100 |
2/2✓ Branch 0 taken 1097 times.
✓ Branch 1 taken 15 times.
|
2209 | return (sid == other.sid) && |
101 |
1/2✓ Branch 0 taken 1097 times.
✗ Branch 1 not taken.
|
2209 | (sid_bday == other.sid_bday); |
102 | } | ||
103 | |||
104 | 1071 | bool operator !=(const SessionKey &other) const { | |
105 | 1071 | return !(*this == other); | |
106 | } | ||
107 | }; | ||
108 | |||
109 | 18 | static uint32_t HashPidKey(const PidKey &key) { | |
110 | struct { | ||
111 | uint64_t bday; | ||
112 | pid_t pid; | ||
113 | } __attribute__((packed)) key_info; | ||
114 | 18 | key_info.pid = key.pid; | |
115 | 18 | key_info.bday = key.pid_bday; | |
116 | 18 | return MurmurHash2(&key_info, sizeof(key_info), 0x07387a4f); | |
117 | } | ||
118 | |||
119 | 30 | static uint32_t HashSessionKey(const SessionKey &key) { | |
120 | struct { | ||
121 | uint64_t bday; | ||
122 | pid_t pid; | ||
123 | } __attribute__((packed)) key_info; | ||
124 | 30 | key_info.pid = key.sid; | |
125 | 30 | key_info.bday = key.sid_bday; | |
126 | 30 | return MurmurHash2(&key_info, sizeof(key_info), 0x07387a4f); | |
127 | } | ||
128 | |||
129 | AuthzSessionManager(); | ||
130 | |||
131 | bool GetPidInfo(pid_t pid, PidKey *pid_key); | ||
132 | bool LookupSessionKey(pid_t pid, PidKey *pid_key, SessionKey *session_key); | ||
133 | void MaySweepPids(); | ||
134 | void SweepPids(uint64_t now); | ||
135 | |||
136 | bool LookupAuthzData(const PidKey &pid_key, | ||
137 | const SessionKey &session_key, | ||
138 | const std::string &membership, | ||
139 | AuthzData *authz_data); | ||
140 | void MaySweepCreds(); | ||
141 | void SweepCreds(uint64_t now); | ||
142 | |||
143 | /** | ||
144 | * Caches (extended) session information for an (extended) pid. | ||
145 | */ | ||
146 | SmallHashDynamic<PidKey, SessionKey> pid2session_; | ||
147 | pthread_mutex_t lock_pid2session_; | ||
148 | uint64_t deadline_sweep_pids_; | ||
149 | |||
150 | /** | ||
151 | * Caches credentials corresponding to a session. | ||
152 | */ | ||
153 | SmallHashDynamic<SessionKey, AuthzData> session2cred_; | ||
154 | pthread_mutex_t lock_session2cred_; | ||
155 | uint64_t deadline_sweep_creds_; | ||
156 | |||
157 | /** | ||
158 | * The helper that takes care of bringing in credentials from the client | ||
159 | * context. | ||
160 | */ | ||
161 | AuthzFetcher *authz_fetcher_; | ||
162 | |||
163 | perf::Counter *no_pid_; | ||
164 | perf::Counter *no_session_; | ||
165 | perf::Counter *n_fetch_; | ||
166 | perf::Counter *n_grant_; | ||
167 | perf::Counter *n_deny_; | ||
168 | }; | ||
169 | |||
170 | #endif // CVMFS_AUTHZ_AUTHZ_SESSION_H_ | ||
171 |