userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
secdist.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/storages/secdist/secdist.hpp
4
/// @brief @copybrief storages::secdist::SecdistConfig
5
6
#
include
<
any
>
7
#
include
<
chrono
>
8
#
include
<
cstdint
>
9
#
include
<
functional
>
10
#
include
<
optional
>
11
#
include
<
stdexcept
>
12
#
include
<
string
>
13
#
include
<
string_view
>
14
#
include
<
typeindex
>
15
#
include
<
vector
>
16
17
#
include
<
userver
/
concurrent
/
async_event_source
.
hpp
>
18
#
include
<
userver
/
engine
/
task
/
task_processor_fwd
.
hpp
>
19
#
include
<
userver
/
formats
/
json
/
value
.
hpp
>
20
#
include
<
userver
/
rcu
/
rcu
.
hpp
>
21
#
include
<
userver
/
storages
/
secdist
/
provider
.
hpp
>
22
#
include
<
userver
/
utils
/
fast_pimpl
.
hpp
>
23
#
include
<
userver
/
utils
/
resource_scopes_fwd
.
hpp
>
24
25
USERVER_NAMESPACE_BEGIN
26
27
/// Credentials storage
28
namespace
storages::secdist {
29
30
class
SecdistConfig;
31
32
namespace
detail {
33
34
template
<
typename
T>
35
class
SecdistModule
final
{
36
public
:
37
static
const
T& Get(
const
SecdistConfig& config);
38
static
std::any Factory(
const
formats::
json
::
Value
& data) {
return
T(data); }
39
40
private
:
41
static
std::size_t index;
42
};
43
44
}
// namespace detail
45
46
/// Secdist file format
47
enum
class
SecdistFormat
{
48
kJson,
49
kYaml,
50
kYamlConfig,
51
};
52
53
/// @ingroup userver_clients
54
///
55
/// @brief Client to retrieve credentials from the components::Secdist.
56
///
57
/// ## Example usage:
58
///
59
/// Declare a type that would work with the credentials:
60
///
61
/// @snippet core/src/storages/secdist/secdist_test.cpp UserPasswords
62
///
63
/// Fill the components::Secdist `config` from file with the secure data:
64
///
65
/// @snippet core/src/storages/secdist/secdist_test.cpp Secdist Usage Sample - json
66
///
67
/// Retrieve SecdistConfig from components::Secdist and get the type from it:
68
///
69
/// @snippet core/src/storages/secdist/secdist_test.cpp Secdist Usage Sample - SecdistConfig
70
///
71
/// Json with secure data can also be loaded from environment variable with name defined in `environment_secrets_key`.
72
/// Sample variable value: `{"user-passwords":{"username":"password","another username":"another password"}}`.
73
/// It has the same format as data from file.
74
/// If both sources are presented, data from environment variable will be merged with data from file
75
/// (json objects will be merged, duplicate fields of other types will be overridden by data from environment variable).
76
class
SecdistConfig
final
{
77
public
:
78
struct
Settings
{
79
SecdistProvider
* provider{
nullptr
};
80
std::chrono::milliseconds update_period{std::chrono::milliseconds::zero()};
81
};
82
83
SecdistConfig();
84
explicit
SecdistConfig(
const
Settings
& settings);
85
86
template
<
typename
T>
87
static
std::size_t Register(std::function<std::any(
const
formats::
json
::
Value
&)>&& factory) {
88
return
Register(std::move(factory));
89
}
90
91
template
<
typename
T>
92
const
T& Get()
const
{
93
return
detail::SecdistModule<T>::Get(*
this
);
94
}
95
96
private
:
97
void
Init(
const
formats::
json
::
Value
& doc);
98
99
static
std::size_t Register(std::function<std::any(
const
formats::
json
::
Value
&)>&& factory);
100
const
std::any& Get(
const
std::type_index& type, std::size_t index)
const
;
101
102
template
<
typename
T>
103
friend
class
detail::SecdistModule;
104
105
std::vector<std::any> configs_;
106
};
107
108
/// @ingroup userver_clients
109
///
110
/// @brief Client to retrieve credentials from the components::Secdist and to
111
/// subscribe to their updates.
112
class
Secdist
final
{
113
public
:
114
explicit
Secdist(SecdistConfig::
Settings
settings);
115
~Secdist();
116
117
/// Returns secdist data loaded on service start.
118
/// Does not support secdist updating during service work.
119
const
storages::secdist::SecdistConfig&
Get
()
const
;
120
121
/// Returns fresh secdist data (from last update).
122
/// Supports secdist updating during service work.
123
rcu
::
ReadablePtr
<storages::secdist::SecdistConfig>
GetSnapshot
()
const
;
124
125
/// Subscribes to secdist updates using a member function, named
126
/// `OnSecdistUpdate` by convention. Also immediately invokes the function
127
/// with the current secdist data.
128
///
129
/// Further updates are delivered after @ref utils::ResourceScopeStorage::AfterConstruction, including those updates
130
/// that arrived before it. Unsubscribe runs in @ref utils::ResourceScopeStorage::BeforeDestruction.
131
///
132
/// @param scopes storage that owns the subscription lifetime. In a component constructor pass `context.Scopes()`
133
/// or @ref components::GetResourceScopes.
134
template
<
typename
Class>
135
void
UpdateAndListen
(
136
utils
::ResourceScopeStorage& scopes,
137
Class* obj,
138
std::string_view name,
139
void
(Class::*func)(
const
storages::secdist::SecdistConfig& secdist)
140
);
141
142
/// @overload
143
/// @deprecated Use the overload that takes @ref utils::ResourceScopeStorage.
144
///
145
/// Store the returned scope as a member and call `Unsubscribe` explicitly.
146
template
<
typename
Class>
147
concurrent
::AsyncEventSubscriberScope
UpdateAndListen
(
148
Class* obj,
149
std::string_view name,
150
void
(Class::*func)(
const
storages::secdist::SecdistConfig& secdist)
151
);
152
153
bool
IsPeriodicUpdateEnabled()
const
noexcept
;
154
155
private
:
156
using
EventSource =
concurrent
::
AsyncEventSource
<
const
SecdistConfig&>;
157
158
concurrent
::AsyncEventSubscriberScope DoUpdateAndListen(
159
concurrent
::FunctionId id,
160
std::string_view name,
161
EventSource::Function&& func
162
);
163
164
void
DoUpdateAndListen(
165
utils
::ResourceScopeStorage& scopes,
166
concurrent
::FunctionId id,
167
std::string_view name,
168
EventSource::Function&& func
169
);
170
171
class
Impl;
172
utils
::FastPimpl<Impl, 1280, 16> impl_;
173
};
174
175
template
<
typename
Class>
176
void
Secdist::
UpdateAndListen
(
177
utils
::ResourceScopeStorage& scopes,
178
Class* obj,
179
std::string_view name,
180
void
(Class::*func)(
const
storages::secdist::SecdistConfig& secdist)
181
) {
182
DoUpdateAndListen(scopes,
concurrent
::FunctionId(obj), name, [obj, func](
const
SecdistConfig& config) {
183
(obj->*func)(config);
184
});
185
}
186
187
template
<
typename
Class>
188
concurrent
::AsyncEventSubscriberScope Secdist::
UpdateAndListen
(
189
Class* obj,
190
std::string_view name,
191
void
(Class::*func)(
const
storages::secdist::SecdistConfig& secdist)
192
) {
193
return
DoUpdateAndListen(
concurrent
::FunctionId(obj), name, [obj, func](
const
SecdistConfig& config) {
194
(obj->*func)(config);
195
});
196
}
197
198
namespace
detail {
199
200
template
<
typename
T>
201
const
T& SecdistModule<T>::Get(
const
SecdistConfig& config) {
202
return
std::any_cast<
const
T&>(config.Get(
typeid
(T), index));
203
}
204
205
template
<
typename
T>
206
std::size_t SecdistModule<T>::index = SecdistConfig::Register<T>(&SecdistModule<T>::Factory);
207
208
}
// namespace detail
209
210
}
// namespace storages::secdist
211
212
USERVER_NAMESPACE_END
userver
storages
secdist
secdist.hpp
Generated on
for userver by
Doxygen
1.17.0