Commit fc70c2fb authored by Admin Y Strator's avatar Admin Y Strator

Merge branch 'master' of https://gitlab.crans.org/nounous/scripts

ette fusion est
parents b1cb80ae 1fbb723e
[submodule "utils/bind-dnssec"]
path = utils/bind-dnssec
url = https://gitlab.crans.org/samir/bind-dnssec
url = https://gitlab.adm.crans.org/samir/bind-dnssec.git
......@@ -268,6 +268,7 @@ def register_machine(data, machine, conn):
logger.info('...Success. Now triggering firewall')
trigger_generate('odlyd')
logger.info('done ! (triggered firewall)')
return machine
@radius_event
@use_ldap_admin
......@@ -553,7 +554,7 @@ def decide_vlan(data, is_wifi, conn):
# Avant de continuer, on assigne la mac à la machine candidat
if '<automatique>' in machine['macAddress'] or not machine['rid']:
register_machine(data, machine)
machine = register_machine(data, machine)
if not machine['ipHostNumber']:
decision = 'v6only', u'No IPv4'
......
......@@ -46,6 +46,7 @@ if not shell in shells:
with adh as ad:
ad['loginShell']=shell
ad.history_gen()
ad.save()
# A cause de nscd
......
......@@ -329,7 +329,7 @@ mac_titanic = 'aa:73:65:63:6f:76'
bcfg2_main = "bcfg2.adm.crans.org"
#: Fichier de mapping lun/nom de volume iscsi
ISCSI_MAP_FILE = "/usr/scripts/var/iscsi_names_%s.py"
ISCSI_MAP_FILE = "/var/lib/iscsi/iscsi_names_%s.py"
#: Algorithmes de hashage pour le champ SSHFP
# format : { algorithm : (IANA_id, ssh_algo) }
......
......@@ -45,6 +45,10 @@ DNSSEC_BACKEND = {
'silice': 'bind',
}
# noms (relatif) sur lequels on veux mettre les enregistrements MX
# utiliser @ pour l'apex des zone dns (crans.org, crans.fr, etc...)
MXs_NAMES = ['@', 'lists']
MXs = {
'redisdead.crans.org': {
'prio': 10,
......
......@@ -3,8 +3,8 @@
SAP_MCAST_GRP = '224.2.127.254' # sap.mcast.net
SAP_MCAST_PORT = 9875
SAP_FILE_TXT = "/usr/scripts/var/tv/sap.txt"
SAP_FILE_PIC = "/usr/scripts/var/tv/sap.pickel"
SAP_FILE_TXT = "/var/lib/tv/sap.txt"
SAP_FILE_PIC = "/var/lib/tv/sap.pickel"
BASE_IMAGE_URL = "https://tv.crans.org/images/"
IMAGE_SUFFIX = ".jpg"
......
......@@ -14,7 +14,7 @@ exempt = [ ['138.231.136.0/21', '138.231.0.0/16'],
analyse_limit = "3000"
#: Template fichier d'analyse
analyse_file_tpl = "/usr/scripts/var/analyse/%s_%s_%s.txt"
analyse_file_tpl = "/home/logs/analyse/%s_%s_%s.txt"
#: Période de surveillance pour le max de décos
periode_watch = 30 * 86400
......
......@@ -379,7 +379,7 @@ class Dialog(object):
)
@tailcaller
def get_timestamp(self, title, text, cont, hour=-1, minute=-1, second=-1, day=0, month=0, year=0):
def get_timestamp(self, title, text, cont, hour=-1, minute=-1, second=-1, day=0, month=0, year=0, date_only=False):
"""Fait choisir une date et une heure et retourne le tuple (year, month, day, hour, minute, second)"""
retry_cont = TailCall(self.get_timestamp, title=title, text=text, cont=cont, hour=hour,
minute=minute, second=second, day=day, month=month, year=year)
......@@ -404,7 +404,10 @@ class Dialog(object):
else:
raise EnvironmentError("Pourquoi je n'ai pas d'horaire ?")
(year, month, day) = get_date(day, month, year)
(hour, minute, second) = get_time(hour, minute, second, day, month, year)
if date_only:
(hour, minute, second) = (0, 0, 0)
else:
(hour, minute, second) = get_time(hour, minute, second, day, month, year)
return (year, month, day) + (hour, minute, second)
def confirm(self, text, title, defaultno=False, width=0, height=0):
......
......@@ -578,7 +578,7 @@ class Dialog(proprio.Dialog):
)
def adherent_etudes(self, adherent, cont, cancel_cont=None, default_item=None, etablissement=None, annee=None, section=None):
def adherent_etudes(self, adherent, cont, cancel_cont=None, default_item=None, etablissement=None):
"""Gestion des études de l'adhérent. etudes est un triplet (établissement, année, section)"""
choices_etablissement = [
('Autre', ''),
......@@ -609,63 +609,6 @@ class Dialog(proprio.Dialog):
LYCEE = ['Maximilien Sorre', 'Gustave Eiffel']
ANNEE = ['IUT Cachan', 'ESTP']
def choices(max_annee):
c = []
if max_annee >= 1:
c.append(('1', '1ère année'))
for i in range(2, max_annee+1):
c.append((str(i), "%sème année" % i))
c.append(('Autre', ''))
return c
choices_LMD = [
('L1', 'Licence 1ère année'),
('L2', 'Licence 2ième année'),
('L3', 'Licence 3ième année'),
('M1', 'Master 1ère année'),
('M2', 'Master 2ième année'),
('D1', '1ère année de thèse'),
('D2', '2ième année de thèse'),
('D3', '3ième année de thèse'),
('Autre', ''),
]
choices_LM = choices_LMD[:5] + choices_LMD[-1:]
choices_ENS = [
('1', 'Licence'),
('2', 'Master 1'),
('3', 'Agrégation'),
('4', 'Master 2'),
('5', '1ère année de thèse'),
('6', '2ième année de thèse'),
('7', '3ième année de thèse'),
('Autre', ''),
]
section_ENS = [
('A0', 'Informatique'),
('A1', 'Mathématiques'),
('A2', 'Physique fondamentale'),
("A'2", 'Physique appliquée'),
("A''2", 'Chimie'),
('A3', 'Biochimie'),
('B1', 'Mécanique'),
('B2', 'Génie civil'),
('B3', 'Génie mécanique'),
('B4', 'Génie électrique'),
('C', 'Art et création industrielle'),
('D2', 'Economie gestion'),
('D3', 'Sciences sociales'),
('E', 'Anglais'),
('S', 'Saphire'),
('Autre', ''),
]
choices_LYCEE = [
('Seconde',''),
('Première',''),
('Terminale',''),
('1/2', '1ère année de prépa'),
('3/2', '2nd année de prépa'),
('5/2', '3ième année de prépa'),
('Autre',''),
]
def box_etablissement(default_item):
if etablissement == 'Autre' or \
......@@ -691,65 +634,7 @@ class Dialog(proprio.Dialog):
backtitle=self._connected_as(),
choices=choices_etablissement)
def box_annee(default_item):
if etablissement in LMD:
box_choice = choices_LMD
elif etablissement in LM:
box_choice = choices_LM
elif etablissement in LYCEE:
box_choice = choices_LYCEE
elif etablissement == 'ENS':
box_choice = choices_ENS
else:
box_choice = choices(7)
if not box_choice or annee == 'Autre' or \
(annee is not None and annee not in [i[0] for i in box_choice]) or \
(default_item is not None and default_item not in [i[0] for i in box_choice]):
return self.dialog.inputbox(
text="Choisissez l'année administrative :",
title="Études de %s %s" % (adherent['prenom'][0], adherent["nom"][0]),
timeout=self.timeout,
init=str(default_item) if default_item else "")
else:
return self.dialog.menu(
"Choisissez l'année administrative :",
width=0,
height=0,
menu_height=0,
timeout=self.timeout,
item_help=0,
default_item=str(default_item),
title="Études de %s %s" % (adherent['prenom'][0], adherent["nom"][0]),
scrollbar=True,
cancel_label="Retour",
backtitle=self._connected_as(),
choices=box_choice)
def box_section(default_item):
if etablissement != 'ENS' or section == 'Autre' or \
(section and section not in [i[0] for i in section_ENS]) or \
(default_item is not None and default_item not in [i[0] for i in section_ENS]):
return self.dialog.inputbox(
text="Choisissez la section :",
title="Études de %s %s" % (adherent['prenom'][0], adherent["nom"][0]),
timeout=self.timeout,
init=str(default_item) if default_item else "")
else:
return self.dialog.menu(
"Choisissez la section :",
width=0,
height=0,
menu_height=0,
timeout=self.timeout,
item_help=0,
default_item=str(default_item),
title="Études de %s %s" % (adherent['prenom'][0], adherent["nom"][0]),
scrollbar=True,
cancel_label="Retour",
backtitle=self._connected_as(),
choices=section_ENS)
self_cont = TailCall(self.adherent_etudes, adherent=adherent, cont=cont, cancel_cont=cancel_cont, default_item=default_item, etablissement=etablissement, annee=annee, section=section)
self_cont = TailCall(self.adherent_etudes, adherent=adherent, cont=cont, cancel_cont=cancel_cont, default_item=default_item, etablissement=etablissement)
if etablissement is None or etablissement == 'Autre':
if not default_item and adherent["etudes"]:
default_item = str(adherent["etudes"][0])
......@@ -757,36 +642,17 @@ class Dialog(proprio.Dialog):
(code, etablissement) = self.handle_dialog(cancel_cont, box_etablissement, default_item)
output = etablissement
self_cont(default_item=etablissement)
elif annee is None or annee == 'Autre':
if not default_item and adherent["etudes"]:
default_item = str(adherent["etudes"][1])
print default_item
lcont = TailCall(self.adherent_etudes, adherent=adherent, cont=cont, cancel_cont=cancel_cont, default_item=etablissement, etablissement=None, annee=None, section=None)
(code , annee) = self.handle_dialog(lcont, box_annee, default_item)
output = annee
self_cont(default_item=annee)
elif section is None or section == 'Autre':
if not default_item and adherent["etudes"]:
default_item = str(adherent["etudes"][2])
lcont = TailCall(self.adherent_etudes, adherent=adherent, cont=cont, cancel_cont=cancel_cont, default_item=annee, etablissement=etablissement, annee=None, section=None)
(code, section) = self.handle_dialog(lcont, box_section, default_item)
output = section
self_cont(default_item=section)
else:
output = ""
lcont = TailCall(self.adherent_etudes, adherent=adherent, cont=cont, cancel_cont=cancel_cont, default_item=section, etablissement=etablissement, annee=annee, section=None)
lcont = TailCall(self.adherent_etudes, adherent=adherent, cont=cont, cancel_cont=cancel_cont, default_item=section, etablissement=etablissement)
def todo(etablissement, annee, section, adherent, self_cont, cont):
def todo(etablissement, adherent, self_cont, cont):
if etablissement is None or etablissement == 'Autre':
raise Continue(self_cont(default_item=None, etablissement=etablissement))
elif annee is None or annee == 'Autre':
raise Continue(self_cont(default_item=None, etablissement=etablissement, annee=annee))
elif section is None or section == 'Autre':
raise Continue(self_cont(default_item=None, etablissement=etablissement, annee=annee, section=section))
else:
if not adherent["etudes"] or adherent["etudes"][0] != etablissement or adherent["etudes"][1] != annee or adherent["etudes"][2] != section:
if not adherent["etudes"] or adherent["etudes"][0] != etablissement:
with self.conn.search(dn=adherent.dn, scope=0, mode='rw')[0] as adherent:
adherent["etudes"] = [unicode(etablissement), unicode(annee), unicode(section)]
adherent["etudes"] = unicode(etablissement)
adherent.validate_changes()
adherent.history_gen()
adherent.save()
......@@ -796,5 +662,5 @@ class Dialog(proprio.Dialog):
output=output,
cancel_cont=lcont,
error_cont=self_cont,
codes_todo=[([self.dialog.DIALOG_OK], todo, [etablissement, annee, section, adherent, self_cont, cont])]
codes_todo=[([self.dialog.DIALOG_OK], todo, [etablissement, adherent, self_cont, cont])]
)
......@@ -74,6 +74,7 @@ class Dialog(proprio.Dialog):
'Remarques' : [a.cableur, a.nounou],
'Blackliste':[a.bureau, a.nounou],
'Vente':[a.cableur, a.nounou],
'Ticket':[a.cableur, a.nounou],
'Supprimer':[a.nounou, a.bureau],
}
menu = {
......@@ -85,9 +86,10 @@ class Dialog(proprio.Dialog):
'Remarques' : {'text':'Ajouter ou supprimer une remarque à ce club', 'attribut':attributs.info},
'Blackliste' : {'text': 'Modifier les blacklist de ce club', 'callback':self.modif_club_blacklist},
'Vente' : {'text':"Chargement solde crans, vente de cable ou adaptateur ethernet ou autre", "club":"proprio", "callback":self.proprio_vente},
'Ticket': {'text':"Imprime un ticket complet avec toutes les machines du club", "club":"proprio", "callback":self.proprio_ticket},
'Supprimer' : {'text':"Supprimer le club de la base de donnée", 'callback':TailCall(self.delete_club, del_cont=cont(proprio=None))},
}
menu_order = ['Administratif', 'Infos', 'Gestion', 'Local', 'Compte', 'Remarques', 'Blackliste', 'Vente', 'Supprimer']
menu_order = ['Administratif', 'Infos', 'Gestion', 'Local', 'Compte', 'Remarques', 'Blackliste', 'Vente', 'Ticket', 'Supprimer']
def box(default_item=None):
choices = []
......@@ -202,6 +204,7 @@ class Dialog(proprio.Dialog):
def gestion_club(self, club, cont, default_item=None):
"""Menu de gestion spécifique aux clubs"""
has_compte = 'cransAccount' in club['objectClass']
a = attributs
menu_droits = {
......@@ -214,7 +217,9 @@ class Dialog(proprio.Dialog):
'Ajouter un imprimeur' : {'text': "Choix d'un adhérent comme nouvel imprimeur", "help":"", 'callback':self.imprimeur_add},
"Retirer un imprimeur" : {"text" : "Enlever un imprimeur au club", "help":'', "callback":self.imprimeur_del},
}
menu_order = ["Responsable", 'Ajouter un imprimeur', "Retirer un imprimeur"]
menu_order = ["Responsable"]
if has_compte:
menu_order.extend(['Ajouter un imprimeur', "Retirer un imprimeur"])
def box(default_item=None):
return self.dialog.menu(
"Quelle action administrative effectuer",
......
......@@ -74,7 +74,7 @@ class Dialog(CPS.Dialog):
# On vérifie que l'utilisateur système existe dans ldap (pour la gestion des droits)
luser=self.conn.search(u'(&(uid=%s)(objectClass=cransAccount))' % self.conn.current_login)
if not luser:
sys.stderr.write("L'utilisateur %s n'existe pas dans la base de donnée" % self.conn.current_login)
sys.stderr.write(u"L'utilisateur %s n'existe pas dans la base de données\n" % self.conn.current_login)
sys.exit(1)
self.conn.droits = [str(d) for d in luser[0]['droits']]
self.conn.dn = luser[0].dn
......
......@@ -30,6 +30,8 @@ import lc_ldap.crans_utils as lc_utils
from lc_ldap.attributs import UniquenessError
import datetime
from dateutil.relativedelta import relativedelta
import machine
import blacklist
......@@ -78,9 +80,9 @@ class Dialog(machine.Dialog, blacklist.Dialog):
def create_compte(proprio, login, self_cont, cont, return_obj=False):
try:
proprio.compte(login=unicode(login, 'utf-8'))
except (ValueError, UniquenessError):
except (ValueError, UniquenessError) as error:
self.dialog.msgbox(
text=u'Ce login est déjà utilisé',
text='Impossible de créer le login %s:\n%s' % (login, error),
title="Création du compte de %s %s" % (proprio.get('prenom', [''])[0], proprio["nom"][0]),
width=75,
height=12, timeout=self.timeout,
......@@ -194,6 +196,12 @@ class Dialog(machine.Dialog, blacklist.Dialog):
@tailcaller
def proprio_ticket(self, proprio, cont, reset=False, return_obj=False):
if isinstance(proprio, objets.adherent):
search = "aid=%s" % proprio['aid']
elif isinstance(proprio, objets.club):
search = "cid=%s" % proprio['cid']
else:
raise ValueError("Objet inconnu et non géré")
if reset:
if bool(proprio.get('droits', False)):
self.dialog.msgbox("Vous ne pouvez pas régénérer le mot de passe d'un membre actif!",
......@@ -204,13 +212,13 @@ class Dialog(machine.Dialog, blacklist.Dialog):
title="Impression de ticket pour %s %s" % (proprio.get('prenom', [''])[0], proprio["nom"][0]),
timeout=self.timeout
) == self.dialog.DIALOG_OK:
subprocess.call(['/usr/scripts/cransticket/dump_creds.py', '--forced', '--pass', 'uid=%s' % proprio['uid'][0]])
subprocess.call(['/usr/scripts/cransticket/dump_creds.py', '--forced', '--pass', search])
self.display_item(proprio, "Impression du ticket en cours ...")
elif self.dialog.yesno("Imprimer un ticket avec l'ensemble des mots de passe des machines ?",
title="Impression de ticket pour %s %s" % (proprio.get('prenom', [''])[0], proprio["nom"][0]),
timeout=self.timeout
) == self.dialog.DIALOG_OK:
subprocess.call(['/usr/scripts/cransticket/dump_creds.py', '--forced', 'uid=%s' % proprio['uid'][0]])
subprocess.call(['/usr/scripts/cransticket/dump_creds.py', '--forced', search])
self.display_item(proprio, "Impression du ticket en cours ...")
raise Continue(cont(proprio=proprio))
......@@ -892,6 +900,17 @@ class Dialog(machine.Dialog, blacklist.Dialog):
else:
make_compte_crans = False
debut_tuple = self.get_timestamp(title="Création d'un utilisateur", text="Choisir la date de naissance", cont=cont, date_only=True)
naissance_date = datetime.date(debut_tuple[0], debut_tuple[1], debut_tuple[2])
if relativedelta(datetime.date.today(), naissance_date).years < 18:
if self.dialog.yesno(
text="\Zr\Z1AVERTISSEMENT :\Zn \nL'adhérent est mineur, vous DEVEZ disposer d'une autorisation parentale écrite\n\n\n\ZnContinuer ?",
title="Création d'un utilisateur",
defaultno=True,
width=70,
colors=True, timeout=self.timeout) != self.dialog.DIALOG_OK:
raise Continue(cont)
fields = [(
"%s %s:" % (a.legend, '(optionnel) ' if a.optional else ''),
fields_attrs.get(a, separateur.join(attrs.get(a.ldap_name, [a.default] if a.default else []))),
......@@ -968,7 +987,7 @@ class Dialog(machine.Dialog, blacklist.Dialog):
# on récupère la chambre
proprio = self.proprio_chambre_campus(success_cont=None, cont=self_cont(make_compte_crans=make_compte_crans, sorte=sorte), proprio=proprio, create=True)
# Si c'est EXT, on demande une adresse complète
if 'EXT' in proprio['chbre']:
if 'EXT' in proprio['chbre'] and sorte!='club':
proprio = self.proprio_chambre_ext(keep_machine=True, keep_compte=True, success_cont=None, cont=self_cont(make_compte_crans=make_compte_crans, sorte=sorte), proprio=proprio, create=True)
# Si compte crans à créer, on le crée.
# On le met en dernier pour éviter de faire entrez plusieurs fois son mdp à l'adhérent
......
......@@ -463,8 +463,8 @@ class Zone(ZoneBase):
to_nom = self.get_name(machine['host'][0])
# Si l'alias est sur le nom de la zone, il faut ajouter
# des entrées standard.
if alias in ['@', '%s.' % self.zone_name]:
# des entrées standard. Idem ii on veux également y mettre un enregistrment MX.
if alias in ['@', '%s.' % self.zone_name] + config.dns.MXs_NAMES:
self.add_a_record(alias, machine)
self.add_aaaa_record(alias, machine)
self.add_sshfp_record(alias, machine)
......@@ -625,8 +625,12 @@ class dns(gen_config):
DELEG = {}
### Serveurs de mail
# format : [ priorité serveur , .... ]
MXs = [MX('@', config.dns.MXs[_mx].get('prio', 25), "%s." %_mx) for _mx in config.dns.MXs]
# format : [ priorité serveur , .... ]. ON génère la liste a partir de config.dns
MXs = [
MX(name, config.dns.MXs[_mx].get('prio', 25), "%s." %_mx)
for _mx in config.dns.MXs
for name in config.dns.MXs_NAMES
]
SRVs = {
'crans.org': [
......
......@@ -26,6 +26,7 @@ class firewall(base.firewall_routeur):
'filtrage_ports' : self.filtrage_ports,
'limitation_debit' : self.limitation_debit,
'limit_ssh_connexion' : self.limit_ssh_connexion,
'limit_connexion' : self.limit_connexion,
'tunnel_6in4' : self.tunnel_6in4,
'challenge_letsencrypt': self.challenge_letsencrypt,
})
......@@ -121,6 +122,8 @@ class firewall(base.firewall_routeur):
self.add(table, chain, '-j %s' % self.connexion_wififederez(table))
self.add(table, chain, '-j %s' % self.ingress_filtering(table))
self.add(table, chain, '-j %s' % self.limit_ssh_connexion(table, ttl=30, counter_name="SSH2"))
self.add(table, chain, '-o %s -j %s' % (dev['out'], self.limit_connexion(table, ip_track='srcip')))
self.add(table, chain, '-i %s -d %s -j %s' % ( dev['out'], ','.join(base.config.NETs['adherents'] + base.config.NETs['wifi-adh'] + base.config.NETs['personnel-ens']), self.limit_connexion(table, ip_track='dstip')))
self.add(table, chain, '-i %s -j %s' % (dev['out'], self.filtrage_ports(table)))
self.add(table, chain, '-o %s -j %s' % (dev['out'], self.filtrage_ports(table)))
return
......@@ -170,6 +173,26 @@ class firewall(base.firewall_routeur):
self.apply(table, chain)
return chain
def limit_connexion(self, table=None, apply=False, ip_track='srcip'):
chain = 'LIMIT-CONNEXION-%s' % ip_track.upper()
if table == 'filter':
pretty_print(table, chain)
self.add(table, chain, '-m hashlimit -p udp --hashlimit-name LIMIT_UDP_%s_CONNEXION --hashlimit-mode %s --hashlimit-upto 400/sec --hashlimit-burst 800 -j RETURN' % (ip_track.upper(), ip_track))
self.add(table, chain,'-m hashlimit -p udp --hashlimit-name LIMIT_UDP_%s_CONNEXION_LOG --hashlimit-mode %s --hashlimit-upto 5/hour -j LOG --log-prefix "CONNEXION_LIMIT_UDP_%s "' % (ip_track.upper(), ip_track, ip_track.upper()))
self.add(table, chain, '-p udp -j REJECT')
self.add(table, chain, '-m hashlimit -p tcp -m state --state NEW --hashlimit-name LIMIT_TCP_%s_CONNEXION --hashlimit-mode %s --hashlimit-upto 2000/min --hashlimit-burst 4000 -j RETURN' % (ip_track.upper(), ip_track))
self.add(table, chain,'-m hashlimit -p tcp -m state --state NEW --hashlimit-name LIMIT_TCP_%s_CONNEXION_LOG --hashlimit-mode %s --hashlimit-upto 5/hour -j LOG --log-prefix "CONNEXION_LIMIT_TCP_%s "' % (ip_track.upper(), ip_track, ip_track.upper()))
self.add(table, chain, '-p tcp -m state --state NEW -j REJECT')
self.add(table, chain, '-m hashlimit --hashlimit-name LIMIT_OTHER_%s_CONNEXION --hashlimit-mode %s --hashlimit-upto 400/sec --hashlimit-burst 800 -j RETURN' % (ip_track.upper(), ip_track))
self.add(table, chain,'-m hashlimit --hashlimit-name LIMIT_OTHER_%s_CONNEXION_LOG --hashlimit-mode %s --hashlimit-upto 5/hour -j LOG --log-prefix "CONNEXION_LIMIT "' % (ip_track.upper(), ip_track))
self.add(table, chain, '-j REJECT')
print OK
if apply:
self.apply(table, chain)
return chain
def test_mac_ip(self, table=None, fill_ipset=False, apply=False):
chain = super(self.__class__, self).test_mac_ip()
......
......@@ -48,7 +48,8 @@ ERASE_DAY = {'second': 0, 'minute': 0, 'microsecond': 0, 'hour': 0, }
FILTRE_TPL_SIMPLE = u'(&(finConnexion>=%(debut)s)(!(finConnexion>=%(fin)s)))'
# Le cas précédent était simplifié, en réalité, la connexion s'achève dès que
# l'adhésion se termine. On regarde donc min(max(finConnexion), max(finAdhesion))
# l'adhésion se termine.
# On regarde donc min(max(finConnexion), max(finAdhesion))
# min(a,b) >= v <=> a >= v /\ b >= v
# min(a,b) < v <=> a < v \/ b < v
FILTRE_TPL = u"""(&
......
Dear Crans Member,
You receive this message to inform you that your Internet connection will
expire in less than {{ delai }} days. {%if finConnexion > finAdhesion %}
Indeed, your annual subscription ends on {{ finAdhesion|date }} even though
your Internet connection is paid until {{ finConnexion|date }}.
{% else %}
Indeed, you paid a connection until {{ finConnexion|date }}, and your annual
subscription ends on {{ finAdhesion|date }}.
{%- endif %}{%- if sursis %}
However, due to the influx after the summer holidays, your connection has been
extended until {{ sursis|date }}.{%- endif %}
In order to rejoin, or to extend your internet connection, you can meet us
during our office hours. The current hours are available on our website ;
www.crans.org/PermanencesCrans .
A one year subscription ( membership + connection ) costs 50€. The membership
alone costs 10€ for 1 year, to which you have to add 5€ per month of
connection. You can pay by credit card, cash or by bank cheque payable to
"L'association Crans".
If you want so, you can ask us if you want to delete your Crans account, your
machines, or change any other information of our database.
See you very soon !
--
The Crans active Members
......@@ -139,7 +139,7 @@ def sudo_loader(name):
raise SecretNotFound()
elif proc.returncode != 0:
sys.stderr.write(err)
raise Exception("Erreur d'appel secrets_new.py")
raise SecretNotFound("Erreur d'appel secrets_new.py")
else:
last = out.split('\n')[-1]
return json.loads(last)
......@@ -154,7 +154,7 @@ class SequenceLoader(list):
return loader(name)
except SecretNotFound as exc:
notfound_error = notfound_error or exc
raise notfound_error
class ACLChecker(object):
......@@ -175,17 +175,17 @@ class ACLChecker(object):
def check(self, name):
"""Teste si ``name`` a le droit d'être lu"""
user = os.getenv('SUDO_USER')
# TODO Trigger et sa clé SSH !
if user == 'root':
return True
# radius a besoin des mdp clients (pour dynamic_clients),
# du ldap et du dhcp pour inscrire des gens
if user == 'freerad' and in_group('freeradius') and \
name.split('_', 1)[0] in ['radius', 'dhcp', 'ldap']:
return True
if user == 'www-data' and in_group('intranet2-service'):
logger.debug('ici: %s' % name.split('_', 1)[0])
if name.split('_', 1)[0] in [ 'comnpay', 'dhcp', 'digicode', 'intranet',
......@@ -202,6 +202,12 @@ class ACLChecker(object):
if user == 'gammu' and in_group('service-sms') and name == "rabbitmq_sms":
return True
# nagios a besoin de faire des recherches dans la base LDAP
if (user == 'nagios' and
in_group('icinga2-master') and
name in ['ldap_readonly_auth_dn', 'ldap_readonly_password']):
return True
# Rempli loader avec la variable qu'on veut
loader = SequenceLoader([python_loader, single_file_loader, json_loader])
......@@ -223,7 +229,7 @@ def get(name):
""" Récupère un secret. """
prog = os.path.basename(getattr(sys, 'argv', ['undefined'])[0])
logger.debug('%s (in %s) asked for %s' % (getpass.getuser(), prog, name))
try:
return loader(name)
except SecretNotFound:
......
#!/usr/scripts/python.sh
#-*- coding: utf-8 -*-
"""
Plugin Nagios récupérant l'état de certaines ressources de l'association
"""
from __future__ import print_function, unicode_literals