{
"fullname": "Michele Azzolari",
"description": "Dad, Full Stack Developer, Avid music listener",
"nickname": "macno",
"created_at": "1977-04-11T18:40Z",
"current_job": "CTO and co-founder Fluidware srl",
"city": "Milan, Italy"
}
?
Of course if you use them
And if you don't... you should!
Since openssh 6.2 (2013-03-22) a new option is available
AuthorizedKeysCommand
which supports fetching authorized_keys from a command's stdout besides (or
instead of) the filesystem.
https://www.openssh.com/txt/release-6.2
Thanks @johnnyrun for heading me there
Store accounts/public keys/permissons in a single place and serve them via HTTPS to the hosts
ssh a.user@server1
GET /authorized_keys/server1/a.user
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD[....]GQWv5CcHIe1kQljCzz macno@helsinki.local
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ[....]rhAdoKKhbGfAdUw0xv macno@gruff
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQ[....]347PRq7LplS03D7xUw== macno@habanero
Involves 3 components
Consumed by Theo CLI
Consumed by Theo Agent
To avoid unauthorized keys to be returned to SSHD, Theo CLI and Theo Agent both support a way to sign (Theo CLI) and to verify (Theo Agent) each key.
Using a private key, when it sends a public key to Theo Server, it attaches also a digital signature of the key.
Using the corresponding public key of the certificate used by Theo CLI, it verifies each retrieved public key with its signature.
To test it locally, you need a machine with node, docker and a virtualization software
In the next slides I will use macos with node 8.9.4, docker 18.06.1-ce and virtualbox 5.2.20 (with
vagrant 2.2.1). The VM test-server
has been created using this
Vagrantfile.
$ head -1 /dev/urandom | base64 | head -3
AWPJQZDWIG8/RgRvJQf7oBOpbt2deEVv/79+O5DTL6wEZC33HsaefORMRhx3ocDQ8X3LsA79MNIU
vW0bhte0SDI4ZtL26m7O4+W3Z44pWfdjHnrZorOtOlvHlqBM6O/UW+dNIDK/GEy8bURlTjpjEHvG
SooEMhppFnYZofmG2Fx438L9i7fM1keXbWQdRWGN+ipmMZ2VP+pQGywNpCIq4K6mdDHfKeLzCEcB
We will use the first string as administration token and the last two as client tokens
$ docker run --rm -v /tmp/theo:/data \
--name theo-server \
-e DATA_PATH=/data/theo.db \
-e ADMIN_TOKEN="AWPJQZDWIG8/RgRvJQf7oBOpbt2deEVv/79+O5DTL6wEZC33HsaefORMRhx3ocDQ8X3LsA79MNIU" \
-e CLIENT_TOKENS="vW0bhte0SDI4ZtL26m7O4+W3Z44pWfdjHnrZorOtOlvHlqBM6O/UW+dNIDK/GEy8bURlTjpjEHvG,SooEMhppFnYZofmG2Fx438L9i7fM1keXbWQdRWGN+ipmMZ2VP+pQGywNpCIq4K6mdDHfKeLzCEcB" \
-p 9100:9100 theoapp/theo
> theo@0.12.0 start /usr/src/app
> node ./build/index.js
theo/0.12.0 listening at http://[::]:9100
$ npm i -g theoapp-cli
$ export THEO_URL=http://localhost:9100
$ export THEO_TOKEN="AWPJQZDWIG8/RgRvJQf7oBOpbt2deEVv/79+O5DTL6wEZC33HsaefORMRhx3ocDQ8X3LsA79MNIU"
We can also put these variables in a file and save it as~/.theo/env
/etc/theo/env
$ theo accounts add \
--name "Developer 1" \
--email "dev1@example.com"
+------------------------------------+
{
"id": 1,
"name": "Developer 1",
"email": "dev1@example.com",
"active": 1,
"expire_at": 0,
"public_keys": [],
"groups": [
{
"id": 1,
"name": "dev1@example.com",
"active": 1
}
],
"permissions": []
}
+------------------------------------+
$ theo keys add dev1@example.com \
--key "$(cat ~/.ssh/id_rsa.pub)"
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
{
"account_id": 1,
"public_keys": [
{
"id": 1,
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQD4DaQVgWsexxOabTPxnDau5UsQj5eGUgXLD+28rtWMEAIzehiCcM5y0aOVZO/dBHA7NyHo/jWcw6Dew/Ty/J2WAQwXtV0xFTuA+6TpWBl35UeRJwjuuGnk0nCuvxQL9qs8+7CPis9SNlIQ38wXnsHWuWKEqnTAoO5YdRsjoGtILw== macno@habanero"
}
]
}
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
$ theo accounts add \
--name "Developer 2" \
--email "dev2@example.com"
[...]
$ theo keys add dev2@example.com \
--key "$(cat ~/.ssh/id_rsa.pub)"
$ theo accounts add \
--name "Sysop A" \
--email "sysop.a@example.com"
[...]
$ theo keys add sysop.a@example.com \
--key "$(cat ~/.ssh/id_rsa.pub)"
[...]
$ theo groups add --name developers
+------------------------+
{
"id": 4,
"name": "developers",
"active": 1,
"accounts": [],
"permissions": []
}
+------------------------+
$ theo groups edit developers --add dev1@example.com dev2@example.com
+----------------+
{
"status": 201
}
+----------------+
$ theo permissions add --group developers --host test-server --user node
+---------------------+
{
"group_id": 4,
"permission_id": 1
}
+---------------------+
$ theo permissions add --account sysop.a@example.com --host test-server --user admin
+---------------------+
{
"account_id": 3,
"permission_id": 2
}
+---------------------+
$ theo groups get developers
+-------------------------------------+
{
"id": 4,
"name": "developers",
"active": 1,
"accounts": [
{
"id": 1,
"name": "Developer 1",
"email": "dev1@example.com",
"active": 1
},
{
"id": 2,
"name": "Developer 2",
"email": "dev2@example.com",
"active": 1
}
],
"permissions": [
{
"id": 1,
"user": "node",
"host": "test-server",
"created_at": 1542702951350
}
]
}
+-------------------------------------+
$ theo accounts get sysop.a@example.com
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
{
"id": 3,
"name": "Sysop A",
"email": "sysop.a@example.com",
"active": 1,
"expire_at": 0,
"public_keys": [
{
"id": 3,
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCtKaAI2AoNoA9gvd0THROZavXoYVa0DoIfrVmBW+FTh8/79yPyf3ZilZVEVpGYJixxneAk1S/k/KsMt68GrG1qaiGLh/pbtT3l6MkHXYqDZI7soi0plUtczXlX8GTyZKML+H/ZOzoltBmV02yUCnSvFecgMvoLzqg1ExGIb1/5AQ== macno@habanero",
"public_key_sig": null,
"created_at": 1542702914738
}
],
"groups": [
{
"id": 3,
"name": "sysop.a@example.com",
"active": 1
}
],
"permissions": [
{
"id": 2,
"user": "admin",
"host": "test-server",
"created_at": 1542702964294
}
]
}
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Let's move to Theo Agent
vagrant@test-server:~$ sudo curl -L -o /usr/sbin/theo-agent \
https://github.com/theoapp/theo-agent/releases/download/v0.5.2/theo-agent-linux-amd64
vagrant@test-server:~$ sudo chmod 755 /usr/sbin/theo-agent
vagrant@test-server:~$ sudo useradd --comment 'Theo Agent' \
--create-home theo-agent --shell /bin/false
vagrant@test-server:~$ sudo theo-agent -install -no-interactive \
-sshd-config \
-url http://192.168.56.1:9100 \
-token vW0bhte0SDI4ZtL26m7O4+W3Z44pWfdjHnrZorOtOlvHlqBM6O/UW+dNIDK/GEy8bURlTjpjEHvG
vagrant@test-server:~$ sudo systemctl reload ssh
vagrant@test-server:~$ sudo su theo-agent -s /bin/sh -c "/usr/sbin/theo-agent admin"
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDOul6NpEnQdRRlt9ALhWjcf1tDkK8VSwtK4FMsDcl8knAr3Ap7oj3/fBhLmlFl9e7AW9J2XFEf6jK+8Sv/N2+vxCMdg6APEsfSa0/gnTnv0JRRmMxBr0kKI/DfrCwGm0075uNmr6JegrLOiGtU/PfmHCgdNJiHqD7Z8301h+XNFQ== macno@habanero
macno@habanero:~$ ssh admin@test-server
admin@test-server: ~$
I would like to thank @gizero for his patience, hints and
support.
It's always a pleasure to work with you.
To Tommaso for his beautiful artwork on Theo's logos
Also I want to apologise to my wife and my daughters for the nights and weekends I
spent working on this project...
Thanks I love you ❤