Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
ec88bb8
branch off of david's 3.11 changes with my redis changes
willronchetti Sep 29, 2023
4c4c394
update master
willronchetti Oct 17, 2023
b127d65
unit test /login to initiate ras workflow
willronchetti Oct 18, 2023
b56f325
Merge branch 'master' into py311_redis
utku-ozturk Oct 18, 2023
286a806
lock new snovault, update test to use GET
willronchetti Oct 19, 2023
333eaf8
Merge branch 'py311_redis' of https://github.com/4dn-dcic/fourfront i…
willronchetti Oct 19, 2023
09734b8
content security policy for RAS
utku-ozturk Oct 31, 2023
713c6e0
auth0 options initialization
utku-ozturk Oct 31, 2023
14a5f82
bump spc, snovault and dcicutils
utku-ozturk Oct 31, 2023
8c4b832
misc
utku-ozturk Oct 31, 2023
bc53426
authentication
utku-ozturk Oct 31, 2023
4796675
RAS public key support
utku-ozturk Nov 5, 2023
61d03f8
upgrade snovault
utku-ozturk Nov 6, 2023
1c8d258
update ini file to take auth0 domain
willronchetti Nov 6, 2023
a736e6a
test auth0 domain
utku-ozturk Nov 7, 2023
52aee6c
debug info for auth0 config
willronchetti Nov 7, 2023
b244d9c
Merge branch 'ras_integration' of https://github.com/4dn-dcic/fourfro…
willronchetti Nov 7, 2023
bae0020
bring utils fix
willronchetti Nov 7, 2023
5e75456
ras - new user registration
utku-ozturk Nov 7, 2023
7811c66
upgrade snovault
utku-ozturk Nov 7, 2023
2f28b2d
switch access key check from encoded to snovault
utku-ozturk Nov 8, 2023
e0cb704
Merge branch 'master' into ras_integration
utku-ozturk Nov 17, 2023
3b9ef90
snovault and dcicutils upgrade
utku-ozturk Nov 17, 2023
cc1b318
spc upgrade
utku-ozturk Nov 17, 2023
d092927
public key url
utku-ozturk Nov 18, 2023
9c1ac41
spc upgrade
utku-ozturk Nov 18, 2023
fd709ab
add filtered omitted type facet terms
utku-ozturk Nov 17, 2023
a0abe5e
fix typo
utku-ozturk Nov 16, 2023
c27d299
auth init
utku-ozturk Nov 20, 2023
b5c6168
remove unnecessary print statements
utku-ozturk Nov 20, 2023
ce2a53a
simplify auth options of RAS
utku-ozturk Nov 21, 2023
6ed0933
SPC upgrade
utku-ozturk Nov 21, 2023
592ee56
remove mostly duplicate auth content
utku-ozturk Nov 22, 2023
fd6a40e
remove debug statements
utku-ozturk Nov 22, 2023
2f57545
more docstring for jwk_to_pem
utku-ozturk Nov 22, 2023
e05efec
remove unused submit4dn package
utku-ozturk Nov 23, 2023
3a7428c
spc upgrade (0.1.72b6)
utku-ozturk Dec 14, 2023
174d510
return url and registration view updates
utku-ozturk Dec 14, 2023
83f9761
Merge branch 'master' into ras_integration
utku-ozturk Feb 12, 2024
5bb5cb0
poetry.lock
utku-ozturk Feb 12, 2024
0792437
missing prop href
utku-ozturk Feb 13, 2024
ad16c23
Merge branch 'master' into ras_integration
utku-ozturk May 1, 2024
684de66
poetry.lock update
utku-ozturk May 1, 2024
037491d
Merge branch 'master' into ras_integration
utku-ozturk Sep 15, 2024
fcfdab0
delete breaking insert field
utku-ozturk Sep 15, 2024
094f028
merge from master
dmichaels-harvard Oct 29, 2024
796f537
ran poetry update
dmichaels-harvard Oct 29, 2024
8bdcf50
merge from master
dmichaels-harvard Dec 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
node-version: ${{ matrix.node_version }}
check-latest: false

