Repository: cloud-custodian/cloud-custodian

Issue:
The CopyRelatedResourceTag action does not handle many-to-one relationships
I have the following policy to copy instance tags to its ENIs when the instance launches deployed as a lambda.  It works correctly when the instance launches with one ENI.  If the instance has more than one ENI, only one of the interfaces is tagged.  The lambda invocation runs to completion without errors, though.

```yaml
  - name: copy-tags-from-ec2-instance-to-eni
    description: 'Copies tags from instances to attached ENIs on launch'
    resource: eni
    mode:
      <<: *mode-var
      type: cloudtrail
      events:
        - source: ec2.amazonaws.com
          event: RunInstances
          ids: 'responseElements.instancesSet.items[].networkInterfaceSet.items[].networkInterfaceId'
    actions:
      - type: copy-related-tag
        resource: ec2
        skip_missing: True
        key: Attachment.InstanceId
        tags: '*'
```

Here are the invocation logs from CloudWatch.  The instance was launched with two ENIs.

```
[INFO] 2019-05-08T20:23:32.379Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Found resource ids: ['eni-0bb2ed16e499e4e50', 'eni-053019442cf2945bf']

[INFO] 2019-05-08T20:23:32.858Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Resources [{'Attachment': {'AttachTime': datetime.datetime(2019, 5, 8, 20, 22, 44, tzinfo=tzlocal()), 'AttachmentId': 'eni-attach-0a3af1145ba20a92d', 'DeleteOnTermination': True, 'DeviceIndex': 0, 'InstanceId': 'i-0486f3807f3d85628', 'InstanceOwnerId': '483701481926', 'Status': 'attached'}, 'AvailabilityZone': 'us-east-1a', 'Description': 'Primary network interface', 'Groups': [{'GroupName': 'default', 'GroupId': 'sg-8362deff'}], 'InterfaceType': 'interface', 'Ipv6Addresses': [], 'MacAddress': '0a:9a:bf:9a:d1:f8', 'NetworkInterfaceId': 'eni-0bb2ed16e499e4e50', 'OwnerId': '483701481926', 'PrivateDnsName': 'ip-10-246-228-116.ec2.internal', 'PrivateIpAddress': '10.246.228.116', 'PrivateIpAddresses': [{'Primary': True, 'PrivateDnsName': 'ip-10-246-228-116.ec2.internal', 'PrivateIpAddress': '10.246.228.116'}], 'RequesterManaged': False, 'SourceDestCheck': True, 'Status': 'in-use', 'SubnetId': 'subnet-f56250bc', 'VpcId': 'vpc-c2db4fa4', 'Tags': []}, {'Attachment': {'AttachTime': datetime.datetime(2019, 5, 8, 20, 22, 44, tzinfo=tzlocal()), 'AttachmentId': 'eni-attach-0ba113e95654672bf', 'DeleteOnTermination': True, 'DeviceIndex': 1, 'InstanceId': 'i-0486f3807f3d85628', 'InstanceOwnerId': '483701481926', 'Status': 'attached'}, 'AvailabilityZone': 'us-east-1a', 'Description': '', 'Groups': [{'GroupName': 'default', 'GroupId': 'sg-8362deff'}], 'InterfaceType': 'interface', 'Ipv6Addresses': [], 'MacAddress': '0a:cb:26:7b:e0:36', 'NetworkInterfaceId': 'eni-053019442cf2945bf', 'OwnerId': '483701481926', 'PrivateDnsName': 'ip-10-246-228-45.ec2.internal', 'PrivateIpAddress': '10.246.228.45', 'PrivateIpAddresses': [{'Primary': True, 'PrivateDnsName': 'ip-10-246-228-45.ec2.internal', 'PrivateIpAddress': '10.246.228.45'}], 'RequesterManaged': False, 'SourceDestCheck': True, 'Status': 'in-use', 'SubnetId': 'subnet-f56250bc', 'VpcId': 'vpc-c2db4fa4', 'Tags': []}]

[INFO] 2019-05-08T20:23:32.859Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Filtering resources with []

[DEBUG] 2019-05-08T20:23:32.859Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Filtered from 2 to 2 networkinterface

[INFO] 2019-05-08T20:23:32.859Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Filtered resources 2

[DEBUG] 2019-05-08T20:23:32.859Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Storing output with <LogFile file:///tmp/12b4f671-2360-4edf-9c74-362d49398c76/copy-tags-from-ec2-instance-to-eni/custodian-run.log>

[DEBUG] 2019-05-08T20:23:32.859Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de metric:ResourceCount Count:2 policy:copy-tags-from-ec2-instance-to-eni restype:eni scope:policy

[INFO] 2019-05-08T20:23:32.860Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Invoking actions [<c7n.tags.CopyRelatedResourceTag object at 0x7fa48dea2da0>]

[INFO] 2019-05-08T20:23:32.860Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de policy: copy-tags-from-ec2-instance-to-eni invoking action: copyrelatedresourcetag resources: 2

[DEBUG] 2019-05-08T20:23:33.105Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Filtered from 4 to 4 ec2

[INFO] 2019-05-08T20:23:33.269Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de Tagged 1 resources from related, missing-skipped 0 unchanged 0

[DEBUG] 2019-05-08T20:23:33.272Z 8e7cebe3-a67b-42bc-a46f-37788b51d3de metric:ApiCalls Count:2 policy:copy-tags-from-ec2-instance-to-eni restype:eni
```

