Summary
kfutil stores import csv --dry-run does not actually perform a dry run. It
validates the CSV header/field shape, then proceeds to call the real
create/update store APIs against Command exactly as a non-dry-run invocation
would. Running an import with --dry-run results in real certificate stores
being created in Command.
Version
- kfutil version: 1.9.2
- Confirmed against source at commit
392497dab03fe8e847861186bc70ef0f80fe2a3a
(cmd/storesBulkOperations.go)
Steps to reproduce
-
Build a valid CSV for any store type via kfutil stores import generate-template.
-
Run: kfutil stores import csv --file mystores.csv --store-type-name <type> --results-path results.csv --dry-run --no-prompt
-
Check Command for the certificate store(s) listed in the CSV.
Expected behavior
No store is created or updated in Command. The command should only report
whether the rows/fields are valid.
Actual behavior
The store(s) are created (or updated, with --sync) in Command for real,
identically to a run without --dry-run.
Root cause
In cmd/storesBulkOperations.go (pinned commit above), the dry-run flag is
read and only ever used for logging:
dryRun, _ := cmd.Flags().GetBool("dry-run") // line 167
...
Bool("dryRun", dryRun).Msg("Specific flags") // line 204
...
Bool("dryRun", dryRun). // line 243
The per-row loop that follows calls the mutating API methods unconditionally,
with no if !dryRun (or equivalent) guard anywhere around them:
res, err := kfClient.UpdateStore(&updateReqParameters) // line 424
...
res, cErr := kfClient.CreateStore(&createStoreReqParameters) // line 462
So --dry-run only gates the earlier "missing required fields in headers"
check; it never prevents the actual CreateStore/UpdateStore calls.
Impact
Anyone relying on --dry-run as a safety gate before a real bulk import
(e.g. scripting a "dry run first, then confirm, then real run" workflow)
will unknowingly create/update real stores during what they believe is a
no-op validation step. This also means dry-run results can show "0 errors"
while duplicate real stores are simultaneously created, and a subsequent
real (non-dry-run) run of the same CSV will then fail rows with
"certificate store already exists" errors caused by the dry run itself.
Suggested fix
Gate the kfClient.CreateStore / kfClient.UpdateStore calls (and any other
mutating calls in this code path) behind if !dryRun, returning/recording a
simulated success result per row instead when dryRun is true.
Summary
kfutil stores import csv --dry-rundoes not actually perform a dry run. Itvalidates the CSV header/field shape, then proceeds to call the real
create/update store APIs against Command exactly as a non-dry-run invocation
would. Running an import with
--dry-runresults in real certificate storesbeing created in Command.
Version
392497dab03fe8e847861186bc70ef0f80fe2a3a(
cmd/storesBulkOperations.go)Steps to reproduce
Build a valid CSV for any store type via
kfutil stores import generate-template.Run:
kfutil stores import csv --file mystores.csv --store-type-name <type> --results-path results.csv --dry-run --no-promptCheck Command for the certificate store(s) listed in the CSV.
Expected behavior
No store is created or updated in Command. The command should only report
whether the rows/fields are valid.
Actual behavior
The store(s) are created (or updated, with
--sync) in Command for real,identically to a run without
--dry-run.Root cause
In
cmd/storesBulkOperations.go(pinned commit above), thedry-runflag isread and only ever used for logging: