Wir haben in einem vorheriger Artikel über Rewinds Nutzung des AWS SSM Session Managers und der zugehörigen IAM-Richtlinien, um Shell- und SSH-Tunnelzugriff auf AWS-Ressourcen zu ermöglichen. Wir haben außerdem ein kleines Tool zur Verfügung gestellt, das die Nutzung von SSM vereinfacht: aws-connect. Was aber, wenn wir Benutzern nur die Ausführung einer Teilmenge genehmigter Befehle erlauben möchten, anstatt ihnen vollen Shell-Zugriff auf eine EC2-Instanz zu gewähren? Dafür haben wir eine Lösung!
AWS-Systemmanager hat eine Funktion namens Befehle ausführen Damit können Sie Skripte oder Befehle auf EC2-Instanzen ausführen, die über die SSM-Agent installiert. Die Befehle basieren auf Dokumenten, wobei ein Dokument in der Regel ein Skript mit optionalen Parametern ist. Das Besondere an diesen SSM-Dokumenten ist, dass der Zugriff über IAM-Richtlinien gesteuert werden kann.
Wie sieht ein SSM-Dokument aus? Es handelt sich um eine YAML- oder JSON-Datei, die in etwa so aussieht:
schemaVersion: "2.2"
description: "Hello World"
parameters:
parameters:
type: "String"
description: "Some text to print"
default: "none"
mainSteps:
-
action: "aws:runShellScript"
name: "runShellScript"
inputs:
workingDirectory: "{{.}}"
runCommand:
- "echo 'hello world'"
- "echo {{ parameters }}"
Dieses einfache Beispiel verwendet lediglich einige Parameter und gibt diese zusammen mit der Zeichenfolge „Hallo Welt“ aus. SSM-Dokumente können über die AWS-Konsole aufgerufen werden, indem Sie das Dokument auswählen und Fahrbefehl Alternativ kann es über die CLI oder API aufgerufen werden. So rufen wir dies auf einer Instanz über die CLI auf:
aws ssm send-command
--document-name "admin-hello-world"
--document-version "4"
--targets '[{"Key":"InstanceIds","Values":["i-123456789"]}]'
--parameters '{"parameters":["param1 param2"]}'
--timeout-seconds 600
--max-concurrency "50"
--max-errors "0"
--region us-east-1
OK, wir verstehen also die Grundlagen der Systems Manager-Dokumente. Was kommt als Nächstes?
Während das obige Beispieldokument ein in ein SSM-Dokument eingebettetes Skript zeigt, ist es möglich, ein SSM-Dokument Referenzcode direkt in Github (entweder öffentliche oder private Repos). Das ist unglaublich praktisch, da wir nun alle Funktionen von Github für die Quellcodeverwaltung nutzen können (einschließlich Pull Requests für Peer-Review). Wir haben jetzt kuratierte SSM-Skripte!
Wie sieht ein SSM-Dokument aus, wenn es Code von Github bezieht? Der größte Teil davon ist die Hinzufügung einer Aktion, die auf aws:downloadContent
- action: "aws:downloadContent"
name: "downloadContent"
inputs:
sourceType: "GitHub"
sourceInfo: "{"owner":"rewindio", "repository":"my_private_repo","getOptions" : "branch:main","path" :"scripts/read-only/", "tokenInfo":"{{ ssm-secure:{{githubTokenLocation}} }}"}"
destinationPath: "{{ workingDirectory }}"
Der wichtige Parameter, der hier benötigt wird, ist die ssm-sicher Parameter. Dies ist der Pfad zu einem AWS-Parameterspeicher sicherer String-Parameter. Dieser Parameter muss einen Github enthalten Persönliches Zugangs-Token (PAT), der über die Berechtigung zum Klonen des angegebenen Repositorys verfügt. Im obigen Beispiel muss der PAT über Klonberechtigungen für das rewindio/mein_privates_repo Repository.
Sehen wir uns dies im Kontext eines vollständigen Dokuments an.
---
schemaVersion: "2.2"
description: "Run Github script"
parameters:
githubTokenLocation:
type: "String"
description: "Location in ssm param store of your github token"
default: "none"
workingDirectory:
type: "String"
default: ""
description: "(Optional) The path where the content will be downloaded and executed
from on your instance."
maxChars: 4096
executionTimeout:
description: "(Optional) The time in seconds for a command to complete before
it is considered to have failed. Default is 3600 (1 hour). Maximum is 28800
(8 hours)."
type: "String"
default: "3600"
allowedPattern: "([1-9][0-9]{0,3})|(1[0-9]{1,4})|(2[0-7][0-9]{1,3})|(28[0-7][0-9]{1,2})|(28800)"
mainSteps:
- action: "aws:downloadContent"
name: "downloadContent"
inputs:
sourceType: "GitHub"
sourceInfo: "{"owner":"rewindio", "repository":"my_private_repo","getOptions" : "branch:main","path" :"scripts/read-only/", "tokenInfo":"{{ ssm-secure:{{githubTokenLocation}} }}"}"
destinationPath: "{{ workingDirectory }}"
- precondition:
StringEquals:
- "platformType"
- "Linux"
action: "aws:runShellScript"
name: "runShellScript"
inputs:
runCommand:
- chmod a+x my_script.sh
- ./my_script.sh
workingDirectory: "{{ workingDirectory }}"
timeoutSeconds: "{{ executionTimeout }}"
In diesem Beispiel ist der Pfad Skripte/schreibgeschützt aus dem privaten GitHub-Repo rewindio/mein_privates_repo geklont wird. Der eigentliche Run-Befehl führt dann ein einzelnes Skript von hier aus aus, genannt my_script.sh.
Wir haben also diese SSM-Dokumente. Wie können wir Berechtigungen zuweisen, sodass nur bestimmte Benutzer bestimmte Dokumente auf bestimmten Instanzen ausführen können? Hier ist ein Beispiel für eine IAM-Richtlinie, das wir Schritt für Schritt durchgehen:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SessionManagerSendCommandSpecificDocs",
"Effect": "Allow",
"Action": "ssm:SendCommand",
"Resource": "arn:aws:ssm:*:*:document/scripts-read-only-*",
"Condition": {
"BoolIfExists": {
"ssm:SessionDocumentAccessCheck": "true"
}
}
},
{
"Sid": "SessionManagerTomyGreatProductInstances",
"Effect": "Allow",
"Action": [
"ssm:StartSession",
"ssm:SendCommand"
],
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringLike": {
"ssm:resourceTag/product": "myGreatProduct"
}
}
}
]
}
Der erste Block ermöglicht den Zugriff auf SSM-Dokumente, die mit dem Präfix beginnen Skripte-schreibgeschützt-. Benutzer (oder Rollen) mit dieser Richtliniensperre können nur Dokumente ausführen, deren Name mit Skripte-schreibgeschützt-.
Der zweite Block erlaubt das Ausführen von Befehlen nur auf Instanzen, die ein Tag namens PRODUKTE mit einem Wert von meinGroßartigesProdukt.
Durch Kombinationen dieser Blöcke, die verschiedenen IAM-Benutzern/-Gruppen/-Rollen zugewiesen sind, können Sie den Zugriff auf bestimmte SSM-Dokumente und EC2-Instanzen einschränken. In unserem Fall verwenden wir je nach benötigtem Zugriff verschiedene Benutzerprofile. Dies wird auf IAM-Gruppenebene gesteuert, und die entsprechende IAM-Richtlinie wird für die Teilmenge der kuratierten Skripte zugewiesen, auf die wir Zugriff gewähren möchten.
Die meisten Teile dieser Lösung sind nun implementiert. Aber wie können wir Code aus einem privaten Github-Repo automatisch in SSM-Dokumente übersetzen? Geben Sie ein Github-Aktionen.
Wir haben eine erstellt öffentlich verfügbare Github-Aktion Dadurch werden automatisch SSM-Dokumente für Code erstellt, der einem Github-Repository hinzugefügt wird. Diese Aktion generiert das korrekte YAML für das SSM-Dokument und fügt den korrekten Skriptnamen zur Ausführung ein. Das Schöne daran: Skriptautoren können sich nun ganz auf das Schreiben ihrer Skripte konzentrieren – sie müssen weder die Syntax noch die Feinheiten des SSM-Dokumentschemas kennen.
Wie verwenden wir diese Github-Aktion? Hier ist ein Beispiel-Workflow (dieser befindet sich im Ordner .github/workflows im Github-Repository, das Ihre Skripte enthält).
name: synchronizeSSM
on:
push:
branches:
- main
jobs:
release-staging:
strategy:
matrix:
publish-region: [us-east-1, eu-west-1]
name: ${{ matrix.publish-region }}-staging
runs-on: ubuntu-latest
env:
PUBLISH_REGIONS: ${{ matrix.publish-region }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: get files changed
uses: lots0logs/[email protected]
id: get_files_changed
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: generate ssm yaml file
id: generate_ssm_yaml
uses: rewindio/github-action-generate-ssm-documents@main
env:
FILE_LIST: ${{ steps.get_files_changed.outputs.added }}
PREFIX_FILTER: scripts
DEBUG: True
AWS_ACCESS_KEY_ID: ${{ secrets.STAGING_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.STAGING_AWS_SECRET_ACCESS_KEY }}
REPO_NAME: my_private_repo
REPO_OWNER: rewindio
In diesem Beispiel werden SSM-Dokumente für alle im Repository eingecheckten Dateien erstellt und in die Regionen „us-east-1“ und „eu-west-1“ übertragen. Sehen wir uns einige Teile dieses Workflows genauer an:
jobs:
release-staging:
strategy:
matrix:
publish-region: [us-east-1, eu-west-1]
name: ${{ matrix.publish-region }}-staging
runs-on: ubuntu-latest
env:
PUBLISH_REGIONS: ${{ matrix.publish-region }}
Dies nutzt die Matrixstrategie für Jobs. Github-Aktionen erstellen dynamisch einen neuen Job für jeden Eintrag in der Veröffentlichungsregionenliste, benennen ihn mit dem Regionsnamen und legen in jedem Job eine Umgebungsvariable mit dem Namen der Region fest.
- name: get files changed
uses: lots0logs/[email protected]
id: get_files_changed
with:
token: ${{ secrets.GITHUB_TOKEN }}
Dies nutzt eine praktische öffentliche Aktion, um die Liste der geänderten Dateien in der aktuellen Änderung am Repository abzurufen. Wir möchten für jede geänderte Datei SSM-Dokumente generieren.
- name: generate ssm yaml file
id: generate_ssm_yaml
uses: rewindio/github-action-generate-ssm-documents@main
env:
FILE_LIST: ${{ steps.get_files_changed.outputs.added }}
PREFIX_FILTER: scripts
DEBUG: True
AWS_ACCESS_KEY_ID: ${{ secrets.STAGING_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.STAGING_AWS_SECRET_ACCESS_KEY }}
REPO_NAME: my_private_repo
REPO_OWNER: rewindio
Hier ist die besondere Zutat. Dies ist unsere Github-Aktion, die die SSM-Dokumente für jede geänderte Datei generiert. In diesem Fall verwendet sie PREFIX_FILTER um nur geänderte Dateien im Skriptordner anzuzeigen. Die referenzierten AWS-Schlüssel müssen gespeichert werden als Github verschlüsselte Geheimnisse für das Repo und den entsprechenden AWS IAM-Benutzer müssen ausreichende Berechtigungen zum Hochladen von SSM-Dokumenten vorhanden sein (idealerweise nicht mehr als diese)
Fassen Sie das alles in einer einfachen „Was bewirkt dies“-Anweisung zusammen:
Immer wenn Dateien zu diesem GitHub-Repository im Ordner „Scripts“ hinzugefügt werden, wird in den Regionen „us-east-1“ und „eu-west-1“ ein entsprechendes SSM-Dokument erstellt.
Der letzte Teil unserer Lösung ist eine einfache Möglichkeit, diese Skripte auszuführen. Da wir bereits über unser Dienstprogramm aws-connect verfügen, war es sinnvoll, dieses zu erweitern. Hier ist ein Beispiel in Aktion:
aws-connect -x i-23323ere3423
-r us-east-1
-a document
-d my-ssm-document
-p my_aws_profile
-w 'param1 "param 2"'
-g /devops/github_token
-c ssm-cloudwatch-logs
Wir bitten um die Ausführung der mein-ssm-dokument SSM-Dokument auf Instanz i-23323ere3423, Übergabe von Parametern param1 und Parameter 2 zum Dokument. Das Gitub PAT befindet sich im /devops/github_token SSM-Parameterspeicherparameter.
Zusammenfassend haben wir eine Lösung entwickelt, mit der IAM-Benutzer Zugriff auf die Ausführung einer Teilmenge kuratierter Skripte für eine Reihe getaggter Instanzen erhalten. Wir haben dies erfolgreich eingesetzt, um den Zugriff auf leistungsstärkere Skripte auf unsere leitenden Ingenieure zu beschränken. Dies ist ein weiteres hervorragendes Beispiel für die Nutzung des unglaublich vielseitigen SSM-Dienstes.
Möchten Sie solche Lösungen zusammenstellen? Schauen Sie sich unsere Karriere Seite für alle Ingenieurpositionen, für die wir heute einstellen.
Dieser Artikel erschien ursprünglich in der Rewind.io Blog und wurde hier mit Genehmigung veröffentlicht.


