Exemplo n.º 1
0
def verify(current_request: chalice.app.Request) -> str:
    try:
        current_request.headers['authorization']
    except KeyError as e:
        logger.warning('Missing authorization header: ', exc_info=e)
        chalice.UnauthorizedError('Not Authorized')

    base_url = current_request.headers['host']
    path = current_request.context['resourcePath']
    endpoint = f'{base_url}{path}'
    method = current_request.context['httpMethod']
    headers = current_request.headers
    _key_id: Optional[str] = None

    def key_resolver(*, key_id, algorithm):
        require(algorithm == 'hmac-sha256', algorithm)
        key, _ = aws.get_hmac_key_and_id_cached(key_id)
        key = key.encode()
        # Since HTTPSignatureAuth.verify doesn't return anything we need to
        # extract the key ID in this round-about way.
        nonlocal _key_id
        _key_id = key_id
        return key

    try:
        HTTPSignatureAuth.verify(requests.Request(method, endpoint, headers),
                                 key_resolver=key_resolver)
    except BaseException as e:
        logger.warning('Exception while validating HMAC: ', exc_info=e)
        raise chalice.UnauthorizedError('Invalid authorization credentials')
    else:
        assert _key_id is not None
        return _key_id
Exemplo n.º 2
0
    def dss_notification():
        body = app.current_request.json_body
        bundle_uuid = body['match']['bundle_uuid']
        bundle_version = body['match']['bundle_version']
        subscription_id = body['subscription_id']
        event_type = body['event_type']

        config = MatrixInfraConfig()
        hmac_secret_key = config.dss_subscription_hmac_secret_key.encode()
        HTTPSignatureAuth.verify(
            requests.Request(url="http://host/dss/notification",
                             method=app.current_request.method,
                             headers=app.current_request.headers),
            key_resolver=lambda key_id, algorithm: hmac_secret_key)

        payload = {
            'bundle_uuid': bundle_uuid,
            'bundle_version': bundle_version,
            'event_type': event_type,
        }
        queue_url = config.notification_q_url
        SQSHandler().add_message_to_queue(queue_url, payload)

        return chalice.Response(
            status_code=requests.codes.ok,
            body=f"Received notification from subscription {subscription_id}: "
            f"{event_type} {bundle_uuid}.{bundle_version}")
Exemplo n.º 3
0
def auth_from_account(account: Optional[Account] = None) -> Optional[Callable]:
    "Generate the HTTP Signatures authenticator of requests."

    def signature_auth(func):
        """
        Authenticator wrapper.
        The HTTP param used in ActivityPub implementations
        differs from the standard one?
        """
        def call(request):
            request = func(request)
            _signature, string = request.headers["Authorization"].split(" ", 1)
            request.headers["Signature"] = string
            del request.headers["Authorization"]
            return request

        return call

    if account:
        return signature_auth(
            HTTPSignatureAuth(key=account.private_key.encode('utf-8'),
                              key_id="%s#main-key" % account.ap_id,
                              algorithm="rsa-sha256",
                              headers=["(request-target)", "host", "date"]))
    else:
        return None
    def _post_notification(self, bundle_fqid, event_type):
        data = {}
        bundle_uuid = bundle_fqid.split('.', 1)[0]
        bundle_version = bundle_fqid.split('.', 1)[1]
        url = f"{self.api_url[:-3]}/dss/notification"
        config = MatrixInfraConfig()

        data["transaction_id"] = "test_transaction_id"
        data["subscription_id"] = "test_subscription_id"
        data["event_type"] = event_type
        data["match"] = {}
        data["match"]["bundle_uuid"] = bundle_uuid
        data["match"]["bundle_version"] = bundle_version

        response = requests.post(
            url=url,
            json=data,
            auth=HTTPSignatureAuth(
                key_id=DSS_SUBSCRIPTION_HMAC_SECRET_ID,
                key=config.dss_subscription_hmac_secret_key.encode()))

        print(
            f"POST NOTIFICATION TO MATRIX SERVICE: \nPOST {url}\n-> {response.status_code}"
        )
        if response.content:
            print(response.content.decode('utf8'))
