2020-09-28 06:16:06 +00:00
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
import pytest
|
2020-09-28 06:16:06 +00:00
|
|
|
|
|
|
|
import boto3
|
|
|
|
|
2021-01-31 12:21:24 +00:00
|
|
|
from botocore.exceptions import ClientError
|
2020-09-28 06:16:06 +00:00
|
|
|
from botocore.parsers import ResponseParserError
|
|
|
|
import sure # noqa
|
|
|
|
|
|
|
|
from moto import (
|
|
|
|
settings,
|
|
|
|
mock_ec2,
|
|
|
|
mock_s3,
|
|
|
|
mock_logs,
|
|
|
|
)
|
|
|
|
from moto.core import ACCOUNT_ID
|
|
|
|
from moto.ec2.exceptions import FilterNotImplementedError
|
|
|
|
|
|
|
|
|
|
|
|
@mock_s3
|
|
|
|
@mock_ec2
|
|
|
|
def test_create_flow_logs_s3():
|
|
|
|
s3 = boto3.resource("s3", region_name="us-west-1")
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
|
|
|
|
bucket = s3.create_bucket(
|
|
|
|
Bucket="test-flow-logs",
|
|
|
|
CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
|
|
|
|
)
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket.name,
|
|
|
|
DryRun=True,
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
|
2021-09-07 16:10:01 +00:00
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"An error occurred (DryRunOperation) when calling the CreateFlowLogs operation: Request would have succeeded, but DryRun flag is set"
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket.name,
|
|
|
|
)["FlowLogIds"]
|
|
|
|
response.should.have.length_of(1)
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(1)
|
|
|
|
|
|
|
|
flow_log = flow_logs[0]
|
|
|
|
|
|
|
|
flow_log["FlowLogId"].should.equal(response[0])
|
|
|
|
flow_log["DeliverLogsStatus"].should.equal("SUCCESS")
|
|
|
|
flow_log["FlowLogStatus"].should.equal("ACTIVE")
|
|
|
|
flow_log["ResourceId"].should.equal(vpc["VpcId"])
|
|
|
|
flow_log["TrafficType"].should.equal("ALL")
|
|
|
|
flow_log["LogDestinationType"].should.equal("s3")
|
|
|
|
flow_log["LogDestination"].should.equal("arn:aws:s3:::" + bucket.name)
|
|
|
|
flow_log["LogFormat"].should.equal(
|
|
|
|
"${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}"
|
|
|
|
)
|
|
|
|
flow_log["MaxAggregationInterval"].should.equal(600)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_logs
|
|
|
|
@mock_ec2
|
|
|
|
def test_create_flow_logs_cloud_watch():
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
logs_client = boto3.client("logs", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
logs_client.create_log_group(logGroupName="test-group")
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="cloud-watch-logs",
|
|
|
|
LogGroupName="test-group",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
|
|
|
|
DryRun=True,
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
|
2021-09-07 16:10:01 +00:00
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"An error occurred (DryRunOperation) when calling the CreateFlowLogs operation: Request would have succeeded, but DryRun flag is set"
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="cloud-watch-logs",
|
|
|
|
LogGroupName="test-group",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
|
|
|
|
)["FlowLogIds"]
|
|
|
|
response.should.have.length_of(1)
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(1)
|
|
|
|
|
|
|
|
flow_log = flow_logs[0]
|
|
|
|
|
|
|
|
flow_log["FlowLogId"].should.equal(response[0])
|
|
|
|
flow_log["DeliverLogsStatus"].should.equal("SUCCESS")
|
|
|
|
flow_log["FlowLogStatus"].should.equal("ACTIVE")
|
|
|
|
flow_log["ResourceId"].should.equal(vpc["VpcId"])
|
|
|
|
flow_log["TrafficType"].should.equal("ALL")
|
|
|
|
flow_log["LogDestinationType"].should.equal("cloud-watch-logs")
|
|
|
|
flow_log["LogGroupName"].should.equal("test-group")
|
|
|
|
flow_log["DeliverLogsPermissionArn"].should.equal(
|
|
|
|
"arn:aws:iam::" + ACCOUNT_ID + ":role/test-role"
|
|
|
|
)
|
|
|
|
flow_log["LogFormat"].should.equal(
|
|
|
|
"${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}"
|
|
|
|
)
|
|
|
|
flow_log["MaxAggregationInterval"].should.equal(600)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_s3
|
|
|
|
@mock_ec2
|
|
|
|
def test_create_flow_log_create():
|
|
|
|
s3 = boto3.resource("s3", region_name="us-west-1")
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc1 = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
|
|
|
|
|
|
|
|
bucket = s3.create_bucket(
|
|
|
|
Bucket="test-flow-logs",
|
2020-11-11 15:55:37 +00:00
|
|
|
CreateBucketConfiguration={"LocationConstraint": "us-west-1",},
|
2020-09-28 06:16:06 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
response = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc1["VpcId"], vpc2["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket.name,
|
|
|
|
LogFormat="${version} ${vpc-id} ${subnet-id} ${instance-id} ${interface-id} ${account-id} ${type} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${pkt-srcaddr} ${pkt-dstaddr} ${protocol} ${bytes} ${packets} ${start} ${end} ${action} ${tcp-flags} ${log-status}",
|
|
|
|
)["FlowLogIds"]
|
|
|
|
response.should.have.length_of(2)
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(2)
|
|
|
|
|
|
|
|
flow_logs[0]["LogFormat"].should.equal(
|
|
|
|
"${version} ${vpc-id} ${subnet-id} ${instance-id} ${interface-id} ${account-id} ${type} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${pkt-srcaddr} ${pkt-dstaddr} ${protocol} ${bytes} ${packets} ${start} ${end} ${action} ${tcp-flags} ${log-status}"
|
|
|
|
)
|
|
|
|
flow_logs[1]["LogFormat"].should.equal(
|
|
|
|
"${version} ${vpc-id} ${subnet-id} ${instance-id} ${interface-id} ${account-id} ${type} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${pkt-srcaddr} ${pkt-dstaddr} ${protocol} ${bytes} ${packets} ${start} ${end} ${action} ${tcp-flags} ${log-status}"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_s3
|
|
|
|
@mock_ec2
|
|
|
|
def test_delete_flow_logs():
|
|
|
|
s3 = boto3.resource("s3", region_name="us-west-1")
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc1 = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
|
|
|
|
|
|
|
|
bucket = s3.create_bucket(
|
|
|
|
Bucket="test-flow-logs",
|
|
|
|
CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc1["VpcId"], vpc2["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket.name,
|
|
|
|
)["FlowLogIds"]
|
|
|
|
response.should.have.length_of(2)
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(2)
|
|
|
|
|
|
|
|
client.delete_flow_logs(FlowLogIds=[response[0]])
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(1)
|
|
|
|
flow_logs[0]["FlowLogId"].should.equal(response[1])
|
|
|
|
|
|
|
|
client.delete_flow_logs(FlowLogIds=[response[1]])
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(0)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_s3
|
|
|
|
@mock_ec2
|
|
|
|
def test_delete_flow_logs_delete_many():
|
|
|
|
s3 = boto3.resource("s3", region_name="us-west-1")
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc1 = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
|
|
|
|
|
|
|
|
bucket = s3.create_bucket(
|
|
|
|
Bucket="test-flow-logs",
|
|
|
|
CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc1["VpcId"], vpc2["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket.name,
|
|
|
|
)["FlowLogIds"]
|
|
|
|
response.should.have.length_of(2)
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(2)
|
|
|
|
|
|
|
|
client.delete_flow_logs(FlowLogIds=response)
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(0)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_delete_flow_logs_non_existing():
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.delete_flow_logs(FlowLogIds=["fl-1a2b3c4d"])
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("InvalidFlowLogId.NotFound")
|
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"These flow log ids in the input list are not found: [TotalCount: 1] fl-1a2b3c4d"
|
|
|
|
)
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.delete_flow_logs(FlowLogIds=["fl-1a2b3c4d", "fl-2b3c4d5e"])
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("InvalidFlowLogId.NotFound")
|
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"These flow log ids in the input list are not found: [TotalCount: 2] fl-1a2b3c4d fl-2b3c4d5e"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_create_flow_logs_unsuccessful():
|
|
|
|
s3 = boto3.resource("s3", region_name="us-west-1")
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc1 = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
|
|
|
|
|
|
|
|
response = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc1["VpcId"], vpc2["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::non-existing-bucket",
|
|
|
|
)
|
|
|
|
response["FlowLogIds"].should.have.length_of(0)
|
|
|
|
response["Unsuccessful"].should.have.length_of(2)
|
|
|
|
|
|
|
|
error1 = response["Unsuccessful"][0]["Error"]
|
|
|
|
error2 = response["Unsuccessful"][1]["Error"]
|
|
|
|
|
|
|
|
error1["Code"].should.equal("400")
|
|
|
|
error1["Message"].should.equal(
|
|
|
|
"LogDestination: non-existing-bucket does not exist."
|
|
|
|
)
|
|
|
|
error2["Code"].should.equal("400")
|
|
|
|
error2["Message"].should.equal(
|
|
|
|
"LogDestination: non-existing-bucket does not exist."
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_s3
|
|
|
|
@mock_ec2
|
|
|
|
def test_create_flow_logs_invalid_parameters():
|
|
|
|
s3 = boto3.resource("s3", region_name="us-west-1")
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
|
|
|
|
bucket = s3.create_bucket(
|
|
|
|
Bucket="test-flow-logs",
|
|
|
|
CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
|
|
|
|
)
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket.name,
|
|
|
|
MaxAggregationInterval=10,
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("InvalidParameter")
|
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"Invalid Flow Log Max Aggregation Interval"
|
|
|
|
)
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("InvalidParameter")
|
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"LogDestination can't be empty if LogGroupName is not provided."
|
|
|
|
)
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogGroupName="test",
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("InvalidParameter")
|
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"LogDestination type must be cloud-watch-logs if LogGroupName is provided."
|
|
|
|
)
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogGroupName="test",
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("InvalidParameter")
|
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"DeliverLogsPermissionArn can't be empty if LogDestinationType is cloud-watch-logs."
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket.name,
|
|
|
|
)["FlowLogIds"]
|
|
|
|
response.should.have.length_of(1)
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket.name,
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("FlowLogAlreadyExists")
|
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"Error. There is an existing Flow Log with the same configuration and log destination."
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogGroupName="test-group",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
|
|
|
|
)["FlowLogIds"]
|
|
|
|
response.should.have.length_of(1)
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as ex:
|
2020-09-28 06:16:06 +00:00
|
|
|
client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc["VpcId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogGroupName="test-group",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex.value.response["Error"]["Code"].should.equal("FlowLogAlreadyExists")
|
|
|
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.value.response["Error"]["Message"].should.equal(
|
2020-09-28 06:16:06 +00:00
|
|
|
"Error. There is an existing Flow Log with the same configuration and log destination."
|
|
|
|
)
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(2)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_s3
|
|
|
|
@mock_ec2
|
|
|
|
@mock_logs
|
|
|
|
def test_describe_flow_logs_filtering():
|
|
|
|
s3 = boto3.resource("s3", region_name="us-west-1")
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
logs_client = boto3.client("logs", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc1 = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
|
|
|
|
vpc3 = client.create_vpc(CidrBlock="10.2.0.0/16")["Vpc"]
|
|
|
|
|
|
|
|
subnet1 = client.create_subnet(VpcId=vpc1["VpcId"], CidrBlock="10.0.0.0/18")[
|
|
|
|
"Subnet"
|
|
|
|
]
|
|
|
|
|
|
|
|
bucket1 = s3.create_bucket(
|
|
|
|
Bucket="test-flow-logs-1",
|
|
|
|
CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
|
|
|
|
)
|
|
|
|
|
|
|
|
logs_client.create_log_group(logGroupName="test-group")
|
|
|
|
|
|
|
|
fl1 = client.create_flow_logs(
|
|
|
|
ResourceType="Subnet",
|
|
|
|
ResourceIds=[subnet1["SubnetId"]],
|
|
|
|
TrafficType="ALL",
|
|
|
|
LogGroupName="test-group",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
|
|
|
|
)["FlowLogIds"][0]
|
|
|
|
|
|
|
|
fl2 = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc2["VpcId"]],
|
|
|
|
TrafficType="Accept",
|
|
|
|
LogDestinationType="s3",
|
|
|
|
LogDestination="arn:aws:s3:::" + bucket1.name,
|
|
|
|
TagSpecifications=[
|
|
|
|
{"ResourceType": "vpc-flow-log", "Tags": [{"Key": "foo", "Value": "bar"}]}
|
|
|
|
],
|
|
|
|
)["FlowLogIds"][0]
|
|
|
|
|
|
|
|
fl3 = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc3["VpcId"]],
|
|
|
|
TrafficType="Reject",
|
|
|
|
LogGroupName="non-existing-group",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
|
|
|
|
)["FlowLogIds"][0]
|
|
|
|
|
|
|
|
all_flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
all_flow_logs.should.have.length_of(3)
|
|
|
|
|
|
|
|
fl_by_deliver_status = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "deliver-log-status", "Values": ["SUCCESS"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_deliver_status.should.have.length_of(3)
|
|
|
|
|
|
|
|
fl_by_s3_bucket = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "log-destination-type", "Values": ["s3"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_s3_bucket.should.have.length_of(1)
|
|
|
|
fl_by_s3_bucket[0]["FlowLogId"].should.equal(fl2)
|
|
|
|
fl_by_s3_bucket[0]["ResourceId"].should.equal(vpc2["VpcId"])
|
|
|
|
|
|
|
|
fl_by_cloud_watch = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "log-destination-type", "Values": ["cloud-watch-logs"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_cloud_watch.should.have.length_of(2)
|
|
|
|
|
|
|
|
flow_logs_ids = tuple(map(lambda fl: fl["FlowLogId"], fl_by_cloud_watch))
|
|
|
|
fl1.should.be.within(flow_logs_ids)
|
|
|
|
fl3.should.be.within(flow_logs_ids)
|
|
|
|
|
|
|
|
flow_logs_resource_ids = tuple(map(lambda fl: fl["ResourceId"], fl_by_cloud_watch))
|
|
|
|
subnet1["SubnetId"].should.be.within(flow_logs_resource_ids)
|
|
|
|
vpc3["VpcId"].should.be.within(flow_logs_resource_ids)
|
|
|
|
|
|
|
|
test_fl3 = next(fl for fl in fl_by_cloud_watch if fl["FlowLogId"] == fl3)
|
|
|
|
test_fl3["DeliverLogsStatus"].should.equal("FAILED")
|
|
|
|
test_fl3["DeliverLogsErrorMessage"].should.equal("Access error")
|
|
|
|
|
|
|
|
fl_by_both = client.describe_flow_logs(
|
|
|
|
Filters=[
|
|
|
|
{"Name": "log-destination-type", "Values": ["cloud-watch-logs", "s3"]}
|
|
|
|
],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_both.should.have.length_of(3)
|
|
|
|
|
|
|
|
fl_by_flow_log_ids = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "flow-log-id", "Values": [fl1, fl3]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_flow_log_ids.should.have.length_of(2)
|
|
|
|
flow_logs_ids = tuple(map(lambda fl: fl["FlowLogId"], fl_by_flow_log_ids))
|
|
|
|
fl1.should.be.within(flow_logs_ids)
|
|
|
|
fl3.should.be.within(flow_logs_ids)
|
|
|
|
|
|
|
|
flow_logs_resource_ids = tuple(map(lambda fl: fl["ResourceId"], fl_by_flow_log_ids))
|
|
|
|
subnet1["SubnetId"].should.be.within(flow_logs_resource_ids)
|
|
|
|
vpc3["VpcId"].should.be.within(flow_logs_resource_ids)
|
|
|
|
|
|
|
|
fl_by_group_name = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "log-group-name", "Values": ["test-group"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_group_name.should.have.length_of(1)
|
|
|
|
fl_by_group_name[0]["FlowLogId"].should.equal(fl1)
|
|
|
|
fl_by_group_name[0]["ResourceId"].should.equal(subnet1["SubnetId"])
|
|
|
|
|
|
|
|
fl_by_group_name = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "log-group-name", "Values": ["non-existing-group"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_group_name.should.have.length_of(1)
|
|
|
|
fl_by_group_name[0]["FlowLogId"].should.equal(fl3)
|
|
|
|
fl_by_group_name[0]["ResourceId"].should.equal(vpc3["VpcId"])
|
|
|
|
|
|
|
|
fl_by_resource_id = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "resource-id", "Values": [vpc2["VpcId"]]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_resource_id.should.have.length_of(1)
|
|
|
|
fl_by_resource_id[0]["FlowLogId"].should.equal(fl2)
|
|
|
|
fl_by_resource_id[0]["ResourceId"].should.equal(vpc2["VpcId"])
|
|
|
|
|
|
|
|
fl_by_traffic_type = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "traffic-type", "Values": ["ALL"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_traffic_type.should.have.length_of(1)
|
|
|
|
fl_by_traffic_type[0]["FlowLogId"].should.equal(fl1)
|
|
|
|
fl_by_traffic_type[0]["ResourceId"].should.equal(subnet1["SubnetId"])
|
|
|
|
|
|
|
|
fl_by_traffic_type = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "traffic-type", "Values": ["Reject"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_traffic_type.should.have.length_of(1)
|
|
|
|
fl_by_traffic_type[0]["FlowLogId"].should.equal(fl3)
|
|
|
|
fl_by_traffic_type[0]["ResourceId"].should.equal(vpc3["VpcId"])
|
|
|
|
|
|
|
|
fl_by_traffic_type = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "traffic-type", "Values": ["Accept"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_traffic_type.should.have.length_of(1)
|
|
|
|
fl_by_traffic_type[0]["FlowLogId"].should.equal(fl2)
|
|
|
|
fl_by_traffic_type[0]["ResourceId"].should.equal(vpc2["VpcId"])
|
|
|
|
|
|
|
|
fl_by_tag_key = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "tag-key", "Values": ["foo"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_tag_key.should.have.length_of(1)
|
|
|
|
fl_by_tag_key[0]["FlowLogId"].should.equal(fl2)
|
|
|
|
fl_by_tag_key[0]["ResourceId"].should.equal(vpc2["VpcId"])
|
|
|
|
|
|
|
|
fl_by_tag_key = client.describe_flow_logs(
|
|
|
|
Filters=[{"Name": "tag-key", "Values": ["non-existing"]}],
|
|
|
|
)["FlowLogs"]
|
|
|
|
fl_by_tag_key.should.have.length_of(0)
|
|
|
|
|
|
|
|
if not settings.TEST_SERVER_MODE:
|
|
|
|
client.describe_flow_logs.when.called_with(
|
|
|
|
Filters=[{"Name": "not-implemented-filter", "Values": ["foobar"]}],
|
|
|
|
).should.throw(FilterNotImplementedError)
|
|
|
|
else:
|
|
|
|
client.describe_flow_logs.when.called_with(
|
|
|
|
Filters=[{"Name": "not-implemented-filter", "Values": ["foobar"]}],
|
|
|
|
).should.throw(ResponseParserError)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_s3
|
|
|
|
@mock_ec2
|
|
|
|
def test_flow_logs_by_ids():
|
|
|
|
s3 = boto3.resource("s3", region_name="us-west-1")
|
|
|
|
client = boto3.client("ec2", region_name="us-west-1")
|
|
|
|
|
|
|
|
vpc1 = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
|
|
|
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
|
|
|
|
vpc3 = client.create_vpc(CidrBlock="10.2.0.0/16")["Vpc"]
|
|
|
|
|
|
|
|
fl1 = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc1["VpcId"]],
|
|
|
|
TrafficType="Reject",
|
|
|
|
LogGroupName="test-group-1",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-1",
|
|
|
|
)["FlowLogIds"][0]
|
|
|
|
|
|
|
|
fl2 = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc2["VpcId"]],
|
|
|
|
TrafficType="Reject",
|
|
|
|
LogGroupName="test-group-3",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-3",
|
|
|
|
)["FlowLogIds"][0]
|
|
|
|
|
|
|
|
fl3 = client.create_flow_logs(
|
|
|
|
ResourceType="VPC",
|
|
|
|
ResourceIds=[vpc3["VpcId"]],
|
|
|
|
TrafficType="Reject",
|
|
|
|
LogGroupName="test-group-3",
|
|
|
|
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-3",
|
|
|
|
)["FlowLogIds"][0]
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs(FlowLogIds=[fl1, fl3])["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(2)
|
|
|
|
flow_logs_ids = tuple(map(lambda fl: fl["FlowLogId"], flow_logs))
|
|
|
|
fl1.should.be.within(flow_logs_ids)
|
|
|
|
fl3.should.be.within(flow_logs_ids)
|
|
|
|
|
|
|
|
flow_logs_resource_ids = tuple(map(lambda fl: fl["ResourceId"], flow_logs))
|
|
|
|
vpc1["VpcId"].should.be.within(flow_logs_resource_ids)
|
|
|
|
vpc3["VpcId"].should.be.within(flow_logs_resource_ids)
|
|
|
|
|
|
|
|
client.delete_flow_logs(FlowLogIds=[fl1, fl3])
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs(FlowLogIds=[fl1, fl3])["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(0)
|
|
|
|
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(1)
|
|
|
|
flow_logs[0]["FlowLogId"].should.equal(fl2)
|
|
|
|
flow_logs[0]["ResourceId"].should.equal(vpc2["VpcId"])
|
|
|
|
|
|
|
|
flow_logs = client.delete_flow_logs(FlowLogIds=[fl2])
|
|
|
|
flow_logs = client.describe_flow_logs()["FlowLogs"]
|
|
|
|
flow_logs.should.have.length_of(0)
|