mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
fix(web-app-homeassistant): realign the owner password the hub kept from onboarding
Home Assistant writes the owner password into the auth store on its volume
during onboarding and never reads the environment again. When the deploy
rotates credentials the container gets the new value and the store keeps the
old one, so the login that every later step needs is refused.
The provisioning script returned that refusal as an ordinary step, and the
/auth/token call that followed failed on a missing result key - a message about
the transport for a problem in the credentials. It now exits on any login flow
that does not reach create_entry, naming the account.
That turns a five-minute wait into an immediate branch: the retry loop stopped
only on success, so a password that will never be accepted was tried thirty
times. The loop now also breaks on the refusal, and only that one outcome is
allowed past failed_when - a crash or a traceback still fails the task, which
matters because the step after this reads a token out of stdout.
hass --script auth change_password reaches the store through the filesystem, so
it needs no working login. The hub holds the store in memory, hence the restart
before the same mint runs again.
e3caa074b2 fixed the account one layer in: the MCP service account, through
admin_change_password, which needs an admin token. This is the login that
issues that token, so without it that fix cannot be reached at all.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
d7de6e3805
commit
82452789c9
4 files changed
+77
-1
No files matched your search
@@ -94,6 +94,10 @@ def access_token_via_login(username, password):
|
||||
"password": password,
|
||||
},
|
||||
)
|
||||
if step.get("type") != "create_entry":
|
||||
raise SystemExit(
|
||||
f"home assistant refused the login of {username}: {json.dumps(step)}"
|
||||
)
|
||||
return request(
|
||||
"/auth/token",
|
||||
{
|
||||
|
||||
@@ -28,12 +28,23 @@
|
||||
register: homeassistant_provision
|
||||
retries: 30
|
||||
delay: 10
|
||||
until: homeassistant_provision.rc == 0
|
||||
until: homeassistant_provision.rc == 0 or (HOMEASSISTANT_LOGIN_REFUSED in homeassistant_provision.stderr)
|
||||
failed_when:
|
||||
- homeassistant_provision.rc != 0
|
||||
- HOMEASSISTANT_LOGIN_REFUSED not in homeassistant_provision.stderr
|
||||
changed_when: "'CHANGED' in homeassistant_provision.stdout"
|
||||
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
|
||||
delegate_to: "{{ HOMEASSISTANT_HOST_NODE }}"
|
||||
run_once: true
|
||||
|
||||
- name: "🔑 Realign the owner password the hub still holds from its onboarding"
|
||||
ansible.builtin.include_tasks:
|
||||
file: realign_owner.yml
|
||||
apply:
|
||||
delegate_to: "{{ HOMEASSISTANT_HOST_NODE }}"
|
||||
when: HOMEASSISTANT_LOGIN_REFUSED in homeassistant_provision.stderr
|
||||
run_once: true
|
||||
|
||||
- name: "🔧 Take the minted token from the provisioning output"
|
||||
ansible.builtin.set_fact:
|
||||
homeassistant_mcp_token: "{{ homeassistant_provision.stdout_lines | last | trim }}"
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
- name: "🔑 Write the rotated owner password into the hub's auth store"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- container
|
||||
- exec
|
||||
- -i
|
||||
- "{{ HOMEASSISTANT_LOCAL_CID }}" # nocheck: container-exec-resolver
|
||||
- hass
|
||||
- --script
|
||||
- auth
|
||||
- --config
|
||||
- "{{ HOMEASSISTANT_CONFIG_DIR }}"
|
||||
- change_password
|
||||
- "{{ HOMEASSISTANT_ADMIN_USERNAME }}"
|
||||
- "{{ HOMEASSISTANT_ADMIN_PASSWORD }}"
|
||||
changed_when: true
|
||||
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
|
||||
|
||||
- name: "🔄 Restart the hub so it reads the store it no longer has in memory"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- container
|
||||
- restart
|
||||
- "{{ HOMEASSISTANT_LOCAL_CID }}" # nocheck: container-exec-resolver
|
||||
changed_when: true
|
||||
|
||||
- name: "🔑 Mint the long-lived token now that the hub accepts the rotated password"
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- container
|
||||
- exec
|
||||
- -i
|
||||
- -e
|
||||
- "HA_PORT={{ HOMEASSISTANT_PORT_INTERNAL }}"
|
||||
- -e
|
||||
- "HA_USERNAME={{ HOMEASSISTANT_ADMIN_USERNAME }}"
|
||||
- -e
|
||||
- "HA_PASSWORD={{ HOMEASSISTANT_ADMIN_PASSWORD }}"
|
||||
- -e
|
||||
- "HA_TOKEN_CLIENT_NAME={{ HOMEASSISTANT_TOKEN_CLIENT_NAME }}"
|
||||
- -e
|
||||
- "HA_SERVICE_USERNAME={{ HOMEASSISTANT_MCP_ACCOUNT_USERNAME }}"
|
||||
- -e
|
||||
- "HA_SERVICE_PASSWORD={{ HOMEASSISTANT_MCP_ACCOUNT_PASSWORD }}"
|
||||
- -e
|
||||
- "HA_SERVICE_NAME={{ HOMEASSISTANT_MCP_ACCOUNT_NAME }}"
|
||||
- -e
|
||||
- "HA_SERVICE_GROUP={{ HOMEASSISTANT_MCP_ACCOUNT_GROUP }}"
|
||||
- "{{ HOMEASSISTANT_LOCAL_CID }}" # nocheck: container-exec-resolver
|
||||
- python3
|
||||
- "-"
|
||||
stdin: "{{ lookup('file', 'python/provision_mcp.py') }}"
|
||||
register: homeassistant_provision
|
||||
retries: 30
|
||||
delay: 10
|
||||
until: homeassistant_provision.rc == 0
|
||||
changed_when: "'CHANGED' in homeassistant_provision.stdout"
|
||||
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
|
||||
@@ -11,6 +11,8 @@ HOMEASSISTANT_MCP_ENABLED: "{{ lookup('config', application_id, 'mcp.enabled') }
|
||||
HOMEASSISTANT_ADMIN_USERNAME: "{{ lookup('users', 'administrator').username }}"
|
||||
HOMEASSISTANT_ADMIN_PASSWORD: "{{ lookup('config', application_id, 'secrets.credentials.administrator_password') }}"
|
||||
HOMEASSISTANT_TOKEN_CLIENT_NAME: "infinito-mcp"
|
||||
HOMEASSISTANT_CONFIG_DIR: "{{ lookup('volume', application_id, 'homeassistant_config').target }}"
|
||||
HOMEASSISTANT_LOGIN_REFUSED: "home assistant refused the login of"
|
||||
HOMEASSISTANT_MCP_ACCOUNT: "{{ lookup('users', 'mcp-web-app-homeassistant') }}"
|
||||
HOMEASSISTANT_MCP_ACCOUNT_USERNAME: "{{ HOMEASSISTANT_MCP_ACCOUNT.username }}"
|
||||
HOMEASSISTANT_MCP_ACCOUNT_NAME: "Infinito MCP"
|
||||
|
||||
Reference in new issue
Block a user