👁️
pierreinside
  • Introduction
  • Workbench
    • VirtualBox
    • Linux
      • Linux-Paketverwaltung
      • Linux Initialisierung
      • Ubuntu 14.10 LTS
      • Ubuntu 16.04 LTS
      • Ubuntu 18.04 LTS
      • Ubuntu 20.04 LTS
      • Ubuntu - Netzwerk
    • Konsole
      • ssh
      • zsh
      • cygwin
      • Babun
      • terminator
      • Terminal Multiplexer
      • Linux Tools
    • awesome
    • Entwicklungsumgebungen
      • Texteditors
      • Visual Studio Code
      • IntelliJ - IDEA
  • Softwareentwicklungsprozess
    • Schätzungen
    • Eventstorming
    • OKR
  • Architektur
    • Uncle Bob
    • Microservices
    • NoSQL
      • ElasticSearch
    • Hystrix
    • Reactive Programming
    • AngularJS
    • Service Mesh
  • Networking
    • Dependency Injection
  • Programming
    • Java Core/EE
      • Java 8
      • Java Annotationen
      • Bean Validation
      • Enterprise Java Beans Specification
      • Dependency Injection
    • JRebel
    • Webservices
      • HTTP
      • REST
      • Spring MVC REST
      • Swagger
      • Postman
    • Spring Ecosystem
      • Spring Core
      • Spring Boot
        • Programming
        • Production Ready
        • Testing
      • Spring Cloud
      • Spring Cloud Config
      • Spring MVC
      • Spring Data
      • Spring Petclinic
    • NodeJS
    • UI-Technologie
      • Thymeleaf
      • ionic
      • Web Fonts
      • Jinja Templates
      • Twitter Bootstrap
    • Python Ecosystem
      • Python Libraries
      • Python Testing
      • Python Best-Practices
      • Python Snippets
      • Python Selenium
      • Kivy UI
      • FastAPI
      • Typer CLI
      • Django
    • Groovy
    • Persistenz
      • Transactions
        • Java TX
        • JPA TX
      • TX Handling
      • JPA
        • Eclipse Link
      • MySQL
        • MySQL Performance
        • Docker MySQL
      • Hazelcast
    • Glassfish
    • YAML
    • Angular
    • Camel
    • Zeichenkodierung
    • Kinder lernen Programmieren
  • Testen
    • Easymock
    • Mockito
  • Performance & Scalability
    • Java Performance
      • Heapdump Analysis
    • Java Concurrency
    • Instana
  • Sicherheit
    • Authentifizierung
      • OpenID Connect
      • Web-Authentication API
    • Authorisierung
      • OAuth
      • SAML
    • Spring Security
    • Zertifikate
    • Kali Linux
    • VPN
    • Zero-Trust-Networks
  • Build und Deployment
    • Maven
    • Bamboo
    • Jenkins
      • Jenkins Pipelines
      • Jenkins Pipelines Tips und Tricks
      • Jenkins-configuration-as-Code
      • Jenkins IDE
    • Travis CI
    • Shellprogrammierung
      • jq - JSON Parsing
    • Konfiguration Management
    • Vagrant
      • Vagrant-Ansible-Integration
      • Vagrant Box bauen
    • Ansible
      • Getting Started
      • Ansible Details
    • Saltstack
    • LinuxKit
    • Container
      • Docker
        • Docker Getting Started
        • Debugging Docker
        • Docker Build
        • Docker Registry
        • Docker run
          • docker run
          • docker network
        • Docker Compose
        • docker machine
        • Docker@Windows
        • Docker Host
        • Docker Scaling
        • Docker Ressources
        • Docker Logging
        • windowsContainer
      • Cloud Deployment Provider
        • AWS
          • Anwendungsdeployment
          • Workload
          • Permissions
          • Netzwerke
          • AWS CLI
            • aws-vault
          • RDS
          • Static Website Hosting
          • EKS - Elastic Kubernetes Service
          • S3
        • Google Cloud Platform
      • Docker Orchestrierung
        • CoreOS
        • Kubernetes
          • microK8s
          • minikube
          • autoscaler
          • Docker
          • k9s
        • Nomad
    • PHP
  • Operations
    • Proxy
      • NGINX
    • DNS
    • Logging
      • Graylog
      • Fluentd
    • Monitoring
      • Grafana
    • Infrastructure-as-Code
      • Terraform
        • AWS-Provider
        • GitHub-Provider
      • Packer
    • Deployment
      • Vault
      • Consul
        • Consul Template
      • Fabio
  • Rechtliches
    • Software-Lizenzen
  • Git Ecosystem
    • Git
      • Git Lifecycle Hooks
    • GitHub
      • GitHub Organizations
    • GitHub Actions
    • GitHub Pages
    • GitHub CLI
    • GitHub Copilot
    • GitHub-AWS OIDC
    • GitBook
    • GitLab
    • Bitbucket/Stash
  • Publishing
    • WordPress
    • Markdown
    • Static Site Generators
      • Hugo
      • Jekyll
    • Tiddly Wiki
    • Leanpub
    • Animationsfilme
  • Storage
    • Synology 2012
    • Synology 2021
  • Collaboration
    • Übersicht
    • Microsoft Teams
  • Konferenzen
    • Velocity Berlin 2019
  • IT mit Kindern
    • Projekt Sportstracker
    • Scratch
    • Pico Spielekonsole
  • Schule
    • Mathematik
  • Misc
    • Foto/Video
      • Foto/Video Sammlung bis 2023
        • Handbrake
        • Onedrive
      • Foto/Video Sammlung ab 2024
      • Gopro
      • Panasonic FZ1000 ii
        • als Webcam
      • AV Receiver
      • Videos erstellen
        • OBS Studio
        • Touch Portal
        • Game-Streaming
      • Kameratasche
      • Kamera 2020
    • Handy
      • 2016
      • 2018
      • 2019
      • 2021
      • 2022
    • Computer
      • Laptop
        • 2018
        • Chromebook
      • Monitor
        • 4k
      • Software
        • Command Line Interface
        • Google API
        • Plant UML
        • Chromium
        • Passwort-Manager
        • GPG
      • Dell CNF 2665 Farbdrucker
      • Dockingstation
      • Gaming PC 2021
      • Mobiles Büro
      • Mobiles Internet
      • Mobiler Router
    • Beamer Benq W1000+
    • Spielekonsole
      • 2017
        • Playstation 4
      • Pico Spielekonsole
    • Gadgets
      • iPad Pro 2015 und 2016
      • iPad Air 2024
      • Macbook Pro
      • Smartwatch
      • Slate
      • Mudi
    • Fahrrad
      • Jonas 2018
      • SQLab
    • Auto
      • Auto 2022
      • Camping
        • Camping Touren Ideen
          • Camping Tour - Gardasee 2021
        • Camper
          • Camper klein - keine Stehhöhe
            • VW Bus Erfahrungen
          • Camper gross - Stehhöhe
    • Haus
      • Klimaanlage
      • Swimming Pool
      • Quick Mill Orione 3000
      • Spülmaschine 2021
      • Hebe-Schiebetür
      • Gasgrill
      • Minibar / Mini-Kühlschrank
      • Glasfaseranschluss (Fiber-to-the-Home)
      • Smart-Home
        • Raspberry Pi
        • Heimnetzwerk
      • Homeoffice
      • Energie
        • Solar
        • Wärmepumpe
    • Freizeit
      • Musik Streaming
      • Sky
      • Online Lernplattformen
      • eScooter - ePowerFun
    • Fußball
      • Meine Arbeit als Fußball-Trainer
      • Fußball Tools
      • DFB Talentförderung
    • Google Impact Challenge
  • Englisch
