Conversation
Every Elasticsearch request in the lab was unauthenticated. The only two
Authorization headers in data/ were both on the ClickHouse side, and the
throwaway cluster in _base/ runs with xpack.security.enabled=false -- so the
tools worked there and could not connect to any real 8.x cluster, where
security is on by default. Found while answering "can another agent just
follow this?", which is the honest answer to that question.
es_client.py is shared rather than copied into four scripts, because the
credential handling is the part that is either right or wrong in one place:
* basic auth (ES_USER/ES_PASSWORD) or an API key (ES_API_KEY), and both at
once is an error rather than a precedence rule -- a tool that silently
picks one gets debugged against the wrong identity
* TLS against a private CA (ES_CA_CERT), since 8.x generates its own on
first start, plus --es-insecure that warns on every call. The alternative
to that flag is not "everyone configures a CA properly", it is "someone
disables security on the source cluster"
* credentials come from the environment and are refused in a URL, which
ends up in shell history, ps and error messages. run.py passes them to
the export.py it spawns in the child's environment, never in its argv
* 401 and 403 are translated into the thing to change, and a wrong password
prints a sentence instead of a traceback
The minimum privileges, found by narrowing an API key until each tool broke:
cluster [monitor] and index [read, view_index_metadata, monitor]. The
index-level monitor is the one that gets left out -- _cat/indices needs both
cluster:monitor/state and indices:monitor/stats, and the 403 names the action
rather than the privilege, which is why the hint says it outright.
_base/ gains an `elastic-secure` profile: the same Elasticsearch with security
on, on 9201, so the authenticated path has a reproducible home instead of
being tested once by hand. HTTP TLS is off there on purpose -- authentication
was the gap, and a self-signed CA on top would mean copying a certificate out
of a container before anything runs at all. The CA path is verified against a
default-configuration container instead.
Verified on Elasticsearch 8.17.0 with security enabled: the whole pipeline
with basic auth, then again with an API key scoped to exactly those
privileges (20,000 documents, 3 chunks, 20,000 distinct _id in ClickHouse
26.6.8.7); https with ES_CA_CERT connects, without it fails with one line of
cause and one of remedy, and --es-insecure runs while warning. Both
credentials together and credentials in a URL are refused. The unauthenticated
path still runs end to end -- 300,000 documents, 4 chunks, parity passing --
so the quick path did not pay for this.
Closes #42
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #42. Found while answering "can another agent just follow this lab?" — the honest
answer was no, and this is the first reason why.
Every Elasticsearch request in the lab was unauthenticated. The only two
Authorizationheaders in
data/were both on the ClickHouse side, and_base/'s throwaway cluster runswith
xpack.security.enabled=false— so the tools worked there and could not connect to anyreal 8.x cluster, where security is on by default. Four tools, all failing at their first
request.
es_client.py, shared rather than copied four timesThe credential handling is the part that is either right or wrong in exactly one place:
ES_USER/ES_PASSWORD) or an API key (ES_API_KEY), and both at onceis an error, not a precedence rule — a tool that silently picks one gets debugged
against the wrong identity.
ES_CA_CERT), because 8.x generates its own on first start.Plus
--es-insecure, which warns on every call: the alternative to that flag is not"everyone configures a CA properly", it is "someone disables security on the source
cluster".
history, in
psand in error messages.run.pypasses them to theexport.pyit spawnsthrough the child's environment, never its argv, for the same reason.
sentence instead of a traceback.
The minimum privileges, found by narrowing a key until each tool broke
{"cluster": ["monitor"], "index": [{"names": ["logs-*"], "privileges": ["read", "view_index_metadata", "monitor"]}]}The index-level
monitoris the one that gets left out._cat/indicesneeds bothcluster:monitor/stateandindices:monitor/stats, and the 403 names the action ratherthan the privilege — so the hint says it outright. My first attempt at that hint was wrong
in exactly this way until the cluster corrected it.
A reproducible home for the authenticated path
_base/gains anelastic-secureprofile: the same Elasticsearch with security on, port9201. HTTP TLS is off there on purpose — authentication was the gap, and a self-signed CA on
top would mean copying a certificate out of a container before anything runs, which makes a
profile nobody uses. The CA path is verified against a default-configuration container
instead.
Verified on
Elasticsearch 8.17.0 with
xpack.security.enabled=true, plus a default-configuration 8.17.0container over https with its generated CA.
plan.py→mapping_to_ddl.py→run.py→parity_checks.py, 20,000 documents, 3/3 chunks verified_idin ClickHouse 26.6.8.7ES_CA_CERTCERTIFICATE_VERIFY_FAILED→ one line of cause, one of remedy--es-insecureelasticprofileTwo bugs this caught in my own work, both only visible by running it:
parity_checks.pygotthe new flags and never applied them (401 against a cluster it had credentials for), and the
401 hint disappeared once the error was wrapped in a
RuntimeError— the status code was in__cause__.Remaining gaps from the same review are tracked separately: #39 (the sort key is a default,
not a design), #40 (a pattern of indices with different mappings), #41 (the Cloud path is
documented but never run).
🤖 Generated with Claude Code