feat: mlock nicht mehr gegen vault

This commit is contained in:
neri 2025-01-11 02:12:21 +01:00
parent ce18b83ece
commit a34e80113c
2 changed files with 119 additions and 44 deletions

2
.gitignore vendored
View file

@ -1,4 +1,6 @@
.idea/ .idea/
venv/ venv/
.venv/
.esphome/ .esphome/
secrets.yaml secrets.yaml
.envrc

View file

@ -1,14 +1,11 @@
# todos:
# - move code into packages to make this re-useable
# - testing
substitutions: substitutions:
ota_password: "" name_of_board: lasercutter
api_enckey: "" ip_addr: "172.23.23.26"
wifi_ssid: "" machines_token: !secret mlock_machines_token
wifi_password: "" wifi_ssid: !secret wifi_ssid
vault_role_id: "" wifi_password: !secret wifi_password
vault_secret_id: "" ota_password: !secret ota_password
api_enckey: !secret api_enckey
###### nothing to change below this line ###### ###### nothing to change below this line ######
esphome: esphome:
@ -35,6 +32,7 @@ esp8266:
# Enable logging # Enable logging
logger: logger:
level: DEBUG
api: api:
encryption: encryption:
@ -58,6 +56,9 @@ wifi:
dns1: 172.23.23.1 dns1: 172.23.23.1
subnet: 255.255.255.0 subnet: 255.255.255.0
on_connect:
- script.execute: refresh_access_machines
captive_portal: captive_portal:
spi: spi:
@ -102,7 +103,7 @@ script:
then: then:
- script.execute: toggle_switch - script.execute: toggle_switch
- script.wait: toggle_switch - script.wait: toggle_switch
- if: # return LED to switch state before - if: # set LED to new switch state
condition: condition:
switch.is_on: mlock_${name_of_board}_switch switch.is_on: mlock_${name_of_board}_switch
then: then:
@ -110,36 +111,18 @@ script:
else: else:
- light.addressable_set: { id: status_led, red: 100%, green: 0%, blue: 0% } - light.addressable_set: { id: status_led, red: 100%, green: 0%, blue: 0% }
else: else:
- script.execute: fetch_token_vault - script.execute: check_access_machines
- id: fetch_token_vault - id: check_access_machines
then: mode: queued
# 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
then: then:
- lambda: |- - lambda: |-
id(access_allowed) = false; id(access_allowed) = false;
- http_request.get: - http_request.get:
url: !lambda |- 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 verify_ssl: false
headers: headers:
X-Vault-Token: !lambda return id(vault_api_token).c_str(); Authorization: !lambda return "Bearer $machines_token";
on_response: on_response:
then: then:
- if: - if:
@ -147,15 +130,27 @@ script:
lambda: 'return status_code == 200;' lambda: 'return status_code == 200;'
then: # when found, check if machine is allowed, turn on output or blink LED red then: # when found, check if machine is allowed, turn on output or blink LED red
- lambda: |- - lambda: |-
json::parse_json(id(http_request_data).get_string(), [](JsonObject root) { std::string response = id(http_request_data).get_string();
id(access_allowed) = (root["data"]["mlock-$name_of_board"] == "1"); 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<JsonArray>()) {
std::string received_token = elem.as<std::string>();
int received_value = decode_token(received_token);
if (rfid_value == received_value) {
id(access_allowed) = true;
break;
}
}
- if: - if:
condition: condition:
lambda: 'return id(access_allowed);' lambda: 'return id(access_allowed);'
then: then:
- script.execute: toggle_switch - script.execute: toggle_switch
- script.execute: cache_token - script.execute:
id: cache_token
token: !lambda return id(rfid_tag);
- script.wait: toggle_switch - script.wait: toggle_switch
else: else:
- repeat: - repeat:
@ -165,15 +160,15 @@ script:
- delay: 0.1s - delay: 0.1s
- light.addressable_set: { id: status_led, red: 0%, green: 0%, blue: 0% } - light.addressable_set: { id: status_led, red: 0%, green: 0%, blue: 0% }
- delay: 0.1s - delay: 0.1s
else: # vault returns 404 on missing/unknown Tag so blink LED else: # could not fetch machine config, so blink LED
- repeat: - repeat:
count: 3 count: 5
then: then:
- light.addressable_set: { id: status_led, red: 100%, green: 0%, blue: 0% } - 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% } - light.addressable_set: { id: status_led, red: 0%, green: 0%, blue: 0% }
- delay: 0.5s - delay: 0.8s
- if: # return LED to switch state before - if: # return LED to switch state
condition: condition:
switch.is_on: mlock_${name_of_board}_switch switch.is_on: mlock_${name_of_board}_switch
then: then:
@ -181,6 +176,7 @@ script:
else: else:
- light.addressable_set: { id: status_led, red: 100%, green: 0%, blue: 0% } - light.addressable_set: { id: status_led, red: 100%, green: 0%, blue: 0% }
- id: toggle_switch - id: toggle_switch
mode: queued
then: then:
- if: - if:
condition: condition:
@ -203,9 +199,13 @@ script:
id: ${name_of_board}_letzte_entsperrung id: ${name_of_board}_letzte_entsperrung
value: !lambda return id(rfid_tag); value: !lambda return id(rfid_tag);
- id: cache_token - id: cache_token
mode: queued
parameters:
token: string
then: then:
- lambda: |- - 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; int rfid_value_pos = 23;
// search the token in the list to keep the access_cache unique // search the token in the list to keep the access_cache unique
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
@ -220,6 +220,79 @@ script:
} }
// write the new token to the start // write the new token to the start
id(access_cache)[0] = rfid_value; 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<JsonArray>();
// 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<std::string>();
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<std::string>();
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: rc522_spi:
cs_pin: GPIO15 cs_pin: GPIO15