Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/test_multi_arch_images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Test Multi-arch images

on:
schedule:
- cron: '0 */6 * * *' # runs every 6 hours
push:
branches: #
- '*'

permissions:
contents: read
id-token: write

jobs:
test_multi_arch:
runs-on: ubuntu-latest
environment:
name: plugin-development
strategy:
matrix:
platform:
- "linux/386"
- "linux/amd64"
- "linux/arm/v5"
- "linux/arm/v7"
- "linux/arm64/v8"
- "linux/ppc64le"
- "linux/riscv64"
- "linux/s390x"

steps:

- name: Checkout this repository
uses: actions/checkout@v4

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ secrets.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
role-to-assume: ${{ secrets.AWS_IAM_ROLE }}

- name: Test multi-arch image - ${{ matrix.platform }}
id: inspector
uses: aws-actions/vulnerability-scan-github-action-for-amazon-inspector@investigate_multi_arch
with:
artifact_type: 'container'
artifact_path: 'debian:trixie'
platform: ${{ matrix.platform }}
display_vulnerability_findings: "enabled"
sbomgen_version: "latest"

- name: Demonstrate SBOM Output (JSON)
run: cat ${{ steps.inspector.outputs.artifact_sbom }}

- name: Display scan results
run: cat ${{ steps.inspector.outputs.inspector_scan_results }}

- name: Validate multi-arch - ${{ matrix.platform }}
run: python3 validator/validate_multi_platform_image_support.py --platform "${{ matrix.platform }}" --sbom "${{ steps.inspector.outputs.artifact_sbom }}"


1 change: 1 addition & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ runs:
- --thresholds
- ${{ inputs.threshold_fixable_only == 'true' && '--threshold-fixable-only' || '--no-op' }}
- ${{ inputs.show_only_fixable_vulns == 'true' && '--show-only-fixable-vulns'|| '--no-op' }}
- --platform=${{ inputs.platform || '' }}
- --critical=${{ inputs.critical_threshold }}
- --high=${{ inputs.high_threshold }}
- --medium=${{ inputs.medium_threshold }}
Expand Down
74 changes: 74 additions & 0 deletions validator/validate_multi_platform_image_support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python3

import argparse
import json
import sys


def get_expected_arch(platform):
"""Map platform string to expected architecture value in SBOM"""
platform_to_arch = {
"linux/386": "386",
"linux/amd64": "amd64",
"linux/arm/v5": "arm",
"linux/arm/v7": "arm",
"linux/arm64/v8": "arm64",
"linux/ppc64le": "ppc64le",
"linux/riscv64": "riscv64",
"linux/s390x": "s390x"
}

if platform not in platform_to_arch:
raise ValueError(f"Unknown platform: {platform}")

return platform_to_arch[platform]


def extract_arch_from_sbom(sbom_file):
"""Extract architecture from SBOM metadata"""
try:
with open(sbom_file, 'r') as f:
sbom = json.load(f)

properties = sbom.get('metadata', {}).get('component', {}).get('properties', [])

for prop in properties:
if prop.get('name') == 'amazon:inspector:sbom_generator:image_arch':
return prop.get('value')

raise ValueError("Architecture property not found in SBOM")

except Exception as e:
raise ValueError(f"Failed to parse SBOM: {e}")


def main():
parser = argparse.ArgumentParser(description='Validate SBOM architecture matches expected platform')
parser.add_argument('--platform', required=True, help='Expected platform (e.g., linux/amd64)')
parser.add_argument('--sbom', required=True, help='Path to SBOM file')

args = parser.parse_args()

try:
expected_arch = get_expected_arch(args.platform)
actual_arch = extract_arch_from_sbom(args.sbom)

print(f"Platform: {args.platform}")
print(f"Expected arch: {expected_arch}")
print(f"Actual arch: {actual_arch}")

if actual_arch != expected_arch:
print(f" Architecture mismatch for platform {args.platform}")
print(f" Expected: {expected_arch}")
print(f" Found: {actual_arch}")
sys.exit(1)

print(f"Architecture validation passed: {actual_arch} matches expected {expected_arch}")

except Exception as e:
print(f"Validation failed: {e}")
sys.exit(1)


if __name__ == '__main__':
main()