[akamai] - Replace CEL input with OpenTelemetry akamai_siem receiver - #19496
Conversation
Elastic Docs Style Checker (Vale)Summary: 1 warning, 1 suggestion found
|
| File | Line | Rule | Message |
|---|---|---|---|
| packages/akamai/_dev/build/docs/README.md | 25 | Elastic.DirectionalLanguage | Don't use directional language. Use 'the following steps' instead of 'the below steps'. |
💡 Suggestions (1): Optional style improvements. Apply when helpful.
| File | Line | Rule | Message |
|---|---|---|---|
| packages/akamai/data_stream/siem_otel/manifest.yml | 103 | Elastic.WordChoice | Consider using 'deactivated, deselected, hidden, turned off, unavailable' instead of 'Disabled', unless the term is in the UI. |
The Vale linter checks documentation changes against the Elastic Docs style guide. To use Vale locally or report issues, refer to Elastic style guide for Vale.
TL;DR
Remediation
Investigation detailsRoot CauseThe The separate Evidence
Verification
Follow-upAfter correcting the changelog link, if the Akamai integration step still fails, share the full untruncated step log (or failed JUnit XML content) and I can map it to the exact source file/line for a second-pass fix recommendation. Note 🔒 Integrity filter blocked 2 itemsThe following items were blocked because they don't meet the GitHub integrity level.
To allow these resources, lower tools:
github:
min-integrity: approved # merged | approved | unapproved | noneWhat is this? | From workflow: PR Buildkite Detective Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not. |
|
@jamiehynds, wanted to get your opinion on this change from an user perspective. With the current limitations imposed by Fleet, having an otel receiver config within an existing data stream breaks it for existing users since fleet renames the index template by appending an The The issue now is about user perception. We end up having two similar looking inputs from the outside Do we keep both of these or phase out the older cc: @narph |
|
Collection transport - I'm assuming none of the managed OTel paths apply, since we're still hitting the same Akamai SIEM API and Akamai isn't pushing to us. mOTLP (the Managed OTLP Endpoint) is out - that's a destination you send to, not something that polls, so Akamai can't push to a receiver like that; ECF doesn't fit for the same reason. We need a durable collector to pull Akamai's API on an interval. Right? Agentless — Today agentless is limited to cel/httpjson, so I assume the gap is that the agentless runtime doesn't yet run the EDOT Collector / otel input type? Worth flagging: the CEL Akamai input can likely run agentless today, so if we make the OTel receiver the recommended path but it forces a self-managed agent, that's a regression for those users. What would it take to get the otel input supported in agentless? Packaging — would an OTel input package (akamai_input_otel) be a better fit than bolting the receiver into the existing data stream? My assumption is no: Akamai isn't OTel-native, we're only using the Collector to hit their API, and input packages store data OTel-native rather than ECS in logs-akamai.siem-* - so we'd lose pipeline/dashboard/detection-rule continuity for existing users and need a migration path, whereas your current design deliberately routes back through the existing ECS pipeline to keep all that working. cc @qcorporation @andrewkroh as this may relate to ingest hub onboarding, and it's the first example I'm aware of using an OTel collector but mapping back to ECS |
Really interesting conversation cc.ing @nimarezainia as well |
|
|
👀 I have started reviewing the PR |
|
My take is this shouldn't be an additional input. The receiver should replace the CEL input with an invisible migration, so we have one API collection mechanism and one code path.
I would like the same package, replaced input, same dataset. |
@andrewkroh, but what about the state ? Currently the CEL state is not compatible with otel receiver, so it will be a breaking change for existing users on older stacks and then upgrading to 9.5 ? |
@jamiehynds we are no longer bound by cel/httpjson only inputs, observabilty team has already added aws-metrics (as an example) and worked on supporting many other integrations. @ishleenk17 and @lalit-satapathy can comment on the otel input and agentless deployment as their teams have been adapting many otel packages to agentless as well. |
@ShourieG Isn't the pagination offset token only valid for 2 minutes? This would mean that cursor reset is a very normal occurrence, so a change-over that does not retain state will be indistinguishable from other events like an agent software upgrade that causes more than 2 minutes of downtime. |
Yes this is true, token validity is indeed 2mins atm. But then I think we should explicitly call it out in some upgrade note/description etc, that this will be a breaking change, and increment to version 4.0.0. This is just to preserve clarity with the end user on what's happening. I have just one concern with out right replacing, that is, is not better to do a bit of real-world testing with end users/customers before completely removing the CEL input ? That way we could potentially identify any issues that might exist. The CEL input is GA and has been for a while. The new input has not been stress tested under real circumstances yet. |
Is the question if OTel receivers can be used in agentless mode ? |
|
The reason we developed a dedicated Akamai input in OTel was to address known limitations with the Akamai SIEM API and the existing CEL-based implementation. This issue has affected not only us but also other vendors and competitors that have integrated with the API. Adding both options would likely create confusion for users without really solving the underlying problem. We'd still be offering an ingestion method that we know has limitations and isn't the preferred approach. We should stay consistent with how we've handled this in the past and replace the existing input rather than add another option. Since the upgrade impact and the effort required to switch inputs are minimal, replacing it gives users a simpler experience and steers them toward the more reliable solution. |
|
@narph @andrewkroh, Did an analysis with the results below, the main friction of replacing without breaking changes is that the ssl/tls configs differ a bit in beats vs otel. Akamai SIEM: TLS config mapping (Beats
|
| Beats (CEL input) | OTel (akamai_siem receiver) |
|
|---|---|---|
| Config block name | ssl: |
tls: |
| Underlying protocol | TLS | TLS (identical) |
| Source schema | libbeat SSL common config | configtls.ClientConfig v1.60.0 (squashed via confighttp) |
The bytes on the wire are the same. The migration cost is translating one YAML schema
into the other, not changing the encryption.
Beats ssl: (current CEL input)
ssl:
certificate_authorities: # LIST of files or inline PEM
- /etc/agent/certs/akamai-ca.pem
- /etc/agent/certs/corp-root.pem
certificate: /etc/agent/certs/client.pem
key: /etc/agent/certs/client-key.pem
key_passphrase: "${KEY_PASS}"
verification_mode: certificate # full | strict | certificate | none
supported_protocols: [TLSv1.2, TLSv1.3] # explicit list
cipher_suites:
- ECDHE-RSA-AES-256-GCM-SHA384 # OpenSSL-style names
curve_types: [P-256]
ca_trusted_fingerprint: "9f8b...c2" # pin by sha256 fingerprintOTel tls: (akamai_siem receiver)
confighttp.ClientConfig squashes configtls.ClientConfig
at the receiver root, so this block sits directly under the receiver next to endpoint:.
The keys below are defined in configtls.Config (shared) plus the
client-only fields in configtls.ClientConfig.
tls:
ca_file: /etc/agent/certs/akamai-bundle.pem # the two CAs above concatenated into ONE file
cert_file: /etc/agent/certs/client.pem
key_file: /etc/agent/certs/client-key.pem
# key_passphrase: -> no equivalent; key must be decrypted first
insecure_skip_verify: false # only `verification_mode: none` maps here (-> true)
min_version: "1.2" # note "1.2", not "TLSv1.2"
max_version: "1.3"
cipher_suites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 # IANA/Go names, NOT the Beats names
curve_preferences: [P-256]
include_system_ca_certs_pool: true # see behavioral note below
# ca_trusted_fingerprint: -> no equivalentName changes (mechanical renames)
Beats ssl: |
OTel tls: |
Note |
|---|---|---|
certificate_authorities (list) |
ca_file / ca_pem (single) |
list → single; concat multiple CAs into one PEM |
certificate |
cert_file / cert_pem |
rename only |
key |
key_file / key_pem |
rename only |
curve_types |
curve_preferences |
rename (value naming also differs) |
cipher_suites |
cipher_suites |
same key, different value vocabulary (OpenSSL → IANA/Go names) |
Lossy conversions (need human judgment)
Beats ssl: |
OTel tls: |
Why lossy |
|---|---|---|
verification_mode: none |
insecure_skip_verify: true |
enum → bool |
verification_mode: full / strict |
insecure_skip_verify: false (default) |
enum → bool |
supported_protocols: [..] |
min_version / max_version |
list → range; can't express non-contiguous sets (e.g. 1.1 + 1.3 but not 1.2); version string format differs |
No OTel equivalent
Beats ssl: |
Status |
|---|---|
key_passphrase |
❌ no field — passphrase-protected keys won't load; decrypt the key first |
verification_mode: certificate |
❌ no equivalent — "verify chain but skip hostname" can't be expressed (OTel is verify-all or verify-nothing) |
ca_trusted_fingerprint / ca_sha256 |
❌ no fingerprint/sha256 CA pinning in configtls |
renegotiation |
❌ no equivalent |
Behavioral changes: system CA pool default flips
In configtls, specifying ca_file/ca_pem means you trust only that CA — the system
root pool is excluded unless you set include_system_ca_certs_pool: true. A Beats user who
added a private CA generally still has system roots available, so a naïve port can silently
break TLS to anything signed by a public CA.
References
OTel side (resolved module versions in this repo):
configtls.ClientConfig— thetls:schema (client-only fields:insecure,
insecure_skip_verify,server_name_override), v1.60.0:
pkg.go.dev · sourceconfigtls.Config— the shared/squashed TLS fields (ca_file,ca_pem,cert_file,
cert_pem,key_file,key_pem,min_version,max_version,cipher_suites,
curve_preferences,include_system_ca_certs_pool,reload_interval, …), v1.60.0:
pkg.go.devconfighttp.ClientConfig— owns thetlsfield and applies it viaToClient
(cc.TLS.LoadTLSConfig→transport.TLSClientConfig), v0.154.0:
pkg.go.dev ·ToClient· source
In-repo wiring (this receiver):
- Squash that exposes
tls:at the receiver root —config.go(HTTP confighttp.ClientConfigwith,squash) - Where the client (incl. TLS transport) is built —
receiver.go(r.cfg.HTTP.ToClient(...))
Beats side:
- libbeat
tlscommon— thessl:schema source: config.go - SSL common config reference (what the CEL
sslvar description links to): elastic.co
fc275fc to
0bb8dfc
Compare
|
@narph @andrewkroh, I've added a key by key explanation for the hard gaps (missing keys) for the ssl block and their possible impact. Otel vs Beats (TLS Gaps)
Examples to explain each scenario1.
|
|
This looks like a functionality degradation, but I wonder how often these options are actually used. @andrewkroh, do you think we can proceed with this? It could break existing setups. |
|
None of those missing TLS config options seem like blockers because the input is talking to a SaaS API with a CA cert issued by a widely trusted CA. If this is widely shared TLS config in the otel, then we should log issue(s) to close that gap between what the agent offers because it could be important for future use-cases. |
0bb8dfc to
39bfd25
Compare
The OpenTelemetry akamai_siem receiver becomes the collection method for the Akamai SIEM API, replacing the CEL input. The policy template now offers "Collect Akamai SIEM logs via API" (backed by the receiver) alongside the Google Cloud Storage method, and the receiver is no longer labelled a technical preview. This is a breaking change: existing policies that collect via the API must be reconfigured after upgrading. The package major version is bumped to 4.0.0 and the minimum supported Elastic Stack version is raised to 9.5.0. The README is reorganised around the two collection methods (API and GCS), and the cursor-persistence note now documents that persistence is not guaranteed across stack upgrades and breaking changes.
The OpenTelemetry akamai_siem receiver already replaced the CEL input as the API collection method, so the leftover CEL artifacts are no longer needed. This removes the CEL stream from the siem data stream manifest, its cel.yml.hbs template, the CEL system test, and an orphaned CEL pipeline test config. The emulator-based system test is re-wired onto the siem_otel data stream using the otelcol input against the same akamai-siem-emulator mock. The test is skipped for now because the receiver redirects all events to the akamai.siem dataset and elastic-package cannot yet assert hit counts on a redirected dataset (elastic/elastic-package#2109). The shared akamai.siem ingest pipeline remains covered by the siem pipeline test.
cd865b7 to
7422279
Compare
🚀 Benchmarks reportPackage
|
| Data stream | Previous EPS | New EPS | Diff (%) | Result |
|---|---|---|---|---|
siem |
1090.51 | 851.79 | -238.72 (-21.89%) | 💔 |
To see the full report comment with /test benchmark fullreport
Render the data_stream.dataset var in otelcol.yml.hbs instead of a hardcoded literal so the dataset declared in the Fleet policy is the one the receiver writes; the default still targets akamai.siem. Rework the tags OTTL statement to emit preserve_original_event first so an empty tags list can no longer render an invalid list literal. Extend the 4.0.0 breaking-change note with the 9.5.0 minimum stack version and the Beats ssl to OpenTelemetry tls schema change, add the disabled-by-default input toggle to the API setup steps, and dedupe the cursor-persistence note while scoping the replay-deduplication claim to the same backing index. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Address review feedback on the OTel rework. The otelcol collection path had no executable coverage because the emulator system test is skipped, so add a policy test that pins the Fleet-rendered collector config: the injected transform routes events to the akamai.siem dataset, dynamic_dataset/dynamic_namespace widen the API key grant to logs-*-*, and the storage reference is rewritten to the renamed file_storage extension. The expected policy is generated against 9.5.0-SNAPSHOT, the version CI resolves for the ^9.5.0 condition. Retitle the config_ids variable from "Zone ID" to "Security Configuration IDs" so the Fleet UI matches the variable description and the README wording; the old title was inherited from the removed CEL stream. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
chrisberkhout
left a comment
There was a problem hiding this comment.
For the commit message:
- Has this been manually tested against a live API?
- Should it be "OpenTelemetry
akamai_siemreceiver" rather than "OpenTelemetryakamaisiemreceiver"?
Question: Can you please say the reason why the new siem_otel collection can't be done directly in data_stream/siem if it's correct that it wouldn't work? Is it because of a fleet issue during upgrade? If it could be done it would avoid data_steam/siem_otel existing without being populated itself.
|
|
||
| The Akamai integration collects events from the Akamai API, specifically reading from the [Akamai SIEM API](https://techdocs.akamai.com/siem-integration/reference/api). | ||
|
|
||
| > **Breaking change in 4.0.0**: The backend used to collect Akamai SIEM logs from the API has changed. This version requires Elastic Stack 9.5.0 or later. After upgrading, existing agent policies that collect Akamai SIEM logs via the API must be reconfigured for data collection to resume. If you previously set the advanced **SSL Configuration** option, it must be rewritten using the OpenTelemetry `tls` schema (`ca_file`/`ca_pem`, `cert_file`/`cert_pem`, `key_file`/`key_pem`, `insecure_skip_verify`, `min_version`, `max_version`) rather than the Beats keys (`certificate_authorities`, `verification_mode`, `supported_protocols`). Collection from Google Cloud Storage is unaffected. |
There was a problem hiding this comment.
Could mention that it's only possible to get 12 hours of historical data, so the new policy should be configured within that time to avoid data gaps.
There was a problem hiding this comment.
Don't see this part. Did you mean to commit something for that?
This has been live tested against Andrew's mock Akamai API at https://proteus.sit.estc.dev/. There's a mock active, you can check it out. Getting access to a real env is tricky because of setup issues. We can rename to OpenTelemetry The reason we can't do |
Rename the enable_storage variable to persist_cursor across the manifest, agent template, and test configurations, and reword its description and the README to match. Drop the placeholder default for api_host and render event_limit only when set. Split the tags transform statement over several lines using template whitespace trimming so it is easier to read; the rendered policy is unchanged. Add policy tests covering preserve_original_event with custom tags and disabled cursor persistence. Document in the changelog that dynamic dataset/namespace routing widens the agent output API key scope to logs-*-*. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@chrisberkhout, I've addressed all the issues. |
Review summaryIssues found across the latest commits 2f570bf — 1 high, 1 medium
Issues found across earlier commits d47ae09 — 2 medium
Issues found across earlier commits ef0acd7 — 2 high, 2 medium
Issues found across earlier commits 3bf57bc — 1 high, 1 medium, 1 low
Issues found across earlier commits cf99bfa…7422279 (29 commits) — 3 medium, 2 low
Issues found across earlier commits 26c576c…cd865b7 (250 commits) — 2 medium
🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills
|
Okay, that's fine. Could optionally note the mock-only testing in the end of the commit message.
Thanks, good explanation. That makes sense. So it's clear in the PR, but for future maintenance it would help to have a comment in the policy config, near the
Okay. I see |
chrisberkhout
left a comment
There was a problem hiding this comment.
Thanks for the updates and explanations.
Remaining points worth a final look are only about doc/code comments:
- #19496 (comment)
(policy update required within max data range of 12h to avoid gaps) - #19496 (comment)
(testing in commit message, maintainer comment in policy, receiver naming)
Otherwise GTG
|
Tick the box to add this pull request to the merge queue (same as
|
In bodymap mode the Elasticsearch exporter serializes only the log record body into the document, and the ingest pipeline sets @timestamp only when httpMessage.start is present, so events without it (Akamai internal 500s) were rejected by the data stream. Seed @timestamp from the record time as a fallback; the pipeline still overwrites it with the real event time when available. Also address review feedback: correct the system test fixture and the initial_interval description to say the receiver rejects lookbacks over 12h rather than clamping, document receiver-level dataset routing next to the data_stream block, and note the 12-hour API window in the upgrade instructions. Verified against a mock Akamai SIEM API only: 2.4M events ingested end to end with no failure store entries, pipeline errors, or mapping conflicts, and event timestamps preserved. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
✅ All changelog entries have the correct PR link. |
akamaisiemreceiver
💚 Build Succeeded
History
cc @ShourieG |
|
Package akamai - 4.0.0 containing this change is available at https://epr.elastic.co/package/akamai/4.0.0/ |
Type of change
Proposed commit message
Checklist
changelog.ymlfile.NOTE:
Upgrade path was tested locally before going for a breaking-change
Steps:
3.2.0 (CEL Input)was configured with akamai mock server and ingestion started.3.3.0was made with CEL being replaced by otel receiver and the input was enabled by default.In this scenario, while upgrading we saw the following error :-
This is because the separate data stream approach ( adopted due to fleet limitations) changed the fleet computed attribute paths and they were no longer configured.
4.0.0and kept the input disabled by default and the upgrade happened without any errors.Author's Checklist
How to test this PR locally
Related issues
Screenshots
All Inputs
Receiver Config