Skip to content

Commit

Permalink
debug
Browse files Browse the repository at this point in the history
  • Loading branch information
dmichaels-harvard committed Sep 27, 2023
1 parent 74db13e commit dce2744
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
matrix:
test_type: ['UNIT', 'INDEX', 'DOCKER']
# We are really not set up for these next two to be multiplicative, so be careful adding more.
python_version: ['3.8', '3.11']
python_version: ['3.8']
node_version: ['18']

# Steps represent a sequence of tasks that will be executed as part of the job
Expand Down
9 changes: 2 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,10 @@ classifiers = [
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
]

[tool.poetry.dependencies]
python = ">=3.8.1,<3.12"
python = ">=3.8.1,<3.10"
awscli = ">=1.29.54"
boto3 = "^1.28.54"
botocore = "^1.31.54"
Expand Down Expand Up @@ -91,7 +88,7 @@ python-dateutil = "^2.8.2"
# python-magic is presently pinned to 0.4.15 in lockstep with dcicsnovault's requirements. See explanation there.
python_magic = ">=0.4.24,<1"
pytz = ">=2021.3"
PyYAML = "^6.0.1"
PyYAML = "5.3.1"
rdflib = "^4.2.2"
rdflib-jsonld = ">=0.5.0,<1.0.0"
# repoze.debug is needed to use pyramid.pserve - Will Feb 17 2022
Expand Down Expand Up @@ -181,7 +178,6 @@ dis2pheno = "encoded.commands.parse_hpoa:main"
es-index-data = "snovault.commands.es_index_data:main"
export-data = "encoded.commands.export_data:main"
extract-test-data = "encoded.commands.extract_test_data:main"
generate-local-access-key = "snovault.commands.generate_local_access_key:main"
import-data = "encoded.commands.import_data:main"
jsonld-rdf = "encoded.commands.jsonld_rdf:main"
load-access-keys = "encoded.commands.load_access_keys:main"
Expand All @@ -206,7 +202,6 @@ submission-test = "encoded.commands.submission_test:main"
# submit-metadata-bundle = "encoded.commands.submit_metadata_bundle:main"
update-inserts-from-server = "encoded.commands.update_inserts_from_server:main"
verify-item = "encoded.commands.verify_item:main"
view-local-object= "snovault.commands.view_local_object:main"
# cgap-specific commands
clear-variants-and-genes = "encoded.commands.clear_variants_and_genes:main"
gene-table-intake = "encoded.commands.gene_table_intake:main"
Expand Down
2 changes: 1 addition & 1 deletion src/encoded/ingestion/table_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import io
import json
import logging
from collections.abc import Mapping
from collections import Mapping
from ..util import resolve_file_path

logger = logging.getLogger(__name__)
Expand Down
69 changes: 69 additions & 0 deletions src/encoded/schemas/access_key.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"title": "Admin access key",
"$id": "/profiles/access_key.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [],
"additionalProperties": false,
"mixinProperties": [
{
"$ref": "mixins.json#/schema_version"
},
{
"$ref": "mixins.json#/uuid"
},
{
"$ref": "mixins.json#/submitted"
},
{
"$ref": "mixins.json#/modified"
}
],
"type": "object",
"properties": {
"schema_version": {
"default": "1"
},
"status": {
"title": "Status",
"type": "string",
"default": "current",
"enum": [
"current",
"deleted"
]
},
"user": {
"title": "User",
"comment": "Only admins are allowed to set this value.",
"type": "string",
"linkTo": "User"
},
"description": {
"title": "Description",
"type": "string",
"formInput": "textarea"
},
"access_key_id": {
"title": "Access key ID",
"comment": "Only admins are allowed to set this value.",
"type": "string",
"uniqueKey": true
},
"secret_access_key_hash": {
"title": "Secret access key Hash",
"comment": "Only admins are allowed to set this value.",
"type": "string"
},
"expiration_date": {
"Title": "Expiration Date",
"comment": "Only admins are allowed to set this value.",
"type": "string",
"permission": "restricted_fields"
}
},
"facets": {
"user.display_title": {
"title": "User Name"
}
}
}
161 changes: 161 additions & 0 deletions src/encoded/types/access_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
"""Access_key types file."""