Here is the request and response properties from the RunInstances CloudTrail event.
```json
{
    "requestParameters": {
        "instancesSet": {
            "items": [
                {
                    "imageId": "ami-0de53d8956e8dcf80",
                    "minCount": 1,
                    "maxCount": 1
                }
            ]
        },
        "instanceType": "t3a.micro",
        "blockDeviceMapping": {
            "items": [
                {
                    "deviceName": "/dev/xvda",
                    "ebs": {
                        "volumeSize": 8,
                        "deleteOnTermination": true,
                        "volumeType": "gp2"
                    }
                }
            ]
        },
        "availabilityZone": "us-east-1a",
        "tenancy": "default",
        "monitoring": {
            "enabled": false
        },
        "disableApiTermination": false,
        "networkInterfaceSet": {
            "items": [
                {
                    "deviceIndex": 0,
                    "subnetId": "subnet-f56250bc",
                    "description": "Primary network interface",
                    "deleteOnTermination": true,
                    "groupSet": {
                        "items": [
                            {
                                "groupId": "sg-8362deff"
                            }
                        ]
                    },
                    "ipv6AddressCount": 0
                },
                {
                    "deviceIndex": 1,
                    "subnetId": "subnet-f56250bc",
                    "deleteOnTermination": true,
                    "groupSet": {
                        "items": [
                            {
                                "groupId": "sg-8362deff"
                            }
                        ]
                    },
                    "ipv6AddressCount": 0
                }
            ]
        },
        "ebsOptimized": true,
        "tagSpecificationSet": {
            "items": [
                {
                    "resourceType": "instance",
                    "tags": [
                        {
                            "key": "Name",
                            "value": "custodian-testing-2"
                        },
                        {
                            "key": "description",
                            "value": "two netwok interfaces"
                        }
                    ]
                }
            ]
        },
        "creditSpecification": {
            "cpuCredits": "standard"
        }
    },
    "responseElements": {
        "requestId": "d81d5423-7554-4a0a-8e5f-9c1bcccc6f3a",
        "reservationId": "r-0da95df40e1ae7882",
        "ownerId": "483701481926",
        "groupSet": {},
        "instancesSet": {
            "items": [
                {
                    "instanceId": "i-0486f3807f3d85628",
                    "imageId": "ami-0de53d8956e8dcf80",
                    "instanceState": {
                        "code": 0,
                        "name": "pending"
                    },
                    "privateDnsName": "ip-10-246-228-116.ec2.internal",
                    "amiLaunchIndex": 0,
                    "productCodes": {},
                    "instanceType": "t3a.micro",
                    "launchTime": 1557346964000,
                    "placement": {
                        "availabilityZone": "us-east-1a",
                        "tenancy": "default"
                    },
                    "monitoring": {
                        "state": "disabled"
                    },
                    "subnetId": "subnet-f56250bc",
                    "vpcId": "vpc-c2db4fa4",
                    "privateIpAddress": "10.246.228.116",
                    "stateReason": {
                        "code": "pending",
                        "message": "pending"
                    },
                    "architecture": "x86_64",
                    "rootDeviceType": "ebs",
                    "rootDeviceName": "/dev/xvda",
                    "blockDeviceMapping": {},
                    "virtualizationType": "hvm",
                    "hypervisor": "xen",
                    "tagSet": {
                        "items": [
                            {
                                "key": "Name",
                                "value": "custodian-testing-2"
                            },
                            {
                                "key": "description",
                                "value": "two netwok interfaces"
                            }
                        ]
                    },
                    "groupSet": {
                        "items": [
                            {
                                "groupId": "sg-8362deff",
                                "groupName": "default"
                            }
                        ]
                    },
                    "sourceDestCheck": true,
                    "networkInterfaceSet": {
                        "items": [
                            {
                                "networkInterfaceId": "eni-0bb2ed16e499e4e50",
                                "subnetId": "subnet-f56250bc",
                                "vpcId": "vpc-c2db4fa4",
                                "description": "Primary network interface",
                                "ownerId": "483701481926",
                                "status": "in-use",
                                "macAddress": "0a:9a:bf:9a:d1:f8",
                                "privateIpAddress": "10.246.228.116",
                                "privateDnsName": "ip-10-246-228-116.ec2.internal",
                                "sourceDestCheck": true,
                                "interfaceType": "interface",
                                "groupSet": {
                                    "items": [
                                        {
                                            "groupId": "sg-8362deff",
                                            "groupName": "default"
                                        }
                                    ]
                                },
                                "attachment": {
                                    "attachmentId": "eni-attach-0a3af1145ba20a92d",
                                    "deviceIndex": 0,
                                    "status": "attaching",
                                    "attachTime": 1557346964000,
                                    "deleteOnTermination": true
                                },
                                "privateIpAddressesSet": {
                                    "item": [
                                        {
                                            "privateIpAddress": "10.246.228.116",
                                            "privateDnsName": "ip-10-246-228-116.ec2.internal",
                                            "primary": true
                                        }
                                    ]
                                },
                                "ipv6AddressesSet": {},
                                "tagSet": {}
                            },
                            {
                                "networkInterfaceId": "eni-053019442cf2945bf",
                                "subnetId": "subnet-f56250bc",
                                "vpcId": "vpc-c2db4fa4",
                                "ownerId": "483701481926",
                                "status": "in-use",
                                "macAddress": "0a:cb:26:7b:e0:36",
                                "privateIpAddress": "10.246.228.45",
                                "privateDnsName": "ip-10-246-228-45.ec2.internal",
                                "sourceDestCheck": true,
                                "interfaceType": "interface",
                                "groupSet": {
                                    "items": [
                                        {
                                            "groupId": "sg-8362deff",
                                            "groupName": "default"
                                        }
                                    ]
                                },
                                "attachment": {
                                    "attachmentId": "eni-attach-0ba113e95654672bf",
                                    "deviceIndex": 1,
                                    "status": "attaching",
                                    "attachTime": 1557346964000,
                                    "deleteOnTermination": true
                                },
                                "privateIpAddressesSet": {
                                    "item": [
                                        {
                                            "privateIpAddress": "10.246.228.45",
                                            "privateDnsName": "ip-10-246-228-45.ec2.internal",
                                            "primary": true
                                        }
                                    ]
                                },
                                "ipv6AddressesSet": {},
                                "tagSet": {}
                            }
                        ]
                    },
                    "ebsOptimized": true,
                    "cpuOptions": {
                        "coreCount": 1,
                        "threadsPerCore": 2
                    },
                    "capacityReservationSpecification": {
                        "capacityReservationPreference": "open"
                    }
                }
            ]
        }
    }
}
```

