hack/check-opensearch-readme.bats
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bats
# Tests that the opensearch README.md has the correct structure after generation.
#
# These are static checks on the committed README.md — they do not invoke
# make generate (which requires cozyvalues-gen in PATH). They verify that:
# 1. tls.issuer description is not truncated (ends with "on and off")
# 2. topologySpreadPolicy appears outside the TLS section
# 3. opensearch-rd cozyrds labels the tenant CA and no server certificate
load test_helper
REPO_ROOT="$(cd "$(dirname "${BATS_TEST_FILENAME:-$0}")/.." && pwd)"
README="$REPO_ROOT/packages/apps/opensearch/README.md"
COZYRDS="$REPO_ROOT/packages/system/opensearch-rd/cozyrds/opensearch.yaml"
@test "tls.issuer description is not truncated" {
# The last clause of the @field line in values.yaml. cozyvalues-gen copies only
# the first line of a description into the table, so a wrapped @field silently
# loses its tail and the row still renders.
grep -q "does switch TLS on and off" "$README"
}
@test "topologySpreadPolicy is not in TLS configuration section" {
# TLS section should contain only tls/tls.issuer rows, not topology spread.
# The awk pattern skips the heading line itself, then prints until the next
# section heading so the range is non-vacuous.
#
# if/exit rather than a `!` prefix, for the reason spelled out on the
# publish-ca-cert check below: under hack/cozytest.sh a negated pipeline cannot
# fail the test at all.
if awk '/### TLS configuration/{found=1; next} found && /^### /{exit} found' "$README" | grep -q "topologySpreadPolicy"; then
echo "topologySpreadPolicy appears inside the TLS configuration section" >&2
exit 1
fi
}
@test "topologySpreadPolicy appears in README at all" {
# Deliberately only presence. This is what stops the test above passing
# vacuously: a README that lost the row entirely would satisfy "not in the TLS
# section" without documenting the parameter anywhere. The "outside the TLS
# section" half is that test's job, not this one's.
grep -q "topologySpreadPolicy" "$README"
}
@test "cozyrds opensearch.yaml labels the tenant CA for the tenant registry" {
# The key-free trust anchor the CA-extraction controller publishes, selected by
# label rather than by name. This entry is the whole tenant read path: it drives the
# lineage webhook's tenantresource verdict, and the tenant reads the projection
# through core.cozystack.io/tenantsecrets, which the base tenant roles grant. The
# chart Role grants no name for it — tests/dashboard-resourcemap_test.yaml pins that.
grep -q "internal.cozystack.io/tenant-ca" "$COZYRDS"
}
@test "cozyrds opensearch.yaml exposes no server certificate to the tenant" {
# A tenant needs ca.crt to verify the endpoint and nothing more. Both the leaf
# Secret and the cert-manager CA Secret carry a private key under tls.key, so
# neither may be listed here — only the controller's key-free projection.
#
# Asserted on the SHAPE of secrets.include, not by grepping one spelling: this is
# the only thing standing between the CA private key and the tenant, and a name
# written a different way, or a selector that happens to match a key-bearing
# Secret, has to fail this too. Every entry must be one of exactly two known-safe
# forms — the credentials Secret by name, or the tenant-ca projection by label.
command -v yq >/dev/null || { echo "yq (mikefarah v4+) is required" >&2; exit 1; }
credentials='{"resourceNames":["opensearch-{{ .name }}-credentials"]}'
tenant_ca='{"matchLabels":{"internal.cozystack.io/tenant-ca":"true"}}'
entries="$(yq --output-format=json -I=0 '.spec.secrets.include[]' "$COZYRDS")"
# Guard against a vacuous pass. A loop over nothing is a green test, and this one
# guards tenant read access to a Secret holding the HTTP CA private key — so assert
# the list is the size we think it is before concluding anything about its members.
# Without this the test would still report ok if the path were restructured away.
# `|| true` because grep exits non-zero on no match, which under set -e would kill
# the test before the diagnostic below could explain what was expected.
count="$(printf '%s\n' "$entries" | grep -c '^{' || true)"
if [ "$count" -ne 2 ]; then
echo "expected exactly 2 secrets.include entries, found $count" >&2
printf '%s\n' "$entries" >&2
return 1
fi
while IFS= read -r entry; do
[ -n "$entry" ] || continue
if [ "$entry" != "$credentials" ] && [ "$entry" != "$tenant_ca" ]; then
echo "secrets.include has an entry that is neither the credentials Secret" >&2
echo "nor the key-free tenant-ca projection: $entry" >&2
return 1
fi
done <<EOF
$entries
EOF
}
@test "cozyrds opensearch.yaml selects the projection, never a publish source" {
# publish-ca-cert was a label-driven extraction leg that never shipped: no
# controller on main reads it. What ships is the TenantProjection sentinel, which
# names its source Secret outright, and the only label in the mechanism is
# tenant-ca on the projection the controller writes — which is what the selector
# above matches.
#
# The assertion outlives the leg it was written for. A publish-ca-cert selector
# here would be inert rather than dangerous today, but the name marked a
# key-bearing SOURCE — the cert-manager CA Secret, private key under tls.key — so
# reviving it as a selector is the one edit that would hand the tenant that key.
# Cheaper to keep the name out of this file than to re-derive that each time.
#
# NOT written as `! grep -q`. These files run under hack/cozytest.sh, which
# injects `return 0` ahead of the closing brace, and a `!`-prefixed pipeline is
# exempt from set -e — so a bare negation reports green under the runner CI uses
# while real bats fails it. if/exit is the form that survives both.
if grep -q "internal.cozystack.io/publish-ca-cert" "$COZYRDS"; then
echo "cozyrds selects on publish-ca-cert, which marks the key-bearing CA Secret" >&2
exit 1
fi
}