Commit 0e9becf1 authored by Lukas Burgey's avatar Lukas Burgey

Merge branch 'userinfo-issuer' into hdf-portal-dev

parents 99ed51d6 06670e63
.secret.key
feudal/settings.py
env
static
deploy
runtest
__pycache__
config.env
dist
[submodule "webpage"]
path = webpage
url = https://git.scc.kit.edu/feudal/feudalWebpage
url = https://git.scc.kit.edu/feudal/feudalWebpage.git
This diff is collapsed.
PWD := $(shell pwd)
KEY := .secret.key
VENV := env
ADMIN := static
WEBPAGE := webpage
DIST := $(WEBPAGE)/dist
RPMBUILDROOT := $(PWD)/.rpmbuild
.PHONY: all $(WEBPAGE) rpm clean
all: $(ADMIN) $(DIST)
$(KEY):
dd if=/dev/urandom bs=64 count=1 | base64 > $@
$(VENV):
@python3.6 -m venv $@; \
source $@/bin/activate; \
pip -q install -U pip; \
pip -q install .
$(ADMIN): $(KEY) $(VENV)
@export DJANGO_SECRET=$< ; \
./manage.py collectstatic --no-input
$(WEBPAGE):
@git submodule update --init --force
$(DIST): $(WEBPAGE)
@$(MAKE) -C $^ prod
$(RPMBUILDROOT):
mkdir -p $@
rpm: $(DIST) $(ADMIN) $(RPMBUILDROOT)
@docker run \
--name feudal-rpmbuild \
--rm=true \
-v $(RPMBUILDROOT):/home/rpmbuilder/rpmbuild \
-v $(PWD)/feudal.spec:/home/rpmbuilder/rpmbuild/SPECS/feudal.spec \
-v $(PWD):/home/rpmbuilder/rpmbuild/SOURCES \
jc21/rpmbuild-centos7 \
/bin/build-spec /home/rpmbuilder/rpmbuild/SPECS/feudal.spec
@cp $(RPMBUILDROOT)/RPMS/noarch/*.rpm $(PWD)
clean:
@$(MAKE) -C webpage cleaner
@rm -rf $(ADMIN) $(VENV) $(RPMBUILDROOT)
FEderated User Credential Deployment PortAL (FEUDAL)
====
# FEderated User Credential Deployment PortAL (FEUDAL)
- User interface: [Webpage](https://git.scc.kit.edu/feudal/feudalWebpage)
- Component at the sites: [Client](https://git.scc.kit.edu/feudal/feudalClient)
Installation (Debian 9.6)
----
## Installation
- Needs Python 3.6 or higher
- `pip install git+https://git.scc.kit.edu/feudal/feudalBackend`
- Add some dependency repositories
- Add repository for Erlang 21 (e.g. from [here](https://www.rabbitmq.com/install-debian.html#bintray-apt-repo-erlang))
- Add repository for node.js v10.x (e.g. from [nodesource](https://github.com/nodesource/distributions#debinstall))
- Add a user for the backend
- `useradd -m $user`
- login as $user
- `git clone https://git.scc.kit.edu/feudal/feudalBackend $backend`
- `cd $backend`
- `cp config.env.default config.env`
- Adjust the default values where needed
- $backend needs to the directory this repo is cloned into
- $domain is the domain of your host machine
- Run `./install_privileged` as root
- Run `./install` as $user
Starting the backend
----
## Starting the backend
- systemctl start nginx rabbitmq-server (as root)
- systemctl --user start uwsgi
Checking the status of the backend
----
- `./status`
Runtime Configuration
----
## Runtime Configuration
- For runtime configuration we use the django inbuilt admin interface.
- Default path of the django admin: `/backend/admin`
- Default path of the django admin: `/backend/admin`
- The credentials for the admin were entered by you during the run of the `install` script
- Your OpenId Connect clients are configured in `Home > Backend > Oidc configs`
- The default redirect URI is: `/backend/auth/v1/callback`
......@@ -45,4 +22,3 @@ Runtime Configuration
- You can specify admin users
- You need to configure the `sites`, which provide services to your users in `Home > Backend > Sites`
- Configure your RabbitMQ instance in `Home > Backend > Rabbit mq instances`
#!/bin/sh
base=$(dirname "$0")
cd $base/..
RPMBUILDROOT=${RPMBUILDROOT-~/.rpmbuild}
mkdir -p $RPMBUILDROOT
SPEC=feudal.spec
docker run \
--name rpmbuild-centos7-feudal \
-v $RPMBUILDROOT:/home/rpmbuilder/rpmbuild \
-v $(pwd)/$SPEC:/home/rpmbuilder/rpmbuild/SPECS/$SPEC \
-v $(pwd):/home/rpmbuilder/rpmbuild/SOURCES \
--rm=true \
jc21/rpmbuild-centos7 \
/bin/build-spec /home/rpmbuilder/rpmbuild/SPECS/$SPEC
#!/bin/bash
# exit whole script
trap "exit" INT
# {{{ CONFIG FILES
config_file_default=./config.env.default
config_file=${1-./config.env}
if [[ ! -f $config_file ]]
then
echo "FEUDAL> Need the file with config variables!"
echo "FEUDAL> Adjust the file $config_file_default to your needs"
echo "FEUDAL> Copy the result to $config_file or provide the file name as parameter to this script"
exit 1
fi
# load config variables
source $config_file
if [[ $user != $(whoami) ]]
then
echo "FEUDAL> You need to run this script as user $user"
echo "FEUDAL> Exiting"
exit 1
fi
templates=$backend/config-templates
# the webpage is now a submodule
export webpage=$backend/webpage
export dist=$webpage/dist
mkdir -p $logs
echo "FEUDAL> Logs will be located at: $logs"
mkdir -p $config
echo "FEUDAL> Config files will be located at: $config"
# django settings
[[ $DEV ]] && export django_debug=True || export django_debug=False
echo "FEUDAL> Configuring $config/django_settings.py with DEBUG=$django_debug"
cat $templates/django_settings.py | envsubst > $config/django_settings.py
echo "FEUDAL> Configuring $backend/feudal/settings.py"
ln -sf $config/django_settings.py $backend/feudal/settings.py
# django secret key
if [[ ! -f $secret ]]
then
echo "FEUDAL> Generating secret key: $secret"
dd if=/dev/urandom bs=64 count=1 | base64 > $secret
fi
# uwsgi files
echo "FEUDAL> Configuring $uwsgi_ini"
cat $templates/uwsgi.ini | envsubst > $uwsgi_ini
echo "FEUDAL> Configuring $HOME/.local/share/systemd/user/uwsgi.service"
mkdir -p $HOME/.local/share/systemd/user
cat $templates/uwsgi.service | envsubst > $HOME/.local/share/systemd/user/uwsgi.service
echo "FEUDAL> Configuring $config/uwsgi_params"
cp $templates/uwsgi_params $config/uwsgi_params
echo "FEUDAL> Configuring $mysql"
cat $templates/mysql.cnf | envsubst > $mysql
echo "FEUDAL> Enabling uWSGI service"
mkdir -p $HOME/.config/systemd/user/default.target.wants
ln -s $systemd/uwsgi.service $HOME/.config/systemd/user/default.target.wants
# }}}
# {{{ PYTHON
echo "FEUDAL> Creating new python virtual environment: $venv"
python3.6 -m venv $venv
echo "FEUDAL> Activating virtual environment"
source $venv/bin/activate
pip -q install -U pip
pip install .
# }}}
# {{{ DJANGO
echo "FEUDAL> Starting database migration"
# makemigrations seems to be a bad idea here
# $backend/manage.py makemigrations backend
$backend/manage.py migrate
if [[ -d $static ]]
then
rm -rf $static
mkdir -p $static
fi
echo "FEUDAL> Preparing static files in $static"
$backend/manage.py collectstatic
# }}}
# {{{ WEBPAGE
cd $webpage
# this file get changed during building
git checkout package-lock.json
cd $backend
git submodule update --init
echo "FEUDAL> Changing directory to $webpage"
cd $webpage
echo "FEUDAL> Installing dependencies (using npm install)"
export npm_config_loglevel=error
npm install
ng=$webpage/node_modules/.bin/ng
ng_flags="--prod"
[[ -n $DEV ]] && ng_flags="--aot"
echo "FEUDAL> Building webpage (using $ng build $ng_flags)"
$ng build $ng_flags
# }}}
echo "FEUDAL>"
echo "FEUDAL> Done. Please check the output above for errors"
echo "FEUDAL>"
echo "FEUDAL> Here is how you can start the backend:"
echo "FEUDAL> Run as root: systemctl start nginx rabbitmq-server"
echo "FEUDAL> Run as $user: systemctl --user start uwsgi"
echo "FEUDAL>"
echo "FEUDAL> Here is how you can check the status of the backend:"
echo "FEUDAL> Run as $user: systemctl status nginx rabbitmq-server"
echo "FEUDAL> Run as $user: systemctl --user status uwsgi"
echo "FEUDAL>"
echo "FEUDAL> Have a nice day"
# vim: set foldmethod=marker :
#!/bin/bash
# vim: foldmethod=marker
#{{{ python 3.6
# enable additional repos
# subscription-manager repos --enable rhel-7-server-optional-rpms --enable rhel-server-rhscl-7-rpms
# install gcc and the like
# yum -y install @development
yum -y install @development python36 python36-devel python36-pip uwsgi-plugin-python36 epel-release
yum -y install mariadb-server mariadb-devel
#}}}
#{{{ rabbitmq 3.7
# erlang 21
curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | bash
# add rabbitmq packagecloud repo
curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.rpm.sh | bash
#}}}
yum -y install rabbitmq-server nginx
#{{{ mysql 5.7
yum install mysql-community-devel
#}}}
FEderated User Credential Deployment PortAL (FEUDAL)
====
- User interface: [Webpage](https://git.scc.kit.edu/feudal/feudalWebpage)
- Component at the sites: [Client](https://git.scc.kit.edu/feudal/feudalClient)
Installation (Debian 9.6)
----
- Add some dependency repositories
- Add repository for Erlang 21 (e.g. from [here](https://www.rabbitmq.com/install-debian.html#bintray-apt-repo-erlang))
- Add repository for node.js v10.x (e.g. from [nodesource](https://github.com/nodesource/distributions#debinstall))
- Add a user for the backend
- `useradd -m $user`
- login as $user
- `git clone https://git.scc.kit.edu/feudal/feudalBackend $backend`
- `cd $backend`
- `cp config.env.default config.env`
- Adjust the default values where needed
- $backend needs to the directory this repo is cloned into
- $domain is the domain of your host machine
- Run `./install_privileged` as root
- Run `./install` as $user
Starting the backend
----
- systemctl start nginx rabbitmq-server (as root)
- systemctl --user start uwsgi
Checking the status of the backend
----
- `./status`
Runtime Configuration
----
- For runtime configuration we use the django inbuilt admin interface.
- Default path of the django admin: `/backend/admin`
- The credentials for the admin were entered by you during the run of the `install` script
- Your OpenId Connect clients are configured in `Home > Backend > Oidc configs`
- The default redirect URI is: `/backend/auth/v1/callback`
- `scopes` is a list of strings (JSON)
- Users *and* FEUDAL Clients are managed in `Home > Backend > Users`
- You can manually add FEUDAL Clients
- You can specify admin users
- You need to configure the `sites`, which provide services to your users in `Home > Backend > Sites`
- Configure your RabbitMQ instance in `Home > Backend > Rabbit mq instances`
Name: feudal
Version: 0.1.0
Release: 1
Summary: FEUDAL
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
Prefix: %{_prefix}
BuildArch: noarch
Vendor: Lukas Burgey
Url: https://git.scc.kit.edu/feudal
License: MIT
Requires: gcc
Requires: python36
Requires: python36-devel
Requires: python36-pip
Requires: uwsgi >= 2.0.0
Requires: uwsgi-plugin-python36
Requires: mysql-community-devel >= 5.7.0
Requires: nginx
Requires: rabbitmq-server >= 3.7.0
# ignore byte compilation errors
%global _python_bytecompile_errors_terminate_build 0
%description
FEUDAL backend and webpage
%install
rm -rf $RPM_BUILD_ROOT
%define feudal $RPM_BUILD_ROOT%{_datadir}/feudal
mkdir -p %{feudal}
install -d %{_sourcedir}/feudal %{feudal}
install %{_sourcedir}/manage.py \
%{_sourcedir}/setup.py \
%{_sourcedir}/LICENSE \
%{_sourcedir}/README.md \
%{feudal}
%define var $RPM_BUILD_ROOT%{_localstatedir}/feudal
mkdir -p %{var}/webpage
cp -r %{_sourcedir}/webpage/dist %{var}/webpage
mkdir -p %{var}/webpage
cp -r %{_sourcedir}/static %{var}/django-static
%post
pip3.6 install %{feudal}
%postun
pip3.6 uninstall --yes feudal
%files
%doc %{feudal}/README.md
%{_datadir}/feudal
%{_localstatedir}/feudal
%changelog
......@@ -387,6 +387,11 @@ class User(AbstractUser):
self.first_name = userinfo['given_name']
self.userinfo = userinfo
# augment the userinfo if the issuer is missing
if 'iss' not in userinfo:
self.userinfo['iss'] = self.idp.issuer_uri
self.save()
ignore_group = False
......
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# SECURITY WARNING: don't run with debug turned on in production!
if os.getenv('DJANGO_ENV') == 'dev':
DEBUG = True
ALLOWED_HOSTS = [
]
else:
DEBUG = False
ALLOWED_HOSTS = [
os.getenv('DJANGO_HOST'),
]
if DEBUG:
DEBUG_AUTH = False
DEBUG_PUBLISHING = False
DEBUG_CREDENTIALS = False
AUTH_USER_MODEL = 'backend.User'
# cookie settings
SESSION_COOKIE_AGE = 3600
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = False
WSGI_APPLICATION = 'feudal.wsgi.application'
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
CORS_ORIGIN_ALLOW_ALL = True
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
secret_file = os.getenv('DJANGO_SECRET')
if secret_file is not None:
with open(secret_file) as f:
SECRET_KEY = f.read().strip()
# Application definition
ROOT_URLCONF = 'feudal.urls'
STATIC_URL = '/backend/static/'
STATIC_ROOT = './static'
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'polymorphic',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'feudal.backend',
'corsheaders',
'django_mysql',
'django_nose',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'charset': 'utf8mb4'
},
'USER': 'root',
'PASSWORD': 'root',
'HOST': 'db',
'PORT': '3306',
'NAME': 'backend',
}
}
# AUTHENTICATION AND AUTHORIZATION
AUTHENTICATION_BACKENDS = [
'feudal.backend.auth.v1.OIDCTokenAuthBackend',
'django.contrib.auth.backends.ModelBackend',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'feudal.backend.auth.v1.OIDCTokenAuthHTTPBackend',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
# Password validation
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Europe/Berlin'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# LOGGING
AUDIT_LOG_LEVEL = 25
LOGGING_ROOT = '/var/log/feudal'
if os.path.exists(LOGGING_ROOT):
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'standard': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
},
'compact': {
'format': '%(levelname)s - %(message)s',
},
'audit': {
'format': '%(asctime)s - %(message)s',
},
},
'handlers': {
'django': {
'class': 'logging.FileHandler',
'filename': LOGGING_ROOT + '/django.log',
'formatter': 'standard',
},
'debug': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': LOGGING_ROOT + '/debug.log',
'formatter': 'standard',
},
'compact-debug': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': LOGGING_ROOT + '/compact-debug.log',
'formatter': 'compact',
},
'info': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': LOGGING_ROOT + '/info.log',
'formatter': 'standard',
},
'error': {
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': LOGGING_ROOT + '/error.log',
'formatter': 'standard',
},
'console': {
'class': 'logging.StreamHandler',
'formatter': 'standard',
},
'audit': {
'level': AUDIT_LOG_LEVEL,
'class': 'logging.FileHandler',
'filename': LOGGING_ROOT + '/audit.log',
'formatter': 'audit',
},
},
'loggers': {
'feudal': {
'handlers': ['compact-debug', 'debug', 'info', 'error', 'audit'],
'level': 'DEBUG',
},
'django': {
'handlers': ['django'],
'level': 'INFO',
},
},
}
#!/usr/bin/env python
#!/usr/bin/python3.6
import os
import sys
......
oic==0.15.0
pika==0.13.1
urllib3==1.24.0
Django==2.1.0
djangorestframework==3.9.0
django-cors-headers==2.5.0
django-mysql==3.0.0.post1
django-nose==1.4.6
django_polymorphic==2.0.3
django-rest-polymorphic==0.1.8
mysqlclient==1.4.2.post1
......@@ -26,17 +26,16 @@ setup(
'manage.py',
],
install_requires=[
'Django==2.1.7',
'django-cors-headers==2.4.0',
'django-mysql==2.4.1',
'django-nose==1.4.6',
'django-polymorphic==2.0.3',
'django-rest-polymorphic==0.1.8',
'djangorestframework==3.9.1',
'nose==1.3.7',
'mysqlclient==1.4.2.post1',
'oic==0.15.1',
'pika==0.13.0',
'urllib3==1.24.1',
'oic>=0.15.0',
'pika>=0.13.0',
'urllib3>=1.24.0',
'Django>=2.1.0',
'djangorestframework>=3.9.0',
'django-cors-headers>=2.5.0',
'django-mysql>=3.0.0',
'django-nose>=1.4.6',
'django_polymorphic>=2.0.3',
'django-rest-polymorphic>=0.1.8',
'mysqlclient>=1.4.2.post1',
],
)
#!/bin/bash
./manage.py collectstatic --no-input
./manage.py migrate --no-input
# create a superuser
cat << EOF | ./manage.py shell
from feudal.backend.models import User;
username = '${1}'
password = '${2}'
qs = User.objects.filter(username=username)
if not qs.exists():
admin = User.objects.create_superuser(username, '', password)
else:
admin = qs.first()
admin.set_password(password)
admin.user_type = 'admin'
admin.save()
EOF
......@@ -5,7 +5,7 @@ trap "exit" INT
# {{{ MOCK CONFIG FILES
# the webpage is now a submodule
cd $(dirname "$0")
cd $(dirname "$0")/..
export backend=$(pwd)
export webpage=$backend/webpage
export dist=$webpage/dist
......@@ -14,37 +14,6 @@ export DJANGO_SECRET=$backend/.secret.key
export venv=$backend/env
# django settings
# {{{ PYTHON
echo "FEUDAL> Creating new python virtual environment: $venv"
python3.6 -m venv $venv
echo "FEUDAL> Activating virtual environment"
source $venv/bin/activate
pip -q install -U pip
pip install -r requirements.txt
# }}}
# {{{ DJANGO
# django secret key
if [[ ! -f $DJANGO_SECRET ]]
then
echo "FEUDAL> Generating secret key: $DJANGO_SECRET"
dd if=/dev/urandom bs=64 count=1 | base64 > $DJANGO_SECRET
fi
echo "FEUDAL> Starting database migration"
# makemigrations seems to be a bad idea here
# $backend/manage.py makemigrations backend
$backend/manage.py migrate
echo "FEUDAL> Preparing static files in $static"
$backend/manage.py collectstatic