Skip to content
This repository was archived by the owner on Nov 9, 2020. It is now read-only.

Commit 4185aaa

Browse files
committed
Merge branch 'master' into v5.7.7
2 parents 2cff8ad + 7e44ddb commit 4185aaa

File tree

11 files changed

+183
-61
lines changed

11 files changed

+183
-61
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
/vendor/
2-
composer.lock

README.md

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,51 +18,19 @@ The service provider is auto-discovered by Laravel.
1818

1919
Add `$app->register(Biigle\RemoteQueue\RemoteQueueServiceProvider::class);` to `bootstrap/app.php`.
2020

21-
## Configuration
22-
23-
You can override any of these configuration options of the `remote-queue` config either directly or via environment variables:
24-
25-
### remote-queue.listen
26-
27-
Default: `false`
28-
Environment: `REMOTE_QUEUE_LISTEN`
29-
30-
Accept and process jobs sent to this application instance.
31-
32-
### remote-queue.endpoint
33-
34-
Default: `api/v1/remote-queue`
35-
Environment: `REMOTE_QUEUE_ENDPOINT`
36-
37-
API endpoint to receive new jobs.
38-
39-
### remote-queue.connection
40-
41-
Default: `null`
42-
Environment: `REMOTE_QUEUE_CONNECTION`
43-
44-
Use this queue connection to process received jobs. If `null`, the default connection is used.
45-
46-
### remote-queue.accept-tokens
47-
48-
Default: `[]`
49-
Environment: `REMOTE_QUEUE_ACCEPT_TOKENS`
50-
51-
Accept jobs only if they provide one of these tokens. Specify tokens as comma separated list if you use the environment variable. One way to generate tokens is this command: `head -c 32 /dev/urandom | base64`.
52-
5321
## Usage
5422

5523
This package can be used to submit queued jobs to another Laravel or Lumen application, receive jobs from another application or both.
5624

5725
### Receive jobs
5826

59-
By default, this package does not allow receiving of jobs from another application. To allow this, set the `remote-queue.listen` config to `true`. Tokens are used to authenticate incoming requests. A token is just some long random string in this case. Configure `remote-queue.accept-tokens` with all tokens that are accepted. All received jobs which are successfully authenticated are pushed to a "regular" queue of this application and processed by the queue worker.
27+
By default, this package does not allow receiving of jobs from another application. To allow this, set the `remote-queue.listen` configuration to `true`. Tokens are used to authenticate incoming requests. A token is just some long random string in this case. Configure `remote-queue.accept-tokens` with all tokens that are accepted. All received jobs which are successfully authenticated are pushed to a "regular" queue of this application and processed by the queue worker.
6028

6129
**Important:** Make sure that the job class exists in both the submitting and receiving application.
6230

6331
### Submit jobs
6432

65-
Jobs pushed to the remote queue are transmitted via HTTP and processed on another application. To use the remote queue, configure a queue connection in the `queue.connections` config to use the `remote`. Example:
33+
Jobs pushed to the remote queue are transmitted via HTTP and processed on another application. To use the remote queue, configure a queue connection in the `queue.connections` config to use the `remote` driver. Example:
6634

