Projet

Général

Profil

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

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

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
            '--pubkey-cert-pem', signcert_pem,
72
            '--id-attr:ID', 'EntitiesDescriptor',
73
            metadata])
74
    if ret:
75
        os.rename(metadata, metadata_filename(codename))
76
    else:
77
        print 'warn: bad signature for %s metadata' % codename
78
        os.rename(metadata, metadata_filename(codename, 'bad_signature'))
79
    return ret
80

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

    
90

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

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

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

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

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

    
124

    
(3-3/3)