Skip to content

Commit af68dbe

Browse files
committed
Add support for base API logging of all requests
ref pterodactyl#31
1 parent 0fe0f75 commit af68dbe

File tree

4 files changed

+172
-0
lines changed

4 files changed

+172
-0
lines changed

app/Http/Middleware/APISecretToken.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
use Pterodactyl\Models\APIKey;
3131
use Pterodactyl\Models\APIPermission;
32+
use Pterodactyl\Services\APILogService;
3233

3334
use Illuminate\Http\Request;
3435
use Dingo\Api\Routing\Route;
@@ -61,13 +62,15 @@ public function getAuthorizationMethod()
6162
public function authenticate(Request $request, Route $route)
6263
{
6364
if (!$request->bearerToken() || empty($request->bearerToken())) {
65+
APILogService::log($request);
6466
throw new UnauthorizedHttpException('The authentication header was missing or malformed');
6567
}
6668

6769
list($public, $hashed) = explode('.', $request->bearerToken());
6870

6971
$key = APIKey::where('public', $public)->first();
7072
if (!$key) {
73+
APILogService::log($request);
7174
throw new AccessDeniedHttpException('Invalid API Key.');
7275
}
7376

@@ -82,6 +85,7 @@ public function authenticate(Request $request, Route $route)
8285
}
8386
}
8487
if (!$inRange) {
88+
APILogService::log($request);
8589
throw new AccessDeniedHttpException('This IP address <' . $request->ip() . '> does not have permission to use this API key.');
8690
}
8791
}
@@ -94,21 +98,26 @@ public function authenticate(Request $request, Route $route)
9498
}
9599

96100
if (!$this->permissionAllowed) {
101+
APILogService::log($request);
97102
throw new AccessDeniedHttpException('You do not have permission to access this resource.');
98103
}
99104
}
100105

101106
try {
102107
$decrypted = Crypt::decrypt($key->secret);
103108
} catch (\Illuminate\Contracts\Encryption\DecryptException $ex) {
109+
APILogService::log($request);
104110
throw new HttpException('There was an error while attempting to check your secret key.');
105111
}
106112

107113
$this->url = urldecode($request->fullUrl());
108114
if($this->_generateHMAC($request->getContent(), $decrypted) !== base64_decode($hashed)) {
115+
APILogService::log($request);
109116
throw new BadRequestHttpException('The hashed body was not valid. Potential modification of contents in route.');
110117
}
111118

119+
// Log the Route Access
120+
APILogService::log($request, true);
112121
return true;
113122

114123
}

app/Models/APILog.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Models;
25+
26+
use Illuminate\Database\Eloquent\Model;
27+
28+
class APILog extends Model
29+
{
30+
31+
/**
32+
* The table associated with the model.
33+
*
34+
* @var string
35+
*/
36+
protected $table = 'api_logs';
37+
38+
/**
39+
* The attributes excluded from the model's JSON form.
40+
*
41+
* @var array
42+
*/
43+
protected $hidden = [];
44+
45+
/**
46+
* Fields that are not mass assignable.
47+
*
48+
* @var array
49+
*/
50+
protected $guarded = ['id', 'created_at', 'updated_at'];
51+
52+
/**
53+
* Cast values to correct type.
54+
*
55+
* @var array
56+
*/
57+
protected $casts = [
58+
'authorized' => 'boolean'
59+
];
60+
61+
}

app/Services/APILogService.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Services;
25+
26+
use Log;
27+
28+
use Illuminate\Http\Request;
29+
use Pterodactyl\Models\APILog;
30+
31+
class APILogService
32+
{
33+
34+
public function __constructor()
35+
{
36+
//
37+
}
38+
39+
public static function log(Request $request, $authorized = false)
40+
{
41+
if ($request->bearerToken() && !empty($request->bearerToken())) {
42+
list($public, $hashed) = explode('.', $request->bearerToken());
43+
} else {
44+
$public = null;
45+
}
46+
47+
try {
48+
$log = APILog::create([
49+
'authorized' => $authorized,
50+
'key' => $public,
51+
'method' => $request->method(),
52+
'route' => $request->fullUrl(),
53+
'content' => (empty($request->getContent())) ? null : $request->getContent(),
54+
'user_agent' => $request->header('User-Agent'),
55+
'request_ip' => $request->ip()
56+
]);
57+
$log->save();
58+
} catch (\Exception $ex) {
59+
// Simply log it and move on.
60+
Log::error($ex);
61+
}
62+
}
63+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Schema;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Database\Migrations\Migration;
6+
7+
class BuildApiLogTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('api_logs', function (Blueprint $table) {
17+
$table->increments('id');
18+
$table->boolean('authorized');
19+
$table->char('key', 16)->nullable();
20+
$table->char('method', 6);
21+
$table->text('route');
22+
$table->text('content')->nullable();
23+
$table->text('user_agent');
24+
$table->ipAddress('request_ip');
25+
$table->timestampsTz();
26+
27+
});
28+
}
29+
30+
/**
31+
* Reverse the migrations.
32+
*
33+
* @return void
34+
*/
35+
public function down()
36+
{
37+
Schema::drop('api_logs');
38+
}
39+
}

0 commit comments

Comments
 (0)