Blog

Geheimnisse in AWS ECS Fargate

Martijn van Dongen

Aktualisiert Oktober 21, 2025
5 Minuten

Es gibt viele Möglichkeiten, 'Geheimnisse' in ECS und ECS Fargate zu verwenden. Meistens werden sie mit Hilfe von Umgebungsvariablen offengelegt, da dies vor einigen Jahren die einzige einfache Möglichkeit war. Heute haben wir zwei verbesserte Optionen. Sie können ein Tool zu Ihrem Docker-Container hinzufügen, das Ihre Geheimnisse abruft und entschlüsselt, bevor Sie sie an die Anwendung weitergeben. Die andere Möglichkeit besteht darin, das Abrufen und Entschlüsseln in die Anwendung einzubetten. Beide Ansätze werden in diesem Blogbeitrag behandelt. So werden wir vorgehen:

  1. Legen Sie ein Geheimnis in den SSM-Parameterspeicher
  2. Fügen Sie das Tool ssm-env zu Ihrem Dockerfile hinzu, um die Geheimnisse beim 'Booten' zu ersetzen
  3. Fügen Sie Ihrer Anwendung eine Logik zum Abrufen von Geheimnissen hinzu
  4. Hinzufügen eines Verweises auf das Geheimnis in Container-Umgebungsvariablen mit CloudFormation

1. Legen Sie ein Geheimnis im SSM Parameter Store ab

Diesmal fügen wir das Geheimnis manuell hinzu, z. B. im Falle eines mit Ihnen geteilten Api-Schlüssels eines Dritten. Sie können auch mit der CloudFormation-Erweiterung ein Geheimnis generieren, zum Beispiel wenn Sie ein Geheimnis generieren möchten, das niemand kennen soll, nicht einmal Sie selbst. (Vergessen Sie nicht, den Zugriff auf den SSM Parameter Store zu beschränken).

aws ssm put-parameter 
  --name my.little.secret 
  --type SecureString 
  --value "th15-1s-53cur3"

2. Fügen Sie das Tool ssm-env zu Ihrer Anwendung hinzu

Fügen Sie nun den folgenden Code zu Ihrer Dockerdatei hinzu. Er wird das in Golang geschriebene Tool ssm-env herunterladen und validieren. Um auf die AWS-APIs wie SSM zuzugreifen, müssen Sie Zertifikate installieren. Das vollständige Dockerfile finden Sie hier.

FROM alpine
# SSM Secret Sauce
RUN wget -O /usr/local/bin/ssm-env https://github.com/remind101/ssm-env/releases/download/v0.0.3/ssm-env
RUN echo "c944fc169d860a1079e90b03a8ea2c71f749e1265e3c5b66f57b2dc6e0ef84f8  /usr/local/bin/ssm-env" | sha256sum -c -
RUN chmod +x /usr/local/bin/ssm-env
RUN apk add —no-cache ca-certificates
ENTRYPOINT ["/usr/local/bin/ssm-env", "-with-decryption"]
# /SSM Secret Sauce

Es durchläuft alle Umgebungsvariablen und sucht nach dem Präfix ssm://. Wenn es gefunden wird, verwendet es die IAM-Rolle des Containers, um das Geheimnis abzurufen und ersetzt den Wert für das Geheimnis. Zum Beispiel:

MY_LITTLE_SECRET=ssm://my.secret
# becomes within the container
MY_LITTLE_SECRET=th15-1s-53cur3

3. Fügen Sie Ihrer Anwendung eine Logik zum Abrufen von Geheimnissen hinzu

In diesem Beispiel wird das öffentliche Docker-Image: mvandongen/alittlesecret verwendet, bei dem es sich lediglich um eine sehr einfache Python-Flask-Anwendung handelt. Im ersten Abschnitt wird das SSM-Geheimnis mithilfe des SDK abgerufen. Das Geheimnis im zweiten Teil ist bereits entschlüsselt. Dies wird wahrscheinlich für (Alt-)Anwendungen oder Anwendungen verwendet, die Sie nicht einfach ändern können.

from flask import Flask
import boto3
import os

app = Flask(__name__)

def ssm_secret(path, prefix = "ssm_sdk://"):
    client = boto3.client('ssm') # uses the container role
    prefix_len = len(prefix)
    if os.environ['SECRET_SDK'][0:prefix_len] == prefix:
        result = client.get_parameter(
            Name=os.environ['SECRET_SDK'][prefix_len:],
            WithDecryption=True
        )
        secret = result['Parameter']['Value']
    else:
        secret = os.environ['SECRET_SDK']
    return secret

