Skip to main content
  1. Posts/

Protecting GitLab as a Crown Jewel: Security Logs, Dashboards, and Alerts with Wazuh

·4327 words·21 mins· loading · loading · ·
Pratik
Author
Pratik

This is my little digital scratchpad. Some days it’s about security tools, code, or systems I’m tinkering with. Some days it’s poems, emotions, or thoughts that refused to stay quiet. And sometimes it’s just photos I took while pretending I knew what I was doing.

Expect a mix of tech notes, life reflections, creative bursts, and the occasional anxious-mind ramble that somehow made sense at 2 AM.

Table of Contents

For an organization that builds software, GitLab can be one of its crown jewels. It may hold proprietary source code, internal architecture, deployment configuration, and customer information in issues, attachments, or repository files. Depending on permissions and how delivery is configured, access to GitLab can also provide a way to change what the organization builds and deploys.

That makes GitLab a security monitoring priority. The questions extend from who signed in to who changed access, read sensitive repositories, pushed code, or initiated a destructive action. The answers matter to the confidentiality of company and customer data, the integrity of software, and the availability of the development environment.

This article walks through understanding GitLab’s security-relevant logs, sending them to a central SIEM, and using them for dashboards, alerts, and investigation. Wazuh is the implementation example. The approach starts with the information an analyst needs and follows it from a real GitLab event to a usable security signal.

Central collection gives the team a place to search and connect events. Dashboards make activity and changes visible. Alerts bring selected patterns to an analyst’s attention. Each needs its own validation: a file being forwarded does not establish that an account field is searchable, a chart counts the right thing, or a detection reaches someone who can investigate.

The examples draw on GitLab logs and Wazuh configuration, with identifying values replaced by placeholders. Authentication is the detailed walkthrough; access changes and repository activity extend monitoring to what happens after sign-in. Validate the configuration against your GitLab version and installation.

Start with the security questions
#

Before choosing log files or writing XML, identify the actions that could affect the organization’s data and software.

Security questionEvidence to look for
Is someone trying to gain access?Rejected sign-ins, repeated failures, attempted accounts, source addresses, and lockouts where emitted
Who successfully authenticated, and how?Password, OAuth, and MFA audit events, with account, address, time, and request correlation
Was access extended or weakened?Token and SSH-key activity, MFA changes, membership changes, and repository access settings
Was sensitive code read or changed?HTTP and SSH Git activity, repository/account context, exports, and transfer volume where available
Was a destructive or administrative action attempted?Project lifecycle requests, related background jobs, and administrative changes, followed by outcome verification

These questions define a monitoring scope. The example rules address parts of it; they do not establish complete coverage of customer-data access, pipeline changes, or every action GitLab supports.

Know which GitLab logs answer which questions
#

GitLab separates application, audit, and component activity across several logs. Start with its log system documentation and inspect the files your installation actually writes. Paths below follow the Linux package layout used by the example collection configuration, under /var/log/gitlab/.

Log sourceSecurity use in this integrationEvidence or coverage boundary
gitlab-rails/production_json.logWeb sign-ins, security-setting requests, and Git-over-HTTP activityCheck controller, action, method, and status together; a request does not always prove a completed change
gitlab-rails/audit_json.logExplicit audit events and actor contextCheck which password, OAuth, MFA, and lockout events your version and edition emit
gitlab-rails/application.log / application_json.logApplication events; the example custom failure decoder expects the plain-text fileConfirm file availability and the failure-message format before enabling account-based correlation
gitlab-rails/api_json.logAPI activity, including the routes targeted by project lifecycle rulesVerify API event shapes and outcomes on your instance
gitlab-rails/auth.logAuthentication/rate-limit context, depending on emitted eventsInspect the format and event content; allowlist messages do not establish failed-login coverage
nginx/gitlab_access.log / gitlab_error.logHTTP access and error context for investigating requestsCollection is configured; these do not replace application-level account and outcome evidence
gitlab-workhorse/currentTransfer context; the repository rules inspect route_id, written_bytes, and source addressLarge-transfer rules are heuristics requiring validation and an automation baseline
gitlab-shell/gitlab-shell.logThe intended source for Git-over-SSH push/fetch rulesExpected SSH fields need validation against an actual event on your instance
sidekiq/currentBackground-job context for asynchronous actionsDeletion rules inspect job starts; a start does not prove completed deletion
gitaly/current, Rails git_json.log and graphql_json.logAdditional repository-service, Git-error, and GraphQL context to investigateCollection entries exist; their presence alone does not establish detection coverage

