Commit 2854c218 authored by Jonathan Schaeffer's avatar Jonathan Schaeffer
Browse files

Preparing gitlab delivery

parent b276d5da
image: python:3.7-alpine
test:
script:
- pip install tox
- tox
build:
script:
- pip install -upgrade setuptools wheel
- python setup.py sdist bdist_wheel
artifacts:
path:
- dist/eidawsauth*.whl
name: eidawsauth-stable-py3-none-any.whl
# coverage:
......@@ -41,22 +41,48 @@ RUNMODE=PRODUCTION gunicorn -w 4 eidaws_auth:aut
### User and minimum privileges
``` sql
postgres# grant connect on database ""resifAuth-Dev" to eidawsauth;
postgres# grant connect on database ""resifInv-Dev" to eidawsauth;
resifAuth-Dev=# grant SELECT,INSERT on TABLE users,credentials TO eidawsauth ;
resifInv-Dev=# grant SELECT,INSERT on TABLE aut_user TO eidawsauth ;
grant connect on database "resifAuth" to eidawsauth;
grant connect on database "resifInv-Prod" to eidawsauth;
\c "resifAuth"
grant select,insert on table users,credentials TO eidawsauth ;
grant select,update on sequence users_user_index_seq TO eidawsauth ;
\c "resifInv-Prod"
grant select,insert on TABLE aut_user TO eidawsauth;
grant select,update on sequence aut_user_user_id_seq to eidawsauth ;
```
### Expected tables schema
#### AUTHDB
Table `users`
Table `users`:
From the existing table, we have to add an `expires_at` column.
Table `credentials`
``` sql
alter table users add column if not exists expires_at timestamp default value null;
```
Table `credentials` :
No modification to the resifAuth schema
Table `epos_fdsn`
#### PRIVILEDGEDB
Table `aut_user`
Table `aut_user`.
No modification to the resifInv-Prod schema.
``` sql
Colonne | Type | Collationnement | NULL-able | Par défaut | Stockage |
------------+---------+-----------------+-----------+-------------------------------------------+----------+
user_id | integer | | not null | nextval('aut_user_user_id_seq'::regclass) | plain |
network_id | bigint | | | 0 | plain |
network | text | | not null | | extended |
start_year | integer | | not null | 0 | plain |
end_year | integer | | not null | 0 | plain |
name | text | | not null | | extended |
Index :
"aut_user_pkey" PRIMARY KEY, btree (user_id)
"uniq_aut_user" UNIQUE CONSTRAINT, btree (network, start_year, end_year, name)
Contraintes de clés étrangères :
"aut_user_network_id_fkey" FOREIGN KEY (network_id) REFERENCES networks(network_id) ON DELETE SET DEFAULT
```
# Explanations
......@@ -68,16 +94,12 @@ What does this program do ?
0. Get all configurations and setup database connections
1. Read the data from POST request
NOTE : We should put a size limit on the WSGI server
2. Decrypt the token using the geofon public key
2. Verify the token's signature using the geofon public key
2. Parse the token's informations
3. Compute a random login and password
4. Register this in the resifAuth database, along with the `valid-until` value (24h)
4. Register this in the resifAuth database, along with the `expires_at` value (24h)
5. From the `member-of` field in the token :
- do the mapping from EPOS names to FDSN reference from the epos_fdsn table in the resifAuth database
the FDSN reference is the network name, startyear, endyear
- register the login along with the FDSN references and the expiration date in the resifInv-Prod database, table `access`
6. Return the `login:password` to the client
# TODO
- get eida signature and import to GPG at startup
- play around with a test token
__version__='0.0.2'
__version__='0.1.0'
......@@ -4,6 +4,7 @@ class default():
"""
DEBUG=False
TESTING=False
LOGLEVEL='INFO'
ENVIRONMENT='default'
GNUPGHOMEDIR='/gnupg'
......@@ -21,5 +22,5 @@ class default():
PRIVILEGEDBPASSWORD='secret'
EPOS_FDSN_MAP={
'/epos/alparray': {'networkcode':'Z3', 'startyear':2015, 'endyear': 2015},
'/epos/alparray': {'networkcode':'Z3', 'startyear':2015, 'endyear': 2020},
}
......@@ -11,7 +11,7 @@ import configurations
import psycopg2
application = Flask(__name__)
if os.environ['RUNMODE'] == 'production':
if 'RUNMODE' in os.environ and os.environ['RUNMODE'] == 'production':
application.config.from_object(configurations.production.config)
else:
application.config.from_object(configurations.development.config)
......@@ -28,7 +28,7 @@ dictConfig({
'formatter': 'default'
}},
'root': {
'level': 'DEBUG',
'level': application.config['LOGLEVEL'],
'handlers': ['wsgi']
}
})
......@@ -75,9 +75,19 @@ def register_login(login, password):
application.config['AUTHDBHOST'],
application.config['AUTHDBPORT']))
raise e
wsshash(login, password)
# cur.execute("INSERT INTO ... ")
cur.execute("""
INSERT INTO users VALUES (DEFAULT, %(login)s, 'Temp', 'EIDA', %(tmpmail)s, %(expiration)s);
""",
{'login': login, 'tmpmail': "%s@eida"%(login),'expiration': datetime.datetime.now()+datetime.timedelta(days=1)}
)
cur.execute("""
INSERT INTO credentials VALUES (CURRVAL('users_user_index_seq'), NULL, %(wsshash)s);
""",
{'wsshash': wsshash(login, password)}
)
conn.commit()
conn.close()
def register_privileges(login, fdsn_refs):
......@@ -85,6 +95,35 @@ def register_privileges(login, fdsn_refs):
- Connect to PRIVILEGEDB
- For each fdsn reference, insert the privilege in the access table
"""
try:
conn = psycopg2.connect(dbname= application.config['PRIVILEGEDBNAME'],
port = application.config['PRIVILEGEDBPORT'],
host = application.config['PRIVILEGEDBHOST'],
user= application.config['PRIVILEGEDBUSER'],
password = application.config['PRIVILEGEDBPASSWORD'])
cur = conn.cursor()
logging.debug("Connected to users database")
except Exception as e:
logging.error("Unable to connect to database %s as %s@%s:%s"%(application.config['PRIVILEGEDBNAME'],
application.config['PRIVILEGEDBUSER'],
application.config['PRIVILEGEDBHOST'],
application.config['PRIVILEGEDBPORT']))
raise e
# Get the network id
for ref in fdsn_refs:
ref['login'] = login
cur.execute("""
select network_id from networks where start_year=%(startyear)s and end_year=%(endyear)s and network=%(networkcode)s;
""", ref)
ref['networkid'] = cur.fetchone()[0]
logging.info(ref)
cur.execute("""
insert into aut_user (network_id, network, start_year, end_year, name) values (%(networkid)s, %(networkcode)s, %(startyear)s, %(endyear)s, %(login)s);
""", ref)
conn.commit()
conn.close()
@application.route("/auth", methods=['POST'])
......@@ -116,7 +155,7 @@ def auth():
# If fdsn_memberships is empty, there is no point to continue.
if len(fdsn_memberships) == 0 :
logging.info("User has no access to any data hosted here.")
# return Response("This token does not grant access to any data hosted at RESIF. You are member of %s. Please contact the PI of the data you are looking for to grant you access."%tokendict['memberof'], status=204)
return Response("This token does not grant access to any data hosted at RESIF. You are member of %s. Please contact the PI of the data you are looking for to grant you access."%tokendict['memberof'], status=204)
# Compute a random login and password
login = 'temp_'+''.join(random.choices(string.ascii_uppercase + string.digits, k=12))
......@@ -126,7 +165,7 @@ def auth():
register_login(login, password)
# Store in PRIVILEGEDB
#register_privileges(login, fdsn_refs)
register_privileges(login, fdsn_memberships)
# Return
return "%s:%s"%(login, password)
......
......@@ -2,14 +2,16 @@ atomicwrites==1.3.0
attrs==19.1.0
Click==7.0
eidaws-auth==0.0.1
-e git+git@gricad-gitlab.univ-grenoble-alpes.fr:OSUG/RESIF/eidawsauth.git@49c18e1cb19d29c744cc79372d9ee362c7bb0347#egg=eidawsauth
-e git+git@gricad-gitlab.univ-grenoble-alpes.fr:OSUG/RESIF/eidawsauth.git@b276d5daf2443658908cda5724ff49cb1e337844#egg=eidawsauth
Flask==1.0.2
gunicorn==19.9.0
itsdangerous==1.1.0
Jinja2==2.10
MarkupSafe==1.1.1
more-itertools==6.0.0
PACKAGENAME==0.0.0
pluggy==0.9.0
psycopg2-binary==2.7.7
py==1.8.0
pytest==4.3.1
pytest-datafiles==2.0
......
......@@ -26,6 +26,7 @@ setup(
license='GPL-3.0',
packages=find_packages(),
install_requires=[
'Flask==1.0.2', 'psycopg2-binary==2.7.7', 'python-gnupg==0.4.4'
],
keywords=[
'',
......@@ -41,7 +42,7 @@ setup(
'Programming Language :: Python :: 3.7',
],
tests_require=['coverage', 'pytest'],
tests_require=['coverage', 'pytest', 'pytest-datafiles', 'tox'],
#entry_points='''
#[console_scripts]
#ringserverstats=ringserverstats:cli
......
[tox]
envlist =
py37,
py36
# py36
[testenv]
passenv = *
......
Supports Markdown
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