Repository: ansible-collections/community.aws

Issue:
ecr option scan_on_push
##### SUMMARY
ecr module does not support `--image-scanning-configuration` option.

##### ISSUE TYPE
- Feature Idea

##### COMPONENT NAME
ecs_ecr



Discussion:

Resolving patch:
diff --git a/plugins/modules/ecs_ecr.py b/plugins/modules/ecs_ecr.py
--- a/plugins/modules/ecs_ecr.py
+++ b/plugins/modules/ecs_ecr.py
@@ -58,12 +58,12 @@
         type: str
     lifecycle_policy:
         description:
-            - JSON or dict that represents the new lifecycle policy
+            - JSON or dict that represents the new lifecycle policy.
         required: false
         type: json
     purge_lifecycle_policy:
         description:
-            - if yes, remove the lifecycle policy from the repository
+            - if yes, remove the lifecycle policy from the repository.
         required: false
         default: false
         type: bool
@@ -74,6 +74,14 @@
         choices: [present, absent]
         default: 'present'
         type: str
+    scan_on_push:
+        description:
+            - if yes, images are scanned for known vulnerabilities after being pushed to the repository.
+            - I(scan_on_push) requires botocore >= 1.13.3
+        required: false
+        default: false
+        type: bool
+        version_added: 1.3.0
 author:
  - David M. Lee (@leedm777)
 extends_documentation_fragment:
@@ -132,6 +140,7 @@
 - name: set-lifecycle-policy
   community.aws.ecs_ecr:
     name: needs-lifecycle-policy
+    scan_on_push: yes
     lifecycle_policy:
       rules:
         - rulePriority: 1
@@ -355,6 +364,25 @@ def purge_lifecycle_policy(self, registry_id, name):
                 return policy
             return None
 
+    def put_image_scanning_configuration(self, registry_id, name, scan_on_push):
+        if not self.check_mode:
+            if registry_id:
+                scan = self.ecr.put_image_scanning_configuration(
+                    registryId=registry_id,
+                    repositoryName=name,
+                    imageScanningConfiguration={'scanOnPush': scan_on_push}
+                )
+            else:
+                scan = self.ecr.put_image_scanning_configuration(
+                    repositoryName=name,
+                    imageScanningConfiguration={'scanOnPush': scan_on_push}
+                )
+            self.changed = True
+            return scan
+        else:
+            self.skipped = True
+            return None
+
 
 def sort_lists_of_strings(policy):
     for statement_index in range(0, len(policy.get('Statement', []))):
@@ -378,6 +406,7 @@ def run(ecr, params):
         image_tag_mutability = params['image_tag_mutability'].upper()
         lifecycle_policy_text = params['lifecycle_policy']
         purge_lifecycle_policy = params['purge_lifecycle_policy']
+        scan_on_push = params['scan_on_push']
 
         # Parse policies, if they are given
         try:
@@ -474,6 +503,13 @@ def run(ecr, params):
                     result['policy'] = policy_text
                     raise
 
+            original_scan_on_push = ecr.get_repository(registry_id, name)
+            if original_scan_on_push is not None:
+                if scan_on_push != original_scan_on_push['imageScanningConfiguration']['scanOnPush']:
+                    result['changed'] = True
+                    result['repository']['imageScanningConfiguration']['scanOnPush'] = scan_on_push
+                    response = ecr.put_image_scanning_configuration(registry_id, name, scan_on_push)
+
         elif state == 'absent':
             result['name'] = name
             if repo:
@@ -510,7 +546,8 @@ def main():
         purge_policy=dict(required=False, type='bool', aliases=['delete_policy'],
                           deprecated_aliases=[dict(name='delete_policy', date='2022-06-01', collection_name='community.aws')]),
         lifecycle_policy=dict(required=False, type='json'),
