'Full Administrator', 'guard_name' => 'admin']); $this->admin = User::factory()->create(); $this->admin->assignRole('Full Administrator'); } private function service(string $productType = 'ssl'): Service { $product = Product::factory()->create(['product_type' => $productType, 'name' => 'SSL - Positive']); return Service::create(['customer_id' => Customer::factory()->create()->id, 'product_id' => $product->id, 'status' => 'active']); } private function zip(array $entries): UploadedFile { $path = tempnam(sys_get_temp_dir(), 'ssl') . '.zip'; $zip = new ZipArchive(); $zip->open($path, ZipArchive::CREATE); foreach ($entries as $name => $content) { $zip->addFromString($name, $content); } $zip->close(); return new UploadedFile($path, 'cert.zip', 'application/zip', null, true); } public function test_archive_is_extracted_to_text_files_and_visible_to_client(): void { $service = $this->service(); $base = "/api/v1/administrator/services/{$service->id}/ssl-info"; $this->actingAs($this->admin, 'admin') ->post("{$base}/archive", ['archive' => $this->zip([ 'bundle/example.com.crt' => "-----BEGIN CERTIFICATE-----\nabc\n-----END CERTIFICATE-----", '../../evil.key' => 'key-data', '__MACOSX/._example.com.crt' => 'junk', 'logo.png' => "\0\1binary", 'dir/' => '', ])], ['Accept' => 'application/json']) ->assertOk() ->assertJsonCount(2, 'data.files') ->assertJsonPath('data.files.0.name', 'example.com.crt') ->assertJsonPath('data.files.1.name', 'evil.key'); $this->actingAs($this->admin, 'admin') ->putJson($base, [ 'fields' => [['label' => 'CNAME host', 'value' => '_abc.example.com']], 'files' => [['name' => 'a.pem', 'content' => 'pem']], ]) ->assertOk(); $this->actingAs($this->admin, 'admin')->getJson($base) ->assertJsonPath('data.fields.0.value', '_abc.example.com') ->assertJsonCount(1, 'data.files'); $this->assertStringNotContainsString('pem', (string) \DB::table('service_ssl_certificates')->value('data')); $payload = (new ServiceClientDetailResource($service->fresh()))->toArray(new Request()); $this->assertSame('a.pem', $payload['ssl_certificate']['files'][0]['name']); } public function test_non_ssl_service_is_rejected(): void { $service = $this->service('domain'); $this->actingAs($this->admin, 'admin') ->getJson("/api/v1/administrator/services/{$service->id}/ssl-info") ->assertStatus(422); } public function test_customer_downloads_own_certificate_zip_only(): void { $service = $this->service(); $service->sslCertificate()->create(['data' => [ 'fields' => [['label' => 'CNAME', 'value' => 'abc']], 'files' => [['name' => 'a.pem', 'content' => 'pem-data']], ]]); $owner = Customer::find($service->customer_id); $path = "/v1/client/client-service/{$service->uuid}/ssl-archive"; $response = $this->actingAs($owner, 'client')->withHeaders(['x-access-token' => $this->buildClientAccessToken()])->get($path); $response->assertOk(); $zip = new ZipArchive(); $zip->open($response->baseResponse->getFile()->getPathname()); $this->assertSame('pem-data', $zip->getFromName('a.pem')); $this->assertStringContainsString('CNAME: abc', $zip->getFromName('thong-tin.txt')); $this->actingAs(Customer::factory()->create(), 'client')->withHeaders(['x-access-token' => $this->buildClientAccessToken()])->get($path)->assertNotFound(); } }