Commit 6b851367 authored by Jonathan Schaeffer's avatar Jonathan Schaeffer

Ne pas créer de nouveaux logins si même token

parent b5ef7eb1
......@@ -54,6 +54,26 @@ alter table credentials add column if not exists expires_at timestamp default va
Table `eida_temp_users` :
``` sql
alter table aut_user add column if not exists expires_at timestamp default value null;
CREATE TABLE public.eida_temp_users (
network text,
start_year integer,
end_year integer,
name text,
network_id bigint DEFAULT 0,
expires_at timestamp without time zone
);
ALTER TABLE ONLY public.eida_temp_users
ADD CONSTRAINT unique_privilege UNIQUE (name, network_id);
ALTER TABLE ONLY public.eida_temp_users
ADD CONSTRAINT eida_temp_users_network_id_fkey FOREIGN KEY (network_id) REFERENCES public.networks(network_id) ON DELETE SET DEFAULT;
GRANT ALL ON TABLE public.eida_temp_users TO eidawsauth;
GRANT SELECT ON TABLE public.eida_temp_users TO resifinv_ro;
```
......
......@@ -4,7 +4,7 @@ import random
import string
import logging
import os
from hashlib import md5
from hashlib import md5, sha1
from flask import Flask, request, Response
import psycopg2
import gnupg
......@@ -44,51 +44,29 @@ def parse_input_data(data):
token = re.search(r'{(?P<token>.*)}',str(data)).groupdict()['token']
application.logger.debug(token)
d = dict([i for i in kv.split(':',1)] for kv in token.replace('"','').replace(' ','').split(','))
# Add the sha1 of the token to put in the credentials db
d['shortSha1'] = sha1(token.encode()).hexdigest()[0:8]
application.logger.debug("Transformed to dictionary : %s", d)
return d
def register_login(login, password):
"""
- Connects to the AUTHDB
- Generate Login and Password hash
- register in the users table
"""
expiration_time=datetime.datetime.now()+datetime.timedelta(days=1)
try:
conn = psycopg2.connect(dbname= application.config['RESIFAUTH_PGDATABASE'],
port = application.config['RESIFAUTH_PGPORT'],
host = application.config['RESIFAUTH_PGHOST'],
user= application.config['RESIFAUTH_PGUSER'],
password = application.config['RESIFAUTH_PGPASSWORD'])
cur = conn.cursor()
application.logger.debug("Connected to users database")
except Exception as e:
application.logger.error("Unable to connect to database %s as %s@%s:%s", application.config['RESIFAUTH_PGDATABASE'],
application.config['RESIFAUTH_PGUSER'],
application.config['RESIFAUTH_PGHOST'],
application.config['RESIFAUTH_PGPORT'])
raise e
cur.execute("""
INSERT INTO users VALUES (DEFAULT, %(login)s, 'Temp', 'EIDA', %(tmpmail)s, %(expires_at)s);
""",
{'login': login, 'tmpmail': "%s@eida"%(login),'expires_at': expiration_time }
)
cur.execute("""
INSERT INTO credentials VALUES (CURRVAL('users_user_index_seq'), NULL, %(wsshash)s, %(expires_at)s);
""",
{'wsshash': wsshash(login, password), 'expires_at': expiration_time }
)
conn.commit()
conn.close()
def register_privileges(login, fdsn_refs):
def register_privileges(login, tokendict):
"""
- Check membership and get FDSN references
- Connect to PRIVILEGEDB
- For each fdsn reference, insert the privilege in the access table
- For each fdsn reference, insert the privilege in the access table if not already there
"""
fdsn_memberships = []
for em in tokendict['memberof'].split(';'):
application.logger.debug("EPOS membership: "+em)
if em in application.config['EPOS_FDSN_MAP']:
application.logger.debug(" ... is in epos fdsn map")
fdsn_memberships.append(application.config['EPOS_FDSN_MAP'][em])
if len(fdsn_memberships) == 0:
return
application.logger.debug("FDSN memberships: %s"%(fdsn_memberships))
try:
conn = psycopg2.connect(dbname= application.config['RESIFINV_PGDATABASE'],
port = application.config['RESIFINV_PGPORT'],
......@@ -105,7 +83,7 @@ def register_privileges(login, fdsn_refs):
raise e
# Get the network id
for ref in fdsn_refs:
for ref in fdsn_memberships:
ref['login'] = login
ref['expires_at'] = datetime.datetime.now()+datetime.timedelta(days=1)
application.logger.info(ref)
......@@ -122,11 +100,62 @@ def register_privileges(login, fdsn_refs):
ref['networkid'] = cur.fetchone()[0]
application.logger.info("Inserting tupple in %s.eida_temp_users: %s", application.config['RESIFINV_PGDATABASE'], ref)
cur.execute("""
insert into eida_temp_users (network_id, network, start_year, end_year, name, expires_at) values (%(networkid)s, %(networkcode)s, %(startyear)s, %(endyear)s, %(login)s, %(expires_at)s);
insert into eida_temp_users (network_id, network, start_year, end_year, name, expires_at) values (%(networkid)s, %(networkcode)s, %(startyear)s, %(endyear)s, %(login)s, %(expires_at)s) ON CONFLICT DO NOTHING;
""", ref)
conn.commit()
conn.close()
def get_login_password(tokendict):
"""
Try to read the token's mail. If it exists and a valid credential already exists in the database, return this tuple
else, generate a new login/password, register it in the database and return the tupple
"""
# TODO Try to get an existing login/password from the token's short sha1
login = ""
password = ""
try:
conn = psycopg2.connect(dbname= application.config['RESIFAUTH_PGDATABASE'],
port = application.config['RESIFAUTH_PGPORT'],
host = application.config['RESIFAUTH_PGHOST'],
user= application.config['RESIFAUTH_PGUSER'],
password = application.config['RESIFAUTH_PGPASSWORD'])
cur = conn.cursor()
application.logger.debug("Connected to users database")
cur.execute("select user_index,login from users where email=%s and expires_at between now()+'1 hour' and now()+'26 hours'", (tokendict['mail'],))
application.logger.debug(cur.mogrify("select user_index,login from users where email=%s and expires_at between now()+'1 hour' and now()+'26 hours'", (tokendict['mail'],)))
if cur.rowcount != 0:
(uid, login) = cur.fetchone()
application.logger.debug("Found a temporary account corresponding to %s", tokendict['mail'])
cur.execute("select ws_hash from credentials where user_index=%s", (uid,))
if cur.rowcount != 0:
password = cur.fetchone()[0]
application.logger.debug("Found correspondig password also")
# If not found, compute a random login and password
if not login or not password:
application.logger.debug("No existing user found. Create a new one")
login = ''.join(random.choices(string.ascii_uppercase + string.digits, k=14))
password = ''.join(random.choices(string.ascii_uppercase + string.digits, k=14))
expiration_time = datetime.datetime.now()+datetime.timedelta(days=1)
# Register login in authentication database
cur.execute("""
INSERT INTO users VALUES (DEFAULT, %(login)s, %(givenName)s, %(sn)s, %(mail)s, %(expires_at)s);
""",
{'login': login, 'givenName': tokendict['givenName'], 'sn': tokendict['sn'], 'mail': tokendict['mail'], 'expires_at': expiration_time }
)
cur.execute("""
INSERT INTO credentials VALUES (CURRVAL('users_user_index_seq'), NULL, %(wsshash)s, %(expires_at)s);
""",
{'wsshash': wsshash(login, password), 'expires_at': expiration_time }
)
conn.commit()
conn.close()
except psycopg2.Error as e:
application.logger.error(e.pgerror)
raise e
return (login, password)
@application.route("/version", methods=['GET'])
def version():
......@@ -141,13 +170,12 @@ def cleanup():
rows_deleted = 0
try:
conn = psycopg2.connect(dbname= application.config['RESIFAUTH_PGDATABASE'],
port = application.config['RESIFAUTH_PGPORT'],
host = application.config['RESIFAUTH_PGHOST'],
user= application.config['RESIFAUTH_PGUSER'],
password = application.config['RESIFAUTH_PGPASSWORD'])
port = application.config['RESIFAUTH_PGPORT'],
host = application.config['RESIFAUTH_PGHOST'],
user= application.config['RESIFAUTH_PGUSER'],
password = application.config['RESIFAUTH_PGPASSWORD'])
cur = conn.cursor()
application.logger.debug("Connected to users database")
cur.execute("delete from credentials where expires_at < now();")
cur.execute("delete from users where expires_at < now();")
rows_deleted = cur.rowcount
conn.commit()
......@@ -158,10 +186,10 @@ def cleanup():
try:
conn = psycopg2.connect(dbname= application.config['RESIFINV_PGDATABASE'],
port = application.config['RESIFINV_PGPORT'],
host = application.config['RESIFINV_PGHOST'],
user= application.config['RESIFINV_PGUSER'],
password = application.config['RESIFINV_PGPASSWORD'])
port = application.config['RESIFINV_PGPORT'],
host = application.config['RESIFINV_PGHOST'],
user= application.config['RESIFINV_PGUSER'],
password = application.config['RESIFINV_PGPASSWORD'])
cur = conn.cursor()
application.logger.debug("Connected to privlieges database")
application.logger.debug("Deleting from privileges database")
......@@ -195,30 +223,12 @@ def auth():
return Response('Token is expired. Please generate a new one at https://geofon.gfz-potsdam.de/eas/', status=400)
application.logger.info("Token is valid")
# Compute a random login and password
login = ''.join(random.choices(string.ascii_uppercase + string.digits, k=14))
password = ''.join(random.choices(string.ascii_uppercase + string.digits, k=14))
# Register login
register_login(login, password)
# Store in PRIVILEGEDB
# Check membership and get FDSN references
fdsn_memberships = []
for em in tokendict['memberof'].split(';'):
application.logger.debug("EPOS membership: "+em)
if em in application.config['EPOS_FDSN_MAP']:
application.logger.debug(" ... is in epos fdsn map")
fdsn_memberships.append(application.config['EPOS_FDSN_MAP'][em])
if len(fdsn_memberships) > 0:
application.logger.debug("FDSN memberships: %s"%(fdsn_memberships))
try:
register_privileges(login, fdsn_memberships)
except NameError as n:
return "Internal error at RESIF. Please contact resif-dc@univ-grenoble-alpes.fr specifying the URL"
return "%s:%s"%(login, password)
(login, password) = get_login_password(tokendict)
if login and password:
register_privileges(login, tokendict)
return "%s:%s"%(login, password)
else:
return Response('Internal server error. Contact resif-dc@univ-grenoble-alpes.fr', status=500)
if __name__ == "__main__":
application.logger.info("Running in %s mode"%(application.config['ENVIRONMENT']))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment