diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5717143 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "actors/fabreader"] + path = actors/fabreader + url = https://gitlab.com/fabinfra/fabaccess/actors/fabreader.git +[submodule "actors/fablock"] + path = actors/fablock + url = https://gitlab.com/fabinfra/fabaccess/actors/fablock.git diff --git a/actors/fablock b/actors/fablock new file mode 160000 index 0000000..608ed8e --- /dev/null +++ b/actors/fablock @@ -0,0 +1 @@ +Subproject commit 608ed8ecd223cbe91beeef268991790dd136c891 diff --git a/actors/fabreader b/actors/fabreader new file mode 160000 index 0000000..1eabb0d --- /dev/null +++ b/actors/fabreader @@ -0,0 +1 @@ +Subproject commit 1eabb0d82ee93c87b369a2a7ed82a4fe7a8bf279 diff --git a/bffh.dhall b/bffh.dhall new file mode 100644 index 0000000..5927f7c --- /dev/null +++ b/bffh.dhall @@ -0,0 +1,459 @@ +{- Main configuration file for bffh + - ================================ + - + - In this configuration file you configure almost all parts of how bffh operates, but most importantly: + - * Machines + - * Initiators and Actors + - * Which Initiators and Actors relate to which machine(s) + - * Roles and the permissions granted by them + -} + +-- The config is in the configuration format/language dhall. You can find more information about dhall over at +-- https://dhall-lang.org + +-- (Our) Dhall is somewhat similar to JSON and YAML in that it expects a top-level object containing the +-- configuration values +{ + -- Configure the addresses and ports bffh listens on + listens = [ + -- BFFH binds a port for every listen object in this array. + -- Each listen object is of the format { address = , port = } + -- If you don't specify a port bffh will use the default of `59661` + -- 'address' can be a IP address or a hostname + -- If bffh can not bind a port for the specified combination if will log an error but *continue with the remaining ports* + { address = "::", port = Some 59661 } + ], + + -- Configure TLS. BFFH requires a PEM-encoded certificate and the associated key as two separate files + certfile = "certs/self-signed-cert.pem", + keyfile = "certs/self-signed-key.pem", + + -- BFFH right now requires a running MQTT broker. + mqtt_url = "mqtt://localhost:1883", + + -- Path to the database file for bffh. bffh will in fact create two files; ${db_path} and ${db_path}.lock. + -- BFFH will *not* create any directories so ensure that the directory exists and the user running bffh has write + -- access into them. + db_path = "/var/lib/bffh/db", + + -- Audit log path. Bffh will log state changes into this file, one per line. + -- Audit log entries are for now JSON: + -- {"timestamp":1641497361,"machine":"Testmachine","state":{"state":{"InUse":{"uid":"Testuser","subuid":null,"realm":null}}}} + auditlog_path = "/tmp/bffh.audit", + + -- set logging to verbose + verbosity = 3, + spacename = "FabCity-Demo", + instanceurl = "fabcity_demo.fab-access.org", + + -- In dhall you can also easily import definitions from other files, e.g. you could write + -- roles = ./roles.dhall + roles = + { + -- Role definitions + -- A role definition is of the form + -- rolename = { + -- parents = [], + -- permissions = [], + -- } + -- + -- Role names are case sensitive, so RoleName != rolename. + -- + -- If you want either parents or permissions to be empty its best to completely skip it: + + Default = { + permissions = + [ + "fabcity.disclose", + "fabcity.read", + + + ] + }, + Admin = + { + permissions = + [ + "fabcity.*", + "bffh.users.info", + "bffh.users.manage", + "bffh.users.admin", + ] + }, + Manage = + { + permissions = + [ + "fabcity.manage", + ] + }, + + EuroBox = + { + permissions = + [ + "fabcity.eurobox.write", + ] + }, + + LBoxx = + { + permissions = + [ + "fabcity.lboxx.write", + ] + }, + Locker = + { + permissions = + [ + "fabcity.locker.write", + ] + }, + Lasercutter = + { + permissions = + [ + "fabcity.lasercutter.write", + ] + }, + Printer = + { + permissions = + [ + "fabcity.printer.write", + ] + }, + CNC = + { + permissions = + [ + "fabcity.cnc.write", + ] + }, + }, + + -- Configure machines + -- "Machines" (which in future will be more appropiately named "resources") are the main thing bffh is concerned + -- with. + -- You can define an almost limitless amount of machines (well 2^64 - 1, so 18_446_744_073_709_551_615 to be precise) + -- Each of these machines can then have several "actors" and "initiators" assigned + machines = { + -- FabLock with LBoxx + LBoxx_0 = + { + name = "Filament", + description = Some "LBoxx with 1,75mm PLA", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.lboxx.use", + manage = "fabcity.manage", + category = "LBoxx" + }, + LBoxx_1 = + { + name = "FabLock Tools", + description = Some "LBoxx with Tools of the FabLock Project", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.lboxx.use", + manage = "fabcity.manage", + category = "LBoxx" + }, + LBoxx_2 = + { + name = "FabReader Tools", + description = Some "LBoxx with Tools of the FabReader Project", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.lboxx.use", + manage = "fabcity.manage", + category = "LBoxx" + }, + LBoxx_3 = + { + name = "Sticker", + description = Some "LBoxx with FabAccess Sticker and NTAGs", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.lboxx.use", + manage = "fabcity.manage", + category = "LBoxx" + }, + LBoxx_4 = + { + name = "Demo Parts", + description = Some "LBoxx with Parts for the FabCity Demo", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.lboxx.use", + manage = "fabcity.manage", + category = "LBoxx" + }, + + -- FabLock with EuroBox + EuroBox_0 = + { + name = "Haribo", + description = Some "EuroBox with Haribo", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.eurobox.use", + manage = "fabcity.manage", + category = "EuroBox" + }, + EuroBox_1 = + { + name = "Goldschatz", + description = Some "EuroBox with Rittersport Goldschatz", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.eurobox.use", + manage = "fabcity.manage", + category = "EuroBox" + }, + + -- FabLock with Kallax + Drawer_0 = + { + name = "Drawer 0 ???", + description = Some "Kallax Drawer", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.locker.use", + manage = "fabcity.manage", + category = "Locker" + }, + Drawer_1 = + { + name = "Drawer 1 ???", + description = Some "Kallax Drawer", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.locker.use", + manage = "fabcity.manage", + category = "Locker" + }, + Drawer_2 = + { + name = "Drawer 2 ???", + description = Some "Kallax Drawer", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.locker.use", + manage = "fabcity.manage", + category = "Locker" + }, + Drawer_3 = + { + name = "Drawer 3 ???", + description = Some "Kallax Drawer", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.locker.use", + manage = "fabcity.manage", + category = "Locker" + }, + Door_0 = + { + name = "Door ???", + description = Some "Kallax Door", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.locker.use", + manage = "fabcity.manage", + category = "Locker" + }, + + -- Machines + Printer_0 = + { + name = "Prusa MK3", + description = Some "FabAccess Prusa MK3", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.printer.use", + manage = "fabcity.manage", + category = "Printers" + }, + Printer_1 = + { + name = "Other Printer ???", + description = Some "FabCity Printer", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.printer.use", + manage = "fabcity.manage", + category = "Printers" + }, + Lasercutter_0 = + { + name = "Other Lasercutter ???", + description = Some "FabCity Lasercutter", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.printer.use", + manage = "fabcity.manage", + category = "Lasercutter" + }, + CNC_0 = + { + name = "Other Printer ???", + description = Some "FabCity CNC", + disclose = "fabcity.disclose", + read = "fabcity.read", + write = "fabcity.printer.use", + manage = "fabcity.manage", + category = "CNC" + }, + }, + + -- Actor configuration. Actors are how bffh affects change in the real world by e.g. switching a power socket + -- using a shelly + actors = { + -- Actors similarly to machines have an 'id'. This id (here "Shelly1234") is limited to Alphanumeric ASCII + -- and must begin with a letter. + shellyplug-s-C8C9A3B942DB = { module = "Shelly", params = {=} }, + shellyplug-s-C8C9A3B943D7 = { module = "Shelly", params = {=} }, + shellyplug-s-C8C9A3B8DB67 = { module = "Shelly", params = {=} }, + shellyplug-s-3CE90ED72CEF = { module = "Shelly", params = {=} }, + shellyplug-s-3CE90ED72481 = { module = "Shelly", params = {=} }, + shellyplug-s-C8C9A3B8E88A = { module = "Shelly", params = {=} }, + shellyplug-2C94AA = { module = "Shelly", params = {=} }, + shellyplug-C198E8 = { module = "Shelly", params = {=} }, + + -- Kallax Locker + fablock_locker_0 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00000 --lock 00000" + }}, + fablock_locker_1 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00000 --lock 00001" + }}, + fablock_locker_2 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00000 --lock 00002" + }}, + fablock_locker_3 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00000 --lock 00003" + }}, + fablock_locker_4 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00000 --lock 00004" + }}, + fablock_locker_5 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00000 --lock 00005" + }}, + fablock_locker_6 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00000 --lock 00006" + }}, + + -- LBoxx Rack + fablock_lboxx_0 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00001 --lock 00000" + }}, + fablock_lboxx_1 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00001 --lock 00001" + }}, + fablock_lboxx_2 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00001 --lock 00002" + }}, + fablock_lboxx_3 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00001 --lock 00003" + }}, + fablock_lboxx_4 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fablock/main.py --host localhost --fablock 00001 --lock 00004" + }}, + + -- FabReader + fabreader_0 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fabreader/main.py --host localhost --fabreader 00000" + }}, + fabreader_1 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fabreader/main.py --host localhost --fabreader 00001" + }}, + fabreader_2 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fabreader/main.py --host localhost --fabreader 00002" + }}, + fabreader_3 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fabreader/main.py --host localhost --fabreader 00003" + }}, + fabreader_4 = { module = "Process", params = + { + cmd = "python", + args = "config/actors/fabreader/main.py --host localhost --fabreader 00004" + }}, + }, + + -- Linkng up machines to actors + -- Actors need to be connected to machines to be useful. A machine can be connected to multiple actors, but one + -- actor can only be connected to one machine. + actor_connections = [ + { machine = "LBoxx_0", actor = "fablock_lboxx_0" }, + { machine = "LBoxx_1", actor = "fablock_lboxx_1" }, + { machine = "LBoxx_2", actor = "fablock_lboxx_2" }, + { machine = "LBoxx_3", actor = "fablock_lboxx_3" }, + { machine = "LBoxx_4", actor = "fablock_lboxx_4" }, + + { machine = "EuroBox_0", actor = "fablock_locker_0" }, + { machine = "EuroBox_1", actor = "fablock_locker_1" }, + { machine = "Drawer_0", actor = "fablock_locker_2" }, + { machine = "Drawer_1", actor = "fablock_locker_3" }, + { machine = "Drawer_2", actor = "fablock_locker_4" }, + { machine = "Drawer_3", actor = "fablock_locker_5" }, + { machine = "Door_4", actor = "fablock_locker_6" }, + + { machine = "Printer_0", actor = "shellyplug-s-C8C9A3B942DB" }, + { machine = "Printer_1", actor = "shellyplug-s-3CE90ED72481" }, + { machine = "Lasercutter_0", actor = "shellyplug-s-C8C9A3B943D7" }, + { machine = "CNC_0", actor = "shellyplug-s-C8C9A3B8E88A" }, + ], + + -- Initiators are configured almost the same way as Actors, refer to actor documentation for more details + -- The below '{=}' is what you need if you want to define *no* initiators at all and only use the API with apps + -- to let people use machines. + initiators = + { + + }, + -- The "Dummy" initiator will try to use and return a machine as the given user every few seconds. It's good to + -- test your system but will spam your log so is disabled by default. + --initiators = { Initiator = { module = "Dummy", params = { uid = "Testuser" } } }, + + -- Linking up machines to initiators. Similar to actors a machine can have several initiators assigned but an + -- initiator can only be assigned to one machine. + -- The below is once again how you have to define *no* initiators. + init_connections = + [ + + ] : List { machine : Text, initiator : Text } +} diff --git a/certs/self-signed-cert.pem b/certs/self-signed-cert.pem new file mode 100644 index 0000000..89f056d --- /dev/null +++ b/certs/self-signed-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFzCCAf+gAwIBAgIUDr+1F3zzyza+soLtiurKEXW9pGIwDQYJKoZIhvcNAQEL +BQAwGzEZMBcGA1UEAwwQYmZmaC1kZXZlbG9wbWVudDAeFw0yMTEyMDkxODQ2Mjla +Fw0zMTEyMDkxODQ2MjlaMBsxGTAXBgNVBAMMEGJmZmgtZGV2ZWxvcG1lbnQwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGwNy7yGaURR08dWfoDmnJeyx1 +0FVRmozoGCIb3Oj6c2t+84QUxqTdknE7Cdcz5Wi1o0x2CWPZG4z1vgTaCcJVhcME +hxn+7eK1NtDQEjs8Ojs7uaraVvooIe8R7jat0qs7Dmf8RO9P0I4MMZlvijhI7aLw +0C6vNsr1ebeppIiwO5aUuCGuKqxJGghHeqZv18ZcPayunyNrxMC6uyX7y6nUVkfq +x0m9gDsN112Iv9Dd/ZE5Gxivm8jZvVUGZgJD2szK7zbeCDeo5aU3cRWfYaoN0QDx +AKmo4bjciJzfMDDgvcIBq9lGS3FxEv394Mc5YX/ZdP+KRTiHcYCXfBzr3B6HAgMB +AAGjUzBRMB0GA1UdDgQWBBTtUvvWXlo5tU8cEoxbs5UJdodOVDAfBgNVHSMEGDAW +gBTtUvvWXlo5tU8cEoxbs5UJdodOVDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQAB3IxRnWi/LrxCvlHNaWEi3ZvlbN+KpegWZeKtjHwQoizhR/Fi +SMC7z4y6trJE7LXUOSb9Pu8QQSvpVQZd3W4XCPZMl10Lt7iV8vc3pVviCseDnT9r +X1gXdbeuyYm9lE8KtlhX03jD/CiEx7Qe/q8Rc20AQIKAAJzvl7sXU2tmJ5kpzMEO +v5czlLaX2ajlD/QMgNBUuDyw6wPo3wx9Khph484RygN2LHeT6kfu/PBiF0dGDTUu +mgxg4K0GfwTcHgtz5Bag/HyuuJEKx8Wv7jth59PyKPT+lMVBznxIm3gLS5U+Nnr1 +uAws8dgLXRlPo5HJORuJCcZWVBClruZUpyDT +-----END CERTIFICATE----- diff --git a/certs/self-signed-key.pem b/certs/self-signed-key.pem new file mode 100644 index 0000000..08139db --- /dev/null +++ b/certs/self-signed-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDGwNy7yGaURR08 +dWfoDmnJeyx10FVRmozoGCIb3Oj6c2t+84QUxqTdknE7Cdcz5Wi1o0x2CWPZG4z1 +vgTaCcJVhcMEhxn+7eK1NtDQEjs8Ojs7uaraVvooIe8R7jat0qs7Dmf8RO9P0I4M +MZlvijhI7aLw0C6vNsr1ebeppIiwO5aUuCGuKqxJGghHeqZv18ZcPayunyNrxMC6 +uyX7y6nUVkfqx0m9gDsN112Iv9Dd/ZE5Gxivm8jZvVUGZgJD2szK7zbeCDeo5aU3 +cRWfYaoN0QDxAKmo4bjciJzfMDDgvcIBq9lGS3FxEv394Mc5YX/ZdP+KRTiHcYCX +fBzr3B6HAgMBAAECggEAS5DGG6ssvRCt9e+ZatQYCl+HXt+voJAHJLMQPNG3zokV +hLXnMNL5mbh0zoKGTJfbQLvudS5KxR/BbykoxRFSzptFszH+gztEp6tIpuNXnCVz +odiMiejpwVptf763EU14hsKKbJJ0/j6H00EEWjEOB0Q6YB52sW0+qyf02U3SHlZN +k2PZYkpHi3YCONtOGj7jOdW7M3RfvcBNg9EW7fZc1KkiRAlscUAYLMkKcOLevil0 +lUuF/JWj4iH22Oq6+JeSiecf6izF6lyIGvMXPry+woa8Iq0BBdmbZsK7r/Pa+wlz ++E6xHGn2rcyrnYB2pPc+RfHhYlodaOo69DxAYlRYaQKBgQDxnKySmlcfHe8lMqR4 +2LvqMyGjNRo2+q9VZYej2mvr6+TGyd7Op/fRJ1t5f9DgtINomNQYSOtYAsPiEnl+ +43z2N/Rdh6XSmOj4gLkDeiYNSpy86L/F39uCWZpkkqiy2zxYLWOs15MA0GWOtQGh +dz4cM0b/jyZOdHZR//L5WiMLawKBgQDSltEfQKqCEKJTqp4SU9BCHQmyheIjepY2 +eKakgcsjpFjRBK2VrUalDLOQV74rtd7wp8F8kqqPJpRshb+oVuDCg6JB17UxYd34 +iB+5cMdLRpg8f0HOqcYz4KOql2QhJQhFc3jzY7n1piPEhFO/MqFwmlUB4RdgJ3ix +HqX+F/T8VQKBgGos76l9KcwC25T9LEnu9KV20tFmBJ8kiuh8NZ9L3SFQCLlS/RbT +uZOwOAKsqJ4WtajBgHMrmECU9n/inoGkdsW80SZI9hYWHEsYRjXA9/ffUgGyRpQu +S8h8l9yalogC0AHv8F2EXpV8/yQ3ZwAN5r19yzWDMtJHW7etQplRgxUBAoGAGeOy +t+3iSHU1D6YlIsmtC8O4Int1LrluaCnzCrxuNeaJiMDTelhAHCBwnuk6lvMYAmwN +THxXfZvXmXPj+RUdMqyuMPwM6ZJHkLtjcw/bYHTAWIeolnimxk/yrxFHnQ+Jcchd +cUasYPfY49sE1Lerw0Ul+EIs9oRDwTqsW42kb7UCgYEA2y+oc7Fz2eq38hSbTfy7 +OcATtny+xQ1+4IELtQIP7VctkMInJs57J+vS//IT41P0L2K1YjvL8RacnvG7yMvP +GnwHBcKgvL6zuoy11I3zPPYtbKGwcJoVGomPX7W0csfl4gdST3uugd9iCDEB8NsS +QmOYM/dk8x8aWpndBjRF5ig= +-----END PRIVATE KEY----- diff --git a/users.toml b/users.toml new file mode 100644 index 0000000..b32fd13 --- /dev/null +++ b/users.toml @@ -0,0 +1,11 @@ +[Admin] +roles = ["Admin"] +passwd = "secret" + +[Manager] +roles = ["Default", "Manage"] +passwd = "secret" + +[Maker] +roles = ["Default"] +passwd = "secret" \ No newline at end of file