moto/tests/test_ram/test_ram.py
2024-01-27 19:38:09 +00:00

380 lines
12 KiB
Python

import re
import time
from datetime import datetime
import boto3
import pytest
from botocore.exceptions import ClientError
from moto import mock_aws
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
@mock_aws
def test_create_resource_share():
# given
client = boto3.client("ram", region_name="us-east-1")
# when
response = client.create_resource_share(name="test")
# then
resource = response["resourceShare"]
assert resource["allowExternalPrincipals"] is True
assert isinstance(resource["creationTime"], datetime)
assert isinstance(resource["lastUpdatedTime"], datetime)
assert resource["name"] == "test"
assert resource["owningAccountId"] == ACCOUNT_ID
assert re.match(
(
r"arn:aws:ram:us-east-1:\d{12}:resource-share"
r"/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
),
resource["resourceShareArn"],
)
assert resource["status"] == "ACTIVE"
assert "featureSet" not in resource
# creating a resource share with the name should result in a second one
# not overwrite/update the old one
# when
response = client.create_resource_share(
name="test",
allowExternalPrincipals=False,
resourceArns=[
f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
],
)
# then
resource = response["resourceShare"]
assert resource["allowExternalPrincipals"] is False
assert isinstance(resource["creationTime"], datetime)
assert isinstance(resource["lastUpdatedTime"], datetime)
assert resource["name"] == "test"
assert resource["owningAccountId"] == ACCOUNT_ID
assert re.match(
(
r"arn:aws:ram:us-east-1:\d{12}:resource-share"
r"/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
),
resource["resourceShareArn"],
)
assert resource["status"] == "ACTIVE"
response = client.get_resource_shares(resourceOwner="SELF")
assert len(response["resourceShares"]) == 2
@mock_aws
def test_create_resource_share_errors():
# given
client = boto3.client("ram", region_name="us-east-1")
# invalid ARN
# when
with pytest.raises(ClientError) as e:
client.create_resource_share(name="test", resourceArns=["inalid-arn"])
ex = e.value
assert ex.operation_name == "CreateResourceShare"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "MalformedArnException" in ex.response["Error"]["Code"]
assert ex.response["Error"]["Message"] == (
"The specified resource ARN inalid-arn is not valid. "
"Verify the ARN and try again."
)
# valid ARN, but not shareable resource type
# when
with pytest.raises(ClientError) as e:
client.create_resource_share(
name="test", resourceArns=[f"arn:aws:iam::{ACCOUNT_ID}:role/test"]
)
ex = e.value
assert ex.operation_name == "CreateResourceShare"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "MalformedArnException" in ex.response["Error"]["Code"]
assert (
ex.response["Error"]["Message"]
== "You cannot share the selected resource type."
)
# invalid principal ID
# when
with pytest.raises(ClientError) as e:
client.create_resource_share(
name="test",
principals=["invalid"],
resourceArns=[
f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
],
)
ex = e.value
assert ex.operation_name == "CreateResourceShare"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "InvalidParameterException" in ex.response["Error"]["Code"]
assert ex.response["Error"]["Message"] == (
"Principal ID invalid is malformed. Verify the ID and try again."
)
@mock_aws
def test_create_resource_share_with_organization():
# given
client = boto3.client("organizations", region_name="us-east-1")
org_arn = client.create_organization(FeatureSet="ALL")["Organization"]["Arn"]
root_id = client.list_roots()["Roots"][0]["Id"]
ou_arn = client.create_organizational_unit(ParentId=root_id, Name="test")[
"OrganizationalUnit"
]["Arn"]
client = boto3.client("ram", region_name="us-east-1")
# share in whole Organization
# when
response = client.create_resource_share(
name="test",
principals=[org_arn],
resourceArns=[
f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
],
)
# then
assert response["resourceShare"]["name"] == "test"
# share in an OU
# when
response = client.create_resource_share(
name="test",
principals=[ou_arn],
resourceArns=[
f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
],
)
# then
assert response["resourceShare"]["name"] == "test"
@mock_aws
def test_create_resource_share_with_organization_errors():
# given
client = boto3.client("organizations", region_name="us-east-1")
client.create_organization(FeatureSet="ALL")
root_id = client.list_roots()["Roots"][0]["Id"]
client.create_organizational_unit(ParentId=root_id, Name="test")
client = boto3.client("ram", region_name="us-east-1")
# unknown Organization
# when
with pytest.raises(ClientError) as e:
client.create_resource_share(
name="test",
principals=[f"arn:aws:organizations::{ACCOUNT_ID}:organization/o-unknown"],
resourceArns=[
f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
],
)
ex = e.value
assert ex.operation_name == "CreateResourceShare"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "UnknownResourceException" in ex.response["Error"]["Code"]
assert ex.response["Error"]["Message"] == (
"Organization o-unknown could not be found."
)
# unknown OU
# when
with pytest.raises(ClientError) as e:
client.create_resource_share(
name="test",
principals=[f"arn:aws:organizations::{ACCOUNT_ID}:ou/o-unknown/ou-unknown"],
resourceArns=[
f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
],
)
ex = e.value
assert ex.operation_name == "CreateResourceShare"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "UnknownResourceException" in ex.response["Error"]["Code"]
assert ex.response["Error"]["Message"] == (
"OrganizationalUnit ou-unknown in unknown organization could not be found."
)
@mock_aws
def test_get_resource_shares():
# given
client = boto3.client("ram", region_name="us-east-1")
client.create_resource_share(name="test")
# when
response = client.get_resource_shares(resourceOwner="SELF")
# then
assert len(response["resourceShares"]) == 1
resource = response["resourceShares"][0]
assert resource["allowExternalPrincipals"] is True
assert isinstance(resource["creationTime"], datetime)
assert resource["featureSet"] == "STANDARD"
assert isinstance(resource["lastUpdatedTime"], datetime)
assert resource["name"] == "test"
assert resource["owningAccountId"] == ACCOUNT_ID
assert re.match(
(
r"arn:aws:ram:us-east-1:\d{12}:resource-share"
r"/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
),
resource["resourceShareArn"],
)
assert resource["status"] == "ACTIVE"
@mock_aws
def test_get_resource_shares_errors():
# given
client = boto3.client("ram", region_name="us-east-1")
# invalid resource owner
# when
with pytest.raises(ClientError) as e:
client.get_resource_shares(resourceOwner="invalid")
ex = e.value
assert ex.operation_name == "GetResourceShares"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "InvalidParameterException" in ex.response["Error"]["Code"]
assert ex.response["Error"]["Message"] == (
"invalid is not a valid resource owner. "
"Specify either SELF or OTHER-ACCOUNTS and try again."
)
@mock_aws
def test_update_resource_share():
# given
client = boto3.client("ram", region_name="us-east-1")
arn = client.create_resource_share(name="test")["resourceShare"]["resourceShareArn"]
# when
time.sleep(0.1)
response = client.update_resource_share(resourceShareArn=arn, name="test-update")
# then
resource = response["resourceShare"]
assert resource["allowExternalPrincipals"] is True
assert resource["name"] == "test-update"
assert resource["owningAccountId"] == ACCOUNT_ID
assert re.match(
(
r"arn:aws:ram:us-east-1:\d{12}:resource-share"
r"/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
),
resource["resourceShareArn"],
)
assert resource["status"] == "ACTIVE"
assert "featureSet" not in resource
creation_time = resource["creationTime"]
assert resource["lastUpdatedTime"] > creation_time
response = client.get_resource_shares(resourceOwner="SELF")
assert len(response["resourceShares"]) == 1
@mock_aws
def test_update_resource_share_errors():
# given
client = boto3.client("ram", region_name="us-east-1")
# invalid resource owner
# when
with pytest.raises(ClientError) as e:
client.update_resource_share(
resourceShareArn=f"arn:aws:ram:us-east-1:{ACCOUNT_ID}:resource-share/not-existing",
name="test-update",
)
ex = e.value
assert ex.operation_name == "UpdateResourceShare"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "UnknownResourceException" in ex.response["Error"]["Code"]
assert ex.response["Error"]["Message"] == (
f"ResourceShare arn:aws:ram:us-east-1:{ACCOUNT_ID}"
":resource-share/not-existing could not be found."
)
@mock_aws
def test_delete_resource_share():
# given
client = boto3.client("ram", region_name="us-east-1")
arn = client.create_resource_share(name="test")["resourceShare"]["resourceShareArn"]
# when
time.sleep(0.1)
response = client.delete_resource_share(resourceShareArn=arn)
# then
assert response["returnValue"] is True
response = client.get_resource_shares(resourceOwner="SELF")
assert len(response["resourceShares"]) == 1
resource = response["resourceShares"][0]
assert resource["status"] == "DELETED"
creation_time = resource["creationTime"]
assert resource["lastUpdatedTime"] > creation_time
@mock_aws
def test_delete_resource_share_errors():
# given
client = boto3.client("ram", region_name="us-east-1")
# invalid resource owner
# when
with pytest.raises(ClientError) as e:
client.delete_resource_share(
resourceShareArn=f"arn:aws:ram:us-east-1:{ACCOUNT_ID}:resource-share/not-existing"
)
ex = e.value
assert ex.operation_name == "DeleteResourceShare"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "UnknownResourceException" in ex.response["Error"]["Code"]
assert ex.response["Error"]["Message"] == (
f"ResourceShare arn:aws:ram:us-east-1:{ACCOUNT_ID}"
":resource-share/not-existing could not be found."
)
@mock_aws
def test_enable_sharing_with_aws_organization():
# given
client = boto3.client("organizations", region_name="us-east-1")
client.create_organization(FeatureSet="ALL")
client = boto3.client("ram", region_name="us-east-1")
# when
response = client.enable_sharing_with_aws_organization()
# then
assert response["returnValue"] is True
@mock_aws
def test_enable_sharing_with_aws_organization_errors():
# given
client = boto3.client("ram", region_name="us-east-1")
# no Organization defined
# when
with pytest.raises(ClientError) as e:
client.enable_sharing_with_aws_organization()
ex = e.value
assert ex.operation_name == "EnableSharingWithAwsOrganization"
assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "OperationNotPermittedException" in ex.response["Error"]["Code"]
assert ex.response["Error"]["Message"] == (
"Unable to enable sharing with AWS Organizations. "
"Received AccessDeniedException from AWSOrganizations with the "
"following error message: "
"You don't have permissions to access this resource."
)