From 948713db5e1399d5747dbf191dfe22a95e69a4b4 Mon Sep 17 00:00:00 2001 From: Stefan Heinemann Date: Mon, 14 Oct 2013 16:59:30 +0200 Subject: [PATCH 1/2] Don't mind the options of a key when removing it This allows to remove a key without knowing the options in the authorized_key file --- system/authorized_key | 45 ++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/system/authorized_key b/system/authorized_key index 98f97eeb22f..8d1866974b9 100644 --- a/system/authorized_key +++ b/system/authorized_key @@ -221,16 +221,17 @@ def readkeys(filename): if not os.path.isfile(filename): return [] - keys = [] + keys = {} f = open(filename) for line in f.readlines(): key_data = parsekey(line) if key_data: - keys.append(key_data) + # use key as identifier + keys[key_data[0]] = key_data else: # for an invalid line, just append the line # to the array so it will be re-output later - keys.append(line) + keys[line] = line f.close() return keys @@ -239,7 +240,7 @@ def writekeys(module, filename, keys): fd, tmp_path = tempfile.mkstemp('', 'tmp', os.path.dirname(filename)) f = open(tmp_path,"w") try: - for key in keys: + for index, key in keys.items(): try: (keyhash,type,options,comment) = key option_str = "" @@ -290,39 +291,35 @@ def enforce_state(module, params): present = False matched = False non_matching_keys = [] - for existing_key in existing_keys: - # skip bad entries or bad input - if len(parsed_new_key) == 0 or len(existing_key) == 0: - continue - # the first element in the array after parsing - # is the actual key hash, which we check first - if parsed_new_key[0] == existing_key[0]: - present = True - # Then we check if everything matches, including - # the key type and options. If not, we append this - # existing key to the non-matching list - if parsed_new_key != existing_key: - non_matching_keys.append(existing_key) - else: - matched = True + + if parsed_new_key[0] in existing_keys: + present = True + # Then we check if everything matches, including + # the key type and options. If not, we append this + # existing key to the non-matching list + # We only want it to match everything when the state + # is present + if parsed_new_key != existing_keys[parsed_new_key[0]] and state == "present": + non_matching_keys.append(existing_keys[parsed_new_key[0]]) + else: + matched = True + # handle idempotent state=present if state=="present": if unique and len(non_matching_keys) > 0: for non_matching_key in non_matching_keys: - existing_keys.remove(non_matching_key) + del existing_keys[non_matching_key[0]] do_write = True if not matched: - existing_keys.append(parsed_new_key) + existing_keys[parsed_new_key[0]] = parsed_new_key do_write = True elif state=="absent": - # currently, we only remove keys when - # they are an exact match if not matched: continue - existing_keys.remove(parsed_new_key) + del existing_keys[parsed_new_key[0]] do_write = True if do_write: From 576f5813a2ab1b604d1f04e7230be5010e9a60e1 Mon Sep 17 00:00:00 2001 From: Stefan Heinemann Date: Tue, 15 Oct 2013 10:11:05 +0200 Subject: [PATCH 2/2] Set the options of an authorized key comma separated According to the sshd man page, no spaces are permitted between the options of an authorized ssh key --- system/authorized_key | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/system/authorized_key b/system/authorized_key index 8d1866974b9..339e3b4bf2e 100644 --- a/system/authorized_key +++ b/system/authorized_key @@ -245,11 +245,15 @@ def writekeys(module, filename, keys): (keyhash,type,options,comment) = key option_str = "" if options: + option_strings = [] for option_key in options.keys(): if options[option_key]: - option_str += "%s=%s " % (option_key, options[option_key]) + option_strings.append("%s=%s" % (option_key, options[option_key])) else: - option_str += "%s " % option_key + option_strings.append("%s " % option_key) + + option_str = ",".join(option_strings) + option_str += " " key_line = "%s%s %s %s\n" % (option_str, type, keyhash, comment) except: key_line = key