Skip to content

Releases: IS4IT/midgie

midgie 0.20.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 17:27

Added

  • deploy --plan without a folder writes to plan/ in the deployment's own folder under $XDG_STATE_HOME/midgie, next to its rollback plans, and replaces the plan there on every run — iterating on a tree no longer leaves a plan folder per run to clean up. The run ends with the command that replays it, and deploy <tree> --apply-plan without a folder finds that plan from the tree.
  • --overwrite lets --plan replace the plan in a folder you named. It goes only with --plan, and only on the command line: a config file setting it is refused, as yes is.

Changed

  • --plan refuses a folder that holds anything but a plan — any file or subfolder midgie did not write there as part of a plan, checked before the server is contacted, with --overwrite too. It used to accept any folder without plan files in it, so a plan could land among other files, or in a tree it was pointed at by mistake.
  • The documentation moved from the README to docs/. The README is now an overview with a quick start; installing, the container image and Helm chart, the commands, removal detection, the policy file, the diff strategy, configuration, the flag reference, the safety guards and the schema each have a page of their own. Links to the README's old section anchors no longer land on those sections.

Downloads

  • Standalone binary: midgie-0.20.0.jar, below. Run it with java -jar midgie-0.20.0.jar --help (Java 21 or later); see Installing midgie.
  • Container image: is4it/midgie:0.20.0 on Docker Hub, for linux/amd64 and linux/arm64. This release built docker.io/is4it/midgie:0.20.0@sha256:f0ea4da598f09fe7327f3b5b846671bdc98eae05211f030edd91e35324a22f8b; pin that digest to keep the same bytes after an image-only rebuild moves the tag. See Container image and Helm chart.
  • Helm chart: midgie-0.20.0.tgz, below: helm install midgie https://github.com/IS4IT/midgie/releases/download/v0.20.0/midgie-0.20.0.tgz -n midgie --create-namespace
  • SBOM: midgie-0.20.0.cdx.json, below. It lists every library the JAR bundles, in CycloneDX format; Verifying a release checks it against the JAR.

midgie 0.19.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 08:48

Changed

  • midgie bundles the midPoint 4.11.0 schema, and serves midPoint 4.11.x and 4.10.3 or later. One build covers both lines. 4.11 keeps 4.10's data model: its schema adds types and items, and the few it removed were deprecated since 4.8. midgie --version names the range: bundled midPoint schema 4.11.0, for midPoint 4.10.3 to 4.11.x. The live modes' version check warns about a server outside that range, so a 4.11 server no longer gets the "differs from the bundled schema" warning. midPoint 4.10.0 to 4.10.2 now get it: use 0.18.5 for them, the last release built on the 4.10.5 schema. Against a 4.10 server, two cases need care:
    • A desired object that uses an item new in 4.11, such as UserType/displayName or credentials/otp, diffs fine, and the server rejects it at deploy.
    • An object that still uses the eight OIDC resource-server items 4.11 removed, such as issuerUri or jwkSetUri, no longer parses. Their replacement, the jwt and opaqueToken token definitions, already works on 4.10.
  • Jackson comes from midPoint again. midPoint 4.11.0 brings jackson-core and jackson-databind 2.21.7 itself, the version 0.18.5 pinned, so the pin is gone.

midgie 0.18.5

Choose a tag to compare

@github-actions github-actions released this 20 Oct 11:47

Security

midgie 0.18.4

Choose a tag to compare

@github-actions github-actions released this 20 Oct 11:16

Added

  • Releases can be verified. The JAR and the Helm chart carry a SLSA build-provenance attestation, and the release attaches midgie-<version>.cdx.json, a CycloneDX SBOM of every library the JAR bundles, attested against the JAR. The image in Docker Hub is signed with cosign and carries a provenance attestation and an SBOM of its OS packages. All of it is keyless, through Sigstore: a signature names the workflow and git ref that built the artifact. The README's new "Verifying a release" section has the gh attestation verify and cosign verify commands. Every build now writes the SBOM to target/bom.json.