The collection file also includes webhook, integration, exception, and Gitaly-hook logs. Choose and validate sources against the security questions above. For each one, record whether it exists, which events it emits, whether the agent collects it, and whether any rule or dashboard actually uses it.

Send the logs to a central SIEM
#

In this example, the Wazuh agent reads the GitLab files and forwards events to the manager for decoding and rule evaluation. Wazuh describes the collection flow in its log collection documentation. Centralizing that evidence supports investigation across accounts, repositories, hosts, and identity systems without relying on a local log search during an incident.

These two blocks from the example agent configuration collect the main sources used in the authentication walkthrough. Add them inside the agent’s existing ossec_config element after verifying paths and file access:

<localfile>
  <location>/var/log/gitlab/gitlab-rails/production_json.log</location>
  <log_format>json</log_format>
  <only-future-events>yes</only-future-events>
  <label key="integration.source">gitlab</label>
  <label key="integration.log_type">production_json</label>
</localfile>

<localfile>
  <location>/var/log/gitlab/gitlab-rails/audit_json.log</location>
  <log_format>json</log_format>
  <only-future-events>yes</only-future-events>
  <label key="integration.source">gitlab</label>
  <label key="integration.log_type">audit_json</label>
</localfile>

The labels identify the integration and log family; several example rules explicitly require integration.log_type. With only-future-events=yes, generate new test activity after collection starts. Check the source line, received event, decoded fields, and final indexed alert. Repeat the check after rotation or a logging-format change.

flowchart LR
    A["GitLab application, audit, and component logs"] --> B["Wazuh agent collection and labels"]
    B --> C["Manager decoding and rules"]
    C --> D["Indexed alerts"]
    D --> E["Security dashboards"]
    D --> F["Configured notification or triage queue"]
    E --> G["Investigation and response"]
    F --> G

The bundled dashboards query wazuh-alerts-*. Do not assume that this view contains every forwarded source event. Decide separately how much raw evidence to retain for reconstruction, who can access it, and how long it is needed. GitLab logs can themselves contain account details, repository paths, request parameters, and sensitive context. Central retention needs access controls appropriate to that data.

Give someone ownership of collection health as well as security alerts. An unexpectedly silent source should lead to a check of file activity, agent access, forwarding, and indexing before its empty dashboard is interpreted as an absence of suspicious activity.

Extract the fields needed for authentication monitoring
#

There are two request/failure paths in the example configuration, supplemented by audit events.

SourceDecoder and useful fieldsIntended use
production_json.logjson; remote_ip, ua, controller, path, action, status, correlation_idFailed web sign-ins and repeated failures from one IP
Plain-text application.loggitlab-failed-login; dstuser, srcipRepeated failures against an account and attempts across accounts
audit_json.logjson; event_name, meta.user, meta.remote_ip, correlation_id, where presentPassword, OAuth and two-factor authentication events

GitLab documents several application and component logs, with different purposes and formats. The useful starting point is its log system documentation, followed by checking what the installed instance actually writes.

Check which decoder handles each event before writing rules against its fields. The JSON request rules here target json; the plain-text failure rule targets gitlab-failed-login. A rule tied to a decoder that never handles its input will not provide the intended coverage.

A failed sign-in can carry the submitted login inside the user entry of params, an array of key/value objects, without a populated top-level username or meta.user. Account correlation requires extracting that login into a field the rule can compare across events. A submitted login is an attempted identity, not proof that the account exists.

Wazuh documents JSON extraction and plugin-based decoder arrangements, and explicitly lists arrays of objects as unsupported, in its JSON decoder guide. Replay the full event, including params, when checking extraction. After any decoder change, confirm that the account field and the request fields needed by other rules are still available.

The configuration separates request-level and account-level detection:

flowchart TD
    A["GitLab authentication activity"] --> B["JSON request logs"]
    A --> C["Plain-text failure log, if available"]
    B --> D["Built-in JSON decoder"]
    C --> E["Custom failure decoder"]
    D --> F["Per-IP failure correlation"]
    E --> G["Account correlation: review required"]
    F --> H["Alerts and investigation"]
    G --> H

The second path uses a small decoder:

<decoder name="gitlab-failed-login">
  <prematch>Failed Login: </prematch>
  <regex offset="after_prematch">^username=(\S+) ip=(\S+)</regex>
  <order>dstuser, srcip</order>
</decoder>