Exemplo n.º 5
0
def sign_transaction(address,
                     nonce,
                     gaslimit,
                     value=None,
                     dest=None,
                     contract_data=None,
                     gas_price=None,
                     chain_id=None,
                     child_id=None):
    data = {
        'from': address,
        'nonce': nonce,
        'gas': gaslimit,
    }
    if value:
        data['value'] = value
    if dest:
        data['to'] = dest
    if contract_data:
        data['data'] = contract_data
    if gas_price:
        data['gasPrice'] = gas_price

    if chain_id:
        data['chainId'] = chain_id
    if child_id:
        data['child_id'] = child_id

    auth = HTTPSignatureAuth(key=SECRET_KEY, key_id=KEY_ID)
    signed_response = requests.post(SIGNER, auth=auth, json=data)
    signed_data = json.loads(signed_response.content.decode())
    return signed_data['signed_tx']
Exemplo n.º 6
0
 def test_readme_example(self):
     preshared_key_id = 'squirrel'
     preshared_secret = 'monorail_cat'
     url = 'http://example.com/path'
     requests.get(url,
                  auth=HTTPSignatureAuth(key=preshared_secret,
                                         key_id=preshared_key_id))
Exemplo n.º 7
0
 def _prepare_request(self, timeout, attempt) -> Mapping[str, Any]:
     if self.hmac_key:
         auth = HTTPSignatureAuth(key=self._sqs2bin(self.hmac_key),
                                  key_id=self.hmac_key_id)
     else:
         auth = None
     headers = {}
     if attempt is not None:
         headers[attempt_header_name] = str(attempt)
     request = dict(method=self.method,
                    url=self.url,
                    auth=auth,
                    allow_redirects=False,
                    headers=headers,
                    timeout=timeout)
     body = json.loads(self._sqs2bin(self.body))
     if self.encoding == 'application/json':
         request['json'] = body
     elif self.encoding == 'multipart/form-data':
         # The requests.request() method can encode this content type for us (using the files= keyword argument)
         # but it is awkward to use if the field values are strings or bytes and not streams.
         data, content_type = urllib3.encode_multipart_formdata(body)
         request['data'] = data
         request['headers']['Content-Type'] = content_type
     else:
         raise ValueError(f'Encoding {self.encoding} is not supported')
     return request
Exemplo n.º 8
0
    def _just_request(self, request, is_signed=False):
        auth_value = None
        if is_signed:
            auth_value = HTTPSignatureAuth(
                algorithm="ecdsa-sha256",
                key=open(self.key, "rb").read(),
                # key_id needs to be specified but is unused
                key_id="tls",
                headers=[
                    "(request-target)",
                    "Date",
                    "Content-Length",
                    "Content-Type",
                ],
            )

        extra_headers = {}
        if request.readonly_hint:
            extra_headers[CCF_READ_ONLY_HEADER] = "true"

        response = self.session.post(
            f"https://{self.host}:{self.port}/{request.method}",
            json=request.params,
            timeout=self.request_timeout,
            auth=auth_value,
            headers=extra_headers,
        )
        return Response.from_requests_response(response)
Exemplo n.º 9
0
    def do_POST(self):
        length = int(self.headers['content-length'])
        attempt = int(self.headers[attempt_header_name])
        payload = json.loads(self.rfile.read(length).decode())
        verify = payload['verify']
        if verify:
            HTTPSignatureAuth.verify(
                requests.Request("POST", self.path, self.headers),
                key_resolver=lambda key_id, algorithm: self.hmac_secret_key)
            try:
                HTTPSignatureAuth.verify(requests.Request(
                    "POST", self.path, self.headers),
                                         key_resolver=lambda key_id, algorithm:
                                         self.hmac_secret_key[::-1])
            except AssertionError:
                pass
            else:
                raise AssertionError("Expected AssertionError")
        responses = payload['responses']
        delay, status = responses[attempt if attempt < len(responses) else -1]
        self.send_response(status)
        if delay:
            self.send_header("Content-length", len(self.response_body))
            self.end_headers()
            time.sleep(delay)
            # Write a lot of data to force the detection of a client disconnect. The connection is to the loopback
            # interface so this shouldn't matter much performance-wise. When the disconnect is detected,
            # the execptions raised range from the expected EPIPE to the exotic 'OSError: [Errno 41] Protocol wrong
            # type for socket'. We don't care which exception is raised as long as it prevents the request being
            # recorded as a success.
            try:
                self.wfile.write(self.response_body)
                self.wfile.flush()
            except OSError:
                logger.info(
                    "An expected exception occurred while sending response to client:",
                    exc_info=True)
                return
        else:
            self.send_header("Content-length", 0)
            self.end_headers()

        if status == 200:
            notification_id = payload['notification_id']
            logger.info("Received notification_id %s", notification_id)
            self.actual_receptions.append(notification_id)
Exemplo n.º 10
0
 def test_basic_statements(self):
     url = 'http://example.com/path?query#fragment'
     self.session.get(url,
                      auth=HTTPSignatureAuth(key=hmac_secret,
                                             key_id="sekret"))
     with self.assertRaises(AssertionError):
         self.session.get(url,
                          auth=HTTPSignatureAuth(key=hmac_secret[::-1],
                                                 key_id="sekret"))
     with self.assertRaisesRegex(
             RequestsHttpSignatureException,
             "Could not compute digest header for request without a body"):
         self.session.get(url,
                          auth=HTTPSignatureAuth(key=hmac_secret[::-1],
                                                 key_id="sekret",
                                                 headers=["date",
                                                          "digest"]))
Exemplo n.º 11
0
    def send(self, request, *args, **kwargs):
        def key_resolver(key_id, algorithm):
            if "pubkey" in request.headers:
                return base64.b64decode(request.headers["pubkey"])
            return hmac_secret

        HTTPSignatureAuth.verify(request,
                                 key_resolver=key_resolver,
                                 scheme=request.headers.get(
                                     "sigScheme", "Authorization"))
        if "expectSig" in request.headers:
            self.testcase.assertEqual(
                request.headers["expectSig"],
                HTTPSignatureAuth.get_sig_struct(request)["signature"])
        response = requests.Response()
        response.status_code = requests.codes.ok
        response.url = request.url
        return response
Exemplo n.º 12
0
 def _test(self, body: JSON, delete: bool, valid_auth: bool) -> requests.Response:
     hmac_creds = {'key': b'good key', 'key_id': 'the id'}
     with patch('azul.deployment.aws.get_hmac_key_and_id', return_value=hmac_creds):
         if valid_auth:
             auth = hmac.prepare()
         else:
             auth = HTTPSignatureAuth(key=b'bad key', key_id='the id')
         url = self.base_url.set(path=(self.catalog, 'delete' if delete else 'add'))
         return requests.post(str(url), json=body, auth=auth)
Exemplo n.º 13
0
def run_query(args):
    while args.endpoint.endswith("/"):
        args.endpoint = args.endpoint[:-1]
    if args.variant:
        logger.info("Executing query for %s...", args.variant)
        url = "%s/query" % args.endpoint
        chrom, pos, ref, alt = args.variant.split("-")
        params = {
            "assemblyId": "GRCh37",
            "referenceName": chrom,
            "start": pos,
            "referenceBases": ref,
            "alternateBases": alt,
        }
    else:
        logger.info("Asking beacon for info...")
        url = "%s/" % args.endpoint
        params = None

    with open(args.key_file, "rb") as keyf:
        key = keyf.read()

    headers = {"X-Beacon-User": args.beacon_user}

    r = requests.get(
        url,
        headers=headers,
        params=params,
        auth=HTTPSignatureAuth(
            algorithm="rsa-sha256",
            key=key,
            key_id=args.key_id,
            headers=["date", "x-beacon-user"],
        ),
    )

    if r.ok:
        logger.info("=> OK %s", r.status_code)
        logger.info("result below on stdout --8<-- --8<-- --8<--")
        print(json.dumps(r.json(), indent=2))
        logger.info("-->8-- -->8-- -->8-- result above on stdout")
    else:
        logger.info("=> ERROR: %s (%s)", r.status_code, r.reason)
        try:
            data = json.dumps(r.json(), indent=2)
            logger.info("details below on stdout --8<-- --8<-- --8<--")
            print(data)
            logger.info("-->8-- -->8-- -->8-- details above on stdout")
        except:
            pass  # swallow

    if args.variant:
        logger.info("... done executing query.")
    else:
        logger.info("... done asking beacon for info.")
    logger.info("Have a nice day!")
Exemplo n.º 14
0
def sign_view(request):
    try:
        HTTPSignatureAuth.verify(request, key_resolver=key_resolver)
    except (AssertionError, ClientSecret.DoesNotExist):
        raise PermissionDenied

    tx_params = request.data

    try:
        account = BlockchainAccount.objects.get(address=tx_params.pop('from'))
    except BlockchainAccount.DoesNotExist:
        raise PermissionDenied

    if account.network_type == NetworkType.ETHEREUM_LIKE:
        signed_tx = Web3().eth.account.sign_transaction(
            tx_params, account.private_key)
        raw_hex_tx = signed_tx.rawTransaction.hex()
        return JsonResponse({'signed_tx': raw_hex_tx})
    elif account.network_type == NetworkType.BINANCE_CHAIN:
        raise PermissionDenied
Exemplo n.º 15
0
 def test_httpget_signature_auth_with_valid_credential(self):
     key_id = "test-key-id"
     priv_key_bytes = priv_key.private_bytes(
         encoding=Encoding.PEM,
         format=PrivateFormat.PKCS8,
         encryption_algorithm=NoEncryption())
     r = requests.get(self.get_server_url() + '/userinfo',
                      auth=HTTPSignatureAuth(
                          algorithm='rsa-sha256',
                          key=priv_key_bytes,
                          key_id=key_id,
                          headers=['(request-target)', '(created)']))
     self.assertEqual(r.status_code, 200)
     self.assertEqual(r.json()['key_id'], key_id)
Exemplo n.º 16
0
 def my_handle(self, method):
     global recieved_notification
     if "notification_test_pass_with_auth" in self.path:
         code = 200
         HTTPSignatureAuth.verify(requests.Request(method, self.path,
                                                   self.headers),
                                  key_resolver=lambda key_id, algorithm:
                                  self.hmac_secret_key.encode())
     if "notification_test_pass" in self.path:
         code = 200
     elif "notification_test_fail" in self.path:
         code = 400
     else:
         return self._generic_handle()
     size = int(self.headers.get('Content-Length', 0))
     body = self.rfile.read(size)
     try:
         recieved_notification = json.loads(body)
     except Exception as e:
         recieved_notification = str(e)
     self.send_response(code)
     self.send_header("Content-Length", 0)
     self.end_headers()
Exemplo n.º 17
0
Arquivo: hmac.py Projeto: NoopDog/azul
def verify(current_request):
    try:
        current_request.headers['authorization']
    except KeyError as e:
        logger.warning('Missing authorization header: ', exc_info=e)
        chalice.UnauthorizedError('Not Authorized')

    base_url = current_request.headers['host']
    path = current_request.context['resourcePath']
    endpoint = f'{base_url}{path}'
    method = current_request.context['httpMethod']
    headers = current_request.headers

    def key_resolver(key_id, algorithm):
        require(algorithm == 'hmac-sha256', algorithm)
        key, _ = aws.get_hmac_key_and_id_cached(key_id)
        return key.encode()

    try:
        HTTPSignatureAuth.verify(requests.Request(method, endpoint, headers),
                                 key_resolver=key_resolver)
    except BaseException as e:
        logger.warning('Exception while validating HMAC: ', exc_info=e)
        raise chalice.UnauthorizedError('Invalid authorization credentials')
Exemplo n.º 18
0
 def get(self, request, *args, **kwargs):
     local_site = Site.objects.get(role=Site.LOCAL)
     remote_site = get_object_or_404(Site, sodar_uuid=kwargs.get("site"))
     r = requests.get(
         remote_site.entrypoint_url,
         headers={"X-Beacon-User": request.user.username},
         auth=HTTPSignatureAuth(
             algorithm=local_site.key_algo,
             key=str(local_site.private_key).encode("utf-8"),
             key_id=local_site.identifier,
             headers=["date", "x-beacon-user"],
         ),
     )
     return JsonResponse(data=r.json(),
                         status=r.status_code,
                         reason=r.reason)
Exemplo n.º 19
0
    def request(self, request, is_signed=False):
        auth_value = None
        if is_signed:
            auth_value = HTTPSignatureAuth(
                algorithm="ecdsa-sha256",
                key=open(self.key, "rb").read(),
                # key_id needs to be specified but is unused
                key_id="tls",
                headers=[
                    "(request-target)",
                    "Date",
                    "Content-Length",
                    "Content-Type",
                ],
            )

        extra_headers = {}
        extra_headers.update(request.headers)

        request_args = {
            "method": request.http_verb,
            "url": f"https://{self.host}:{self.port}/{request.method}",
            "auth": auth_value,
            "headers": extra_headers,
        }

        is_get = request.http_verb == "GET"
        if request.params is not None:
            if is_get:
                request_args["params"] = build_query_string(request.params)
            else:
                request_args["json"] = request.params

        try:
            response = self.session.request(timeout=self.request_timeout,
                                            **request_args)
        except requests.exceptions.ReadTimeout as exc:
            raise TimeoutError from exc
        except requests.exceptions.SSLError as exc:
            raise CCFConnectionException from exc
        except Exception as exc:
            raise RuntimeError(
                "Request client failed with unexpected error") from exc

        return Response.from_requests_response(response)
Exemplo n.º 20
0
 def signed_request(self, request):
     with open(self.key, "rb") as k:
         rep = requests.post(
             f"https://{self.host}:{self.port}/{request.method}",
             json=request.to_dict(),
             cert=(self.cert, self.key),
             verify=self.ca,
             timeout=self.request_timeout,
             # key_id needs to be specified but is unused
             auth=HTTPSignatureAuth(
                 algorithm="ecdsa-sha256",
                 key=k.read(),
                 key_id="tls",
                 headers=["(request-target)", "Date"],
             ),
         )
         self.stream.update(rep.content)
     return request.id
Exemplo n.º 21
0
    def _notify_subscriber(self, subscription: dict):
        subscription_id = subscription['id']
        transaction_id = str(uuid.uuid4())
        payload = {
            "transaction_id": transaction_id,
            "subscription_id": subscription_id,
            "es_query": subscription['es_query'],
            "match": {
                "bundle_uuid": self.fqid.uuid,
                "bundle_version": self.fqid.version,
            }
        }
        callback_url = subscription['callback_url']

        # FIXME wrap all errors in this block with an exception handler
        if DeploymentStage.IS_PROD():
            allowed_schemes = {'https'}
        else:
            allowed_schemes = {'https', 'http'}

        assert urlparse(callback_url).scheme in allowed_schemes, "Unexpected scheme for callback URL"

        if DeploymentStage.IS_PROD():
            hostname = urlparse(callback_url).hostname
            for family, socktype, proto, canonname, sockaddr in socket.getaddrinfo(hostname, port=None):
                msg = "Callback hostname resolves to forbidden network"
                assert ipaddress.ip_address(sockaddr[0]).is_global, msg  # type: ignore

        auth = None
        if "hmac_secret_key" in subscription:
            auth = HTTPSignatureAuth(key=subscription['hmac_secret_key'].encode(),
                                     key_id=subscription.get("hmac_key_id", "hca-dss:" + subscription_id))
        response = requests.post(callback_url, json=payload, auth=auth)

        # TODO (mbaumann) Add webhook retry logic
        if 200 <= response.status_code < 300:
            logger.info(f"Successfully notified for subscription {subscription_id}"
                        f" for bundle {self.fqid} with transaction id {transaction_id} "
                        f"Code: {response.status_code}")
        else:
            logger.warning(f"Failed notification for subscription {subscription_id}"
                           f" for bundle {self.fqid} with transaction id {transaction_id} "
                           f"Code: {response.status_code}")
