Skip to content

feat(certificatemanager): add CertificateMap, DnsAuthorization and TrustConfig - #171

Merged
naxty merged 6 commits into
naxty/gcpBigtableBatchfrom
naxty/gcpCertManagerBatch
Aug 31, 2026
Merged

feat(certificatemanager): add CertificateMap, DnsAuthorization and TrustConfig#171
naxty merged 6 commits into
naxty/gcpBigtableBatchfrom
naxty/gcpCertManagerBatch

Conversation

@naxty

@naxty naxty commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Adds Certificate Manager, which was absent from the plugin. Stacked on #170.

Type Case CRUD Discovery
GCP::CertificateManager::CertificateMap certmanager-certificate-map 7/7 + Replace skipped 4/4
GCP::CertificateManager::DnsAuthorization certmanager-dns-authorization 7/7 + Replace skipped 4/4
GCP::CertificateManager::TrustConfig certmanager-trust-config 7/7 + Replace skipped 4/4

Verified locally, not yet in CI. The runs are on this branch with the
service account CI uses; CI will run them when this reaches the merge train.

The grant this was blocked on — and why the original ask was wrong

The draft asked for roles/certificatemanager.editor. That role is not enough:
it carries every .create permission and no .delete permission at all
(only deleteTagBinding). With it, Create through Update pass and Destroy fails
with Permission 'certificatemanager.dnsauthorizations.delete' denied — which
looks like a plugin bug and is not one.

roles/certificatemanager.owner is the minimal role that covers a conformance
run. It is now granted to github-deploy@ (CI) and formae-tester@ (local).

Two real defects the grant exposed

Neither was visible while everything failed at Create on a permission denial.

A trust config cannot be empty. The fixture and the schema comment both
claimed a config with no stores "is valid and trusts nothing". Certificate
Manager rejects it: trust config must contain at least one trust store or allowlisted certificate. The fixture now pins one throwaway self-signed anchor,
inline, so the case carries its own input and holds no private key.

Certificate Manager appends a trailing newline to every pemCertificate.
Whatever you send, it comes back with one — a PEM posted without a trailing
newline is stored with it. So the first fixed fixture passed Create and then
failed Verify, Extract, Sync and Update against its own certificate. A declared
PEM has to carry the newline the API will add; in the fixture that is the blank
line before the closing """, which is load-bearing and commented as such.

This one bites any forma with an inline PEM, not just this fixture, so it is
recorded in the CHANGELOG. It is not fixed in the plugin: normalising on read
would break the forma that does end its PEM with a newline, and normalising on
write does not change what the comparison sees. Matching the API's form is the
behaviour a read() of a real .pem file gives for free, since PEM files end
with a newline by convention.

What is still not covered

Replace is skipped for all three — no -replace.pkl fixtures. Certificate
and CertificateMapEntry are not in this batch.

naxty added 2 commits August 28, 2026 09:23
…ustConfig

Certificate Manager was absent from the plugin. These three are the types that
need nothing external: a map with no entries, an authorization that only hands
back a CNAME, and a trust config with no stores are all valid and free.

Left out deliberately: Certificate needs either a PEM keypair committed to the
repository or a domain that actually resolves; CertificateIssuanceConfig needs
a privateca CA pool; CertificateMapEntry needs a certificate to point at.

All three fit the generic engine - location-scoped, create id as a query
parameter, patch with a query-string field mask - so there is no custom
provisioner here, which is a first for this run of batches.

DnsAuthorization drops both name and domain from update bodies: domain is
immutable and UpdateMaskFromBody builds the mask from the body's top-level
fields, so leaving it in would put an unchangeable field in the mask and have
the patch rejected.

Verification runs through debug-conformance: the local key is 403 on this
service, as it is on DNS and Bigtable.
Create failed for all three types with

    Malformed name: '.../locations/europe-central2/certificateMaps/...'
    [Invalid location in resource URL path]

Certificate maps, DNS authorizations and trust configs are global; inheriting
the target's region addresses a location the API does not have. The path
builder pins "global" rather than the fixtures pinning it, which keeps create
and discovery pointed at the same place - a fixture that pins a region leaves
the discovery pass looking somewhere else, which is what makes API Gateway
undiscoverable in this project.

The ScopeLocationBased scope is gone with it: it makes List return nothing
whenever the target declares no location, which is exactly the case for a
global resource.
naxty added 4 commits August 31, 2026 10:56
The fixture asserted that a trust config with no stores is valid and trusts
nothing, and the schema comment said the same. Certificate Manager rejects it:
"trust config must contain at least one trust store or allowlisted certificate".
Create never got off the ground, so nothing behind it had ever run.

The fixture now pins one throwaway self-signed anchor, inline rather than read
from a file so the case carries its own input and holds no private key.

The blank line before the closing delimiter is load-bearing. Certificate Manager
appends a trailing newline to every pemCertificate it stores, whatever was sent -
a PEM posted without one comes back with one - so a fixture declaring it without
the newline passed Create and then failed Verify, Extract, Sync and Update
against its own certificate. A declared PEM has to carry the newline the API will
add. Recorded in the CHANGELOG, because it bites any forma with an inline PEM.

All three certificate manager cases now pass locally, CRUD and discovery 4/4.
@naxty
naxty marked this pull request as ready for review August 31, 2026 15:02
@naxty
naxty merged commit 6386642 into naxty/gcpBigtableBatch Aug 31, 2026
naxty added a commit that referenced this pull request Aug 31, 2026
…ustConfig

Restores #171. That pull request was stacked, and it merged into its parent
branch rather than into main - GitHub marks a stacked pull request merged once
its commits reach its base, and its base was a branch. #167, #168, #169 and #170
went the same way but were recovered when #173 landed, because #173 descended
from them. Nothing descended from #171, so certificate manager was the one batch
left behind: main has carried a Merged badge and no code since.

This is that content on top of current main, nothing else - the three types,
their schemas, six fixtures, and the package registration.

Verified locally against the service account CI uses, all three CRUD 7/7 with
Replace skipped and discovery 4/4. Two things it needed, both recorded in the
CHANGELOG: roles/certificatemanager.owner rather than editor, which carries no
delete permission at all; and a trust config that is not empty, since the API
rejects one carrying neither a trust store nor an allowlisted certificate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant