From 6a885a19ef798e68a7fe053be9e1029313e8a1b1 Mon Sep 17 00:00:00 2001 From: Krystian Duma Date: Thu, 22 Dec 2022 00:43:51 +0100 Subject: [PATCH] ACL Proof of concept --- app/Models/ClientApplication.php | 16 +++++- app/Models/Printer.php | 22 ++++++++- app/Models/Traits/ArnDefaultsTrait.php | 41 ++++++++++++++++ composer.json | 1 + composer.lock | 67 +++++++++++++++++++++++++- tests/Feature/AclPlaygroundTest.php | 67 ++++++++++++++++++++++++++ 6 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 app/Models/Traits/ArnDefaultsTrait.php create mode 100755 tests/Feature/AclPlaygroundTest.php diff --git a/app/Models/ClientApplication.php b/app/Models/ClientApplication.php index 9600190..66e8f4c 100644 --- a/app/Models/ClientApplication.php +++ b/app/Models/ClientApplication.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Models\Traits\ArnDefaultsTrait; use Illuminate\Auth\Authenticatable; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; @@ -12,17 +13,20 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Foundation\Auth\Access\Authorizable; use Laravel\Sanctum\HasApiTokens; +use RenokiCo\Acl\Concerns\HasPolicies; +use RenokiCo\Acl\Contracts\RuledByPolicies; /** * @mixin IdeHelperClientApplication */ -class ClientApplication extends Model implements AuthorizableContract, AuthenticatableContract +class ClientApplication extends Model implements AuthorizableContract, AuthenticatableContract, RuledByPolicies { use HasFactory; use HasApiTokens; use Authorizable; use HasUlidField; use Authenticatable; + use HasPolicies; public function getRememberTokenName() { @@ -52,4 +56,14 @@ public function Jobs(): HasMany { return $this->hasMany(PrintJob::class, 'client_application_id'); } + + public function resolveArnAccountId() + { + return $this->Team->ulid; + } + + public function resolveArnRegion() + { + return 'local'; + } } diff --git a/app/Models/Printer.php b/app/Models/Printer.php index 8334bbb..fef8750 100644 --- a/app/Models/Printer.php +++ b/app/Models/Printer.php @@ -2,18 +2,28 @@ namespace App\Models; +use App\Models\Traits\ArnDefaultsTrait; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use RenokiCo\Acl\Concerns\HasArn; +use RenokiCo\Acl\Concerns\HasStaticArn; +use RenokiCo\Acl\Contracts\Arnable; /** * @mixin IdeHelperPrinter */ -class Printer extends Model +class Printer extends Model implements Arnable { + use HasArn, ArnDefaultsTrait { + ArnDefaultsTrait::arnPartition insteadof HasArn; + ArnDefaultsTrait::arnService insteadof HasArn; + ArnDefaultsTrait::arnRegion insteadof HasArn; + } + use HasFactory; use HasUlidField; @@ -61,4 +71,14 @@ public function scopeForType(Builder $query, string $type) ->orWhereJsonContains('raw_languages_supported', '*'); }); } + + public function arnResourceAccountId() + { + return $this->Server->Team->ulid; + } + + public function arnResourceId() + { + return $this->ulid; + } } diff --git a/app/Models/Traits/ArnDefaultsTrait.php b/app/Models/Traits/ArnDefaultsTrait.php new file mode 100644 index 0000000..15b59bb --- /dev/null +++ b/app/Models/Traits/ArnDefaultsTrait.php @@ -0,0 +1,41 @@ +create(); + + $server = PrintServer::factory() + ->recycle($client->Team) + ->create(); + + $printers = Printer::factory() + ->active() + ->for($server, 'Server') + ->count(3) + ->create(); + + $policy = Acl::createPolicy([ + Statement::make( + effect: 'Allow', + action: 'printer:Print', + resource: [ + 'arn:webprint:server:testing:'.$client->Team->ulid.':printer/*', + ], + ), + Statement::make( + effect: 'Deny', + action: 'printer:Print', + resource: [ + 'arn:webprint:server:testing:'.$client->Team->ulid.':printer/'.$printers[1]->ulid, + ], + ), + ]); + +// dd( +// Printer::resourceIdAgnosticArn($client), +// json_encode($policy->toArray(), JSON_PRETTY_PRINT), +// ); + + $client->loadPolicies($policy); + + $this->assertTrue($client->isAllowedTo('printer:Print', $printers[0])); + $this->assertFalse($client->isAllowedTo('printer:Print', $printers[1])); + $this->assertTrue($client->isAllowedTo('printer:Print', $printers[2])); + } +}