Powered by GitBook
On this page
  • GitHub-AWS OIDC
  • Nachteil von Passwörtern
  • Konzeptuell
  • GitHub Implementierung
  • Lösung OIDC
  • Konfiguration in AWS
  • GitHub Workflow
  • Bewertung
  • Trennung Role vs GitHub Workflow
  • Ist das Beispiel sicher?
  • Wo wird denn die Identität des Callers geprüft?

Was this helpful?

  1. Git Ecosystem

GitHub-AWS OIDC

GitHub-AWS OIDC

Mit OIDC (basierend auf der OAuth Idee) lässt sich eine Authentifizierung und Authorisierung ganz ohne Passwörter bewerkstelligen. Grundprinzip von OAuth:

OAuth 2 versucht die Komplexität aus den Clients rauszuhalten und in die Server zu verlagern. Für den Enduser (z. B. Applikationsentwickler) wird es dadurch einfacher. Die Konfiguration erfolgt ZENTRAL (das ist der Vorteil hinsichtlich Sicherheit) im Backend.

Hierbei geht GitHub als OIDC-Identity-Provider eine Trust-Beziehung mit AWS ein ... die Authentifizierung wandert von AWS nach GitHub, d. h. solange GitHub die Identität des Nutzers bestätigt, erteilt AWS dem Nutzer die im Vertrag konfigurierten Zugriffsberechtigung. Somit kommt ein Nutzer (führt einen GitHub Workflow aus) ohne Passwort aus ... zudem können die Berechtigungen zentral von einem anderen Team geregelt werden.