from pyramid.view import view_config
from pyramid.security import (
Allow,
Deny,
Authenticated,
Everyone,
)
from pyramid.settings import asbool
import datetime
from .base import (
Item,
DELETED_ACL,
ONLY_ADMIN_VIEW_ACL,
)
from ..authentication import (
generate_password,
generate_user,
CRYPT_CONTEXT,
)
from snovault import (
collection,
load_schema,
)
from snovault.crud_views import (
collection_add,
item_edit,
)
from snovault.validators import (
validate_item_content_post,
)
from snovault.util import debug_log

@collection(
name='access-keys',
unique_key='access_key:access_key_id',
properties={
'title': 'Access keys',
'description': 'Programmatic access keys',
},
acl=[
(Allow, Authenticated, 'add'),
(Allow, 'group.admin', 'list'),
(Allow, 'group.read-only-admin', 'list'),
(Allow, 'remoteuser.INDEXER', 'list'),
(Allow, 'remoteuser.EMBED', 'list'),
(Deny, Everyone, 'list'),
])
class AccessKey(Item):
"""AccessKey class."""
ACCESS_KEY_EXPIRATION_TIME = 90 # days
item_type = 'access_key'
schema = load_schema('encoded:schemas/access_key.json')
name_key = 'access_key_id'
embedded_list = []

STATUS_ACL = {
'current': [(Allow, 'role.owner', ['view', 'edit'])] + ONLY_ADMIN_VIEW_ACL,
'deleted': DELETED_ACL,
}

@classmethod
def create(cls, registry, uuid, properties, sheets=None):
""" Sets the access key timeout 90 days from creation. """
properties['expiration_date'] = (datetime.datetime.utcnow() + datetime.timedelta(
days=cls.ACCESS_KEY_EXPIRATION_TIME)).isoformat()
return super().create(registry, uuid, properties, sheets)

def __ac_local_roles__(self):
"""grab and return user as owner."""
owner = 'userid.%s' % self.properties['user']
return {owner: 'role.owner'}

def __json__(self, request):
"""delete the secret access key has from the object when used."""
properties = super(AccessKey, self).__json__(request)
del properties['secret_access_key_hash']
return properties

def update(self, properties, sheets=None):
"""smth."""
# make sure PUTs preserve the secret access key hash
if 'secret_access_key_hash' not in properties:
new_properties = self.properties.copy()
new_properties.update(properties)
properties = new_properties
# set new expiration
properties['expiration_date'] = (datetime.datetime.utcnow() + datetime.timedelta(
days=self.ACCESS_KEY_EXPIRATION_TIME)).isoformat()
self._update(properties, sheets)

class Collection(Item.Collection):
pass


# access keys have view permissions for update so readonly admin and the like
# can create access keys to download files.
@view_config(context=AccessKey.Collection, request_method='POST',
permission='add',
validators=[validate_item_content_post])
@debug_log
def access_key_add(context, request):
"""smth."""
crypt_context = request.registry[CRYPT_CONTEXT]

if 'access_key_id' not in request.validated:
request.validated['access_key_id'] = generate_user()

if 'user' not in request.validated:
request.validated['user'], = [
principal.split('.', 1)[1]
for principal in request.effective_principals
if principal.startswith('userid.')
]

password = None
if 'secret_access_key_hash' not in request.validated:
password = generate_password()
request.validated['secret_access_key_hash'] = crypt_context.hash(password)

result = collection_add(context, request)

if password is None:
result['secret_access_key'] = None
else:
result['secret_access_key'] = password

result['access_key_id'] = request.validated['access_key_id']
result['description'] = request.validated.get('description', "")
return result


@view_config(name='reset-secret', context=AccessKey,
permission='add',
request_method='POST', subpath_segments=0)
@debug_log
def access_key_reset_secret(context, request):
"""smth."""
request.validated = context.properties.copy()
crypt_context = request.registry[CRYPT_CONTEXT]
password = generate_password()
new_hash = crypt_context.hash(password)
request.validated['secret_access_key_hash'] = new_hash
result = item_edit(context, request, render=False)
result['access_key_id'] = request.validated['access_key_id']
result['secret_access_key'] = password
return result


@view_config(context=AccessKey, permission='view_raw', request_method='GET',
name='raw')
@debug_log
def access_key_view_raw(context, request):
"""smth."""
if asbool(request.params.get('upgrade', True)):
properties = context.upgrade_properties()
else:
properties = context.properties.copy()
del properties['secret_access_key_hash']
return properties

0 comments on commit dce2744

Please sign in to comment.