README.md 15.3 KB
Newer Older
Marco Malavolti's avatar
Marco Malavolti committed
1
# EduGAIN Connectivity Check Service - ECCS
Marco Malavolti's avatar
Marco Malavolti committed
2

Marco Malavolti's avatar
Marco Malavolti committed
3
4
5
6
7
8
9
10
1. [Introduction](#introduction)
2. [Check Performed on the IdPs](#check-performed-on-the-idps)
3. [Limitations](#limitations)
4. [Disable Checks](#disable-checks)
5. [On-line interface](#on-line-interface)
6. [Requirements Hardware](#requirements-hardware)
7. [Requirements Software](#requirements-software)
8. [HOWTO Install and Configure](#howto-install-and-configure)
Marco Malavolti's avatar
Marco Malavolti committed
11
   * [Python 3](#python-3)
Marco Malavolti's avatar
Marco Malavolti committed
12
13
     + [CentOS 7 requirements](#centos-7-requirements)
     + [Debian requirements](#debian-requirements)
Marco Malavolti's avatar
Marco Malavolti committed
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
     + [Install](#install)
   * [Install the Chromedriver](#install-the-chromedriver)
   * [Install Google Chrome needed by Selenium](#install-google-chrome-needed-by-selenium)
   * [ECCS Script](#eccs-script)
     + [Install](#install-1)
     + [Configure](#configure)
     + [Execute](#execute)    
9. [ECCS API Server (UWSGI)](#eccs-api-server-uwsgi)
   * [Install](#install-1)
   * [Configure](#configure-1)
   * [Utility](#utility)
10. [ECCS API JSON](#eccs-api-json)
11. [Utility for web interface](#utility-for-web-interface)
12. [Utility for developers](#utility-for-developers)
    * [ECCS API Development Server](#eccs-api-development-server)
13. [Authors](#authors)
Marco Malavolti's avatar
Marco Malavolti committed
30
31
32

# Introduction

Marco Malavolti's avatar
Marco Malavolti committed
33
The purpose of the eduGAIN Connectivity Check is to identify eduGAIN Identity Providers (IdP) that are not properly configured. In particular it checks if an IdP properly loads and consumes SAML2 metadata which contains the eduGAIN Service Providers (SP). The check results are published on the public eduGAIN Connectivity Check web page (### NOT-AVAILABLE-YET ###). The main purpose is to increase the service overall quality and user experience of the eduGAIN interfederation service by making federation and Identity Provider operators aware of configuration problems.
Marco Malavolti's avatar
Marco Malavolti committed
34
35
36
37
38
39
40
41
42
43
44
45

The check is performed by sending a SAML authentication request to each eduGAIN IdP and then follow the various HTTP redirects. The expected result is a login form that allows users to authenticate (typically with username/password) or an error message of some form. For those Identity Providers that output an error message, it can be assumed that they don't consume eduGAIN metadata properly or that they suffer from another configuration problem. There are some cases where the check will generate false positives, therefore IdPs can be excluded from checks as is described below.

The Identity Providers are checked once per day. Therefore, the login requests should not have any significant effect on the log entries/statistics of an Identity Provider. Also, no actual login is performed because the check cannot authenticate users due to missing username and password for the IdPs. Only Identity Providers are checked but not the Service Providers.

# Check Performed on the IdPs

The check executed by the service follows these steps:

1. It retrieves the eduGAIN IdPs from eduGAIN Operator Team database via a JSON interface

2. For each IdP that is was not manually disabled by the eduGAIN Operations Team, the check creates a Wayfless URL for each SP involved and retrieves the IdP login page. It expects to find the HTML form with a username and password field. Therefore, no complete login will happen at the Identity Provider because the check stops at the login page.
Marco Malavolti's avatar
Marco Malavolti committed
46
The SPs used for the check are "SP Demo provided by GARR" (https://sp-demo.idem.garr.it/shibboleth) from IDEM GARR AAI and the "AAI Viewer Interfederation Test" (https://attribute-viewer.aai.switch.ch/interfederation-test/shibboleth) from SWITCHaai. These SPs might change in the future if needed.
Marco Malavolti's avatar
Marco Malavolti committed
47
48
49
50
51
52
53
54
55
56
57
58
The SAML authenticatin request is not signed. Therefore, authentication request for any eduGAIN SP could be created because the SP's private key is not needed.

# Limitations

There are some situations where the check cannot work reliably. In those cases it is possible to disable the check for a particular IdP. The so far known cases where the check might generate a false negative are:

* IdP does not support HTTP or HTTPS with at least SSLv3 or TLS1 or newer (these IdPs are insecure anyway)
* IdP is part of a Hub & Spoke federation (some of them manually have to first approve eduGAIN SPs)
* IdP does not use web-based login form (e.g. HTTP Basic Authentication or X.509 login)

# Disable Checks

59
60
61
62
63
64
In cases where an IdP cannot be reliably checked, it is necessary to create or enrich the `robots.txt` file on the IdP's web root with:

```bash
User-agent: ECCS
Disallow: /
```
Marco Malavolti's avatar
Marco Malavolti committed
65
66
67

# On-line interface

Marco Malavolti's avatar
Marco Malavolti committed
68
The test eduGAIN Connectivity Check web pages is available at: https://technical-test.edugain.org/eccs
Marco Malavolti's avatar
Marco Malavolti committed
69
70
71
72

The tool uses following status for IdPs:

* ERROR (red):
Marco Malavolti's avatar
Marco Malavolti committed
73
74
75
76
77
78
79
80
81
  * The IdP's response contains an HTTP Error or the web page returned does not look like a login page.
    * **Invalid-Form**: considers those IdPs that do not load a standard username/password login page and do not return messages like "No return endpoint available for relying party" or "No metadata found for relying party".
    * **Timeout**: considers those IdPs that do not load a standard username/password login page within 60 seconds.
    * **Connection-Error**: considers those IdPs that are not reachable due to a connection problem. View the "Page Source" value to discover which problem the IdP has. 
  * The IdP most likely does not consume the eduGAIN metadata correctly.
    A typical case that falls into this category is when an IdP returns a message "No return endpoint available for relying party" or "No metadata found for relying party":
    * **No-eduGAIN-Metadata**
  * The IdP has a problem with its SSL certificate:
    * **SSL-Error**
Marco Malavolti's avatar
Marco Malavolti committed
82
83
* OK (green):
  * The IdP most likely correctly consumes eduGAIN metadata and returns a valid login page. This is no guarantee that login on this IdP works for all eduGAIN services but if the check is passed for an IdP, this is probable.
Marco Malavolti's avatar
Marco Malavolti committed
84
* DISABLED (white)
Marco Malavolti's avatar
Marco Malavolti committed
85
  * The IdP is excluded because it cannot be checked reliably. The "Page Source" column, when an entity is disabled, shows the reason of the disabling.
Marco Malavolti's avatar
Marco Malavolti committed
86

87
88
# Requirements Hardware

Marco Malavolti's avatar
Marco Malavolti committed
89
* OS: Debian 9, CentOS 7.8 (tested)
90
91
* HDD: 10 GB
* RAM: 4 GB
92
* CPU: >= 2 vCPU (suggested)
Marco Malavolti's avatar
Marco Malavolti committed
93
* ARCH: 64 Bit
94
95
96
97

# Requirements Software

* Apache Server + WSGI
98
* Python 3 (tested with v3.9.1)
Marco Malavolti's avatar
Marco Malavolti committed
99
100
101
* Selenim + Google Chrome Web Brower (tested with v91.0.4472.164)
* Chromedriver (tested with v91.0.4472.101)
* Git
102
103
104

# HOWTO Install and Configure

Marco Malavolti's avatar
Marco Malavolti committed
105
## Download ECCS Repository
106

Marco Malavolti's avatar
Marco Malavolti committed
107
* `cd $HOME ; git clone https://gitlab.geant.org/edugain/eccs.git`
108

Marco Malavolti's avatar
Marco Malavolti committed
109
## Install Python 3
Marco Malavolti's avatar
Marco Malavolti committed
110
111
112
113
114
115

### CentOS 7 requirements

1. Update the system packages:
   * `sudo yum -y update`

116
117
2. Install the YUM utils:
   * `sudo yum install yum-utils`
Marco Malavolti's avatar
Marco Malavolti committed
118
119

3. Install needed packages to build python:
120
   * `sudo yum-builddep python3`
Marco Malavolti's avatar
Marco Malavolti committed
121

Marco Malavolti's avatar
Marco Malavolti committed
122
123
124
4. Install Git:
   * `sudo yum -y install git`

Marco Malavolti's avatar
Marco Malavolti committed
125
### Debian requirements
126
127
128
129

1. Update the system packages:
   * `sudo apt update ; sudo apt upgrade -y`

130
131
2. Install needed packages to build python3:
   * `sudo apt-get build-dep python3`
132

Marco Malavolti's avatar
Marco Malavolti committed
133
134
135
3. Install Git:
   * `sudo apt install git`

Marco Malavolti's avatar
Marco Malavolti committed
136
### Install
137

Marco Malavolti's avatar
Marco Malavolti committed
138
1. Download the last version of Python 3 from https://www.python.org/downloads/source/ into your home:
139
   * `wget https://www.python.org/ftp/python/3.9.1/Python-3.9.1.tgz -O $HOME/eccs/Python-3.9.1.tgz`
140

Marco Malavolti's avatar
Marco Malavolti committed
141
2. Extract Python source package:
Marco Malavolti's avatar
Marco Malavolti committed
142
   * `cd $HOME/eccs/`
143
   * `tar xzf Python-3.9.1.tgz`
144

Marco Malavolti's avatar
Marco Malavolti committed
145
3. Build Python from the source package:
146
   * `cd $HOME/eccs/Python-3.9.1`
Marco Malavolti's avatar
Marco Malavolti committed
147
   * `./configure --prefix=$HOME/eccs/python`
148
149
   * `make`

Marco Malavolti's avatar
Marco Malavolti committed
150
4. Install Python 3 under `$HOME/eccs/python`:
151
   * `make install`
Marco Malavolti's avatar
Marco Malavolti committed
152
   * `$HOME/eccs/python/bin/python3 --version`
153
 
Marco Malavolti's avatar
Marco Malavolti committed
154
   This will install python3 under your $HOME/eccs directory.
155
156
   
5. Remove useless things:
157
   * `rm -Rf $HOME/eccs/Python-3.9.1 $HOME/eccs/Python-3.9.1.tgz`
158

Marco Malavolti's avatar
Marco Malavolti committed
159
## Install Google Chrome needed by Selenium
160

Marco Malavolti's avatar
Marco Malavolti committed
161
* Debian (64 bit):
Marco Malavolti's avatar
Marco Malavolti committed
162
  * `cd $HOME/eccs`
Marco Malavolti's avatar
Marco Malavolti committed
163
164
  * `sudo wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb`
  * `sudo apt install ./google-chrome-stable_current_amd64.deb`
Marco Malavolti's avatar
Marco Malavolti committed
165

Marco Malavolti's avatar
Marco Malavolti committed
166
* CentOS (64 bit):
Marco Malavolti's avatar
Marco Malavolti committed
167
  * `cd $HOME/eccs`
Marco Malavolti's avatar
Marco Malavolti committed
168
169
  * `sudo wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm`
  * `sudo yum install ./google-chrome-stable_current_x86_64.rpm`
170

Marco Malavolti's avatar
Marco Malavolti committed
171
## Install the Chromedriver
172

Marco Malavolti's avatar
Marco Malavolti committed
173
174
1. Find out which version of Chromium you are using:
   * Debian 9 (stretch):
Marco Malavolti's avatar
Marco Malavolti committed
175
     * `google-chrome -version` => Google Chrome 91.0.4472.164
Marco Malavolti's avatar
Marco Malavolti committed
176
   * CentOS 7.8:
Marco Malavolti's avatar
Marco Malavolti committed
177
     * `google-chrome -version` => Google Chrome 91.0.4472.164
Marco Malavolti's avatar
Marco Malavolti committed
178
179
180
181
182
183

2. Take the Chrome version number, remove the last part, and append the result to URL "`https://chromedriver.storage.googleapis.com/LATEST_RELEASE_`". For example, with Chrome version 73.0.3683.75, you'd get a URL "`https://chromedriver.storage.googleapis.com/LATEST_RELEASE_73.0.3683`".

3. Use the URL created in the last step to discover the version of ChromeDriver to use. For example, the above URL will get your a file containing "73.0.3683.68".

4. Use the version number retrieved from the previous step to construct the URL to download ChromeDriver. With version `72.0.3626.69`, the URL would be "https://chromedriver.storage.googleapis.com/index.html?path=73.0.3683.68/"
184

Marco Malavolti's avatar
Marco Malavolti committed
185
5. Download the Chromedriver and extract it with:
Marco Malavolti's avatar
Marco Malavolti committed
186
   * `cd $HOME/eccs`
Marco Malavolti's avatar
Marco Malavolti committed
187
   * `wget https://chromedriver.storage.googleapis.com/73.0.3683.75/chromedriver_linux64.zip`
Marco Malavolti's avatar
Marco Malavolti committed
188
   * `unzip chromedriver_linux64.zip`
Marco Malavolti's avatar
Marco Malavolti committed
189
   * `rm chromedriver_linux64.zip google-chrome-stable_current_amd64.deb`
Marco Malavolti's avatar
Marco Malavolti committed
190
191
192

**Note:**
After the initial download, it is recommended that you occasionally go through the above process again to see if there are any bug fix releases.
193

Marco Malavolti's avatar
Marco Malavolti committed
194
## ECCS Script
Marco Malavolti's avatar
Marco Malavolti committed
195

Marco Malavolti's avatar
Marco Malavolti committed
196
### Install and Configure the Virtual Environment
Marco Malavolti's avatar
Marco Malavolti committed
197

Marco Malavolti's avatar
Marco Malavolti committed
198
199
200
201
202
203
* `cd $HOME/eccs`
* `./python/bin/python3 -m pip install virtualenv`
* `$HOME/eccs/python/bin/virtualenv --python=$HOME/eccs/python/bin/python3 eccs-venv`
* `$HOME/eccs/eccs-venv/bin/python3 -m pip install --upgrade pip`
* `source eccs-venv/bin/activate`   (`deactivate` to exit Virtualenv)
  * `python3 -m pip install -r requirements.txt`
204

Marco Malavolti's avatar
Marco Malavolti committed
205
### Configure ECCS
206

Marco Malavolti's avatar
Marco Malavolti committed
207
208
1. Configure ECCS properties:
   * `vim eccs_properties.py` (and change it upon your needs)
209

210
2. Change `PATH` by adding the virtualenv Python `bin` dir:
211
212
   * CentOS:
     * `vim $HOME/.bash_profile`
Marco Malavolti's avatar
Marco Malavolti committed
213
214
215
     * Add the following lines at the tail:
       
       ```bash
Marco Malavolti's avatar
Marco Malavolti committed
216
217
218
       # set PATH for ECCS
       if [ -d "$HOME/eccs" ] ; then
          PATH="$HOME/eccs/eccs-venv/bin:$PATH"
Marco Malavolti's avatar
Marco Malavolti committed
219
220
221
       fi
       ```

Marco Malavolti's avatar
Marco Malavolti committed
222
223
     * `source $HOME/.bash_profile`

224
   * Debian:
Marco Malavolti's avatar
Marco Malavolti committed
225
     * `vim $HOME/.bash_profile`
Marco Malavolti's avatar
Marco Malavolti committed
226
227
228
     * Add the following lines at the tail:
       
       ```bash
Marco Malavolti's avatar
Marco Malavolti committed
229
230
231
       # set PATH for ECCS
       if [ -d "$HOME/eccs" ] ; then
          PATH="$HOME/eccs/eccs-venv/bin:$PATH"
Marco Malavolti's avatar
Marco Malavolti committed
232
233
234
       fi
       ```

Marco Malavolti's avatar
Marco Malavolti committed
235
236
     * `source $HOME/.bash_profile`

Marco Malavolti's avatar
Marco Malavolti committed
237
3. Configure ECCS cron job for the local user:
238
   * `crontab -e`
239

240
     ```bash
Marco Malavolti's avatar
Marco Malavolti committed
241
242
     SHELL=/bin/bash

Marco Malavolti's avatar
Marco Malavolti committed
243
     0 4 * * * /bin/bash $HOME/eccs/cleanAndRunEccs.sh > $HOME/eccs/logs/eccs-cron.log 2>&1
244
     ```
Marco Malavolti's avatar
Marco Malavolti committed
245

Marco Malavolti's avatar
Marco Malavolti committed
246
## Execute
247

Marco Malavolti's avatar
Marco Malavolti committed
248
249
250
251
252
253
254
  * `cd $HOME/eccs`
  * `./cleanAndRunEccs.py` (to run a full and clean check)
  * `./runEccs.py` (to run a full check on the existing inputs)
  * `./runEccs.py --idp <IDP-ENTITYID>` (to run check on a single IdP)
  * `./runEccs.py --test` (to run a full check without effects)
  * `./runEccs.py --idp <IDP-ENTITYID> --test` (to run check on a single IdP without effects)
  * `./runEccs.py --idp <IDP-ENTITYID> --replace` (to run check on a single IdP and replace, or add, a result)
255

Marco Malavolti's avatar
Marco Malavolti committed
256
  If something prevent the good execution of the ECCS's check, the `logs/failed-cmd.sh` file will be not empty at the end of the execution.
Marco Malavolti's avatar
Marco Malavolti committed
257

Marco Malavolti's avatar
Marco Malavolti committed
258
  The "--test" parameter will not change the result of ECCS, but will write the output on the `logs/stdout_idp_YYYY-MM-DD.log`,`logs/stderr_idp_YYYY-MM-DD.log` and `logs/failed-cmd-idp.sh` files if the argument "--test" will be used.
Marco Malavolti's avatar
Marco Malavolti committed
259

Marco Malavolti's avatar
Marco Malavolti committed
260
# ECCS API Server (uWSGI)
Marco Malavolti's avatar
Marco Malavolti committed
261

262
## Install
Marco Malavolti's avatar
Marco Malavolti committed
263

264
265
266
267
268
1. Install requirements:
   * Debian:
     * `sudo apt-get install libpcre3 libpcre3-dev libapache2-mod-proxy-uwsgi build-essentials python3-dev unzip`
   * CentOS:
     * `sudo yum install mod_proxy_uwsgi unzip`
Marco Malavolti's avatar
Marco Malavolti committed
269
270
271
     * Configure SElinux to enable ECCS:
       * `sudo semanage fcontext -a -t httpd_sys_content_t "$HOME/eccs(/.*)?"`
       * `sudo restorecon -R -e $HOME/eccs/`
272
273
       * `sudo setsebool -P httpd_can_network_connect 1`
 
Marco Malavolti's avatar
Marco Malavolti committed
274
275
## Configure

Marco Malavolti's avatar
Marco Malavolti committed
276
277
278
279
280
281
282
1. Add the systemd service to enable ECCS API:
   * `cd $HOME/eccs`
   * `cp eccs.ini.template eccs.ini`
   * `cp eccs.service.template eccs.service`
   * `vim eccs.ini` (and change "`uid`", "`gid`" and "`base`" values opportunely)
   * `vim eccs.service` (and change "`User`","`Group`","`WorkingDirectory`","`RuntimeDirectory`","`ExecStart`" values opportunely)
   * `sudo cp $HOME/eccs/eccs.service /etc/systemd/system/eccs.service`
283
   * `sudo systemctl daemon-reload`
Marco Malavolti's avatar
Marco Malavolti committed
284
285
   * `sudo systemctl enable eccs.service`
   * `sudo systemctl start eccs.service`
286

Marco Malavolti's avatar
Marco Malavolti committed
287
2. Configure Apache for ECCS web side:
288
   * Debian:
Marco Malavolti's avatar
Marco Malavolti committed
289
290
     * `sudo cp $HOME/eccs/eccs-debian.conf /etc/apache2/conf-available/eccs.conf`
     * `sudo a2enconf eccs.conf`
291
292
293
     * `sudo chgrp www-data $HOME ; sudo chmod g+rx $HOME` (Apache needs permission to access the $HOME dir)
     * `sudo systemctl restart apache2.service`
   * CentOS:
Marco Malavolti's avatar
Marco Malavolti committed
294
     * `sudo cp $HOME/eccs/eccs-centos.conf /etc/httpd/conf.d/eccs.conf`
295
296
     * `sudo chgrp apache $HOME ; sudo apache g+rx $HOME` (Apache needs permission to access the $HOME dir)
     * `sudo systemctl restart httpd.service`
297

298
299
300
301
302
303
3. Restart API WSGI server each day to update the datetime:
   * `crontab -e`

   ```bash
   SHELL=/bin/bash

Marco Malavolti's avatar
Marco Malavolti committed
304
   0 3 * * * /usr/bin/touch $HOME/eccs/eccs.ini
305
306
   ```

307
308
309
310
## Utility

To perform a restart after an API change use the following command:

Marco Malavolti's avatar
Marco Malavolti committed
311
* `touch $HOME/eccs/eccs.ini`
312

Marco Malavolti's avatar
Marco Malavolti committed
313
# ECCS API JSON
314

315
* `/api/eccsresults` (Return the results of the last check ready for ECCS web interface)
Marco Malavolti's avatar
Marco Malavolti committed
316
* `/api/eccsresults?<parameter1>=<value1>&<parameter2>=<value2>`:
317
  * `date=2020-02-20` (select date)
Marco Malavolti's avatar
Marco Malavolti committed
318
  * `idp=https://idp.example.org/idp/shibboleth` (select a specific idp)
Marco Malavolti's avatar
Marco Malavolti committed
319
  * `status=` (select specific ECCS status)
320
321
322
    * 'OK'
    * 'ERROR'
    * 'DISABLED'
Marco Malavolti's avatar
Marco Malavolti committed
323
324
325
326
327
328
329
330
  * `check_result=`
    * `OK`
    * `Timeout`
    * `Invalid-Form`
    * `Connection-Error`
    * `No-eduGAIN-Metadata`
    * `SSL-Error`
    * `DISABLED`
331
  * `reg_auth=https://reg.auth.example.org` (select a specific Registration Authority)
332
  * `format=simple` (retrieve results in a simple format)
333
334
* `/api/fedstats`
* `/api/fedstats?reg_auth=https://reg.auth.example.org`:
335

Marco Malavolti's avatar
Marco Malavolti committed
336
# Utility for web interface
337
338

The available dates are provided by the first and the last file created into the `output/` directory
339

Marco Malavolti's avatar
Marco Malavolti committed
340
341
## Clean old results

Marco Malavolti's avatar
Marco Malavolti committed
342
To clean the ECCS results from files older than last 7 days use (modify it on your needs):
343

Marco Malavolti's avatar
Marco Malavolti committed
344
345
346
347
348
* `crontab -e`

  ```bash
  SHELL=/bin/bash

Marco Malavolti's avatar
Marco Malavolti committed
349
  0 10 * * * /bin/bash $HOME/eccs/clean7daysOldFiles.sh > $HOME/eccs/logs/clean7daysOldFiles.log 2>&1  
Marco Malavolti's avatar
Marco Malavolti committed
350
  ```
Marco Malavolti's avatar
Marco Malavolti committed
351

Marco Malavolti's avatar
Marco Malavolti committed
352
## User interface
Marco Malavolti's avatar
Marco Malavolti committed
353
The eduGAIN Connectivity Check Service web page is available at https://technical-test.edugain.org/eccs
Marco Malavolti's avatar
Marco Malavolti committed
354
355
356
357
358
359
360
361
362
363
364
365
366

## User interface parameters

| Parameter name | Example                                      |
| -------------- | -------------------------------------------- |
| `date`         | `date=2020-02-20`                            |
| `reg_auth`     | `reg_auth=https://reg.auth.example.org`      |
| `idp`          | `idp=https://idp.example.org/idp/shibboleth` |
| `status`       | `status=ERROR`                               |
| `check_result` | `check_result=Timeout`                       |

**Example:**

Marco Malavolti's avatar
Marco Malavolti committed
367
`https://technical-test.edugain.org/eccs?reg_auth=http://www.idem.garr.it/&check_result=SSL-Error`
Marco Malavolti's avatar
Marco Malavolti committed
368

369
370
# Utility for developers

Marco Malavolti's avatar
Marco Malavolti committed
371
## ECCS API Development Server
372

Marco Malavolti's avatar
Marco Malavolti committed
373
* `cd $HOME/eccs ; ./api.py`
374

Marco Malavolti's avatar
Marco Malavolti committed
375
376
377
378
379
# Authors

## Original Author

 * Marco Malavolti (marco.malavolti@garr.it)