Nachteil von Passwörtern

Konzeptuell

  • unsicher (gleiche, zu einfache)

  • long-lived

  • werden selten geändert

  • häufig personengebunden ... was natürlich schlecht ist, wenn eine Person mal nicht mehr dabei ist aber sein Passwort in automatisierten Prozessen verwendet wird (und damit dann auch ungültig wird) => Prozesse brechen

  • müssen dann evtl. noch zusätzlich in einem Passwort-Store hinterlegt werden

  • müssen manchmal geändert werden

  • man verliert den Überblick wo sie überall verwendet werden und wo sie dann auch geändert werden müssen

GitHub Implementierung

GitHub kennt zwar das Konzept der Secrets ... allerdings haben Secrets gewisse Schwachstellen. Sie können gestohlen werden, die bleiben häufig immer gleich (Abhilfe Rotation). Ein typisches Beispiel aus dem GitHub Alltag:

Shared Workflows brauchen manchmal Zugriff auf AWS Ressourcen (z. B. man hat das GitHub-Setup über Terraform implementiert und hosted den Terraform State in S3). Shared Workflows haben keinen separaten Secret Space, sondern müssen die Secrets von den Callern bekommen, d. h. die Secrets müssen entweder direkt in den Repos des Callers liegen oder von der GitHub Organisation an die Repos propagiert werden. Dadurch können ALLE Workflows des Repositories (nicht nur der Shared-Workflow) diese Secrets in nicht dafür vorgesehenen Workflows verwenden (sie können sie nicht im Klartext auslesen). Das funktioniert dann auf ALLEN Branches ... also auch auf Feature-Branches, die evtl. nicht unter 4-eyes Prinzip (Pull-Request-Enforcement) stehen. Somit könnte ein Angreifer die Secrets vollkommen unbemerkt verwendem.


Lösung OIDC

  • YouTube - Connecting GitHub Actions To AWS Using OIDC

  • YouTube - Securely deploy to AWS with GitHub Actions and OIDC

  • GitHub - Configuring OpenID Connect in Amazon Web Services

  • AWS - About security hardening with OpenID Connect

Bei der Authentifizierung gibt es zwei wesentliche Beteiligte - am Beispiel eines typischen Szenario (GitHub => AWS) aus dem Bereich des Software-Deployments "Workflow A möchte ein Deployment auf AWS ausführen":

  • GitHub Workflow, der den Zugriff erhalten möchte (Caller)

  • AWS als Resource Owner gewährt den Zugriff auf die Protected Resource

Typisch ist, dass es zwei unterschiedliche Systeme sind, die

  • Authorisierung i. a. unterschiedlich abgebildet haben (unterschiedliche Modelle/Granularitäten)

  • von unterschiedlichen Firmen oder Gruppen verwaltet werden

Die Lösung von OIDC sieht folgendermassen aus:

der GitHub Workflow fragt bei SEINEM Authorization Server (= GitHub OIDC Identity Provider) nach einem bestimmten Zugriff auf ein Zielsystem (= Context) für einen bestimmten Use-Case (= Claim) an, z. B. "ich will eine Lambda-Funktion in AWS auf Produktion deployen"

  • wenn GitHub den User identifiziert hat, dann stellt es einen signierten Token (JWT - enthält die Claims = ) aus, so dass

    • AWS die Rechtmäßigkeit der Anfrage über die Signatur prüfen kann ... AWS prüft also, ob die Anfrage vom trusted GitHub-OIDC-Provider kommt

    • AWS die Claims (Nutzungsszenario) prüfen kann

  • ist alles in Ordnung, dann stelle AWS einen kurzlebigen AWS Token aus, mit dem der Workflow Zugriff auf die Protected AWS Ressourcen erhält

