Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sugo integration #48

Merged
merged 9 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions config/config-example.php
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
<?php
define('TEST_MODE', true); // Use false for production
define('CRAUTO_PASS_MIN_LENGTH', 12);
define('CRAUTO_SIR_TMP_DIR_CLEANUP', 30);
define('CRAUTO_LDAP_URL', 'ldap://ldap1.sso.local');
define('CRAUTO_LDAP_BIND_DN', 'cn=Directory Manager');
define('CRAUTO_LDAP_PASSWORD', 'secret1');
define('CRAUTO_LDAP_STARTTLS', true);
define('CRAUTO_LDAP_USERS_DN', 'ou=People,dc=sso,dc=local');
define('CRAUTO_LDAP_GROUPS_DN', 'ou=Groups,dc=sso,dc=local');
define('CRAUTO_LDAP_INVITES_DN', 'ou=Invites,dc=sso,dc=local');
define('CRAUTO_OIDC_ISSUER', 'https://wso2.sso.local:9443/oauth2/oidcdiscovery');
define('CRAUTO_OIDC_CLIENT_ID', 'crauto'); // This is useless
define('CRAUTO_OIDC_CLIENT_KEY', '3VEQd6YM2a9qXtCGQJs8nGfm2Dsa'); // This is important (generated by WSO2 IS)
define('CRAUTO_OIDC_CLIENT_SECRET', 'Fd4BxUyaYYlByimKfAwv6_rDyl0a'); // This is even more important (generated by WSO2 IS)
const TEST_MODE = true; // Use false for production
const TEST_MODE_SSO = 1; // Use 1, 2 or 3 to log in as different test accounts, only used if TEST_MODE is true
const CRAUTO_PASS_MIN_LENGTH = 12;
const CRAUTO_SIR_TMP_DIR_CLEANUP = 30;
const CRAUTO_LDAP_URL = 'ldap://ldap1.sso.local';
const CRAUTO_LDAP_BIND_DN = 'cn=Directory Manager';
const CRAUTO_LDAP_PASSWORD = 'secret1';
const CRAUTO_LDAP_STARTTLS = true;
const CRAUTO_LDAP_USERS_DN = 'ou=People,dc=example,dc=test';
const CRAUTO_LDAP_GROUPS_DN = 'ou=Groups,dc=example,dc=test';
const CRAUTO_LDAP_INVITES_DN = 'ou=Invites,dc=example,dc=test';
const CRAUTO_OIDC_ISSUER = 'https://sso.example/oauth2/oidcdiscovery';
const CRAUTO_OIDC_CLIENT_KEY = '3VEQd6YM2a9qXtCGQJs8nGfm2Dsa'; // This is important (generated by WSO2 IS)
const CRAUTO_OIDC_CLIENT_SECRET = 'Fd4BxUyaYYlByimKfAwv6_rDyl0a'; // This is even more important (generated by WSO2 IS)
// Also, you shouldn't commit the secret (and possibly the key) in a public repo. These are used only in development,
// production key and secret are obviously different.
define('VERIFY_CERTIFICATES', true); // Set to false for development with self-signed certificates
define('CRAUTO_URL', 'http://[::1]:8200');
define('CRAUTO_DEBUG_ALWAYS_REFRESH', false); // Set to true to use the refresh token to get a new id token on each request
define('CRAUTO_DEFAULT_GROUPS', 'Test,Cloud,Admin');
define('CRAUTO_WEBSITE_IGNORE_GROUPS', 'Docenti,Foo,Bar');
define('CRAUTO_HOME_PAGE_SERVICES', [
const VERIFY_CERTIFICATES = true; // Set to false for development with self-signed certificates
const CRAUTO_URL = 'http://[::1]:8200';
const CRAUTO_DEBUG_ALWAYS_REFRESH = false; // Set to true to use the refresh token to get a new id token on each request
const CRAUTO_DEFAULT_GROUPS = 'Test,Cloud,Admin';
const CRAUTO_WEBSITE_IGNORE_GROUPS = 'Docenti,Foo,Bar';
const CRAUTO_HOME_PAGE_SERVICES = [
['Description description description', 'https://url.example.com', 'something'],
['Description', 'https://url.example.com'],
['Description without link']
]);
];
20 changes: 19 additions & 1 deletion public/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,28 @@
require '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
Authentication::requireLogin();

$error = null;
$attributes = [];
try {
$ldap = new Ldap(
CRAUTO_LDAP_URL,
CRAUTO_LDAP_BIND_DN,
CRAUTO_LDAP_PASSWORD,
CRAUTO_LDAP_USERS_DN,
CRAUTO_LDAP_GROUPS_DN,
CRAUTO_LDAP_STARTTLS
);
$attributes = $ldap->getUser($_SESSION['uid'], ['signedsir']);
} catch (LdapException $e) {
$error = $e->getMessage();
}

