Projet

Général

Profil

Télécharger (4,56 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / usr / local / univnautes / sp / sp / management / commands / update-metadatas.py @ aa01889d

1
# -*- coding: utf-8 -*-
2
#
3
# UnivNautes
4
# Copyright (C) 2014  Entr'ouvert
5
#
6
# This program is free software: you can redistribute it and/or modify it under
7
# the terms of the GNU Affero General Public License as published by the Free
8
# Software Foundation, either version 3 of the License, or (at your option) any
9
# later version.
10
#
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
14
# details.
15
#
16
# You should have received a copy of the GNU Affero General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18

    
19
from django.core.management.base import BaseCommand, CommandError
20
from django.core.management import call_command
21

    
22
import os
23
import sys
24
import subprocess
25
from sp import pfconfigxml
26
import urllib2
27

    
28
from authentic2.saml.models import LibertyProvider
29
from django.conf import settings
30
from sp import pfconfigxml
31

    
32
METADATAS_DIR = os.path.join('/', 'var', 'db', 'univnautes-sp-federations')
33

    
34
def metadata_filename(codename, suffix=None):
35
    if not suffix:
36
        return os.path.join(METADATAS_DIR, codename, 'metadata.xml')
37
    else:
38
        return os.path.join(METADATAS_DIR, codename, 'metadata.xml.%s' % suffix)
39

    
40
def store_metadata(codename, fp):
41
    tempfilename = '/var/tmp/%s-metadata.xml-%s' % (codename, os.getpid())
42
    f = open(tempfilename, 'wb')
43
    f.write(fp.read())
44
    f.close()
45
    if not os.path.exists(METADATAS_DIR):
46
        os.mkdir(METADATAS_DIR, 0770)
47
    dir = os.path.join(METADATAS_DIR, codename)
48
    if not os.path.exists(dir):
49
        os.mkdir(dir, 0770)
50
    os.rename(tempfilename, metadata_filename(codename, 'downloaded'))
51

    
52
    # remove obsoletes files if they exist (just to be clean...)
53
    for suffix in ('bad_signature', 'disabled'):
54
        try:
55
            os.remove(metadata_filename(codename, suffix))
56
        except OSError:
57
            pass
58

    
59
def verify_metadata(codename, signcert):
60
    if not signcert:
61
        print 'warn: do not verify %s metadata (no certificate provided)' % codename
62
        ret = True
63
    else:
64
        metadata = metadata_filename(codename, 'downloaded')
65
        signcert_pem = metadata_filename(codename, 'signcert.pem')
66
        dir = os.path.join(METADATAS_DIR, codename)
67
        f = open(signcert_pem, 'wb')
68
        f.write(signcert)
69
        f.close()
70
        ret = 0 == subprocess.call(['xmlsec1', '--verify',
71
            '--id-attr:ID', 'EntitiesDescriptor',
72
            '--pubkey-cert-pem', signcert_pem,
73
            '--enabled-key-data', 'key-name',
74
            metadata])
75
    if ret:
76
        os.rename(metadata, metadata_filename(codename))
77
    else:
78
        print 'warn: bad signature for %s metadata' % codename
79
        os.rename(metadata, metadata_filename(codename, 'bad_signature'))
80
    return ret
81

    
82
def disable(codename):
83
    print 'disable %s metadata' % str(codename)
84
    LibertyProvider.objects.filter(federation_source=codename).delete()
85
    dir = os.path.join(METADATAS_DIR, codename)
86
    try:
87
        os.rename(metadata_filename(codename), metadata_filename(codename, 'disabled'))
88
    except OSError:
89
        pass
90

    
91

    
92
class Command(BaseCommand):
93
    help = 'update all metadatas in %s' % METADATAS_DIR
94

    
95
    def handle(self, *args, **options):
96
        actives = set()
97

    
98
        federations = pfconfigxml.get_federations()
99
        for federation in federations:
100
            url = federation.get('url')
101
            codename = federation.get('codename')
102
            descr = federation.get('descr')
103
            signcert = federation.get('signcert')
104
            try:
105
                print 'download federation %s metadata from %s' % (str(codename), str(url))
106
                store_metadata(codename, urllib2.urlopen(url))
107
            except urllib2.HTTPError as e:
108
                print 'Error loading metadata (%s)' % str(e)
109
            except urllib2.URLError as e:
110
                print 'Error loading metadata (%s)' % str(e)
111
            else:
112
                if verify_metadata(codename, signcert):
113
                    actives.add(codename)
114
                    call_command('sync-metadata', metadata_filename(codename), source=codename, idp=True)
115

    
116
        present_in_filesystem = set(os.listdir(METADATAS_DIR))
117
        for codename in present_in_filesystem - actives:
118
            disable(codename)
119

    
120
        present_in_database = set([str(i['federation_source']) \
121
            for i in LibertyProvider.objects.distinct().values('federation_source').order_by('federation_source')])
122
        for codename in present_in_database - actives:
123
            disable(codename)
124

    
125

    
(3-3/3)