Commit 107fd794 authored by Jonathan Schaeffer's avatar Jonathan Schaeffer
Browse files

Move EPOS mapping in inventory database

for better consistency

Get rid of network identification by name/start_year/end_year
parent 8cdc102c
Pipeline #85557 passed with stage
in 1 minute and 27 seconds
......@@ -31,6 +31,7 @@ grant select,update on sequence users_user_index_seq TO eidawsauth ;
\c "resifInv-Prod"
grant select,insert,update,delete on table eida_temp_users TO eidawsauth;
grant select on table networks to eidawsauth;
grant select on table resif_users to eidawsauth;
grant select,update on sequence aut_user_user_id_seq to eidawsauth ;
```
......@@ -76,6 +77,19 @@ GRANT ALL ON TABLE public.eida_temp_users TO eidawsauth;
GRANT SELECT ON TABLE public.eida_temp_users TO resifinv_ro;
```
Table `epos_network_map`
``` sql
create table epos_network_map (
epos_network_map_id bigint generated always as identity,
epos_name text, network_id bigint,
created_at timestamp with time zone default now(),
updated_at timestamp with time zone default now(),
primary key(epos_network_map_id),
constraint fk_network foreign key(network_id) references networks(network_id) );
grant select on epos_network_map to eidawsauth;
insert into epos_network_map (epos_name, network_id) values ('/epos/alparray', 34);
```
## Playing around
......
import os
import json
class Configurator():
class Configurator:
"""
All the configuration logic for this app goes here.
"""
# For convenience, prepare configuration for RESIF RUNMODE
if os.getenv('RUNMODE') == 'production':
ENVIRONMENT = 'production'
if os.getenv("RUNMODE") == "production":
ENVIRONMENT = "production"
RESIFINV_PGUSER = "eidawsauth"
RESIFINV_PGHOST = "resif-pgprod.u-ga.fr"
RESIFINV_PGPORT = 5432
......@@ -16,8 +18,8 @@ class Configurator():
RESIFAUTH_PGHOST = "resif-pgprod.u-ga.fr"
RESIFAUTH_PGPORT = 5432
RESIFAUTH_PGDATABASE = "resifAuth"
elif os.getenv('RUNMODE') == 'preprod':
ENVIRONMENT = 'preprod'
elif os.getenv("RUNMODE") == "preprod":
ENVIRONMENT = "preprod"
RESIFINV_PGUSER = "eidawsauth"
RESIFINV_PGHOST = "resif-pgpreprod.u-ga.fr"
RESIFINV_PGPORT = 5432
......@@ -27,38 +29,32 @@ class Configurator():
RESIFAUTH_PGPORT = 5432
RESIFAUTH_PGDATABASE = "resifAuth"
else:
ENVIRONMENT = 'custom'
RESIFINV_PGUSER = os.getenv('RESIFINV_PGUSER', 'eidawsauth')
RESIFINV_PGHOST = os.getenv('RESIFINV_PGHOST', 'localhost')
RESIFINV_PGPORT = os.getenv('RESIFINV_PGPORT', 5432)
RESIFINV_PGDATABASE = os.getenv('RESIFINV_PGDATABASE', 'resifInv')
RESIFAUTH_PGUSER = os.getenv('RESIFAUTH_PGUSER', 'eidawsauth')
RESIFAUTH_PGHOST = os.getenv('RESIFAUTH_PGHOST', 'localhost')
RESIFAUTH_PGPORT = os.getenv('RESIFAUTH_PGPORT', 5432)
RESIFAUTH_PGDATABASE = os.getenv('RESIFAUTH_PGDATABASE', 'resifAuth')
ENVIRONMENT = "custom"
RESIFINV_PGUSER = os.getenv("RESIFINV_PGUSER", "eidawsauth")
RESIFINV_PGHOST = os.getenv("RESIFINV_PGHOST", "localhost")
RESIFINV_PGPORT = os.getenv("RESIFINV_PGPORT", 5432)
RESIFINV_PGDATABASE = os.getenv("RESIFINV_PGDATABASE", "resifInv")
RESIFAUTH_PGUSER = os.getenv("RESIFAUTH_PGUSER", "eidawsauth")
RESIFAUTH_PGHOST = os.getenv("RESIFAUTH_PGHOST", "localhost")
RESIFAUTH_PGPORT = os.getenv("RESIFAUTH_PGPORT", 5432)
RESIFAUTH_PGDATABASE = os.getenv("RESIFAUTH_PGDATABASE", "resifAuth")
# if PGPASS is provided, then use it for both database connection
if 'PGPASSWORD' in os.environ:
RESIFINV_PGPASSWORD = os.getenv('PGPASSWORD')
RESIFAUTH_PGPASSWORD = os.getenv('PGPASSWORD')
else:
RESIFINV_PGPASSWORD = os.getenv('RESIFINV_PGPASSWORD')
RESIFAUTH_PGPASSWORD = os.getenv('RESIFAUTH_PGPASSWORD')
GNUPG_HOMEDIR = os.getenv('GNUPG_HOMEDIR', '/gpghome')
SUPPORT_EMAIL = os.getenv('SUPPORT_EMAIL', 'resif-dc@univ-grenoble-alpes.fr')
if 'EPOS_FDSN_MAP' in os.environ:
try:
EPOS_FDSN_MAP = json.loads(os.getenv('EPOS_FDSN_MAP'))
except Exception as e:
raise ValueError("Value in EPOS_FDSN_MAP variable is not valid json.", e)
if "PGPASSWORD" in os.environ:
RESIFINV_PGPASSWORD = os.getenv("PGPASSWORD")
RESIFAUTH_PGPASSWORD = os.getenv("PGPASSWORD")
else:
EPOS_FDSN_MAP = {"/epos/alparray": {"networkcode":"Z3", "startyear":2015, "endyear": 2022}}
RESIFINV_PGPASSWORD = os.getenv("RESIFINV_PGPASSWORD")
RESIFAUTH_PGPASSWORD = os.getenv("RESIFAUTH_PGPASSWORD")
GNUPG_HOMEDIR = os.getenv("GNUPG_HOMEDIR", "/gpghome")
SUPPORT_EMAIL = os.getenv("SUPPORT_EMAIL", "resif-dc@univ-grenoble-alpes.fr")
if not RESIFINV_PGPASSWORD:
raise ValueError("No value for RESIFINV_PGPASSWORD, please set environment variable PGPASSWORD or RESIFINV_PGPASSWORD")
raise ValueError(
"No value for RESIFINV_PGPASSWORD, please set environment variable PGPASSWORD or RESIFINV_PGPASSWORD"
)
if not RESIFAUTH_PGPASSWORD:
raise ValueError("No value for RESIFAUTH_PGPASSWORD, please set environment variable PGPASSWORD or RESIFAUTH_PGPASSWORD")
raise ValueError(
"No value for RESIFAUTH_PGPASSWORD, please set environment variable PGPASSWORD or RESIFAUTH_PGPASSWORD"
)
......@@ -57,18 +57,13 @@ def parse_input_data(data):
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 if not already there
- Find all privileges defined in the authorization table (locally at Résif)
- Find all privileges attached to the epos groups found in the token
- Register the privileges in the database
"""
authorizations = []
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")
authorizations.append(application.config["EPOS_FDSN_MAP"][em])
# Now get localy defined autorizations, from email adress
authorized_network_ids = []
# First get localy defined autorizations, from email adress
# 1. Chercher tous les users ayant cet email dans la table resifAuth.users
# select login from users where email = '' and expires_at is NULL
# 2. Pour chaque login récupéré, prendre la liste des réseaux autorisés dans resifInv
......@@ -76,7 +71,7 @@ def register_privileges(login, tokendict):
# Ajouter ces tuples à membership pour que les autorisations soient accordées à cet utilisateur
#
#
# Step 1 :
# Step 1 : Get the list of users related to the email adress in the token
permanent_logins = []
with psycopg2.connect(
dbname=application.config["RESIFAUTH_PGDATABASE"],
......@@ -96,9 +91,8 @@ def register_privileges(login, tokendict):
"Found an account corresponding to %s: %s", tokendict["mail"], l[0]
)
permanent_logins.append(l[0])
# Step 2
# Maintenant, on enregistre les authorizations
# Now, connect to the inventory database
try:
conn = psycopg2.connect(
dbname=application.config["RESIFINV_PGDATABASE"],
......@@ -119,55 +113,57 @@ def register_privileges(login, tokendict):
)
raise e
# Then, find out the mapping between EPOS naming and internal network reference
# For instance "/epos/alparray" -> 34
epos_names = tokendict["memberof"].split(";")
application.logger.debug(
"Mapping %s to network identifiers in inventory", epos_names
)
cur.execute(
"select distinct network_id from epos_network_map where epos_name = any (%s)",
(epos_names,),
)
for ref in cur:
authorized_network_ids.append(ref[0])
# Now for each permanent login attached to the token's email, get the localy defined privileges
for l in permanent_logins:
application.logger.debug("Searching for privileges on login %s", l)
application.logger.debug("Searching for privileges for login %s", l)
cur.execute(
"select network_id, network, start_year, end_year from resif_users where name=%s",
"select distinct network_id from resif_users where name=%s",
(l,),
)
for ref in cur:
authorizations.append(
{
"networkid": ref[0],
"networkcode": ref[1],
"startyear": ref[2],
"endyear": ref[3],
}
)
authorized_network_ids.append(ref[0])
if len(authorizations) == 0:
if len(authorized_network_ids) == 0:
application.logger.debug("No membership for user %s", login)
return
application.logger.debug("FDSN authorizations: %s" % (authorizations))
# Get the network id
for ref in authorizations:
ref["login"] = login
ref["expires_at"] = datetime.datetime.now() + datetime.timedelta(days=1)
application.logger.debug(
"User %s has privileges for networks ID %s", login, authorized_network_ids
)
# Finaly, we can register all authorized_network_ids
# Iterate through unique net_id
for net_id in list(dict.fromkeys(authorized_network_ids)):
expires_at = datetime.datetime.now() + datetime.timedelta(days=1)
application.logger.info(ref)
sql_request = "select network_id from networks where start_year=%(startyear)s and end_year=%(endyear)s and network=%(networkcode)s"
try:
cur.execute(sql_request, ref)
except psycopg2.Error as e:
application.logger.error(e.pgerror)
else:
if cur.rowcount != 1:
application.logger.info(cur.mogrify(sql_request, ref))
application.logger.error("%d networks found for %s", cur.rowcount, ref)
raise NameError(f"{cur.rowcount} networks found for {ref}")
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)
ON CONFLICT DO NOTHING;
""",
ref,
)
application.logger.info(
"Inserting tupple in %s.eida_temp_users: %s, %s, %s",
application.config["RESIFINV_PGDATABASE"],
login,
expires_at,
net_id,
)
cur.execute(
"""
INSERT INTO eida_temp_users (network_id, name, expires_at)
VALUES (%s, %s, %s)
ON CONFLICT DO NOTHING;
""",
(net_id, login, expires_at),
)
conn.commit()
conn.close()
......@@ -177,10 +173,15 @@ 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 = ""
application.logger.debug(
"Trying to connect to resifauth with %s %s %s %s",
application.config["RESIFAUTH_PGDATABASE"],
application.config["RESIFAUTH_PGPORT"],
application.config["RESIFAUTH_PGHOST"],
application.config["RESIFAUTH_PGUSER"],
)
try:
conn = psycopg2.connect(
dbname=application.config["RESIFAUTH_PGDATABASE"],
......
from .default import default
class config(default):
"""
Configuration in production
"""
DEBUG=True
GNUPGHOMEDIR='/gpghome'
ENVIRONMENT='production'
LOGLEVEL='INFO'
AUTHDBPORT=5432
AUTHDBHOST='resif-pgprod.u-ga.fr'
AUTHDBNAME='resifAuth'
AUTHDBUSER='eidawsauth'
AUTHDBPASSWORD=''
PRIVILEGEDBHOST='resif-pgprod.u-ga.fr'
PRIVILEGEDBPORT=5432
PRIVILEGEDBNAME='resifInv-Prod'
PRIVILEGEDBUSER='eidawsauth'
PRIVILEGEDBPASSWORD=''
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