In einem früheren Beitrag haben wir beschrieben, wie Repositorys unter Beibehaltung der vollständigen Git-Historie – einschließlich Branches, Tags und Submodul-Referenzen – von Bitbucket Cloud zu GitHub Cloud migriert wurden. Diese Migration schuf eine solide Grundlage, doch die reine Verlagerung der Repositorys ist nur ein Teil einer erfolgreichen Umstellung.

Dieser Artikel setzt die Reihe fort und befasst sich mit der sicheren Aktualisierung von Projektabhängigkeiten nach dem Umstieg auf GitHub. Die korrekte Handhabung der Abhängigkeiten ist entscheidend, um während des gesamten Migrationsprozesses stabile Builds und einen zuverlässigen Betrieb der CI-Pipelines zu gewährleisten.

Sobald die Repositorys eingerichtet sind, müssen alle projektbezogenen Abhängigkeiten überprüft und gegebenenfalls aktualisiert werden. In diesem Fall stützen sich die Projekte auf Yocto, einem Open-Source-Kooperationsprojekt, das Werkzeuge, Vorlagen und Methoden zur Erstellung benutzerdefinierter Linux-basierter Systeme für Embedded-Produkte auf verschiedenen Hardwarearchitekturen bereitstellt.

GitHub

Bei der Überprüfung der Abhängigkeiten haben wir festgestellt, dass mehrere Yocto-Rezepte auf den Git-Fetcher über HTTPS zurückgriffen, wobei die Anmeldedaten fest im Rezept eingebettet waren. Diese Anmeldedaten tauchten sowohl in der SRC_URI sowie in benutzerdefinierten Funktionen, die für das Klonen von Submodulen zuständig sind.

Ein vereinfachtes Beispiel für ein solches Rezept sah folgendermaßen aus:

DESCRIPTION = "Example Service for Embedded System"
LICENSE = "MIT"

BRANCH = "master"
SRC_URI = "git://bitbucket.org/organization/example_service.git;protocol=https;user=<username>:<hardcoded_token>;branch=${BRANCH}"
SRCREV = "<commit_hash>"

do_configure_prepend() {
    cd ${WORKDIR}/git

    # Clone submodule 1 using HTTPS and hardcoded token
    rm -rf submodule1
    git clone https://<username>:<hardcoded_token>@bitbucket.org/organization/submodule1.git submodule1
    cd submodule1
    git checkout <version>

    # Clone submodule 2 using HTTPS and hardcoded token
    cd ${WORKDIR}/git
    rm -rf submodule2
    git clone https://<username>:<hardcoded_token>@bitbucket.org/organization/submodule2.git submodule2
}

Dieser Ansatz birgt zahlreiche Risiken:

Für eine langfristige, skalierbare CI/CD-Umgebung ist diese Methode weder sicher noch zuverlässig.

Um die Sicherheit zu verbessern und eine nahtlose Automatisierung zu gewährleisten, wurden alle betroffenen Rezepte so aktualisiert, dass sie nun eine SSH-basierte Authentifizierung anstelle von HTTPS verwenden. Dadurch entfallen eingebettete Tokens, und die Rezepte lassen sich besser in automatisierte Build-Umgebungen integrieren.

Das aktualisierte Rezept sieht wie folgt aus:

DESCRIPTION = "Example Service for Embedded System"
LICENSE = "MIT"

BRANCH = "master"
SRC_URI = "git://git@github.com/organization/example_service.git;protocol=ssh;branch=${BRANCH}"
SRCREV = "<commit_hash>"

do_configure_prepend() {
    cd ${WORKDIR}/git

    # Clone submodule 1 securely over SSH
    rm -rf submodule1
    git clone git@github.com:organization/submodule1.git submodule1
    cd submodule1
    git checkout <version>

    # Clone submodule 2 securely over SSH
    cd ${WORKDIR}/git
    rm -rf submodule2
    git clone git@github.com:organization/submodule2.git submodule2
}

Mit dieser Änderung:

Um das Abrufen von Abhängigkeiten über SSH zu unterstützen, muss die CI-Umgebung Zugriff auf einen privaten SSH-Schlüssel haben. Wenn BitBake diese Rezepte ausführt, verwendet es diesen Schlüssel zur Authentifizierung bei GitHub für alle referenzierten Repositorys und Submodule.

Der entsprechende öffentliche Schlüssel muss einem GitHub-Konto zugeordnet sein, das Zugriff auf alle erforderlichen Repositorys hat.

Es ist wichtig zu beachten, dass ein einziger SSH-Schlüssel ausreicht. Solange das verknüpfte GitHub-Konto über die richtigen Berechtigungen verfügt, kann derselbe Schlüssel für mehrere Repositorys und Submodule verwendet werden.

Um Probleme bei der SSH-Authentifizierung zu vermeiden, sollte GitHub ebenfalls als vertrauenswürdiger Host konfiguriert werden:

ssh-keyscan github.com >> $HOME/.ssh/known_hosts

In dieser Konfiguration läuft der Build in einem Docker-Container, daher muss der Container das Verzeichnis ` .ssh` des Hosts einbinden . Dadurch kann BitBake bei Abrufvorgängen auf den SSH-Schlüssel zugreifen.

Nachfolgend finden Sie ein Beispiel für eine GitHub-Actions-Pipeline, die in diesem Szenario verwendet wird:

name: Build Embedded Project

on:
  push:
    branches:
      - master
      - 'release/*'
      - 'feature/*'
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

env:
  DOWNLOAD_DIR: /opt/build_dir
  BRANCH: ${{ github.ref_name }}

jobs:
  build:
    runs-on: [self-hosted, linux, x64]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      
      - name: Set up SSH key
        run: |
          mkdir -p $HOME/.ssh
          echo "${{ secrets.SSH_PRIVATE_KEY }}" > $HOME/.ssh/id_ed25519
          chmod 600 $HOME/.ssh/id_ed25519
          ssh-keyscan github.com >> $HOME/.ssh/known_hosts
          ssh -T git@github.com || true

      - name: Prepare build environment
        run: |
          make -f docker.mk cleanup DOWNLOAD_DIR=$DOWNLOAD_DIR

      - name: Build project
        run: |
          make -f docker.mk DOWNLOAD_DIR=$DOWNLOAD_DIR

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: project-build
          path: |
            $DOWNLOAD_DIR/output/*.tar.gz
            $DOWNLOAD_DIR/output/*.ipk

Im Schritt „SSH-Schlüssel einrichten“ ruft die Pipeline den privaten Schlüssel aus GitHub Secrets ab, konfiguriert GitHub als vertrauenswürdigen Host und überprüft die Authentifizierung. Dadurch wird sichergestellt, dass während des Builds sicher auf alle in den BitBake-Rezepten definierten Repositorys und Submodule zugegriffen werden kann.

Damit ist Teil 2 unserer Serie über die Migrationsreise abgeschlossen.

Im nächsten Beitrag konzentrieren wir uns auf die Modernisierung von CI/CD, indem wir bestehende Bash- und Jenkins-Pipelines auf GitHub Actions migrieren und so die gesamte Automatisierung in einem einzigen, standardisierten Workflow zusammenführen. Seien Sie gespannt auf Teil 3!

Weitere Blogbeiträge findest duhier.