CEE verification protocol¶
Status: written, never executed. Nothing here has been run. It is the procedure for finding out whether putting a Dell CEE server between a PowerScale cluster and cee-exporter produces events this exporter already understands — not a claim that it does.
CEE ships for both Windows and Linux and either will answer the question; the procedure covers both, and says which to prefer.
Read this alongside powerscale-verification.md, which covers the direct path (OneFS PUTs straight at the exporter). That path has been run; this one has not.
Why this exists¶
The direct path was measured on 2026-08-12 against a live 4-node OneFS 9.13.0.0 cluster, and it half-worked:
- Transport: fine. The cluster reaches the exporter, the handshake is
answered, all four nodes heartbeat, and
Protocol Audit Cee Timeadvances. - Events: undecodable. OneFS sends its events inside
<CheckFileRequest>withArgs/@action="11", carrying an<NFSEventArgs>whoseeventTypeis a numeric bitmask and whose path is base64 UTF-16LE.pkg/mapperkeys on theCEPP_*strings PowerStore's CEE emits. Six values were observed (8, 32, 128, 256, 512, 2048); only 8 (open) and 128/256 (closes) are identified.
So the exporter currently answers PowerScale events and throws them away,
counting them in cee_events_dropped_total.
That leaves two ways forward. Write a decoder for the OneFS dialect — weeks of
guessing bitmask values with one capture per isolated operation — or let
Dell's own CEE do the translation and see whether what comes out the far side
is already CEPP_*.
This protocol answers that, and it is worth answering first because a pass means zero new exporter code.
The one question¶
Does a Dell CEE server, fed by OneFS, emit
CEPP_*event payloads — the same dialect PowerStore's CEE emits andpkg/mapperalready handles?
Everything below exists to answer that. Three outcomes, all useful:
| Outcome | Meaning | Work implied |
|---|---|---|
CEE emits CEPP_* events |
PowerScale support already works via CEE | None — record it and promote the PROMISES row |
| CEE emits events in some third shape | Transport works, one new mapper dialect | Mapper keys, measurable from the capture |
| CEE forwards nothing | OneFS→CEE link is the problem, not the exporter | Debug CEE, not this repo |
Topology¶
Direct path, as measured (v5.4.0 behaviour):
What this protocol sets up:
OneFS ──HTTP PUT :12228──▶ Dell CEE ──HTTP PUT──▶ cee-exporter
<CheckFileRequest> (translates?) <RegisterRequest/> + <CEEEvent>?
The exporter's role does not change: it is the CEPA consumer, an HTTP listener that answers PUTs. Only who PUTs to it changes.
Do not leave both URIs configured
isi audit settings global --cee-server-uris is a list, and OneFS
distributes events across the servers in it. If the exporter's direct URI
stays in that list next to the new CEE server's, roughly half the events go
down the direct path — where this exporter acknowledges them and destroys
them, because the ACK advances the cluster's forwarding cursor. The other
half go through CEE and are the only ones you can measure.
The result is a run that looks half-broken for a reason that has nothing to do with what you are testing, and a set of audit records that no longer exist. Replace the URI, never append to it — step D2.
Windows or Linux¶
CEE ships for both, and either answers the question. They differ in ways that matter for a lab:
| Windows | Linux | |
|---|---|---|
| Delivery protocols | RPC and HTTP | HTTP only |
| Configuration | Registry, HKLM\SOFTWARE\EMC\CEE\CEPP |
One XML file, /opt/CEEPack/emc_cee_config.xml |
| Service control | Restart-Service |
/opt/CEEPack/emc_cee_svc restart |
| Log | Windows Application event log | /opt/CEEPack/emc_cee_svc.log |
| Host needed | A Windows box | Any RHEL 9.x host — possibly the one already running the exporter |
Prefer Linux if you have the choice. It is HTTP-only, which removes a whole class of failure: on Windows, delivery can silently be attempted over RPC and the HTTP server has to be explicitly enabled, so "CEE received the event but the exporter saw nothing" has one extra cause. The Linux configuration is also a single file you can diff and put in the results record, rather than registry values you have to screenshot.
EndPoint has identical semantics on both: a semicolon-separated list of
PartnerId@http://address:port, case sensitive.
Prerequisites¶
| CEE host | RHEL 9.x, or Windows Server 2016+ / Windows 10+ — reachable from the cluster and able to reach the exporter |
| CEE version | 9.x — Dell downloads |
| Exporter | v5.4.0 or later |
| Cluster | The same one used for the direct run, so the comparison is like-for-like |
| Ports | Cluster → CEE 12228/tcp; CEE → exporter, whatever port you put in EndPoint |
12228 is claimed twice
CEE's own HTTP listener defaults to 12228, and so does cee-exporter. Putting
both on one host with default settings means whichever starts second fails
to bind — or, worse, the cluster's PUTs reach the exporter directly and CEE
is never in the path at all, which looks like a successful test right up
until you read the payloads and find CheckFileRequest.
Colocating is otherwise fine and convenient on Linux. Move the exporter:
and point EndPoint at :12229. Then confirm who owns what before
starting the run:
Part A — Install CEE¶
Do A-Linux or A-Windows, not both. Everything from Part C onwards is identical.
A-Linux. Install on RHEL¶
Record the exact version — it belongs in the results table, because the translation behaviour this protocol measures may differ between releases.
Turn on verbose logging before the run. On Linux this is the same file you are about to configure, so it costs one edit rather than a second restart:
sudo cp /opt/CEEPack/emc_cee_config.xml /opt/CEEPack/emc_cee_config.xml.orig
# Set Debug and Verbose to 63 in emc_cee_config.xml.
sudo /opt/CEEPack/emc_cee_svc restart
tail -f /opt/CEEPack/emc_cee_svc.log
Keep the .orig copy. It is both the rollback and the evidence of what the
host looked like before.
A-Windows. Install on Windows¶
Run the CEE installer. It installs the CAVA (antivirus) and CEPA (event publishing) facilities; only CEPA matters here.
Find the service names — do not assume them, they have varied across releases:
Get-Service | Where-Object { $_.Name -match 'CEE|CEPA|CAVA|EMC' } |
Format-Table Name, DisplayName, Status
Whatever the CEPA service is called on this build is the one to restart in B4 and watch in F2.
Part B — Configure CEE to publish to the exporter¶
Same three settings either way — enable the Audit facility, point EndPoint at
the exporter, leave the other subfacilities alone. Only the storage differs: an
XML file on Linux, registry values on Windows. All protocol strings are case
sensitive on both.
B-Linux. Edit emc_cee_config.xml¶
There is no HTTP-server toggle to find: Linux CEE delivers over HTTP only, which is the reason to prefer it for this test.
Edit /opt/CEEPack/emc_cee_config.xml so the CEPP Audit section is enabled and
its EndPoint names the exporter:
<CEPP>
<Audit>
<Configuration>
<Enabled>1</Enabled>
<EndPoint>cee-exporter@http://<exporter-ip>:12228</EndPoint>
</Configuration>
</Audit>
</CEPP>
Match the element names to what the installed file already contains rather than to the sketch above — the surrounding structure varies by version, and this is one file you can read in full before touching it.
Two ways to mangle the value in a file
The semicolon. In an XML file it is an ordinary character and needs
no escaping. In the shell command that writes it, ; ends the command.
Editing the file with an editor is safe; echo/sed without quoting is
not.
# Wrong — the shell ends the command at the semicolon.
sudo sed -i s/OLD/a@http://x:1;b@http://y:2/ /opt/CEEPack/emc_cee_config.xml
# Right — quoted.
sudo sed -i 's|OLD|a@http://x:1;b@http://y:2|' /opt/CEEPack/emc_cee_config.xml
The ampersand. If a PartnerId or URL ever contains &, it must be
written & in the XML or CEE will not parse the file at all — a
failure that shows up as the service refusing to start, not as a bad
endpoint.
Read the value back after every edit, as above.
B-Windows. Set the registry values¶
All of this is under HKLM\SOFTWARE\EMC\CEE\CEPP.
CEE on Windows can deliver over RPC or HTTP, so the HTTP server has to be switched on explicitly. This step has no Linux equivalent:
$http = 'HKLM:\SOFTWARE\EMC\CEE\CEPP\Configuration\Security\Http'
New-Item -Path $http -Force | Out-Null
Set-ItemProperty -Path $http -Name 'ServerEnabled' -Value 1 -Type DWord
Get-ItemProperty -Path $http
Then point the Audit facility at the exporter.
EndPoint is a semicolon-separated list in PartnerId@http://address:port
form for HTTP delivery. The PartnerId is a name you choose; it identifies
this consumer to CEE.
$audit = 'HKLM:\SOFTWARE\EMC\CEE\CEPP\Audit\Configuration'
Set-ItemProperty -Path $audit -Name 'Enabled' -Value 1 -Type DWord
Set-ItemProperty -Path $audit -Name 'EndPoint' `
-Value 'cee-exporter@http://<exporter-ip>:12228' -Type String
Get-ItemProperty -Path $audit | Format-List Enabled, EndPoint
If EndPoint already has a value — another consumer such as a SIEM agent —
append with a semicolon rather than overwriting it. That is the opposite of
the rule for the OneFS URI list in D2, and for the opposite reason: CEE
delivers to every endpoint, while OneFS distributes across its URIs.
Overwriting it here silently unhooks whatever was already consuming events.
Read, append, write back — never retype the existing value from a screenshot:
$existing = (Get-ItemProperty -Path $audit -Name 'EndPoint' -ErrorAction SilentlyContinue).EndPoint
$mine = 'cee-exporter@http://<exporter-ip>:12228'
$value = if ([string]::IsNullOrWhiteSpace($existing)) { $mine } else { "$existing;$mine" }
Set-ItemProperty -Path $audit -Name 'EndPoint' -Value $value -Type String
(Get-ItemProperty -Path $audit).EndPoint -split ';' # one endpoint per line
Quote the semicolon
The ; is a statement separator in PowerShell and a nothing-in-particular
in cmd.exe. Inside 'single' or "double" quotes it is a literal
character and the value lands intact, which is why every example here is
quoted. Unquoted, PowerShell ends the command at the semicolon and writes a
truncated EndPoint containing only the first consumer — the other one
stops receiving events, with nothing in any log to say why.
The same applies to reg.exe: quote the whole /d argument.
reg add "HKLM\SOFTWARE\EMC\CEE\CEPP\Audit\Configuration" /v EndPoint ^
/t REG_SZ /d "other-app@http://10.0.0.9:12229;cee-exporter@http://10.0.0.8:12228" /f
Verify by reading the value back and splitting it, as above. A semicolon count that does not match the number of consumers you expect is the bug.
The path component is absent above on purpose. The exporter routes on HTTP
method only, never on path (pkg/server/server.go), so /cee, /vee or
nothing all behave identically. If CEE insists on a path, any value works.
B3. Leave VCAPS and CQM alone — both platforms¶
CEPA has separate subfacilities: Audit, VCAPS (asynchronous post-events) and CQM. Enabling more than one makes it ambiguous which produced a given payload, and VCAPS in particular is the one that batches thousands of events per PUT — a different question from the one this protocol asks.
# Linux — read the whole file; it is short enough.
grep -nEi '<(Audit|VCAPS|CQM)>|<Enabled>' /opt/CEEPack/emc_cee_config.xml
# Windows — expect these absent or disabled.
Get-ChildItem 'HKLM:\SOFTWARE\EMC\CEE\CEPP' | Select-Object Name
B4. Restart CEPA — both platforms¶
Configuration is read at service start, on either platform.
# Windows — the service name discovered in A-Windows.
Restart-Service -Name '<the CEPA service>' -Force
Get-Service -Name '<the CEPA service>'
Part C — Start the exporter with capture running¶
Do this before pointing OneFS at CEE. The RegisterRequest handshake and
the first event batch are the two most valuable packets in the exercise, and
neither is repeatable once the cluster's forwarder advances past them.
On the exporter host:
sudo tcpdump -i any -s0 -w cee-windows.pcap 'tcp port 12228' &
cat > /etc/cee-exporter/config.toml <<'TOML'
[listen]
addr = "0.0.0.0:12228"
[output]
type = "evtx"
evtx_path = "/var/log/cee-exporter/cee-windows-test.evtx"
[metrics]
addr = "0.0.0.0:9228"
TOML
CEE_LOG_LEVEL=debug ./cee-exporter -config /etc/cee-exporter/config.toml
Baseline before anything is pointed at it — the absence matters as much as the later presence:
curl -s http://localhost:12228/health | jq .
curl -s http://localhost:9228/metrics | grep -E 'cee_cepa|cee_events'
cee_cepa_last_request_unix_seconds should have no series at all, and
cee_events_dropped_total should be 0. Any series appearing later came from
this run.
Part D — Point OneFS at CEE¶
D1. Record the current setting first¶
You are about to overwrite it, and you will need it for rollback:
Write the existing CEE Server URIs value down somewhere outside the cluster.
D2. Replace the URI — do not append¶
Clear the list rather than removing one entry by name — --clear cannot leave
behind a URI you forgot was there, and D1 already recorded what to restore:
isi audit settings global modify --clear-cee-server-uris
isi audit settings global modify \
--add-cee-server-uris=http://<cee-host>:12228/cee
isi audit settings global view
--remove-cee-server-uris=<uri> also exists if you would rather drop a single
entry, but it silently does nothing when the URI does not match exactly.
Confirm the list contains exactly one URI, the Windows host. See the danger note above for why.
D3. Forward only from now on¶
Without this, a cluster that has had auditing enabled for a while replays its whole backlog at the new endpoint — thousands of events that predate the test, which makes both the counts and the throughput meaningless:
Part E — Generate a known set of events¶
Mount the audit share and perform one operation of each type, in this order, noting the wall-clock time of the first:
sudo mount -t cifs //<cluster>/audit-test /mnt/audit -o user=<user>
cd /mnt/audit
echo hello > alpha.txt # create + write + close
cat alpha.txt # read
mv alpha.txt beta.txt # rename
chmod 640 beta.txt # set_security
rm beta.txt # delete
Five operations. Anything other than five event families arriving is itself a result — CEE may coalesce, or emit several events per operation.
Part F — Verify hop by hop¶
Three hops, three places to lose events. Check them in order; blaming the exporter for something CEE never forwarded wastes the most time.
F1. Did the cluster send?¶
isi_audit_viewer -t protocol # events recorded at all
isi audit progress view # Cee Time vs Log Time — a gap means queued
tail -f /var/log/isi_audit_cee.log # delivery errors land here
A vcstatus in that log is CEE's answer coming back. Two values are already
known from the direct run: 0x1 is VC_ERROR_SETUP, 0x16 is
VC_ERROR_CEPP_NOT_FOUND — which specifically means CEE is running but the
partner app named in EndPoint is not reachable. Seeing 0x16 here points at
Part B, not at the cluster.
F2. Did CEE receive and forward?¶
# Linux — with Debug/Verbose at 63 from A-Linux, this is the richest
# view of the whole chain.
tail -f /opt/CEEPack/emc_cee_svc.log
# Windows
Get-EventLog -LogName Application -Source '*CEE*','*CEPA*' -Newest 50 |
Format-Table TimeGenerated, EntryType, Message -Wrap
If CEE logs receipt but the exporter sees nothing, the problem is EndPoint
(Part B) or the network between CEE and the exporter — not OneFS.
F3. Did the exporter receive, and in what dialect?¶
This is the measurement the whole protocol exists for.
cee_cepa_registrations_total{remote="<cee-host>"}climbing → CEE is sending theRegisterRequesthandshake, same as PowerStore's CEE.cee_events_received_total> 0 → the payload parsed asCEEEvent. This is the pass condition. It means CEE translated the OneFS dialect into the onepkg/parseralready reads.cee_events_dropped_totalclimbing while received stays 0 → CEE is forwarding the OneFSCheckFileRequestdialect unchanged. Transport works, translation does not.
Then read the wire, because the counter tells you that it parsed, not what the event types were:
sudo pkill tcpdump
tcpdump -r cee-windows.pcap -A 'tcp port 12228' | grep -aoE '<EventType>[^<]+' | sort -u
Those strings, verbatim, are the answer. CEPP_* means no exporter change is
needed.
F4. Did anything come out the far end?¶
ls -l /var/log/cee-exporter/cee-windows-test.evtx
evtx dump /var/log/cee-exporter/cee-windows-test.evtx | head -40
Event IDs 4663 / 4660 / 4670 with the right paths closes the loop from a file operation on a client to a record in a backend.
Rollback¶
Whatever the outcome, put the cluster back:
isi audit settings global modify \
--remove-cee-server-uris=http://<cee-host>:12228/cee
# Restore whatever D1 recorded.
isi audit settings global view
Leaving the CEE host in the URI list after the test means audit events keep flowing through a lab machine.
Results record¶
Fill this in when the protocol is run. An empty row is not a failure — it is an accurate statement that nobody has looked yet.
| Question | Result (date / CEE version / OneFS version) |
|---|---|
| CEE platform (Linux/Windows), version, service name | |
CEE sends RegisterRequest to the exporter (yes/no) |
|
| Payload encoding (UTF-8 / UTF-16LE / BOM) | |
| Event type strings, verbatim | |
cee_events_received_total after the five operations |
|
cee_events_dropped_total after the five operations |
|
| Event count vs the five operations performed | |
| Events mapped to a Windows event ID (count / total) | |
| Backend received the events (EVTX, evidence) |
Once filled, add the corresponding rows to docs/PROMISES.md with the same
evidence and cite this document.
Known unknowns¶
Stated explicitly so they are not mistaken for oversights:
- Whether CEE translates the OneFS dialect at all. The whole point. CEE may
be a router rather than a translator, in which case the exporter receives the
same
CheckFileRequestpayloads it cannot decode today, just from a different IP. - Whether the
PartnerIdappears in the forwarded payload. If CEE labels events with it, that is a field the exporter currently ignores. - Whether CEE batches. PowerStore's CEE uses VCAPS batches of thousands of
events per PUT. Whether the Audit facility batches OneFS-sourced events the
same way decides whether
gelf_protocol = "tcp"is required in production. - HTTPS. CEE URIs are documented as
http://throughout. The exporter's TLS listener is untested against CEE. - Which CEE releases behave alike. One version measured is one version known.
Sources¶
- Using the Common Event Enabler on Windows Platforms 9.x (Dell)
- PowerScale: Linux CEE debugging and log gather —
/opt/CEEPack/emc_cee_config.xml,emc_cee_svc(Dell KB 000009293) - Common Event Enabler — downloads and support (Dell)
- Configure CEE for Windows — OneFS CLI Administration Guide
- Configure CEE servers to deliver protocol audit events — OneFS CLI Administration Guide
- CEPP server state ERROR_CEPP_NOT_FOUND (Dell KB 000052027)
- Install Dell CEE — registry
EndPointformat (Netwrix) - File System Auditing with Dell PowerScale and Dell Common Event Enabler