For an illustrative message such as Failed Login: username=developer1 ip=192.0.2.10, the intended output is dstuser=developer1 and srcip=192.0.2.10. The prematch locates the failure message; the regex reads the account and address after it.

The account-based path depends on a collected application.log that emits the expected failure message. Confirm file availability and message format on your instance before enabling the decoder. A collection entry alone does not establish that the source exists or produces useful events.

Inspect auth.log before choosing a parser or treating it as a failed-login source. It can contain JSON messages with fields such as gitlab_throttle_user_allowlist; the filename alone does not establish which authentication events it provides.

An empty account-failure panel needs a collection and decoding check. Confirm that application.log receives failed-login messages and is readable by the agent, then check field extraction and correlation. An empty chart can mean missing telemetry as well as no matching activity.

Alert on authentication behaviour, starting with the actual outcome
#

The request-level failure rule is deliberately specific:

<rule id="110100" level="5">
  <decoded_as>json</decoded_as>
  <field name="controller">^SessionsController$</field>
  <field name="path">^/users/sign_in$</field>
  <field name="method">^POST$</field>
  <action type="pcre2">^new$</action>
  <status type="pcre2">^200$</status>
  <description>GitLab failed web sign-in from $(remote_ip), UA $(ua), correlation $(correlation_id)</description>
  <mitre><id>T1110</id></mitre>
  <group>authentication_failed,credential_access,</group>
</rule>

In the example logs, rejected sign-ins render the form again with action=new, status=200. HTTP 200 describes the response, not successful authentication.

A reduced, sanitized example from production_json.log looks like this:

{"time":"2026-01-01T12:00:00.000Z","controller":"SessionsController","path":"/users/sign_in","method":"POST","action":"new","status":200,"meta.caller_id":"SessionsController#create","remote_ip":"192.0.2.10","meta.remote_ip":"192.0.2.10","ua":"ExampleBrowser/1.0","correlation_id":"example-request-001"}

The example keeps the request-field structure while replacing the timestamp and identifying values. Other fields, including params, are omitted for readability. Use a complete event when testing decoding, including any arrays. Notice that meta.caller_id says SessionsController#create while the final action is new; rule 110100 checks action.

A sign-in request can produce multiple records with the same correlation_id, including a create/0 record and a final new/200 record. Counting both as attempts can inflate failure totals. Rule 110100 selects the final failure fingerprint. Other outcomes, such as 422 or create/200, need separate interpretation; these rules do not classify every possible sign-in response.

Rule 110105 matches the same controller, path and POST method with status 302, and labels that a successful sign-in at level 3. It does not require action=create, despite that combination appearing in the explanatory comments. A redirect is therefore the implemented signal; completed authentication should be cross-checked against audit events, including MFA and unsuccessful redirect flows.

Join the request and audit records using correlation_id to check whether a redirect corresponds to password or MFA authentication. Treat linked records as evidence about the same request when calculating login totals, rather than adding each record as a separate login.

The audit rules add useful context: 110010 matches authenticated_with_password, 110011 matches authenticated_with_oauth, and 110012 matches authenticated_with_two_factor. All three use level 3. Use meta.user, meta.remote_ip and correlation_id, where populated, to connect the authentication event to its actor and request. Check event availability on your GitLab version and edition.

These audit rules also require the agent’s integration.log_type=audit_json label. Pasting a raw line into a test session without reproducing that field will not exercise the complete predicate. The request-level replacement rules deliberately avoid that dependency.

Distinguish repeated guessing from possible password spraying
#

A single rejected sign-in can be a typing mistake. Repeated attempts against one account and one source trying several accounts deserve different investigation paths. The latter can fit password spraying: trying a small set of passwords across many users. These logs do not expose attempted passwords, so they cannot prove password reuse. That distinction follows MITRE’s definition of password spraying and should constrain the alert’s claim.

The per-IP rule builds on the JSON failure event:

<rule id="110101" level="10" frequency="5" timeframe="600" ignore="300">
  <if_matched_sid>110100</if_matched_sid>
  <same_field>remote_ip</same_field>
  <description>GitLab: repeated failed web sign-ins from $(remote_ip)</description>
  <mitre><id>T1110.001</id></mitre>
  <group>brute_force,authentication_failures,</group>
</rule>

The XML sets frequency=5, timeframe=600, grouping by remote_ip, and ignore=300. The exact trigger event and suppression behaviour still need a sequence replay on the installed release. The intended signal is a concentration of failures from an address; it does not say how many accounts were targeted.