6735
```php
6836
[
@@ -91,3 +59,47 @@ MyJob::dispatch($data)->onConnection('remote');
9159
We developed this package to be able to process jobs on a remote machine with GPU. To return the computed results, we applied what we call the "submit/response" pattern.
9260

9361
In this pattern, this package is installed on both Laravel/Lumen instances (let's call them A and B). In instance A, the remote queue is configured to push jobs to instance B (the one with the GPU). In instance B, the remote queue is configured to push jobs to instance A. New GPU jobs are submitted from instance A to the remote queue on instance B. Once the results are computed, they are returned as a "response job" to the remote queue on instance A where the results can be further processed.
62+
63+
## Configuration
64+
65+
You can override any of these configuration options of the `remote-queue` config either directly or via environment variables:
66+
67+
### remote-queue.listen
68+
69+
Default: `false`
70+
Environment: `REMOTE_QUEUE_LISTEN`
71+
72+
Accept and process jobs sent to this application instance.
73+
74+
### remote-queue.endpoint
75+
76+
Default: `api/v1/remote-queue`
77+
Environment: `REMOTE_QUEUE_ENDPOINT`
78+
79+
API endpoint to receive new jobs.
80+
81+
### remote-queue.connection
82+
83+
Default: `null`
84+
Environment: `REMOTE_QUEUE_CONNECTION`
85+
86+
Use this queue connection to process received jobs. If `null`, the default connection is used.
87+
88+
### remote-queue.accept_tokens
89+
90+
Default: `[]`
91+
Environment: `REMOTE_QUEUE_ACCEPT_TOKENS`
92+
93+
Accept jobs only if they provide one of these tokens. Specify tokens as comma separated list if you use the environment variable. One way to generate tokens is this command: `head -c 32 /dev/urandom | base64`.
94+
95+
### remote-queue.accept_ips
96+
97+
Default: `[]`
98+
99+
Accept requests only from the IP addresses of this whitelist. Leave empty to accept jobs from all IPs.
100+
101+
### remote-queue.accept_jobs
102+
103+
Default: `[]`
104+
105+
Accept only jobs of this whitelist of class names. Leave empty to accept all job classes.

composer.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Http/Controllers/QueueController.php

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,39 @@ public function store(Request $request, $queue)
3434

3535
$job = @unserialize($request->input('job'));
3636

37-
if (is_object($job)) {
38-
if ($job instanceof __PHP_Incomplete_Class) {
39-
return response()->json(['errors' => ['job' => ['Unknown job class']]], 422);
40-
}
41-
} else {
42-
$job = $request->input('job');
43-
44-
if (!class_exists($job)) {
45-
return response()->json(['errors' => ['job' => ['Unknown job class']]], 422);
46-
}
37+
if ($this->isIncompleteClass($job)) {
38+
return response()->json(['errors' => ['job' => ['Unknown job class']]], 422);
39+
} elseif (!$this->isWhitelistedJob($job)) {
40+
return response()->json(['errors' => ['job' => ['Job class not whitelisted']]], 422);
4741
}
4842

4943
app('queue')->connection(config('remote-queue.connection'))
5044
->push($job, $request->input('data', ''), $queue);
5145
}
46+
47+
/**
48+
* Determine if the received job class exists.
49+
*
50+
* @param object $job Job class name
51+
*
52+
* @return boolean
53+
*/
54+
protected function isIncompleteClass($job)
55+
{
56+
return !is_object($job) || $job instanceof __PHP_Incomplete_Class;
57+
}
58+
59+
/**
60+
* Determine if the received job is whitelisted.
61+
*
62+
* @param object $job Job class name
63+
*
64+
* @return boolean
65+
*/
66+
protected function isWhitelistedJob($job)
67+
{
68+
$whitelist = config('remote-queue.accept_jobs');
69+
70+
return empty($whitelist) || in_array(get_class($job), $whitelist);
71+
}
5272
}

src/Http/Middleware/Authenticate.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Authenticate
1717
public function handle($request, Closure $next, $guard = null)
1818
{
1919
$token = $request->bearerToken();
20-
if ($token && in_array($token, config('remote-queue.accept-tokens'))) {
20+
if ($token && in_array($token, config('remote-queue.accept_tokens'))) {
2121
return $next($request);
2222
}
2323

src/Http/Middleware/WhitelistIps.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Biigle\RemoteQueue\Http\Middleware;
4+
5+
use Closure;
6+
7+
class WhitelistIps
8+
{
9+
/**
10+
* Handle an incoming request.
11+
*
12+
* @param \Illuminate\Http\Request $request
13+
* @param \Closure $next
14+
* @param string|null $guard
15+
* @return mixed
16+
*/
17+
public function handle($request, Closure $next, $guard = null)
18+
{
19+
$whitelist = config('remote-queue.accept_ips');
20+
21+
$token = $request->bearerToken();
22+
if (empty($whitelist) || in_array($request->ip(), $whitelist)) {
23+
return $next($request);
24+
}
25+
26+
return response('Unauthorized.', 401);
27+
}
28+
}

src/RemoteQueueServiceProvider.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Support\ServiceProvider;
66
use Biigle\RemoteQueue\Http\Middleware\Authenticate;
7+
use Biigle\RemoteQueue\Http\Middleware\WhitelistIps;
78

89
class RemoteQueueServiceProvider extends ServiceProvider
910
{
@@ -22,7 +23,7 @@ public function boot()
2223
$this->app['router']->group([
2324
'prefix' => config('remote-queue.endpoint'),
2425
'namespace' => 'Biigle\RemoteQueue\Http\Controllers',
25-
'middleware' => Authenticate::class,
26+
'middleware' => [Authenticate::class, WhitelistIps::class],
2627
], function ($router) {
2728
$router->post('{queue}', 'QueueController@store');
2829
$router->get('{queue}/size', 'QueueController@show');

src/config/remote-queue.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@
2525
| Accept jobs only if they provide one of these tokens.
2626
*/
2727

28-
'accept-tokens' => array_filter(explode(',', env('REMOTE_QUEUE_ACCEPT_TOKENS'))),
28+
'accept_tokens' => array_filter(explode(',', env('REMOTE_QUEUE_ACCEPT_TOKENS'))),
29+
30+
/*
31+
| Accept jobs only from the IP addresses of this whitelist. Leave empty to accept
32+
| jobs from all IPs.
33+
*/
34+
'accept_ips' => [],
35+
36+
/*
37+
| Accept only jobs of this whitelist of class names. Leave empty to accept all job
38+
| classes.
39+
*/
40+
'accept_jobs' => [],
2941

3042
];

tests/Http/Controllers/QueueControllerTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,34 @@ public function testStore()
4141
->postJson('api/v1/remote-queue/myqueue', $payload)
4242
->assertStatus(200);
4343
}
44+
45+
public function testStoreJobWhitelist()
46+
{
47+
config(['remote-queue.accept_jobs' => [TestJob::class]]);
48+
$payload = ['job' => serialize(new TestJob2), 'data' => 'mydata'];
49+
50+
$mock = Mockery::mock();
51+
$mock->shouldReceive('push')->once()
52+
->with(Mockery::type(TestJob::class), 'mydata', 'myqueue');
53+
Queue::shouldReceive('connection')->once()->andReturn($mock);
54+
55+
$this->withoutMiddleware()
56+
->postJson('api/v1/remote-queue/myqueue', $payload)
57+
// Job class is not whitelisted.
58+
->assertStatus(422);
59+
60+
$payload = ['job' => serialize(new TestJob), 'data' => 'mydata'];
61+
62+
$this->withoutMiddleware()
63+
->postJson('api/v1/remote-queue/myqueue', $payload)
64+
->assertStatus(200);
65+
}
4466
}
4567

4668
class TestJob
4769
{
4870
}
71+
72+
class TestJob2
73+
{
74+
}

tests/Http/Middleware/AuthenticateTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class AuthenticateTest extends TestCase
88
{
99
public function testHandle()
1010
{
11-
config(['remote-queue.accept-tokens' => ['mytoken']]);
11+
config(['remote-queue.accept_tokens' => ['mytoken']]);
1212

1313
$this->get('api/v1/remote-queue/default/size')->assertStatus(401);
1414

0 commit comments

Comments
 (0)