From 5b00b66f24e90d5349ec7270e335d6752b6418f8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 20 Sep 2024 12:27:55 +0200 Subject: [PATCH] refactor: Update PrivateKey model to improve code readability and maintainability --- app/Models/PrivateKey.php | 40 ++++++++++++------- .../PopulateSshKeysDirectorySeeder.php | 11 ++++- database/seeders/ProductionSeeder.php | 1 + 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/app/Models/PrivateKey.php b/app/Models/PrivateKey.php index 6985ca536..58e12d6cb 100644 --- a/app/Models/PrivateKey.php +++ b/app/Models/PrivateKey.php @@ -2,11 +2,11 @@ namespace App\Models; -use OpenApi\Attributes as OA; +use DanHarrin\LivewireRateLimiting\WithRateLimiting; use Illuminate\Support\Facades\Storage; use Illuminate\Validation\ValidationException; +use OpenApi\Attributes as OA; use phpseclib3\Crypt\PublicKeyLoader; -use DanHarrin\LivewireRateLimiting\WithRateLimiting; #[OA\Schema( description: 'Private Key model', @@ -44,8 +44,8 @@ class PrivateKey extends BaseModel { static::saving(function ($key) { $key->private_key = formatPrivateKey($key->private_key); - - if (!self::validatePrivateKey($key->private_key)) { + + if (! self::validatePrivateKey($key->private_key)) { throw ValidationException::withMessages([ 'private_key' => ['The private key is invalid.'], ]); @@ -73,6 +73,7 @@ class PrivateKey extends BaseModel public static function ownedByCurrentTeam(array $select = ['*']) { $selectArray = collect($select)->concat(['id']); + return self::whereTeamId(currentTeam()->id)->select($selectArray->all()); } @@ -80,6 +81,7 @@ class PrivateKey extends BaseModel { try { PublicKeyLoader::load($privateKey); + return true; } catch (\Throwable $e) { return false; @@ -91,18 +93,19 @@ class PrivateKey extends BaseModel $privateKey = new self($data); $privateKey->save(); $privateKey->storeInFileSystem(); + return $privateKey; } public static function generateNewKeyPair($type = 'rsa') { try { - $instance = new self(); + $instance = new self; $instance->rateLimit(10); $name = generate_random_name(); $description = 'Created by Coolify'; $keyPair = generateSSHKey($type === 'ed25519' ? 'ed25519' : 'rsa'); - + return [ 'name' => $name, 'description' => $description, @@ -110,7 +113,7 @@ class PrivateKey extends BaseModel 'public_key' => $keyPair['public'], ]; } catch (\Throwable $e) { - throw new \Exception("Failed to generate new {$type} key: " . $e->getMessage()); + throw new \Exception("Failed to generate new {$type} key: ".$e->getMessage()); } } @@ -118,6 +121,7 @@ class PrivateKey extends BaseModel { try { $key = PublicKeyLoader::load($privateKey); + return $key->getPublicKey()->toString('OpenSSH', ['comment' => '']); } catch (\Throwable $e) { return null; @@ -128,7 +132,7 @@ class PrivateKey extends BaseModel { $isValid = self::validatePrivateKey($privateKey); $publicKey = $isValid ? self::extractPublicKeyFromPrivate($privateKey) : ''; - + return [ 'isValid' => $isValid, 'publicKey' => $publicKey, @@ -138,12 +142,16 @@ class PrivateKey extends BaseModel public function storeInFileSystem() { $filename = "ssh_key@{$this->uuid}"; + echo 'Storing key: '.$filename."\n".'Private key: '.$this->private_key."\n"; Storage::disk('ssh-keys')->put($filename, $this->private_key); + $file = Storage::disk('ssh-keys')->get($filename); + echo 'File: '.$file."\n"; + return "/var/www/html/storage/app/ssh/keys/{$filename}"; } public static function deleteFromStorage(self $privateKey) - { + { $filename = "ssh_key@{$privateKey->uuid}"; Storage::disk('ssh-keys')->delete($filename); } @@ -157,6 +165,7 @@ class PrivateKey extends BaseModel { $this->update($data); $this->storeInFileSystem(); + return $this; } @@ -182,18 +191,20 @@ class PrivateKey extends BaseModel public function isInUse() { - return $this->servers()->exists() - || $this->applications()->exists() - || $this->githubApps()->exists() + return $this->servers()->exists() + || $this->applications()->exists() + || $this->githubApps()->exists() || $this->gitlabApps()->exists(); } public function safeDelete() { - if (!$this->isInUse()) { + if (! $this->isInUse()) { $this->delete(); + return true; } + return false; } @@ -202,6 +213,7 @@ class PrivateKey extends BaseModel try { $key = PublicKeyLoader::load($privateKey); $publicKey = $key->getPublicKey(); + return $publicKey->getFingerprint('sha256'); } catch (\Throwable $e) { return null; @@ -211,7 +223,7 @@ class PrivateKey extends BaseModel private static function fingerprintExists($fingerprint, $excludeId = null) { $query = self::where('fingerprint', $fingerprint); - + if ($excludeId) { $query->where('id', '!=', $excludeId); } diff --git a/database/seeders/PopulateSshKeysDirectorySeeder.php b/database/seeders/PopulateSshKeysDirectorySeeder.php index 9fd6e5cfc..77ec1cf3b 100644 --- a/database/seeders/PopulateSshKeysDirectorySeeder.php +++ b/database/seeders/PopulateSshKeysDirectorySeeder.php @@ -2,9 +2,10 @@ namespace Database\Seeders; -use Illuminate\Database\Seeder; -use Illuminate\Support\Facades\Storage; use App\Models\PrivateKey; +use Illuminate\Database\Seeder; +use Illuminate\Support\Facades\Process; +use Illuminate\Support\Facades\Storage; class PopulateSshKeysDirectorySeeder extends Seeder { @@ -12,11 +13,17 @@ class PopulateSshKeysDirectorySeeder extends Seeder { Storage::disk('ssh-keys')->deleteDirectory(''); Storage::disk('ssh-keys')->makeDirectory(''); + Storage::disk('ssh-mux')->deleteDirectory(''); + Storage::disk('ssh-mux')->makeDirectory(''); PrivateKey::chunk(100, function ($keys) { foreach ($keys as $key) { + echo 'Storing key: '.$key->name."\n"; $key->storeInFileSystem(); } }); + + Process::run('chown -R 9999:9999 '.storage_path('app/ssh/keys')); + Process::run('chown -R 9999:9999 '.storage_path('app/ssh/mux')); } } diff --git a/database/seeders/ProductionSeeder.php b/database/seeders/ProductionSeeder.php index 9e7df74da..17a85f7b6 100644 --- a/database/seeders/ProductionSeeder.php +++ b/database/seeders/ProductionSeeder.php @@ -123,6 +123,7 @@ class ProductionSeeder extends Seeder ]); $server->update(['user' => $user]); echo "SSH key found for the Coolify host machine (localhost).\n"; + } else { PrivateKey::create( [