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

Merge branch 'dblock' into 'master'

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

See merge request !2
parents b5ef7eb1 6b851367
Pipeline #47750 passed with stage
in 44 seconds
......@@ -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