1

Basically what I am trying to do is generate a json list of SSH keys (public and private) on a server using Python. I am using nested dictionaries and while it does work to an extent, the issue lies with it displaying every other user's keys; I need it to list only the keys that belong to the user for each user.

Below is my code:

def ssh_key_info(key_files):
    for f in key_files:
            c_time = os.path.getctime(f)  # gets the creation time of file (f)
            username_list = f.split('/')  # splits on the / character
            user = username_list[2]  # assigns the 2nd field frome the above spilt to the user variable

            key_length_cmd = check_output(['ssh-keygen','-l','-f', f])  # Run the ssh-keygen command on the file (f)

            attr_dict = {}
            attr_dict['Date Created'] = str(datetime.datetime.fromtimestamp(c_time))  # converts file create time to string
            attr_dict['Key_Length]'] = key_length_cmd[0:5]  # assigns the first 5 characters of the key_length_cmd variable

            ssh_user_key_dict[f] = attr_dict
            user_dict['SSH_Keys'] = ssh_user_key_dict
            main_dict[user] = user_dict

A list containing the absolute path of the keys (/home/user/.ssh/id_rsa for example) is passed to the function. Below is an example of what I receive:

{
"user1": {
    "SSH_Keys": {
        "/home/user1/.ssh/id_rsa": {
            "Date Created": "2017-03-09 01:03:20.995862", 
            "Key_Length]": "2048 "
        }, 
        "/home/user2/.ssh/id_rsa": {
            "Date Created": "2017-03-09 01:03:21.457867", 
            "Key_Length]": "2048 "
        }, 
        "/home/user2/.ssh/id_rsa.pub": {
            "Date Created": "2017-03-09 01:03:21.423867", 
            "Key_Length]": "2048 "
        }, 
        "/home/user1/.ssh/id_rsa.pub": {
            "Date Created": "2017-03-09 01:03:20.956862", 
            "Key_Length]": "2048 "
        }
    }
}, 

As can be seen, user2's key files are included in user1's output. I may be going about this completely wrong, so any pointers are welcomed.

j0k3R
  • 48
  • 5
  • You should ask a generic question on Python containers - I believe most people just skip this, as they do not have knowledge about SSH keys. While your question actually has nothing to do with the SSH host keys. It's pretty trivial Python question. – Martin Prikryl Apr 10 '17 at 06:46
  • The critical point of function is `ssh_user_key_dict[f] = attr_dict`. That is where a new key for each iteration is created. (First key is "/home/user1/.ssh/id_rsa"). The next two steps just constantly reassign `user_dict['SSH_Keys']` and `main_dict[user]`. I guess you have `user2` with 3 `SSH_Keys`;) – Vadim Shkaberda Apr 10 '17 at 16:48

1 Answers1

0

Thanks for the replies, I read up on nested dictionaries and found that the best answer on this post, helped me solve the issue: What is the best way to implement nested dictionaries?

Instead of all the dictionaries, I simplfied the code and just have one dictionary now. This is the working code:

class Vividict(dict):
    def __missing__(self, key):          # Sets and return a new instance
        value = self[key] = type(self)() # retain local pointer to value
        return value                     # faster to return than dict lookup

main_dict = Vividict()

def ssh_key_info(key_files):
            for f in key_files:
                c_time = os.path.getctime(f)
                username_list = f.split('/')
                user = username_list[2]

                key_bit_cmd = check_output(['ssh-keygen','-l','-f', f])
                date_created = str(datetime.datetime.fromtimestamp(c_time))
                key_type = key_bit_cmd[-5:-2]
                key_bits = key_bit_cmd[0:5]

                main_dict[user]['SSH Keys'][f]['Date Created'] = date_created
                main_dict[user]['SSH Keys'][f]['Key Type'] = key_type
                main_dict[user]['SSH Keys'][f]['Bits'] = key_bits
Community
  • 1
  • 1
j0k3R
  • 48
  • 5