commit
d9015a1863
5 changed files with 125 additions and 103 deletions
|
@ -10,7 +10,7 @@ COPY requirements.txt requirements-tests.txt ./
|
||||||
# Due to the following bug, pip results must be piped to a file before grepping:
|
# Due to the following bug, pip results must be piped to a file before grepping:
|
||||||
# https://github.com/pypa/pip/pull/3304
|
# https://github.com/pypa/pip/pull/3304
|
||||||
RUN cat requirements.txt | grep -v "^-e" | awk -F'==' '{print $1}' | xargs venv/bin/pip --disable-pip-version-check show > pipinfo.txt && \
|
RUN cat requirements.txt | grep -v "^-e" | awk -F'==' '{print $1}' | xargs venv/bin/pip --disable-pip-version-check show > pipinfo.txt && \
|
||||||
test -z $(cat pipinfo.txt | grep GPL | grep -v LGPL) && \
|
test -z "$(cat pipinfo.txt | grep GPL | grep -v LGPL)" && \
|
||||||
rm pipinfo.txt
|
rm pipinfo.txt
|
||||||
|
|
||||||
RUN virtualenv --distribute venv \
|
RUN virtualenv --distribute venv \
|
||||||
|
@ -57,4 +57,4 @@ RUN PYTHONPATH=$QUAYPATH venv/bin/alembic heads | grep -E '^[0-9a-f]+ \(head\)$'
|
||||||
|
|
||||||
RUN ./scripts/detect-config.sh
|
RUN ./scripts/detect-config.sh
|
||||||
|
|
||||||
CMD ./quay-entrypoint.sh
|
CMD ./quay-entrypoint.sh
|
||||||
|
|
|
@ -110,30 +110,31 @@ def test_token_with_access(access, initialized_db):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('token', [
|
@pytest.mark.parametrize('token', [
|
||||||
(_token(
|
pytest.param(_token(
|
||||||
_token_data(access=[{
|
_token_data(access=[{
|
||||||
'toipe': 'repository',
|
'toipe': 'repository',
|
||||||
'namesies': 'somens/somerepo',
|
'namesies': 'somens/somerepo',
|
||||||
'akshuns': ['pull', 'push', '*']}]))),
|
'akshuns': ['pull', 'push', '*']}])), id='bad access'),
|
||||||
(_token(_token_data(audience='someotherapp'))),
|
pytest.param(_token(_token_data(audience='someotherapp')), id='bad aud'),
|
||||||
(_token(_delete_field(_token_data(), 'aud'))),
|
pytest.param(_token(_delete_field(_token_data(), 'aud')), id='no aud'),
|
||||||
(_token(_token_data(nbf=int(time.time()) + 600))),
|
pytest.param(_token(_token_data(nbf=int(time.time()) + 600)), id='future nbf'),
|
||||||
(_token(_delete_field(_token_data(), 'nbf'))),
|
pytest.param(_token(_delete_field(_token_data(), 'nbf')), id='no nbf'),
|
||||||
(_token(_token_data(iat=int(time.time()) + 600))),
|
pytest.param(_token(_token_data(iat=int(time.time()) + 600)), id='future iat'),
|
||||||
(_token(_delete_field(_token_data(), 'iat'))),
|
pytest.param(_token(_delete_field(_token_data(), 'iat')), id='no iat'),
|
||||||
(_token(_token_data(exp=int(time.time()) + MAX_SIGNED_S * 2))),
|
pytest.param(_token(_token_data(exp=int(time.time()) + MAX_SIGNED_S * 2)), id='exp too long'),
|
||||||
(_token(_token_data(exp=int(time.time()) - 60))),
|
pytest.param(_token(_token_data(exp=int(time.time()) - 60)), id='expired'),
|
||||||
(_token(_delete_field(_token_data(), 'exp'))),
|
pytest.param(_token(_delete_field(_token_data(), 'exp')), id='no exp'),
|
||||||
(_token(_delete_field(_token_data(), 'sub'))),
|
pytest.param(_token(_delete_field(_token_data(), 'sub')), id='no sub'),
|
||||||
(_token(_token_data(iss='badissuer'))),
|
pytest.param(_token(_token_data(iss='badissuer')), id='bad iss'),
|
||||||
(_token(_delete_field(_token_data(), 'iss'))),
|
pytest.param(_token(_delete_field(_token_data(), 'iss')), id='no iss'),
|
||||||
(_token(_token_data(), skip_header=True)),
|
pytest.param(_token(_token_data(), skip_header=True), id='no header'),
|
||||||
(_token(_token_data(), key_id='someunknownkey')),
|
pytest.param(_token(_token_data(), key_id='someunknownkey'), id='bad key'),
|
||||||
(_token(_token_data(), key_id='kid7')),
|
pytest.param(_token(_token_data(), key_id='kid7'), id='bad key :: kid7'),
|
||||||
(_token(_token_data(), alg='none', private_key=None)),
|
pytest.param(_token(_token_data(), alg='none', private_key=None), id='none alg'),
|
||||||
('some random token'),
|
pytest.param('some random token', id='random token'),
|
||||||
('Bearer: sometokenhere'),
|
pytest.param('Bearer: sometokenhere', id='extra bearer'),
|
||||||
('\nBearer: dGVzdA'),])
|
pytest.param('\nBearer: dGVzdA', id='leading newline'),
|
||||||
|
])
|
||||||
def test_invalid_jwt(token, initialized_db):
|
def test_invalid_jwt(token, initialized_db):
|
||||||
with pytest.raises(InvalidJWTException):
|
with pytest.raises(InvalidJWTException):
|
||||||
_parse_token(token)
|
_parse_token(token)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
-e git+https://github.com/coreos/pyapi-gitlab.git@timeout#egg=pyapi-gitlab
|
-e git+https://github.com/coreos/pyapi-gitlab.git@timeout#egg=pyapi-gitlab
|
||||||
-e git+https://github.com/coreos/resumablehashlib.git#egg=resumablehashlib
|
-e git+https://github.com/coreos/resumablehashlib.git#egg=resumablehashlib
|
||||||
-e git+https://github.com/jepcastelein/marketo-rest-python.git#egg=marketorestpython
|
-e git+https://github.com/jepcastelein/marketo-rest-python.git#egg=marketorestpython
|
||||||
-e git+https://github.com/app-registry/appr-server.git#egg=cnr-server
|
-e git+https://github.com/app-registry/appr-server.git@c2ef3b88afe926a92ef5f2e11e7d4a259e286a17#egg=cnr_server # naming has changed
|
||||||
APScheduler==3.0.5
|
APScheduler==3.0.5
|
||||||
Flask-Login
|
Flask-Login
|
||||||
Flask-Mail
|
Flask-Mail
|
||||||
|
@ -77,5 +77,4 @@ tzlocal
|
||||||
xhtml2pdf
|
xhtml2pdf
|
||||||
recaptcha2
|
recaptcha2
|
||||||
mockredispy
|
mockredispy
|
||||||
cnr
|
|
||||||
yapf
|
yapf
|
||||||
|
|
164
requirements.txt
164
requirements.txt
|
@ -1,139 +1,147 @@
|
||||||
aiowsgi==0.6
|
aiowsgi==0.6
|
||||||
alembic==0.9.1
|
alembic==0.9.8
|
||||||
-e git+https://github.com/coreos/mockldap.git@59a46efbe8c7cd8146a87a7c4f2b09746b953e11#egg=mockldap
|
-e git+https://github.com/coreos/mockldap.git@59a46efbe8c7cd8146a87a7c4f2b09746b953e11#egg=mockldap
|
||||||
-e git+https://github.com/coreos/py-bitbucket.git@07a80f63388d004f05f58441983bdf195f9b666e#egg=py_bitbucket
|
-e git+https://github.com/coreos/py-bitbucket.git@55a1ada645f2fb6369147996ec71edd7828d91c8#egg=py_bitbucket
|
||||||
-e git+https://github.com/coreos/pyapi-gitlab.git@136c3970d591136a4f766a846c5d22aad52e124f#egg=pyapi_gitlab
|
-e git+https://github.com/coreos/pyapi-gitlab.git@136c3970d591136a4f766a846c5d22aad52e124f#egg=pyapi_gitlab
|
||||||
-e git+https://github.com/coreos/resumablehashlib.git@b1b631249589b07adf40e0ee545b323a501340b4#egg=resumablehashlib
|
-e git+https://github.com/coreos/resumablehashlib.git@b1b631249589b07adf40e0ee545b323a501340b4#egg=resumablehashlib
|
||||||
-e git+https://github.com/DevTable/aniso8601-fake.git@bd7762c7dea0498706d3f57db60cd8a8af44ba90#egg=aniso8601
|
-e git+https://github.com/DevTable/aniso8601-fake.git@bd7762c7dea0498706d3f57db60cd8a8af44ba90#egg=aniso8601
|
||||||
-e git+https://github.com/DevTable/anunidecode.git@d59236a822e578ba3a0e5e5abbd3855873fa7a88#egg=anunidecode
|
-e git+https://github.com/DevTable/anunidecode.git@d59236a822e578ba3a0e5e5abbd3855873fa7a88#egg=anunidecode
|
||||||
-e git+https://github.com/app-registry/appr-server.git@c2ef3b88afe926a92ef5f2e11e7d4a259e286a17#egg=cnr_server
|
-e git+https://github.com/app-registry/appr-server.git@c2ef3b88afe926a92ef5f2e11e7d4a259e286a17#egg=cnr_server
|
||||||
-e git+https://github.com/DevTable/container-cloud-config.git@bce675537904175f6975024a4c89269027ea6792#egg=container_cloud_config
|
-e git+https://github.com/DevTable/container-cloud-config.git@8e8ae177c3d5cd6608f64250fcd8770022d61562#egg=container_cloud_config
|
||||||
-e git+https://github.com/DevTable/python-etcd.git@f1168cb02a2a8c83bec1108c6fcd8615ef463b14#egg=python_etcd
|
-e git+https://github.com/DevTable/python-etcd.git@f1168cb02a2a8c83bec1108c6fcd8615ef463b14#egg=python_etcd
|
||||||
-e git+https://github.com/jarus/flask-testing.git@18baff32969a0634a414ce61d2dd4a77433817a8#egg=Flask_Testing
|
-e git+https://github.com/jarus/flask-testing.git@17f19d7fee0e1e176703fc7cb04917a77913ba1a#egg=Flask_Testing
|
||||||
-e git+https://github.com/jepcastelein/marketo-rest-python.git@e26af0c5acd3d4ad899383442703a053120aa7ab#egg=marketorestpython
|
-e git+https://github.com/jepcastelein/marketo-rest-python.git@6134d1129f2435b313c4301503a4b74974d79a42#egg=marketorestpython
|
||||||
-e git+https://github.com/NateFerrero/oauth2lib.git@d161b010f8a596826050a09e5e94d59443cc12d9#egg=oauth2lib
|
-e git+https://github.com/NateFerrero/oauth2lib.git@d161b010f8a596826050a09e5e94d59443cc12d9#egg=oauth2lib
|
||||||
appdirs==1.4.3
|
|
||||||
APScheduler==3.0.5
|
APScheduler==3.0.5
|
||||||
asn1crypto==0.22.0
|
asn1crypto==0.24.0
|
||||||
autobahn==0.9.3.post3
|
autobahn==0.9.3.post3
|
||||||
azure-common==1.1.8
|
azure-common==1.1.8
|
||||||
|
azure-nspkg==2.0.0
|
||||||
azure-storage-blob==1.1.0
|
azure-storage-blob==1.1.0
|
||||||
Babel==2.4.0
|
azure-storage-common==1.1.0
|
||||||
beautifulsoup4==4.5.3
|
azure-storage-nspkg==3.0.0
|
||||||
|
Babel==2.5.3
|
||||||
|
beautifulsoup4==4.6.0
|
||||||
bencode==1.0
|
bencode==1.0
|
||||||
bintrees==2.0.6
|
bintrees==2.0.7
|
||||||
bitmath==1.3.1.2
|
bitmath==1.3.1.2
|
||||||
blinker==1.4
|
blinker==1.4
|
||||||
boto==2.46.1
|
boto==2.48.0
|
||||||
boto3==1.4.7
|
boto3==1.5.36
|
||||||
|
botocore==1.8.50
|
||||||
cachetools==1.1.6
|
cachetools==1.1.6
|
||||||
certifi==2017.11.5
|
certifi==2018.1.18
|
||||||
cffi==1.10.0
|
cffi==1.11.4
|
||||||
|
chardet==3.0.4
|
||||||
click==6.7
|
click==6.7
|
||||||
contextlib2==0.5.4
|
contextlib2==0.5.5
|
||||||
cryptography==1.8.1
|
cryptography==2.1.4
|
||||||
debtcollector==1.13.0
|
debtcollector==1.19.0
|
||||||
decorator==4.0.11
|
decorator==4.2.1
|
||||||
enum34==1.1.6
|
enum34==1.1.6
|
||||||
Flask-Login==0.4.0
|
Flask-Cors==3.0.3
|
||||||
|
Flask-Login==0.4.1
|
||||||
Flask-Mail==0.9.1
|
Flask-Mail==0.9.1
|
||||||
Flask-Principal==0.4.0
|
Flask-Principal==0.4.0
|
||||||
Flask-RESTful==0.3.5
|
Flask-RESTful==0.3.6
|
||||||
Flask==0.12.1
|
Flask==0.12.2
|
||||||
funcparserlib==0.3.6
|
funcparserlib==0.3.6
|
||||||
funcsigs==1.0.2
|
funcsigs==1.0.2
|
||||||
functools32==3.2.3.post2
|
functools32==3.2.3.post2
|
||||||
furl==1.0.0
|
furl==1.0.1
|
||||||
future==0.16.0
|
future==0.16.0
|
||||||
futures==3.0.5
|
futures==3.2.0
|
||||||
geoip2==2.5.0
|
geoip2==2.7.0
|
||||||
gevent==1.2.1
|
gevent==1.2.2
|
||||||
gipc==0.6.0
|
gipc==0.6.0
|
||||||
greenlet==0.4.12
|
greenlet==0.4.13
|
||||||
gunicorn==18.0
|
gunicorn==18.0
|
||||||
hiredis==0.2.0
|
hiredis==0.2.0
|
||||||
html5lib==0.9999999
|
html5lib==0.9999999
|
||||||
httmock==1.2.6
|
httmock==1.2.6
|
||||||
|
httplib2==0.10.3
|
||||||
httpretty==0.8.10
|
httpretty==0.8.10
|
||||||
idna==2.5
|
idna==2.6
|
||||||
ipaddress==1.0.18
|
ipaddress==1.0.19
|
||||||
iso8601==0.1.11
|
iso8601==0.1.12
|
||||||
itsdangerous==0.24
|
itsdangerous==0.24
|
||||||
Jinja2==2.9.6
|
Jinja2==2.10
|
||||||
|
jmespath==0.9.3
|
||||||
jsonpath-rw==1.4.0
|
jsonpath-rw==1.4.0
|
||||||
jsonschema==2.6.0
|
jsonschema==2.6.0
|
||||||
keystoneauth1==2.19.0
|
keystoneauth1==3.4.0
|
||||||
Mako==1.0.6
|
Mako==1.0.7
|
||||||
marisa-trie==0.7.4
|
marisa-trie==0.7.4
|
||||||
MarkupSafe==1.0
|
MarkupSafe==1.0
|
||||||
|
maxminddb==1.3.0
|
||||||
mixpanel==4.3.2
|
mixpanel==4.3.2
|
||||||
mock==2.0.0
|
mock==2.0.0
|
||||||
mockredispy==2.9.3
|
mockredispy==2.9.3
|
||||||
monotonic==1.3
|
monotonic==1.4
|
||||||
moto==0.4.25
|
moto==0.4.25
|
||||||
msgpack-python==0.4.8
|
msgpack==0.5.6
|
||||||
namedlist==1.7
|
namedlist==1.7
|
||||||
ndg-httpsclient==0.4.2
|
ndg-httpsclient==0.4.4
|
||||||
netaddr==0.7.19
|
netaddr==0.7.19
|
||||||
netifaces==0.10.5
|
netifaces==0.10.6
|
||||||
oauthlib==2.0.2
|
oauthlib==2.0.6
|
||||||
olefile==0.44
|
|
||||||
orderedmultidict==0.7.11
|
orderedmultidict==0.7.11
|
||||||
oslo.config==3.24.0
|
oslo.config==5.2.0
|
||||||
oslo.i18n==3.15.0
|
oslo.i18n==3.19.0
|
||||||
oslo.serialization==2.18.0
|
oslo.serialization==2.24.0
|
||||||
oslo.utils==3.25.0
|
oslo.utils==3.35.0
|
||||||
packaging==16.8
|
pathvalidate==0.16.3
|
||||||
pathvalidate==0.15.0
|
pbr==3.1.1
|
||||||
pbr==2.0.0
|
|
||||||
peewee==2.8.1
|
peewee==2.8.1
|
||||||
Pillow==4.1.0
|
Pillow==5.0.0
|
||||||
ply==3.10
|
ply==3.11
|
||||||
positional==1.1.1
|
psutil==5.4.3
|
||||||
psutil==5.2.1
|
psycopg2==2.7.4
|
||||||
psycopg2==2.7.1
|
pyasn1==0.4.2
|
||||||
pyasn1==0.3.7
|
|
||||||
py-bcrypt==0.4
|
py-bcrypt==0.4
|
||||||
pycparser==2.17
|
pycparser==2.18
|
||||||
pycryptodome==3.4.5
|
pycryptodome==3.4.11
|
||||||
pycryptodomex==3.4.5
|
pycryptodomex==3.4.12
|
||||||
PyGithub==1.34
|
PyGithub==1.36
|
||||||
pygpgme==0.3
|
pygpgme==0.3
|
||||||
pyjwkest==1.3.2
|
pyjwkest==1.4.0
|
||||||
PyJWT==1.4.2
|
PyJWT==1.5.3
|
||||||
PyMySQL==0.6.7
|
PyMySQL==0.6.7
|
||||||
pyOpenSSL==16.2.0
|
pyOpenSSL==17.5.0
|
||||||
pyparsing==2.2.0
|
pyparsing==2.2.0
|
||||||
PyPDF2==1.26.0
|
PyPDF2==1.26.0
|
||||||
python-dateutil==2.6.0
|
python-dateutil==2.6.1
|
||||||
python-editor==1.0.3
|
python-editor==1.0.3
|
||||||
python-keystoneclient==3.10.0
|
python-keystoneclient==3.15.0
|
||||||
python-ldap==2.4.32
|
python-ldap==2.5.2
|
||||||
python-magic==0.4.13
|
python-magic==0.4.15
|
||||||
python-swiftclient==3.3.0
|
python-swiftclient==3.5.0
|
||||||
pytz==2017.2
|
pytz==2018.3
|
||||||
PyYAML==3.12
|
PyYAML==3.12
|
||||||
raven==6.0.0
|
raven==6.5.0
|
||||||
recaptcha2==0.1
|
recaptcha2==0.1
|
||||||
redis==2.10.5
|
redis==2.10.6
|
||||||
redlock==1.2.0
|
redlock==1.2.0
|
||||||
reportlab==2.7
|
reportlab==2.7
|
||||||
requests-oauthlib==0.8.0
|
requests-oauthlib==0.8.0
|
||||||
requests[security]==2.18.4
|
requests[security]==2.18.4
|
||||||
rfc3986==0.4.1
|
rfc3986==1.1.0
|
||||||
|
s3transfer==0.1.13
|
||||||
semantic-version==2.6.0
|
semantic-version==2.6.0
|
||||||
six==1.10.0
|
simplejson==3.13.2
|
||||||
|
six==1.11.0
|
||||||
SQLAlchemy==1.1.5
|
SQLAlchemy==1.1.5
|
||||||
stevedore==1.21.0
|
stevedore==1.28.0
|
||||||
stringscore==0.1.0
|
stringscore==0.1.0
|
||||||
stripe==1.51.0
|
stripe==1.79.0
|
||||||
toposort==1.5
|
toposort==1.5
|
||||||
trollius==2.1
|
trollius==2.1
|
||||||
tzlocal==1.3
|
tzlocal==1.5.1
|
||||||
urllib3==1.20
|
urllib3==1.22
|
||||||
waitress==1.0.2
|
waitress==1.1.0
|
||||||
WebOb==1.7.2
|
WebOb==1.7.4
|
||||||
Werkzeug==0.12.1
|
Werkzeug==0.14.1
|
||||||
wrapt==1.10.10
|
wrapt==1.10.11
|
||||||
xhtml2pdf==0.0.6
|
xhtml2pdf==0.2.1
|
||||||
xmltodict==0.10.2
|
xmltodict==0.11.0
|
||||||
|
yapf==0.20.2
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from calendar import timegm
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from jwt import PyJWT
|
from jwt import PyJWT
|
||||||
from jwt.exceptions import (
|
from jwt.exceptions import (
|
||||||
|
@ -42,6 +43,9 @@ class StrictJWT(PyJWT):
|
||||||
# Do all of the other checks
|
# Do all of the other checks
|
||||||
super(StrictJWT, self)._validate_claims(payload, options, audience, issuer, leeway, **kwargs)
|
super(StrictJWT, self)._validate_claims(payload, options, audience, issuer, leeway, **kwargs)
|
||||||
|
|
||||||
|
now = timegm(datetime.utcnow().utctimetuple())
|
||||||
|
self._reject_future_iat(payload, now, leeway)
|
||||||
|
|
||||||
if 'exp' in payload and options.get('exp_max_s') is not None:
|
if 'exp' in payload and options.get('exp_max_s') is not None:
|
||||||
# Validate that the expiration was not more than exp_max_s seconds after the issue time
|
# Validate that the expiration was not more than exp_max_s seconds after the issue time
|
||||||
# or in the absense of an issue time, more than exp_max_s in the future from now
|
# or in the absense of an issue time, more than exp_max_s in the future from now
|
||||||
|
@ -58,6 +62,16 @@ class StrictJWT(PyJWT):
|
||||||
raise InvalidTokenError('Token was signed for more than %s seconds from %s', max_signed_s,
|
raise InvalidTokenError('Token was signed for more than %s seconds from %s', max_signed_s,
|
||||||
start_time)
|
start_time)
|
||||||
|
|
||||||
|
def _reject_future_iat(self, payload, now, leeway):
|
||||||
|
try:
|
||||||
|
iat = int(payload['iat'])
|
||||||
|
except ValueError:
|
||||||
|
raise DecodeError('Issued At claim (iat) must be an integer.')
|
||||||
|
|
||||||
|
if iat > (now + leeway):
|
||||||
|
raise InvalidIssuedAtError('Issued At claim (iat) cannot be in'
|
||||||
|
' the future.')
|
||||||
|
|
||||||
|
|
||||||
def exp_max_s_option(max_exp_s):
|
def exp_max_s_option(max_exp_s):
|
||||||
return {
|
return {
|
||||||
|
|
Reference in a new issue