The account-aware rules depend on 110106, the level-5 event matching gitlab-failed-login.

RuleConfigured conditionIntended interpretation
110101110100, frequency 5, 600 seconds, same remote_ipRepeated web failures from one source; level 10
110102110106, frequency 5, 600 seconds, same_field on dstuserRepeated attempts against one account; level 10
110103110106, frequency 5, 600 seconds, same source IP and different_field on dstuserAttempts against multiple accounts from one source; level 12

The last two need a technical correction before I would present them as dependable coverage. The decoder puts the username in Wazuh’s static dstuser field, while those rules use dynamic-field correlation operators. Wazuh distinguishes these from its dedicated user operators. Review same_user and different_user, then replay the full sequences. See the rule syntax reference.

The downloadable spraying rule illustrates the correlation intent, but still contains the dstuser operator issue described above:

<rule id="110103" level="12" frequency="5" timeframe="600" ignore="300">
  <if_matched_sid>110106</if_matched_sid>
  <same_srcip />
  <different_field>dstuser</different_field>
  <description>GitLab: one source IP attempted multiple accounts: $(srcip)</description>
  <mitre><id>T1110.003</id></mitre>
  <group>password_spraying,</group>
</rule>

Even after fixing the operator, “different users” needs testing. Five events are not automatically five distinct accounts. A sequence alternating developer1 and developer2 should be tested separately from one touching five different users. Only describe a distinct-account threshold once the test sequence demonstrates it.

The configuration does not automatically link a later successful login to earlier failures; the analyst must make that connection. Correlation by user agent across accounts would also require both values to be available as usable fields on the failure event.

The ATT&CK mappings express detection intent. T1110 accompanies individual failures, T1110.001 repeated guessing, and T1110.003 the proposed cross-account pattern. An ordinary mistyped password is not an attack merely because the alert includes a technique ID.

Monitor OAuth with a clear identity boundary
#

Rule 110041 handles Google OAuth callbacks. It matches OmniauthCallbacksController, action google_oauth2 and status 302, then searches the raw event for an approved hd parameter. It is configured to emit a level-12 alert when that raw-text pattern is absent.

Test approved, unapproved, and missing hd values. Keep callback records and successful OAuth audit events distinct: they describe different parts of the authentication flow and should not be counted as interchangeable sessions.

The rule uses a negated match against the raw JSON, with alternatives for the two key/value orders. A regex written for raw JSON may not match the representation of a decoded field. Inspect the actual input to the matcher when testing this rule.

There is a more important boundary: a request parameter is not a verified identity claim. Google says domain restrictions should be checked using the hd claim in the validated ID token; the request parameter is a flow hint. See Google’s OpenID Connect documentation.

So this rule is a callback-parameter anomaly check. It does not prove that an unauthorized domain successfully authenticated, and its T1078 mapping does not establish compromised valid-account use. Missing parameters, legitimate callback variations and redirects after errors need negative tests too.

The downloadable copy replaces the original domain expression with example\.(?:org|net). That is a documented sanitization change, not a production allowlist recommendation.

Extend monitoring to access changes and repository activity
#

Successful authentication is the start of an investigation into what an account did. For an organization protecting proprietary code or customer information, changes to access and movement of repository data need attention alongside failed sign-ins.

Monitoring areaExample rulesSecurity interpretation
Tokens, SSH keys, and MFA settings110050110053, with selected audit names in 110030Review whether access was created or account security changed; confirm request outcomes and authorization
Project settings, membership, hooks, and related access controls110061, 110062Investigate changes that could alter who can reach or modify a repository
HTTP pushes and repeated push activity110064, 110065Identify account/repository activity and bursts; relate them to expected developer or automation work
SSH pushes and fetches110080110082Intended coverage for another repository access path; still needs a real SSH sample
Exports and large transfers110066, 110083110085Review potential data movement; volume alone does not establish exfiltration
Project/group lifecycle and administrative activity110067110074Investigate destructive or privileged actions; distinguish requests and job starts from completed outcomes

These rules provide starting points for monitoring. Validate SSH fields and lifecycle outcomes on your instance, and check for gaps in pipeline configuration and customer-data access separately. A rule covering repository activity does not establish visibility into every sensitive action.

For triage, preserve the actor, source address, repository, action, timestamp, and correlation ID where available. Compare the activity with that account’s role and expected workflow. A service account performing scheduled fetches needs different context from an unfamiliar account accessing several sensitive repositories.

Validate the path from source event to security alert
#

