Compare commits

...

7 Commits

23 changed files with 199 additions and 35 deletions

View File

@ -2,7 +2,7 @@
defaults_service_provider:
type: "legal" # Accepted Values: natural, legal
company:
titel: "CyMaIS GbR"
titel: "CyMaIS by Kevin Veen-Birkenbach"
slogan: "CyMaIS — Empowering a Sovereign Digital Future."
address:
street: "Binary Avenue 01"

15
main.py
View File

@ -162,12 +162,17 @@ if __name__ == "__main__":
text=True
)
os.close(slave_fd)
import errno
with os.fdopen(master_fd) as master:
for line in master:
ts = datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
log_file.write(f"{ts} {line}")
log_file.flush()
print(line, end='')
try:
for line in master:
ts = datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
log_file.write(f"{ts} {line}")
log_file.flush()
print(line, end='')
except OSError as e:
if e.errno != errno.EIO:
raise
proc.wait()
rc = proc.returncode
else:

View File

@ -1,16 +1,27 @@
- name: Check if docker is installed
ansible.builtin.stat:
path: /usr/bin/docker
register: docker_bin
- name: "pkgmgr install"
include_role:
name: pkgmgr-install
vars:
package_name: dockreap
when: run_once_cleanup_docker_anonymous_volumes is not defined
when:
- run_once_cleanup_docker_anonymous_volumes is not defined
- docker_bin.stat.exists
- name: run dockreap with --no-confirmation
command:
cmd: "dockreap --no-confirmation"
when: run_once_cleanup_docker_anonymous_volumes is not defined
when:
- run_once_cleanup_docker_anonymous_volumes is not defined
- docker_bin.stat.exists
- name: mark dockreap as run
set_fact:
run_once_cleanup_docker_anonymous_volumes: true
when: run_once_cleanup_docker_anonymous_volumes is not defined
when:
- run_once_cleanup_docker_anonymous_volumes is not defined
- docker_bin.stat.exists

View File

@ -0,0 +1,5 @@
# Administration
## Logs
The logs you will find here on the host: **/var/lib/docker/volumes/nextcloud_data/_data/data/nextcloud.log**

View File