I suspect the issue is in the first line of [process method](https://github.com/cloud-custodian/cloud-custodian/blob/b0f41d72ce7eccee7b74254358d3838e217fbb28/c7n/tags.py#L1023) where the mapping between the resources is created.


Discussion:

Resolving patch:
diff --git a/c7n/tags.py b/c7n/tags.py
--- a/c7n/tags.py
+++ b/c7n/tags.py
@@ -1020,9 +1020,11 @@ def validate(self):
         return self
 
     def process(self, resources):
-        related_resources = dict(
-            zip(jmespath.search('[].%s' % self.data['key'], resources), resources))
-        related_ids = set(related_resources)
+        related_resources = list(
+            zip(jmespath.search('[].[%s || "c7n:NotFound"]|[]' % self.data['key'], resources),
+                resources))
+        related_ids = set([r[0] for r in related_resources])
+        related_ids.discard('c7n:NotFound')
         related_tag_map = self.get_resource_tag_map(self.data['resource'], related_ids)
 
         missing_related_tags = related_ids.difference(related_tag_map.keys())
@@ -1038,7 +1040,7 @@ def process(self, resources):
 
         stats = Counter()
 
-        for related, r in related_resources.items():
+        for related, r in related_resources:
             if related in missing_related_tags or not related_tag_map[related]:
                 stats['missing'] += 1
             elif self.process_resource(
diff --git a/tools/c7n_azure/setup.py b/tools/c7n_azure/setup.py
--- a/tools/c7n_azure/setup.py
+++ b/tools/c7n_azure/setup.py
@@ -42,7 +42,7 @@
             'azure = c7n_azure.entry:initialize_azure']
     },
     install_requires=["azure-mgmt-authorization",
-                      "azure-mgmt-applicationinsights",
+                      "azure-mgmt-applicationinsights==0.1.1",
                       "azure-mgmt-batch",
                       "azure-mgmt-cognitiveservices",
                       "azure-mgmt-cosmosdb",


Test patch:
diff --git a/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.CreateTags_1.json b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.CreateTags_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.CreateTags_1.json
@@ -0,0 +1,16 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {
+            "RequestId": "018f51f4-5b77-4ee7-82e7-dcd208b3286d",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "content-type": "text/xml;charset=UTF-8",
+                "content-length": "221",
+                "date": "Thu, 16 May 2019 17:06:38 GMT",
+                "server": "AmazonEC2"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.CreateTags_2.json b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.CreateTags_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.CreateTags_2.json
@@ -0,0 +1,16 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {
+            "RequestId": "5b133543-22ed-4c63-ac10-5959b8f444bc",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "content-type": "text/xml;charset=UTF-8",
+                "content-length": "221",
+                "date": "Thu, 16 May 2019 17:06:39 GMT",
+                "server": "AmazonEC2"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeSnapshots_1.json b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeSnapshots_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeSnapshots_1.json
@@ -0,0 +1,80 @@
+{
+    "status_code": 200,
+    "data": {
+        "Snapshots": [
+            {
+                "Description": "",
+                "Encrypted": false,
+                "OwnerId": "644160558196",
+                "Progress": "100%",
+                "SnapshotId": "snap-09b2f5724227e0e77",
+                "StartTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 5,
+                    "day": 16,
+                    "hour": 15,
+                    "minute": 40,
+                    "second": 15,
+                    "microsecond": 829000
+                },
+                "State": "completed",
+                "VolumeId": "vol-00ab6a43334e4224b",
+                "VolumeSize": 1
+            },
+            {
+                "Description": "",
+                "Encrypted": true,
+                "KmsKeyId": "arn:aws:kms:us-west-2:644160558196:key/68425528-9938-4a15-90f2-f1755263b836",
+                "OwnerId": "644160558196",
+                "Progress": "100%",
+                "SnapshotId": "snap-0d3154c96a586adff",
+                "StartTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 5,
+                    "day": 16,
+                    "hour": 15,
+                    "minute": 39,
+                    "second": 37,
+                    "microsecond": 69000
+                },
+                "State": "completed",
+                "VolumeId": "vol-069d75193c497b8aa",
+                "VolumeSize": 8
+            },
+            {
+                "Description": "",
+                "Encrypted": true,
+                "KmsKeyId": "arn:aws:kms:us-west-2:644160558196:key/68425528-9938-4a15-90f2-f1755263b836",
+                "OwnerId": "644160558196",
+                "Progress": "100%",
+                "SnapshotId": "snap-08734982bb772fc02",
+                "StartTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 5,
+                    "day": 16,
+                    "hour": 15,
+                    "minute": 39,
+                    "second": 56,
+                    "microsecond": 541000
+                },
+                "State": "completed",
+                "VolumeId": "vol-069d75193c497b8aa",
+                "VolumeSize": 8
+            }
+        ],
+        "ResponseMetadata": {
+            "RequestId": "5e784a86-e385-45a8-bea0-de4c47b85f6d",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "content-type": "text/xml;charset=UTF-8",
+                "content-length": "1763",
+                "date": "Thu, 16 May 2019 17:06:37 GMT",
+                "server": "AmazonEC2"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeSnapshots_2.json b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeSnapshots_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeSnapshots_2.json
@@ -0,0 +1,93 @@
+{
+    "status_code": 200,
+    "data": {
+        "Snapshots": [
+            {
+                "Description": "",
+                "Encrypted": false,
+                "OwnerId": "644160558196",
+                "Progress": "100%",
+                "SnapshotId": "snap-09b2f5724227e0e77",
+                "StartTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 5,
+                    "day": 16,
+                    "hour": 15,
+                    "minute": 40,
+                    "second": 15,
+                    "microsecond": 829000
+                },
+                "State": "completed",
+                "VolumeId": "vol-00ab6a43334e4224b",
+                "VolumeSize": 1
+            },
+            {
+                "Description": "",
+                "Encrypted": true,
+                "KmsKeyId": "arn:aws:kms:us-west-2:644160558196:key/68425528-9938-4a15-90f2-f1755263b836",
+                "OwnerId": "644160558196",
+                "Progress": "100%",
+                "SnapshotId": "snap-0d3154c96a586adff",
+                "StartTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 5,
+                    "day": 16,
+                    "hour": 15,
+                    "minute": 39,
+                    "second": 37,
+                    "microsecond": 69000
+                },
+                "State": "completed",
+                "VolumeId": "vol-069d75193c497b8aa",
+                "VolumeSize": 8,
+                "Tags": [
+                    {
+                        "Key": "test",
+                        "Value": "test"
+                    }
+                ]
+            },
+            {
+                "Description": "",
+                "Encrypted": true,
+                "KmsKeyId": "arn:aws:kms:us-west-2:644160558196:key/68425528-9938-4a15-90f2-f1755263b836",
+                "OwnerId": "644160558196",
+                "Progress": "100%",
+                "SnapshotId": "snap-08734982bb772fc02",
+                "StartTime": {
+                    "__class__": "datetime",
+                    "year": 2019,
+                    "month": 5,
+                    "day": 16,
+                    "hour": 15,
+                    "minute": 39,
+                    "second": 56,
+                    "microsecond": 541000
+                },
+                "State": "completed",
+                "VolumeId": "vol-069d75193c497b8aa",
+                "VolumeSize": 8,
+                "Tags": [
+                    {
+                        "Key": "test",
+                        "Value": "test"
+                    }
+                ]
+            }
+        ],
+        "ResponseMetadata": {
+            "RequestId": "dabff43f-6cce-4660-8600-b04c6e2fd6ea",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "content-type": "text/xml;charset=UTF-8",
+                "content-length": "2095",
+                "vary": "accept-encoding",
+                "date": "Thu, 16 May 2019 17:06:49 GMT",
+                "server": "AmazonEC2"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeVolumes_1.json b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeVolumes_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeVolumes_1.json
@@ -0,0 +1,46 @@
+{
+    "status_code": 200,
+    "data": {
+        "Volumes": [
+            {
+                "Attachments": [],
+                "AvailabilityZone": "us-west-2a",
+                "CreateTime": {
+                    "__class__": "datetime",
+                    "year": 2017,
+                    "month": 3,
+                    "day": 6,
+                    "hour": 21,
+                    "minute": 50,
+                    "second": 37,
+                    "microsecond": 143000
+                },
+                "Encrypted": true,
+                "KmsKeyId": "arn:aws:kms:us-west-2:644160558196:key/68425528-9938-4a15-90f2-f1755263b836",
+                "Size": 8,
+                "SnapshotId": "",
+                "State": "available",
+                "VolumeId": "vol-069d75193c497b8aa",
+                "Iops": 100,
+                "Tags": [
+                    {
+                        "Key": "test",
+                        "Value": "test"
+                    }
+                ],
+                "VolumeType": "gp2"
+            }
+        ],
+        "ResponseMetadata": {
+            "RequestId": "a65cf257-c79f-4212-b604-37426556c99a",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "content-type": "text/xml;charset=UTF-8",
+                "content-length": "951",
+                "date": "Thu, 16 May 2019 17:06:37 GMT",
+                "server": "AmazonEC2"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeVolumes_2.json b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeVolumes_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_copy_related_resource_tag_multi_ref/ec2.DescribeVolumes_2.json
@@ -0,0 +1,46 @@
+{
+    "status_code": 200,
+    "data": {
+        "Volumes": [
+            {
+                "Attachments": [],
+                "AvailabilityZone": "us-west-2a",
+                "CreateTime": {
+                    "__class__": "datetime",
+                    "year": 2017,
+                    "month": 3,
+                    "day": 6,
+                    "hour": 21,
+                    "minute": 50,
+                    "second": 37,
+                    "microsecond": 143000
+                },
+                "Encrypted": true,
+                "KmsKeyId": "arn:aws:kms:us-west-2:644160558196:key/68425528-9938-4a15-90f2-f1755263b836",
+                "Size": 8,
+                "SnapshotId": "",
+                "State": "available",
+                "VolumeId": "vol-069d75193c497b8aa",
+                "Iops": 100,
+                "Tags": [
+                    {
+                        "Key": "test",
+                        "Value": "test"
+                    }
+                ],
+                "VolumeType": "gp2"
+            }
+        ],
+        "ResponseMetadata": {
+            "RequestId": "d904226e-6707-46c2-99b8-ae7bb27b8de1",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "content-type": "text/xml;charset=UTF-8",
+                "content-length": "951",
+                "date": "Thu, 16 May 2019 17:06:38 GMT",
+                "server": "AmazonEC2"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/test_tags.py b/tests/test_tags.py
--- a/tests/test_tags.py
+++ b/tests/test_tags.py
@@ -21,6 +21,7 @@
 
 from c7n.tags import universal_retry, coalesce_copy_user_tags
 from c7n.exceptions import PolicyExecutionError, PolicyValidationError
+from c7n.utils import yaml_load
 
 from .common import BaseTest
 
@@ -316,3 +317,51 @@ def test_copy_related_resource_tag_validate(self):
             ]
         }
         self.assertRaises(PolicyValidationError, self.load_policy, policy)
+
+    def test_copy_related_resource_tag_multi_ref(self):
+        session_factory = self.replay_flight_data('test_copy_related_resource_tag_multi_ref')
+        client = session_factory().client('ec2')
+
+        result = client.describe_volumes()['Volumes']
+        self.assertEqual(len(result), 1)
+        vol = result[0]
+
+        self.assertEqual(vol['Tags'], [{'Key': 'test', 'Value': 'test'}])
+
+        policy = """
+        name: copy-tags-from-ebs-volume-to-snapshot
+        resource: ebs-snapshot
+        filters:
+          - type: value
+            key: Tags
+            value: empty
+        actions:
+          - type: copy-related-tag
+            resource: ebs
+            skip_missing: True
+            key: VolumeId
+            tags: '*'
+        """
+
+        p = self.load_policy(yaml_load(policy), session_factory=session_factory)
+
+        resources = p.run()
+
+        self.assertEqual(len(resources), 3)
+
+        if self.recording:
+            time.sleep(10)
+
+        all_snaps = client.describe_snapshots(OwnerIds=['self'])['Snapshots']
+
+        self.assertEqual(len(all_snaps), 3)
+
+        tagged_snaps = [e for e in all_snaps if e['VolumeId'] == vol['VolumeId']]
+        untagged_snaps = [e for e in all_snaps if e['VolumeId'] != vol['VolumeId']]
+
+        self.assertEqual(len(tagged_snaps), 2)
+        self.assertEqual(tagged_snaps[0]['Tags'], vol['Tags'])
+        self.assertEqual(tagged_snaps[1]['Tags'], vol['Tags'])
+
+        self.assertEqual(len(untagged_snaps), 1)
+        self.assertTrue('Tags' not in untagged_snaps[0].keys())