- name: Install/Link Postgres
- name: Install/Link Postgres and Redis
if: ${{ matrix.test_type == 'NPM' || matrix.test_type == 'UNIT' }}
run: |
sudo apt-get install curl ca-certificates gnupg
Expand All @@ -54,6 +54,9 @@ jobs:
sudo apt-get install postgresql-14 postgresql-client-14
echo "/usr/lib/postgresql/14/bin" >> $GITHUB_PATH
sudo ln -s /usr/lib/postgresql/14/bin/initdb /usr/local/bin/initdb
sudo apt install redis-server
sudo ln -s /usr/bin/redis-server /usr/local/bin/redis-server
sudo ln -s /usr/bin/redis-cli /usr/local/bin/redis-cli
- name: Install Deps
if: ${{ matrix.test_type == 'NPM' || matrix.test_type == 'UNIT' }}
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.coverage
coverage.xml
beanstalk.cfg
dump.rdb
/coverage
/.installed.cfg
/.mr.developer.cfg
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ fourfront
Change Log
----------

9.0.0
=====

* RAS integration branch (ras_integration)
* 2024-10-29: merged in master branch (and ran poetry updte).
* 2024-12-03: merged in master branch.


8.4.5
=====

Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ kibana-stop:

kill: # kills back-end processes associated with the application. Use with care.
pkill -f postgres &
pkill -f elasticsearch &
pkill -f opensearch &
pkill -f moto_server &
pkill -f redis-server &

clean-python:
@echo -n "Are you sure? This will wipe all libraries installed on this virtualenv [y/N] " && read ans && [ $${ans:-N} = y ]
Expand Down
6 changes: 3 additions & 3 deletions base.ini
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ multiauth.policy.remoteuser.use = encoded.authentication.NamespacedAuthenticatio
multiauth.policy.remoteuser.base = pyramid.authentication.RemoteUserAuthenticationPolicy

multiauth.policy.accesskey.namespace = accesskey
multiauth.policy.accesskey.use = encoded.authentication.NamespacedAuthenticationPolicy
multiauth.policy.accesskey.base = encoded.authentication.BasicAuthAuthenticationPolicy
multiauth.policy.accesskey.check = encoded.authentication.basic_auth_check
multiauth.policy.accesskey.use = snovault.authentication.NamespacedAuthenticationPolicy
multiauth.policy.accesskey.base = snovault.authentication.BasicAuthAuthenticationPolicy
multiauth.policy.accesskey.check = snovault.authentication.basic_auth_check

multiauth.policy.auth0.use = encoded.authentication.NamespacedAuthenticationPolicy
multiauth.policy.auth0.namespace = auth0
Expand Down
4 changes: 4 additions & 0 deletions deploy/docker/production/fourfront_any_alpha.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[app:app]
use = config:base.ini#app
session.secret = %(here)s/session-secret.b64
auth0.domain = ${AUTH0_DOMAIN}
auth0.client = ${AUTH0_CLIENT}
auth0.secret = ${AUTH0_SECRET}
file_upload_bucket = ${FILE_UPLOAD_BUCKET}
Expand Down Expand Up @@ -31,6 +32,9 @@ elasticsearch.aws_auth = true
production = true
load_test_data = snovault.loadxl:load_${DATA_SET}_data
sqlalchemy.url = postgresql://${RDS_USERNAME}:${RDS_PASSWORD}@${RDS_HOSTNAME}:${RDS_PORT}/${RDS_DB_NAME}
redis.server = ${REDIS_SERVER}
g.recaptcha.key = ${g.recaptcha.key}
g.recaptcha.secret = ${g.recaptcha.secret}

