From a34e80113caf996ae9813d1c1da4b8e2bff891bc Mon Sep 17 00:00:00 2001 From: neri Date: Sat, 11 Jan 2025 02:12:21 +0100 Subject: [PATCH] feat: mlock nicht mehr gegen vault --- .gitignore | 2 + mlock-common.yaml | 161 +++++++++++++++++++++++++++++++++------------- 2 files changed, 119 insertions(+), 44 deletions(-) diff --git a/.gitignore b/.gitignore index 4b61c8f..13c7732 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .idea/ venv/ +.venv/ .esphome/ secrets.yaml +.envrc diff --git a/mlock-common.yaml b/mlock-common.yaml index bb6117a..9dc1793 100644 --- a/mlock-common.yaml +++ b/mlock-common.yaml @@ -1,14 +1,11 @@ -# todos: -# - move code into packages to make this re-useable -# - testing - substitutions: - ota_password: "" - api_enckey: "" - wifi_ssid: "" - wifi_password: "" - vault_role_id: "" - vault_secret_id: "" + name_of_board: lasercutter + ip_addr: "172.23.23.26" + machines_token: !secret mlock_machines_token + wifi_ssid: !secret wifi_ssid + wifi_password: !secret wifi_password + ota_password: !secret ota_password + api_enckey: !secret api_enckey ###### nothing to change below this line ###### esphome: @@ -35,6 +32,7 @@ esp8266: # Enable logging logger: + level: DEBUG api: encryption: @@ -58,6 +56,9 @@ wifi: dns1: 172.23.23.1 subnet: 255.255.255.0 + on_connect: + - script.execute: refresh_access_machines + captive_portal: spi: @@ -102,7 +103,7 @@ script: then: - script.execute: toggle_switch - script.wait: toggle_switch - - if: # return LED to switch state before + - if: # set LED to new switch state condition: switch.is_on: mlock_${name_of_board}_switch then: @@ -110,36 +111,18 @@ script: else: - light.addressable_set: { id: status_led, red: 100%, green: 0%, blue: 0% } else: - - script.execute: fetch_token_vault - - id: fetch_token_vault - then: - # login to vault with role_id to fetch short lived token - - http_request.post: - url: https://vault.ctdo.de/v1/auth/approle/login - verify_ssl: false - headers: - Content-Type: application/json - json: - role_id: $vault_role_id - secret_id: $vault_secret_id - on_response: - # fetch token from response, store into vault_api_token - then: - - lambda: |- - json::parse_json(id(http_request_data).get_string(), [](JsonObject root) { - id(vault_api_token) = (const char*) root["auth"]["client_token"]; - }); - - script.execute: check_access_vault - - id: check_access_vault + - script.execute: check_access_machines + - id: check_access_machines + mode: queued then: - lambda: |- id(access_allowed) = false; - http_request.get: url: !lambda |- - return ((std::string) "https://vault.ctdo.de/v1/maschinenlock/" + id(rfid_tag)); + return ((std::string) "https://machines.ctdo.de/machine/mlock-$name_of_board"); verify_ssl: false headers: - X-Vault-Token: !lambda return id(vault_api_token).c_str(); + Authorization: !lambda return "Bearer $machines_token"; on_response: then: - if: @@ -147,15 +130,27 @@ script: lambda: 'return status_code == 200;' then: # when found, check if machine is allowed, turn on output or blink LED red - lambda: |- - json::parse_json(id(http_request_data).get_string(), [](JsonObject root) { - id(access_allowed) = (root["data"]["mlock-$name_of_board"] == "1"); - }); + std::string response = id(http_request_data).get_string(); + id(process_machines_response)->execute(response); + DynamicJsonDocument doc(2048); + deserializeJson(doc, response); + unsigned int rfid_value = decode_token(id(rfid_tag)); + for (JsonVariant elem : doc.as()) { + std::string received_token = elem.as(); + int received_value = decode_token(received_token); + if (rfid_value == received_value) { + id(access_allowed) = true; + break; + } + } - if: condition: lambda: 'return id(access_allowed);' then: - script.execute: toggle_switch - - script.execute: cache_token + - script.execute: + id: cache_token + token: !lambda return id(rfid_tag); - script.wait: toggle_switch else: - repeat: @@ -165,15 +160,15 @@ script: - delay: 0.1s - light.addressable_set: { id: status_led, red: 0%, green: 0%, blue: 0% } - delay: 0.1s - else: # vault returns 404 on missing/unknown Tag so blink LED + else: # could not fetch machine config, so blink LED - repeat: - count: 3 + count: 5 then: - light.addressable_set: { id: status_led, red: 100%, green: 0%, blue: 0% } - - delay: 0.5s + - delay: 0.8s - light.addressable_set: { id: status_led, red: 0%, green: 0%, blue: 0% } - - delay: 0.5s - - if: # return LED to switch state before + - delay: 0.8s + - if: # return LED to switch state condition: switch.is_on: mlock_${name_of_board}_switch then: @@ -181,6 +176,7 @@ script: else: - light.addressable_set: { id: status_led, red: 100%, green: 0%, blue: 0% } - id: toggle_switch + mode: queued then: - if: condition: @@ -203,9 +199,13 @@ script: id: ${name_of_board}_letzte_entsperrung value: !lambda return id(rfid_tag); - id: cache_token + mode: queued + parameters: + token: string then: - lambda: |- - int rfid_value = decode_token(id(rfid_tag)); + ESP_LOGI("mlock", "Caching token: %s", token.c_str()); + int rfid_value = decode_token(token); int rfid_value_pos = 23; // search the token in the list to keep the access_cache unique for (int i = 0; i < 24; i++) { @@ -220,6 +220,79 @@ script: } // write the new token to the start id(access_cache)[0] = rfid_value; + - id: refresh_access_machines + mode: queued + then: + - logger.log: + tag: mlock + level: info + format: "Fetching config" + - http_request.get: + url: !lambda |- + return ((std::string) "https://machines.ctdo.de/machine/mlock-$name_of_board"); + verify_ssl: false + headers: + Authorization: !lambda return "Bearer $machines_token"; + on_response: + then: + - script.execute: + id: process_machines_response + response: !lambda return id(http_request_data).get_string(); + - id: process_machines_response + mode: queued + parameters: + response: string + then: + - logger.log: + tag: mlock + level: info + format: "Allowed tokens: %s" + args: [ 'response.c_str()' ] + - lambda: |- + DynamicJsonDocument doc(2048); + deserializeJson(doc, response); + JsonArray array = doc.as(); + // invalidate cached tokens that are not allowed anymore + for (int i = 0; i < 24; i++) { + unsigned int cached_token = id(access_cache)[i]; + if (cached_token == 0) { + break; + } + bool token_valid = false; + // search for cached token in the allowed list + for (JsonVariant elem : array) { + std::string received_token = elem.as(); + int received_value = decode_token(received_token); + if (cached_token == received_value) { + token_valid = true; + break; + } + } + if (!token_valid) { + ESP_LOGI("mlock", "Purging removed token: %08X", id(access_cache)[i]); + // move remaining tokens up in the cache + for (int j = i; j < 23; j++) { + id(access_cache)[j] = id(access_cache)[j + 1]; + } + id(access_cache)[23] = 0; + i--; + } + } + for (JsonVariant elem : array) { + std::string received_token = elem.as(); + int received_value = decode_token(received_token); + // append the token at the end of the cache in an empty slot if it is not in there yet + for (int i = 0; i < 24; i++) { + if (id(access_cache)[i] == received_value) { + break; + } + if (id(access_cache)[i] == 0) { + ESP_LOGI("mlock", "Pre-caching token: %X", received_value); + id(access_cache)[i] = received_value; + break; + } + } + } rc522_spi: cs_pin: GPIO15