Changed

  • A container id in a printed path follows its item's name. midgie printed mapping/4/lifecycleState; it now prints mapping[4]/lifecycleState, the form midPoint 4.11 itself writes and the one deploy's removal report already used for a value paired by id (inducement[3]). That covers the summary format and every warning and note that names a path. The PATCH body is unchanged: its <path> elements are midPoint's own syntax. A script that reads --format summary output has to expect the new form.

midgie 0.18.3

Choose a tag to compare

@github-actions github-actions released this 15 Oct 13:31

Fixed

  • The removal warning in deploy's output is one readable line. Under an object it read warning: WARNING: this change REMOVES 1 value from the live object; - subtype (1 value), the multi-line warning of the offline diff squashed into one; it now reads warning: this change REMOVES 1 value from the live object: subtype ×1, the paths counted the way the "keeps live value(s)" note counts them. diff keeps its own multi-line form.

midgie 0.18.2

Choose a tag to compare

@github-actions github-actions released this 15 Oct 12:50

Changed

  • The note about an object that left the tree says when the server no longer holds it either. It asked you to delete the object yourself even when that had already been done — after a --dry-run, or between a --plan and its --apply-plan. The run now looks the object up at the end, by OID or else by type and name, and says …, and also does not exist on the server anymore. instead, dimmed like the other notes since nothing is left to do. A plan made by 0.18.1 does not record what to look the object up by, so its apply keeps the old wording, as does a run whose lookup fails.

midgie 0.18.1

Choose a tag to compare

@github-actions github-actions released this 15 Oct 11:48

Changed

  • Notes are dim and italic in a terminal. note: … lines, and the items listed under one, no longer look like the result rows, warnings and summary they comment on. Whether to style follows the same rules as --help's colours: only when standard input and output are a terminal, never with NO_COLOR set or CLICOLOR=0, and anywhere with CLICOLOR_FORCE=1 — for a CI log that renders ANSI styles. Piped or redirected output is unchanged. The note naming an object that left the tree keeps full brightness.

  • An object that left the tree is named at the end of the run. The note that a deleted file's object is no longer declared, and is left on the server for you to delete, came before the per-object rows and the summary, so on any real tree it scrolled out of sight — and a deploy that writes reports it only once. It is now the last thing deploy prints, --plan included, and it names the object by type and name as well as OID — RoleType/Old Role (5a3b…) — where it gave the OID alone; so does the note that an object moved to another file. deploy --apply-plan repeats it at the end of its output too, since it is the apply that lets go of the object's record: a plan-and-apply pipeline used to name the object only in the plan job's log. A plan made by an earlier version carries no such note.

midgie 0.18.0

Choose a tag to compare

@github-actions github-actions released this 02 Oct 10:14