[composite:indexer]
use = config:base.ini#indexer
Expand Down
1 change: 1 addition & 0 deletions development.ini.template
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[app:app]
use = config:base.ini#app
sqlalchemy.url = postgresql://postgres@localhost:5441/postgres?host=/tmp/snovault/pgdata
redis.server = redis://localhost:6379
blob_bucket = encoded-4dn-blobs
metadata_bundles_bucket = metadata-bundles-fourfront-local-test
load_test_only = true
Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Install or update dependencies::
$ brew install libevent libmagic libxml2 libxslt openssl postgresql graphviz nginx python3
$ brew install freetype libjpeg libtiff littlecms webp # Required by Pillow
$ brew cask install adoptopenjdk8
$ brew install opensearch node@20
$ brew install opensearch node@20 redis

NOTES:

Expand Down
1,458 changes: 767 additions & 691 deletions poetry.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tool.poetry]
# Note: Various modules refer to this system as "encoded", not "fourfront".
name = "encoded"
version = "8.4.5"
version = "9.0.0"
description = "4DN-DCIC Fourfront"
authors = ["4DN-DCIC Team <[email protected]>"]
license = "MIT"
Expand Down Expand Up @@ -151,6 +151,7 @@ pytest = "^7.2.1"
pytest-cov = ">=2.2.1"
pytest-instafail = ">=0.3.0"
pytest-mock = ">=0.11.0"
pytest-redis = "^2.0.0"
pytest-timeout = ">=1.0.0"
pytest-xdist = ">=1.14"
"repoze.debug" = ">=1.0.2"
Expand Down
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[pytest]
timeout_func_only = true
redis_exec = /usr/local/bin/redis-server
addopts =
--basetemp=/tmp/pytest
-p encoded.tests.datafixtures
-p snovault.tests.serverfixtures
--instafail
Expand Down
116 changes: 100 additions & 16 deletions src/encoded/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import encoded.project_defs
import base64
import hashlib
import logging
import json # used only in Fourfront, not CGAP
import mimetypes
import netaddr
import os
import pkg_resources
import requests
import sentry_sdk
import subprocess

from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from dcicutils.misc_utils import PRINT
from codeguru_profiler_agent import Profiler
from dcicutils.ecs_utils import ECSUtils
from dcicutils.env_utils import EnvUtils, get_mirror_env_from_context
Expand Down Expand Up @@ -148,6 +153,58 @@ def init_code_guru(*, group_name, region=ECSUtils.REGION):
Profiler(profiling_group_name=group_name, region_name=region).start()


def jwk_to_pem(jwk):
"""Converts JSON Web Key (JWK) to PEM format.

A JSON Web Key (JWK) contains various fields depending on the key type ('kty').
For an RSA key ('kty': 'RSA'), it must include:
- 'n': Base64url encoding of the RSA modulus (often called 'n' in mathematical terms).
- 'e': Base64url encoding of the RSA public exponent (often called 'e' in mathematical terms).

Args:
jwk (dict): JSON Web Key in dictionary format.

Returns:
bytes: PEM encoded key.

Raises:
ValueError: If the 'kty' field is missing or if the key type is unsupported.
ValueError: If the 'n' or 'e' fields are missing in the JWK for an RSA key.
"""

# Example usage:
# jwk = {
# "kty": "RSA",
# "n": "base64_encoded_value_of_n",
# "e": "base64_encoded_value_of_e"
# }
# pem_key = jwk_to_pem(jwk)
# print(pem_key.decode())

#TODO Move it into snovault for possible RAS integration of CGAP or SMaHT

if 'kty' not in jwk:
raise ValueError("JWK must have a 'kty' field")
kty = jwk['kty']

if kty == 'RSA':
if 'n' not in jwk or 'e' not in jwk:
Comment on lines +186 to +191
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be useful to give an example here, maybe move this helper to snovault as well so it can be re-used in smaht-portal eventually

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@willronchetti I added more description, sample into docstring and TODO for possible move to snovault.

raise ValueError("JWK RSA key must have 'n' and 'e' fields")

