Skip to content

Commit

Permalink
community-ci workflow: prevent injection
Browse files Browse the repository at this point in the history
  • Loading branch information
alafanechere committed Apr 22, 2024
1 parent 5f1e4e6 commit 13ff71d
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 204 deletions.
104 changes: 0 additions & 104 deletions .github/actions/airbyte-ci-requirements/action.yml

This file was deleted.

10 changes: 8 additions & 2 deletions .github/actions/install-airbyte-ci/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,26 @@ inputs:
description: "Path to airbyte-ci source"
required: false
default: airbyte-ci/connectors/pipelines
is_fork:
description: "Whether the PR is from a fork"
required: false
default: "false"
runs:
using: "composite"
steps:
- name: Get changed files
uses: tj-actions/changed-files@v39
if: inputs.is_fork == 'false'
id: changes
with:
files_yaml: |
pipelines:
- '${{ inputs.path_to_airbyte_ci_source }}/**'
- name: Determine how Airbyte CI should be installed
- name: "[NON FORK] Determine how Airbyte CI should be installed"
shell: bash
id: determine-install-mode
if: inputs.is_fork == 'false'
run: |
if [[ "${{ github.ref }}" != "refs/heads/master" ]] && [[ "${{ steps.changes.outputs.pipelines_any_changed }}" == "true" ]]; then
echo "Making changes to Airbyte CI on a non-master branch. Airbyte-CI will be installed from source."
Expand All @@ -34,7 +40,7 @@ runs:
- name: Install Airbyte CI from binary
id: install-airbyte-ci-binary
if: steps.determine-install-mode.outputs.install-mode == 'binary'
if: steps.determine-install-mode.outputs.install-mode == 'binary' || ${{ inputs.is_fork }} == 'true'
shell: bash
run: |
curl -sSL ${{ inputs.airbyte_ci_binary_url }} --output airbyte-ci-bin
Expand Down
22 changes: 10 additions & 12 deletions .github/actions/run-airbyte-ci/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ inputs:
description: "GCP credentials for GCP Secret Manager"
required: false
default: ""
git_repo_url:
description: "Git repository URL"
default: https://github.com/airbytehq/airbyte.git
required: false
git_branch:
description: "Git branch to checkout"
required: false
Expand Down Expand Up @@ -79,7 +83,10 @@ inputs:
python_registry_token:
description: "Python registry API token to publish python package"
required: false

is_fork:
description: "Whether the PR is from a fork"
required: false
default: "false"
runs:
using: "composite"
steps:
Expand All @@ -88,16 +95,6 @@ runs:
shell: bash
run: echo "name=start-timestamp=$(date +%s)" >> $GITHUB_OUTPUT

- name: Check if PR is from a fork
id: check-if-pr-is-from-fork
if: github.event_name == 'pull_request'
shell: bash
run: |
if [ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]; then
echo "PR is from a fork. Exiting workflow..."
exit 78
fi
- name: Docker login
id: docker-login
uses: docker/login-action@v3
Expand All @@ -110,14 +107,15 @@ runs:
uses: ./.github/actions/install-airbyte-ci
with:
airbyte_ci_binary_url: ${{ inputs.airbyte_ci_binary_url }}

is_fork: ${{ inputs.is_fork }}
- name: Run airbyte-ci
id: run-airbyte-ci
shell: bash
run: |
airbyte-ci --disable-update-check --disable-dagger-run --is-ci --gha-workflow-run-id=${{ github.run_id }} ${{ inputs.subcommand }} ${{ inputs.options }}
env:
CI_CONTEXT: "${{ inputs.context }}"
CI_GIT_REPO_URL: ${{ inputs.git_repo_url }}
CI_GIT_BRANCH: ${{ inputs.git_branch || github.head_ref }}
CI_GIT_REVISION: ${{ inputs.git_revision || github.sha }}
CI_GITHUB_ACCESS_TOKEN: ${{ inputs.github_token }}
Expand Down
123 changes: 48 additions & 75 deletions .github/workflows/community_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,20 @@ concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}

