passenger 5.0.9 → 5.0.10
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/CHANGELOG +15 -0
- data/CONTRIBUTORS +6 -0
- data/README.md +1 -1
- data/bin/passenger-install-apache2-module +24 -11
- data/bin/passenger-status +29 -14
- data/build/agents.rb +12 -10
- data/build/cxx_tests.rb +30 -30
- data/doc/Design and Architecture.html +1 -10
- data/doc/Design and Architecture.txt +1 -6
- data/doc/Users guide Apache.html +1 -19
- data/doc/Users guide Apache.txt +1 -1
- data/doc/Users guide Nginx.html +2 -20
- data/doc/Users guide Nginx.txt +2 -2
- data/doc/users_guide_snippets/tips.txt +0 -9
- data/ext/common/ApplicationPool2/ApiKey.h +158 -0
- data/ext/common/ApplicationPool2/BasicGroupInfo.h +81 -0
- data/ext/common/ApplicationPool2/BasicProcessInfo.h +106 -0
- data/ext/common/ApplicationPool2/Common.h +5 -44
- data/ext/common/ApplicationPool2/Context.h +94 -0
- data/ext/common/ApplicationPool2/Group.h +130 -1205
- data/ext/common/ApplicationPool2/Group/InitializationAndShutdown.cpp +190 -0
- data/ext/common/ApplicationPool2/Group/InternalUtils.cpp +329 -0
- data/ext/common/ApplicationPool2/Group/LifetimeAndBasics.cpp +103 -0
- data/ext/common/ApplicationPool2/{Pool/Debug.h → Group/Miscellaneous.cpp} +40 -38
- data/ext/common/ApplicationPool2/Group/OutOfBandWork.cpp +323 -0
- data/ext/common/ApplicationPool2/Group/ProcessListManagement.cpp +606 -0
- data/ext/common/ApplicationPool2/Group/SessionManagement.cpp +337 -0
- data/ext/common/ApplicationPool2/Group/SpawningAndRestarting.cpp +478 -0
- data/ext/common/ApplicationPool2/Group/StateInspection.cpp +197 -0
- data/ext/common/ApplicationPool2/Group/Verification.cpp +159 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +19 -1401
- data/ext/common/ApplicationPool2/Options.h +5 -5
- data/ext/common/ApplicationPool2/Pool.h +260 -815
- data/ext/common/ApplicationPool2/Pool/{AnalyticsCollection.h → AnalyticsCollection.cpp} +55 -56
- data/ext/common/ApplicationPool2/Pool/{GarbageCollection.h → GarbageCollection.cpp} +49 -49
- data/ext/common/ApplicationPool2/Pool/GeneralUtils.cpp +241 -0
- data/ext/common/ApplicationPool2/Pool/GroupUtils.cpp +276 -0
- data/ext/common/ApplicationPool2/Pool/InitializationAndShutdown.cpp +145 -0
- data/ext/common/ApplicationPool2/Pool/Miscellaneous.cpp +244 -0
- data/ext/common/ApplicationPool2/Pool/ProcessUtils.cpp +330 -0
- data/ext/common/ApplicationPool2/Pool/StateInspection.cpp +299 -0
- data/ext/common/ApplicationPool2/Process.h +399 -205
- data/ext/common/ApplicationPool2/Session.h +70 -28
- data/ext/common/ApplicationPool2/Socket.h +1 -0
- data/ext/common/Constants.h +11 -3
- data/ext/common/Exceptions.h +1 -1
- data/ext/common/Logging.cpp +9 -4
- data/ext/common/Logging.h +6 -0
- data/ext/common/ServerKit/HttpServer.h +225 -215
- data/ext/common/ServerKit/Server.h +57 -57
- data/ext/common/SpawningKit/BackgroundIOCapturer.h +160 -0
- data/ext/common/SpawningKit/Config.h +107 -0
- data/ext/common/{ApplicationPool2 → SpawningKit}/DirectSpawner.h +17 -16
- data/ext/common/{ApplicationPool2 → SpawningKit}/DummySpawner.h +33 -33
- data/ext/common/{ApplicationPool2/SpawnerFactory.h → SpawningKit/Factory.h} +17 -17
- data/ext/common/{ApplicationPool2/ComponentInfo.h → SpawningKit/Options.h} +8 -21
- data/ext/common/SpawningKit/PipeWatcher.h +148 -0
- data/ext/common/{ApplicationPool2/PipeWatcher.h → SpawningKit/Result.h} +15 -33
- data/ext/common/{ApplicationPool2 → SpawningKit}/SmartSpawner.h +52 -57
- data/ext/common/{ApplicationPool2 → SpawningKit}/Spawner.h +83 -371
- data/ext/common/SpawningKit/UserSwitchingRules.h +265 -0
- data/ext/common/Utils/BufferedIO.h +24 -0
- data/ext/common/{ApplicationPool2/SpawnObject.h → Utils/ClassUtils.h} +24 -51
- data/ext/common/Utils/IOUtils.cpp +70 -0
- data/ext/common/Utils/IOUtils.h +19 -0
- data/ext/common/Utils/JsonUtils.h +113 -0
- data/ext/common/Utils/StrIntUtils.h +29 -0
- data/ext/common/Utils/json.h +1 -1
- data/ext/common/agents/ApiServerUtils.h +941 -0
- data/ext/common/agents/HelperAgent/{AdminServer.h → ApiServer.h} +163 -365
- data/ext/common/agents/HelperAgent/Main.cpp +86 -88
- data/ext/common/agents/HelperAgent/OptionParser.h +9 -10
- data/ext/common/agents/HelperAgent/RequestHandler/BufferBody.cpp +3 -0
- data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +2 -0
- data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +1 -1
- data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +2 -2
- data/ext/common/agents/LoggingAgent/ApiServer.h +279 -0
- data/ext/common/agents/LoggingAgent/Main.cpp +41 -51
- data/ext/common/agents/LoggingAgent/OptionParser.h +11 -11
- data/ext/common/agents/Watchdog/ApiServer.h +311 -0
- data/ext/common/agents/Watchdog/Main.cpp +91 -65
- data/helper-scripts/prespawn +2 -0
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/admin_tools/instance.rb +1 -1
- data/lib/phusion_passenger/common_library.rb +27 -14
- data/lib/phusion_passenger/config/{admin_command_command.rb → api_call_command.rb} +19 -16
- data/lib/phusion_passenger/config/detach_process_command.rb +6 -3
- data/lib/phusion_passenger/config/main.rb +3 -5
- data/lib/phusion_passenger/config/reopen_logs_command.rb +29 -7
- data/lib/phusion_passenger/config/restart_app_command.rb +13 -4
- data/lib/phusion_passenger/config/utils.rb +15 -8
- data/lib/phusion_passenger/constants.rb +6 -2
- data/lib/phusion_passenger/platform_info/apache.rb +4 -0
- data/lib/phusion_passenger/platform_info/apache_detector.rb +18 -3
- data/resources/templates/apache2/mpm_unknown.txt.erb +20 -0
- metadata +42 -21
- metadata.gz.asc +7 -7
- data/ext/common/ApplicationPool2/Pool/GeneralUtils.h +0 -127
- data/ext/common/ApplicationPool2/Pool/Inspection.h +0 -219
- data/ext/common/ApplicationPool2/Pool/ProcessUtils.h +0 -85
- data/ext/common/ApplicationPool2/SuperGroup.h +0 -706
- data/ext/common/agents/LoggingAgent/AdminServer.h +0 -435
- data/ext/common/agents/Watchdog/AdminServer.h +0 -432
@@ -1002,6 +1002,7 @@ keepAliveAppConnection(Client *client, Request *req) {
|
|
1002
1002
|
void
|
1003
1003
|
storeAppResponseInTurboCache(Client *client, Request *req) {
|
1004
1004
|
if (turboCaching.isEnabled() && !req->cacheKey.empty()) {
|
1005
|
+
TRACE_POINT();
|
1005
1006
|
AppResponse *resp = &req->appResponse;
|
1006
1007
|
unsigned int headerSize = 0;
|
1007
1008
|
unsigned int i;
|
@@ -1013,6 +1014,7 @@ storeAppResponseInTurboCache(Client *client, Request *req) {
|
|
1013
1014
|
turboCaching.responseCache.store(req, ev_now(getLoop()),
|
1014
1015
|
headerSize, resp->bodyCacheBuffer.size));
|
1015
1016
|
if (entry.valid()) {
|
1017
|
+
UPDATE_TRACE_POINT();
|
1016
1018
|
SKC_DEBUG(client, "Storing app response in turbocache");
|
1017
1019
|
SKC_TRACE(client, 2, "Turbocache entries:\n" << turboCaching.responseCache.inspect());
|
1018
1020
|
|
@@ -31,7 +31,7 @@ virtual unsigned int getClientName(const Client *client, char *buf, size_t size)
|
|
31
31
|
char *pos = buf;
|
32
32
|
const char *end = buf + size - 1;
|
33
33
|
// WARNING: If you change the format, be sure to change
|
34
|
-
//
|
34
|
+
// ApiServer::extractThreadNumberFromClientName() too.
|
35
35
|
pos += uintToString(threadNumber, pos, end - pos);
|
36
36
|
pos = appendData(pos, end, "-", 1);
|
37
37
|
pos += uintToString(client->number, pos, end - pos);
|
@@ -290,7 +290,7 @@ determineHeaderSizeForSessionProtocol(Request *req,
|
|
290
290
|
}
|
291
291
|
|
292
292
|
dataSize += sizeof("PASSENGER_CONNECT_PASSWORD");
|
293
|
-
dataSize +=
|
293
|
+
dataSize += ApplicationPool2::ApiKey::SIZE + 1;
|
294
294
|
|
295
295
|
if (req->https) {
|
296
296
|
dataSize += sizeof("HTTPS");
|
@@ -404,7 +404,7 @@ constructHeaderForSessionProtocol(Request *req, char * restrict buffer, unsigned
|
|
404
404
|
}
|
405
405
|
|
406
406
|
pos = appendData(pos, end, P_STATIC_STRING_WITH_NULL("PASSENGER_CONNECT_PASSWORD"));
|
407
|
-
pos = appendData(pos, end, req->session->
|
407
|
+
pos = appendData(pos, end, req->session->getApiKey().toStaticString());
|
408
408
|
pos = appendData(pos, end, "", 1);
|
409
409
|
|
410
410
|
if (req->https) {
|
@@ -0,0 +1,279 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2013-2015 Phusion
|
4
|
+
*
|
5
|
+
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
12
|
+
* furnished to do so, subject to the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
15
|
+
* all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
* THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
#ifndef _PASSENGER_LOGGING_AGENT_API_SERVER_H_
|
26
|
+
#define _PASSENGER_LOGGING_AGENT_API_SERVER_H_
|
27
|
+
|
28
|
+
#include <sstream>
|
29
|
+
#include <string>
|
30
|
+
|
31
|
+
#include <agents/LoggingAgent/LoggingServer.h>
|
32
|
+
#include <agents/ApiServerUtils.h>
|
33
|
+
#include <ApplicationPool2/ApiKey.h>
|
34
|
+
#include <ServerKit/HttpServer.h>
|
35
|
+
#include <DataStructures/LString.h>
|
36
|
+
#include <Exceptions.h>
|
37
|
+
#include <StaticString.h>
|
38
|
+
#include <Utils/StrIntUtils.h>
|
39
|
+
#include <Utils/modp_b64.h>
|
40
|
+
#include <Utils/json.h>
|
41
|
+
#include <Utils/BufferedIO.h>
|
42
|
+
#include <Utils/MessageIO.h>
|
43
|
+
|
44
|
+
namespace Passenger {
|
45
|
+
namespace LoggingAgent {
|
46
|
+
|
47
|
+
using namespace std;
|
48
|
+
|
49
|
+
|
50
|
+
class Request: public ServerKit::BaseHttpRequest {
|
51
|
+
public:
|
52
|
+
string body;
|
53
|
+
Json::Value jsonBody;
|
54
|
+
|
55
|
+
DEFINE_SERVER_KIT_BASE_HTTP_REQUEST_FOOTER(Request);
|
56
|
+
};
|
57
|
+
|
58
|
+
class ApiServer: public ServerKit::HttpServer<ApiServer, ServerKit::HttpClient<Request> > {
|
59
|
+
private:
|
60
|
+
typedef ServerKit::HttpServer<ApiServer, ServerKit::HttpClient<Request> > ParentClass;
|
61
|
+
typedef ServerKit::HttpClient<Request> Client;
|
62
|
+
typedef ServerKit::HeaderTable HeaderTable;
|
63
|
+
|
64
|
+
void route(Client *client, Request *req, const StaticString &path) {
|
65
|
+
if (path == P_STATIC_STRING("/ping.json")) {
|
66
|
+
apiServerProcessPing(this, client, req);
|
67
|
+
} else if (path == P_STATIC_STRING("/version.json")) {
|
68
|
+
apiServerProcessVersion(this, client, req);
|
69
|
+
} else if (path == P_STATIC_STRING("/shutdown.json")) {
|
70
|
+
apiServerProcessShutdown(this, client, req);
|
71
|
+
} else if (path == P_STATIC_STRING("/backtraces.txt")) {
|
72
|
+
apiServerProcessBacktraces(this, client, req);
|
73
|
+
} else if (path == P_STATIC_STRING("/config.json")) {
|
74
|
+
processConfig(client, req);
|
75
|
+
} else if (path == P_STATIC_STRING("/reinherit_logs.json")) {
|
76
|
+
apiServerProcessReinheritLogs(this, client, req,
|
77
|
+
instanceDir, fdPassingPassword);
|
78
|
+
} else if (path == P_STATIC_STRING("/reopen_logs.json")) {
|
79
|
+
apiServerProcessReopenLogs(this, client, req);
|
80
|
+
} else if (path == P_STATIC_STRING("/status.txt")) {
|
81
|
+
processStatusTxt(client, req);
|
82
|
+
} else {
|
83
|
+
apiServerRespondWith404(this, client, req);
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
void processConfig(Client *client, Request *req) {
|
88
|
+
if (req->method == HTTP_GET) {
|
89
|
+
if (!authorizeStateInspectionOperation(this, client, req)) {
|
90
|
+
apiServerRespondWith401(this, client, req);
|
91
|
+
}
|
92
|
+
|
93
|
+
HeaderTable headers;
|
94
|
+
Json::Value doc;
|
95
|
+
string logFile = getLogFile();
|
96
|
+
string fileDescriptorLogFile = getFileDescriptorLogFile();
|
97
|
+
|
98
|
+
headers.insert(req->pool, "Content-Type", "application/json");
|
99
|
+
doc["log_level"] = getLogLevel();
|
100
|
+
if (!logFile.empty()) {
|
101
|
+
doc["log_file"] = logFile;
|
102
|
+
}
|
103
|
+
if (!fileDescriptorLogFile.empty()) {
|
104
|
+
doc["file_descriptor_log_file"] = fileDescriptorLogFile;
|
105
|
+
}
|
106
|
+
|
107
|
+
writeSimpleResponse(client, 200, &headers, doc.toStyledString());
|
108
|
+
if (!req->ended()) {
|
109
|
+
endRequest(&client, &req);
|
110
|
+
}
|
111
|
+
} else if (req->method == HTTP_PUT) {
|
112
|
+
if (!authorizeAdminOperation(this, client, req)) {
|
113
|
+
apiServerRespondWith401(this, client, req);
|
114
|
+
} else if (!req->hasBody()) {
|
115
|
+
endAsBadRequest(&client, &req, "Body required");
|
116
|
+
}
|
117
|
+
// Continue in processConfigBody()
|
118
|
+
} else {
|
119
|
+
apiServerRespondWith405(this, client, req);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
void processConfigBody(Client *client, Request *req) {
|
124
|
+
HeaderTable headers;
|
125
|
+
Json::Value &json = req->jsonBody;
|
126
|
+
|
127
|
+
headers.insert(req->pool, "Content-Type", "application/json");
|
128
|
+
|
129
|
+
if (json.isMember("log_level")) {
|
130
|
+
setLogLevel(json["log_level"].asInt());
|
131
|
+
}
|
132
|
+
if (json.isMember("log_file")) {
|
133
|
+
string logFile = json["log_file"].asString();
|
134
|
+
try {
|
135
|
+
logFile = absolutizePath(logFile);
|
136
|
+
} catch (const SystemException &e) {
|
137
|
+
unsigned int bufsize = 1024;
|
138
|
+
char *message = (char *) psg_pnalloc(req->pool, bufsize);
|
139
|
+
snprintf(message, bufsize, "{ \"status\": \"error\", "
|
140
|
+
"\"message\": \"Cannot absolutize log file filename: %s\" }",
|
141
|
+
e.what());
|
142
|
+
writeSimpleResponse(client, 500, &headers, message);
|
143
|
+
if (!req->ended()) {
|
144
|
+
endRequest(&client, &req);
|
145
|
+
}
|
146
|
+
return;
|
147
|
+
}
|
148
|
+
|
149
|
+
int e;
|
150
|
+
if (!setLogFile(logFile, &e)) {
|
151
|
+
unsigned int bufsize = 1024;
|
152
|
+
char *message = (char *) psg_pnalloc(req->pool, bufsize);
|
153
|
+
snprintf(message, bufsize, "{ \"status\": \"error\", "
|
154
|
+
"\"message\": \"Cannot open log file: %s (errno=%d)\" }",
|
155
|
+
strerror(e), e);
|
156
|
+
writeSimpleResponse(client, 500, &headers, message);
|
157
|
+
if (!req->ended()) {
|
158
|
+
endRequest(&client, &req);
|
159
|
+
}
|
160
|
+
return;
|
161
|
+
}
|
162
|
+
P_NOTICE("Log file opened.");
|
163
|
+
}
|
164
|
+
|
165
|
+
writeSimpleResponse(client, 200, &headers, "{ \"status\": \"ok\" }\n");
|
166
|
+
if (!req->ended()) {
|
167
|
+
endRequest(&client, &req);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
void processStatusTxt(Client *client, Request *req) {
|
172
|
+
if (req->method != HTTP_GET) {
|
173
|
+
apiServerRespondWith405(this, client, req);
|
174
|
+
} else if (authorizeStateInspectionOperation(this, client, req)) {
|
175
|
+
HeaderTable headers;
|
176
|
+
headers.insert(req->pool, "Content-Type", "text/plain");
|
177
|
+
|
178
|
+
stringstream stream;
|
179
|
+
loggingServer->dump(stream);
|
180
|
+
writeSimpleResponse(client, 200, &headers, stream.str());
|
181
|
+
if (!req->ended()) {
|
182
|
+
endRequest(&client, &req);
|
183
|
+
}
|
184
|
+
} else {
|
185
|
+
apiServerRespondWith401(this, client, req);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
protected:
|
190
|
+
virtual void onRequestBegin(Client *client, Request *req) {
|
191
|
+
const StaticString path(req->path.start->data, req->path.size);
|
192
|
+
|
193
|
+
P_INFO("API request: " << http_method_str(req->method) <<
|
194
|
+
" " << StaticString(req->path.start->data, req->path.size));
|
195
|
+
|
196
|
+
try {
|
197
|
+
route(client, req, path);
|
198
|
+
} catch (const oxt::tracable_exception &e) {
|
199
|
+
SKC_ERROR(client, "Exception: " << e.what() << "\n" << e.backtrace());
|
200
|
+
if (!req->ended()) {
|
201
|
+
req->wantKeepAlive = false;
|
202
|
+
endRequest(&client, &req);
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
virtual ServerKit::Channel::Result onRequestBody(Client *client, Request *req,
|
208
|
+
const MemoryKit::mbuf &buffer, int errcode)
|
209
|
+
{
|
210
|
+
if (buffer.size() > 0) {
|
211
|
+
// Data
|
212
|
+
req->body.append(buffer.start, buffer.size());
|
213
|
+
} else if (errcode == 0) {
|
214
|
+
// EOF
|
215
|
+
Json::Reader reader;
|
216
|
+
if (reader.parse(req->body, req->jsonBody)) {
|
217
|
+
try {
|
218
|
+
processConfigBody(client, req);
|
219
|
+
} catch (const oxt::tracable_exception &e) {
|
220
|
+
SKC_ERROR(client, "Exception: " << e.what() << "\n" << e.backtrace());
|
221
|
+
if (!req->ended()) {
|
222
|
+
req->wantKeepAlive = false;
|
223
|
+
endRequest(&client, &req);
|
224
|
+
}
|
225
|
+
}
|
226
|
+
} else {
|
227
|
+
apiServerRespondWith422(this, client, req, reader.getFormattedErrorMessages());
|
228
|
+
}
|
229
|
+
} else {
|
230
|
+
// Error
|
231
|
+
disconnect(&client);
|
232
|
+
}
|
233
|
+
return ServerKit::Channel::Result(buffer.size(), false);
|
234
|
+
}
|
235
|
+
|
236
|
+
virtual void deinitializeRequest(Client *client, Request *req) {
|
237
|
+
req->body.clear();
|
238
|
+
if (!req->jsonBody.isNull()) {
|
239
|
+
req->jsonBody = Json::Value();
|
240
|
+
}
|
241
|
+
ParentClass::deinitializeRequest(client, req);
|
242
|
+
}
|
243
|
+
|
244
|
+
public:
|
245
|
+
LoggingServer *loggingServer;
|
246
|
+
ApiAccountDatabase *apiAccountDatabase;
|
247
|
+
string instanceDir;
|
248
|
+
string fdPassingPassword;
|
249
|
+
EventFd *exitEvent;
|
250
|
+
|
251
|
+
ApiServer(ServerKit::Context *context)
|
252
|
+
: ParentClass(context),
|
253
|
+
loggingServer(NULL),
|
254
|
+
apiAccountDatabase(NULL),
|
255
|
+
exitEvent(NULL)
|
256
|
+
{ }
|
257
|
+
|
258
|
+
virtual StaticString getServerName() const {
|
259
|
+
return P_STATIC_STRING("LoggerApiServer");
|
260
|
+
}
|
261
|
+
|
262
|
+
virtual unsigned int getClientName(const Client *client, char *buf, size_t size) const {
|
263
|
+
return ParentClass::getClientName(client, buf, size);
|
264
|
+
}
|
265
|
+
|
266
|
+
bool authorizeByUid(uid_t uid) const {
|
267
|
+
return uid == 0 || uid == geteuid();
|
268
|
+
}
|
269
|
+
|
270
|
+
bool authorizeByApiKey(const ApplicationPool2::ApiKey &apiKey) const {
|
271
|
+
return apiKey.isSuper();
|
272
|
+
}
|
273
|
+
};
|
274
|
+
|
275
|
+
|
276
|
+
} // namespace LoggingAgent
|
277
|
+
} // namespace Passenger
|
278
|
+
|
279
|
+
#endif /* _PASSENGER_LOGGING_AGENT_API_SERVER_H_ */
|
@@ -22,6 +22,9 @@
|
|
22
22
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
23
|
* THE SOFTWARE.
|
24
24
|
*/
|
25
|
+
// Include ev++.h early to avoid macro clash on EV_ERROR.
|
26
|
+
#include <ev++.h>
|
27
|
+
|
25
28
|
#include <oxt/system_calls.hpp>
|
26
29
|
#include <oxt/backtrace.hpp>
|
27
30
|
#include <oxt/thread.hpp>
|
@@ -35,13 +38,15 @@
|
|
35
38
|
#include <cstring>
|
36
39
|
#include <cerrno>
|
37
40
|
#include <algorithm>
|
41
|
+
#include <stdexcept>
|
38
42
|
#include <stdlib.h>
|
39
43
|
#include <signal.h>
|
40
44
|
|
41
45
|
#include <agents/Base.h>
|
46
|
+
#include <agents/ApiServerUtils.h>
|
42
47
|
#include <agents/LoggingAgent/OptionParser.h>
|
43
48
|
#include <agents/LoggingAgent/LoggingServer.h>
|
44
|
-
#include <agents/LoggingAgent/
|
49
|
+
#include <agents/LoggingAgent/ApiServer.h>
|
45
50
|
|
46
51
|
#include <AccountsDatabase.h>
|
47
52
|
#include <Account.h>
|
@@ -68,8 +73,8 @@ namespace LoggingAgent {
|
|
68
73
|
struct WorkingObjects {
|
69
74
|
string password;
|
70
75
|
FileDescriptor serverSocketFd;
|
71
|
-
vector<int>
|
72
|
-
|
76
|
+
vector<int> apiSockets;
|
77
|
+
ApiAccountDatabase apiAccountDatabase;
|
73
78
|
|
74
79
|
ResourceLocator *resourceLocator;
|
75
80
|
BackgroundEventLoop *bgloop;
|
@@ -77,7 +82,7 @@ namespace LoggingAgent {
|
|
77
82
|
AccountsDatabasePtr accountsDatabase;
|
78
83
|
LoggingServer *loggingServer;
|
79
84
|
|
80
|
-
LoggingAgent::
|
85
|
+
LoggingAgent::ApiServer *apiServer;
|
81
86
|
EventFd exitEvent;
|
82
87
|
EventFd allClientsDisconnectedEvent;
|
83
88
|
|
@@ -109,7 +114,7 @@ static WorkingObjects *workingObjects;
|
|
109
114
|
|
110
115
|
static void printInfo(EV_P_ struct ev_signal *watcher, int revents);
|
111
116
|
static void onTerminationSignal(EV_P_ struct ev_signal *watcher, int revents);
|
112
|
-
static void
|
117
|
+
static void apiServerShutdownFinished(LoggingAgent::ApiServer *server);
|
113
118
|
static void waitForExitEvent();
|
114
119
|
|
115
120
|
void
|
@@ -149,30 +154,6 @@ makeFileWorldReadableAndWritable(const string &path) {
|
|
149
154
|
} while (ret == -1 && errno == EINTR);
|
150
155
|
}
|
151
156
|
|
152
|
-
static void
|
153
|
-
parseAndAddAdminAuthorization(const string &description) {
|
154
|
-
TRACE_POINT();
|
155
|
-
WorkingObjects *wo = workingObjects;
|
156
|
-
LoggingAgent::AdminServer::Authorization auth;
|
157
|
-
vector<string> args;
|
158
|
-
|
159
|
-
split(description, ':', args);
|
160
|
-
|
161
|
-
if (args.size() == 2) {
|
162
|
-
auth.level = LoggingAgent::AdminServer::FULL;
|
163
|
-
auth.username = args[0];
|
164
|
-
auth.password = strip(readAll(args[1]));
|
165
|
-
} else if (args.size() == 3) {
|
166
|
-
auth.level = LoggingAgent::AdminServer::parseLevel(args[0]);
|
167
|
-
auth.username = args[1];
|
168
|
-
auth.password = strip(readAll(args[2]));
|
169
|
-
} else {
|
170
|
-
P_BUG("Too many elements in authorization description");
|
171
|
-
}
|
172
|
-
|
173
|
-
wo->adminAuthorizations.push_back(auth);
|
174
|
-
}
|
175
|
-
|
176
157
|
static void
|
177
158
|
initializePrivilegedWorkingObjects() {
|
178
159
|
TRACE_POINT();
|
@@ -190,7 +171,11 @@ initializePrivilegedWorkingObjects() {
|
|
190
171
|
|
191
172
|
UPDATE_TRACE_POINT();
|
192
173
|
foreach (description, authorizations) {
|
193
|
-
|
174
|
+
try {
|
175
|
+
wo->apiAccountDatabase.add(description);
|
176
|
+
} catch (const ArgumentException &e) {
|
177
|
+
throw std::runtime_error(e.what());
|
178
|
+
}
|
194
179
|
}
|
195
180
|
|
196
181
|
// Initialize ResourceLocator here in case passenger_root's parent
|
@@ -204,7 +189,7 @@ startListening() {
|
|
204
189
|
const VariantMap &options = *agentsOptions;
|
205
190
|
WorkingObjects *wo = workingObjects;
|
206
191
|
string address;
|
207
|
-
vector<string>
|
192
|
+
vector<string> apiAddresses;
|
208
193
|
|
209
194
|
address = options.get("logging_agent_address");
|
210
195
|
wo->serverSocketFd.assign(createServer(address, 0, true,
|
@@ -216,13 +201,13 @@ startListening() {
|
|
216
201
|
}
|
217
202
|
|
218
203
|
UPDATE_TRACE_POINT();
|
219
|
-
|
204
|
+
apiAddresses = options.getStrSet("logging_agent_api_addresses",
|
220
205
|
false);
|
221
|
-
foreach (address,
|
222
|
-
wo->
|
206
|
+
foreach (address, apiAddresses) {
|
207
|
+
wo->apiSockets.push_back(createServer(address, 0, true,
|
223
208
|
__FILE__, __LINE__));
|
224
|
-
P_LOG_FILE_DESCRIPTOR_PURPOSE(wo->
|
225
|
-
"Server address: " << wo->
|
209
|
+
P_LOG_FILE_DESCRIPTOR_PURPOSE(wo->apiSockets.back(),
|
210
|
+
"Server address: " << wo->apiSockets.back());
|
226
211
|
if (getSocketAddressType(address) == SAT_UNIX) {
|
227
212
|
makeFileWorldReadableAndWritable(parseUnixSocketAddress(address));
|
228
213
|
}
|
@@ -299,13 +284,15 @@ initializeUnprivilegedWorkingObjects() {
|
|
299
284
|
wo->serverSocketFd, wo->accountsDatabase, options);
|
300
285
|
|
301
286
|
UPDATE_TRACE_POINT();
|
302
|
-
wo->
|
303
|
-
wo->
|
304
|
-
wo->
|
305
|
-
wo->
|
306
|
-
wo->
|
307
|
-
|
308
|
-
|
287
|
+
wo->apiServer = new LoggingAgent::ApiServer(wo->serverKitContext);
|
288
|
+
wo->apiServer->loggingServer = wo->loggingServer;
|
289
|
+
wo->apiServer->apiAccountDatabase = &wo->apiAccountDatabase;
|
290
|
+
wo->apiServer->instanceDir = options.get("instance_dir", false);
|
291
|
+
wo->apiServer->fdPassingPassword = options.get("watchdog_fd_passing_password", false);
|
292
|
+
wo->apiServer->exitEvent = &wo->exitEvent;
|
293
|
+
wo->apiServer->shutdownFinishCallback = apiServerShutdownFinished;
|
294
|
+
foreach (fd, wo->apiSockets) {
|
295
|
+
wo->apiServer->listen(fd);
|
309
296
|
}
|
310
297
|
|
311
298
|
UPDATE_TRACE_POINT();
|
@@ -362,12 +349,12 @@ mainLoop() {
|
|
362
349
|
}
|
363
350
|
|
364
351
|
static void
|
365
|
-
|
366
|
-
workingObjects->
|
352
|
+
shutdownApiServer() {
|
353
|
+
workingObjects->apiServer->shutdown();
|
367
354
|
}
|
368
355
|
|
369
356
|
static void
|
370
|
-
|
357
|
+
apiServerShutdownFinished(LoggingAgent::ApiServer *server) {
|
371
358
|
workingObjects->allClientsDisconnectedEvent.notify();
|
372
359
|
}
|
373
360
|
|
@@ -410,7 +397,7 @@ waitForExitEvent() {
|
|
410
397
|
/* We received an exit command. */
|
411
398
|
P_NOTICE("Received command to shutdown gracefully. "
|
412
399
|
"Waiting until all clients have disconnected...");
|
413
|
-
wo->bgloop->safe->runLater(
|
400
|
+
wo->bgloop->safe->runLater(shutdownApiServer);
|
414
401
|
|
415
402
|
UPDATE_TRACE_POINT();
|
416
403
|
FD_ZERO(&fds);
|
@@ -433,7 +420,7 @@ cleanup() {
|
|
433
420
|
|
434
421
|
P_DEBUG("Shutting down " AGENT_EXE " logger...");
|
435
422
|
wo->bgloop->stop();
|
436
|
-
delete wo->
|
423
|
+
delete wo->apiServer;
|
437
424
|
P_NOTICE(AGENT_EXE " logger shutdown finished");
|
438
425
|
}
|
439
426
|
|
@@ -458,6 +445,9 @@ runLoggingAgent() {
|
|
458
445
|
} catch (const tracable_exception &e) {
|
459
446
|
P_ERROR("ERROR: " << e.what() << "\n" << e.backtrace());
|
460
447
|
return 1;
|
448
|
+
} catch (const std::runtime_error &e) {
|
449
|
+
P_CRITICAL("ERROR: " << e.what());
|
450
|
+
return 1;
|
461
451
|
}
|
462
452
|
|
463
453
|
return 0;
|
@@ -500,11 +490,11 @@ preinitialize(VariantMap &options) {
|
|
500
490
|
static void
|
501
491
|
setAgentsOptionsDefaults() {
|
502
492
|
VariantMap &options = *agentsOptions;
|
503
|
-
set<string>
|
504
|
-
|
493
|
+
set<string> defaultApiListenAddress;
|
494
|
+
defaultApiListenAddress.insert(DEFAULT_LOGGING_AGENT_API_LISTEN_ADDRESS);
|
505
495
|
|
506
496
|
options.setDefault("logging_agent_address", DEFAULT_LOGGING_AGENT_LISTEN_ADDRESS);
|
507
|
-
options.setDefaultStrSet("
|
497
|
+
options.setDefaultStrSet("logging_agent_api_addresses", defaultApiListenAddress);
|
508
498
|
}
|
509
499
|
|
510
500
|
static void
|