Changed

  • midgie needs Java 21 or later. Java 17 is no longer supported: the JAR is built for 21, the container image runs on the Temurin 21 JRE, and CI tests 21 and 25. bin/midgie refuses an older JVM with a message naming the version it found; running the JAR directly on 17 fails with UnsupportedClassVersionError.

  • Items midPoint or its operators own after creation are now written only when the object is created, with or without a policy file. midgie ships nine built-in apply=on-create rules: task executionState and schedulingState; user credentials, activation/administrativeStatus, activation/lockoutStatus and activation/lockoutExpirationTimestamp; resource administrativeOperationalState, schema/definition and cacheInvalidationTimestamp. Before, a redeploy resumed a task an operator had suspended, re-enabled a disabled user, unlocked a locked-out one and took a resource out of maintenance. This changes what a deploy does: a change to one of these items in the tree no longer reaches an object that already exists, and a --yes run says nothing about it — --dry-run shows left alone by the policy: executionState (apply=on-create, built-in). To have midgie write one again, add a line naming the item to your --policy file, e.g. TaskType/*/executionState apply=always; a file line wins the tie with a built-in one. The rules extend a policy file rather than being replaced by it, and there is no switch to turn them all off. An offline diff of two files is unaffected.

  • init --write-policy writes the built-in rules as active lines instead of commented-out apply=on-create suggestions for the items the tree declares. A deploy applies them anyway, so the file still changes nothing; it now shows the whole policy in effect, with how to override each rule. ResourceType/*/schema became ResourceType/*/schema/definition, so a resource's schema/generationConstraints still deploys. The policy line names the built-ins too: midgie: policy: midgie.policy (3 rule(s), plus 9 built-in). Neither a built-in rule nor a file line restating one is reported as matching no object.

Fixed

  • An OID is checked before it becomes part of a URL. Object addresses are built by concatenation, and an OID from a tree file, --oid, or a plan or rollback file went in as it stood: ../roles/x?options=raw addressed another collection and added a query option to the PATCH or DELETE, and an OID with a space failed with "Illegal character in path". Anything but a UUID — the only form midPoint's native repository stores — now fails that object with a message naming it, before any request is sent, and --plan refuses to write a plan file for one.

  • A refused proxy URL is named without its password. https_proxy=https://bob:S3cret@proxy:3128 and every other proxy value midgie cannot use was echoed in full in the error, credentials included — and the environment is where a CI job carries them, straight into its log. The part before the host is now shown as ***@.

  • insecure in a config file applies to the command it names. Any key ending in insecure counted before any command ran, so midgie.init.insecure = true switched hostname verification off for deploy and every other command too. The file is now read the way picocli reads it: midgie.<command>.insecure for that command, else bare insecure; the same goes for proxy-user. And one of --insecure/--cacert on the command line against the other in a config file no longer refuses the run: the command line wins, with a note.

  • --trace masks password values. It printed every REST request and response body in full, so a desired password travelling as <clearValue> and the server's encrypted or hashed form went into whatever log the run wrote to — as did an error message quoting the response. The content of clearValue, cipherValue and digestValue is now shown as ***. Plain-text values that are not recognisable as secrets can still appear, which --trace's help says.

  • -o FILE is written whole and owner-only. The payload was written over the file in place, so a crash or a full disk left half a PATCH body behind, and a file that already existed kept its permissions — world-readable, say — while now holding the desired object, which may carry a clearValue password. It is now written to an owner-only file beside the target and renamed over it; a link is written through.

  • A tree-local .midgie.properties is only read from the tree. The search walked up from the working directory until it met a repository root — and outside a checkout never met one, so from /tmp/work it read a /tmp/.midgie.properties anyone could have left, whose policy or rollback-plan then applied. Outside a git checkout only the working directory's own file is read now, and a tree file that any user may change, or that belongs to another user who is not root, is ignored with a warning.

  • A config file with a password that others can read is said. A password or proxy-password in a group- or world-readable midgie.properties passed without a word; each run now starts with a warning naming the file and its permissions.

  • A live diff - removes its copy of stdin when it is done. The desired object — a clearValue password and all — was copied to midgie-stdin-NNN.xml in the shared temporary directory and only removed when the JVM exited, so a run that was killed left it there. It is now written as stdin.xml into an owner-only directory of its own and removed as soon as the diff finishes; only a run killed outright can still leave it behind.

  • A rollback that failed part way can simply be run again. The objects it had restored had new versions, which read as someone else's change, so the second run needed --force — which turned the check off for the objects still to be restored as well. Each restored object is now marked in the plan, and running rollback again sends only the rest.

  • An object deployed without a recorded version needs --force to roll back. It was replayed as if known to be unchanged, with a warning --quiet hid. Every object a rollback finds changed is now named whatever --quiet asks.

  • rollback says when it cannot check which deployment a plan belongs to. Outside a repository, or in a shallow clone, the deployment check was skipped without a word.

  • Two deploys finishing in the same second keep separate rollback plans. They shared a directory, so a rollback replayed the inverses of both. Plans are named to the millisecond now, and two deployments whose names flatten to the same directory no longer rotate away or pick each other's plans.

  • An unfinished rollback plan is refused in rollback's own words, rather than with --apply-plan's advice to re-run --plan.

  • A deploy without --yes over a tree already in sync records what it deployed. It returned before writing the tracking rows, which a --yes run over the same tree did, so the next run judged its removals against an older revision.

  • An object's last-applied files are one object whatever order they come in. A file naming the object by OID, one by name and one by both could leave two groups behind, and what one of them dropped went unseen or read as an object that left the tree.

  • A new object with an old object's name is not paired with the old one's history. The old one's values were offered for removal from the new one, and the old one's leaving went unreported.

  • Removal rules apply to the object's current name. A policy rule naming an object by the name a commit gave it missed the removals in that same commit.

  • A removal inside an entry finds that entry when the history's container ids came from another server. Paired by id, it could address the server's other entry that happened to hold the same value.

  • Writing the tracking rows survives a row another deploy moved meanwhile. The rows were addressed by the ids read at the start of the run, and one that had moved failed the whole write. They are now built from a fresh read, retried once, and a key two runs added twice is cleaned up when next written.

  • --smart-refs verify says when it cannot verify. A search the server refused (no search rights, a 403) or that failed in transit was logged at TRACE only, and every smart reference quietly counted as a change. Each filter is now also searched once per object, not once per reference and live value.

  • Several smart references in one item are no longer paired by guesswork. Under accept the first live OID was taken for each filter, so with more live values than filters the one left to delete was arbitrary, and with fewer, a filter whose resolution was already there could be sent again — which midPoint 4.10 refuses, failing the whole PATCH. Under replace such an item is now sent as a replace for midPoint to resolve; under merge nothing is sent for it, with a warning.

  • A natural key that cannot be evaluated is said. Its entries silently fell back to pairing by id or content.

  • A policy selector keeps the spaces of an unquoted name. RoleType/Help Desk was read as Help Desk.

  • Two files giving different values to an item without a loaded schema are a contradiction. The union took both, turning a disagreement into two values of what may be a single-valued item. Load the schema that defines it, or declare the item in one file.

  • References midPoint maintains no longer order the deploy. roleMembershipRef, archetypeRef and references under metadata in an exported object counted as dependencies, ordering objects after roles they had merely been given and reporting cycles that were not there.

  • What you confirm is what is sent. The writing pass reads the server again after the prompt, and an object whose change had moved in between — someone edited it while the prompt waited — was written as it now diffe...

Read more

midgie 0.17.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 08:18

Changed

  • Each object's result and its notes are printed together. deploy printed an object's result row on stdout and its notes and warnings on stderr, before the row and each prefixed with the object's path, so telling which note belonged to which object took reading — and a CI log that captures the two streams apart could reorder them. Each object now gets one block on one stream: the result alone in the first column, and in the second the file and the object, the change, and its warnings and notes. In a terminal the second column wraps to the window width (re-read after a resize); elsewhere it is not wrapped unless COLUMNS is set. Per-object notes therefore now appear on stdout; notes about the run as a whole stay on stderr. --plan also shows an object's warnings, which it used to leave out. rollback uses the same first column.

  • A key left empty inside an entry no longer demotes the whole list. One <addFocus/> without a <name> in a synchronization reaction made --equivalence auto compare every schemaHandling/objectType by content, so any edit inside an object type replaced it whole — a new container id, and what the server had added inside it gone — and under merge relied on the old-form and duplicate-key safeguards to avoid a second copy. The same held for an objectDetailsPage with one panel lacking its <identifier>. A list that fills in its own key is now paired by it and edited in place; only the list below that leaves its key empty is compared by content. -v names that inner list. A list that leaves its own key empty (assignment, inducement) is compared by content as before.

  • A broken file in a deployed tree fails the run. A .xml that is not well-formed — a merge that left its conflict markers behind — or a SchemaType that does not parse was skipped with a warning that --quiet hid: the run exited 0 without it, and on a tracked tree its object read as removed. Both are errors now, reported before any server contact, as an unparseable object already was.

  • A --schema file that cannot be used fails the run. One named outright that was not a schema or did not parse was warned about and skipped, so every extension item it defines diffed as raw; a missing one already failed. An unreadable --schema-dir fails too instead of reading as empty. Files inside --schema-dir in the wrong format are still skipped with a warning.

Fixed

  • Rollback rotation removes only its own run directories. After writing a net, deploy kept the newest five subdirectories of the base path and deleted every other one, recursively and through symlinks, without checking what they were. The base path can come from --rollback-plan or a tree-local .midgie.properties, so rollback-plan = . deleted the tree's own roles/, users/, … on the next deploy that wrote — letters sort after the timestamps, so the real net went first. Rotation now considers only directories with a timestamp name that hold a rollback manifest or an unfinished-plan marker, skips symlinked directories, and removes links inside a run without following them. An --app (or app) of . or .. no longer resolves the default base to the state root or the directory above it.

  • An escaped \* in a policy selector stays a literal. RoleType/\* multivalue=replace scope=full, written for a role literally named *, unescaped to the same text as the one-segment wildcard and then matched every role, full-replacing all of them. A parsed segment now remembers whether it was written as a wildcard; \* and \*\* as a whole segment match only a name that is * or **.

  • apply=on-create and apply=if-absent items are no longer deleted with their container. Only a replace of a container was checked for such items. A list compared by content changes an entry by adding its new form and deleting its old one, and the delete took the protected item along — UserType/*/assignment/activation/administrativeStatus apply=on-create did not stop an edited assignment from losing its status. Deleting a single-valued container around the item (an activation the file leaves out, under --scope full or inside a paired entry) did the same. The object is now refused instead, naming the item; giving the entry its container id in the file makes the change in place. The check runs on the whole PATCH, so a removal of a value dropped from the tree that pairs with the diff's add is caught too. Removing an entry the file no longer declares still removes it whole.

  • Container ids from another server no longer pair unrelated entries. prism pairs two list values that both carry a container id by that id, under every --equivalence, real-value included, and edits one into the other. A file exported from DEV carries DEV's ids, so its <inducement id="5"> re-pointed whatever PROD holds under 5 — often an entry an admin added there — and <mapping id="4"><name>fromDev</name> renamed PROD's unrelated mapping 4, under merge too; merge also kept the delete of a PROD entry whose id a DEV entry happened to use. midgie now checks each list's ids against the server's first: a matching id with a different filled-in natural key, a file entry the server holds under another id, or a server entry another file entry declares means the numbering is foreign, and that list's entries are paired by natural key or content instead. -v names each such list. A file exported from the target server is unaffected, since midPoint never reuses a container id. One case remains indistinguishable: a single edited entry whose foreign id is taken, with no other entry in the list to show the mismatch.

  • Merge no longer sends an empty delete beside an add. When merge kept every value a list's delete side would have removed, the emptied delete still went out as a <delete> item delta with no value next to the add, and the summary read add+delete. It is now left out.

  • A smart reference inside an inducement or assignment is recognised. A filter-only targetRef or construction/resourceRef inside an entry without a container id made the whole entry differ from the server's resolved copy, and the reference-level check never saw it: every deploy deleted the resolved inducement and added one whose reference named nothing, sent without reevaluateSearchFilters, so midPoint stored it unresolved. Under merge a duplicate was added on every run instead. Such an entry now reads as in sync when the server's copy is its resolution; when several entries could be, it is left as a change and -v suggests --smart-refs verify. An entry still sent whole — and a plan file holding one — goes out with reevaluateSearchFilters.

  • A deploy that dies part way still leaves its rollback plan. A rejected login (401) or a lost connection in the middle of the apply ended the run before the net was written, so the objects already patched had no undo — the one case the net exists for. The plan for what was written is now saved before the error is reported.

  • Removal detection that fails for an object is reported, not read as "nothing removed". When an object's last-deployed files could not be parsed, contradicted each other, or could not be compared, detection for it ended at TRACE level and its rows moved on — so a value dropped from the tree stayed on the server for good, with a green run. Each case is now a warning that --quiet does not hide. An object whose old content no longer parses or whose comparison failed keeps its rows so the next run tries again; one whose files' records contradict each other (a file deployed on its own since) lets them move on, since that history would fail every run. An object that left the tree is still reported as an orphan when its old files no longer combine.

  • rollback moves the tracking rows back with the objects. On a tracked tree a rollback restored the objects but left midgie-state saying the rolled-back revision was applied. Deploying that revision again then found nothing it had dropped, and under merge the values it was meant to remove stayed beside the new ones. The rollback plan now records the rows the deploy moved, before and after, and rollback restores them for each object it restored, leaving any row a later deploy has written since. --dry-run says how many rows would move.

  • deploy --apply-plan leaves a rollback plan and records what it applied. Replaying a reviewed plan wrote neither, although every deploy that writes is documented to leave a net — so the production path had no undo, and --rollback-plan was accepted and ignored. On a tracked tree a pipeline that only ever plans and applies also never moved its midgie-state rows, so a value added by one plan and dropped by the next was never detected and stayed under merge. --plan now writes state.xml into the plan directory with the rows an apply would write, and --apply-plan writes them for the entries it applied (leaving any row another run has moved since), builds the inverse of each body it sent, and writes the net where a deploy of that tree would. --no-rollback-plan is honoured.

  • An object whose inverse cannot be computed is named. A rollback plan left such an object out with a debug log line, while deploy still reported the net. It is now named in a warning, marked unrecorded in the manifest, and reported again by rollback.

  • A password source on the command line beats one from a config file. A config file's value arrives as the option's default, and --password is tried before --password-env and --password-file, so a password in a config file outranked --password-file typed on the command line — the documented order says the reverse. Any of the three given on the command line now comes first, whichever spelling the file uses; the proxy password likewise.

  • A secret joined to a mistyped option is withheld. --pasword=hunter2 or -Phunter2 printed the value i...

Read more

midgie 0.16.3

Choose a tag to compare

@github-actions github-actions released this 28 Sep 13:08

Fixed

  • An edited keyed entry is replaced, not duplicated, on a tracked tree. A resource whose schemaHandling/objectType held a reaction with an unnamed <addFocus/> came out of a deploy with two object types of one kind and intent, and midPoint no longer loaded its schema. --equivalence auto compares a list by content when any key inside its entries is left empty, so the edited object type diffed to "add the new form, delete the old"; merge, the default on a tracked tree, dropped that delete as a value beyond the tree, and the removal detector — which pairs the entry by its kind + intent — deleted only the items dropped from inside it. Merge now keeps the delete of a live value that carries the container id or natural key of an entry the tree declares: that value is the entry's old form. A server already holding both forms is cleaned up by the next deploy of the tree.

Added

  • A change that would hold one natural key twice is refused. deploy, a live diff and an offline diff project the whole PATCH onto the live object and fail the object (exit 2) when a keyed list would end up with more values sharing one filled-in key than it has now: refusing a change that would leave schemaHandling/objectType[kind=GENERIC, intent=task] ×2 …. A duplicate the server already holds does not block.

  • -v names the lists auto compared as whole values. Per object, a note: for each list --equivalence auto did not pair by natural key, naming the key inside it that is not filled in (…/reaction/actions/addFocus does not fill in its key (name)). A change inside such a list replaces the entry whole; this was visible only in the debug log's equivalence= field.