Wie man Geheimnisse in Bitbucket handhabt

secrets

Sensible Daten wie Passwörter, API-Tokens und DB-Zugangsdaten sind für die Projektentwicklung und das Testen unerlässlich, sollten aber niemals im Klartext im Repository gespeichert werden. In diesem Abschnitt erklären wir, wie WATA Factory diese Geheimnisse mit Hilfe von Bitbuckets eingebauten Funktionen verwaltet: Repository-Variablen und Deployment-Variablen.

Um eine dieser Lösungen zu nutzen, benötigst du lediglich Schreibrechte. Für die Einrichtung von Variablen jeglicher Art sind jedoch Admin-Rechte erforderlich. Wenn du mehr technische Informationen benötigst, kannst du diesen Artikel lesen.

Cypress ist eine der Referenzen von WATA Factory für automatisierte Test-Frameworks, daher werden wir ein Cypress-Projekt als Beispiel verwenden, obwohl dieser Ansatz in jedem Projekt mit einer anderen Technologie verwendet werden kann.

In diesem Projekt haben wir einen Verweis auf die Datei credentials.ts in der cypress.config.ts. Wenn wir unsere automatisierten Tests in der Pipeline ausführen wollen, müssen wir die Datei credentials.ts im Repo haben, sonst schlägt die Pipeline fehl. Wir wissen bereits, dass dies keine gute Praxis ist, also wie können wir das beheben?

Eingabe der Szene-Repository-Variablen. Mit dieser nativen Bitbucket-Funktion können wir definierte Variablen in unseren Pipelines referenzieren und sie nach Belieben verwenden.

Unsere Lösung besteht aus diesen zwei einfachen Schritten:

  1. Erstellen der Variablen in Bitbucket
  2. Erstellen der temporären credentials.ts Datei
  3. Kopieren des Inhaltes der Variable in unsere temporäre Datei
  4. FERTIG! Unser Projekt hat bereits die benötigte Datei mit all unseren Geheimnissen!

Repository-Variablen

Nehmen wir an, unsere Datei credential.ts hat die folgende Struktur:

export const USERS = {
    admin: {
      username: 'admin',
      password: 'adminPassword',
    },
    regularuser: {
      username: 'justAnUser',
      password: 'regularPassword',
    },
  };
   
export const DB_CREDENTIALS = {
    host: 'your-server.com',
    user: 'dbUser',
    password: 'anotherPassword',
    database: 'my_sample_db',
    port: 1234,
  };

Und unsere Datei cypress.config.ts muss sie importieren, um diese Anmeldedaten zu verwenden:

import { DB_CREDENTIALS } from './cypress/properties/credentials';

//my DB connection
const connections: Record<string, any> = {
  atDashboard: {
    host: DB_CREDENTIALS.host,
    user: DB_CREDENTIALS.user,
    password: DB_CREDENTIALS.password,
    database: DB_CREDENTIALS.database,
    port: DB_CREDENTIALS.port,
  }
};

Variablen können eine ganze json-Datei sein, wenn wir wollen, also kopieren wir den Inhalt unserer credentials.ts-Datei und gehen zu ‚Repository settings > Repository variables‘ in unserem Repo.

Geheimnisse
Geheimnisse

Hier müssen wir nur einen Namen für unsere Variable eingeben, den Inhalt unserer Datei einfügen und auf Hinzufügen klicken. Wenn du möchtest, dass diese Anmeldeinformationen verschlüsselt und in den Build-Protokollen verborgen werden, kannst du die Option „Sicher“ aktivieren, aber Achtung: du kannst dann den Inhalt nicht mehr sehen und die Variable nicht mehr bearbeiten, sondern nur einen neuen Wert eingeben oder sie löschen.

Sobald wir die Variable eingerichtet haben, müssen wir nur noch „$“ verwenden, um unsere Variable aufzurufen und die Echo-Ausgabe mit dem Befehl „>“ innerhalb unserer Pipeline umzuleiten. Im Stammverzeichnis Ihres Projekts musst du eine bitbucket-pipeline.yml haben:

image: cypress/base:20.11.0