Exemplo n.º 22
0
    def _just_request(self, request, is_signed=False):
        auth_value = None
        if is_signed:
            auth_value = HTTPSignatureAuth(
                algorithm="ecdsa-sha256",
                key=open(self.key, "rb").read(),
                # key_id needs to be specified but is unused
                key_id="tls",
                headers=[
                    "(request-target)",
                    "Date",
                    "Content-Length",
                    "Content-Type",
                ],
            )

        extra_headers = {}
        if request.readonly_hint:
            extra_headers[CCF_READ_ONLY_HEADER] = "true"

        extra_headers.update(request.headers)

        request_args = {
            "method": request.http_verb,
            "url": f"https://{self.host}:{self.port}/{request.method}",
            "auth": auth_value,
            "headers": extra_headers,
        }

        is_get = request.http_verb == "GET"
        if request.params is not None:
            if is_get:
                request_args["params"] = build_query_string(request.params)
            else:
                request_args["json"] = request.params

        response = self.session.request(timeout=self.request_timeout,
                                        **request_args)
        return Response.from_requests_response(response)
Exemplo n.º 23
0
    def _just_request(self, request, is_signed=False):
        auth_value = None
        if is_signed:
            auth_value = HTTPSignatureAuth(
                algorithm="ecdsa-sha256",
                key=open(self.key, "rb").read(),
                # key_id needs to be specified but is unused
                key_id="tls",
                headers=[
                    "(request-target)",
                    "Date",
                    "Content-Length",
                    "Content-Type",
                ],
            )

        rep = self.session.post(
            f"https://{self.host}:{self.port}/{request.method}",
            json=request.params,
            timeout=self.request_timeout,
            auth=auth_value,
        )
        return rep.content
Exemplo n.º 24
0
 def test_rsa(self):
     from cryptography.hazmat.backends import default_backend
     from cryptography.hazmat.primitives.asymmetric import rsa
     from cryptography.hazmat.primitives import serialization
     private_key = rsa.generate_private_key(public_exponent=65537,
                                            key_size=2048,
                                            backend=default_backend())
     private_key_pem = private_key.private_bytes(
         encoding=serialization.Encoding.PEM,
         format=serialization.PrivateFormat.PKCS8,
         encryption_algorithm=serialization.BestAvailableEncryption(
             passphrase))
     public_key_pem = private_key.public_key().public_bytes(
         encoding=serialization.Encoding.PEM,
         format=serialization.PublicFormat.SubjectPublicKeyInfo)
     url = 'http://example.com/path?query#fragment'
     auth = HTTPSignatureAuth(algorithm="rsa-sha256",
                              key=private_key_pem,
                              key_id="sekret",
                              passphrase=passphrase)
     self.session.get(url,
                      auth=auth,
                      headers=dict(pubkey=base64.b64encode(public_key_pem)))
Exemplo n.º 25
0
 def test_httppost_signature_auth_with_valid_credential(self):
     key_id = "test-key-id"
     first_name = "Test First Name"
     last_name = "Test Last Name"
     priv_key_bytes = priv_key.private_bytes(
         encoding=Encoding.PEM,
         format=PrivateFormat.PKCS8,
         encryption_algorithm=NoEncryption())
     r = requests.post(self.get_server_url() + '/userinfo',
                       auth=HTTPSignatureAuth(algorithm='rsa-sha256',
                                              key=priv_key_bytes,
                                              key_id=key_id,
                                              headers=[
                                                  '(request-target)',
                                                  '(created)', 'digest'
                                              ]),
                       json={
                           'first_name': first_name,
                           'last_name': last_name
                       })
     self.assertEqual(r.status_code, 200)
     self.assertEqual(r.json()['key_id'], key_id)
     self.assertEqual(r.json()['first_name'], first_name)
     self.assertEqual(r.json()['last_name'], last_name)