n = int.from_bytes(base64.urlsafe_b64decode(jwk['n'] + '=='), byteorder='big')
e = int.from_bytes(base64.urlsafe_b64decode(jwk['e'] + '=='), byteorder='big')

public_key = rsa.RSAPublicNumbers(e, n).public_key(default_backend())
pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)

return pem

# You can add more cases for other key types (e.g., 'EC' for elliptic curve keys)
raise ValueError("Unsupported 'kty': {}".format(kty))

def main(global_config, **local_config):
"""
This function returns a Pyramid WSGI application.
Expand Down Expand Up @@ -180,20 +237,42 @@ def main(global_config, **local_config):
settings['auth0.domain'] = settings.get('auth0.domain', os.environ.get('Auth0Domain', DEFAULT_AUTH0_DOMAIN))
settings['auth0.client'] = settings.get('auth0.client', os.environ.get('Auth0Client'))
settings['auth0.secret'] = settings.get('auth0.secret', os.environ.get('Auth0Secret'))
settings['auth0.options'] = {
'auth': {
'sso': False,
'redirect': False,
'responseType': 'token',
'params': {
'scope': 'openid email',
'prompt': 'select_account'

#options
if 'auth0' in settings['auth0.domain']: # Auth0
settings['auth0.options'] = {
'auth': {
'sso': False,
'redirect': False,
'responseType': 'token',
'params': {
'scope': 'openid email',
'prompt': 'select_account'
}
},
'allowedConnections': ['github', 'google-oauth2'] # TODO: make at least this part configurable
}
elif 'nih.gov' in settings['auth0.domain']: # RAS
# we are still keeping the Auth0 structure for compatibility (SPC)
settings['auth0.options'] = {
'auth': {
'responseType': 'code',
'params': {
'scope': 'openid profile email ga4gh_passport_v1',
'prompt': 'login consent'
}
}
},
'allowedConnections': [ # TODO: make at least this part configurable
'github', 'google-oauth2'
]
}
}
auth0Domain = settings['auth0.domain']
# get public key from jwks uri
response = requests.get(url=f'https://{auth0Domain}/openid/connect/jwks.json')
jwks = response.json()
# gives the set of jwks keys.the keys has to be passed as it is to jwt.decode() for signature verification.
settings['auth0.public.key'] = jwk_to_pem(jwks['keys'][0])
else:
# Unknown
settings['auth0.options'] = {}

# ga4 api secret
if 'IDENTITY' in os.environ:
identity = assume_identity()
Expand All @@ -203,8 +282,8 @@ def main(global_config, **local_config):
settings['ga4.secret'] = settings.get('ga4.secret', os.environ.get('GA4Secret'))
# set google reCAPTCHA keys
# TODO propagate from GAC
settings['g.recaptcha.key'] = os.environ.get('reCaptchaKey')
settings['g.recaptcha.secret'] = os.environ.get('reCaptchaSecret')
settings['g.recaptcha.key'] = settings.get('g.recaptcha.key', os.environ.get('reCaptchaKey'))
settings['g.recaptcha.secret'] = settings.get('g.recaptcha.secret', os.environ.get('reCaptchaSecret'))
# enable invalidation scope
settings[INVALIDATION_SCOPE_ENABLED] = True

Expand All @@ -223,6 +302,8 @@ def main(global_config, **local_config):
config.include('pyramid_multiauth') # must be before calling set_authorization_policy
# Override default authz policy set by pyramid_multiauth
config.set_authorization_policy(LocalRolesAuthorizationPolicy())

# This creates a session factory (from definition in Snovault/app.py)
config.include(session)

# must include, as tm.attempts was removed from pyramid_tm
Expand Down Expand Up @@ -253,6 +334,9 @@ def main(global_config, **local_config):
config.include('snovault.elasticsearch')
config.include('.search')

if 'redis.server' in config.registry.settings:
config.include('snovault.redis')

# this contains fall back url, so make sure it comes just before static_resoruces
config.include('.types.page')
config.include(static_resources)
Expand Down
Loading
Loading