Blog

Temporäre AWS-Anmeldeinformationen generieren

Martijn van Dongen

Aktualisiert Oktober 21, 2025
7 Minuten

Für unser Produkt Instruqt bauen wir Herausforderungen, um die AWS-Technologie zu erlernen. Die Benutzer von instruqt benötigen einen temporären Zugang, um ihre Ressourcen in AWS zu erstellen, zu aktualisieren und zu zerstören. Wir möchten den Benutzern das Gefühl geben, ein eigenes AWS-Konto zu haben. Zugriffsschlüssel zur Verwendung in der CLI oder dem programmatischen Zugriff und der Management-Konsole im Browser. Dieser Blogbeitrag beschreibt, wie Sie ein AWS-Konto für diese Nutzung vorbereiten und wie Sie temporäre Zugriffsschlüssel und einen magischen Link zur Verwaltungskonsole generieren und verwenden.

Voraussetzungen

  • AWS-Konto. Sie benötigen ein AWS-Konto mit einem Benutzer und Zugriffsschlüsseln mit Berechtigungen zum Auflisten, Lesen, Erstellen, Aktualisieren und Löschen von IAM-Gruppen, Benutzern, Rollen und Richtlinien.
  • Terraform. Sie müssen Terraform installiert haben.
  • Python. Stellen Sie sicher, dass Sie eine aktuelle Python-Version mit pip haben. Auf einem Mac empfehle ich diese Einstellung.
  • AWS CLI. Installieren Sie die AWS CLI mit pip. (pip install awscli --upgrade --user)
  • Keybase. Installieren und erstellen Sie ein Keybase-Konto(keybase.io/)

Rollen und Föderation

Neben allgemeinen Entitäten wie Benutzern und Gruppen bietet AWS auch "Rollen". Eine Rolle in AWS kann z.B. einem Server zugewiesen werden, der der auf dem Server laufenden Software den Zugriff auf AWS-Ressourcen ermöglicht. Eine Rolle kann auch von einem Benutzer übernommen werden, wodurch er Zugriff auf die Ressourcen erhält. Auch bekannt als "Föderation". Eine Rolle enthält zwei Arten von Richtlinien. Eine Richtlinie, die den Typ des Dienstes beschreibt, der die Rolle übernehmen darf (eine ec2-Instanz oder ein AWS-Konto mit Benutzern). Die andere Richtlinie beschreibt die Berechtigungsstufe für die angegebenen Ressourcen.
Für diesen Anwendungsfall erstellen wir eine Rolle, die von einem AWS IAM Benutzer übernommen werden kann. Ein einfaches Vertrauen reicht nicht aus, der Benutzer muss auch die Berechtigung haben, die Rolle mit AssumeRolePolicy zu übernehmen. Nachdem die Rolle übernommen wurde, werden die AccessPolicy-Berechtigungen vorübergehend an den Benutzer vergeben, indem eine Reihe von Schlüsseln gesendet wird.

+------------------+
|                  |
|       User       <-----------+
|                  |           |
+---------+--------+           |
          |                    |
          | AssumeRolePolicy   | TrustPolicy
          |                    |
+---------v--------+           |
|                  |           |
+       Role       +-----------+
|                  |
+---------+--------+
          |
          | AccessPolicy 
          |
+---------v--------+
|                  |
+     Resources    |
|                  |
+---------+--------+

Einrichtung

Für die Einrichtung von Benutzer, Rolle, Richtlinien usw. können Sie CloudFormation, Terraform, die CLI oder die Management-Konsole verwenden. In diesem Beispiel habe ich Terraform verwendet, aber Sie können dies einfach als Dokumentation verwenden, um es manuell oder mit CloudFormation zu tun.
Erstellen Sie unter Verwendung der folgenden Quelle. Sie müssen nichts ändern, aber es wird empfohlen, in der Terraform-Dokumentation nachzulesen, was genau passiert.

# CONFIGURATION AND PARAMETERS

variable "aws" {
  content = "Enter the aws profile to deploy."
}

variable "keybase" {
  content = "Enter the keybase profile to encrypt the secret_key (to decrypt: terraform output secret_key | base64 --decode | keybase pgp decrypt)"
}

variable "region" {
  default = "eu-west-1"
}

provider "aws" {
  profile    = "${var.aws}"
  region     = "${var.region}"
}

data "aws_caller_identity" "current" {}

# RESOURCES

resource "aws_iam_user" "instruqt" {
  name = "instruqt"
}

resource "aws_iam_access_key" "instruqt" {
  user = "${aws_iam_user.instruqt.name}"
  pgp_key = "keybase:${var.keybase}"
}

resource "aws_iam_user_policy" "instruqt_assume_role" {
  name = "test"
  user = "${aws_iam_user.instruqt.name}"

  policy = <<eof
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "sts:Assume*"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
EOF
}