$template = Template::create();
$template->addData(['currentSection' => 'index'], 'navbar');
echo $template->render('index', [
'error' => $error,
'uid' => $_SESSION['uid'],
'id' => $_SESSION['id'],
'name' => $_SESSION['cn']
'name' => $_SESSION['cn'],
'signedSir' => Ldap::optionalBooleanToBool($attributes, 'signedsir')
]);
4 changes: 2 additions & 2 deletions public/personal.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@
header('Content-Type: application/json');
header('Content-Transfer-Encoding: Binary');
header('Content-Description: File Transfer');
header("Content-Disposition: attachment; filename=${_SESSION['uid']}.json");
header("Content-Disposition: attachment; filename={$_SESSION['uid']}.json");
echo json_encode($attributes, JSON_PRETTY_PRINT);
exit;
}

if (isset($_POST) && !empty($_POST)) {
if (!empty($_POST)) {
Validation::handleUserEditPost($editableAttributes, $ldap, $_SESSION['uid'], $attributes);
http_response_code(303);
header('Location: personal.php');
Expand Down
2 changes: 1 addition & 1 deletion public/sir.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

require '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
Authentication::requireLogin();
if (!Authentication::isAdmin()) {
if (!Authentication::isAdmin() && !isset($_GET['uid']) && $_GET['uid'] !== $_SESSION['uid']) {
$template = Template::create();
echo $template->render('403');
exit;
Expand Down
49 changes: 49 additions & 0 deletions public/sugo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace WEEEOpen\Crauto;

require '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
Authentication::requireLogin();

$ldap = new Ldap(
CRAUTO_LDAP_URL,
CRAUTO_LDAP_BIND_DN,
CRAUTO_LDAP_PASSWORD,
CRAUTO_LDAP_USERS_DN,
CRAUTO_LDAP_GROUPS_DN,
CRAUTO_LDAP_STARTTLS
);

$selectedUser = null;
if (Authentication::isAdmin()) {
$users = $ldap->getUsers(['givenname', 'sn', 'signedsir', 'nsaccountlock', 'mail']);
if (isset($_GET['uid'])) {
$selectedUser = $_GET['uid'];
}
} else {
$users = [$ldap->getUser($_SESSION['uid'], ['givenname', 'sn', 'signedsir', 'nsaccountlock', 'mail'])];
$selectedUser = $_SESSION['uid'];
}

$mappedUsers = [];
foreach ($users as $user) {
$mappedUsers[] = [
'uid' => $user['uid'],
'cn' => $user['cn'],
'needsToSign' => Ldap::optionalBooleanToBool($user, 'signedsir'),
'isLocked' => Ldap::optionalBooleanToBool($user, 'nsaccountlock'),
'email' => $user['mail']
];
}

usort($mappedUsers, function (array $a, array $b): int {
return strcasecmp($a['uid'], $b['uid']);
});

$template = Template::create();
$template->addData(['currentSection' => 'sugo'], 'navbar');

echo $template->render('sugo', [
'users' => $mappedUsers,
'selectedUser' => $selectedUser
]);
50 changes: 41 additions & 9 deletions src/Authentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,38 @@ public static function authenticate()
session_start();
}

if (defined('TEST_MODE') && TEST_MODE) {
if (TEST_MODE) {
error_log('TEST_MODE, faking authentication');
$_SESSION['uid'] = 'test.administrator';
$_SESSION['id'] = 'fake:example:68048769-c06d-4873-adf6-dbfa6b0afcd3';
$_SESSION['cn'] = 'Test Administrator';
$_SESSION['groups'] = ['HR'];
$_SESSION['expires'] = PHP_INT_MAX;
$_SESSION['refresh_token'] = 'refresh_token';
$_SESSION['id_token'] = 'id_token';
switch (TEST_MODE_SSO) {
case 1:
default:
$_SESSION['uid'] = 'test.administrator';
$_SESSION['id'] = 'fake:example:68048769-c06d-4873-adf6-dbfa6b0afcd3';
$_SESSION['cn'] = 'Test Administrator';
$_SESSION['groups'] = ['HR'];
$_SESSION['expires'] = PHP_INT_MAX;
$_SESSION['refresh_token'] = 'refresh_token';
$_SESSION['id_token'] = 'id_token';
break;
case 2:
$_SESSION['uid'] = 'alice';
$_SESSION['id'] = 'fake:example:9e071e1e-d0dd-4d58-9ac2-087ea0b41e97';
$_SESSION['cn'] = 'Alice Test';
$_SESSION['groups'] = ['Cloud', 'Gente', 'Riparatori'];
$_SESSION['expires'] = PHP_INT_MAX;
$_SESSION['refresh_token'] = 'refresh_token';
$_SESSION['id_token'] = 'id_token';
break;
case 3:
$_SESSION['uid'] = 'brodino';
$_SESSION['id'] = 'fake:example:c476f0de-e554-439e-af4f-35c8bed02b9b';
$_SESSION['cn'] = 'Bro Dino';
$_SESSION['groups'] = ['Admin', 'Gente'];
$_SESSION['expires'] = PHP_INT_MAX;
$_SESSION['refresh_token'] = 'refresh_token';
$_SESSION['id_token'] = 'id_token';
break;
}
} else {
$oidc = self::getOidc();
//$oidc->setCertPath('/path/to/my.cert');
Expand All @@ -110,7 +133,7 @@ public static function signOut()
$token = $_SESSION['id_token'];
session_destroy();

if (defined('TEST_MODE') && TEST_MODE) {
if (TEST_MODE) {
error_log('TEST_MODE, no need to log out');
} else {
$oidc->signOut($token, CRAUTO_URL . '/logout_done.php');
Expand Down Expand Up @@ -307,6 +330,15 @@ private static function setAttributes(OpenIDConnectClient $oidc, $claims = null,
$refresh_token = $oidc->getRefreshToken();
$id_token = $idt ?? $oidc->getIdToken();

$ldap = new Ldap(
CRAUTO_LDAP_URL,
CRAUTO_LDAP_BIND_DN,
CRAUTO_LDAP_PASSWORD,
CRAUTO_LDAP_USERS_DN,
CRAUTO_LDAP_GROUPS_DN,
CRAUTO_LDAP_STARTTLS
);

$_SESSION['uid'] = $uid;
$_SESSION['id'] = $id;
$_SESSION['cn'] = $cn;
Expand Down
48 changes: 42 additions & 6 deletions src/Ldap.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use DateTime;
use DateTimeZone;
use InvalidArgumentException;
use LDAP\Result;

class Ldap
{
Expand All @@ -24,6 +25,7 @@ class Ldap
'createtimestamp' => '20191025105022Z',
'modifytimestamp' => '20191025155317Z',
'safetytestdate' => '20160909',
'degreecourse' => 'Ingegneria dell\'Ingegno',
'signedsir' => 'true',
'haskey' => 'true',
'schacpersonaluniquecode' => 's111111',
Expand All @@ -33,7 +35,8 @@ class Ldap
'weeelabnickname' => ['io'],
'websitedescription' => "Il capo supremo\nSu due righe",
'description' => '',
'nsaccountlock' => null
'nsaccountlock' => null,
'mail' => '[email protected]',
],
'alice' => [
'uid' => 'alice',
Expand All @@ -44,6 +47,7 @@ class Ldap
'createtimestamp' => '20191025105022Z',
'modifytimestamp' => '20191025155317Z',
'safetytestdate' => '20991104',
'degreecourse' => 'Architettura (dei calcolatori però)',
'signedsir' => null,
'haskey' => null,
'schacpersonaluniquecode' => 's22222',
Expand All @@ -53,7 +57,8 @@ class Ldap
'weeelabnickname' => [],
'websitedescription' => 'Persona',
'description' => '',
'nsaccountlock' => 'true'
'nsaccountlock' => 'true',
'mail' => '[email protected]',
],
'brodino' => [
'uid' => 'brodino',
Expand All @@ -64,6 +69,7 @@ class Ldap
'createtimestamp' => '20191025105022Z',
'modifytimestamp' => '20191025155317Z',
'safetytestdate' => '20201104',
'degreecourse' => 'Ingegneria dell\'Ingegnerizzazione',
'signedsir' => 'true',
'haskey' => null,
'nsaccountlock' => 'true',
Expand All @@ -72,7 +78,8 @@ class Ldap
'sshpublickey' => [],
'weeelabnickname' => [],
'description' => '',
'telegramnickname' => 'brodino'
'telegramnickname' => 'brodino',
'mail' => '[email protected]',
],
'bob' => [
'uid' => 'bob',
Expand All @@ -92,7 +99,8 @@ class Ldap
'sshpublickey' => [],
'weeelabnickname' => [],
'description' => '',
'nsaccountlock' => null
'nsaccountlock' => null,
'mail' => '[email protected]',
],
'broski' => [
'uid' => 'broski',
Expand All @@ -103,6 +111,7 @@ class Ldap
'createtimestamp' => '20191025105022Z',
'modifytimestamp' => '20191025155317Z',
'safetytestdate' => '20201025',
'degreecourse' => 'Ingegneria dell\'Ingegnerizzazione',
'signedsir' => null,
'haskey' => null,
'nsaccountlock' => null,
Expand All @@ -111,7 +120,29 @@ class Ldap
'sshpublickey' => [],
'weeelabnickname' => [],
'description' => '',
'telegramid' => '123456789'
'telegramid' => '123456789',
'mail' => '[email protected]',
],
'brobruh' => [
'uid' => 'brobruh',
'cn' => 'Bro Bruh',
'givenname' => 'Bro',
'sn' => 'Bruh',
'memberof' => ["cn=Admin,ou=Groups,dc=weeeopen,dc=it", "cn=Gente,ou=Groups,dc=weeeopen,dc=it"],
'createtimestamp' => '20191025105022Z',
'modifytimestamp' => '20191025155317Z',
'safetytestdate' => '20210926',
'degreecourse' => 'Ingegneria Disinformatica',
'signedsir' => null,
'haskey' => null,
'nsaccountlock' => 'true',
'schacpersonaluniquecode' => 's333444555666',
'telegramnickname' => null,
'sshpublickey' => [],
'weeelabnickname' => [],
'description' => '',
'telegramid' => '12345678912345',
'mail' => '[email protected]',
],
];
private const EXAMPLE_GROUPS = ['Admin', 'Persone', 'Cloud'];
Expand Down Expand Up @@ -264,7 +295,7 @@ public function getUsers(array $attributes): array
* @param string $uid UID to search
* @param array|null $attributes Attributes to include in search result ("null" for all)
*
* @return resource|null $sr from ldap_search or none if no users are found
* @return array|Result|null $sr from ldap_search or none if no users are found
* @throws LdapException if cannot search or more than one user is found
*/
private function searchByUid(string $uid, ?array $attributes = null)
Expand Down Expand Up @@ -484,6 +515,11 @@ public static function groupDnToName(string $dn): string
throw new InvalidArgumentException("$dn is not a group DN");
}

public static function optionalBooleanToBool(array $attributes, string $var): bool
{
return isset($attributes[$var]) && $attributes[$var] === 'true';
}

public function groupNamesToDn(array $names): array
{
if (count($names) <= 0) {
Expand Down
2 changes: 1 addition & 1 deletion src/Template.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ public static function telegramColumn($nickname, $id): string
public static function shortListEntry(string $uid, string $cn, ?string $schacpersonaluniquecode): string
{
$schacpersonaluniquecode = $schacpersonaluniquecode ?? 'no matricola';
return /** @lang HTML */ "<a href=\"/people.php?uid=$uid\">$cn</a>, $schacpersonaluniquecode <a class=\"btn btn-sm btn-outline-dark m-1 p-1\" href=\"/sir.php?uid=$uid\"><i class=\"fa fa-download mr-1\"></i>Get SIR</a>";
return /** @lang HTML */ "<a href=\"/people.php?uid=$uid\">$cn</a>, $schacpersonaluniquecode <a class=\"btn btn-sm btn-outline-dark m-1 p-1\" href=\"/sugo.php?uid=$uid\"><i class=\"fa-solid fa-signature\"></i>Sign SIR</a>";
}
}
10 changes: 10 additions & 0 deletions templates/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@
/** @var $uid string */
/** @var $id string */
/** @var $name string */
/** @var $signedSir bool */
/** @var $error string|null */
$this->layout('base', ['title' => 'Welcome']) ?>

<h1>Crauto</h1>
<small>Creatore e Rimuovitore Autogestito di Utenti che Tutto Offre</small>
<p>Hi <?= $name ?>, your username is <?= $uid ?> and your ID is <?= $id ?></p>
<?php if ($error !== null) : ?>
<div class="alert alert-danger" role="alert">
Error: <?= $this->e($error) ?>
</div>
<?php endif ?>
<?php if (!$signedSir) : ?>
<p class="alert alert-warning">You need to sign your SIR! <a href="/sugo.php?uid=<?= urlencode($uid)?>" class="btn btn-sm btn-warning">Sign the SIR</a></p>
<?php endif ?>
<h2>Enabled services</h2>
<p>What can I access with this account?</p>
<ul>
Expand Down
3 changes: 3 additions & 0 deletions templates/navbar.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
<a class="nav-link <?= $currentSection === 'groups' ? 'active' : '' ?>" href="/groups.php">Groups</a>
</li>
<?php endif ?>
<li class="nav-item">
<a class="nav-link <?= $currentSection === 'sugo' ? 'active' : '' ?>" href="/sugo.php">SIR</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/logout.php">Logout</a>
</li>
Expand Down
Loading
Loading