@app.route("/")
def hello():
    # section 1: get the secret and decrypt it using the sdk
    secret = ssm_secret(
        os.environ['SECRET_SDK'],
        os.environ['SECRET_SDK_PREFIX']
    )
    section1 = "SDK decrypted: " + secret
    # section 2: get the already decrypted secret
    section2 = "ssn-env decrypted: " + os.environ['SECRET']
    return section1 + section2

app.run(host='0.0.0.0', port=80)

4. Fügen Sie in den Container-Umgebungsvariablen mit CloudFormation einen Verweis auf das Geheimnis hinzu

Lassen Sie uns diesen Fargate-Container mit CloudFormation bereitstellen. Er funktioniert in jeder öffentlichen VPC, auch in der Standard-VPC.

AWSTemplateFormatVersion: "2010-09-09"
Description: >
  "AWS Example Setup For Secrets in ECS / ECS Fargate"

Parameters:

  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: >
      "ID of the VPC to deploy the containers to."

  Subnets:
    Type: List<AWS::EC2::Subnet::Id>
    Description: >
      "IDs of the Subnets to deploy the containers to."

Resources:

  Cluster:
    Type: AWS::ECS::Cluster
    Properties: {}

  Service:
    Type: AWS::ECS::Service
    Properties:
      Cluster: !Ref Cluster
      TaskDefinition: !Ref 'TaskDefinition'
      DesiredCount: 1
      LaunchType: 'FARGATE'
      NetworkConfiguration:
        AwsvpcConfiguration:
          Subnets: !Ref 'Subnets'
          SecurityGroups:
            - !Ref SecurityGroup
          AssignPublicIp: 'ENABLED'

  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      NetworkMode: 'awsvpc'
      Cpu: '256'
      Memory: '512'
      ExecutionRoleArn: !Ref TaskRole
      TaskRoleArn: !Ref TaskRole
      RequiresCompatibilities:
        - FARGATE
      ContainerDefinitions:
        -
          Name: "asecretservice"
          Image: "mvandongen/asecretservice:latest"
          PortMappings:
            - ContainerPort: 80
          Environment:
            - Name: "SECRET"
              Value: "ssm://my.little.secret"
            - Name: "SECRET_SDK"
              Value: "ssm_sdk://my.little.secret"
            - Name: "SECRET_SDK_PREFIX"
              Value: "ssm_sdk://"
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-region: !Ref AWS::Region
              awslogs-group: !Ref LogGroup
              awslogs-stream-prefix: ecs

  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ecs-tasks.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess'
        - 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'

  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref 'VpcId'
      GroupDescription: "Public access to container"
      SecurityGroupIngress:
        - FromPort: 80
          ToPort: 80
          IpProtocol: 'tcp'
          CidrIp: "0.0.0.0/0"

  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "${AWS::StackName}"

Aufgrund der wenigen Parameter, die leicht auszuwählen sind, setzen wir den Stack über die Konsole ein. Wenn Sie möchten, können Sie auch den Cli verwenden.
Geheimnisse in AWS ECS Fargate
Suchen Sie nun die öffentliche IP-Adresse des Docker-Containers, der in Fargate läuft, und verwenden Sie curl oder einen Webbrowser, um die entschlüsselten Geheimnisse zu überprüfen. Versuchen Sie auch, die Geheimnisse in der AWS Management Console zu finden. Sie sind nicht in der CloudFormation-Konsole und nicht in der ECS Fargate-Konsole sichtbar. Sie sind nur im SSM Parameter Store sichtbar.

Fazit

In diesem Blogbeitrag haben wir ein Geheimnis im AWS SSM-Parameterspeicher erstellt und es in einem Docker-Container abgerufen, ohne es irgendwo in der Verwaltungskonsole offenzulegen. Durch die Verwendung des SDK stellt der Programmierer sicher, dass das Geheimnis nur dort abgerufen und verwendet wird, wo es benötigt wird. Das ist am sichersten.
Im zweiten Beispiel handelt es sich aus Sicht der Anwendung lediglich um eine Umgebungsvariable innerhalb des Containers. Wenn Sie alle Umgebungsvariablen preisgeben, geben Sie auch Ihr Geheimnis preis, was es weniger sicher macht.
Jetzt wird es wirklich einfach, Geheimnisse zu rotieren. Dazu ist nicht einmal eine Bereitstellung erforderlich.

  1. Aktualisieren Sie das Geheimnis im SSM-Parameterspeicher
  2. Beenden Sie Container auf elegante Weise
  3. Neue Container mit neuen Geheimnissen werden wiederhergestellt
    Wenn Sie so weit gekommen sind, sind Sie vielleicht auch daran interessiert, Geheimnisse in CloudFormation sicher zu verteilen oder zu speichern.

Verfasst von

Martijn van Dongen

Contact

Let’s discuss how we can support your journey.