fix: redis database user and password
This commit is contained in:
@@ -4,7 +4,6 @@ namespace App\Livewire\Project\Database\Redis;
|
|||||||
|
|
||||||
use App\Actions\Database\StartDatabaseProxy;
|
use App\Actions\Database\StartDatabaseProxy;
|
||||||
use App\Actions\Database\StopDatabaseProxy;
|
use App\Actions\Database\StopDatabaseProxy;
|
||||||
use App\Models\EnvironmentVariable;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\StandaloneRedis;
|
use App\Models\StandaloneRedis;
|
||||||
use Exception;
|
use Exception;
|
||||||
@@ -12,12 +11,21 @@ use Livewire\Component;
|
|||||||
|
|
||||||
class General extends Component
|
class General extends Component
|
||||||
{
|
{
|
||||||
protected $listeners = ['refresh'];
|
protected $listeners = [
|
||||||
|
'envsUpdated' => 'refresh',
|
||||||
|
'refresh',
|
||||||
|
];
|
||||||
|
|
||||||
public Server $server;
|
public Server $server;
|
||||||
|
|
||||||
public StandaloneRedis $database;
|
public StandaloneRedis $database;
|
||||||
|
|
||||||
|
public ?string $redis_username;
|
||||||
|
|
||||||
|
public ?string $redis_password;
|
||||||
|
|
||||||
|
public string $redis_version;
|
||||||
|
|
||||||
public ?string $db_url = null;
|
public ?string $db_url = null;
|
||||||
|
|
||||||
public ?string $db_url_public = null;
|
public ?string $db_url_public = null;
|
||||||
@@ -26,35 +34,33 @@ class General extends Component
|
|||||||
'database.name' => 'required',
|
'database.name' => 'required',
|
||||||
'database.description' => 'nullable',
|
'database.description' => 'nullable',
|
||||||
'database.redis_conf' => 'nullable',
|
'database.redis_conf' => 'nullable',
|
||||||
'database.redis_username' => 'required',
|
|
||||||
'database.redis_password' => 'required',
|
|
||||||
'database.image' => 'required',
|
'database.image' => 'required',
|
||||||
'database.ports_mappings' => 'nullable',
|
'database.ports_mappings' => 'nullable',
|
||||||
'database.is_public' => 'nullable|boolean',
|
'database.is_public' => 'nullable|boolean',
|
||||||
'database.public_port' => 'nullable|integer',
|
'database.public_port' => 'nullable|integer',
|
||||||
'database.is_log_drain_enabled' => 'nullable|boolean',
|
'database.is_log_drain_enabled' => 'nullable|boolean',
|
||||||
'database.custom_docker_run_options' => 'nullable',
|
'database.custom_docker_run_options' => 'nullable',
|
||||||
|
'redis_username' => 'required',
|
||||||
|
'redis_password' => 'required',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $validationAttributes = [
|
protected $validationAttributes = [
|
||||||
'database.name' => 'Name',
|
'database.name' => 'Name',
|
||||||
'database.description' => 'Description',
|
'database.description' => 'Description',
|
||||||
'database.redis_conf' => 'Redis Configuration',
|
'database.redis_conf' => 'Redis Configuration',
|
||||||
'database.redis_username' => 'Redis Username',
|
|
||||||
'database.redis_password' => 'Redis Password',
|
|
||||||
'database.image' => 'Image',
|
'database.image' => 'Image',
|
||||||
'database.ports_mappings' => 'Port Mapping',
|
'database.ports_mappings' => 'Port Mapping',
|
||||||
'database.is_public' => 'Is Public',
|
'database.is_public' => 'Is Public',
|
||||||
'database.public_port' => 'Public Port',
|
'database.public_port' => 'Public Port',
|
||||||
'database.custom_docker_run_options' => 'Custom Docker Options',
|
'database.custom_docker_run_options' => 'Custom Docker Options',
|
||||||
|
'redis_username' => 'Redis Username',
|
||||||
|
'redis_password' => 'Redis Password',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->db_url = $this->database->internal_db_url;
|
|
||||||
$this->db_url_public = $this->database->external_db_url;
|
|
||||||
$this->server = data_get($this->database, 'destination.server');
|
$this->server = data_get($this->database, 'destination.server');
|
||||||
|
$this->refreshView();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function instantSaveAdvanced()
|
public function instantSaveAdvanced()
|
||||||
@@ -79,31 +85,26 @@ class General extends Component
|
|||||||
try {
|
try {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
|
||||||
$redis_version = $this->get_redis_version();
|
if (version_compare($this->redis_version, '6.0', '>=')) {
|
||||||
|
$this->database->runtime_environment_variables()->updateOrCreate(
|
||||||
if (version_compare($redis_version, '6.0', '>=') && $this->database->isDirty('redis_username')) {
|
['key' => 'REDIS_USERNAME'],
|
||||||
$this->updateEnvironmentVariable('REDIS_USERNAME', $this->database->redis_username);
|
['value' => $this->redis_username, 'standalone_redis_id' => $this->database->id]
|
||||||
}
|
);
|
||||||
|
|
||||||
if ($this->database->isDirty('redis_password')) {
|
|
||||||
$this->updateEnvironmentVariable('REDIS_PASSWORD', $this->database->redis_password);
|
|
||||||
}
|
}
|
||||||
|
$this->database->runtime_environment_variables()->updateOrCreate(
|
||||||
|
['key' => 'REDIS_PASSWORD'],
|
||||||
|
['value' => $this->redis_password, 'standalone_redis_id' => $this->database->id]
|
||||||
|
);
|
||||||
|
|
||||||
$this->database->save();
|
$this->database->save();
|
||||||
|
|
||||||
$this->dispatch('success', 'Database updated.');
|
$this->dispatch('success', 'Database updated.');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
|
} finally {
|
||||||
|
$this->dispatch('refreshEnvs');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function get_redis_version()
|
|
||||||
{
|
|
||||||
$image_parts = explode(':', $this->database->image);
|
|
||||||
|
|
||||||
return $image_parts[1] ?? '0.0';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -138,6 +139,14 @@ class General extends Component
|
|||||||
public function refresh(): void
|
public function refresh(): void
|
||||||
{
|
{
|
||||||
$this->database->refresh();
|
$this->database->refresh();
|
||||||
|
$this->refreshView();
|
||||||
|
}
|
||||||
|
private function refreshView() {
|
||||||
|
$this->db_url = $this->database->internal_db_url;
|
||||||
|
$this->db_url_public = $this->database->external_db_url;
|
||||||
|
$this->redis_version = $this->database->getRedisVersion();
|
||||||
|
$this->redis_username = $this->database->redis_username;
|
||||||
|
$this->redis_password = $this->database->redis_password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
@@ -147,28 +156,7 @@ class General extends Component
|
|||||||
|
|
||||||
public function isSharedVariable($name)
|
public function isSharedVariable($name)
|
||||||
{
|
{
|
||||||
return EnvironmentVariable::where('key', $name)
|
return $this->database->runtime_environment_variables()->where('key', $name)->where('is_shared', true)->exists();
|
||||||
->where('standalone_redis_id', $this->database->id)
|
|
||||||
->where('is_shared', true)
|
|
||||||
->exists();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateEnvironmentVariable($key, $value)
|
|
||||||
{
|
|
||||||
$envVar = $this->database->runtime_environment_variables()
|
|
||||||
->where('key', $key)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
if ($envVar) {
|
|
||||||
if (! $envVar->is_shared) {
|
|
||||||
$envVar->update(['value' => $value]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->database->runtime_environment_variables()->create([
|
|
||||||
'key' => $key,
|
|
||||||
'value' => $value,
|
|
||||||
'is_shared' => false,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -33,8 +33,6 @@ class Index extends Component
|
|||||||
|
|
||||||
protected Server $server;
|
protected Server $server;
|
||||||
|
|
||||||
public $timezones;
|
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'settings.fqdn' => 'nullable',
|
'settings.fqdn' => 'nullable',
|
||||||
'settings.resale_license' => 'nullable',
|
'settings.resale_license' => 'nullable',
|
||||||
|
@@ -16,13 +16,6 @@ class StandaloneRedis extends BaseModel
|
|||||||
|
|
||||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||||
|
|
||||||
protected $casts = [
|
|
||||||
'redis_password' => 'encrypted',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $attributes = [
|
|
||||||
'redis_username' => 'default',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected static function booted()
|
protected static function booted()
|
||||||
{
|
{
|
||||||
@@ -219,7 +212,7 @@ class StandaloneRedis extends BaseModel
|
|||||||
{
|
{
|
||||||
return new Attribute(
|
return new Attribute(
|
||||||
get: function () {
|
get: function () {
|
||||||
$redis_version = $this->get_redis_version();
|
$redis_version = $this->getRedisVersion();
|
||||||
$username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : '';
|
$username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : '';
|
||||||
|
|
||||||
return "redis://{$username_part}{$this->redis_password}@{$this->uuid}:6379/0";
|
return "redis://{$username_part}{$this->redis_password}@{$this->uuid}:6379/0";
|
||||||
@@ -232,7 +225,7 @@ class StandaloneRedis extends BaseModel
|
|||||||
return new Attribute(
|
return new Attribute(
|
||||||
get: function () {
|
get: function () {
|
||||||
if ($this->is_public && $this->public_port) {
|
if ($this->is_public && $this->public_port) {
|
||||||
$redis_version = $this->get_redis_version();
|
$redis_version = $this->getRedisVersion();
|
||||||
$username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : '';
|
$username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : '';
|
||||||
|
|
||||||
return "redis://{$username_part}{$this->redis_password}@{$this->destination->server->getIp}:{$this->public_port}/0";
|
return "redis://{$username_part}{$this->redis_password}@{$this->destination->server->getIp}:{$this->public_port}/0";
|
||||||
@@ -243,7 +236,7 @@ class StandaloneRedis extends BaseModel
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function get_redis_version()
|
public function getRedisVersion()
|
||||||
{
|
{
|
||||||
$image_parts = explode(':', $this->image);
|
$image_parts = explode(':', $this->image);
|
||||||
|
|
||||||
@@ -318,4 +311,32 @@ class StandaloneRedis extends BaseModel
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function redisPassword(): Attribute
|
||||||
|
{
|
||||||
|
return new Attribute(
|
||||||
|
get: function () {
|
||||||
|
$password = $this->runtime_environment_variables()->where('key', 'REDIS_PASSWORD')->first();
|
||||||
|
if (! $password) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $password->value;
|
||||||
|
},
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function redisUsername(): Attribute
|
||||||
|
{
|
||||||
|
return new Attribute(
|
||||||
|
get: function () {
|
||||||
|
$username = $this->runtime_environment_variables()->where('key', 'REDIS_USERNAME')->first();
|
||||||
|
if (! $username) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return $username->value;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -50,7 +50,6 @@ function create_standalone_redis($environment_id, $destination_uuid, ?array $oth
|
|||||||
$database = new StandaloneRedis;
|
$database = new StandaloneRedis;
|
||||||
$database->name = generate_database_name('redis');
|
$database->name = generate_database_name('redis');
|
||||||
$database->redis_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
|
$database->redis_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
|
||||||
$database->redis_username = 'default';
|
|
||||||
$database->environment_id = $environment_id;
|
$database->environment_id = $environment_id;
|
||||||
$database->destination_id = $destination->id;
|
$database->destination_id = $destination->id;
|
||||||
$database->destination_type = $destination->getMorphClass();
|
$database->destination_type = $destination->getMorphClass();
|
||||||
@@ -68,7 +67,7 @@ function create_standalone_redis($environment_id, $destination_uuid, ?array $oth
|
|||||||
|
|
||||||
EnvironmentVariable::create([
|
EnvironmentVariable::create([
|
||||||
'key' => 'REDIS_USERNAME',
|
'key' => 'REDIS_USERNAME',
|
||||||
'value' => $database->redis_username,
|
'value' => 'default',
|
||||||
'standalone_redis_id' => $database->id,
|
'standalone_redis_id' => $database->id,
|
||||||
'is_shared' => false,
|
'is_shared' => false,
|
||||||
]);
|
]);
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::table('standalone_redis', function (Blueprint $table) {
|
|
||||||
$table->string('redis_username')->default('redis')->after('description');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::table('standalone_redis', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('redis_username');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
|
|||||||
use Illuminate\Support\Facades\Crypt;
|
use Illuminate\Support\Facades\Crypt;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class EncryptExistingRedisPasswords extends Migration
|
class MoveRedisPasswordToEnvs extends Migration
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Run the migrations.
|
* Run the migrations.
|
||||||
@@ -14,13 +14,15 @@ class EncryptExistingRedisPasswords extends Migration
|
|||||||
try {
|
try {
|
||||||
DB::table('standalone_redis')->chunkById(100, function ($redisInstances) {
|
DB::table('standalone_redis')->chunkById(100, function ($redisInstances) {
|
||||||
foreach ($redisInstances as $redis) {
|
foreach ($redisInstances as $redis) {
|
||||||
DB::table('standalone_redis')
|
$redis->runtime_environment_variables()->firstOrCreate([
|
||||||
->where('id', $redis->id)
|
'key' => 'REDIS_PASSWORD',
|
||||||
->update(['redis_password' => Crypt::encryptString($redis->redis_password)]);
|
'value' => $redis->redis_password,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
DB::statement('ALTER TABLE standalone_redis DROP COLUMN redis_password');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
echo 'Encrypting Redis passwords failed.';
|
echo 'Moving Redis passwords to envs failed.';
|
||||||
echo $e->getMessage();
|
echo $e->getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -12,11 +12,8 @@
|
|||||||
<x-forms.input label="Image" id="database.image" required helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/redis'>https://hub.docker.com/_/redis</a>" />
|
<x-forms.input label="Image" id="database.image" required helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/redis'>https://hub.docker.com/_/redis</a>" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
@php
|
|
||||||
$redis_version = explode(':', $database->image)[1] ?? '0.0';
|
|
||||||
@endphp
|
|
||||||
@if (version_compare($redis_version, '6.0', '>='))
|
@if (version_compare($redis_version, '6.0', '>='))
|
||||||
<x-forms.input label="Username" id="database.redis_username" required
|
<x-forms.input label="Username" id="redis_username" required
|
||||||
helper="You can change the Redis Username in the input field below or by editing the value of the REDIS_USERNAME environment variable.
|
helper="You can change the Redis Username in the input field below or by editing the value of the REDIS_USERNAME environment variable.
|
||||||
<br><br>
|
<br><br>
|
||||||
If you change the Redis Username in the database, please sync it here, otherwise automations (like backups) won't work.
|
If you change the Redis Username in the database, please sync it here, otherwise automations (like backups) won't work.
|
||||||
@@ -24,13 +21,12 @@
|
|||||||
Note: If the environment variable REDIS_USERNAME is set as a shared variable (environment, project, or team-based), this input field will become read-only."
|
Note: If the environment variable REDIS_USERNAME is set as a shared variable (environment, project, or team-based), this input field will become read-only."
|
||||||
:disabled="$this->isSharedVariable('REDIS_USERNAME')" />
|
:disabled="$this->isSharedVariable('REDIS_USERNAME')" />
|
||||||
@endif
|
@endif
|
||||||
<x-forms.input label="Password" id="database.redis_password" type="password" required
|
<x-forms.input label="Password" id="redis_password" type="password" required
|
||||||
helper="You can change the Redis Password in the input field below or by editing the value of the REDIS_PASSWORD environment variable.
|
helper="You can change the Redis Password in the input field below or by editing the value of the REDIS_PASSWORD environment variable.
|
||||||
<br><br>
|
<br><br>
|
||||||
If you change the Redis Password in the database, please sync it here, otherwise automations (like backups) won't work.
|
If you change the Redis Password in the database, please sync it here, otherwise automations (like backups) won't work.
|
||||||
<br><br>
|
<br><br>
|
||||||
Note: If the environment variable REDIS_PASSWORD is set as a shared variable (environment, project, or team-based), this input field will become read-only."
|
Note: If the environment variable REDIS_PASSWORD is set as a shared variable (environment, project, or team-based), this input field will become read-only."
|
||||||
wire:model.defer="database.redis_password"
|
|
||||||
:disabled="$this->isSharedVariable('REDIS_PASSWORD')" />
|
:disabled="$this->isSharedVariable('REDIS_PASSWORD')" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input
|
<x-forms.input
|
||||||
|
Reference in New Issue
Block a user