From ddb1c9be0ea015fe52a76bb07be9ab7ce9c29665 Mon Sep 17 00:00:00 2001 From: Jason Bissict Date: Tue, 16 Jan 2024 06:40:10 +0200 Subject: [PATCH 1/8] Add handling for CORS preflight checks --- canarytokens/channel_http.py | 34 +++++++++++++++++++++++++++++++++- frontend/frontend.env.dist | 6 +++--- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/canarytokens/channel_http.py b/canarytokens/channel_http.py index 07bc10eac..d704abb3e 100644 --- a/canarytokens/channel_http.py +++ b/canarytokens/channel_http.py @@ -130,11 +130,12 @@ def render_GET(self, request: Request): request.setHeader("Server", "Apache") return resp - def render_OPTIONS(self, request): + def render_OPTIONS(self, request: Request): """ Alert as if it is a normal GET request, but return the expected content and headers. """ _ = self.render_GET(request) + _check_and_add_cors_preflight_headers(request) request.setHeader("Allow", "OPTIONS, GET, POST") request.setResponseCode(200) request.responseHeaders.removeHeader("Content-Type") @@ -206,6 +207,37 @@ def render_POST(self, request: Request): return self.render_GET(request) +def _check_and_add_cors_preflight_headers(request): + """ + According to https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request, we + should check for `Access-Control-Request-Method` and `Origin` and optionally, + `Access-Control-Request-Headers` headers to determine its a preflight request; and + respond with `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`. + """ + if ( + request.getHeader("Access-Control-Request-Method") is None + or request.getHeader("Origin") is None + ): + return + + acr_headers = request.getHeader("Access-Control-Request-Headers") + if acr_headers is not None: + request.setHeader("Access-Control-Allow-Headers", acr_headers) + + request.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")) + request.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST") + + +# Request +# Access-Control-Request-Method: DELETE +# Access-Control-Request-Headers: origin, x-requested-with +# Origin: https://foo.bar.org + +# Response +# Access-Control-Allow-Origin: https://foo.bar.org +# Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE + + class ChannelHTTP: def __init__( self, diff --git a/frontend/frontend.env.dist b/frontend/frontend.env.dist index 218c11d83..94d0d21b3 100644 --- a/frontend/frontend.env.dist +++ b/frontend/frontend.env.dist @@ -3,9 +3,9 @@ CANARY_DOMAINS=127.0.0.1 CANARY_NXDOMAINS=nx.127.0.0.1 #CANARY_SWITCHBOARD_SETTINGS_PATH= -CANARY_SENTRY_DSN="https://06a5bffddffd4d0f8a9b675ea82a5fb5@o1177763.ingest.sentry.io/6312922" -CANARY_SENTRY_ENVIRONMENT=local -CANARY_SENTRY_ENABLE=False +#CANARY_SENTRY_DSN= +#CANARY_SENTRY_ENVIRONMENT=local +#CANARY_SENTRY_ENABLE=False # template configurations #CANARY_TEMPLATES_PATH= From 85c6613f5afc897b043554f70f07fc81dbbb2155 Mon Sep 17 00:00:00 2001 From: Jason Bissict Date: Tue, 16 Jan 2024 07:30:24 +0200 Subject: [PATCH 2/8] Move check and add to web image handler --- canarytokens/channel_http.py | 32 -------------------------------- canarytokens/tokens.py | 27 ++++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/canarytokens/channel_http.py b/canarytokens/channel_http.py index d704abb3e..5d308e4a1 100644 --- a/canarytokens/channel_http.py +++ b/canarytokens/channel_http.py @@ -135,7 +135,6 @@ def render_OPTIONS(self, request: Request): Alert as if it is a normal GET request, but return the expected content and headers. """ _ = self.render_GET(request) - _check_and_add_cors_preflight_headers(request) request.setHeader("Allow", "OPTIONS, GET, POST") request.setResponseCode(200) request.responseHeaders.removeHeader("Content-Type") @@ -207,37 +206,6 @@ def render_POST(self, request: Request): return self.render_GET(request) -def _check_and_add_cors_preflight_headers(request): - """ - According to https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request, we - should check for `Access-Control-Request-Method` and `Origin` and optionally, - `Access-Control-Request-Headers` headers to determine its a preflight request; and - respond with `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`. - """ - if ( - request.getHeader("Access-Control-Request-Method") is None - or request.getHeader("Origin") is None - ): - return - - acr_headers = request.getHeader("Access-Control-Request-Headers") - if acr_headers is not None: - request.setHeader("Access-Control-Allow-Headers", acr_headers) - - request.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")) - request.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST") - - -# Request -# Access-Control-Request-Method: DELETE -# Access-Control-Request-Headers: origin, x-requested-with -# Origin: https://foo.bar.org - -# Response -# Access-Control-Allow-Origin: https://foo.bar.org -# Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE - - class ChannelHTTP: def __init__( self, diff --git a/canarytokens/tokens.py b/canarytokens/tokens.py index 7bc9c1d08..464a86aa4 100644 --- a/canarytokens/tokens.py +++ b/canarytokens/tokens.py @@ -639,7 +639,7 @@ def _get_response_for_web_image( # If a browser makes cross-origin requests for this img that aren't "simple" it will reject # the image response without this Canarytokens server permitting all cross-origin requests - request.setHeader("Access-Control-Allow-Origin", "*") + _check_and_add_cors_headers(request) if canarydrop.web_image_enabled and canarydrop.web_image_path.exists(): # set response mimetype @@ -753,3 +753,28 @@ def create_token_hit( AnyTokenHit, hit_info, ) + + +def _check_and_add_cors_headers(request): + """ + According to https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request, we + should check for `Access-Control-Request-Method` and `Origin` and optionally, + `Access-Control-Request-Headers` headers to determine its a preflight request; and + respond with `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`. Else, we + will add + """ + if request.method == "GET": + request.setHeader("Access-Control-Allow-Origin", "*") + elif request.method == "OPTIONS": + if ( + request.getHeader("Access-Control-Request-Method") is None + or request.getHeader("Origin") is None + ): + return + + acr_headers = request.getHeader("Access-Control-Request-Headers") + if acr_headers is not None: + request.setHeader("Access-Control-Allow-Headers", acr_headers) + + request.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")) + request.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST") From 628e344d697a64d8374d12d165dba10e051b59fb Mon Sep 17 00:00:00 2001 From: Jason Bissict Date: Tue, 16 Jan 2024 07:46:49 +0200 Subject: [PATCH 3/8] Move check and add to web image handler --- canarytokens/tokens.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/canarytokens/tokens.py b/canarytokens/tokens.py index 464a86aa4..4d2ba0a93 100644 --- a/canarytokens/tokens.py +++ b/canarytokens/tokens.py @@ -763,9 +763,9 @@ def _check_and_add_cors_headers(request): respond with `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`. Else, we will add """ - if request.method == "GET": + if request.method.upper() == "GET": request.setHeader("Access-Control-Allow-Origin", "*") - elif request.method == "OPTIONS": + elif request.method.upper() == "OPTIONS": if ( request.getHeader("Access-Control-Request-Method") is None or request.getHeader("Origin") is None From c5040c9cfa3011143f75f6fe5423bb13efc77fd7 Mon Sep 17 00:00:00 2001 From: Jason Bissict Date: Tue, 16 Jan 2024 10:35:58 +0200 Subject: [PATCH 4/8] Add tests for CORS support --- canarytokens/tokens.py | 30 +------ canarytokens/utils.py | 26 ++++++ tests/integration/test_custom_image.py | 119 ++++++++++++++++++++++++- 3 files changed, 146 insertions(+), 29 deletions(-) diff --git a/canarytokens/tokens.py b/canarytokens/tokens.py index 4d2ba0a93..c38e8d3a5 100644 --- a/canarytokens/tokens.py +++ b/canarytokens/tokens.py @@ -30,6 +30,7 @@ SlackAPITokenHit, TokenTypes, ) +from canarytokens.utils import check_and_add_cors_headers # TODO: put these in a nicer place. Ensure re.compile is called only once at startup # add a naming convention for easy reading when seen in other files. @@ -637,9 +638,7 @@ def _get_response_for_web_image( # render template return template.render(**fortune_template_params).encode() - # If a browser makes cross-origin requests for this img that aren't "simple" it will reject - # the image response without this Canarytokens server permitting all cross-origin requests - _check_and_add_cors_headers(request) + check_and_add_cors_headers(request) if canarydrop.web_image_enabled and canarydrop.web_image_path.exists(): # set response mimetype @@ -753,28 +752,3 @@ def create_token_hit( AnyTokenHit, hit_info, ) - - -def _check_and_add_cors_headers(request): - """ - According to https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request, we - should check for `Access-Control-Request-Method` and `Origin` and optionally, - `Access-Control-Request-Headers` headers to determine its a preflight request; and - respond with `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`. Else, we - will add - """ - if request.method.upper() == "GET": - request.setHeader("Access-Control-Allow-Origin", "*") - elif request.method.upper() == "OPTIONS": - if ( - request.getHeader("Access-Control-Request-Method") is None - or request.getHeader("Origin") is None - ): - return - - acr_headers = request.getHeader("Access-Control-Request-Headers") - if acr_headers is not None: - request.setHeader("Access-Control-Allow-Headers", acr_headers) - - request.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")) - request.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST") diff --git a/canarytokens/utils.py b/canarytokens/utils.py index 3a0a1a2a1..e910f8a52 100644 --- a/canarytokens/utils.py +++ b/canarytokens/utils.py @@ -1,6 +1,32 @@ import subprocess from pathlib import Path from typing import Any, Literal, Union +from twisted.web.http import Request + + +def check_and_add_cors_headers(request: Request): + """ + According to https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request, we + should check for `Access-Control-Request-Method` and `Origin` and optionally, + `Access-Control-Request-Headers` headers in an OPTIONS request to determine its a preflight request; and + respond with `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`. Else, we + will add `Access-Control-Allow-Origin: *` to the GET request. + """ + if request.method.upper() == b"GET": + request.setHeader("Access-Control-Allow-Origin", "*") + elif request.method.upper() == b"OPTIONS": + if ( + request.getHeader("Access-Control-Request-Method") is None + or request.getHeader("Origin") is None + ): + return + + acr_headers = request.getHeader("Access-Control-Request-Headers") + if acr_headers is not None: + request.setHeader("Access-Control-Allow-Headers", acr_headers) + + request.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")) + request.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST") def coerce_to_float(value: Any) -> Union[Literal[False], float]: diff --git a/tests/integration/test_custom_image.py b/tests/integration/test_custom_image.py index 6b2ce5184..db6aee7d9 100644 --- a/tests/integration/test_custom_image.py +++ b/tests/integration/test_custom_image.py @@ -216,7 +216,6 @@ def test_custom_image_web_image( webhook_receiver, runv2, runv3, - # clean_uploads_dir ): run_or_skip(version, runv2=runv2, runv3=runv3) @@ -298,3 +297,121 @@ def test_custom_image_web_image( assert token_hit.geo_info.ip == requests.get("https://ipinfo.io/ip").text else: assert token_hit.geo_info.ip == "127.0.0.1" + + +@pytest.mark.parametrize("version", [v3]) +@pytest.mark.parametrize( + "file_name", ["canary_image.png"] # , "Moon.jpg", "testing.gif"], +) +@pytest.mark.parametrize( + "request_details", + [ + { + "method": "GET", + "req_headers": {}, + "resp_headers": {"Access-Control-Allow-Origin": "*"}, + }, + { + "method": "OPTIONS", + "req_headers": { + "Access-Control-Request-Method": "GET", + "Origin": "test.com", + }, + "resp_headers": { + "Access-Control-Allow-Methods": "OPTIONS, GET, POST", + "Access-Control-Allow-Origin": "test.com", + }, + }, + ], + ids=["Get-Request-Cors-Support", "Preflight-Cors-Support"], +) +def test_custom_image_web_image_cors_support( + version, file_name, webhook_receiver, runv2, runv3, request_details +): + run_or_skip(version, runv2=runv2, runv3=runv3) + + file_mimetype = "image/{mimetype}".format( + mimetype=file_name[-3:].replace("jpg", "jpeg") + ) + with open("data/{file}".format(file=file_name), "rb") as fp: + # record contents + input_file = fp.read() + + # create SpooledTemporaryFile + temp_file = SpooledTemporaryFile() + temp_file.write(input_file) + temp_file.seek(0) + # initialize request + web_image = UploadedImage( + filename=file_name, content_type=file_mimetype, file=temp_file + ) + memo = "custom web token memo!" + token_request = CustomImageTokenRequest( + token_type=TokenTypes.WEB_IMAGE, + web_image=web_image, + webhook_url=webhook_receiver, + memo=Memo(memo), + ) + + # Create custom image token + resp = create_token(token_request=token_request, version=version) + token_info = CustomImageTokenResponse(**resp) + + # ensure web_image is enabled + _res = set_token_settings( + setting=WebImageSettingsRequest( + value="on", + token=token_info.token, + auth=token_info.auth_token, + ), + version=version, + ) + # check success of the web_image settings update + if isinstance(version, V2): + assert _res["result"] == "success" + elif isinstance(version, V3): + assert _res["message"] == "success" + + # Trigger the token + trigger_headers = { + "Referrer-Policy": "strict-origin-when-cross-origin", + "Accept": "{mimetype}".format( + mimetype=file_mimetype, + ), + } + trigger_headers.update(request_details["req_headers"]) + + _resp = trigger_http_token( + token_info=token_info, + version=version, + headers=trigger_headers, + stream=True, + method=request_details["method"], + ) + for header, value in request_details["resp_headers"].items(): + assert header in _resp.headers + assert value in _resp.headers[header] + # import pdb; pdb.set_trace() + # extract incoming file's bytes + # incoming_file = _resp.content + + # # compare bytes between files + # assert input_file == incoming_file + + # # check the memo + # stats = get_stats_from_webhook(webhook_receiver, token=token_info.token) + # if stats: + # assert len(stats) == 1 + # assert stats[0]["memo"] == memo + # _ = TokenAlertDetailGeneric(**stats[0]) + + # # Check that the returned history has a single hit, and is on the HTTP channel + # resp = get_token_history(token_info=token_info, version=version) + # token_history = CustomImageTokenHistory(**resp) + # assert len(token_history.hits) == 1 + # token_hit = token_history.hits[0] + # assert token_hit.input_channel == "HTTP" + # if version.live: + # assert token_hit.geo_info.ip == requests.get("https://ipinfo.io/ip").text + # else: + # assert token_hit.geo_info.ip == "127.0.0.1" From 243acd972bfdc8d21046a4f235c17a9e5d109f3e Mon Sep 17 00:00:00 2001 From: Jason Bissict Date: Tue, 16 Jan 2024 10:37:17 +0200 Subject: [PATCH 5/8] Clean up commented code --- tests/integration/test_custom_image.py | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/tests/integration/test_custom_image.py b/tests/integration/test_custom_image.py index db6aee7d9..438cf9b5c 100644 --- a/tests/integration/test_custom_image.py +++ b/tests/integration/test_custom_image.py @@ -391,27 +391,3 @@ def test_custom_image_web_image_cors_support( for header, value in request_details["resp_headers"].items(): assert header in _resp.headers assert value in _resp.headers[header] - # import pdb; pdb.set_trace() - # extract incoming file's bytes - # incoming_file = _resp.content - - # # compare bytes between files - # assert input_file == incoming_file - - # # check the memo - # stats = get_stats_from_webhook(webhook_receiver, token=token_info.token) - # if stats: - # assert len(stats) == 1 - # assert stats[0]["memo"] == memo - # _ = TokenAlertDetailGeneric(**stats[0]) - - # # Check that the returned history has a single hit, and is on the HTTP channel - # resp = get_token_history(token_info=token_info, version=version) - # token_history = CustomImageTokenHistory(**resp) - # assert len(token_history.hits) == 1 - # token_hit = token_history.hits[0] - # assert token_hit.input_channel == "HTTP" - # if version.live: - # assert token_hit.geo_info.ip == requests.get("https://ipinfo.io/ip").text - # else: - # assert token_hit.geo_info.ip == "127.0.0.1" From 3543ede92b37611903a4d1fab331e74e17449f36 Mon Sep 17 00:00:00 2001 From: Jason Bissict Date: Tue, 16 Jan 2024 13:28:10 +0200 Subject: [PATCH 6/8] Fix tests --- canarytokens/tokens.py | 28 ++++++++- canarytokens/utils.py | 26 -------- tests/integration/test_custom_image.py | 86 +++++++++++++++++++------- tests/units/test_utils.py | 5 +- 4 files changed, 93 insertions(+), 52 deletions(-) diff --git a/canarytokens/tokens.py b/canarytokens/tokens.py index c38e8d3a5..396209924 100644 --- a/canarytokens/tokens.py +++ b/canarytokens/tokens.py @@ -30,7 +30,6 @@ SlackAPITokenHit, TokenTypes, ) -from canarytokens.utils import check_and_add_cors_headers # TODO: put these in a nicer place. Ensure re.compile is called only once at startup # add a naming convention for easy reading when seen in other files. @@ -638,7 +637,7 @@ def _get_response_for_web_image( # render template return template.render(**fortune_template_params).encode() - check_and_add_cors_headers(request) + _check_and_add_cors_headers(request) if canarydrop.web_image_enabled and canarydrop.web_image_path.exists(): # set response mimetype @@ -752,3 +751,28 @@ def create_token_hit( AnyTokenHit, hit_info, ) + + +def _check_and_add_cors_headers(request: Request): + """ + According to https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request, we + should check for `Access-Control-Request-Method` and `Origin` and optionally, + `Access-Control-Request-Headers` headers in an OPTIONS request to determine its a preflight request; and + respond with `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`. Else, we + will add `Access-Control-Allow-Origin: *` to the GET request. + """ + if request.method.upper() == b"GET": + request.setHeader("Access-Control-Allow-Origin", "*") + elif request.method.upper() == b"OPTIONS": + if ( + request.getHeader("Access-Control-Request-Method") is None + or request.getHeader("Origin") is None + ): + return + + acr_headers = request.getHeader("Access-Control-Request-Headers") + if acr_headers is not None: + request.setHeader("Access-Control-Allow-Headers", acr_headers) + + request.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")) + request.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST") diff --git a/canarytokens/utils.py b/canarytokens/utils.py index e910f8a52..3a0a1a2a1 100644 --- a/canarytokens/utils.py +++ b/canarytokens/utils.py @@ -1,32 +1,6 @@ import subprocess from pathlib import Path from typing import Any, Literal, Union -from twisted.web.http import Request - - -def check_and_add_cors_headers(request: Request): - """ - According to https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request, we - should check for `Access-Control-Request-Method` and `Origin` and optionally, - `Access-Control-Request-Headers` headers in an OPTIONS request to determine its a preflight request; and - respond with `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`. Else, we - will add `Access-Control-Allow-Origin: *` to the GET request. - """ - if request.method.upper() == b"GET": - request.setHeader("Access-Control-Allow-Origin", "*") - elif request.method.upper() == b"OPTIONS": - if ( - request.getHeader("Access-Control-Request-Method") is None - or request.getHeader("Origin") is None - ): - return - - acr_headers = request.getHeader("Access-Control-Request-Headers") - if acr_headers is not None: - request.setHeader("Access-Control-Allow-Headers", acr_headers) - - request.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")) - request.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST") def coerce_to_float(value: Any) -> Union[Literal[False], float]: diff --git a/tests/integration/test_custom_image.py b/tests/integration/test_custom_image.py index 438cf9b5c..96fe7e955 100644 --- a/tests/integration/test_custom_image.py +++ b/tests/integration/test_custom_image.py @@ -301,35 +301,72 @@ def test_custom_image_web_image( @pytest.mark.parametrize("version", [v3]) @pytest.mark.parametrize( - "file_name", ["canary_image.png"] # , "Moon.jpg", "testing.gif"], -) -@pytest.mark.parametrize( - "request_details", + "request_details, resp_details", [ - { - "method": "GET", - "req_headers": {}, - "resp_headers": {"Access-Control-Allow-Origin": "*"}, - }, - { - "method": "OPTIONS", - "req_headers": { - "Access-Control-Request-Method": "GET", - "Origin": "test.com", + pytest.param( + {"method": "GET", "headers": {}}, + {"headers": {"Access-Control-Allow-Origin": "*"}, "not_headers": []}, + id="Get-Request-Cors-Support", + ), + pytest.param( + { + "method": "OPTIONS", + "headers": { + "Access-Control-Request-Method": "GET", + "Origin": "test.com", + }, }, - "resp_headers": { - "Access-Control-Allow-Methods": "OPTIONS, GET, POST", - "Access-Control-Allow-Origin": "test.com", + { + "headers": { + "Access-Control-Allow-Methods": "OPTIONS, GET, POST", + "Access-Control-Allow-Origin": "test.com", + }, + "not_headers": ["Access-Control-Request-Method"], }, - }, + id="Preflight-Cors-Support", + ), + pytest.param( + { + "method": "OPTIONS", + "headers": { + "Origin": "test.com", + }, + }, + { + "headers": {}, + "not_headers": [ + "Access-Control-Allow-Methods", + "Access-Control-Allow-Origin", + ], + }, + id="Bad-Preflight-Cors-Request", + ), + pytest.param( + { + "method": "GET", + "headers": { + "Access-Control-Request-Method": "GET", + "Origin": "test.com", + }, + }, + { + "headers": { + "Access-Control-Allow-Origin": "*", + }, + "not_headers": [ + "Access-Control-Request-Method", + "Access-Control-Allow-Methods", + ], + }, + id="Get-with-Preflight-Cors-Headers", + ), ], - ids=["Get-Request-Cors-Support", "Preflight-Cors-Support"], ) def test_custom_image_web_image_cors_support( - version, file_name, webhook_receiver, runv2, runv3, request_details + version, webhook_receiver, runv2, runv3, request_details, resp_details ): run_or_skip(version, runv2=runv2, runv3=runv3) - + file_name = "canary_image.png" file_mimetype = "image/{mimetype}".format( mimetype=file_name[-3:].replace("jpg", "jpeg") ) @@ -379,7 +416,7 @@ def test_custom_image_web_image_cors_support( mimetype=file_mimetype, ), } - trigger_headers.update(request_details["req_headers"]) + trigger_headers.update(request_details["headers"]) _resp = trigger_http_token( token_info=token_info, @@ -388,6 +425,9 @@ def test_custom_image_web_image_cors_support( stream=True, method=request_details["method"], ) - for header, value in request_details["resp_headers"].items(): + for header, value in resp_details["headers"].items(): assert header in _resp.headers assert value in _resp.headers[header] + + for header in resp_details["not_headers"]: + assert header not in _resp.headers diff --git a/tests/units/test_utils.py b/tests/units/test_utils.py index 439ed46b1..54e43df42 100644 --- a/tests/units/test_utils.py +++ b/tests/units/test_utils.py @@ -1,4 +1,7 @@ -from canarytokens.utils import coerce_to_float, get_deployed_commit_sha +from canarytokens.utils import ( + coerce_to_float, + get_deployed_commit_sha, +) def test_get_deployed_commit_sha(tmpdir): From 494a36dc7a03c34f1e62cd640c8be1b816c91987 Mon Sep 17 00:00:00 2001 From: Jason Bissict Date: Tue, 16 Jan 2024 14:22:11 +0200 Subject: [PATCH 7/8] bump aws configure gh action --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9b4a2cc05..95ecb8396 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,7 +50,7 @@ jobs: steps: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 + uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::164951611079:role/Canarytokens-staging-github-action role-session-name: GitHubActions-${{ github.actor }}-${{ github.workflow }}-${{ github.run_id }}-${{ github.run_number }} From b4c9b8fd7fc1c1a884baad74b41142903e5f8273 Mon Sep 17 00:00:00 2001 From: Jason Bissict Date: Tue, 16 Jan 2024 21:18:04 +0200 Subject: [PATCH 8/8] New awsid dev account --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 95ecb8396..bcb86a2e6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,7 +52,7 @@ jobs: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: - role-to-assume: arn:aws:iam::164951611079:role/Canarytokens-staging-github-action + role-to-assume: arn:aws:iam::211125554061:role/Canarytokens-staging-github-action role-session-name: GitHubActions-${{ github.actor }}-${{ github.workflow }}-${{ github.run_id }}-${{ github.run_number }} aws-region: ${{ env.AWS_REGION }} - uses: actions/checkout@v3