-        purge_lifecycle_policy=dict(required=False, type='bool')
+        purge_lifecycle_policy=dict(required=False, type='bool'),
+        scan_on_push=(dict(required=False, type='bool', default=False))
     )
     mutually_exclusive = [
         ['policy', 'purge_policy'],


Test patch:
diff --git a/tests/integration/targets/ecs_ecr/tasks/main.yml b/tests/integration/targets/ecs_ecr/tasks/main.yml
--- a/tests/integration/targets/ecs_ecr/tasks/main.yml
+++ b/tests/integration/targets/ecs_ecr/tasks/main.yml
@@ -1,22 +1,18 @@
 ---
-- set_fact:
-    ecr_name: '{{ resource_prefix }}-ecr'
+- module_defaults:
+    group/aws:
+        region: "{{ aws_region }}"
+        aws_access_key: "{{ aws_access_key }}"
+        aws_secret_key: "{{ aws_secret_key }}"
+        security_token: "{{ security_token | default(omit) }}"
 
-- block:
-
-    - name: set connection information for all tasks
-      set_fact:
-        aws_connection_info: &aws_connection_info
-          aws_access_key: "{{ aws_access_key }}"
-          aws_secret_key: "{{ aws_secret_key }}"
-          security_token: "{{ security_token }}"
-          region: "{{ aws_region }}"
-      no_log: yes
+  block:
+    - set_fact:
+        ecr_name: '{{ resource_prefix }}-ecr'
 
     - name: When creating with check mode
       ecs_ecr:
         name: '{{ ecr_name }}'
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -32,7 +28,6 @@
       ecs_ecr:
         registry_id: 999999999999
         name: '{{ ecr_name }}'
-        <<: *aws_connection_info
       register: result
       ignore_errors: true
 
@@ -46,7 +41,6 @@
     - name: When creating a repository
       ecs_ecr:
         name: '{{ ecr_name }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should change and create
@@ -64,7 +58,6 @@
     - name: When creating a repository that already exists in check mode
       ecs_ecr:
         name: '{{ ecr_name }}'
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -78,7 +71,6 @@
     - name: When creating a repository that already exists
       ecs_ecr:
         name: '{{ ecr_name }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should not change
@@ -91,7 +83,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         purge_policy: yes
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -106,7 +97,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         policy: '{{ policy }}'
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -122,7 +112,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         policy: '{{ policy }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should change and not create
@@ -136,7 +125,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         delete_policy: yes
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -153,7 +141,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         purge_policy: yes
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -170,7 +157,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         purge_policy: yes
-        <<: *aws_connection_info
       register: result
 
     - name: it should change and not create
@@ -184,7 +170,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         policy: '{{ policy | to_json }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should change and not create
@@ -198,7 +183,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         policy: '{{ policy }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should not change
@@ -209,7 +193,6 @@
     - name: When omitting policy on a repository that has a policy
       ecs_ecr:
         name: '{{ ecr_name }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should not change
@@ -222,7 +205,6 @@
         name: '{{ ecr_name }}'
         policy: '{{ policy }}'
         purge_policy: yes
-        <<: *aws_connection_info
       register: result
       ignore_errors: true
 
@@ -236,7 +218,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         policy: "Ceci n'est pas une JSON"
-        <<: *aws_connection_info
       register: result
       ignore_errors: true
 
@@ -250,7 +231,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         purge_lifecycle_policy: yes
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -265,7 +245,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         lifecycle_policy: '{{ lifecycle_policy }}'
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -281,7 +260,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         lifecycle_policy: '{{ lifecycle_policy }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should change and not create
@@ -297,7 +275,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         purge_lifecycle_policy: yes
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -313,7 +290,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         purge_lifecycle_policy: yes
-        <<: *aws_connection_info
       register: result
 
     - name: it should change and not create
@@ -327,7 +303,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         lifecycle_policy: '{{ lifecycle_policy | to_json }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should change and not create
@@ -341,7 +316,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         lifecycle_policy: '{{ lifecycle_policy }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should not change
@@ -353,7 +327,6 @@
     - name: When omitting lifecycle policy on a repository that has a policy
       ecs_ecr:
         name: '{{ ecr_name }}'
-        <<: *aws_connection_info
       register: result
 
     - name: it should not change
@@ -367,7 +340,6 @@
         name: '{{ ecr_name }}'
         lifecycle_policy: '{{ lifecycle_policy }}'
         purge_lifecycle_policy: yes
-        <<: *aws_connection_info
       register: result
       ignore_errors: true
 
@@ -381,7 +353,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         lifecycle_policy: "Ceci n'est pas une JSON"
-        <<: *aws_connection_info
       register: result
       ignore_errors: true
 
@@ -397,7 +368,6 @@
         lifecycle_policy:
           rules:
             - invalid: "Ceci n'est pas une rule"
-        <<: *aws_connection_info
       register: result
       ignore_errors: true
 
@@ -411,7 +381,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         state: absent
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -427,7 +396,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         state: absent
-        <<: *aws_connection_info
       register: result
 
     - name: it should change
@@ -440,7 +408,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         state: absent
-        <<: *aws_connection_info
       register: result
       check_mode: yes
 
@@ -455,7 +422,6 @@
       ecs_ecr:
         name: '{{ ecr_name }}'
         state: absent
-        <<: *aws_connection_info
       register: result
 
     - name: it should not change
@@ -466,10 +432,6 @@
     - name: When creating an immutable repository
       ecs_ecr:
         name: '{{ ecr_name }}'
-        region: '{{ ec2_region }}'
-        ec2_access_key: '{{ec2_access_key}}'
-        ec2_secret_key: '{{ec2_secret_key}}'
-        security_token: '{{security_token}}'
         image_tag_mutability: immutable
       register: result
 
@@ -488,10 +450,6 @@
     - name: When configuring an existing immutable repository to be mutable in check mode
       ecs_ecr:
         name: '{{ ecr_name }}'
-        region: '{{ ec2_region }}'
-        ec2_access_key: '{{ec2_access_key}}'
-        ec2_secret_key: '{{ec2_secret_key}}'
-        security_token: '{{security_token}}'
         image_tag_mutability: mutable
       register: result
       check_mode: yes
@@ -506,10 +464,6 @@
     - name: When configuring an existing immutable repository to be mutable
       ecs_ecr:
         name: '{{ ecr_name }}'
-        region: '{{ ec2_region }}'
-        ec2_access_key: '{{ec2_access_key}}'
-        ec2_secret_key: '{{ec2_secret_key}}'
-        security_token: '{{security_token}}'
         image_tag_mutability: mutable
       register: result
 
@@ -522,10 +476,6 @@
     - name: When configuring an already mutable repository to be mutable
       ecs_ecr:
         name: '{{ ecr_name }}'
-        region: '{{ ec2_region }}'
-        ec2_access_key: '{{ec2_access_key}}'
-        ec2_secret_key: '{{ec2_secret_key}}'
-        security_token: '{{security_token}}'
         image_tag_mutability: mutable
       register: result
 
@@ -534,10 +484,58 @@
         that:
           - result is not changed
 
+    - name: enable scan on push in check mode
+      ecs_ecr:
+        name: '{{ ecr_name }}'
+        scan_on_push: yes
+      check_mode: yes
+      register: result
+
+    - name: it should change
+      assert:
+        that:
+          - result is skipped
+          - result is changed
+
+    - name: enable scan on push
+      ecs_ecr:
+        name: '{{ ecr_name }}'
+        scan_on_push: yes
+      register: result
+
+    - name: it should change
+      assert:
+        that:
+          - result is changed
+          - result.repository.imageScanningConfiguration.scanOnPush
+
+    - name: verify enable scan on push
+      ecs_ecr:
+        name: '{{ ecr_name }}'
+        scan_on_push: yes
+      register: result
+
+    - name: it should not change
+      assert:
+        that:
+          - result is not changed
+          - result.repository.imageScanningConfiguration.scanOnPush
+
+    - name: disable scan on push
+      ecs_ecr:
+        name: '{{ ecr_name }}'
+        scan_on_push: no
+      register: result
+
+    - name: it should change
+      assert:
+        that:
+          - result is changed
+          - not result.repository.imageScanningConfiguration.scanOnPush
+
   always:
 
     - name: Delete lingering ECR repository
       ecs_ecr:
         name: '{{ ecr_name }}'
         state: absent
-        <<: *aws_connection_info