Konfiguration in AWS

  • StratusGrid - Connecting GitHub Actions To AWS Using OIDC

  • Configuring a role for GitHub OIDC identity provider

In AWS wird im Bereich IAM ein OIDC-Provider für GitHub hinzugefügt - man braucht diesen Provider nur einmal pro AWS-Account zu definieren:

  • GitHub Identity Provider URL: https://token.actions.githubusercontent.com

    • daraufhin wird ein sog. Thumbprint ausgegeben

    • diesen Thumbprint ist der Public-Key, den GitHub zur Signierung des Json-Web-Token (JWT) verwendet

      • damit prüft AWS also, ob der JWT tatsächlich echt ist (= von GitHub kommt)

  • Audience: sts.amazonaws.com

    • diese Information wird als Claim im JWT von GitHub mitgegeben

Anschließend muss man noch eine Trust-Relationship (wer darf es nutzen) und Berechtigungen, die beide in einer IAM-Role (basierend auf einer CustomTrustPolicy) abgebildet sind:

  • mit Trusted entity (= wer darf sie nutzen)

    • aud, sub sind sog. Claims, die mehr Kontext zum Request bereitstellen ... Liste aller unterstützten Claims

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "sts:AssumeRoleWebIdentity",
          "Principal": {                                                  // wer is der Ausführende
                                                                          // ... das ist technisch gesehen der OIDC-Provider
            "Federated": 
              "arn:aws:iam:<MY_AWS_ACCOUNT>:oidc-provider/token.actions.githubusercontent.com"
          },
          "Condition": {
            "StringLike": {
              "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",             // Ziel der API Calls
              "token.actions.githubusercontent.com:sub": "repo:mobi3006/myrepo/*"         // Quelle der API Calls
                                                                                          // ... GitHub Workflow
                                                                                          //     ... all branches
            }
          }
        }
      ]
    }
  • Permissions eingepackt in eine IAM-Role ... was darf der Nutzer dieser Rolle?

    • am besten macht man gleich zu Beginn ein "Deny" auf "sts:AssumeRole", um ein Ausbrechen aus DIESER Rolle zu verhindern (und damit Tür und Tor zu öffnen)

    • danach kommen die minimalen Permissions

In Terraform sieht das Ganze dann so in etwa aus:

resource "aws_iam_oidc_identity_provider" "github_identity_provider" {
  url                = "https://token.actions.githubusercontent.com"
  thumbprint_list    = ["abc123"]                                   # Replace with the thumbprint of GitHub's certificate
  client_id_list     = ["sts.amazonaws.com"]
}

# 
resource "aws_iam_role" "github_role" {
  name               = "GitHubRole"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "${aws_iam_oidc_identity_provider.github_identity_provider.arn}"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "${aws_iam_oidc_identity_provider.github_identity_provider.url}:sub": "repo:mobi3006/myrepo/*"
        }
      }
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "github_role_policy" {
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"            # Berechtigungen
  role       = aws_iam_role.github_role.name
}

In obigem Beispiel sieht man immer wieder sts ... letztlich ist es der Security Token Service (aka STS), der das temporäre Token ausstellt, mit dem sich der GitHub Workflow authentifiziert.

GitHub Workflow

  • About security hardening with OpenID Connect

In der GitHub Organisation muss gar nichts mehr konfiguriert werden ... es funktioniert out-of-the-box mit den mit den Werten, die wir in AWS benutzt haben.

Allerdings müssen die Workflows die angelegte Rolle noch nutzen, um die von AWS im OAuth-Flow ausgestellten AWS-Credentials (in Form eines kurzlebigen Tokens) zu nutzen.

Permissions

jobs:
  my-job:
    permissions:
      id-token: write     # Required to fetch a OpenID Connect (OIDC) token
      contents: read      # Required for actions/checkout