@ -49,7 +49,7 @@ http {
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
# set max upload size
client_max_body_size 512M;

View File

@ -1,6 +1,6 @@
configuration_file: "oauth2-proxy-keycloak.cfg" # Needs to be set true in the roles which use it
version: "latest" # Docker Image version
allowed_roles: admin # Restrict it default to admin role. Use the vars/main.yml to open the specific role for other groups
allowed_roles: "admin" # Restrict it default to admin role. Use the vars/main.yml to open the specific role for other groups
features:
matomo: true
css: true

View File

@ -2,6 +2,11 @@ version: "13" # Update when available. Sadly no rolling release
oauth2_proxy:
application: "proxy"
port: "80"
acl:
whitelist:
- "/users/me" # Necessary for Nextcloud Plugin to work
- "/api/" # Necessary for Nextcloud Plugin to work
- "/oauth/token" # Necessary for Nextcloud Plugin to work
ldap:
filters:
administrators: True # Set true to filter administrators

View File

@ -114,5 +114,8 @@ class LookupModule(LookupBase):
cards.append(card)
# Sort A-Z
cards.sort(key=lambda c: c['title'].lower())
# Return the list of cards
return [cards]

View File

@ -43,9 +43,10 @@
- name: Debug portfolio data
debug:
msg:
portfolio_cards: "{{ portfolio_cards }}"
portfolio_menu_categories: "{{ portfolio_menu_categories}}"
portfolio_menu_data: "{{ portfolio_menu_data }}"
portfolio_cards: "{{ portfolio_cards }}"
portfolio_menu_categories: "{{ portfolio_menu_categories}}"
portfolio_menu_data: "{{ portfolio_menu_data }}"
service_provider: "{{ service_provider }}"
when:
- enable_debug | bool
- run_once_docker_portfolio is not defined

View File

@ -93,7 +93,7 @@ platform:
source: {{service_provider.platform.favicon}}
company:
titel: {{service_provider.company.titel}}
subtitel: {{service_provider.company.subtitel}}
subtitel: {{service_provider.company.slogan}}
logo:
source: {{service_provider.company.logo}}
address:

View File

@ -5,7 +5,9 @@ version: "latest"
oauth2_proxy:
application: "application"
port: "80"
location: "/admin/" # Protects the admin area
acl:
blacklist:
- "/admin/" # Protects the admin area
features:
matomo: true
css: true

View File

@ -1,5 +1,5 @@
- name: reload health-msmtp.cymais.service
- name: "reload health-journalctl.cymais.service"
systemd:
name: health-msmtp.cymais.service
name: health-journalctl.cymais.service
enabled: yes
daemon_reload: yes

View File

@ -1,5 +1,5 @@
- name: "reload health-journalctl.cymais.service"
- name: reload health-msmtp.cymais.service
systemd:
name: health-journalctl.cymais.service
name: health-msmtp.cymais.service
enabled: yes
daemon_reload: yes
daemon_reload: yes

View File

@ -15,21 +15,47 @@ server
{% include 'roles/letsencrypt/templates/ssl_header.j2' %}
{% if applications | is_feature_enabled('oauth2',application_id) %}
{% if applications[application_id].oauth2_proxy.location is defined %}
{# Exposed and Unprotected Location #}
{% if applications | is_feature_enabled('oauth2', application_id) %}
{% set acl = applications[application_id].oauth2_proxy.acl | default({}) %}
{% if acl.blacklist is defined %}
{# 1. Expose everything by default, then protect blacklisted paths #}
{% set oauth2_proxy_enabled = false %}
{% set location = "/" %}
{% include 'roles/nginx-docker-reverse-proxy/templates/location/proxy_basic.conf.j2' %}
{% for loc in acl.blacklist %}
{% set oauth2_proxy_enabled = true %}
{% set location = loc %}
{% include 'roles/nginx-docker-reverse-proxy/templates/location/proxy_basic.conf.j2' %}
{% endfor %}
{% elif acl.whitelist is defined %}
{# 2. Protect everything by default, then expose whitelisted paths #}
{% set oauth2_proxy_enabled = true %}
{% set location = applications[application_id].oauth2_proxy.location %}
{# Gated Location by OAuth2 Proxy #}
{% set location = "/" %}
{% include 'roles/nginx-docker-reverse-proxy/templates/location/proxy_basic.conf.j2' %}
{% for loc in acl.whitelist %}
{% set oauth2_proxy_enabled = false %}
{% set location = loc %}
{% include 'roles/nginx-docker-reverse-proxy/templates/location/proxy_basic.conf.j2' %}
{% endfor %}
{% else %}
{# 3. OAuth2 enabled but no (or empty) ACL — protect all #}
{% set oauth2_proxy_enabled = true %}
{# Protected Domain by OAuth2 Proxy #}
{% include 'roles/nginx-docker-reverse-proxy/templates/location/proxy_basic.conf.j2'%}
{% set location = "/" %}
{% include 'roles/nginx-docker-reverse-proxy/templates/location/proxy_basic.conf.j2' %}
{% endif %}
{% else %}
{# Exposed Domain - Not protected by OAuth2 Proxy #}
{# 4. OAuth2 completely disabled — expose all #}
{% set oauth2_proxy_enabled = false %}
{% set location = "/" %}
{% include 'roles/nginx-docker-reverse-proxy/templates/location/proxy_basic.conf.j2' %}
{% endif %}
}

View File

@ -1198,4 +1198,9 @@ input.ng-empty::placeholder,.ng-empty::placeholder {
.navbar-toggler {
background-color: rgba(var(--color-rgb-01-75), 0.9);
border-color: var(--color-01-67)
}
.alert-info {
--bs-alert-color: var(--color-03-14);
--bs-alert-bg: var(--color-01-86);
}

View File

@ -12,9 +12,9 @@ server
location /
{
alias {{nginx.directories.data.files}}; {# Path to your file directory #}
autoindex on; {# Enable directory listing #}
autoindex_exact_size off; {# Display sizes in a human-readable format #}
autoindex_localtime on; {# Show local time #}
autoindex on; {# Enable directory listing #}
autoindex_exact_size off; {# Display sizes in a human-readable format #}
autoindex_localtime on; {# Show local time #}
}
location /.well-known/ {

View File

@ -11,7 +11,7 @@
<h2>Information in accordance with § 5 TMG</h2>
<p>
<strong>{{ service_provider.company.titel }}</strong><br>
{{ service_provider.company.subtitel }}<br>
{{ service_provider.company.slogan }}<br>
<br>
<strong>Address:</strong><br>
{{ service_provider.company.address.street }}<br>

View File

@ -35,3 +35,4 @@ galaxy_info:
dependencies:
- git
- make
- python-yaml

View File

@ -0,0 +1,20 @@
# Python-Yaml
## Description
This Ansible role installs the **python-yaml** package on the target system. It ensures that the Python `yaml` library is available for loading and processing YAML files.
## Overview
Optimized for simplicity and idempotency, this role provides:
- Installation of the `python-yaml` package via the Pacman package manager.
- A mechanism to run the installation only once.
## Purpose
The purpose of this role is to reliably provide the Python-YAML package so that Python scripts can work with YAML files.
## Features
- **YAML Support:** Installs the `python-yaml` package, which supplies the `yaml` library for Python.
- **Idempotency:** Uses a fact to ensure that the installation runs only on the first execution.

View File

@ -0,0 +1,24 @@
galaxy_info:
author: "Kevin Veen-Birkenbach"
description: >
Installs the `python-yaml` package to enable YAML support in Python.
license: "CyMaIS NonCommercial License (CNCL)"
license_url: "https://s.veen.world/cncl"
company: |
Kevin Veen-Birkenbach
Consulting & Coaching Solutions
https://www.veen.world
min_ansible_version: "2.9"
platforms:
- name: Archlinux
versions:
- rolling
galaxy_tags:
- python
- yaml
- package
- installation
- automation
repository: "https://s.veen.world/cymais"
issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais"

View File

@ -0,0 +1,11 @@
---
- name: python-yaml install
pacman:
name: python-yaml
state: present
when: run_once_python_yaml is not defined
- name: run the python_yaml tasks once
set_fact:
run_once_python_yaml: true
when: run_once_python_yaml is not defined

View File

@ -35,7 +35,7 @@
{{
defaults_applications |
canonical_domains_map(primary_domain) |
combine(domains | default({}, true), recursive=True)
combine(current_play_domains, recursive=True)
}}
- name: Merge redirect_domain_mappings
@ -44,7 +44,7 @@
redirect_domain_mappings: "{{
[] |
add_redirect_if_group('assets-server', domains | get_domain('assets-server'), domains | get_domain('file-server'), group_names) |
merge_mapping(redirect_domain_mappings, 'source')
merge_mapping(redirect_domain_mappings| default([]), 'source')
}}"
- name: Set current play redirect domain mappings

View File

@ -0,0 +1,45 @@
import os
import yaml
import unittest
from pathlib import Path
ROLES_DIR = Path(__file__).resolve().parent.parent.parent / "roles"
class TestOauth2AclMutualExclusion(unittest.TestCase):
def test_acl_has_either_whitelist_or_blacklist(self):
failures = []
for role_path in ROLES_DIR.iterdir():
vars_file = role_path / "vars" / "configuration.yml"
if not vars_file.exists():
continue
# open the YAML file instead of passing the Path object
try:
with open(vars_file) as f:
data = yaml.safe_load(f) or {}
except yaml.YAMLError as e:
failures.append(f"{role_path.name}: failed to parse YAML ({e})")
continue
oauth2 = data.get("oauth2_proxy", {})
acl = oauth2.get("acl", None)
if acl is None:
continue
has_wl = "whitelist" in acl
has_bl = "blacklist" in acl
if has_wl and has_bl:
failures.append(
f"{role_path.name}: both 'whitelist' and 'blacklist' are defined"
)
if failures:
self.fail(
"The following roles define both whitelist and blacklist under oauth2_proxy.acl:\n"
+ "\n".join(failures)
)
if __name__ == "__main__":
unittest.main()