Conversation
Added pipelines Added moelcule Signed-off-by: Mark Bolwell <info@krameff.com>
Updated core files added workflow testing
Updates to molecule layout
Signed-off-by: Mark Bolwell <info@krameff.com>
Signed-off-by: Mark Bolwell <info@krameff.com>
…a deletion. Records what it changed per host in facts.d; both stages roll back their own changes and prove access with a real unmultiplexed ssh. Signed-off-by: Mark Bolwell <info@krameff.com>
Signed-off-by: Mark Bolwell <info@krameff.com>
Signed-off-by: Mark Bolwell <info@krameff.com>
Signed-off-by: Mark Bolwell <info@krameff.com>
Signed-off-by: Mark Bolwell <info@krameff.com>
Validation testing
frederickw082922
approved these changes
Aug 11, 2026
frederickw082922
left a comment
There was a problem hiding this comment.
Great improvements @uk-bolly
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.
Description
Huge login improvements and docs
rollback to put back to original state
docs easier to read
full testing framework
More safety checks
v*builds the collection and publishes it to Galaxygalaxy.yml.CONTRIBUTING.md, covering setup, the required checks and the pull request checklist.SECURITY.md, with a private disclosure route for anything that could leave a host unreachable..github/.rotation_vars.example.yml: copy it, fill in your key paths, and pass-e @rotation_vars.ymlinstead of four separate-eflags.Safety checks
sshd -Tthat password and keyboard-interactive logins really were turned off, rather than trusting the config edit.sshd -T -C, catching aMatchblock that re-enables password login for exactly that account.authorized_keysownership and permissions still satisfy sshd'sStrictModes, on both the success and rollback paths.AuthorizedKeysFileand fails if the host does not read keys from the user's own~/.ssh/authorized_keys, rather than installing a key somewhere sshd will never look.Rollback
authorized_keysback as it was before the run, and by default leave the new key alongside it, so the host never ends up depending solely on the old key still working.ssh_key_rotation_rollback_remove_new_key(defaultfalse) restoresauthorized_keysexactly, removing the new key. The old key is proven to work first, and the new key is kept if that proof fails./etc/ansible/facts.d/ssh_key_rotation.fact, so a rollback undoes exactly that, and so the verify stage can roll back install-stage changes even when run on its own. Left in place after a run as a record of what happened.Variables
ssh_key_rotation_sshd_dropin_prefix(default"99") andssh_key_rotation_sshd_dropin_dir: control where the role writes its configuration. Lower prefixes win, because sshd keeps the first value it sees for a keyword.ssh_key_rotation_manage_sshd_dropinis deprecated in favour of the prefix variable, but still honoured; it is equivalent to a prefix of01.ssh_key_rotation_check_match_blocks(defaulttrue) enables the per-userMatchblock check.Testing
nonrootMolecule scenario rotates a non-root user, androllbacknow does too. The previous root-only scenarios could never catch a file-ownership mistake, because when the target is root, root-owned is the correct outcome..claude/agents/, carrying the rules that stop a test lying: never prove connectivity over a multiplexed connection, and never report "refused" when the honest answer is "could not connect".Changed
Includeline (OpenSSH 8.2+, so every currently supported distribution) the role writes its settings to drop-ins under/etc/ssh/sshd_config.d/and no longer edits/etc/ssh/sshd_configat all, so rolling back is deleting a file rather than restoring someone else's config. Two files are used - one per stage - so a verify-stage rollback cannot delete install-stage settings an earlier run established. Older hosts keep the marked-block behaviour, backed up first. This does add files to/etc/ssh/sshd_config.d/, which config-drift tooling such as AIDE or Tripwire will notice. Nothing has been released yet, so no published behaviour changes.AuthorizedKeysFile. Forcing it would have overridden a central key store at drop-in precedence, stripping key access from every other user on the host while the rotated user kept working.molecule/toextensions/molecule/, which also corrects the relative roles path.openssh-serverat build time rather than during prepare.extensions/molecule/resources/Dockerfile.j2and oneresources/prepare.yml; each scenario'sprepare.ymlis a short wrapper supplying only its own keypairs and which one to pre-authorize.remote_tmpdirectory is created during the image build instead of by an entrypoint wrapper, so it exists before the container starts andmolecule-entrypoint.shis gone.dependencyanddestroy, so collection dependencies install the same way locally and in CI, and a container left behind by an aborted run cannot be reused with keys already in itsauthorized_keys.:latesttest images surfaces on its own build rather than on an unrelated pull request.build_ignorestill pointed atmolecule/, so the scenarios were being shipped in the artifact; it now excludesextensions/moleculeplus.github,.claude,.cursor,.ansible,.mcp.json,inventory.iniandrotation_vars.yml.DEVELOPMENT.mdshows how to generate throwaway keys outside the repo for manual testing, and states that behaviour may change within0.xuntil 1.0.0 ships.Fixed
authorized_keysowned by root, which sshd ignores underStrictModes- so the rollback meant to save your access could lock you out instead. Ownership is now restored explicitly, using the target user's real primary group.ansible.builtin.ping, whose connection is multiplexed on host, port and user rather than on the identity file, so they could pass over a socket opened with a different credential and report access that no longer existed. They now drive a real ssh client withControlMaster=noandControlPath=none, and force public key authentication so a client-sidessh_configcannot make a good key look broken.sshd_configsetting was written withlineinfile, which replaces the LAST match, andMatchblocks sit at the end of the file - so on a host with such a block both stages edited per-user policy instead of the global section, silently flipping settings like a deliberatePubkeyAuthentication nofor one account. The role now writes drop-ins, or a block anchored to the global section on older hosts, and never edits aMatchblock. Documented under Limitations in the README./etc/ssh/sshd_config.d/(cloud-init's, typically) could silently override the lock-down and leave password logins working while the run reported success. That is now caught and named.authorized_keysis read per connection and needs none.ansible_facts.date_time, clearing a deprecation warning ahead of ansible-core 2.24.| bool, so passing them via-e(e.g.-e ssh_key_rotation_disable_password_auth=false) no longer fails on ansible-core 2.20.changed=0from tasks that record a per-run timestamp and so can never be idempotent; it now allows those and fails on anything else.authorized_keysagainst a checkpoint taken before the install stage, demanding the rescue undo work it never performs.sshdunit, which resolves on Ubuntu only through an alias; it now uses the same family lookup as prepare.ANSIBLE_ROLES_PATHto a scenario-relative path, but Molecule runs with the project directory as its cwd, so it resolved outside the repo entirely and the rollback scenario could not find the role. It is now${MOLECULE_PROJECT_DIRECTORY:-.}/roles.Removed
test_vars.yml- local scratch files nothing depended on.