on:
workflow_dispatch:
inputs:
test-connectors-options:
description: "Options to pass to the 'airbyte-ci connectors test' command"
default: "--modified"
pull_request_target:
paths:
- "airbyte-integrations/connectors/**"
jobs:
determine_runner_environment:
determine_environment:
runs-on: ubuntu-latest
name: Determine runner and environment
name: Determine environment
steps:
# Checkout is required here to:
# - fetch the local actions stored in .github/actions
# - install airbyte-ci in dev mode if the PR modified airbyte-ci
- name: Checkout Airbyte
uses: actions/checkout@v3
with:
# This checkouts the fork
# /!\ untrusted code
# It's deemed safe as the following step is not executing code from forks
ref: ${{ github.head_ref }}
# Ensures that the git token is not persisted
# It helps prevent access to token from code executed in the workflow
persist-credentials: false
fetch-depth: 1

# Disabling this step for safety during the spike
# - name: Get CI runner
# id: get_ci_runner
# uses: ./.github/actions/airbyte-ci-requirements
# with:
# runner_type: "test"
# runner_size: "large"
# airbyte_ci_command: "connectors test"
# is_fork: ${{ github.event.pull_request.head.repo.fork }}

# We set the environment to community-ci if the PR is from a fork
# The community-ci environment requires manual reviewer approval to run
# This is a safety measure to prevent untrusted code from running on our infrastructure
# The internal-ci environment is reserved for internal PRs (non-forked PRs)
- name: Determine environment
id: determine_environment
if: github.event_name == 'pull_request_target'
shell: bash
run: |
if [ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]; then
Expand All @@ -62,68 +33,70 @@ jobs:
echo "environment=internal-ci" >> $GITHUB_OUTPUT
fi
outputs:
environment: ${{ steps.get_ci_runner.outputs.environment }}
runner_name: ci-runner-connector-test-large-dagger-0-9-6
#runner_name: ${{ steps.get_ci_runner.outputs.runner_name }}
environment: ${{ steps.determine_environment.outputs.environment }}

connectors_ci_on_fork:
name: Connectors CI on fork
needs: determine_environment
if: needs.determine_environment.outputs.environment == 'community-ci'
environment: ${{ needs.determine_environment.outputs.environment }}
runs-on: community-connector-test-large
timeout-minutes: 180 # 3 hours
env:
GITHUB_HEAD_REF: ${{ github.head_ref }}
MAIN_BRANCH_NAME: "augustin/04-18-community-ci_workflow_prevent_injection"
# TODO
#MAIN_BRANCH_NAME: "master"