resource "aws_iam_role" "S3AccessRole" {
  name = "InstruqtS3Access"
  assume_role_policy = <<eof
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "AWS": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "S3AccessPolicy" {
  name = "InstruqtS3AccessPolicy"
  role = "${aws_iam_role.S3AccessRole.id}"
  policy = <<eof
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:*"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
EOF
}

# OUTPUT

output "role_arn" {
  value = "${aws_iam_role.S3AccessRole.arn}"
}
output "access_key" {
  value = "${aws_iam_access_key.instruqt.id}"
}
output "secret_key" {
  value = "${aws_iam_access_key.instruqt.encrypted_secret}"
}

Setzen Sie den Stack mit den folgenden Befehlen ein. Wählen Sie eines der unter konfigurierten Profile aus. Halten Sie den Profilnamen und Ihren Keybase-Benutzernamen bereit, denn der Befehl apply wird Sie zur Eingabe dieser Werte auffordern.

terraform init
terraform apply

Wenn Terraform abgeschlossen ist, enthält die Ausgabe Zugangsschlüssel für die nächsten Schritte. Der geheime Schlüssel wird mit keybase verschlüsselt. Entschlüsseln Sie den generierten geheimen Schlüssel mit dem nächsten Befehl:

terraform output secret_key | base64 --decode | keybase pgp decrypt

Führen Sie die Python-Datei generate_keys.py aus

Installieren Sie zunächst die Abhängigkeiten, z.B. mit pip, anhand des folgenden Beispiels. Wenn Sie Fehlermeldungen über fehlende Abhängigkeiten erhalten, installieren Sie auch diese.

pip install requests boto3

Erstellen Sie eine Datei generate_keys.py mit der folgenden Quelle:

#!/usr/bin/env python
import os
import sys
import boto3
import json
import requests
import argparse
import ConfigParser
from botocore.exceptions import ClientError

def get_credentials_for_role(role_arn, session_name):
    sts = boto3.client('sts')
    try:
        response = sts.assume_role(RoleArn=role_arn, 
                                   RoleSessionName=session_name)
        return response['Credentials']
    except ClientError as e:
        sys.stderr.write('ERROR: %sn' % e.response['Error']['Message'])
        sys.exit(1)

def write_credentials(profile, credentials):
    filename = os.path.expanduser('~/.aws/credentials')
    dirname = os.path.dirname(filename)

    if not os.path.exists(dirname):
        os.makedirs(dirname)

    config = ConfigParser.ConfigParser()
    config.read(filename)
    if not config.has_section(profile):
        config.add_section(profile)
    config.set(profile, 'aws_access_key_id', credentials['AccessKeyId'])
    config.set(profile, 'aws_secret_access_key', credentials['SecretAccessKey'])
    config.set(profile, 'aws_session_token', credentials['SessionToken'])
    with open(filename, 'w') as fp:
        config.write(fp)

def generate_console_link(credentials):
    session = json.dumps({'sessionId': credentials['AccessKeyId'],
                          'sessionKey': credentials['SecretAccessKey'],
                          'sessionToken': credentials['SessionToken']})

    r = requests.get("https://signin.aws.amazon.com/federation",
                     params={'Action': 'getSigninToken',
                             'SessionDuration': 43200,
                             'Session': session})
    signin_token = r.json()

    console = requests.Request('GET',
                              'https://signin.aws.amazon.com/federation',
                              params={'Action': 'login',
                                      'Issuer': 'Instruqt',
                                      'Destination': 'https://console.aws.amazon.com/',
                                      'SigninToken': signin_token['SigninToken']})
    prepared_link = console.prepare()
    return prepared_link.url

if __name__ == '__main__':
    parser = argparse.ArgumentParser(content='generate keys')
    parser.add_argument("--output", "-o", required=False,
                        dest="output", help="output format", metavar="STRING",
                        default="json", choices=['link', 'json', 'write'])
    parser.add_argument("--role-arn", "-r", required=True,
                        dest="role_arn", help="to assume", metavar="STRING")
    parser.add_argument("--session-name", "-s", required=True,
                        dest="session_name", help="to use", metavar="STRING")

    options = parser.parse_args()
    credentials = get_credentials_for_role(options.role_arn, 
                                           options.session_name)

    if options.output == 'link':
        print generate_console_link(credentials)
    elif options.output == 'write':
        write_credentials(options.session_name, credentials)
    elif options.output == 'json':
        print(json.dumps({'AccessKeyId': credentials['AccessKeyId'],
                          'SecretAccessKey': credentials['SecretAccessKey'],
                          'SessionToken': credentials['SessionToken'],
                          'ConsoleMagicLink': generate_console_link(credentials)}))

Das Skript ./generate_keys.py benötigt 3 Parameter:

  • -session-name. Der Sitzungsname ist eine eindeutige ID des Benutzers, der die temporären Anmeldedaten verwenden wird. (Beispiel: martijn@binx.io)
  • -Rolle-arn. Die Rolle arn ist Teil der Ausgabe des Terraform-Skripts. (Beispiel: arn:aws:iam::AWS_ACCOUNT_ID:role/InstruqtS3Access). Sie können dies aus der Ausgabe von terraform kopieren.
  • -Output. Dies kann nur enthalten: json | write | link, die Standardausgabe ist json.
    generate_keys.py verwendet Boto (AWS SDK für Python). Es verwendet Umgebungsvariablen für Zugriffsschlüssel. Verwenden Sie das erste Beispiel oder kopieren Sie die access_key und role_arn Ausgabe von terraform, den entschlüsselten secret_key und ersetzen Sie die Beispielvariablen im zweiten Beispiel.
AWS_ACCESS_KEY_ID=$(terraform output access_key) 
AWS_SECRET_ACCESS_KEY=$(terraform output secret_key | base64 --decode | keybase pgp decrypt) 
python ./generate_keys.py --session-name identified@domain.ext 
                          --role-arn $(terraform output role_arn) 
                          --output json
AWS_ACCESS_KEY_ID=AKIA34K435KLR12KDT345 
AWS_SECRET_ACCESS_KEY=lk45hJSFkl35ADfsdDFtkl34fFADFhlktjrfaewr 
python ./generate_keys.py --session-name identified@domain.ext 
                          --role-arn arn:aws:iam::AWS_ACCOUNT_ID:role/InstruqtS3Access 
                          --output json

Wenn Sie einen Fehler erhalten, erscheint am Ende des Stack Trace die Meldung: "Das in der Anfrage enthaltene Sicherheits-Token ist ungültig." Das liegt wahrscheinlich daran, dass Sie die Werte von AWS_ACCESS_KEY_ID und AWS_SECRET_ACCESS_KEY nicht ersetzt haben.

Verwenden Sie die generierten temporären Schlüssel

Mit einem Browser

Öffnen Sie einen Browser und kopieren Sie den magischen Link "console_access". Sie werden automatisch eingeloggt.
  Temporäre AWS-Anmeldeinformationen generieren

Mit der CLI

Es gibt mehrere Möglichkeiten, die temporären Zugangsdaten zu verwenden. Um den Berechtigungsnachweis einmal hinzuzufügen und ihn bei den nächsten Befehlen einfach zu verwenden, erstellen Sie ein neues Profil in ~/.aws/credentials. Mit --output write wird der Abschnitt direkt in die Credentials-Datei geschrieben und kann verwendet werden.

aws s3 ls --profile tmpinstruqt

Programmatischer Zugang

Und Sie können diese Anmeldeinformationen natürlich für den programmatischen Zugriff verwenden. Dies ist nicht der empfohlene Weg, um Geheimnisse in Ihren Code einzufügen, sondern nur für dieses Beispiel hart kodiert.

import boto3
client = boto3.resource(
    's3',
    aws_access_key_id='ASIAL34H2K3423KL4JLKJLKJ',
    aws_secret_access_key='e0hvLM234LKJ23KDAdsf23DFAXiBrNu8Ht',
    aws_session_token='F4adsJL2sdafK3J42K3LJ4erg2K3J4....',
)
for bucket in client.buckets.all():
    print(bucket.name)

Letzte Worte

Jetzt ist alles eingerichtet und getestet, versuchen Sie nur noch, es zum Erfolg zu führen. Geben Sie den temporären Benutzern mehr Rechte, um andere Dinge als S3 zu tun, die neuen Schlüssel zu generieren und in der CLI, in Skripten oder über die Management-Konsole zu verwenden.
Um aufzuräumen, entfernen Sie einfach die temporären Anmeldeinformationen aus Ihrem und dem Terminal. Führen Sie terraform destroy aus, um die AWS-Einrichtung zu entfernen.
Sie können den Quellcode von github herunterladen: Generate temp aws credentials
Wenn Sie Fragen haben, können Sie mich gerne kontaktieren. Wir freuen uns über Ihr Feedback, das wir zur Verbesserung dieses Blogbeitrags und zukünftiger Beiträge verwenden werden.
NB. Vielen Dank an meinen Kollegen Mark van Holsteijn. Der Python-Code, der in der ersten Version verwendet wurde, wurde aus der AWS-Dokumentation kopiert. Er war nicht sehr sauber. Also haben wir ihn zu dem Skript umgestaltet, das jetzt in diesem Blogbeitrag verwendet wird. Das Skript hat uns auch zu neuen Blogbeiträgen inspiriert. Bleiben Sie also dran für Updates und ähnliche Dinge.

Verfasst von

Martijn van Dongen

Contact

Let’s discuss how we can support your journey.