Просмотр исходного кода

Scope the tag half of the AWS image search to the calling account

AWSImageService.find issues two describe_images calls for a label, one
filtered on name and one on tag:Name, and neither was scoped by Owners.

The tag:Name half can only ever match images in the calling account. AMI
tags are not visible across accounts, so an image owned by anyone else
cannot satisfy the filter however it is tagged - asking EC2 for every
image carrying any visible tag, unscoped across a whole region, returns
only this account's. Omitting Owners therefore never widened what that
search could find; it only made EC2 evaluate the filter against the entire
public catalogue. Measured in ap-southeast-1 against a real tagged AMI:
10.0s unscoped against 0.1s scoped, returning the same single image.

The name half is left alone. Image names are a public attribute and
searching them across public images is the documented behaviour and the
common case, so it keeps working without an owners argument. An explicit
owners still overrides both halves.

This is the smaller of two compounding effects behind the AWS integration
suite's runtime. The other is that _get_paginated_results uses the
caller's result limit as the transport page size, so a small limit walks a
large scan in tiny increments - 977.6s at page size 5 against 10.0s at
1000, for the same query. That is a separate fix.
Nuwan Goonasekera 12 часов назад
Родитель
Сommit
3aaceedb17
2 измененных файлов с 32 добавлено и 1 удалено
  1. 17 0
      CHANGELOG.rst
  2. 15 1
      cloudbridge/providers/aws/services.py

+ 17 - 0
CHANGELOG.rst

@@ -1,3 +1,20 @@
+4.4.0 - unreleased
+------------------
+
+## Fixes
+* **``AWSImageService.find`` no longer scans every public image to run its
+  tag search.** ``find(label=...)`` issues two ``describe_images`` calls, one
+  filtered on ``name`` and one on ``tag:Name``, and neither was scoped by
+  ``Owners``. The ``tag:Name`` half can only ever match images in the calling
+  account - AMI tags are not visible across accounts, so an image owned by
+  anyone else cannot satisfy the filter however it is tagged - so omitting
+  ``Owners`` never widened what it could find. It only made EC2 evaluate the
+  filter against the whole regional catalogue: measured in ap-southeast-1,
+  10.0s unscoped against 0.1s scoped, for identical single-image results.
+  The ``name`` half is unchanged and still searches public images, which is
+  what most callers want; an explicit ``owners`` argument still overrides
+  both.
+
 4.3.1 - August 2, 2026 (sha 8fabc1e2d3916e2c100bdb18075f2caa3bd38b38)
 ---------------------------------------------------------------------
 

+ 15 - 1
cloudbridge/providers/aws/services.py

@@ -806,8 +806,22 @@ class AWSImageService(BaseImageService):
             log.debug("Searching for AWS Image Service %s", label)
             obj_list.extend(
                 self.svc.find(filters={'name': label}, **extra_args))
+            # A tag filter can only ever match images in the calling account.
+            # AMI tags are not visible across accounts, so an image owned by
+            # anyone else can never satisfy tag:Name however it is tagged -
+            # asking for every image carrying any visible tag, unscoped across
+            # a whole region, returns only this account's. Leaving Owners off
+            # therefore does not widen what the search can find; it only makes
+            # EC2 evaluate the filter against every public image in the
+            # region. Measured in ap-southeast-1, identical single-image
+            # results in 10.0s unscoped against 0.1s scoped.
+            #
+            # An explicit owners argument still wins, so a caller can ask for
+            # someone else's images and get the same (empty) answer as before.
+            tag_args = dict(extra_args)
+            tag_args.setdefault('Owners', ['self'])
             obj_list.extend(
-                self.svc.find(filters={'tag:Name': label}, **extra_args))
+                self.svc.find(filters={'tag:Name': label}, **tag_args))
         return ClientPagedResultList(self.provider, obj_list)
 
     # Intentionally extends the base list() with a leading filter_by_owner