connectors_ci:
name: Connectors CI
needs: determine_runner_environment
environment: ${{ needs.determine_runner_environment.outputs.environment }}
runs-on: ${{ needs.determine_runner_environment.outputs.runner_name }}
timeout-minutes: 1440 # 24 hours
steps:
- name: Checkout Airbyte
uses: actions/checkout@v3
- name: Checkout Fork
uses: actions/checkout@v4
with:
# This can checkouts forks
# /!\ untrusted code
# It's deemed safe as the community-ci environment requires manual reviewer approval to run
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.head_ref }}
fetch-depth: 1
- name: Extract branch name [WORKFLOW DISPATCH]
shell: bash
if: github.event_name == 'workflow_dispatch'
run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
id: extract_branch
- name: Fetch last commit id from remote branch [PULL REQUESTS]
if: github.event_name == 'pull_request_target'
# This will sync the .github folder of the main repo with the fork
# This allows us to use up to date actions from the main repo
- name: Sync .github with main
id: sync_github_with_main
run: |
git remote add main https://github.com/airbytehq/airbyte.git
git fetch main ${MAIN_BRANCH_NAME}
git checkout main/${MAIN_BRANCH_NAME} -- .github
- name: Fetch last commit id from remote branch
id: fetch_last_commit_id_pr
run: echo "commit_id=$(git ls-remote --heads origin ${{ github.head_ref }} | cut -f 1)" >> $GITHUB_OUTPUT
- name: Fetch last commit id from remote branch [WORKFLOW DISPATCH]
if: github.event_name == 'workflow_dispatch'
id: fetch_last_commit_id_wd
run: echo "commit_id=$(git rev-parse origin/${{ steps.extract_branch.outputs.branch }})" >> $GITHUB_OUTPUT
- name: Test connectors [WORKFLOW DISPATCH]
if: github.event_name == 'workflow_dispatch'
uses: ./.github/actions/run-airbyte-ci
with:
context: "manual"
dagger_cloud_token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }}
docker_hub_username: ${{ secrets.DOCKER_HUB_USERNAME }}
gcp_gsm_credentials: ${{ secrets.GCP_GSM_CREDENTIALS }}
sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }}
git_branch: ${{ steps.extract_branch.outputs.branch }}
git_revision: ${{ steps.fetch_last_commit_id_pr.outputs.commit_id }}
github_token: ${{ env.PAT }}
s3_build_cache_access_key_id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }}
s3_build_cache_secret_key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }}
subcommand: "connectors ${{ github.event.inputs.test-connectors-options }} test"
- name: Test connectors [PULL REQUESTS]
if: github.event_name == 'pull_request_target'
run: |
# Validation: Check if GITHUB_HEAD_REF contains only alphanumeric characters, hyphens, underscores or slashes
if [[ ! "$GITHUB_HEAD_REF" =~ ^[a-zA-Z0-9_/-]+$ ]]; then
echo "Invalid input: '${GITHUB_HEAD_REF}'. Only alphanumeric characters, hyphens, underscores or slashes are allowed."
exit 1
fi
# Sanitization: Remove any characters that are not alphanumeric, hyphens, underscores, or slashes
sanitized_head_ref=$(echo "$GITHUB_HEAD_REF" | tr -cd '[:alnum:]-_/')
echo "commit_id=$(git ls-remote --heads origin '${sanitized_head_ref}' | cut -f 1)" >> $GITHUB_OUTPUT
- name: Run airbyte-ci connectors test
uses: ./.github/actions/run-airbyte-ci
with:
# TODO remove this once the community-ci environment is fully operational
airbyte_ci_binary_url: https://storage.googleapis.com/dev-airbyte-cloud-connector-metadata-service/airbyte-ci/releases/ubuntu/3570293/airbyte-ci
context: "pull_request"
dagger_cloud_token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }}
docker_hub_username: ${{ secrets.DOCKER_HUB_USERNAME }}
gcp_gsm_credentials: ${{ secrets.GCP_GSM_CREDENTIALS }}
sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }}
git_repo_url: ${{ github.event.pull_request.head.repo.clone_url }}
git_branch: ${{ github.head_ref }}
git_revision: ${{ steps.fetch_last_commit_id_pr.outputs.commit_id }}
github_token: ${{ env.PAT }}
s3_build_cache_access_key_id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }}
s3_build_cache_secret_key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }}
subcommand: "connectors --modified test"
is_fork: ${{ github.event.pull_request.head.repo.fork }}
is_fork: "true"
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ async def connectors(
ctx.obj["diffed_branch"],
ctx.obj["is_local"],
ctx.obj["ci_context"],
ctx.obj["git_repo_url"],
)
)

Expand Down
4 changes: 3 additions & 1 deletion airbyte-ci/connectors/pipelines/pipelines/cli/airbyte_ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from pipelines.dagger.actions.connector.hooks import get_dagger_sdk_version
from pipelines.helpers import github
from pipelines.helpers.git import get_current_git_branch, get_current_git_revision
from pipelines.helpers.utils import get_current_epoch_time
from pipelines.helpers.utils import AIRBYTE_REPO_URL, get_current_epoch_time


def log_context_info(ctx: click.Context) -> None:
Expand All @@ -47,6 +47,7 @@ def log_context_info(ctx: click.Context) -> None:
main_logger.info("Running airbyte-ci in CI mode.")
main_logger.info(f"CI Context: {ctx.obj['ci_context']}")
main_logger.info(f"CI Report Bucket Name: {ctx.obj['ci_report_bucket_name']}")
main_logger.info(f"Git Repo URL: {ctx.obj['git_repo_url']}")
main_logger.info(f"Git Branch: {ctx.obj['git_branch']}")
main_logger.info(f"Git Revision: {ctx.obj['git_revision']}")
main_logger.info(f"GitHub Workflow Run ID: {ctx.obj['gha_workflow_run_id']}")
Expand Down Expand Up @@ -146,6 +147,7 @@ def is_current_process_wrapped_by_dagger_run() -> bool:
@click.option("--enable-update-check/--disable-update-check", default=True)
@click.option("--enable-auto-update/--disable-auto-update", default=True)
@click.option("--is-local/--is-ci", default=True)
@click.option("--git-repo-url", default=AIRBYTE_REPO_URL, envvar="CI_GIT_REPO_URL")
@click.option("--git-branch", default=get_current_git_branch, envvar="CI_GIT_BRANCH")
@click.option("--git-revision", default=get_current_git_revision, envvar="CI_GIT_REVISION")
@click.option(
Expand Down
Loading

0 comments on commit 13ff71d

Please sign in to comment.