Exemplo n.º 26
0
Dx9KSZ39ncBOWzAq+jTZrKlnJco0EyamsuUfq+KcVl9iEySavTeweup9AoGAIjUD
0jm1JDQGzz7/7EhuifWfKGYuLTWNiveVlp09foKIA0g0O9fPEzSzDFhXKMf+QTvy
JAs8RdoeLJHstnbARTuyR3vTUdBtr6GA4pnmbtnqvkeOnExesjZuXzZURZ3bFc8z
tAxrQFfmHKT2HcQcHn7LDa0AuF+oqrisCgH+SvMCgYBX7nvnJds0zrbjuatUiZsk
YLcXOq/N6ht7XUqpfjlqjwSodauC4SdvT4cb7Fs4Pme83NYOemEExIgOjIWNpu6G
EfLwfC9n3PiORmeqIfI+EMEvhHKJZc3h9sCWV7k6cNBUR0p18P6vwQ/+cr5YN4UU
4iqeZglebSwlolY3zdLCOw==
-----END PRIVATE KEY-----
"""

if __name__ == '__main__':
    # GET
    r = requests.get('http://localhost:5900/userinfo',
                     auth=HTTPSignatureAuth(
                         algorithm='rsa-sha256',
                         key=key_bytes,
                         key_id=key_id,
                         headers=['(request-target)', '(created)']))
    assert r.ok

    assert r.json()['key_id'] == key_id

    # POST
    r = requests.post('http://localhost:5900/userinfo',
                      auth=HTTPSignatureAuth(
                          algorithm='rsa-sha256',
                          key=key_bytes,
                          key_id=key_id,
                          headers=['(request-target)', '(created)', 'digest']),
                      json={
                          'first_name': 'Ashley',
Exemplo n.º 27
0
Arquivo: hmac.py Projeto: NoopDog/azul
def prepare():
    key, key_id = aws.get_hmac_key_and_id()
    return HTTPSignatureAuth(key=key.encode(), key_id=key_id)
Exemplo n.º 28
0
import requests
from requests_http_signature import HTTPSignatureAuth

key_id = "squirrel"
key_secret = b"monorail_cat"
url = "https://matrix.ag5.com/api/[endpoint]/serviceIsAvailable"

get_headers = ('(request-target)', 'date', 'host')
post_headers = get_headers + ('content-type', 'digest')

# Example GET request
response = requests.post(
    url,
    auth=HTTPSignatureAuth(
        key=key_secret,
        algorithm='hmac-sha256',
        key_id=key_id,
        headers=get_headers,
    ),
)

# Example POST request
response = requests.post(
    url,
    headers={'Content-Type': 'application/json'},
    data=json.dumps({
        "hello": "world"
    }).encode('utf-8'),
    auth=HTTPSignatureAuth(
        key=key_secret,
        algorithm='hmac-sha256',
        key_id=key_id,
Exemplo n.º 29
0
def notify(subscription: dict, metadata_document: dict, key: str) -> bool:
    """
    Attempt notification delivery. Return True for success, False for failure
    """
    fqid = key.split("/")[1]
    bundle_uuid, bundle_version = fqid.split(".", 1)
    sfx = f".{TOMBSTONE_SUFFIX}"
    if bundle_version.endswith(sfx):
        bundle_version = bundle_version[:-len(sfx)]
    api_domain_name = f'https://{os.environ.get("API_DOMAIN_NAME")}'
    payload = {
        'bundle_url': api_domain_name + f'/v1/bundles/{bundle_uuid}?version={bundle_version}',
        'dss_api': api_domain_name,
        'subscription_id': subscription[SubscriptionData.UUID],
        'event_timestamp': datetime_to_version_format(datetime.datetime.utcnow()),
        'event_type': metadata_document['event_type'],
        'match': {
            'bundle_uuid': bundle_uuid,
            'bundle_version': bundle_version,
        },
        'transaction_id': str(uuid4())
    }

    jmespath_query = subscription.get(SubscriptionData.JMESPATH_QUERY)
    if jmespath_query is not None:
        payload[SubscriptionData.JMESPATH_QUERY] = jmespath_query

    if "CREATE" == metadata_document['event_type']:
        attachments_defs = subscription.get(SubscriptionData.ATTACHMENTS)
        if attachments_defs is not None:
            errors = dict()
            attachments = dict()
            for name, attachment in attachments_defs.items():
                if 'jmespath' == attachment['type']:
                    try:
                        value = jmespath.search(attachment['expression'], metadata_document)
                    except BaseException as e:
                        errors[name] = str(e)
                    else:
                        attachments[name] = value
            if errors:
                attachments['_errors'] = errors
            size = len(json.dumps(attachments).encode('utf-8'))
            if size > _attachment_size_limit:
                attachments = {'_errors': f"Attachments too large ({size} > {_attachment_size_limit})"}
            payload['attachments'] = attachments

    request = {
        'method': subscription.get(SubscriptionData.METHOD, "POST"),
        'url': subscription[SubscriptionData.CALLBACK_URL],
        'headers': dict(),
        'allow_redirects': False,
        'timeout': None,
    }

    hmac_key = subscription.get('hmac_secret_key')
    if hmac_key:
        hmac_key_id = subscription.get('hmac_key_id', "hca-dss:" + subscription['uuid'])
        request['auth'] = HTTPSignatureAuth(key=hmac_key.encode(), key_id=hmac_key_id)
        # get rid of this so it doesn't appear in delivery log messages
        del subscription['hmac_secret_key']
    else:
        request['auth'] = None

    encoding = subscription.get(SubscriptionData.ENCODING, "application/json")
    if encoding == "application/json":
        request['json'] = payload
    elif encoding == 'multipart/form-data':
        body = subscription[SubscriptionData.FORM_FIELDS].copy()
        body[subscription[SubscriptionData.PAYLOAD_FORM_FIELD]] = json.dumps(payload)
        data, content_type = urllib3.encode_multipart_formdata(body)
        request['data'] = data
        request['headers']['Content-Type'] = content_type
    else:
        raise ValueError(f"Encoding {encoding} is not supported")

    try:
        response = requests.request(**request)
    except BaseException as e:
        logger.warning("Exception raised while delivering notification: %s, subscription: %s",
                       str(payload), str(subscription), exc_info=e)
        return False

    if 200 <= response.status_code < 300:
        logger.info("Successfully delivered %s: HTTP status %i, subscription: %s",
                    str(payload), response.status_code, str(subscription))
        return True
    else:
        logger.warning("Failed delivering %s: HTTP status %i, subscription: %s",
                       str(payload), response.status_code, str(subscription))
        return False
Exemplo n.º 30
0
action = sys.argv[2]

if action == 'update' and len(sys.argv) < 5:
    usage()

url = sys.argv[3]
if url.endswith("/"):
    url = url[:-1]

# some APIs check the body digest, others (bodyless) don't
date_digest_target = ['date', 'digest', '(request-target)']
date_target = ['date', '(request-target)']

with open(keyfilepath, 'rb') as fh:
    # define the authentication options for the http requests
    auth = HTTPSignatureAuth(
        algorithm="rsa-sha256",
        key=fh.read(),
        key_id=keyid,
        headers=date_target if action != 'update' else date_digest_target)
    res = {'content': "No request sent"}
    if action == 'reload':
        res = requests.post(url + '/reload', auth=auth)
    if action == 'update':
        res = requests.put(url, data=(sys.argv[4]).encode('ascii'), auth=auth)
    if action == 'delete':
        res = requests.delete(url, auth=auth)
    if action == 'check':
        res = requests.post(url + '/auth_check', auth=auth)
    print(res.content)