Validate each detection through the complete collection and analysis path before depending on it. The examples above establish source-event shapes; they do not establish that every downloadable rule will work unchanged on your manager.

Use positive, negative, and boundary cases to check the following behaviours:

TestEvidence to retain
One rejected web sign-inRaw request, decoded fields and match for 110100
Ordinary GET of the sign-in formConfirmation that the failed-POST rule does not match
Repeated rejected POSTs from one IPExact trigger event for 110101, timeframe boundary and suppression behaviour
Plain-text failure with an accountFile availability, collection and dstuser/srcip extraction for 110106
One account targeted repeatedlyResult for 110102 after reviewing the static-field operator
One IP, several accountsResult for reviewed 110103; compare distinct users with alternating repeated users
Different IPs targeting one accountWhether the intended account grouping works without source grouping
A successful login after failuresSuccess evidence and manual timeline review; no automatic sequence rule exists
Password, OAuth and MFA successAudit matches, required labels and actor field accuracy
Approved, unapproved and missing OAuth hdPositive and negative matches for 110041, with redirect outcomes checked
Account lockoutA real user_access_locked event before trusting 110013

Start on a test manager with the configuration loaded:

/var/ossec/bin/wazuh-logtest -v

Keep related events in the same test session when evaluating correlation. Inspect decoding before the final rule match, and retain negative cases as well as positive ones. Wazuh explains this workflow in its decoder and rule testing guide.

Then test through the agent. The example collection blocks use only-future-events=yes, so generate new activity after collection starts. Check file access, labels and the resulting indexed alert. A successful manual replay does not establish that the agent is reading the source file.

There is also a counting problem if both authentication paths work: one failed login may appear in both request and application logs. Summing every authentication_failed alert can overcount attempts. Success events can likewise represent different stages of one sign-in. Decide what a dashboard counter measures before naming it “logins.”

Build dashboards around security decisions
#

Use dashboards to answer the same questions that drove collection: who is attempting access, who authenticated, what access changed, and what happened to repositories. Keep an overview for prioritization and event ledgers for reconstruction. A useful panel lets an analyst move from an unusual count to the underlying account, source, time window, and events.

The downloads include GitLab Authentication and Account Security and GitLab Repository Activity and Anomalies. Both use the wazuh-alerts-* data view. Set the time window, refresh interval, and GitLab scope to match your operational needs.

The authentication dashboard is mostly counters, tables and event ledgers. It does not include an authentication time-series chart or an automatic failure-to-success join. The saved ledgers sort events newest first, which helps with manual investigation, but that is a different capability.

Authentication panelWhat its query and aggregation actually measure
Failed sign-ins / distinct source IPsCount of 110100 alert documents and cardinality of data.remote_ip.keyword
Failed sign-ins by source IPTop 25 addresses for 110100, with document count and distinct correlation IDs
Repeated-failure burstsCount of 110101 alerts by data.remote_ip.keyword, rather than the number of underlying attempts
One IP, many accounts110103 alerts grouped by data.srcip.keyword, with cardinality of data.dstuser.keyword
Account lockouts / lockouts by account110013 documents, grouped by data.meta.user.keyword in the table
Successful sign-insCombined document count for 110010, 110011, 110012 and 110105
Successful OAuth by account110011 grouped by data.meta.user.keyword, with distinct data.meta.remote_ip.keyword values
OAuth domain-violation ledger110041, displaying account, request IP, parameters and correlation ID

The success counter is therefore a count of matching records, not deduplicated sessions. The failed-sign-in counter also deserves a replay check: it selects only 110100, while the failure ledger includes both 110100 and 110101. Check how the final indexed rule changes when correlation fires before describing that counter as every rejected attempt.

The spraying panel has a subtler limitation. Its “Distinct accounts” metric reads the account field on correlation-alert documents. It does not expand every contributing failure into an account list. Even with a working rule, that number is not automatically the number of users targeted in the whole burst. The separate per-account ledger queries 110102, 110103 and 110106; underlying failure events remain necessary for reconstructing the sequence.

Its field paths also need validation: the export queries data.srcip.keyword and data.dstuser.keyword, while the custom decoder declares static srcip and dstuser. Inspect an actual indexed alert and adjust the panel to the field paths your deployment produces.

Check panel descriptions against their queries and the deployed rules. The downloadable OAuth caption refers to an older implementation using flattened params; the XML now matches raw log text. Update that caption when adapting the dashboard.

