Closed 0xdabbad00 closed 5 years ago
Looking at the output of ec2 describe-network-interfaces
there are some issues.
Using aws ec2 describe-vpc-endpoints
I can see the PrivateLink (VPC Endpoints) and Gateway endpoints (S3 + DynamoDB). These just go to the services, and then you have to parse the policies associated with them to identify the actual resources they allow access to. As such, for an initial release, I'm only going to show a connection as going to a service and not name the specific resources. Further, there are all sorts of other things that can restrict access to the resources, such as IAM or resource policies.
This is explained in the UI screen when you go to edit the policy for one of the endpoints.
An interesting thing is the VPC endpoints end up with interfaces (as found from aws ec2 describe-network-interfaces
) in each of the subnets, so a single VPC endpoint for accessing SQS results in 6 new interfaces appearing for me in us-east-1.
Here is an example:
{
"Status": "in-use",
"MacAddress": "06:61:a7:1f:d0:dc",
"SourceDestCheck": true,
"AvailabilityZone": "us-east-1e",
"Description": "VPC Endpoint Interface vpce-05ed16ac73726e737",
"NetworkInterfaceId": "eni-09785271abed2b16d",
"VpcId": "vpc-4b52dd32",
"PrivateIpAddresses": [
{
"PrivateDnsName": "ip-172-31-60-106.ec2.internal",
"Primary": true,
"PrivateIpAddress": "172.31.60.106"
}
],
"RequesterManaged": true,
"PrivateDnsName": "ip-172-31-60-106.ec2.internal",
"RequesterId": "727180483921",
"InterfaceType": "vpc_endpoint",
"Attachment": {
"Status": "attached",
"DeviceIndex": 1,
"DeleteOnTermination": false,
"AttachmentId": "ela-attach-23af6704",
"InstanceOwnerId": "amazon-aws"
},
"Groups": [
{
"GroupName": "default",
"GroupId": "sg-09920178"
}
],
"Ipv6Addresses": [],
"OwnerId": "954574370272",
"SubnetId": "subnet-07d3ea3b",
"TagSet": [],
"PrivateIpAddress": "172.31.60.106"
}
The Gateway endpoints however do not have any associated interfaces.
$ aws ec2 describe-vpc-endpoints
{
"VpcEndpoints": [
{
"PolicyDocument": "{\"Version\":\"2008-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"*\",\"Resource\":\"*\"}]}",
"VpcId": "vpc-4b52dd32",
"NetworkInterfaceIds": [],
"SubnetIds": [],
"PrivateDnsEnabled": false,
"State": "available",
"ServiceName": "com.amazonaws.us-east-1.s3",
"RouteTableIds": [
"rtb-ca95c4b2"
],
"Groups": [],
"VpcEndpointId": "vpce-05e0785124009dbbc",
"VpcEndpointType": "Gateway",
"CreationTimestamp": "2019-04-11T18:59:11.000Z",
"DnsEntries": []
},
{
"PolicyDocument": "{\n \"Statement\": [\n {\n \"Action\": \"*\",\n \"Effect\": \"Allow\",\n \"Resource\": \"*\",\n \"Principal\": \"*\"\n }\n ]\n}",
"VpcId": "vpc-4b52dd32",
"NetworkInterfaceIds": [
"eni-039a37a6ce940d5d2",
"eni-0972ceecdba8c5df9",
"eni-09785271abed2b16d",
"eni-0afc1be0c66a42633",
"eni-0dde8fc67086a2b22",
"eni-03d75ab23bc6e04e4"
],
"SubnetIds": [
"subnet-7543383d",
"subnet-5d7bc007",
"subnet-1abda07f",
"subnet-07d3ea3b",
"subnet-a09b188c",
"subnet-2e33ab22"
],
"PrivateDnsEnabled": true,
"State": "available",
"ServiceName": "com.amazonaws.us-east-1.sqs",
"RouteTableIds": [],
"Groups": [
{
"GroupName": "default",
"GroupId": "sg-09920178"
}
],
"VpcEndpointId": "vpce-05ed16ac73726e737",
"VpcEndpointType": "Interface",
"CreationTimestamp": "2019-04-30T15:19:35.000Z",
"DnsEntries": [
{
"HostedZoneId": "Z7HUB22UULQXV",
"DnsName": "vpce-05ed16ac73726e737-5xkr9dae.sqs.us-east-1.vpce.amazonaws.com"
},
{
"HostedZoneId": "Z7HUB22UULQXV",
"DnsName": "vpce-05ed16ac73726e737-5xkr9dae-us-east-1c.sqs.us-east-1.vpce.amazonaws.com"
},
{
"HostedZoneId": "Z7HUB22UULQXV",
"DnsName": "vpce-05ed16ac73726e737-5xkr9dae-us-east-1d.sqs.us-east-1.vpce.amazonaws.com"
},
{
"HostedZoneId": "Z7HUB22UULQXV",
"DnsName": "vpce-05ed16ac73726e737-5xkr9dae-us-east-1a.sqs.us-east-1.vpce.amazonaws.com"
},
{
"HostedZoneId": "Z7HUB22UULQXV",
"DnsName": "vpce-05ed16ac73726e737-5xkr9dae-us-east-1e.sqs.us-east-1.vpce.amazonaws.com"
},
{
"HostedZoneId": "Z7HUB22UULQXV",
"DnsName": "vpce-05ed16ac73726e737-5xkr9dae-us-east-1b.sqs.us-east-1.vpce.amazonaws.com"
},
{
"HostedZoneId": "Z7HUB22UULQXV",
"DnsName": "vpce-05ed16ac73726e737-5xkr9dae-us-east-1f.sqs.us-east-1.vpce.amazonaws.com"
},
{
"HostedZoneId": "ZCYZV1JQU4VH2",
"DnsName": "sqs.us-east-1.amazonaws.com"
}
]
}
]
}
Because Gateway Endpoints do not have interfaces, they do not have Security Groups.
I created a Lambda in a VPC. Doing aws lambda list-functions
shows:
{
"TracingConfig": {
"Mode": "PassThrough"
},
"Version": "$LATEST",
"CodeSha256": "H4QrZXTeJhAFtZ6dfi7NjMZiGHZfFgGpD38SjX+BaMw=",
"FunctionName": "invpclambda",
"VpcConfig": {
"SubnetIds": [
"subnet-5d7bc007",
"subnet-7543383d"
],
"VpcId": "vpc-4b52dd32",
"SecurityGroupIds": [
"sg-09920178"
]
},
"MemorySize": 128,
"RevisionId": "78a5eca3-193c-4f09-bed0-123f2d1c3ad3",
"CodeSize": 262,
"FunctionArn": "arn:aws:lambda:us-east-1:954574370272:function:invpclambda",
"Handler": "index.handler",
"Role": "arn:aws:iam::954574370272:role/service-role/invpclambda",
"Timeout": 3,
"LastModified": "2019-04-30T16:26:38.618+0000",
"Runtime": "nodejs8.10",
"Description": ""
},
However aws ec2 describe-network-interfaces
still does not show an interface for it. It therefore looks like I'm going to have to iterate through the different services to identify which ones are in VPCs.
I need to do the following:
I believe the following all support VPCs:
Through PrivateLink:
Through Gateway endpoints:
I'm going to start with the Gateway endpoints, then the PrivateLink ones, then Lambda and EKS, and see how things are from there.
I've added code to read from ec2-describe-vpc-endpoints.json
.
I need to test it works correctly with Security Groups. Because the Gateway endpoints are associated with a VPC, these just sort of "float" in the VPC.
I am generically giving that purple icon (which is supposed to be for an ENI) to any of these end-points, and then for S3 I change it's type to S3.
Some tasks for this
The Gateway endpoints (S3) does not have Security Groups. Everything in the VPC is allowed access to it. I'm not sure if I should therefore draw lines from everything to it? That seems like the most correct choice, but it will be cluttered.
This is what I have currently, and although technically correct I believe, it is misleading because I believe the Gateway and Interface endpoints can't call out, so they can't actually talk to each other.
My belief is correct that the endpoints cannot initiate traffic "Services cannot initiate requests to resources in your VPC through the endpoint. An endpoint only returns responses to traffic initiated from resources in your VPC." - https://docs.aws.amazon.com/vpc/latest/userguide/vpce-interface.html
So I'm going to have a check in the code that if the source is an endpoint, then don't build a connection.
Also, I'm thinking of creating a virtual/fake subnet for the VPC-level resources such as the S3 endpoint.
VPC Endpoint support has been added in #376
I added endpoints to the demo account data. It looks cluttered. :(
I cut a release for this https://github.com/duo-labs/cloudmapper/releases/tag/2.5.4
Going to work on ECS support now.
For ECS, the info I need, using the flaws2 target account for data, comes from:
aws ecs describe-tasks --cluster level3 --tasks arn:aws:ecs:us-east-1:653711331788:task/d190d14a-2404-45d6-9113-4eda22d7f2c7
{
"failures": [],
"tasks": [
{
"launchType": "FARGATE",
"attachments": [
{
"status": "ATTACHED",
"type": "ElasticNetworkInterface",
"id": "ed8fed01-82d0-4bf6-86cf-fe3115c23ab8",
"details": [
{
"name": "subnetId",
"value": "subnet-e45602eb"
},
{
"name": "networkInterfaceId",
"value": "eni-200e9484"
},
{
"name": "macAddress",
"value": "16:2f:d0:d6:ed:28"
},
{
"name": "privateIPv4Address",
"value": "172.31.48.168"
}
]
}
],
"clusterArn": "arn:aws:ecs:us-east-1:653711331788:cluster/level3",
"desiredStatus": "RUNNING",
"createdAt": 1543289790.71,
"taskArn": "arn:aws:ecs:us-east-1:653711331788:task/d190d14a-2404-45d6-9113-4eda22d7f2c7",
"group": "family:level3",
"pullStartedAt": 1543289803.371,
"version": 3,
"memory": "512",
"connectivityAt": 1543289795.422,
"startedAt": 1543289825.371,
"taskDefinitionArn": "arn:aws:ecs:us-east-1:653711331788:task-definition/level3:3",
"containers": [
{
"containerArn": "arn:aws:ecs:us-east-1:653711331788:container/f67ce604-5248-41a0-8a95-78ab4fb57a44",
"taskArn": "arn:aws:ecs:us-east-1:653711331788:task/d190d14a-2404-45d6-9113-4eda22d7f2c7",
"name": "level3",
"networkBindings": [],
"lastStatus": "RUNNING",
"healthStatus": "UNHEALTHY",
"cpu": "0",
"networkInterfaces": [
{
"privateIpv4Address": "172.31.48.168",
"attachmentId": "ed8fed01-82d0-4bf6-86cf-fe3115c23ab8"
}
]
}
],
"tags": [],
"lastStatus": "RUNNING",
"connectivity": "CONNECTED",
"healthStatus": "UNHEALTHY",
"platformVersion": "1.2.0",
"overrides": {
"containerOverrides": [
{
"name": "level3"
}
]
},
"pullStoppedAt": 1543289824.371,
"cpu": "256"
}
]
}
That tells me the subnet and IP for the ECS, but then to get the Security Groups, I have to look at:
aws ec2 describe-network-interfaces
{
"NetworkInterfaces": [
{
"Status": "in-use",
"MacAddress": "16:2f:d0:d6:ed:28",
"SourceDestCheck": true,
"AvailabilityZone": "us-east-1f",
"Description": "arn:aws:ecs:us-east-1:653711331788:attachment/ed8fed01-82d0-4bf6-86cf-fe3115c23ab8",
"NetworkInterfaceId": "eni-200e9484",
"VpcId": "vpc-d301aea9",
"PrivateIpAddresses": [
{
"PrivateDnsName": "ip-172-31-48-168.ec2.internal",
"PrivateIpAddress": "172.31.48.168",
"Primary": true,
"Association": {
"PublicIp": "3.80.3.41",
"PublicDnsName": "ec2-3-80-3-41.compute-1.amazonaws.com",
"IpOwnerId": "amazon"
}
}
],
"RequesterManaged": true,
"PrivateDnsName": "ip-172-31-48-168.ec2.internal",
"RequesterId": "578734482556",
"InterfaceType": "interface",
"Attachment": {
"Status": "attached",
"DeviceIndex": 1,
"AttachTime": "2018-11-27T03:36:34.000Z",
"DeleteOnTermination": false,
"AttachmentId": "eni-attach-08ac3da5d33fc7a02",
"InstanceOwnerId": "501673713797"
},
"Groups": [
{
"GroupName": "level3-4493",
"GroupId": "sg-0e9a07e8609bce851"
}
],
"Ipv6Addresses": [],
"OwnerId": "653711331788",
"PrivateIpAddress": "172.31.48.168",
"SubnetId": "subnet-e45602eb",
"TagSet": [],
"Association": {
"PublicIp": "3.80.3.41",
"PublicDnsName": "ec2-3-80-3-41.compute-1.amazonaws.com",
"IpOwnerId": "amazon"
}
}
]
}
So I need to improve my collect
. My recent attempt at calling ecs-list-container-instances/
does nothing.
I already have:
$ aws ecs list-clusters
{
"clusterArns": [
"arn:aws:ecs:us-east-1:653711331788:cluster/level3"
]
}
So I need to call:
aws ecs list-tasks --cluster arn:aws:ecs:us-east-1:653711331788:cluster/level3
{
"taskArns": [
"arn:aws:ecs:us-east-1:653711331788:task/d190d14a-2404-45d6-9113-4eda22d7f2c7"
]
}
Then I need to use that to call
aws ecs describe-tasks --cluster level3 --tasks arn:aws:ecs:us-east-1:653711331788:task/d190d14a-2404-45d6-9113-4eda22d7f2c7
So I'll need multiple parameters for collect
Once I have all this data, I'll need to combine the aws ecs describe-tasks
with aws ec2 describe-network-interfaces
as mentioned above to get the Security Groups.
ECS support added in #378
Here is a sample from the flaws2 target account. This ECS I believe is connected to an API Gateway which I don't currently support showing.
Next I'll need to show Lambda and API Gateway
Getting API Gateway configs looks like this:
$ aws apigateway get-rest-apis
{
"items": [
{
"apiKeySource": "HEADER",
"description": "Created by AWS Lambda",
"endpointConfiguration": {
"types": [
"REGIONAL"
]
},
"createdDate": 1542734151,
"id": "2rfismmoo8",
"name": "level1-API"
},
{
"apiKeySource": "HEADER",
"description": "Created by AWS Lambda",
"endpointConfiguration": {
"types": [
"REGIONAL"
]
},
"createdDate": 1543342826,
"id": "4y0944ja4h",
"name": "level4-API"
}
]
}
Then use the rest-api-id
:
$ aws apigateway get-resources --rest-api-id 4y0944ja4h
{
"items": [
{
"path": "/level4",
"resourceMethods": {
"ANY": {}
},
"id": "31jtug",
"pathPart": "level4",
"parentId": "tnf7fjnef6"
},
{
"path": "/",
"id": "tnf7fjnef6"
}
]
}
Then use the rest-api-id
, resource-id
, and http-method
:
$ aws apigateway get-integration --rest-api-id 4y0944ja4h --resource-id 31jtug --http-method ANY
{
"integrationResponses": {
"200": {
"selectionPattern": ".*",
"statusCode": "200"
}
},
"passthroughBehavior": "WHEN_NO_MATCH",
"timeoutInMillis": 29000,
"uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:653711331788:function:level4/invocations",
"httpMethod": "POST",
"cacheNamespace": "31jtug",
"type": "AWS_PROXY",
"cacheKeyParameters": []
}
This will require a custom collection function. :(
Also, this still doesn't show how I accessed that Level3 ECS. Need to figure out how that is being called publicly.
ECS was being exposed directly to the Internet, but I didn't realize that I had to look at the network interface to identify the public IP. This is resolved in #379
The flaws2 target account is visualized as follows, as only ECS is supported right now.
Next up will be Lambda and API Gateway. I also need to change the icons for the VPC Endpoints back to a generic endpoint icon now that I am actually supporting the real services for the icons.
I was going crazy trying to find where the Level4 lambda was that I mentioned earlier. Turns out I had setup API Gateway for a level4 lambda, but then deleted that Lambda, so there is no level 4 in flaws2, and thus no lambda, so this is a good test case.
There are no Security Groups associated with API Gateway or with a non-VPC Lambda, so I'm not sure if it really makes sense to map these with the current scope of how CloudMapper works. To map those, and have the maps make sense, I would need to parse their policies, which would be a big scope increase. So I'll just map VPC-configured Lambdas.
Lambda support added in #381 I only show the Lambdas that are inside VPCs. This is going to confuse people when I don't show other Lambdas, but I don't know how to handle that.
Here's a screenshot from a test account with Lambdas.
I'm going to do ElasticSearch and then RedShift next.
ElasticSearch and Redshift added in #382
Screenshot from my test environment. I'll move this data over to the demo data and add unit tests.
I need to fix what I'm doing for Redshift. Currently, I just Redshift as a VPC level node, but technically it does exist in a subnet. I need to do the following:
redshift-describe-clusters.json
data, get the ClusterSubnetGroupName
(ex. default
for my test account).aws redshift describe-cluster-subnet-groups
to collect
and look in ClusterSubnetGroups
for the ClusterSubnetGroupName
that matches (ie. default
)ec2-describe-subnets.json
to get their CidrBlock
, and then look again at redshift-describe-clusters.json
at the ClusterNodes
data and the PrivateIPAddress
to see what subnet(based on the CIDR) that IP falls in.Redshift subnet issue fixed in #383 and the demo data updated along with the tests.
Demo data looks like this currently.
ECS, Lambda, and ES added to demo data in #384
I'm going to update the online demo, then close this ticket.
Demo has been updated.
Why are S3 and Lambda not displayed in the map of my own infrastructure? When preparing the demo-infrastructure, I can see all the different services. But after preparing my own infrastructure (with EC2, ELB, Lambda, S3), I only see EC2 and ELB.
@mfuellbier Only VPC resources are displayed, so unless you set up a VPC Endpoint for the S3 service, or if your Lambda's are VPC Lambdas (not the default), then you won't see them. Basically, if you can't attach a Security Group to it, then it won't be displayed. I'll look into clarifying this better in the docs.
CloudMapper should be able to display a map of all AWS network resources, which I'll define as those resources that can have Security Groups applied to them.
This includes:
There are probably more. My plan is to use
aws ec2 describe-network-interfaces
which provides a list of network interfaces with their:This issue partially resolves #339, #306, #89, adn #51