configure-aws-credentials

- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/gh-actions-role-myrepo-deploy
    aws-region: ${{ env.AWS_REGION }}

Final Result

Workflow mobi3006/myrepo/.github/.workflows/my-workflow.yml:

on:
  workflow_dispatch:
jobs:
  my-job:
    permissions:
      id-token: write     # Required to fetch a OpenID Connect (OIDC) token
      contents: read      # Required for actions/checkout
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/gh-actions-role-myrepo-deploy
          aws-region: ${{ env.AWS_REGION }}
      - name: get caller identity ... for testing access
        run: |
          aws sts get-caller-identity

Wie man hier schön sieht ... es werden keine Secrets gebraucht, weil alles in der Trust-Beziehung im Backend über die IAM-Role gh-actions-role-myrepo-deploy abgebildet ist (Trusted Entity = dieser Workflow PLUS Permissions).


Bewertung

Trennung Role vs GitHub Workflow

Wenn wir nicht gerade in einem kleinen Startup sind, dann werden die Berechtigungen innerhalb eines AWS Accounts von einem anderen Team gemanaged als von den DevOps-Leuten eines Teams, das ein Deployment implementieren will.

Insofern hat man hier schon zwangsläufig eine explizite Diskussion (Vier-Augen-Prinzip) und kann das Least-Priviliges-Prinzip einhalten.

Ist das Beispiel sicher?

Man sieht, dass man nur durch

role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/gh-actions-role-myrepo-deploy

die Berechtigung zur Nutzung der Rolle bekommt. Die Nutzung wird durch die Trusted Entity

"token.actions.githubusercontent.com:sub": "repo:mobi3006/myrepo/*"

eingeschränkt. Doch dann darf doch jeder Workflow aus diesem Repository die Rolle assumen - will man das? Was ist wenn dort jemand seinen Code einschmuggelt indem er er einen Feature-Branch (steht i. a. nicht unter Protection, d. h. jeder kann hier Code bereitstellen) mit einem schädlichen Workflow einschleust. Wir haben das doch nicht unter Kontrolle. Insofern ist das Beispiel nicht unbedingt sicher.

Das stimmt und wir sollten das einschränken. Hierzu bietet GitHub Environments mit Protection Rules. Ein Environment definiert das Ziel eines Deployments (z. B. production, development). Deployments werden natürlich mit einem GitHub Workflow umgesetzt. Mit einer Protection Rule kann man ein Approval (4-eyes Principle) durch bestimmte Engineers einfordern und so Änderungen am AWS Account kontrollieren. Ausserdem kann man einschränken, dass ein Deployment-Workflow aus einem Protected-Branch kommen muss (damit stehen Code-Änderungen evtl. unter Approval-Schutz).

Werden weitere Secrets benötigt, so können die - statt sie an die Organisation oder Repository zu hängen - einem Environment zugeordnet werden. Erst wenn alle Required Checks erfüllt sind (z. B. Approval), werden die Secrets zur Nutzung freigeschaltet.

Wo wird denn die Identität des Callers geprüft?

GitHub wird den Request eine AWS Rolle einzunehmen mit seinem privaten Key signieren und steht somit mit seinem Namen dafür gerade, dass es sich um einen validen Request aus "seinem" Ecosystem handelt. Das schließt natürlich nicht aus, dass es sich dabei nicht doch um eine unrechtmäßige Nutzung handelt. Das wiederum muss das Trust-Entity auf Seite von AWS prüfen ... hier werden die rechtmäßigen Nutzer (z. B. ein Environment eines Repositories) eingeschränkt.

Deploy-Environments

GitHub unterstützt sog. Environments für Deployments (und dabei handelt es sich ja dann, wenn man Änderungen an einem AWS Account vornehmen will).

In der Trust-Relationship der AWS-IAM-Rolle kann man die Nutzung auch auf Environments einschränken (im Beispiel auf das Environment mit dem Namen Production):

"${aws_iam_oidc_identity_provider.github_identity_provider.url}:sub": "repo:mobi3006/myrepo:environment:Production"
PreviousGitHub CopilotNextGitBook

Last updated 1 year ago

Was this helpful?

github-aws-oidc-sketch.png