如何构建递归查询以帮助我找到可通过SSH公钥授权访问的所有服务器到服务器的跳转?
对于给定的SSH pubkey指纹,首先找到授权密钥的服务器/帐户列表。对于找到的每个服务器,迭代该服务器上的私钥,并找到每个那些的授权服务器/帐户列表。
重复此过程,直到死胡同,即授权密钥路径结束。每行返回一个完整的授权密钥路径(作为一个数组)。
CREATE TABLE sshkeys (
server text, -- server UUID
username text, -- authorized username
privkey_owner text, -- owner of private key
fingerprint text, -- SSH key fingerprint
keytype text, -- "public" or "private"
)
Server Username Owner Fingerprint Keytype
banana root key_id_james public
banana james key_id_james public
banana root key_id_root@banana private
apple root key_id_root@banana public
apple fred fred key_id_fred private
mango fred key_id_fred public
James使用ID key_id_james的密钥访问root @ banana。从那里,root @ banana私钥被授权为root @ apple。在apple上,root可以访问key_id_fred,因此被授权使用fred @ mango。
所以最终,詹姆斯可以通过root访问香蕉和苹果访问Fred的芒果帐户。他还可以访问james @ banana。两个输出行将由{source,keyid,target}元素的数组组成,类似于:
{{NULL, key_id_james, root@banana},
{banana, key_id_root@banana, root@apple},
{apple, key_id_fred, fred@mango}},
{{NULL, key_id_james, james@banana}}
我计划添加应该考虑的限制和启发式方法,包括私钥是否加密以及给定用户是否具有对其他用户私钥的组或chmod访问权限(通过连接到数据库中的其他表)。但是,这应该很容易解决工作基础查询。
至于查询,我无法弄清楚如何执行辅助步骤,即:对于最初发现可通过给定密钥访问的每个服务器,迭代每个服务器上的所有私钥并递归。我没有比这个不起作用的查询更进一步:
WITH RECURSIVE initial_authkeys AS (
SELECT
server, username, privkey_owner, fingerprint, keytype
FROM
sshkeys
WHERE
fingerprint = 'key_id_james' AND
keytype = 'public'
UNION ALL
SELECT
ak.server, ak.username, ak.privkey_owner, ak.fingerprint, ak.keytype
FROM
sshkeys,
initial_authkeys ak
WHERE
sshkeys.fingerprint = ak.fingerprint AND
sshkeys.keytype = 'private'
)
SELECT * FROM initial_authkeys;
有什么建议吗?
答案 0 :(得分:0)
使这项工作需要的是一个子查询表达式,用于查找授权给定pubkey的服务器上任何可用私钥的SSH指纹。下面是一个工作查询,其中包括一个基本的启发式方法,只有在用户具有对服务器的root访问权限时才能找到私钥。它可以扩展为验证私钥文件权限,组所有权等。
WITH RECURSIVE authkeys(server, username, fingerprint, level, auth_path) AS (
SELECT
server, username, fingerprint, 1 AS level,
ARRAY['Authorized to '||username||
'@'||server||' using keyid='||fingerprint]
FROM
sshkeys
WHERE
fingerprint = 'key_id_james' AND keytype = 'public'
UNION
SELECT
k.server, k.username, k.fingerprint, ak.level+1 AS level,
auth_path || ARRAY['Authorized to '||k.username||
'@'||k.server||' using keyid='||k.fingerprint]
FROM
sshkeys k, authkeys ak
WHERE
k.keytype = 'public' AND k.fingerprint IN (
SELECT
fingerprint
FROM
sshkeys k2
WHERE
k2.server = ak.server AND k2.keytype = 'private' AND
ak.username = 'root'
)
) SELECT * FROM authkeys;