mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2024-12-23 02:04:46 +02:00
[Web] manage keycloak identity provider
This commit is contained in:
parent
6adad79e5c
commit
f6869da3a0
@ -86,6 +86,8 @@ $cors_settings['allowed_origins'] = str_replace(", ", "\n", $cors_settings['allo
|
||||
$cors_settings['allowed_methods'] = explode(", ", $cors_settings['allowed_methods']);
|
||||
|
||||
$f2b_data = fail2ban('get');
|
||||
// identity provider
|
||||
$identity_provider_settings = identity_provider('get');
|
||||
|
||||
$template = 'admin.twig';
|
||||
$template_data = [
|
||||
@ -117,6 +119,7 @@ $template_data = [
|
||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||
'cors_settings' => $cors_settings,
|
||||
'is_https' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on',
|
||||
'identity_provider_settings' => $identity_provider_settings,
|
||||
'lang_admin' => json_encode($lang['admin']),
|
||||
'lang_datatables' => json_encode($lang['datatables'])
|
||||
];
|
||||
|
@ -2067,6 +2067,74 @@ function uuid4() {
|
||||
|
||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
||||
}
|
||||
function identity_provider($_action, $_data = null) {
|
||||
global $pdo;
|
||||
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($_action) {
|
||||
case 'get':
|
||||
$settings = array();
|
||||
$stmt = $pdo->prepare("SELECT * FROM `identity_provider`;");
|
||||
$stmt->execute();
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach($rows as $row){
|
||||
$settings[$row["key"]] = $row["value"];
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $settings),
|
||||
'msg' => 'admin_api_modified'
|
||||
);
|
||||
return $settings;
|
||||
case 'edit':
|
||||
$required_settings = array('server_url', 'authsource', 'realm', 'client_id', 'client_secret', 'redirect_url', 'version');
|
||||
foreach($required_settings as $setting){
|
||||
if (!$_data[$setting]){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data),
|
||||
'msg' => '2'
|
||||
);
|
||||
$stmt = $pdo->prepare("INSERT INTO identity_provider (`key`, `value`) VALUES (:key, :value) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);");
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data),
|
||||
'msg' => '3'
|
||||
);
|
||||
} catch (Exception $e){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $e->getMessage()),
|
||||
'msg' => 'post'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($_data as $key => $value){
|
||||
if (!in_array($key, $required_settings)){
|
||||
continue;
|
||||
}
|
||||
|
||||
$stmt->bindParam(':key', $key);
|
||||
$stmt->bindParam(':value', $value);
|
||||
$stmt->execute();
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function get_logs($application, $lines = false) {
|
||||
if ($lines === false) {
|
||||
|
@ -568,6 +568,20 @@ function init_db_schema() {
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"identity_provider" => array(
|
||||
"cols" => array(
|
||||
"key" => "VARCHAR(255) NOT NULL",
|
||||
"value" => "VARCHAR(255) NOT NULL",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP"
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("key")
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"logs" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
|
@ -180,6 +180,24 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.auth.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
|
||||
|
||||
// Init Keycloak Provider
|
||||
$identity_provider_settings = identity_provider('get');
|
||||
$keycloak_provider = null;
|
||||
if ($identity_provider_settings['server_url'] && $identity_provider_settings['realm'] && $identity_provider_settings['client_id'] &&
|
||||
$identity_provider_settings['client_secret'] && $identity_provider_settings['redirect_url'] && $identity_provider_settings['version']){
|
||||
$keycloak_provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'authServerUrl' => $identity_provider_settings['server_url'],
|
||||
'realm' => $identity_provider_settings['realm'],
|
||||
'clientId' => $identity_provider_settings['client_id'],
|
||||
'clientSecret' => $identity_provider_settings['client_secret'],
|
||||
'redirectUri' => $identity_provider_settings['redirect_url'],
|
||||
'version' => $identity_provider_settings['version'],
|
||||
// 'encryptionAlgorithm' => 'RS256', // optional
|
||||
// 'encryptionKeyPath' => '../key.pem' // optional
|
||||
// 'encryptionKey' => 'contents_of_key_or_certificate' // optional
|
||||
]);
|
||||
}
|
||||
|
||||
// IMAP lib
|
||||
// use Ddeboer\Imap\Server;
|
||||
// $imap_server = new Server('dovecot', 143, '/imap/tls/novalidate-cert');
|
||||
|
@ -1710,6 +1710,8 @@ if (isset($_GET['query'])) {
|
||||
if ($score)
|
||||
$score = array("score" => preg_replace("/\s+/", "", $score));
|
||||
process_get_return($score);
|
||||
case "identity_provider":
|
||||
process_get_return(identity_provider('get'));
|
||||
break;
|
||||
break;
|
||||
// return no route found if no case is matched
|
||||
@ -2082,6 +2084,8 @@ if (isset($_GET['query'])) {
|
||||
break;
|
||||
case "cors":
|
||||
process_edit_return(cors('edit', $attr));
|
||||
case "identity_provider":
|
||||
process_edit_return(identity_provider('edit', $attr));
|
||||
break;
|
||||
// return no route found if no case is matched
|
||||
default:
|
||||
|
@ -7,6 +7,7 @@
|
||||
<a class="nav-link dropdown-toggle active" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.admin.access }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item active" data-bs-target="#tab-config-admins" aria-selected="false" aria-controls="tab-config-admins" role="tab" data-bs-toggle="tab">{{ lang.admin.admins }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-identity-providers" aria-selected="false" aria-controls="tab-config-identity-providers" role="tab" data-bs-toggle="tab">Identity Providers</button></li>
|
||||
<!-- <li><button class="dropdown-item" data-bs-target="#tab-config-ldap-admins" aria-controls="tab-config-ldap-admins" role="tab" data-bs-toggle="tab">{{ lang.admin.admins_ldap }}</button></li> -->
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-oauth2" aria-selected="false" aria-controls="tab-config-oauth2" role="tab" data-bs-toggle="tab">{{ lang.admin.oauth2_apps }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-rspamd" aria-selected="false" aria-controls="tab-config-rspamd" role="tab" data-bs-toggle="tab">Rspamd UI</button></li>
|
||||
@ -40,6 +41,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="tab-content" style="padding-top:20px">
|
||||
{% include 'admin/tab-config-admins.twig' %}
|
||||
{% include 'admin/tab-config-identity-providers.twig' %}
|
||||
{# {% include 'admin/tab-ldap.twig' %} #}
|
||||
{% include 'admin/tab-config-oauth2.twig' %}
|
||||
{% include 'admin/tab-config-rspamd.twig' %}
|
||||
|
58
data/web/templates/admin/tab-config-identity-providers.twig
Normal file
58
data/web/templates/admin/tab-config-identity-providers.twig
Normal file
@ -0,0 +1,58 @@
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-identity-providers" role="tabpanel" aria-labelledby="tab-config-identity-providers">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-identity-providers" data-bs-toggle="collapse" aria-controls="collapse-tab-config-identity-providers">
|
||||
{{ lang.admin.oauth2_apps }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.oauth2_apps }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-identity-providers" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form-horizontal" autocapitalize="none" data-id="keycloak_sso" autocorrect="off" role="form" method="post">
|
||||
<input type="hidden" name="authsource" value="keycloak">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_url">Server URL:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_url" name="server_url" value="{{ identity_provider_settings.server_url }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_realm">Realm:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_realm" name="realm" value="{{ identity_provider_settings.realm }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_client_id">Client Id:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_client_id" name="client_id" value="{{ identity_provider_settings.client_id }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_client_secret">Client Secret:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_client_secret" name="client_secret" value="{{ identity_provider_settings.client_secret }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_redirect_url">Redirect Url:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_redirect_url" name="redirect_url" value="{{ identity_provider_settings.redirect_url }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="keycloak_version">Keycloak Version:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="keycloak_version" name="version" value="{{ identity_provider_settings.version }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4 mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="keycloak_sso" data-action="edit_selected" data-id="keycloak_sso" data-api-url='edit/identity_provider' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user