diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index daab7e5d..ebb6c194 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -38,10 +38,6 @@ jobs: flake8 --count --select=E9,F63,F7,F82 --show-source --statistics example ## exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 --max-line-length 120 --count --exit-zero --statistics example - - name: Create docker-example folder - run: | - mkdir -p docker-example - cp -r example/. docker-example - name: docker compose run: | cd Docker-compose @@ -49,25 +45,20 @@ jobs: docker ps -a - name: djangosaml2 SP metadata to Proxy run: | - wget http://localhost:8000/saml2/metadata -O example/metadata/sp/djangosaml2_sp.xml - - name: run satosa-saml2spid - run: | - cd docker-example - mkdir -p metadata/idp - mkdir -p metadata/sp + wget http://localhost:8000/saml2/metadata -O Docker-compose/satosa-project/metadata/sp/djangosaml2_sp.xml - name: Metadata proxy to djangosaml2 SP run: | - wget --no-check-certificate https://localhost/Saml2IDP/metadata -O example_sp/djangosaml2_sp/saml2_sp/saml2_config/satosa-saml2spid.xml + wget --no-check-certificate https://localhost/Saml2IDP/metadata -O Docker-compose/djangosaml2_sp/saml2_sp/saml2_config/satosa-saml2spid.xml - name: spid-sp-test SPID metadata, requests and responses run: | - cd docker-example + cd Docker-compose/satosa-project spid_sp_test --idp-metadata > metadata/idp/spid-sp-test.xml spid_sp_test --metadata-url https://localhost/spidSaml2/metadata --authn-url "http://localhost:8000/saml2/login/?idp=https://localhost/Saml2IDP/metadata&next=/saml2/echo_attributes&idphint=https%253A%252F%252Flocalhost%253A8443" -ap spid_sp_test.plugins.authn_request.SatosaSaml2Spid --extra --debug ERROR -tr - name: spid-sp-test CIE id metadata run: | - cd docker-example + cd Docker-compose/satosa-project spid_sp_test --profile cie-sp-public --metadata-url https://localhost/cieSaml2/metadata - name: spid-sp-test eIDAS FiCEP metadata run: | - cd docker-example + cd Docker-compose/satosa-project spid_sp_test --profile ficep-eidas-sp --metadata-url https://localhost/spidSaml2/metadata diff --git a/.gitignore b/.gitignore index 921a1e55..e36be54f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ example/private/* example_sp/djangosaml2_sp/sqlite3.db project/* docker-example/* +Docker-compose/satosa-project/* +Docker-compose/djangosaml2_sp/* +Docker-compose/mongo/db/* +Docker-compose/nginx/html/static/* diff --git a/Docker-compose/.env b/Docker-compose/.env deleted file mode 100644 index c5c2cc94..00000000 --- a/Docker-compose/.env +++ /dev/null @@ -1,4 +0,0 @@ -MONGO_DBUSER=satosa -MONGO_DBPASSWORD=thatpassword -SATOSA_HOSTNAME=localhost -SATOSA_KEYS_FOLDER=./pki diff --git a/Docker-compose/README.md b/Docker-compose/README.md index ea4b3cd4..0eab6bec 100644 --- a/Docker-compose/README.md +++ b/Docker-compose/README.md @@ -3,131 +3,87 @@ ## Table of Contents 1. [Requirements](#requirements) -2. [Run the composition](#run-the-composition) -3. [Stop the composition](#stop-the-composition) -4. [Remove/Delete volumes](#remove/delete-volumes) -5. [Demo data](#demo-data) -6. [Env file](#env-file) -7. [docker-compose.yml](#docker-compose.yml) +2. [Run the composition - MAGIC WAY](#run-the-composition-magic-way) +3. [Run the composition - LONG WAY](#run-the-composition-long-way) +4. [Configure your system](#configure-your-system) +5. [Insights](#Insights) ## Requirements In order to execute the run script you need: -* docker -* jq -* docker version 3 +* docker-compose Installation example in Ubuntu: ``` -sudo apt install jq +sudo apt install docker-compose ``` For docker-compose you can also [see here](https://docs.docker.com/compose/install/other/). -### Satosa-Saml2SPID Docker Image +## Run the composition MAGIC WAY -The official Satosa-Saml2SPID docker image is available at -[italia/satosa-saml2spid](https://ghcr.io/italia/satosa-saml2spid). - -To install it, you can execute the following command: `sudo docker pull ghcr.io/italia/satosa-saml2spid:latest`. - -Otherwise you can build the image executing the following command: `docker build -t satosa-saml2spid .`. - -Then you can even inspect the image content, by running the following command: `docker run -it -v $(pwd)/example:/satosa_proxy --entrypoint sh satosa-saml2spid`. - -## Run the composition - -1. Copy/pull Satosa-Saml2Spid project locally. -2. Copy the folder `example` to a new folder named `docker-example`: `cp -R example docker-example`. -3. Inspect the `docker-example` folder content and do your configuration by setting env variables and local folder contents. - -> :warning: **DO NOT USE the `example` folder _as is_ in production**: the `example` folder provides secrets that **MUST** be not used in a production environment. It sole purpose is to provide a user friendly starting point. - -### Start the Compose - -Execute the run script for the first time: - -``` +Enter in `Docker-compose` directory and run `run-docker-compose.sh`: +```bash cd Docker-compose ./run-docker-compose.sh ``` +The script make the directories for local mounts, copy all required files in right directory and start a full demo with test and Service providers -The following docker volumes are created, if they doesn't exist yet: +* Satosa-saml2spid is published with nginx frontend on https://localhost +* Mongo Espress is published on http://localhost:8081 +* Django SAML2 SP is published on https://localhost:8000 +* Spid-samlcheck is published on https://localhost:8443 -* satosa-saml2spid_nginx_certs -* satosa-saml2spid_mongodata +More details ad start option are avable on [run-docker-compose.sh](../docs/run-docker-compose.sh.md) page -The *satosa-saml2spid_nginx_certs* is populated with data from [nginx/certs/](nginx/certs)`, -*satosa-saml2spid_mongodata* is populated by MongoDB container with its storage. +### Run the composition LONG WAY -After having executed the docker compose you can see the logs of the running containers: -``` -docker-compose -f docker-compose.yml logs -f +Enter in `Docker-compose` directory and make required direcotries for local mounts: +```bash +cd Docker-compose +mkdir -p ./mongo/db # DB Data directory +mkdir -p ./satosa-project # Satosa-saml2spid data istance +mkdir -p ./djangosaml2_sp # Service provider directory +mkdir -p ./nginx/html/static # static files for nginx ``` -After the first run, you can start the docker compose with the run script or by this commands: - -``` -docker-compose pull; docker-compose down -v; docker-compose up -d; docker-compose logs -f +Copy required files +```bash +cp -R ../example/* ./satosa-project +cp -R ../example_sp/djangosaml2_sp/* ./djangosaml2_sp +cp -E ../example/static/* ./nginx/html/static ``` -### Where is your data? -Command: - -``` -docker volume ls +Clean static data from Satosa project +```bash +rm -R ./satosa-project/static ``` -Output: - -``` -DRIVER VOLUME NAME -local satosa-saml2spid_mongodata -local satosa-saml2spid_nginx_certs -``` - -In RedHat and Ubuntu based OS the Docker volumes directory is at: - +Run the compose for a minimal system (nginx and satosa) ``` -# ls -1 /var/lib/docker/volumes/ -satosa-saml2spid_mongodata -satosa-saml2spid_nginx_certs +docker compose up ``` -## Stop the composition - +Run the full demo +```bash +docker compose --profile demo up ``` -./stop-docker-compose.sh -``` - -This script stops all containers of the composition and detaches the volumes, but keeps the data on the persistent volumes. -## Remove/Delete volumes +Read the [profiles guide](../docs/docker_compose_profiles.md) for more informations -If you want to start from scratch, or just clear all persistent data, just run the following script: +### Configure your system +Copy the example env file: +```bash +cp env.example .env ``` -./rm-persistent-volumes.sh -``` - -First, the containers of the composition are stopped and the volumes are detached. - -Then you are asked if you want to delete the volumes and if you answer yes, you have to confirm volume by volume. - -## Demo data - -Demo data for a test client are inserted into the DB during the first run of the composition. - -See [mongo readme](../README.mongo.md) to have some example of demo data. - -## Env file -Customize the environment variables using the [.env](.env) file. -The file [.env.example](.env.example) provides an example with all the environment variables you can set. -The variables not set in the `.env` file will fallback on a default value defined in the [docker-compose.yml](docker-compose.yml). +Edit and personalize the system from `.env` files. You can still edit all files in detail from their local volumes. +**IMPORTANT all the default password must be changed!** -> :warning: Be careful when deploying your solution since some environment variables are **security-related**. +### Insights -See [mongo readme](../README.mongo.md) for explanation of environment variables of MongoDB. +* More details on prodiles read the [Docker Compose Profiles](../docs/docker_compose_profiles.md) page +* More details on run-docker-compose,sh read the [run-docker-compose.sh](../docs/run-docker-compose.sh.md) page diff --git a/Docker-compose/docker-compose.yml b/Docker-compose/docker-compose.yml index b0ce70c8..d454ef3b 100644 --- a/Docker-compose/docker-compose.yml +++ b/Docker-compose/docker-compose.yml @@ -1,54 +1,62 @@ services: satosa-mongo: + profiles: + - demo + - mongo + - mongoexpress image: mongo container_name: satosa-mongo - restart: always environment: MONGO_INITDB_DATABASE: oidcop MONGO_INITDB_ROOT_USERNAME: "${MONGO_DBUSER:-satosa}" MONGO_INITDB_ROOT_PASSWORD: "${MONGO_DBPASSWORD:-thatpassword}" + TZ: "${TZ:-Europe/Rome}" volumes: - - mongodata:/data/db - - /usr/share/zoneinfo/Europe/Rome:/etc/localtime:ro + - ./mongo/db:/data/db - ./mongo/init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh + # - mongodata:/data/db # to be used for external volumes ports: - '27017-27019:27017-27019' networks: - satosa-saml2spid satosa-mongo-express: + profiles: + - demo + - mongoexpress image: mongo-express container_name: satosa-mongo-express - restart: always ports: - 8082:8081 + depends_on: + - satosa-mongo environment: - ME_CONFIG_BASICAUTH_USERNAME: satosauser - ME_CONFIG_BASICAUTH_PASSWORD: satosapw + ME_CONFIG_BASICAUTH_USERNAME: "${EXPRESS_USER:-satosauser}" + ME_CONFIG_BASICAUTH_PASSWORD: "${EXPRESS_PASSWORD:-satosapw}" ME_CONFIG_MONGODB_ADMINUSERNAME: "${MONGO_DBUSER:-satosa}" ME_CONFIG_MONGODB_ADMINPASSWORD: "${MONGO_DBPASSWORD:-thatpassword}" ME_CONFIG_MONGODB_URL: mongodb://${MONGO_DBUSER:-satosa}:${MONGO_DBPASSWORD:-thatpassword}@satosa-mongo:27017/ + TZ: "${TZ:-Europe/Rome}" networks: - satosa-saml2spid - ## START: PARTE NUOVA django_sp: + profiles: + - demo + - dev build: - context: ../ + context: ../ args: - - NODE_ENV=local + - NODE_ENV=local dockerfile: example_sp/django.Dockerfile container_name: django_sp - #restart: always working_dir: /django_sp entrypoint: "sh ../entrypoint.sh" volumes: - - /usr/share/zoneinfo/Europe/Rome:/etc/localtime:ro - - ../example_sp/djangosaml2_sp:/django_sp:rw + - ./djangosaml2_sp:/django_sp:rw ports: - "8000:8000" networks: - satosa-saml2spid -## END: PARTE NUOVA satosa-saml2spid: image: ghcr.io/italia/satosa-saml2spid:latest #image: satosa-saml2spid:latest @@ -58,17 +66,18 @@ services: # - NODE_ENV=local # dockerfile: Dockerfile container_name: satosa-saml2spid - depends_on: - - satosa-mongo + # depends_on: + # - satosa-mongo stdin_open: ${SATOSA_DEBUG:-false} # enables PDB when attach to the compose tty: ${SATOSA_DEBUG:-false} # enables PDB when attach to the compose environment: + - TZ=${TZ:-Europe/Rome} - SATOSA_BY_DOCKER=1 - GET_IDEM_MDQ_KEY=${GET_IDEM_MDQ_KEY:-true} - BASE_DIR=/satosa_proxy - SATOSA_PRIVATE_KEY=${SATOSA_KEYS_FOLDER:-./pki}/${SATOSA_PRIVATE_KEY_FILENAME:-privkey.pem} - - SATOSA_PUBLIC_KEY=${SATOSA_KEYS_FOLDER:-./pki}/${SATOSA_CERT_FILENAME:-cert.pem} + - SATOSA_PUBLIC_KEY=${SATOSA_KEYS_FOLDER:-./pki}/${SATOSA_PUBLIC_KEY_FILENAME:-cert.pem} - SATOSA_BASE=https://${SATOSA_HOSTNAME:-localhost} - SATOSA_BASE_STATIC=https://${SATOSA_HOSTNAME:-localhost}/static - SATOSA_DISCO_SRV=https://${SATOSA_HOSTNAME:-localhost}/static/disco.html @@ -109,8 +118,8 @@ services: ports: - "10000:10000" volumes: - - /usr/share/zoneinfo/Europe/Rome:/etc/localtime:ro - - ../docker-example:/satosa_proxy:rw + - ./satosa-project:/satosa_proxy:rw + # - satosadata:/satosa_proxy # to be used for external volumes working_dir: /satosa_proxy entrypoint: "sh entrypoint.sh" networks: @@ -128,40 +137,43 @@ services: depends_on: - satosa-saml2spid ports: - - "80:80" - "443:443" volumes: - - ./nginx/nginx.conf_uwsgi_pass:/etc/nginx/nginx.conf:ro - - ./nginx/50x.html:/usr/share/nginx/html/50x.html:ro - - ./nginx/404.html:/usr/share/nginx/html/404.html:ro - - ./nginx/403.html:/usr/share/nginx/html/403.html:ro - - nginx_certs:/etc/nginx/certs:ro - - ../docker-example/static:/var/www/html + - ./nginx/conf.d:/etc/nginx/conf.d:ro + - ./nginx/html:/usr/share/nginx/html:ro + - ./nginx/certs:/etc/nginx/certs:ro + # - static:/usr/share/nginx/html # to be used for external volumes networks: - satosa-saml2spid environment: - NGINX_HOST=${SATOSA_HOSTNAME:-localhost} + - TZ=${TZ:-Europe/Rome} spid-samlcheck: + profiles: + - demo + - dev image: italia/spid-saml-check container_name: spid-samlcheck - environment: - - NODE_TLS_REJECT_UNAUTHORIZED=${NODE_TLS_REJECT_UNAUTHORIZED:-0} ports: - "8443:8443" networks: - satosa-saml2spid - -volumes: - - mongodata: - name: satosa-saml2spid_mongodata - external: true - - nginx_certs: - name: satosa-saml2spid_nginx_certs - external: true - networks: satosa-saml2spid: name: satosa-saml2spid + +## External volumes +# volumes: +# mongodata: +# name: satosa-saml2spid_mongodata +# external: true +# nginx_certs: +# name: satosa-saml2spid_nginx_certs +# external: true +# satosadata: +# name: satosa-data +# external: true +# static: +# name: satosa-static +# external: true diff --git a/Docker-compose/.env.example b/Docker-compose/env.example similarity index 92% rename from Docker-compose/.env.example rename to Docker-compose/env.example index a111c914..b71edc39 100644 --- a/Docker-compose/.env.example +++ b/Docker-compose/env.example @@ -1,14 +1,21 @@ SATOSA_HOSTNAME=localhost +# Set Time Zone +TZ="Europe/Rome" + # MongoDB authentication MONGO_DBUSER=satosa MONGO_DBPASSWORD=thatpassword +# Mongo express authentication +EXPRESS_USER=satosauser +EXPRESS_PASSWORD=-satosapw + # The path containing your secrets SATOSA_KEYS_FOLDER=./pki # Keys filename SATOSA_PRIVATE_KEY_FILENAME=privkey.pem -SATOSA_PUBLIC_KEY=cert.pem +SATOSA_PUBLIC_KEY_FILENAME=cert.pem # BE CAREFUL HERE! SATOSA_SALT=CHANGE_ME! diff --git a/Docker-compose/nginx/conf.d/default.conf b/Docker-compose/nginx/conf.d/default.conf new file mode 100644 index 00000000..0ef24688 --- /dev/null +++ b/Docker-compose/nginx/conf.d/default.conf @@ -0,0 +1,57 @@ +server { + listen 443 ssl; + server_name $NGINX_HOST; + ssl_protocols TLSv1.3; + ssl_certificate /etc/nginx/certs/proxy_local.pem; + ssl_certificate_key /etc/nginx/certs/proxy_local.key; + + # max upload size + client_max_body_size 10m; + + # very long url for delega ticket + large_client_header_buffers 4 16k; + + # deny iFrame + add_header X-Frame-Options "DENY"; + + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Robots-Tag none; + + root /usr/share/nginx/html; + try_files $uri/index.html $uri @satosa; + + location @satosa { + include /etc/nginx/uwsgi_params; + + uwsgi_pass satosa-saml2spid:10000; + uwsgi_param Host $host; + uwsgi_param X-Real-IP $remote_addr; + uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for; + uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto; + uwsgi_param HTTP_X_FORWARDED_PROTOCOL https; + + uwsgi_connect_timeout 75s; + uwsgi_read_timeout 40; + uwsgi_buffer_size 128k; + uwsgi_buffers 4 256k; + uwsgi_busy_buffers_size 256k; + uwsgi_param SERVER_ADDR $server_addr; + } + + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html/errors; + } + + error_page 403 /403.html; + location = /403.html { + root /usr/share/nginx/html/errors; + } + + # redirect server error pages to the static page /50x.html + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html/errors; + } +} diff --git a/Docker-compose/nginx/403.html b/Docker-compose/nginx/html/errors/403.html similarity index 100% rename from Docker-compose/nginx/403.html rename to Docker-compose/nginx/html/errors/403.html diff --git a/Docker-compose/nginx/404.html b/Docker-compose/nginx/html/errors/404.html similarity index 100% rename from Docker-compose/nginx/404.html rename to Docker-compose/nginx/html/errors/404.html diff --git a/Docker-compose/nginx/50x.html b/Docker-compose/nginx/html/errors/50x.html similarity index 100% rename from Docker-compose/nginx/50x.html rename to Docker-compose/nginx/html/errors/50x.html diff --git a/Docker-compose/nginx/html/index.html b/Docker-compose/nginx/html/index.html new file mode 100644 index 00000000..d83c0f11 --- /dev/null +++ b/Docker-compose/nginx/html/index.html @@ -0,0 +1,4 @@ + + + Satosa-saml2spid empty index, check docs to edit + \ No newline at end of file diff --git a/Docker-compose/nginx/nginx.conf_uwsgi_pass b/Docker-compose/nginx/nginx.conf_uwsgi_pass deleted file mode 100644 index c6ce1297..00000000 --- a/Docker-compose/nginx/nginx.conf_uwsgi_pass +++ /dev/null @@ -1,116 +0,0 @@ -user nginx; -worker_processes auto; -pid /run/nginx.pid; - -events { - worker_connections 1024; -} - -http { - include mime.types; - default_type application/octet-stream; - - sendfile on; - keepalive_timeout 240s; - send_timeout 240s; - client_max_body_size 3300m; - - log_format main '$http_x_forwarded_for - $remote_user [$time_local] ' - '"$request" $status $body_bytes_sent "$http_referer" ' - '"$http_user_agent"' ; - -# the upstream component nginx needs to connect to -upstream satosa-saml2 { - server satosa-saml2spid:10000; -} - -# configuration of the server -server { - listen 80; - server_name proxy.local; - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log error; - return 301 https://$host$request_uri; -} - -server { - server_name proxy.local; - listen 443 ssl; - - ssl_certificate /etc/nginx/certs/proxy_local.pem; - ssl_certificate_key /etc/nginx/certs/proxy_local.key; - - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log error; - - # max upload size - client_max_body_size 10m; - - # very long url for delega ticket - large_client_header_buffers 4 16k; - - ssl_prefer_server_ciphers on; - ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 - ssl_session_timeout 10m; - ssl_session_cache shared:SSL:10m; - ssl_session_tickets off; # Requires nginx >= 1.5.9 - ssl_stapling on; # Requires nginx >= 1.3.7 - ssl_stapling_verify on; # Requires nginx => 1.3.7 - - # Enable HTTP Strict Transport Security with a 2 year duration - add_header Strict-Transport-Security "max-age=63072000; "; - - # deny iFrame - add_header X-Frame-Options "DENY"; - - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Robots-Tag none; - - location /static { - alias /var/www/html; - autoindex off; - } - - location /bootstrap-italia/dist { - alias /satosa_proxy/static/bootstrap-italia; - autoindex off; - } - - location / { - include /etc/nginx/uwsgi_params; - - - uwsgi_pass satosa-saml2; - uwsgi_param Host $host; - uwsgi_param X-Real-IP $remote_addr; - uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for; - uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto; - uwsgi_param HTTP_X_FORWARDED_PROTOCOL https; - - uwsgi_connect_timeout 75s; - uwsgi_read_timeout 40; - uwsgi_buffer_size 128k; - uwsgi_buffers 4 256k; - uwsgi_busy_buffers_size 256k; - uwsgi_param SERVER_ADDR $server_addr; - - } - - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } - - error_page 404 /404.html; - location = /404.html { - root /usr/share/nginx/html; - } - - error_page 403 /403.html; - location = /403.html { - root /usr/share/nginx/html; - } - -} -} diff --git a/Docker-compose/rm-persistent-volumes.sh b/Docker-compose/rm-persistent-volumes.sh deleted file mode 100755 index 4963d86e..00000000 --- a/Docker-compose/rm-persistent-volumes.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -function delete-volume { - if [ ! "$(docker volume ls -q -f name=$1)" ] - then - echo -e "Il volume $1 non esiste, quindi non faccio nulla! \n" - else - read -p "Il volume $1 esiste. Lo cancello?(y/n):" ELIMINA_VOLUME - ELIMINA_VOLUME=${ELIMINA_VOLUME:-"n"} - export ELIMINA_VOLUME - if [ $ELIMINA_VOLUME = "y" ] - then - docker volume rm $1 - echo -e "Eliminato $1 !!! \n" - else - echo -e "Non ho eliminato $1 !!! \n" - fi - fi -} - -echo -e "\n" - -echo -e "Inizio le procedure per fare il down della composizione e poi CANCELLARE i volumi persistenti! \n" - -echo -e "Fermo la composizione! \n" -docker compose -f docker-compose.yml down -v; - -echo -e "\n" - -read -p "Volete veramente procedere con la cancellazione dei volumi persistenti? Tutti i dati andranno persi! Procedo ? (y/n) :" ELIMINA_DATI_PERSISTENTI -ELIMINA_DATI_PERSISTENTI=${ELIMINA_DATI_PERSISTENTI:-"n"} -export ELIMINA_DATI_PERSISTENTI -if [ $ELIMINA_DATI_PERSISTENTI != "y" ] -then - echo -e "\n" - echo -e "Non elimino nulla ed esco!!! \n" - exit 0 -else - -echo -e "Procedo ... \n" - -echo -e "\n" - -delete-volume satosa-saml2spid_nginx_certs -delete-volume satosa-saml2spid_mongodata - -fi - -exit 0 diff --git a/Docker-compose/run-docker-compose.sh b/Docker-compose/run-docker-compose.sh index e1b2a41a..5bd7a161 100755 --- a/Docker-compose/run-docker-compose.sh +++ b/Docker-compose/run-docker-compose.sh @@ -1,46 +1,94 @@ #!/bin/bash - -function create-volume { - if [ ! "$(docker volume ls -q -f name=$1)" ] - then - echo -e "Il volume $1 non esiste, lo creo! \n" - docker volume create --name=$1 - echo -e "\n" - if [[ ! -z "$2" ]] - then - echo -e "Ho creato il volume e ci copio i dati da $2 \n" - sudo cp -R $2* `docker volume inspect $1 | jq .[0].Mountpoint | sed 's/"//g'` - fi - else - echo -e "Il volume $1 esiste, non faccio nulla! \n" - fi +export COMPOSE_PROFILES=demo +export SKIP_UPDATE= +function clean_data { + rm -Rf ./mongo/db/* + rm -Rf ./satosa-project/* + rm -Rf ./djangosaml2_sp/* + rm -Rf ./nginx/html/static } -create-volume satosa-saml2spid_nginx_certs nginx/certs/ -create-volume satosa-saml2spid_mongodata - -echo -e "\n" - -echo -e "Provo a scaricare le nuove versioni. \n" - -docker compose -f docker-compose.yml pull - -echo -e "\n" - -echo -e "Provo a fare il down della composizione. \n" - -docker compose -f docker-compose.yml down -v +function initialize_satosa { + mkdir -p ./satosa-project + mkdir -p ./djangosaml2_sp + mkdir -p ./mongo/db + mkdir -p ./nginx/html/static -echo -e "\n" - -echo -e "Tiro su la composizione, in caso, con le nuove versioni delle immagini. \n" + if [ ! -f ./satosa-project/proxy_conf.yaml ]; then cp -R ../example/* ./satosa-project/ ; rm -R ./satosa/static/ ; else echo 'satosa-project directory is already initialized' ; fi + if [ ! -f ./djangosaml2_sp/run.sh ]; then cp -R ../example_sp/djangosaml2_sp/* ./djangosaml2_sp ; else echo 'djangosaml2_sp directory is already initialided' ; fi + if [ ! -f ./nginx/html/static/disco.html ]; then cp -R ../example/static/* ./nginx/html/static ; else echo 'nginx directory is already initialized' ; fi +} +function update { + if [[ -z "${SKIP_UPDATE}" ]]; then + echo -e "Provo a scaricare le nuove versioni. \n" + docker compose -f docker-compose.yml pull + echo -e "\n" + echo -e "Provo a fare il down della composizione. \n" + docker compose -f docker-compose.yml down -v + echo -e "\n" + echo -e "Tiro su la composizione, in caso, con le nuove versioni delle immagini. \n" docker compose -f docker-compose.yml build django_sp + fi +} -docker compose -f docker-compose.yml up -d --wait --wait-timeout 60 - -echo -e "\n" +function start { + docker compose -f docker-compose.yml up --wait --wait-timeout 60 --remove-orphans + echo -e "\n" + echo -e "Completato. Per visionare i logs: 'docker-compose -f docker-compose.yml logs -f'" + exit 0 +} -echo -e "Completato. Per visionare i logs: 'docker-compose -f docker-compose.yml logs -f'" +function help { + echo "" + echo "### run-docker-compose.sh ###" + echo "" + echo "initialize check update and start Satosa-Saml2Spid compose structure" + echo "" + echo "Options" + echo "-f Force clean and reinitialize data for Satosa, MongoDB and Djangosaml2_SP" + echo "-h Print this help" + echo "-s Skip docker image update" + echo "-p unset compose profile. Run: satosa and nginx. Usefull for production" + echo "-m Set 'mongo' compose profile. Run: satosa, nginx, mongo" + echo "-M Set 'mongoexpress' compose profile. Run: satosa, nginx, mongo, mongo-express" + echo "-d Set 'dev' compose profile. Run: satosa, nginx, django-sp, spid-saml-check" + echo " if isn't set any of -p, -m, -M, -d, is used 'demo' compose profile" + echo " demo compose profile start: satosa, nginx, mongo, mongo-express, django-sp, spid-saml-check" +} -exit 0 +while getopts ":fpimMdsh" opt; do + case ${opt} in + f) + clean_data + ;; + p) + unset COMPOSE_PROFILES + ;; + m) + COMPOSE_PROFILES="mongo" + ;; + M) + COMPOSE_PROFILES="mongoexpress" + ;; + d) + COMPOSE_PROFILES="dev" + ;; + s) + SKIP_UPDATE=true + ;; + h) + help + exit 0 + ;; + ?) + echo "Invalid option: -${OPTARG}." + echo "" + help + exit 1 + ;; + esac +done +initialize_satosa +update +start diff --git a/Docker-compose/stop-docker-compose.sh b/Docker-compose/stop-docker-compose.sh index 96c1da83..f5e39d16 100755 --- a/Docker-compose/stop-docker-compose.sh +++ b/Docker-compose/stop-docker-compose.sh @@ -3,6 +3,6 @@ echo -e "\n" echo -e "Eseguo il down della composizione. \n" -docker compose -f docker-compose.yml down -v +docker compose -f docker-compose.yml --profile "*" down -v --remove-orphans exit 0 diff --git a/Dockerfile b/Dockerfile index b8fac0e3..fb4fbafd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,20 +18,14 @@ LABEL org.opencontainers.image.authors=$AUTHORS \ org.opencontainers.image.revision=$VCS_REF \ org.opencontainers.image.description="Docker Image di Satosa-Saml2Spid." -RUN apk update -RUN apk add --update --no-cache tzdata -RUN cp /usr/share/zoneinfo/Europe/Rome /etc/localtime -RUN echo "Europe/Rome" > /etc/timezone -RUN apk del tzdata - -# fix: no /etc/mime.types file found. -RUN apk add mailcap COPY requirements.txt / ENV BASEDIR="/satosa_proxy" -RUN apk add --update xmlsec libffi-dev openssl-dev python3 py3-pip python3-dev procps git openssl build-base gcc wget bash jq yq-go pcre-dev +# "tzdata" package is required to set timezone with TZ environment +# "mailcap" package is required to add mimetype support +RUN apk add --update --no-cache tzdata mailcap xmlsec libffi-dev openssl-dev python3 py3-pip python3-dev procps git openssl build-base gcc wget bash jq yq-go pcre-dev RUN python3 -m venv .venv && . .venv/bin/activate && pip3 install --upgrade pip setuptools \ && pip3 install -r requirements.txt --ignore-installed --root-user-action=ignore && mkdir $BASEDIR diff --git a/docs/docker_compose_profiles.md b/docs/docker_compose_profiles.md new file mode 100644 index 00000000..61f4b455 --- /dev/null +++ b/docs/docker_compose_profiles.md @@ -0,0 +1,65 @@ +## Docker Compose profiles in Satosa-saml2spid +Profiles are a good way to optimize and extend a single Docker Compose file. +The [official docker manual](https://docs.docker.com/compose/profiles/) says about profiles: +> Profiles help you adjust your Compose application for different environments or use cases by selectively activating services. Services can be assigned to one or more profiles; unassigned services start by default, while assigned ones only start when their profile is active. This setup means specific services, like those for debugging or development, to be included in a single compose.yml file and activated only as needed. + +In this [Docker Compose project](https://github.com/italia/Satosa-Saml2Spid/blob/master/Docker-compose/docker-compose.yml), profiles are used to limit startup to strictly necessary services. +The services `satota-saml2spid` and `satosa-nginx` do not have a profile and are started every time, every other service can be started with one of the existing profiles: + +* **mongo** - start MongoDB service +* **mongoexpress** - start MongoDB and a MongoExpress service +* **dev** - start all "service provider" and "test" services +* **demo** - start all services + +You can specify the required profile with `--profile` option in Docker Compose. In the next example we add the `demo` profile to start all services: +``` +docker compose --profile demo up +``` + +Youn can specify multiple profile on compose startup, in the next example we add `mongo` and `dev` profiles: +``` +docker compose --profile mongo --profile dev up +``` + +You can specify one or more profiles with environments: +``` +COMPOSE_PROFILES=dev,mongo docker compose up +``` + +The [run-docker-compose.sh](./run-docker-compose.sh.md) script can be start all profiles with his options + +### summary tables +#### Profile by service + +| Service | profiles +| -------------------- | -------- +| django_sp | demo, dev +| satosa-mongo | demo, mongo, mongoexpress +| satosa-mongo-express | demo, mongoexpress +| satosa-nginx | +| satosa-saml2spid | +| spid-samlcheck | demo dev + +#### Services by profile + +| Profile | services +| ----------- | -------- +| no profiles | nginx, satosa +| demo | django_sp, satosa-mongo, satosa-mongo-express, satosa-nginx, satosa-saml2spid, spid-samlcheck +| dev | django_sp, satosa-nginx, satosa-saml2spid, spid-samlcheck +| mongo | satosa-mongo, satosa-nginx, satosa-saml2spid +| mongexpress | satosa-mongo, satosa-mongo-express, satosa-nginx, satosa-saml2spid + +#### Profile by option in [run-docker-compose.sh](./run-docker-compose.sh) + +| Option | Profile +| ------ | ------- +| `-p` | no profiles +| `-m` | mongo +| `-M` | mongoexpress +| `-d` | dev +| | demo + +### Insights +* For more details on Satosa-saml2spid docker compose read [docker-compose readme page](./docker-compose.md) +* For more details on Satosa-saml2spid docker run-docker-compose.sh read [run-docker-compose.sh page](./run-docker-compose.sh.md) diff --git a/docs/run-docker-compose.sh.md b/docs/run-docker-compose.sh.md new file mode 100644 index 00000000..4b6dd6df --- /dev/null +++ b/docs/run-docker-compose.sh.md @@ -0,0 +1,47 @@ +## run-docker-compose.sh + +[This scritp](https://github.com/italia/Satosa-Saml2Spid/blob/master/Docker-compose/run-docker-compose.sh) is a simple uility to initialize, update and start the Satosa-saml2spid compose structure. + +### Script Options +* `-f` Force clean and reinitialize data for Satosa, MongoDB and Djangosaml2_SP +* `-h` Print this help +* `-s`Skip docker image update +* `-p` unset compose profile. Run: satosa and nginx. Usefull for production +* `-m` Set 'mongo' compose profile. Run: satosa, nginx, mongo +* `-M` Set 'mongoexpress' compose profile. Run: satosa, nginx, mongo, mongo-express +* `-d` Set 'dev' compose profile. Run: satosa, nginx, django-sp, spid-saml-check. + If isn't set any of -p, -m, -M, -d, is used 'demo' compose profile. + Demo compose profile start: satosa, nginx, mongo, mongo-express, django-sp, spid-saml-check + +`run-docker-compose.sh` must be executed from `docker-compose` directory. To run the script the user must have access to the docker system. + +On startup the script check if the directories required from docker compose are presents: +* ./satosa-project +* ./djangosaml2_sp +* ./mongo/db +* ./nginx/html/static + +After the script test if the required directories are populated and if isn't copy the default files +| Directory | test presence of | default origin | +| ----------------- | ---------------- | ------------------------------ | +| satosa-project | proxy_conf.yaml | ../example/* | +| djangosaml2_sp | run.sh | ../example_sp/djangosaml2_sp/* | +| nginx/html/static | disco.html | ../example/static/* | + + +Unless `-s` options is enabled, on every start the script try to: +* Download the new versione of each required images +* Compile the new local image (django_sp) + +If `-c` option is enables, before each, the script remove all data from theese directories: +* mongo/db/* +* satosa-project/* +* djangosaml2_sp/* +* nginx/html/static + +The empty directories are populated with the default data + +### Insights +* For more details on Satosa-saml2spid docker compose read [docker-compose readme page](./docker-compose.md) +* For more details on Satosa-saml2spid docker compose profiles read [docker-compose-profiles page](./docker-compose-profiles.md) +* For more details on MongoDB for Satosa-saml2spid read [MongoDB page](./mongo.md) diff --git a/docs/satosa-nginx-vhost.md b/docs/satosa-nginx-vhost.md new file mode 100644 index 00000000..05e3a4f1 --- /dev/null +++ b/docs/satosa-nginx-vhost.md @@ -0,0 +1,106 @@ +## Nginx Virtual Host example + +NGINX is quick and light web server. +Nginx is commonly used as frontend proxy for Satosa and his implementation Satosa-saml2spid. +On follow some configuration examples. + +### General information +* In all example in this doc, the discovery page and errors pages are served directly from NGINX as static file. In some case you can use uWSGI to serve static files, but normally isn't a good choice +* For security reasons, all authentication connection, must be encrypted through HTTPS protocol +* For security reasons, https protocol use exclusively TLS1.3 to encrypt +* In all example we use `try_files` directive. With this directive you can test if the request is to a file or send there to a proxy location. In these examples: +* 1. Test if the request is a existent directory with a `index.html` file. If the request is `/pippo` NGINX try to serve `/usr/share/nginx/html/pippo/index.html` +* 2. Test if exists a file with the request path. If request is `/pippo/pluto.html`, NGINX try to serve `/usr/share/nginx/html/pippo/pluto.html` +* 3. Send the request to `@satosa` location +* `@satosa` location contain the proxy informations +* NGINX can read the system environments. This is useful to configure NGINX in docker. +### Docker host and uWSGI connection from network + +#### Details +* The `server_name` is configured bu `$NGINX_HOST` environment. You change this with a static dns name +* In docker compose, if you create more replicas of a service, the service name is a pointment to all istances +* the certificates must be valid for the current host name +* The root path is `/usr/share/nginx/html` for docker but you can use your preferred path +* if you don't want personalize the errors pages you can remove the errors configurations +* @satosa location use the uWSGI protocol for proxy + +#### satosa.conf +``` +server { + listen 443 ssl; + server_name $NGINX_HOST; + ssl_protocols TLSv1.3; + ssl_certificate /etc/nginx/certs/proxy_local.pem; + ssl_certificate_key /etc/nginx/certs/proxy_local.key; + + # max upload size + client_max_body_size 10m; + + # very long url for delega ticket + large_client_header_buffers 4 16k; + + # deny iFrame + add_header X-Frame-Options "DENY"; + + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Robots-Tag none; + + root /usr/share/nginx/html; + try_files $uri/index.html $uri @satosa; + + location @satosa { + include /etc/nginx/uwsgi_params; + + uwsgi_pass satosa-saml2spid:10000; + uwsgi_param Host $host; + uwsgi_param X-Real-IP $remote_addr; + uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for; + uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto; + uwsgi_param HTTP_X_FORWARDED_PROTOCOL https; + + uwsgi_connect_timeout 75s; + uwsgi_read_timeout 40; + uwsgi_buffer_size 128k; + uwsgi_buffers 4 256k; + uwsgi_busy_buffers_size 256k; + uwsgi_param SERVER_ADDR $server_addr; + } + + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html/errors; + } + + error_page 403 /403.html; + location = /403.html { + root /usr/share/nginx/html/errors; + } + + # redirect server error pages to the static page /50x.html + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html/errors; + } +} +``` + +#### proxy to socket +If you want use a local socket uwsgy server you must change the `uwsgi_pass` key: +``` +uwsgy_pass unix:///opt/satosa-saml2/tmp/sockets/satosa.sock; +``` +where `unix://` is the url protocol and `/opt/satosa-saml2/tmp/sockets/satosa.socks` is the socket path + +#### nginx host log +If you want save the NGINX log for this host you can add this directive in the virtual host: +``` + access_log /var/log/nginx/satosa.access.log; + error_log /var/log/nginx/satosa.error.log error; +``` +For docker instance the logs are sent to STDOUT and going in docker logs. This directive is normally not needed. + +### Insights +* For more details on satosa-nginx compose service read [satosa-nginx_compose doc](./satosa-nginx_compose.md) +* For more details on Satosa-saml2spid docker compose profiles read [docker-compose-profiles page](./docker-compose-profiles.md) +* For more details on NGINX try_files directive read the [official docs](https://www.slingacademy.com/article/nginx-try_files-directive-explained-with-examples/) diff --git a/docs/satosa-nginx_compose_service.md b/docs/satosa-nginx_compose_service.md new file mode 100644 index 00000000..535823bf --- /dev/null +++ b/docs/satosa-nginx_compose_service.md @@ -0,0 +1,62 @@ +## satosa-nginx Compose service + +This service run a container with the last version of [Docker official Alpine NGINX](https://hub.docker.com/_/nginx/) image. +This container work as [uWSGI](https://en.wikipedia.org/wiki/UWSGI) proxy to [satosa-saml2spid](./satosa-saml2spid_compose_service.md) containers and serve static file like the discovery page. + +### Environments +| Environment | from | Default value | Description +| ----------- | --------------- | ------------- | ----------- +| NGINX_HOST | SATOSA_HOSTNAME | localhost | Hostname in satosa virtualhost +| TZ | TZ | Europe/Rome | Set Time Zone for the istance + +### Volumes +| from | to | mode | Description +| -------------- | --------------------- | ---- | ------------ +| ./nginx/conf.d | /etc/nginx/conf.d | ro | this directory contain all NGINX virtualst, read [Virtual Sost section](#vitual-host) +| ./nginx/certs | /etx/nginx/certs | ro | This directory contain the https cerificates, read [Satosa Virtual Host section](#satosa-vitual-host) +| ./nginx/html | /usr/share/nginx/html | ro | This directory contain the html static file for default virtual host, read [Static files section](#static-files) + +*All `from path` are relative to Docker-compose directory* + +### Virtual Hosts +Default NGINX conf import the additional configurations from `/etc/nginx/conf.d/*.conf`. The Path `Docker-compose/nginx/conf.d` is mounted in `/etc/nginx/conf.d` of NGINX container. Each `*.conf` file present in these directory is included in the NGINX configuration. + +In `Docker-compose/nginx/conf.d` is preconfigured the file `default.conf` with [Satosa Virtual Host][#satosa-vitual-host]. You can add more `.conf` file and more virtual host, buth generally is not clever. + +#### Satosa Virtual host +The Satosa Virtual Host listen exclusively on port 443 over protocol https. +The HTTPS protocol il limited at TLS1.3. +The older version of TLS and SSL are denyed + +NGINX configuration accept configurations from environments. In the default configuration the `server_name` is definied with with `$NGINX_HOST` env. If is not present this variable, Docker Compose assign `localhost` as `NGINX_HOST` value. + +TLS certificates will be searched in: +* `ssl_certificate /etc/nginx/certs/proxy_local.pem` - public certificate +* `ssl_certificate_key /etc/nginx/certs/proxy_local.key` - private key + +On default the directory `Docker-compose/nginx/certs` is mounted on `/etc/nginx/certs`. +An self signed certificate for server name `localhost` is persent in the certs directory. To public the host you must overwrite these file with a valid certificate for you server name. + +The virtual host root is set on `/usr/share/nginx/html`, the `Docker-compose/nginx/html` path is mounted over this directory. +To update the static file you must edit the files in `Docker-compose/nginx/html` path. + +For security are added these header key +* `X-Frame-Options "DENY"` to block the IFRAME +* `X-Content-Type-Options nosniff` prevent mime type sniffing +* `X-XSS-Protection "1; mode=block"` prevents some categories of XSS attacks +* `X-Robots-Tag none` crawler are not welcome + +`location @satosa` contain all information to send and get data from satosa-saml2spid uWSGI server. +The default configuration set `satosa-saml2spid:1000` as reverse uWSGI proxy destination. +This permits to balance the connection with multiple satosa-saml2spid instance. + +Satosa Virtual Host use the `try_files` directive to send the request on the proxy. +The proxy test if the request is sended to a existent file. If the file not exists send the request to @satosa location. On detail: +1. Test if the request is a existent directory with a `index.html` file. Example: if the request is `/pippo` NGINX try to serve `/usr/share/nginx/html/pippo/index.html` +2. Test if exists a file with the request path. Example: if request is `/pippo/pluto.html`, NGINX try to serve `/usr/share/nginx/html/pippo/pluto.html` +3. Send the request to `@satosa` location + +### Insights +* For more details and example on NGINX satosa virtual host read [satosa-vitual-host doc](./satosa-virtual-host.md) +* For more details on Satosa-saml2spid docker compose profiles read [docker-compose-profiles page](./docker-compose-profiles.md) + diff --git a/docs/systemd.md b/docs/systemd.md new file mode 100644 index 00000000..f2d56e17 --- /dev/null +++ b/docs/systemd.md @@ -0,0 +1,78 @@ +## Start a local Satosa-saml2spid istance with a SystemD Service + +This example is project with these assumptions: +* Satosa-saml2spid is installed in `/opt/satosa` +* Satosa-saml2spid is executed from a Python VirtualENV sited in `/opt/satosa/env` +* Satosa-saml2spid is executed from `satosa` user + +Create a new SystemD service with the command: +``` +sudo systemctl edit --force --full satosa.service +``` + +copy and personalize this service example: +``` +Description=UWSGI server for Satosa Proxy + +## Socket +# After=syslog.target +# Requires=satosa.sock +## Network +Requires=network.target +After=network.target + +[Service] +# Foreground process +Type=simple + +# Preferably configure a non-privileged user +User=satosa +Group=satosa +WorkingDirectory=/opt/satosa +ExecStart=/bin/bash -c 'cd /opt/satosa && source env/bin/activate && uwsgi --ini ./uwsgi_setup/uwsgi.ini --thunder-lock' +Restart=always +KillSignal=SIGQUIT + +## socket +# [Install] +# WantedBy=sockets.target +``` +Enable the service: +``` +sudo systemctl enable satosa.service +``` + +### Satosa with socket +If you want enable Satosa-saml2spid by socket you should edit the service: +``` +sudo systemctl edit --full satosa.service +``` +uncomment follow line: +* `After=syslog.target` +* `Requires=satosa.sock` +* `[Install]` +* `WantedBy=sockets.target` + +create the socket target: +``` +sudo systemctl edit --full --force satosa.sockets +``` + +Copy and personalize this socket example: +``` +[Unit] +Description=Socket for satosa + +[Socket] +# Change this to your uwsgi application port or unix socket location +ListenStream=/opt/satosa//tmp/sockets/satosa.sock +SocketMode=0770 + +[Install] +WantedBy=sockets.target +``` + +enable il socket: +``` +sudo systectl enable satosa.socket +``` diff --git a/docs/uwsgi.ini.md b/docs/uwsgi.ini.md new file mode 100644 index 00000000..57c233c2 --- /dev/null +++ b/docs/uwsgi.ini.md @@ -0,0 +1,190 @@ +## uWSGI configuration example + +Satosa proxy and his istance Satosa-saml2spid are served by uWSGY. NGINX work as HTTP <-> uWSGI proxy to one or more Satosa-saml2spid istance. + +General information on uWSGI ini configuration: + +* The uWSGI configuration Must be start with `[uwsgi]` +* Can be contain multiple arbitrary keys to generate structurated values, look `base` and `ckdir` keys as example. +* Must be contain the `socket` key with the file or the addres to expose the service +* can be contain `uid` and `gid` keys to define user and and group to execute the service +* If `uid` and `gid` keys are note defined, the service is started as current user and primary group +* must be contain `callable` or `module` key to run the correct application +* `ckdir` key define the derectory from the application must be executed +* if `pidfile` key is set with a file path, uWSGI on startup generate or update the file with the current Process ID (PID) +* You can add the `virtualenv` key with the path of [Python Virtual Env](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#create-and-use-virtual-environments), uWSGI search the dipendences in his VirtualEnv +* If `harakiri` key is set with a number, the inactive process are restarted after the setted seconds +* You can add `pythonpath` key to set the Python runtime path +* If `virtualenv` and `pythonpath` keys are not set, uWSGI use the system default path + + +On follow we present some uWSGI configuration example for various situations. + +### local instance with logrotate on localhost +#### important note: +* The project is located in `%(base)/%(project)` where `/opt` is `base` and `satosa-saml2spid` is `project` +* uWSGI server is runned with user: 'satosa' and group `satosa`. You can change this with the key `uid` and `gid` +* the VirtualEnv path is `%(base)/%(project)/env` or `/opt/satosa-saml2spid/env` +* Log are saved at `/var/log/uwsgi/%(project).log` or `/var/log/uwsgi/satosa-saml2spid.log` +* pid are saved at `/var/log/uwsgi/%(project).pid` or `/var/log/uwsgi/satosa-saml2spid.pid` +* the configuration is reloaded when change the date of `%(base)/%(project)/proxy_conf.yaml` or `/opt/satosa-saml2spid/proxy_conf.yaml` +* uwsgi server listen at 127.0.0.1:3002, only for local host! + +#### uwsgi.ini +```ini +[uwsgi] +project = satosa-saml2spid +base = /opt + +chdir = %(base)/%(project) + +uid = satosa +gid = satosa + +socket = 127.0.0.1:3002 +master = true +processes = 8 +# threads = 2 + +# sets max connections to +listen = 2048 + +wsgi-file = %(base)/%(project)/env/lib/python3.10/site-packages/satosa/wsgi.py +callable = app +# se installato con pip non serve il plugin perchè embedded +# plugins = python + +# con virtualenv non serve +# pythonpath = %(base)/%(project)/%(project) +virtualenv = %(base)/%(project)/env + +logto = /var/log/uwsgi/%(project).log +log-maxsize = 100000000 +log-backupname = /var/log/uwsgi/%(project).old.log + +log-master-bufsize = 128000 + +vacuum = True + +# respawn processes after serving ... requests +max-requests = 512 + +# respawn processes taking more than takes more then ... seconds +harakiri = 20 + +# avoid: invalid request block size: 4420 (max 4096)...skip +buffer-size=32768 + +pidfile = /var/log/uwsgi/%(project).pid +touch-reload = %(base)/%(project)/proxy_conf.yaml +``` + +### local instance on socket +#### important note +* The project is located in `%(base)/%(project)` where `/opt` is `base` and `satosa-saml2spid` is `project` +* uWSGI server is runned with user: 'satosa' and group `satosa`. You can change this with the key `uid` and `gid` +* the VirtualEnv path is `%(base)/%(project)/env` or `/opt/satosa-saml2spid/env` +* Log are saved at `/var/log/uwsgi/%(project).log` or `/var/log/uwsgi/satosa-saml2spid.log` +* pid are saved at `/var/log/uwsgi/%(project).pid` or `/var/log/uwsgi/satosa-saml2spid.pid` +* the configuration is reloaded when change the date of `%(base)/%(project)/proxy_conf.yaml` or `/opt/satosa-saml2spid/proxy_conf.yaml` +* uwsgi server listen in `/opt/satosa-saml2spid/tmp/sockets/satosa.sock` + + +#### uwsgi.ini +```ini +[uwsgi] +project = satosa-saml2 +base = /opt + +chdir = %(base)/%(project) + +uid = satosa +gid = satosa + +socket = %(base)/%(project)/tmp/sockets/satosa.sock +chmod-socket= 770 + +master = true +processes = 12 +#threads = 2 + +# set max connections to 1024 in uWSGI +listen = 5000 + +wsgi-file = %(base)/apps/SATOSA/src/satosa/wsgi.py +callable = app +# se installato con pip non serve il plugin perchè embedded +#plugins = python + +# con virtualenv non serve +#pythonpath = %(base)/%(project)/%(project) + +virtualenv = %(base)/django-pysaml2.env + +logto = /var/log/uwsgi/%(project).log +log-maxsize = 100000000 +log-backupname = /var/log/uwsgi/%(project).old.log + +vacuum = True + +# respawn processes after serving ... requests +max-requests = 1000 + +# respawn processes taking more than takes more then ... seconds +harakiri = 20 + +# avoid: invalid request block size: 4420 (max 4096)...skip +buffer-size=32768 + +#env = %(project).settings + +pidfile = /var/log/uwsgi/%(project).pid +touch-reload = %(base)/%(project)/proxy_conf.yaml +stats = 127.0.0.1:9193 +stats-http = True +``` + +### for docker container or simple local istance +#### Important note +* The project is located in `/satosa_proxy` +* uWSGI server is runned with user: 'root' and group `root`. You can change this with the key `uid` and `gid` +* Isn't user the virtualENV, uWSGY work with python system default +* The log are printed on STDOUT +* pid are saved at `/satosa_proxy/%(project).pid` +* the configuration is reloaded when change the date of `/satosa_proxy/proxy_conf.yaml +* uwsgi server listen in `0.0.0.0:10000` and accept connection from all + +#### uwsgi.ini +``` +[uwsgi] +project = satosa-saml2spid + +chdir = /satosa_proxy + +uid = root +gid = root + +socket = 0.0.0.0:10000 +master = true +processes = 8 + +# sets max connections to +listen = 2048 + +callable = app + +log-master-bufsize = 128000 +vacuum = True + +# respawn processes after serving ... requests +max-requests = 512 + +# respawn processes taking more than takes more then ... seconds +harakiri = 20 + +# avoid: invalid request block size: 4420 (max 4096)...skip +buffer-size=32768 + +pidfile = /satosa_proxy/%(project).pid +touch-reload = /satosa_proxy/proxy_conf.yaml +``` diff --git a/example/uwsgi_setup/SystemD/README.md b/example/uwsgi_setup/SystemD/README.md deleted file mode 100644 index 6fb9f6f7..00000000 --- a/example/uwsgi_setup/SystemD/README.md +++ /dev/null @@ -1,22 +0,0 @@ -### Avvio satosa tramite systemd - -I seguenti script sono esempi per avviare il proy satosa tramite SystemD. Negli esempi vengono considerati i seguenti presupposti: -* Satosa è installano nella directory `/home/satosa/production/current` -* Satosa viene eseguito in un VirtualENV di Python -* Il VitualENV di python è installato su `/home/satosa/production/current/satosa.env` -* Il Satosa proxy viene eseguito da l'utente satosa -* Il Satosa proxy è configurato per offrire servizi tramite socket -* Il socket Satosa è posizioneto su `ListenStream=/home/satosa/production/current/tmp/sockets/satosa.sock` - -Per configurare SystemD seguire la seguente procedura: - -* copiare i file `satosa.service` e `satosa.sock` nella directory /etc/systemd/systemd -* far rilegere i file di configurazione a SistemD con il comando `sudo systemctl daemon-reload` -* abilitare socket `sudo systemctl enable satosa.socket` -* abilitare il service `sudo systemct enable satosa.service` - -Nel caso Satosa proxy lavori tramite rete (es: 127.0.0.1:8003) -* disabilitare il socket `systemctl disable satosa.socket` -* commentare nel file `satosa.service` la riga `Requires=satosa.sock` -* decommentare nel file `satosa.service` la riga `Requires=network.target` -* decommentare nel file `satosa.service` la riga `After=network.target` diff --git a/example/uwsgi_setup/SystemD/satosa.service b/example/uwsgi_setup/SystemD/satosa.service deleted file mode 100644 index 6bfc568a..00000000 --- a/example/uwsgi_setup/SystemD/satosa.service +++ /dev/null @@ -1,24 +0,0 @@ -Description=UWSGI server for Satosa Proxy -## Socket -After=syslog.target -Requires=satosa.sock -## Network -# Requires=network.target -# After=network.target - - -[Service] -# Foreground process -Type=simple - -# Preferably configure a non-privileged user -User=satosa -Group=satosa -WorkingDirectory=/home/satosa/production/current -ExecStart=/bin/bash -c 'cd /home/satosa/production/current && source satosa.env/bin/activate && uwsgi --ini ./uwsgi_setup/uwsgi.ini --thunder-lock' -Restart=always -KillSignal=SIGQUIT - -[Install] -WantedBy=sockets.target - diff --git a/example/uwsgi_setup/SystemD/satosa.socket b/example/uwsgi_setup/SystemD/satosa.socket deleted file mode 100644 index c295b91c..00000000 --- a/example/uwsgi_setup/SystemD/satosa.socket +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Socket for satosa - -[Socket] -# Change this to your uwsgi application port or unix socket location -ListenStream=/home/satosa/production/current/tmp/sockets/satosa.sock -SocketMode=0770 - -[Install] -WantedBy=sockets.target diff --git a/example/uwsgi_setup/nginx/README.md b/example/uwsgi_setup/nginx/README.md deleted file mode 100644 index f9280f51..00000000 --- a/example/uwsgi_setup/nginx/README.md +++ /dev/null @@ -1,4 +0,0 @@ -### Esempi di configurazione nginx -Per i seguenti esempi di configurazioni viene ipotizzache che un server NGINX faccia da proxy verso una o più istanze satosa. All'interno delle configurazioni si considera che: -* il Satosa Proxy é installato nella directory `/opt/satosa-saml2/` -* sia installata una versione recenti del web server NGINX con supporto tls 1.3 diff --git a/example/uwsgi_setup/nginx/net_proxy.conf b/example/uwsgi_setup/nginx/net_proxy.conf deleted file mode 100644 index e5c9de15..00000000 --- a/example/uwsgi_setup/nginx/net_proxy.conf +++ /dev/null @@ -1,75 +0,0 @@ -# the upstream component nginx needs to connect to -upstream satosa-saml2 { - server satosa-saml2spid:10000; -} - -# configuration of the server -server { - if ($host = demo.proxy.eudi.wallet.developers.italia.it) { - return 301 https://$host$request_uri; - } # managed by Certbot - - - listen 80; - server_name demo.proxy.eudi.wallet.developers.italia.it; - access_log /var/log/nginx/proxy_satosa_it.access.log; - error_log /var/log/nginx/proxy_satosa_it.error.log error; - return 301 https://$host$request_uri; - - -} - -server { - server_name demo.proxy.eudi.wallet.developers.italia.it; - listen 443 ssl; - ssl_certificate /etc/letsencrypt/live/demo.proxy.eudi.wallet.developers.italia.it/fullchain.pem; # managed by Certbot - ssl_certificate_key /etc/letsencrypt/live/demo.proxy.eudi.wallet.developers.italia.it/privkey.pem; # managed by Certbot - - access_log /var/log/nginx/proxy_satosa_it.log; - error_log /var/log/nginx/proxy_satosa_it.log error; - - # max upload size - client_max_body_size 8M; - - # very long url for delega ticket - large_client_header_buffers 4 16k; - - # satosa static - location /static { - alias /opt/satosa-saml2spid/example-openid4vp/static; - autoindex off; - } - location /bootstrap-italia/dist { - alias /opt/satosa-saml2spid/example-openid4vp/static/bootstrap-italia; - autoindex off; - } - - # Finally, send all non-media requests to satosa server. - location / { - uwsgi_pass satosa-saml2; - uwsgi_param HTTP_X_FORWARDED_PROTOCOL https; - - # fix: Cookie SameSite: https://github.com/IdentityPython/SATOSA/issues/245 - proxy_cookie_path ~(/*) "$1; SameSite=None; Secure"; - - # Enable HTTP Strict Transport Security with a 2 year duration - add_header Strict-Transport-Security "max-age=63072000; "; - - # deny iFrame - add_header X-Frame-Options "SAMEORIGIN"; - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Robots-Tag none; - - - include /opt/satosa-saml2spid/example-openid4vp/uwsgi_setup/uwsgi_params; # the uwsgi_params file you installed - - uwsgi_read_timeout 33; - - # fix long url upstream buffer size - uwsgi_buffer_size 128k; - uwsgi_buffers 4 256k; - uwsgi_busy_buffers_size 256k; - } - -} diff --git a/example/uwsgi_setup/nginx/socket_proxy.conf b/example/uwsgi_setup/nginx/socket_proxy.conf deleted file mode 100644 index 720c6452..00000000 --- a/example/uwsgi_setup/nginx/socket_proxy.conf +++ /dev/null @@ -1,77 +0,0 @@ -# the upstream component nginx needs to connect to -upstream satosa-saml2 { - server unix:///opt/satosa-saml2/tmp/sockets/satosa.sock; -} - -# configuration of the server -server { - listen 80; - server_name proxy.satosa.it; - access_log /var/log/nginx/proxy_satosa_it.access.log; - error_log /var/log/nginx/proxy_satosa_it.error.log error; - return 301 https://$host$request_uri; -} - -server { - server_name proxy.satosa.it; - listen 443 ssl; - - ssl_certificate /etc/ssl/certs/proxy.satosa.it/proxy_satosa_it.crt; - ssl_certificate_key /etc/ssl/certs/proxy.satosa.it/proxy_satosa_it.key; - - access_log /var/log/nginx/proxy_satosa_it.log; - error_log /var/log/nginx/proxy_satosa_it.log error; - - # max upload size - client_max_body_size 8M; - - # very long url for delega ticket - large_client_header_buffers 4 16k; - - # SSL HARDENING - # disable poodle attack - ssl_protocols TLSv1.2 TLSv1.3; - ssl_prefer_server_ciphers on; - ssl_dhparam /etc/nginx/dhparam.pem; - ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 - ssl_session_timeout 10m; - ssl_session_cache shared:SSL:10m; - ssl_session_tickets off; # Requires nginx >= 1.5.9 - ssl_stapling on; # Requires nginx >= 1.3.7 - ssl_stapling_verify on; # Requires nginx => 1.3.7 - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; - add_header X-Frame-Options DENY; - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Robots-Tag none; - # FINE SSL HARDENING - - # satosa static - location /static { - alias /opt/satosa-saml2/static; - autoindex off; - } - - # Finally, send all non-media requests to satosa server. - location / { - uwsgi_pass satosa-saml2; - uwsgi_param HTTP_X_FORWARDED_PROTOCOL https; - - # fix: Cookie SameSite: https://github.com/IdentityPython/SATOSA/issues/245 - proxy_cookie_path ~(/*) "$1; SameSite=None; Secure"; - - # Enable HTTP Strict Transport Security with a 2 year duration - add_header Strict-Transport-Security "max-age=63072000; "; - - # deny iFrame - add_header X-Frame-Options "DENY"; - - uwsgi_read_timeout 40; - include /opt/satosa-saml2/uwsgi_setup/uwsgi_params; # the uwsgi_params file you installed - - # fix long url upstream buffer size - uwsgi_buffer_size 128k; - uwsgi_buffers 4 256k; - uwsgi_busy_buffers_size 256k; - } -}