definitions:
  steps:
    - step: &install-and-check
        name: Installation and Static Analysis
        caches:
          - node
        script:
          - npm install
        artifacts:
          - node_modules/**
    - step: &test
        name: Run tests with coverage
        caches:
          - node
        script:
          - npm run test -- --coverage
          - node_modules/.bin/cypress install --force
          - echo $OUR_CREDENTIALS > ./cypress/properties/credentials.ts
          - node_modules/.bin/cypress run --component --env coverage=true
          - node_modules/.bin/cypress run --env PLUGIN_ENABLED=false
          ...

Mit diesem Befehl erstellen wir eine temporäre Datei mit dem Inhalt unserer Variablen. Auf diese Weise ist die Anmeldedatei nach der Ausführung der Pipeline verschwunden

echo $VARIABLE > ./your/path/filename.ts

Variablen für den Einsatz:

Um die Bedürfnisse unserer Kunden zu erfüllen und ausgezeichnete Qualität zu liefern, benötigen wir bei WATA Factory verschiedene Umgebungen, von der Entwicklungsphase bis zur Produktion, ohne dabei die dringend benötigte Testumgebung zu vergessen. Verschiedene Umgebungen erfordern verschiedene Anmeldeinformationen oder andere Arten von Flags. Um dieses Problem zu lösen, bietet Bitbuckets Bereitstellungsvariablen.

Diese Variablen funktionieren auf die gleiche Weise wie Repository-Variablen, aber du musst in der Pipeline angeben, auf welche Umgebung sie sich beziehen.

Erstelle einfach die Variable für die Bereitstellung:

  1. Gehe zu ‚Repository-Einstellungen > Einsätze‘.
  2. Erstelle eine neue Umgebung in dem gewünschten Bereich (Test, Staging oder Produktion).
  3. Füge eine neue Variable auf die gleiche Weise wie bei den Repository-Variablen hinzu
  4. Gib in deiner Step-Pipeline an, auf welche Umgebung sie sich beziehen:

image: cypress/base:20.11.0

definitions:
  steps:
    - step: &install-and-check
        name: Installation and Static Analysis
        caches:
          - node
        script:
          - npm install
        artifacts:
          - node_modules/**
    - step: &test
        name: Run tests with coverage
        caches:
          - node
        script:
          - npm run test -- --coverage
          - node_modules/.bin/cypress install --force
          - echo $CREDENTIALS > ./cypress/properties/credentials.ts
          - node_modules/.bin/cypress run --component --env coverage=true
          - node_modules/.bin/cypress run --env PLUGIN_ENABLED=false
        artifacts:
          - coverage/**
          - coverage-component/**
          - cypress-image-diff-html-report/**
          - cypress-image-diff-screenshots/**
    - step: &sonar
        name: SonarQube analysis
        image: sonarsource/sonar-scanner-cli:latest
        script:
          - sonar-scanner -Dsonar.projectKey=Gesa-Dashboard---Angular -Dsonar.host.url=$SONAR_URL -Dsonar.login=$SONAR_SECRET -Dsonar.javascript.lcov.reportPaths=coverage/lcov.info,coverage-component/lcov.info
    - step: &deploy
        name: Deploy
        script:
          - npm run build -- --base-href /dashboard_ang/ --output-hashing=all --aot --configuration=$DEPLOYMENT_PROFILE
          - ssh $FTP_USERNAME@$FTP_HOST -p222 'mkdir -p ~/public_html/dashboard_ang'
          - scp -P 222 -r dist/new_angular_poc/browser/* $FTP_USERNAME@$FTP_HOST:~/public_html/dashboard_ang/

pipelines:
  branches:
    develop:
      - step:
          <<: *install-and-check
      - step:
          deployment: automatictesting
          <<: *test
      - step:
          <<: *sonar
  custom:
    deploy-company1-dev:
      - step:
          <<: *install-and-check
      - step:
          name: Deploy to Company 1
          deployment: company1
          <<: *deploy
    deploy-at:
      - step:
          <<: *install-and-check
      - step:
          name: Deploy to AT
          deployment: automatictesting
          <<: *deploy

Wie du sehen kannst, legen wir im Abschnitt Pipelines die Umgebung und den Schritt fest, der verwendet werden soll. Der Name des Schritts wird weiter oben definiert.

Eine wichtige Warnung: Wenn du eine Bereitstellungsvariable mit demselben Namen wie eine Repository-Variable benennst, wird der Wert überschrieben.