summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-05-27 00:29:36 -0400
committerFreya Murphy <freya@freyacat.org>2024-05-27 00:29:36 -0400
commitcb9d1193c37b7567dcad5497330169d43ab1e8a2 (patch)
tree41fea58928d5d4cf87306458114f5465b6620711
downloadldap_forwardauth-cb9d1193c37b7567dcad5497330169d43ab1e8a2.tar.gz
ldap_forwardauth-cb9d1193c37b7567dcad5497330169d43ab1e8a2.tar.bz2
ldap_forwardauth-cb9d1193c37b7567dcad5497330169d43ab1e8a2.zip
initial
-rw-r--r--.gitignore1
-rw-r--r--build/nginx/Dockerfile21
-rw-r--r--build/php/Dockerfile16
-rw-r--r--conf/ldap/ldap.env9
-rw-r--r--conf/nginx/nginx.conf50
-rw-r--r--docker-compose.yml21
-rw-r--r--src/public/bg.jpgbin0 -> 425136 bytes
-rw-r--r--src/public/main.css70
-rw-r--r--src/web/helpers/auth.php59
-rw-r--r--src/web/helpers/ldap.php41
-rw-r--r--src/web/index.php66
-rw-r--r--src/web/views/footer.php4
-rw-r--r--src/web/views/header.php13
-rw-r--r--src/web/views/login.php22
-rw-r--r--src/web/views/message.php1
15 files changed, 394 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1269488
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+data
diff --git a/build/nginx/Dockerfile b/build/nginx/Dockerfile
new file mode 100644
index 0000000..6aa4e00
--- /dev/null
+++ b/build/nginx/Dockerfile
@@ -0,0 +1,21 @@
+FROM alpine:3.19
+
+# install packages
+RUN apk add --no-cache nginx shadow tini
+RUN rm -fr /var/cache/apk/*
+
+# update nginx user
+RUN groupmod --gid 1000 nginx
+RUN usermod --uid 1000 nginx
+
+# remove build packages
+RUN apk del shadow
+
+# make log syms
+RUN ln -sf /dev/stdout /var/log/nginx/access.log && \
+ ln -sf /dev/stderr /var/log/nginx/error.log
+
+# do the
+USER nginx
+ENTRYPOINT ["/sbin/tini", "--"]
+CMD ["/usr/sbin/nginx", "-c", "/etc/nginx/nginx.conf"]
diff --git a/build/php/Dockerfile b/build/php/Dockerfile
new file mode 100644
index 0000000..252e516
--- /dev/null
+++ b/build/php/Dockerfile
@@ -0,0 +1,16 @@
+FROM php:fpm-alpine
+
+# install packages
+RUN apk add --no-cache runuser shadow openldap-dev
+RUN rm -fr /var/cache/apk/*
+
+# update php user
+RUN groupmod --gid 1000 www-data
+RUN usermod --uid 1000 www-data
+
+# install php packages
+RUN docker-php-ext-install ldap
+
+# remove build packages
+RUN apk del shadow
+USER www-data
diff --git a/conf/ldap/ldap.env b/conf/ldap/ldap.env
new file mode 100644
index 0000000..f387147
--- /dev/null
+++ b/conf/ldap/ldap.env
@@ -0,0 +1,9 @@
+
+LDAP_URL=
+LDAP_BIND_DN=
+LDAP_BIND_PASSWORD=
+LDAP_BASE_DN=
+LDAP_FILTER="(&)"
+LDAP_UID="cn"
+
+HTTP_HOST=auth.example.com
diff --git a/conf/nginx/nginx.conf b/conf/nginx/nginx.conf
new file mode 100644
index 0000000..ae17eba
--- /dev/null
+++ b/conf/nginx/nginx.conf
@@ -0,0 +1,50 @@
+worker_processes 4;
+daemon off;
+pid /tmp/nginx.pid;
+error_log /var/log/nginx/error.log;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+ sendfile on;
+ keepalive_timeout 70;
+ server_tokens off;
+ client_max_body_size 2m;
+
+ access_log /var/log/nginx/access.log;
+
+ server {
+ listen 8080;
+ root /opt/website;
+
+ gzip on;
+ gzip_vary on;
+ gzip_proxied any;
+ gzip_comp_level 6;
+ gzip_buffers 16 8k;
+ gzip_http_version 1.1;
+ gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;
+
+ location /favicon.ico {
+ add_header Cache-Control "public, max-age=31536000, immutable";
+ root /opt/website/public/icons;
+ }
+
+ location /public {
+ add_header Cache-Control "public, max-age=31536000, immutable";
+ try_files $uri =404;
+ }
+
+ location / {
+ add_header Content-Security-Policy "script-src 'none'; object-src 'none'; base-uri 'none'";
+ root /opt/website/web;
+ include fastcgi_params;
+ fastcgi_pass php:9000;
+ fastcgi_param SCRIPT_FILENAME $document_root/index.php;
+ }
+ }
+}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..8c35bad
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,21 @@
+services:
+
+ web:
+ build: ./build/nginx
+ restart: unless-stopped
+ ports:
+ - '80:8080'
+ volumes:
+ - ./src:/opt/website:ro
+ - ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
+ depends_on:
+ - php
+
+ php:
+ build: ./build/php
+ restart: unless-stopped
+ env_file:
+ - ./conf/ldap/ldap.env
+ volumes:
+ - ./src:/opt/website:ro
+ - ./data/session:/var/lib/php/session
diff --git a/src/public/bg.jpg b/src/public/bg.jpg
new file mode 100644
index 0000000..98ef823
--- /dev/null
+++ b/src/public/bg.jpg
Binary files differ
diff --git a/src/public/main.css b/src/public/main.css
new file mode 100644
index 0000000..058a49e
--- /dev/null
+++ b/src/public/main.css
@@ -0,0 +1,70 @@
+
+:root {
+ --blue: rgb(0, 102, 204);
+}
+
+* {
+ box-sizing: border-box;
+}
+
+html, body {
+ height: 100%;
+ padding: 0;
+ margin: 0;
+}
+
+body {
+ display: flex;
+ justify-content: center;
+ background: #898989;
+ background-image: url('./bg.jpg');
+ background-size: 100%;
+ background-position: 50% 50%;
+ color: #fff;
+ font-family: "Open Sans", Helvetica, Arial, sans-serif;
+ font-weight: 100;
+ font-size: 12px;
+}
+
+main {
+ margin-top: 20vh;
+ height: fit-content;
+ width: 400px;
+ background: #fff;
+ color: #000;
+}
+
+main .heading {
+ border-top: 5px solid var(--blue);
+ font-size: 1.5rem;
+ text-align: center;
+ padding: 10px;
+}
+
+main .content {
+ padding: 10px;
+}
+
+main .content, form {
+ display: flex;
+ flex-direction: column;
+}
+
+main label,
+main #submit {
+ margin-top: 10px;
+}
+
+main input {
+ border: 1px solid #ddd;
+ outline: none;
+ padding: 7px;
+ font-size: 14px;
+ border-bottom-color: black;
+}
+
+main #submit {
+ background: var(--blue);
+ color: white;
+ cursor: pointer;
+}
diff --git a/src/web/helpers/auth.php b/src/web/helpers/auth.php
new file mode 100644
index 0000000..7aa4aff
--- /dev/null
+++ b/src/web/helpers/auth.php
@@ -0,0 +1,59 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+$keys = array();
+
+function load_key($key) {
+ $file = "/tmp/$key";
+ if (!file_exists($file))
+ return FALSE;
+ $content = explode("\n", file_get_contents($file));
+ return array(
+ 'user' => $content[0],
+ 'time' => $content[1]
+ );
+}
+
+function store_key($key, $user) {
+ $file = "/tmp/$key";
+ $now = (string)time();
+ $content = "$user\n{$now}";
+ file_put_contents($file, $content, LOCK_EX);
+}
+
+function get_random($n)
+{
+ $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ $randomString = '';
+
+ for ($i = 0; $i < $n; $i++) {
+ $index = rand(0, strlen($characters) - 1);
+ $randomString .= $characters[$index];
+ }
+
+ return $randomString;
+}
+
+function key_auth() {
+ if (!isset($_SESSION['auth'])) {
+ return FALSE;
+ }
+ $key = $_SESSION['auth'];
+ $data = load_key($key);
+ if ($data === FALSE) {
+ return FALSE;
+ }
+ $user = $data['user'];
+ $time = $data['time'];
+ $now = time();
+ if ($time > $now || $now - $time > 60 * 60 * 24) {
+ return FALSE;
+ }
+ store_key($key, $user);
+ return $user;
+}
+
+function key_new($user) {
+ $key = get_random(128);
+ store_key($key, $user);
+ $_SESSION['auth'] = $key;
+}
diff --git a/src/web/helpers/ldap.php b/src/web/helpers/ldap.php
new file mode 100644
index 0000000..f3697cc
--- /dev/null
+++ b/src/web/helpers/ldap.php
@@ -0,0 +1,41 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+function ldap_auth($auth_username, $auth_password) {
+ $url = getenv("LDAP_URL");
+ $bind = getenv("LDAP_BIND_DN");
+ $password = getenv("LDAP_BIND_PASSWORD");
+ $bound = getenv("LDAP_BASE_DN");
+ $filter = getenv("LDAP_FILTER");
+ $uid = getenv("LDAP_UID");
+
+ $conn = @ldap_connect($url);
+ if (!$conn) {
+ return NULL;
+ }
+ ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
+
+ $bind_conn = @ldap_bind($conn, $bind, $password);
+ if (!$bind_conn) {
+ return NULL;
+ }
+
+ $search = @ldap_search($conn, $bound, $filter);
+
+ $info = @ldap_get_entries($conn, $search);
+ $user = NULL;
+ for ($i=0; $i<$info['count']; $i++) {
+ $user = $info[$i];
+ if (!array_key_exists($uid, $user))
+ continue;
+ if ($user[$uid][0] == $auth_username)
+ break;
+ }
+
+ if ($user == NULL) {
+ return FALSE;
+ }
+
+ $succ = @ldap_bind($conn, $user['dn'], $auth_password);
+ return !!$succ;
+}
+
diff --git a/src/web/index.php b/src/web/index.php
new file mode 100644
index 0000000..ffd6b06
--- /dev/null
+++ b/src/web/index.php
@@ -0,0 +1,66 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+ini_set('html_errors', '1');
+
+$webroot = dirname(__FILE__);
+$publicroot = realpath(dirname(__FILE__) . '/../public');
+
+// load stuff
+require($webroot . '/helpers/ldap.php');
+require($webroot . '/helpers/auth.php');
+
+// start session
+session_set_cookie_params(
+ 60 * 60 * 24, // lifetime (seconds),
+ '/', // path
+ NULL, // domain,
+ TRUE, // secure,
+ TRUE // http only
+);
+session_start();
+
+function page($file, $data = array()) {
+ extract($data);
+ $webroot = $GLOBALS['webroot'];
+ require($webroot . '/views/header.php');
+ require($webroot . "/views/$file.php");
+ require($webroot . '/views/footer.php');
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ parse_str(file_get_contents('php://input'), $post);
+ $res = ldap_auth($post['username'], $post['password']);
+ $msg = '';
+ $title = '';
+ if ($res) {
+ $msg = 'Authenticated. You can now go back to your content';
+ $title = 'Success';
+ key_new($post['username']);
+ } else {
+ $msg = 'Invalid Credentials';
+ $title = 'Error';
+ }
+ page('message', array(
+ 'title' => $title,
+ 'msg' => $msg
+ ));
+} else {
+ if (($user = key_auth())) {
+ http_response_code(200);
+ header("X-Webauth-User: $user");
+ die();
+ }
+
+ $host = $_SERVER['HTTP_HOST'];
+ $env = getenv("HTTP_HOST");
+ if ($host != $env) {
+ // we are being forwarded authed
+ // redirect
+ http_response_code(301);
+ header("Location: https://$env");
+ } else {
+ page('login', array(
+ 'title' => 'Login'
+ ));
+ }
+}
diff --git a/src/web/views/footer.php b/src/web/views/footer.php
new file mode 100644
index 0000000..eb7ee28
--- /dev/null
+++ b/src/web/views/footer.php
@@ -0,0 +1,4 @@
+<?php /* Copyright (c) 2024 Freya Murphy */ ?>
+ </main>
+ </body>
+</html>
diff --git a/src/web/views/header.php b/src/web/views/header.php
new file mode 100644
index 0000000..c0a0487
--- /dev/null
+++ b/src/web/views/header.php
@@ -0,0 +1,13 @@
+<?php /* Copyright (c) 2024 Freya Murphy */ ?>
+<!DOCTYPE html>
+<html>
+ <head>
+ <link href="//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&amp;subset=latin" rel="stylesheet">
+ <link rel="stylesheet" href="/public/main.css">
+ </head>
+ <body>
+ <main id="main" role="main">
+ <div class="heading">
+ <span><?=$title?></span>
+ </div>
+ <div class="content">
diff --git a/src/web/views/login.php b/src/web/views/login.php
new file mode 100644
index 0000000..98d69af
--- /dev/null
+++ b/src/web/views/login.php
@@ -0,0 +1,22 @@
+<?php /* Copyright (c) 2024 Freya Murphy */ ?>
+<form method="post">
+<label for="username">Username</label>
+<input
+ type="text"
+ id="username"
+ name="username"
+ autofocus="true"
+>
+<label fot="password">Password</label>
+<input
+ type="password"
+ id="password"
+ name="password"
+>
+<input
+ type="submit"
+ role="button"
+ id="submit"
+ value="Sign In"
+>
+<form>
diff --git a/src/web/views/message.php b/src/web/views/message.php
new file mode 100644
index 0000000..a071409
--- /dev/null
+++ b/src/web/views/message.php
@@ -0,0 +1 @@
+<center><?=$msg?></center>