diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 51a9e1d0..54e7e32f 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -18,9 +18,7 @@ jobs: fail-fast: false matrix: python-version: - - '3.9' - '3.10' - - '3.11' steps: - uses: actions/checkout@v3 diff --git a/README-Setup.md b/README-Setup.md index fb11e85e..219210d0 100644 --- a/README-Setup.md +++ b/README-Setup.md @@ -24,6 +24,8 @@ sudo yum install -y python3-wheel python3-devel ###### Prepare environment +Within the directory `/{your path}/Satosa-Saml2Spid` execute the following commands: + ``` pip install --upgrade pip pip install virtualenv @@ -39,7 +41,7 @@ pip install -r requirements.txt ## Configure the Proxy -- Create certificates for SPID see [psmiraglia](https://github.com/italia/spid-compliant-certificates). +- Create certificates for SPID, using [spid-compliant-certificates](https://github.com/italia/spid-compliant-certificates) or [spid-compliant-certificates-python](https://github.com/italia/spid-compliant-certificates-python) - Copy `repository/example/*` contents (`cp -R repository/example/* .`) and **edit the files below** - `proxy_conf.yaml` diff --git a/README.md b/README.md index 097437cc..59a25a9a 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,14 @@ with the **Italian Digital Identity Systems**. ## Table of Contents -1. [Goal](#goal) -2. [Demo components](#demo-components) -3. [Docker](#docker) -6. [Setup](README-Setup.md) -8. [For Developers](#for-developers) -9. [Author](#authors) -10. [Credits](#credits) +1. [Glossary](#Glossary) +2. [General features](#general-features) +3. [Introduction](#introduction) +4. [Demo components](#demo-components) +5. [Setup](#setup) +6. [For Developers](#for-developers) +7. [Author](#authors) +8. [Credits](#credits) ## Glossary @@ -59,15 +60,11 @@ limitations, traditionally could not interact each other. ## Demo components -The example project comes with the following demo pages, served -with the help of an additional webserver dedicated for static contents: +The example project comes with some preconfigured static pages. + -###### Discovery Service page - - - -See other page screenshot [here](README-GALLERY.md). +for other page screenshots, see [here](README-GALLERY.md). These demo pages are static files, available in `example/static`. To get redirection to these pages, or redirection to third-party services, it is required to configure the files below: @@ -76,41 +73,61 @@ To get redirection to these pages, or redirection to third-party services, it is - file: `example/plugins/{backends,frontends}/$filename`, example value: `disco_srv: "https://static-contents.example.org/static/disco.html"` -## Docker +## Usage + +The average time to set up this project for your needs takes roughly 1 hour. +This time may vary depending on your configuration, how many backend and +frontend you configure, the machine's resources and the type of network +connection for the download of the docker images. + +For the setup of this project, the following dependency must be installed in your machine: + + - Python 3.10 or higher + - Git + - Docker + +### Setup + +All the setup instructions for your Satosa-Saml2spid configuration are available in [README-SETUP.md](README-Setup.md). + +### Docker Compose + +This project uses Docker, all the instructions to configure this project using the official docker images are available in [Docker-compose](Docker-compose/README.md). + +The docker compose may use the [enviroment variables](README-Setup.md#configuration-by-environment-variables) +to configure Satosa-Saml2Spid. The official Satosa-Saml2SPID docker image is available at [italia/satosa-saml2spid](https://ghcr.io/italia/satosa-saml2spid). -Below some quick commands: +To install it, you can execute the following command: `sudo docker pull ghcr.io/italia/satosa-saml2spid:latest`. -- Install it, execute the following command: `sudo docker pull ghcr.io/italia/satosa-saml2spid:latest`. -- Build locally the image, execute the following command: `docker build -t satosa-saml2spid .`. -- Inspect the image content: `docker run -it -v $(pwd)/example:/satosa_proxy --entrypoint sh satosa-saml2spid`. +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`. -### Docker compose -Satosa-Saml2Spid image is built with production ready logic. -The docker compose may use the [enviroment variables](#configuration-by-environment-variables) -to configure Satosa-Saml2Spid. +### Setup a Djangosaml2 example Service Provider -See [Docker-compose](Docker-compose) for details. +This project provides an example SAML2 Service Provider for demo purposes, +this Service Provider is executed by default in the Docker Compose. +For any further detail about its configuration, see [example_sp/djangosaml2_sp/README.md](example_sp/djangosaml2_sp/README.md). -## Setup +Below the demo using the djangosaml2 Service Provider with the Wallet authentication [OpenID4VP ](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html). -See [README-SETUP.md](README-Setup.md). + ## For Developers -If you're doing tests and you don't want to pass through the Discovery page each time you can use `idphinting` if your SP support it. +If you're running tests and you don't want to pass through the Discovery page each time you can use `idphinting` if your SP support it. Below an example using a djangosaml2 Service Provider: ``` -http://localhost:8000/saml2/login/?idp=https://localhost:10000/Saml2IDP/metadata&next=/saml2/echo_attributes&idphint=https%253A%252F%252Flocalhost%253A8080 +http://localhost:8000/saml2/login/?idp=https://localhost/Saml2IDP/metadata&next=/saml2/echo_attributes&idphint=https%253A%252F%252Flocalhost%253A8080 ``` If you're going to test Satosa-Saml2Spid with spid-sp-test, take a look to diff --git a/example/README.md b/example/README.md new file mode 100644 index 00000000..37299e1f --- /dev/null +++ b/example/README.md @@ -0,0 +1,31 @@ +### Pre-requirements + +Make sure that the following Docker containers are up and running + + + + +> **NOTE** +> - use the following command to check if everythings is correctly running ``docker ps -a`` +> - use the following command to start a stopped container ``docker start `` + +
+ +if everything is okay, you will be able to access the login Saml2 service provider page + + + + + +### To log in, follow the steps described in the image below: + +![result](../gallery/screen.gif) + +> #### NOTE: +> +> - Use "Entra con SPID" and select "Spid_Test" Method +> - Use the following credential -> user: validator | psw: validator +> - Use the following link to Load Metadata `https://satosa-nginx/spidSaml2/metadata` +> + + diff --git a/example_sp/djangosaml2_sp/README.md b/example_sp/djangosaml2_sp/README.md index bc7d617f..bfd140d4 100644 --- a/example_sp/djangosaml2_sp/README.md +++ b/example_sp/djangosaml2_sp/README.md @@ -1,3 +1,8 @@ +# How to run the Demo Django template + + + Within the directory `/{your path}/Satosa-Saml2Spid/example_sp` execute the following commands + ### djangosaml2-sp (SP server) ```` sudo apt install xmlsec1 python3-dev python3-pip libssl-dev @@ -8,7 +13,7 @@ source env/bin/activate cd djangosaml2_sp # download idp metadata to sp, not needed if remote options is enabled -wget https://localhost:10000/Saml2IDP/metadata/ -O saml2_sp/saml2_config/satosa-saml2spid.xml --no-check-certificate +wget https://localhost/Saml2IDP/metadata/ -O saml2_sp/saml2_config/satosa-saml2spid.xml --no-check-certificate # install prerequisite pip install -r requirements.txt @@ -20,6 +25,23 @@ python manage.py migrate ./manage.py runserver 0.0.0.0:8000 ```` +At the end of the execution, the server will be started at the following link: http://0.0.0.0:8000 +and you will be able to view the project's demo page (see below) + + + + + + + + +Now click on "Accedi all'area personale" (at the top right of the page header). +You will be redirect to the Saml2 Service Provider page [Service Provider page](../../example/README.md) + + + + + ### Add SP metadata to Satosa server ``` # put sp metadata to satosa diff --git a/example_sp/djangosaml2_sp/djangosaml2_sp/sp_pysaml2_satosa.py b/example_sp/djangosaml2_sp/djangosaml2_sp/sp_pysaml2_satosa.py index e0c0f509..3228d892 100644 --- a/example_sp/djangosaml2_sp/djangosaml2_sp/sp_pysaml2_satosa.py +++ b/example_sp/djangosaml2_sp/djangosaml2_sp/sp_pysaml2_satosa.py @@ -207,6 +207,8 @@ 'eduPersonEntitlement': ('eduPersonEntitlement',), 'schacPersonalUniqueCode': ('schacPersonalUniqueCode',), + "givenName": ('first_name', ), + # spid related 'name': ('first_name', ), 'familyName': ('last_name', ), diff --git a/example_sp/djangosaml2_sp/djangosaml2_sp/urls.py b/example_sp/djangosaml2_sp/djangosaml2_sp/urls.py index 21a985e9..b9d5f64f 100644 --- a/example_sp/djangosaml2_sp/djangosaml2_sp/urls.py +++ b/example_sp/djangosaml2_sp/djangosaml2_sp/urls.py @@ -4,6 +4,8 @@ from django.contrib.auth.views import LogoutView from django.urls import include, path +from saml2_sp.views import amministrazione, index, echo_attributes + urlpatterns = [ path('admin/', admin.site.urls), ] @@ -13,17 +15,22 @@ SAML2_URL_PREFIX = 'saml2' urlpatterns.extend([ - path('', include((saml2_sp.urls, 'sp',))), + #path('', include((saml2_sp.urls, 'sp',))), + path(f'', index, name='index'), + path(f'amministrazione/', amministrazione, name='amministrazione'), + path(f'echo_attributes/', echo_attributes, name='echo_attributes'), + path(f'{SAML2_URL_PREFIX}/login/', views.LoginView.as_view(), name='saml2_login'), path(f'{SAML2_URL_PREFIX}/acs/', views.AssertionConsumerServiceView.as_view(), name='saml2_acs'), path(f'{SAML2_URL_PREFIX}/logout/', views.LogoutInitView.as_view(), name='saml2_logout'), path(f'{SAML2_URL_PREFIX}/ls/', views.LogoutView.as_view(), name='saml2_ls'), path(f'{SAML2_URL_PREFIX}/ls/post/', views.LogoutView.as_view(), name='saml2_ls_post'), path(f'{SAML2_URL_PREFIX}/metadata/', views.MetadataView.as_view(), name='saml2_metadata'), - path(f'{SAML2_URL_PREFIX}/echo_attributes', views.EchoAttributesView.as_view(), name='saml2_echo_attributes'), + # path(f'{SAML2_URL_PREFIX}/echo_attributes', views.EchoAttributesView.as_view(), name='saml2_echo_attributes'), path('logout/', LogoutView.as_view(), {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout') ]) + if 'djangosaml2_spid' in settings.INSTALLED_APPS: import djangosaml2_spid.urls diff --git a/example_sp/djangosaml2_sp/saml2_sp/templates/echo_attributes.html b/example_sp/djangosaml2_sp/saml2_sp/templates/echo_attributes.html index fca882e6..17df15f5 100644 --- a/example_sp/djangosaml2_sp/saml2_sp/templates/echo_attributes.html +++ b/example_sp/djangosaml2_sp/saml2_sp/templates/echo_attributes.html @@ -1,30 +1,37 @@ {% extends "base.html" %} {% load i18n %} {% load static %} -{% block container %} +{% block container %}
+
{% endblock %} - \ No newline at end of file + diff --git a/example_sp/djangosaml2_sp/saml2_sp/views.py b/example_sp/djangosaml2_sp/saml2_sp/views.py index e60afccd..5b0f6fe6 100644 --- a/example_sp/djangosaml2_sp/saml2_sp/views.py +++ b/example_sp/djangosaml2_sp/saml2_sp/views.py @@ -47,16 +47,18 @@ def index(request): """ Barebone 'diagnostics' view, print user attributes if logged in + login/logout links. """ - return render(request,"base.html",context) + return render(request, "base.html", context) + def amministrazione(request): - return render(request,"amministrazione.html",context) + return render(request, "amministrazione.html", context) + def echo_attributes(request): - context['attribute_display_names']=attribute_display_names - return render(request,"echo_attributes.html",context) + context['attribute_display_names'] = attribute_display_names + return render(request, "echo_attributes.html", context) + -# TODO fix this in IdP side? @receiver(pre_user_save, sender=User) def custom_update_user(sender, instance, attributes, user_modified, **kargs): """ Default behaviour does not play nice with booleans encoded in SAML as u'true'/u'false'. @@ -66,4 +68,4 @@ def custom_update_user(sender, instance, attributes, user_modified, **kargs): u = set.intersection(set(v), set([u'true', u'false'])) if u: setattr(instance, k, u.pop() == u'true') - return True # I modified the user object + return True diff --git a/gallery/disco.png b/gallery/disco.png deleted file mode 100644 index b9a0e0ed..00000000 Binary files a/gallery/disco.png and /dev/null differ diff --git a/gallery/disco_page.png b/gallery/disco_page.png new file mode 100644 index 00000000..ad1bc05d Binary files /dev/null and b/gallery/disco_page.png differ diff --git a/gallery/djangosaml2_sp.png b/gallery/djangosaml2_sp.png new file mode 100644 index 00000000..5b8c413e Binary files /dev/null and b/gallery/djangosaml2_sp.png differ diff --git a/gallery/docker_container.png b/gallery/docker_container.png new file mode 100644 index 00000000..12cb7b04 Binary files /dev/null and b/gallery/docker_container.png differ diff --git a/gallery/wallet-demo.gif b/gallery/wallet-demo.gif new file mode 100644 index 00000000..3169e629 Binary files /dev/null and b/gallery/wallet-demo.gif differ