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
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}")
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'))
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']
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))
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
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)
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)
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"]))
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
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)
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!")
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
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)
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()
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')
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)
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)
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
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}")
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)
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
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)))
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)
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',
def prepare(): key, key_id = aws.get_hmac_key_and_id() return HTTPSignatureAuth(key=key.encode(), key_id=key_id)
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,
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
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)