import re import boto3 import pytest import yaml from botocore.exceptions import ClientError from moto import mock_ssm from .test_ssm_docs import _get_yaml_template @mock_ssm def test_describe_document_permissions_unknown_document(): client = boto3.client("ssm", region_name="us-east-1") with pytest.raises(ClientError) as ex: client.describe_document_permission( Name="UnknownDocument", PermissionType="Share" ) err = ex.value.response["Error"] assert err["Code"] == "InvalidDocument" assert err["Message"] == "The specified document does not exist." def get_client(): template_file = _get_yaml_template() json_doc = yaml.safe_load(template_file) client = boto3.client("ssm", region_name="us-east-1") client.create_document( Content=yaml.dump(json_doc), Name="TestDocument", DocumentType="Command", DocumentFormat="YAML", VersionName="Base", ) return client @mock_ssm def test_describe_document_permissions_initial(): client = get_client() res = client.describe_document_permission( Name="TestDocument", PermissionType="Share" ) assert res["AccountIds"] == [] assert res["AccountSharingInfoList"] == [] @pytest.mark.parametrize( "ids", [["111111111111"], ["all"], ["All"], ["111111111111", "222222222222"]], ids=["one_value", "all", "All", "multiple_values"], ) @mock_ssm def test_modify_document_permission_add_account_id(ids): client = get_client() client.modify_document_permission( Name="TestDocument", PermissionType="Share", AccountIdsToAdd=ids ) res = client.describe_document_permission( Name="TestDocument", PermissionType="Share" ) assert "AccountIds" in res assert set(res["AccountIds"]) == set(ids) assert len(res["AccountSharingInfoList"]) == len(ids) expected_account_sharing = [ {"AccountId": _id, "SharedDocumentVersion": "$DEFAULT"} for _id in ids ] assert res["AccountSharingInfoList"] == expected_account_sharing @pytest.mark.parametrize( "initial,to_remove", [ (["all"], ["all"]), (["111111111111"], ["111111111111"]), (["111111111111", "222222222222"], ["222222222222"]), ( ["111111111111", "222222222222", "333333333333"], ["111111111111", "333333333333"], ), ], ids=["all", "one_value", "multiple_initials", "multiple_to_remove"], ) @mock_ssm def test_modify_document_permission_remove_account_id(initial, to_remove): client = get_client() client.modify_document_permission( Name="TestDocument", PermissionType="Share", AccountIdsToAdd=initial ) client.modify_document_permission( Name="TestDocument", PermissionType="Share", AccountIdsToRemove=to_remove ) res = client.describe_document_permission( Name="TestDocument", PermissionType="Share" ) assert "AccountIds" in res expected_new_list = {x for x in initial if x not in to_remove} assert set(res["AccountIds"]) == expected_new_list expected_account_sharing = [ {"AccountId": _id, "SharedDocumentVersion": "$DEFAULT"} for _id in expected_new_list ] assert res["AccountSharingInfoList"] == expected_account_sharing @mock_ssm def test_fail_modify_document_permission_wrong_permission_type(): client = get_client() with pytest.raises(ClientError) as ex: client.modify_document_permission( Name="TestDocument", PermissionType="WrongValue", AccountIdsToAdd=[] ) err = ex.value.response["Error"] assert err["Code"] == "InvalidPermissionType" assert re.search(r"Member must satisfy enum value set: \[Share\]", err["Message"]) @mock_ssm def test_fail_modify_document_permission_wrong_document_version(): client = get_client() with pytest.raises(ClientError) as ex: client.modify_document_permission( Name="TestDocument", PermissionType="Share", SharedDocumentVersion="unknown", AccountIdsToAdd=[], ) err = ex.value.response["Error"] assert err["Code"] == "ValidationException" assert re.search(r"Member must satisfy regular expression pattern", err["Message"]) @pytest.mark.parametrize( "value", [["alll"], ["1234"], ["1234123412341234"], ["account_id"]], ids=["all?", "too_short", "too_long", "no-digits"], ) @mock_ssm def test_fail_modify_document_permission_add_invalid_account_ids(value): client = get_client() with pytest.raises(ClientError) as ex: client.modify_document_permission( Name="TestDocument", PermissionType="Share", AccountIdsToAdd=value ) err = ex.value.response["Error"] assert err["Code"] == "ValidationException" assert re.search(r"Member must satisfy regular expression pattern:", err["Message"]) @pytest.mark.parametrize( "value", [["alll"], ["1234"], ["1234123412341234"], ["account_id"]], ids=["all?", "too_short", "too_long", "no-digits"], ) @mock_ssm def test_fail_modify_document_permission_remove_invalid_account_ids(value): client = get_client() with pytest.raises(ClientError) as ex: client.modify_document_permission( Name="TestDocument", PermissionType="Share", AccountIdsToRemove=value ) err = ex.value.response["Error"] assert err["Code"] == "ValidationException" assert re.search(r"Member must satisfy regular expression pattern:", err["Message"]) @mock_ssm def test_fail_modify_document_permission_add_all_and_specific(): client = get_client() with pytest.raises(ClientError) as ex: client.modify_document_permission( Name="TestDocument", PermissionType="Share", AccountIdsToAdd=["all", "123412341234"], ) err = ex.value.response["Error"] assert err["Code"] == "DocumentPermissionLimit" assert err["Message"] == "Accounts can either be all or a group of AWS accounts" @mock_ssm def test_fail_modify_document_permission_remove_all_and_specific(): client = get_client() with pytest.raises(ClientError) as ex: client.modify_document_permission( Name="TestDocument", PermissionType="Share", AccountIdsToRemove=["all", "123412341234"], ) err = ex.value.response["Error"] assert err["Code"] == "DocumentPermissionLimit" assert err["Message"] == "Accounts can either be all or a group of AWS accounts"