GITHUB
Ce document explique comment ingérer des journaux d'audit GitHub dans Google Security Operations à l'aide d'Amazon S3. L'analyseur tente d'extraire les données du champ "message" à l'aide de différents modèles Grok, en gérant les formats JSON et non JSON. En fonction du "process_type" extrait, il applique une logique d'analyse spécifique à l'aide de filtres grok, kv et autres pour mapper les données de journal brutes dans le schéma UDM (Unified Data Model).
Avant de commencer
Assurez-vous de remplir les conditions suivantes :
- Instance Google SecOps.
- Accès privilégié au locataire GitHub Enterprise Cloud avec les autorisations de propriétaire de l'entreprise.
- Accès privilégié à AWS (S3, IAM).
Recueillir les conditions préalables de GitHub Enterprise Cloud (accès Enterprise)
- Connectez-vous à la console d'administration GitHub Enterprise Cloud.
- Accédez à Paramètres Enterprise> Paramètres> Journal d'audit> Streaming du journal.
- Assurez-vous de disposer des autorisations de propriétaire de l'entreprise pour configurer le streaming des journaux d'audit.
- Copiez et enregistrez les informations suivantes dans un emplacement sécurisé :
- Nom de GitHub Enterprise
- Noms des organisations sous l'entreprise
Configurer le bucket AWS S3 et Identity and Access Management pour Google SecOps
- Créez un bucket Amazon S3 en suivant ce guide de l'utilisateur : Créer un bucket.
- Enregistrez le nom et la région du bucket pour référence ultérieure (par exemple,
github-audit-logs
). - Créez un utilisateur en suivant ce guide de l'utilisateur : Créer un utilisateur IAM.
- Sélectionnez l'utilisateur créé.
- Sélectionnez l'onglet Informations d'identification de sécurité.
- Cliquez sur Créer une clé d'accès dans la section Clés d'accès.
- Sélectionnez Service tiers comme Cas d'utilisation.
- Cliquez sur Suivant.
- Facultatif : Ajoutez un tag de description.
- Cliquez sur Créer une clé d'accès.
- Cliquez sur Télécharger le fichier CSV pour enregistrer la clé d'accès et la clé d'accès secrète pour référence ultérieure.
- Cliquez sur OK.
Configurer la stratégie IAM pour le streaming GitHub S3
- Dans la console AWS, accédez à IAM> Stratégies> Créer une stratégie> onglet JSON.
- Copiez et collez le règlement suivant.
JSON de la règle (remplacez
github-audit-logs
si vous avez saisi un autre nom de bucket) :{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutObjects", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::github-audit-logs/*" } ] }
Cliquez sur Suivant > Créer une règle.
Nommez la règle
GitHubAuditStreamingPolicy
, puis cliquez sur Créer une règle.Revenez à l'utilisateur IAM créé précédemment.
Sélectionnez l'onglet Autorisations.
Cliquez sur Ajouter des autorisations> Joindre directement des règles.
Recherchez et sélectionnez
GitHubAuditStreamingPolicy
.Cliquez sur Suivant > Ajouter des autorisations.
Configurer le streaming des journaux d'audit GitHub Enterprise Cloud
- Connectez-vous à GitHub Enterprise Cloud en tant que propriétaire de l'entreprise.
- Cliquez sur votre photo de profil, puis sur Paramètres d'entreprise.
- Dans la barre latérale du compte d'entreprise, cliquez sur Paramètres> Journal d'audit> Diffusion de journaux.
- Sélectionnez Configurer le flux, puis cliquez sur Amazon S3.
- Sous Authentification, cliquez sur Clés d'accès.
- Fournissez les informations de configuration suivantes :
- Région : sélectionnez la région du bucket (par exemple,
us-east-1
). - Bucket : saisissez le nom du bucket dans lequel vous souhaitez diffuser le flux (par exemple,
github-audit-logs
). - ID de clé d'accès : saisissez l'ID de clé d'accès de l'utilisateur IAM.
- Clé secrète : saisissez la clé secrète de l'utilisateur IAM.
- Région : sélectionnez la région du bucket (par exemple,
- Cliquez sur Vérifier le point de terminaison pour vérifier que GitHub peut se connecter au point de terminaison Amazon S3 et y écrire des données.
- Une fois le point de terminaison validé, cliquez sur Enregistrer.
Créer un utilisateur et des clés IAM en lecture seule pour Google SecOps
- Accédez à la console AWS> IAM> Utilisateurs> Ajouter des utilisateurs.
- Cliquez sur Add users (Ajouter des utilisateurs).
- Fournissez les informations de configuration suivantes :
- Utilisateur : saisissez
secops-reader
. - Type d'accès : sélectionnez Clé d'accès – Accès programmatique.
- Utilisateur : saisissez
- Cliquez sur Créer un utilisateur.
- Associez la stratégie de lecture minimale (personnalisée) : Utilisateurs > lecteur-secops > Autorisations > Ajouter des autorisations > Associer des stratégies directement > Créer une stratégie.
JSON :
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::github-audit-logs/*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::github-audit-logs" } ] }
Nom =
secops-reader-policy
.Cliquez sur Créer une règle> recherchez/sélectionnez > Suivant> Ajouter des autorisations.
Créez une clé d'accès pour
secops-reader
: Identifiants de sécurité> Clés d'accès> Créer une clé d'accès> téléchargez le fichier.CSV
(vous collerez ces valeurs dans le flux).
Configurer un flux dans Google SecOps pour ingérer les journaux GitHub
- Accédez à Paramètres SIEM> Flux.
- Cliquez sur + Ajouter un flux.
- Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple,
GitHub audit logs
). - Sélectionnez Amazon S3 V2 comme type de source.
- Sélectionnez GitHub comme type de journal.
- Cliquez sur Suivant.
- Spécifiez les valeurs des paramètres d'entrée suivants :
- URI S3 :
s3://github-audit-logs/
- Options de suppression de la source : sélectionnez l'option de suppression de votre choix.
- Âge maximal des fichiers : incluez les fichiers modifiés au cours des derniers jours. La valeur par défaut est de 180 jours.
- ID de clé d'accès : clé d'accès utilisateur ayant accès au bucket S3.
- Clé d'accès secrète : clé secrète de l'utilisateur ayant accès au bucket S3.
- Espace de noms de l'élément : espace de noms de l'élément.
- Libellés d'ingestion : libellé appliqué aux événements de ce flux.
- URI S3 :
- Cliquez sur Suivant.
- Vérifiez la configuration de votre nouveau flux sur l'écran Finaliser, puis cliquez sur Envoyer.
Table de mappage UDM
Champ de journal | Mappage UDM | Logique |
---|---|---|
actor |
principal.user.userid |
La valeur est extraite du champ actor . |
actor_id |
principal.user.attribute.labels.value |
La valeur est extraite du champ actor_id . |
actor_ip |
principal.ip |
La valeur est extraite du champ actor_ip . |
actor_location.country_code |
principal.location.country_or_region |
La valeur est extraite du champ actor_location.country_code . |
application_name |
target.application |
La valeur est extraite du champ application_name . |
business |
target.user.company_name |
La valeur est extraite du champ business . |
business_id |
target.resource.attribute.labels.value |
La valeur est extraite du champ business_id . |
config.url |
target.url |
La valeur est extraite du champ config.url . |
created_at |
metadata.event_timestamp |
La valeur est convertie de millisecondes UNIX en code temporel. |
data.cancelled_at |
extensions.vulns.vulnerabilities.scan_end_time |
La valeur est convertie du format ISO8601 en code temporel. |
data.email |
target.email |
La valeur est extraite du champ data.email . |
data.event |
security_result.about.labels.value |
La valeur est extraite du champ data.event . |
data.events |
security_result.about.labels.value |
La valeur est extraite du champ data.events . |
data.head_branch |
security_result.about.labels.value |
La valeur est extraite du champ data.head_branch . |
data.head_sha |
target.file.sha256 |
La valeur est extraite du champ data.head_sha . |
data.hook_id |
target.resource.attribute.labels.value |
La valeur est extraite du champ data.hook_id . |
data.started_at |
extensions.vulns.vulnerabilities.scan_start_time |
La valeur est convertie du format ISO8601 en code temporel. |
data.team |
target.user.group_identifiers |
La valeur est extraite du champ data.team . |
data.trigger_id |
security_result.about.labels.value |
La valeur est extraite du champ data.trigger_id . |
data.workflow_id |
security_result.about.labels.value |
La valeur est extraite du champ data.workflow_id . |
data.workflow_run_id |
security_result.about.labels.value |
La valeur est extraite du champ data.workflow_run_id . |
enterprise.name |
additional.fields.value.string_value |
La valeur est extraite du champ enterprise.name . |
external_identity_nameid |
target.user.email_addresses |
Si la valeur est une adresse e-mail, elle est ajoutée au tableau target.user.email_addresses . |
external_identity_nameid |
target.user.userid |
La valeur est extraite du champ external_identity_nameid . |
external_identity_username |
target.user.user_display_name |
La valeur est extraite du champ external_identity_username . |
hashed_token |
network.session_id |
La valeur est extraite du champ hashed_token . |
job_name |
target.resource.attribute.labels.value |
La valeur est extraite du champ job_name . |
job_workflow_ref |
target.resource.attribute.labels.value |
La valeur est extraite du champ job_workflow_ref . |
org |
target.administrative_domain |
La valeur est extraite du champ org . |
org_id |
additional.fields.value.string_value |
La valeur est extraite du champ org_id . |
programmatic_access_type |
additional.fields.value.string_value |
La valeur est extraite du champ programmatic_access_type . |
public_repo |
additional.fields.value.string_value |
La valeur est extraite du champ public_repo . |
public_repo |
target.location.name |
Si la valeur est "false", elle est associée à "PRIVATE". Sinon, il est mappé sur "PUBLIC". |
query_string |
additional.fields.value.string_value |
La valeur est extraite du champ query_string . |
rate_limit_remaining |
additional.fields.value.string_value |
La valeur est extraite du champ rate_limit_remaining . |
repo |
target.resource.name |
La valeur est extraite du champ repo . |
repo_id |
additional.fields.value.string_value |
La valeur est extraite du champ repo_id . |
repository_public |
additional.fields.value.string_value |
La valeur est extraite du champ repository_public . |
request_body |
additional.fields.value.string_value |
La valeur est extraite du champ request_body . |
request_method |
network.http.method |
La valeur est convertie en majuscules. |
route |
additional.fields.value.string_value |
La valeur est extraite du champ route . |
status_code |
network.http.response_code |
La valeur est convertie en nombre entier. |
timestamp |
metadata.event_timestamp |
La valeur est convertie de millisecondes UNIX en code temporel. |
token_id |
additional.fields.value.string_value |
La valeur est extraite du champ token_id . |
token_scopes |
additional.fields.value.string_value |
La valeur est extraite du champ token_scopes . |
transport_protocol_name |
network.application_protocol |
La valeur est convertie en majuscules. |
url_path |
target.url |
La valeur est extraite du champ url_path . |
user |
target.user.user_display_name |
La valeur est extraite du champ user . |
user_agent |
network.http.user_agent |
La valeur est extraite du champ user_agent . |
user_agent |
network.http.parsed_user_agent |
La valeur est analysée. |
user_id |
target.user.userid |
La valeur est extraite du champ user_id . |
workflow.name |
security_result.about.labels.value |
La valeur est extraite du champ workflow.name . |
workflow_run.actor.login |
principal.user.userid |
La valeur est extraite du champ workflow_run.actor.login . |
workflow_run.event |
additional.fields.value.string_value |
La valeur est extraite du champ workflow_run.event . |
workflow_run.head_branch |
security_result.about.labels.value |
La valeur est extraite du champ workflow_run.head_branch . |
workflow_run.head_sha |
target.file.sha256 |
La valeur est extraite du champ workflow_run.head_sha . |
workflow_run.id |
target.resource.attribute.labels.value |
La valeur est extraite du champ workflow_run.id . |
workflow_run.workflow_id |
security_result.about.labels.value |
La valeur est extraite du champ workflow_run.workflow_id . |
N/A | metadata.event_type |
La valeur est déterminée en fonction des champs action et actor . Si le champ action contient "_member", la valeur est définie sur "USER_RESOURCE_UPDATE_PERMISSIONS". Si les champs action et actor ne sont pas vides, la valeur est définie sur "USER_RESOURCE_UPDATE_CONTENT". Sinon, la valeur est définie sur "USER_RESOURCE_ACCESS". |
N/A | metadata.log_type |
La valeur est définie sur "GITHUB". |
N/A | metadata.product_name |
La valeur est définie sur "GITHUB". |
N/A | metadata.vendor_name |
La valeur est définie sur "GITHUB". |
N/A | target.resource.resource_type |
La valeur est définie sur "STORAGE_OBJECT". |
N/A | security_result.about.labels.key |
La valeur est définie sur une chaîne constante en fonction du champ data correspondant. Par exemple, pour data.workflow_id , la clé est définie sur "ID du workflow". |
N/A | target.resource.attribute.labels.key |
La valeur est définie sur une chaîne constante en fonction du champ data correspondant. Par exemple, pour data.hook_id , la clé est définie sur "Hook Id". |
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.