The repository dashboard provides the next part of an investigation: pushes by account and repository, read/write trends, transport split, lifecycle activity, source addresses, anonymous pressure and a level-7-and-above anomaly queue. Its push counter selects 110064 and 110080. As its own caption correctly points out, those are transport events, not commit counts.

Normalize account, repository, and address fields before combining HTTP and SSH activity in a panel. The HTTP panels use data.meta.user.keyword and data.meta.project.keyword, while the SSH rules expect gl_username and gl_project_path. HTTP request events can contain both remote_ip and meta.remote_ip; verify the indexed fields instead of inferring a mismatch from rule descriptions. Including both transport rule IDs in a query does not populate missing aggregation fields.

The lifecycle panels also measure different things. “Projects created” counts web/API create and API fork records. “Projects deleted” uses distinct project paths from 110067 and 110073, which reduces repeated-job counting but still does not prove completed deletion. “Projects pending deletion” counts paths seen by 110068 during the selected window, not a current inventory of all pending projects. The lifecycle-by-account table includes group deletion rule 110069 but deliberately excludes pending-project browsing.

One more mismatch: the repository anomaly table and raw anomaly feed use different group lists, despite captions suggesting the same queue. Neither includes an explicit rule.groups:gitlab condition, and there is no global GitLab filter. Shared groups such as data_access could bring unrelated alerts into those views. That is worth fixing before comparing their totals.

For investigation, I would start with the failed-sign-in ledger, isolate a source and time window, then inspect the success ledger and validated repository activity. The large-clone ledger includes data.correlation_id for looking up a related Rails event, but that lookup is manual; an existing restrictive panel query may need clearing to find the other event. A level-12 label still needs the underlying evidence before containment.

After importing the dashboards, generate known test activity and verify the resulting panels against indexed alerts. Confirm counts, field mappings, and drill-downs before using the views for operational decisions.

Make alerts actionable and keep the limits visible
#

Choose which validated detections enter the security team’s triage queue and which remain searchable context. Define an owner, severity, and investigation steps for each promoted alert. A Wazuh rule level or an imported dashboard does not configure an email, ticket, or on-call notification; notification delivery must be configured separately. Test it separately so a relevant event reaches the person expected to act.

For a suspicious authentication burst, establish the source and attempted accounts, look for subsequent successful authentication, then review access changes and repository activity in the same period. Use correlation IDs where they connect records and a wider timeline where they do not. Escalate based on the affected account’s privileges, repository sensitivity, and corroborating activity. Record the evidence and outcome so the team can tune the detection without losing its security purpose.

A source-IP threshold can miss attempts spread over many addresses or paced outside the configured window. Shared office egress, proxies and mobile address changes can also complicate attribution. Verify the address semantics before applying an IP-based response.

Similarly, high-volume Git activity can belong to automation. The wider ruleset matches automation user agents on pushes, but that alone does not identify a compromised token. A change to the application’s log format can break extraction without changing the XML at all.

The next useful work is to verify the account-aware path, retain repeatable tests and cross-check the dashboard against indexed events. Explicit failure-to-success correlation, identity-provider evidence and distributed spraying detection would be separate enhancements. Geographic enrichment is not implemented by a rule merely carrying an impossible_travel_candidate group.

Protecting GitLab means maintaining visibility over access to the organization’s code, data, and delivery environment. Start with the logs the instance actually produces, centralize the evidence, and build dashboards and alerts around meaningful security questions. Keep testing both the detection and the investigation path as GitLab and the organization’s workflows change.

Download the configuration and dashboards
#

The downloads include decoder, rule, collection, and dashboard examples. Identifying details have been removed and the OAuth allowlist uses example domains. The account-correlation and dashboard limitations discussed above remain in these reference files; validate and adapt them before deployment.

ResourceDownload
Decodergitlab-decoders.xml
Authentication rulesgitlab-auth-rules.xml
OAuth rulegitlab-oauth-rules.xml
JSON and audit rulesgitlab_rules_10_json.xml
Repository activity rulesgitlab_rules_30_git_activity.xml
Agent collection fragmentsgitlab-agent-localfile.xml
Authentication dashboard exportwazuh-dashboard-gitlab-authentication-security.ndjson
Repository activity dashboard exportwazuh-dashboard-gitlab-activity.ndjson
Sanitization and usage notesREADME.md

The dashboard copies preserve the example queries, aggregations, object IDs and captions, with identifying domains and a source subnet replaced by examples. Their known issues are documented rather than silently repaired. Both require an existing or remapped wazuh-alerts-* data view; its definition is not included in either export.

Related