feat: Add HTTP Basic Authentication
This commit is contained in:
@@ -94,6 +94,9 @@ class General extends Component
|
|||||||
'application.settings.is_preserve_repository_enabled' => 'boolean|required',
|
'application.settings.is_preserve_repository_enabled' => 'boolean|required',
|
||||||
'application.watch_paths' => 'nullable',
|
'application.watch_paths' => 'nullable',
|
||||||
'application.redirect' => 'string|required',
|
'application.redirect' => 'string|required',
|
||||||
|
'application.http_basic_auth_enable' => 'boolean|required',
|
||||||
|
'application.http_basic_auth_username' => 'nullable',
|
||||||
|
'application.http_basic_auth_password' => 'nullable',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $validationAttributes = [
|
protected $validationAttributes = [
|
||||||
|
@@ -103,6 +103,9 @@ use Visus\Cuid2\Cuid2;
|
|||||||
'deleted_at' => ['type' => 'string', 'format' => 'date-time', 'nullable' => true, 'description' => 'The date and time when the application was deleted.'],
|
'deleted_at' => ['type' => 'string', 'format' => 'date-time', 'nullable' => true, 'description' => 'The date and time when the application was deleted.'],
|
||||||
'compose_parsing_version' => ['type' => 'string', 'description' => 'How Coolify parse the compose file.'],
|
'compose_parsing_version' => ['type' => 'string', 'description' => 'How Coolify parse the compose file.'],
|
||||||
'custom_nginx_configuration' => ['type' => 'string', 'nullable' => true, 'description' => 'Custom Nginx configuration base64 encoded.'],
|
'custom_nginx_configuration' => ['type' => 'string', 'nullable' => true, 'description' => 'Custom Nginx configuration base64 encoded.'],
|
||||||
|
'http_basic_auth_enable' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'],
|
||||||
|
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
||||||
|
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
@@ -296,7 +296,8 @@ function generateServiceSpecificFqdns(ServiceApplication|Application $resource)
|
|||||||
|
|
||||||
return $payload;
|
return $payload;
|
||||||
}
|
}
|
||||||
function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null, ?string $image = null, string $redirect_direction = 'both', ?string $predefinedPort = null)
|
|
||||||
|
function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null, ?string $image = null, string $redirect_direction = 'both', ?string $predefinedPort = null, bool $http_basic_auth_enabled = false, ?string $http_basic_auth_username = null, ?string $http_basic_auth_password = null)
|
||||||
{
|
{
|
||||||
$labels = collect([]);
|
$labels = collect([]);
|
||||||
if ($serviceLabels) {
|
if ($serviceLabels) {
|
||||||
@@ -304,6 +305,9 @@ function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains,
|
|||||||
} else {
|
} else {
|
||||||
$labels->push("caddy_ingress_network={$network}");
|
$labels->push("caddy_ingress_network={$network}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$http_basic_auth_enabled = $http_basic_auth_enabled && $http_basic_auth_username !== null && $http_basic_auth_password !== null;
|
||||||
|
|
||||||
foreach ($domains as $loop => $domain) {
|
foreach ($domains as $loop => $domain) {
|
||||||
$url = Url::fromString($domain);
|
$url = Url::fromString($domain);
|
||||||
$host = $url->getHost();
|
$host = $url->getHost();
|
||||||
@@ -343,17 +347,30 @@ function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains,
|
|||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
// $labels->push("caddy_{$loop}.tls=internal");
|
// $labels->push("caddy_{$loop}.tls=internal");
|
||||||
}
|
}
|
||||||
|
if ($http_basic_auth_enabled) {
|
||||||
|
$http_basic_auth_password = password_hash($http_basic_auth_password, PASSWORD_BCRYPT, ['cost' => 10]);
|
||||||
|
$labels->push("caddy_{$loop}.basicauth.{$http_basic_auth_username}=\"{$http_basic_auth_password}\"");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $labels->sort();
|
return $labels->sort();
|
||||||
}
|
}
|
||||||
function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null, bool $generate_unique_uuid = false, ?string $image = null, string $redirect_direction = 'both')
|
|
||||||
|
function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null, bool $generate_unique_uuid = false, ?string $image = null, string $redirect_direction = 'both', bool $http_basic_auth_enabled = false, ?string $http_basic_auth_username = null, ?string $http_basic_auth_password = null)
|
||||||
{
|
{
|
||||||
$labels = collect([]);
|
$labels = collect([]);
|
||||||
$labels->push('traefik.enable=true');
|
$labels->push('traefik.enable=true');
|
||||||
$labels->push('traefik.http.middlewares.gzip.compress=true');
|
$labels->push('traefik.http.middlewares.gzip.compress=true');
|
||||||
$labels->push('traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https');
|
$labels->push('traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https');
|
||||||
|
|
||||||
|
$http_basic_auth_enabled = $http_basic_auth_enabled && $http_basic_auth_username !== null && $http_basic_auth_password !== null;
|
||||||
|
$http_basic_auth_label = "http-basic-auth-{$uuid}";
|
||||||
|
|
||||||
|
if ($http_basic_auth_enabled) {
|
||||||
|
$http_basic_auth_password = password_hash($http_basic_auth_password, PASSWORD_BCRYPT, ['cost' => 10]);
|
||||||
|
$labels->push("traefik.http.middlewares.{$http_basic_auth_label}.basicauth.users={$http_basic_auth_username}:{$http_basic_auth_password}");
|
||||||
|
}
|
||||||
|
|
||||||
$middlewares_from_labels = collect([]);
|
$middlewares_from_labels = collect([]);
|
||||||
|
|
||||||
if ($serviceLabels) {
|
if ($serviceLabels) {
|
||||||
@@ -511,6 +528,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||||||
$labels = $labels->merge($redirect_to_www);
|
$labels = $labels->merge($redirect_to_www);
|
||||||
$middlewares->push($to_www_name);
|
$middlewares->push($to_www_name);
|
||||||
}
|
}
|
||||||
|
if ($http_basic_auth_enabled) {
|
||||||
|
$middlewares->push($http_basic_auth_label);
|
||||||
|
}
|
||||||
$middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
|
$middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
|
||||||
$middlewares->push($middleware_name);
|
$middlewares->push($middleware_name);
|
||||||
});
|
});
|
||||||
@@ -534,6 +554,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||||||
$labels = $labels->merge($redirect_to_www);
|
$labels = $labels->merge($redirect_to_www);
|
||||||
$middlewares->push($to_www_name);
|
$middlewares->push($to_www_name);
|
||||||
}
|
}
|
||||||
|
if ($http_basic_auth_enabled) {
|
||||||
|
$middlewares->push($http_basic_auth_label);
|
||||||
|
}
|
||||||
$middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
|
$middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
|
||||||
$middlewares->push($middleware_name);
|
$middlewares->push($middleware_name);
|
||||||
});
|
});
|
||||||
@@ -577,7 +600,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||||
is_gzip_enabled: $application->isGzipEnabled(),
|
is_gzip_enabled: $application->isGzipEnabled(),
|
||||||
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||||
redirect_direction: $application->redirect
|
redirect_direction: $application->redirect,
|
||||||
|
http_basic_auth_enabled: $application->http_basic_auth_enable,
|
||||||
|
http_basic_auth_username: $application->http_basic_auth_username,
|
||||||
|
http_basic_auth_password: $application->http_basic_auth_password,
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
case ProxyTypes::CADDY->value:
|
case ProxyTypes::CADDY->value:
|
||||||
@@ -589,7 +615,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||||
is_gzip_enabled: $application->isGzipEnabled(),
|
is_gzip_enabled: $application->isGzipEnabled(),
|
||||||
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||||
redirect_direction: $application->redirect
|
redirect_direction: $application->redirect,
|
||||||
|
http_basic_auth_enabled: $application->http_basic_auth_enabled,
|
||||||
|
http_basic_auth_username: $application->http_basic_auth_username,
|
||||||
|
http_basic_auth_password: $application->http_basic_auth_password,
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -601,7 +630,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||||
is_gzip_enabled: $application->isGzipEnabled(),
|
is_gzip_enabled: $application->isGzipEnabled(),
|
||||||
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||||
redirect_direction: $application->redirect
|
redirect_direction: $application->redirect,
|
||||||
|
http_basic_auth_enabled: $application->http_basic_auth_enable,
|
||||||
|
http_basic_auth_username: $application->http_basic_auth_username,
|
||||||
|
http_basic_auth_password: $application->http_basic_auth_password,
|
||||||
));
|
));
|
||||||
$labels = $labels->merge(fqdnLabelsForCaddy(
|
$labels = $labels->merge(fqdnLabelsForCaddy(
|
||||||
network: $application->destination->network,
|
network: $application->destination->network,
|
||||||
@@ -611,7 +643,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||||
is_gzip_enabled: $application->isGzipEnabled(),
|
is_gzip_enabled: $application->isGzipEnabled(),
|
||||||
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||||
redirect_direction: $application->redirect
|
redirect_direction: $application->redirect,
|
||||||
|
http_basic_auth_enabled: $application->http_basic_auth_enable,
|
||||||
|
http_basic_auth_username: $application->http_basic_auth_username,
|
||||||
|
http_basic_auth_password: $application->http_basic_auth_password,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -631,7 +666,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
onlyPort: $onlyPort,
|
onlyPort: $onlyPort,
|
||||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||||
is_gzip_enabled: $application->isGzipEnabled(),
|
is_gzip_enabled: $application->isGzipEnabled(),
|
||||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||||
|
http_basic_auth_enabled: $application->http_basic_auth_enable,
|
||||||
|
http_basic_auth_username: $application->http_basic_auth_username,
|
||||||
|
http_basic_auth_password: $application->http_basic_auth_password,
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
case ProxyTypes::CADDY->value:
|
case ProxyTypes::CADDY->value:
|
||||||
@@ -642,7 +680,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
onlyPort: $onlyPort,
|
onlyPort: $onlyPort,
|
||||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||||
is_gzip_enabled: $application->isGzipEnabled(),
|
is_gzip_enabled: $application->isGzipEnabled(),
|
||||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||||
|
http_basic_auth_enabled: $application->http_basic_auth_enable,
|
||||||
|
http_basic_auth_username: $application->http_basic_auth_username,
|
||||||
|
http_basic_auth_password: $application->http_basic_auth_password,
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -653,7 +694,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
onlyPort: $onlyPort,
|
onlyPort: $onlyPort,
|
||||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||||
is_gzip_enabled: $application->isGzipEnabled(),
|
is_gzip_enabled: $application->isGzipEnabled(),
|
||||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||||
|
http_basic_auth_enabled: $application->http_basic_auth_enable,
|
||||||
|
http_basic_auth_username: $application->http_basic_auth_username,
|
||||||
|
http_basic_auth_password: $application->http_basic_auth_password,
|
||||||
));
|
));
|
||||||
$labels = $labels->merge(fqdnLabelsForCaddy(
|
$labels = $labels->merge(fqdnLabelsForCaddy(
|
||||||
network: $application->destination->network,
|
network: $application->destination->network,
|
||||||
@@ -662,7 +706,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
onlyPort: $onlyPort,
|
onlyPort: $onlyPort,
|
||||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||||
is_gzip_enabled: $application->isGzipEnabled(),
|
is_gzip_enabled: $application->isGzipEnabled(),
|
||||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||||
|
http_basic_auth_enabled: $application->http_basic_auth_enable,
|
||||||
|
http_basic_auth_username: $application->http_basic_auth_username,
|
||||||
|
http_basic_auth_password: $application->http_basic_auth_password,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('applications', function (Blueprint $table) {
|
||||||
|
$table->boolean('http_basic_auth_enable')->default(false);
|
||||||
|
$table->string('http_basic_auth_username')->nullable(true)->default(null);
|
||||||
|
$table->string('http_basic_auth_password')->nullable(true)->default(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('applications', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('http_basic_auth_enable');
|
||||||
|
$table->dropColumn('http_basic_auth_username');
|
||||||
|
$table->dropColumn('http_basic_auth_password');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
@@ -349,6 +349,18 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h3 class="pt-8">HTTP Basic Authentication</h3>
|
||||||
|
<div x-data="{enabled: {{ $application->http_basic_auth_enable ? "true" : "false" }}}">
|
||||||
|
<div class="w-96">
|
||||||
|
<x-forms.checkbox label="Enable" id="application.http_basic_auth_enable" x-model="enabled" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-96" x-show="enabled">
|
||||||
|
<x-forms.input id="application.http_basic_auth_username" label="Username" />
|
||||||
|
<x-forms.input id="application.http_basic_auth_password" label="Password" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if ($application->settings->is_container_label_readonly_enabled)
|
@if ($application->settings->is_container_label_readonly_enabled)
|
||||||
<x-forms.textarea readonly disabled label="Container Labels" rows="15" id="customLabels"
|
<x-forms.textarea readonly disabled label="Container Labels" rows="15" id="customLabels"
|
||||||
monacoEditorLanguage="ini" useMonacoEditor></x-forms.textarea>
|
monacoEditorLanguage="ini" useMonacoEditor></x-forms.textarea>
|
||||||
|
Reference in New Issue
Block a user