Merge pull request #5638 from atomicptr/feat/add-http-basic-auth
feat: Add HTTP Basic Authentication
This commit is contained in:
commit
37e79b25bc
5 changed files with 108 additions and 12 deletions
|
|
@ -94,6 +94,9 @@ class General extends Component
|
|||
'application.settings.is_preserve_repository_enabled' => 'boolean|required',
|
||||
'application.watch_paths' => 'nullable',
|
||||
'application.redirect' => 'string|required',
|
||||
'application.http_basic_auth_enabled' => 'boolean|required',
|
||||
'application.http_basic_auth_username' => 'nullable',
|
||||
'application.http_basic_auth_password' => 'nullable',
|
||||
];
|
||||
|
||||
protected $validationAttributes = [
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@
|
|||
'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.'],
|
||||
'custom_nginx_configuration' => ['type' => 'string', 'nullable' => true, 'description' => 'Custom Nginx configuration base64 encoded.'],
|
||||
'http_basic_auth_enabled' => ['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;
|
||||
}
|
||||
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([]);
|
||||
if ($serviceLabels) {
|
||||
|
|
@ -304,6 +305,9 @@ function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains,
|
|||
} else {
|
||||
$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) {
|
||||
$url = Url::fromString($domain);
|
||||
$host = $url->getHost();
|
||||
|
|
@ -340,20 +344,30 @@ function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains,
|
|||
if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
|
||||
$labels->push("caddy_{$loop}.redir={$schema}://{$host_without_www}{uri}");
|
||||
}
|
||||
if (isDev()) {
|
||||
// $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();
|
||||
}
|
||||
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->push('traefik.enable=true');
|
||||
$labels->push('traefik.http.middlewares.gzip.compress=true');
|
||||
$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([]);
|
||||
|
||||
if ($serviceLabels) {
|
||||
|
|
@ -511,6 +525,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||
$labels = $labels->merge($redirect_to_www);
|
||||
$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->push($middleware_name);
|
||||
});
|
||||
|
|
@ -534,6 +551,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
|||
$labels = $labels->merge($redirect_to_www);
|
||||
$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->push($middleware_name);
|
||||
});
|
||||
|
|
@ -562,6 +582,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
if ($pull_request_id !== 0) {
|
||||
$appUuid = $appUuid.'-pr-'.$pull_request_id;
|
||||
}
|
||||
ray($application);
|
||||
$labels = collect([]);
|
||||
if ($pull_request_id === 0) {
|
||||
if ($application->fqdn) {
|
||||
|
|
@ -577,7 +598,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
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;
|
||||
case ProxyTypes::CADDY->value:
|
||||
|
|
@ -589,7 +613,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
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;
|
||||
}
|
||||
|
|
@ -601,7 +628,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
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,
|
||||
));
|
||||
$labels = $labels->merge(fqdnLabelsForCaddy(
|
||||
network: $application->destination->network,
|
||||
|
|
@ -611,7 +641,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
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,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -631,7 +664,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
onlyPort: $onlyPort,
|
||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||
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;
|
||||
case ProxyTypes::CADDY->value:
|
||||
|
|
@ -642,7 +678,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
onlyPort: $onlyPort,
|
||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||
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;
|
||||
}
|
||||
|
|
@ -653,7 +692,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
onlyPort: $onlyPort,
|
||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||
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,
|
||||
));
|
||||
$labels = $labels->merge(fqdnLabelsForCaddy(
|
||||
network: $application->destination->network,
|
||||
|
|
@ -662,7 +704,10 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||
onlyPort: $onlyPort,
|
||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled(),
|
||||
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,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_enabled')->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_enabled');
|
||||
$table->dropColumn('http_basic_auth_username');
|
||||
$table->dropColumn('http_basic_auth_password');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -349,6 +349,19 @@ class="underline" href="https://coolify.io/docs/knowledge-base/docker/registry"
|
|||
@endif
|
||||
</div>
|
||||
|
||||
<h3 class="pt-8">HTTP Basic Authentication</h3>
|
||||
<div x-data="{ enabled: {{ $application->http_basic_auth_enabled ? 'true' : 'false' }} }">
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox helper="This will add the proper proxy labels to the container."
|
||||
label="Enable" id="application.http_basic_auth_enabled" x-model="enabled" />
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 py-2" x-show="enabled">
|
||||
<x-forms.input id="application.http_basic_auth_username" label="Username" />
|
||||
<x-forms.input id="application.http_basic_auth_password" type="password" label="Password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($application->settings->is_container_label_readonly_enabled)
|
||||
<x-forms.textarea readonly disabled label="Container Labels" rows="15" id="customLabels"
|
||||
monacoEditorLanguage="ini" useMonacoEditor></x-forms.textarea>
|
||||
|
|
|
|||
Loading…
Reference in a new issue