Beispiel #1
0
    def test_get_key(self):
        hs_key = jwk.get_key("HS256")
        assert hs_key == HMACKey
        assert issubclass(hs_key, Key)
        assert issubclass(jwk.get_key("RS256"), Key)
        assert issubclass(jwk.get_key("ES256"), Key)

        assert jwk.get_key("NONEXISTENT") is None
Beispiel #2
0
    def test_get_key(self):
        hs_key = jwk.get_key("HS256")
        assert hs_key == jwk.HMACKey
        assert issubclass(hs_key, Key)
        assert issubclass(jwk.get_key("RS256"), Key)
        assert issubclass(jwk.get_key("ES256"), Key)

        assert jwk.get_key("NONEXISTENT") is None
Beispiel #3
0
def pkcs11_jws_verify(token: str) -> Optional[str]:
    """
    Perform JWS Sign with a key stored in an PKCS#11 token.

    This requires temporarily switching the key class for the algorithm in the token.
    See the documentation for pkcs11_jws_sign for more details.

    :return: The signed payload from the token, or None if verify is not supported
    """
    headers = jws.get_unverified_headers(token)
    _alg = headers['alg']

    # First, check if verify for this algorithm is supported by the token (current YubiKey can
    # sign with ECDSA, but not verify).
    # We have to do it in this hackish manner since the JOSE library will ignore any exceptions
    # from the verify method and just turn everything into an
    # JWSError('Signature verification failed.') exception.
    _p11key = P11Key('', _alg, P11Key_params)
    with _p11key.token.open(user_pin=_p11key.p11.pin) as session:
        _p11key._load_key(session)
        info = _p11key.token.slot.get_mechanism_info(_p11key._mechanism)
    logger.debug('Token mechanism info:\n{}'.format(info))
    if pkcs11.MechanismFlag.VERIFY not in info.flags:
        logger.info(
            'Verify is not a supported operation for algorithm {} using the PKCS#11 token'
            .format(_p11key._algorithm))
        return None

    orig_key = jwk.get_key(_alg)
    try:
        # First check if verify is a supported operation using this al
        jwk.register_key(_alg, P11Key)
        res = jws.verify(
            token, '', algorithms=[jwk.ALGORITHMS.ES256, jwk.ALGORITHMS.RS256])
    except:
        raise
    finally:
        jwk.register_key(_alg, orig_key)
    return res
Beispiel #4
0
def pkcs11_jws_sign(data, key=None, headers=None) -> str:
    """
    Perform JWS Sign with a key stored in an PKCS#11 token.

    This requires some trickery - temporary switch out the key class for the algorithm
    to P11Key before calling jws.sign. It is not possible to just register a new algorithm,
    say ECP11, because the algorithm is included in the JWT and the consumer of the JWT
    would expect ES256 (or similar) and not know how to handle ECP11.

    :return: A signed JWT
    """
    global P11Key_params
    _p11key = P11Key('', '', P11Key_params)
    _alg = _p11key.get_jwk_alg()

    orig_key = jwk.get_key(_alg)
    try:
        jwk.register_key(_alg, P11Key)
        res = jws.sign(data, key, algorithm=_alg, headers=headers)
    except:
        raise
    finally:
        jwk.register_key(_alg, orig_key)
    return res
Beispiel #5
0
    def __init__(self):
        """Initialize the default configuration."""
        self.CORS_ORIGINS = os.environ['ALLOWED_ORIGINS'].split(',')
        self.RSA_PRIVATE_KEY = pathlib.Path('keys/rsa').read_text()
        self.ALGORITHM = 'RS512'
        self.RSA_PUBLIC_KEY = jwk.get_key(self.ALGORITHM)(
            self.RSA_PRIVATE_KEY,
            self.ALGORITHM,
        ).public_key().to_dict()
        self.JWT_VALIDITY = timedelta(minutes=10)
        self.REFRESH_TOKEN_VALIDITY = timedelta(days=30)
        self.SENTRY_DSN = os.environ.get('SENTRY_DSN')

        self.APISPEC_TITLE = "iam"
        self.APISPEC_SWAGGER_UI_URL = "/"

        self.BASIC_AUTH_USERNAME = os.environ['BASIC_AUTH_USERNAME']
        self.BASIC_AUTH_PASSWORD = os.environ['BASIC_AUTH_PASSWORD']

        self.FEAT_TOGGLE_LOCAL_AUTH = bool(
            os.environ['FEAT_TOGGLE_LOCAL_AUTH'])
        self.SQLALCHEMY_DATABASE_URI = (
            f"postgresql://{os.environ['DB_USERNAME']}:"
            f"{os.environ['DB_PASSWORD']}@{os.environ['DB_HOST']}:"
            f"{os.environ['DB_PORT']}/{os.environ['DB_NAME']}"
            f"?connect_timeout=10")
        self.SQLALCHEMY_TRACK_MODIFICATIONS = False

        self.FEAT_TOGGLE_FIREBASE = bool(os.environ['FEAT_TOGGLE_FIREBASE'])
        self.FIREBASE_CLIENT_CERT_URL = os.environ.get(
            'FIREBASE_CLIENT_CERT_URL')
        self.FIREBASE_CLIENT_EMAIL = os.environ.get('FIREBASE_CLIENT_EMAIL')
        self.FIREBASE_CLIENT_ID = os.environ.get('FIREBASE_CLIENT_ID')
        self.FIREBASE_PRIVATE_KEY = os.environ.get('FIREBASE_PRIVATE_KEY')
        self.FIREBASE_PRIVATE_KEY_ID = os.environ.get(
            'FIREBASE_PRIVATE_KEY_ID')
        self.FIREBASE_PROJECT_ID = os.environ.get('FIREBASE_PROJECT_ID')
        self.SENDGRID_API_KEY = os.environ.get('SENDGRID_API_KEY')

        self.LOGGING = {
            'version': 1,
            'disable_existing_loggers': False,
            'formatters': {
                'simple': {
                    'format':
                    "%(asctime)s [%(levelname)s] [%(name)s] "
                    "%(filename)s:%(funcName)s:%(lineno)d | "
                    "%(message)s"
                },
            },
            'handlers': {
                'console': {
                    'level': 'DEBUG',
                    'class': 'logging.StreamHandler',
                    'formatter': 'simple',
                },
            },
            'loggers': {
                # All loggers will by default use the root logger below (and
                # hence be very verbose). To silence spammy/uninteresting log
                # output, add the loggers here and increase the loglevel.
                'parso': {
                    'level': 'INFO',
                    'handlers': ['console'],
                    'propagate': False,
                }
            },
            'root': {
                'level': 'DEBUG',
                'handlers': ['console'],
            },
        }
Beispiel #6
0
    def test_register_key(self):
        assert jwk.register_key("ALG", jwk.Key)
        assert jwk.get_key("ALG") == jwk.Key

        with pytest.raises(TypeError):
            assert jwk.register_key("ALG", object)
Beispiel #7
0
    def test_register_key(self):
        assert jwk.register_key("ALG", jwk.Key)
        assert jwk.get_key("ALG") == jwk.Key

        with pytest.raises(TypeError):
            assert jwk.register_key("ALG", object)
Beispiel #8
0
 def test_get_aes_key(self):
     assert issubclass(jwk.get_key("A256CBC-HS512"), Key)
Beispiel #9
0
    def test_get_key(self):
        assert jwk.get_key("HS256") == jwk.HMACKey
        assert jwk.get_key("RS256") == jwk.RSAKey
        assert jwk.get_key("ES256") == jwk.ECKey

        assert jwk.get_key("NONEXISTENT") == None