Initialize config repository
diff --git a/roles/remove-zuul-sshkey/library/sshagent_remove_keys.py b/roles/remove-zuul-sshkey/library/sshagent_remove_keys.py
new file mode 100644
index 0000000..b4f6ea6
--- /dev/null
+++ b/roles/remove-zuul-sshkey/library/sshagent_remove_keys.py
@@ -0,0 +1,126 @@
+# Copyright 2018 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import argparse
+import os
+import socket
+import struct
+import sys
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+SSH_AGENT_FAILURE = 5
+SSH_AGENT_SUCCESS = 6
+SSH_AGENT_IDENTITIES_ANSWER = 12
+
+SSH_AGENTC_REQUEST_IDENTITIES = 11
+SSH_AGENTC_REMOVE_IDENTITY = 18
+
+
+def unpack_string(data):
+ (l,) = struct.unpack('!i', data[:4])
+ d = data[4:4 + l]
+ return (d, data[4 + l:])
+
+
+def pack_string(data):
+ ret = struct.pack('!i', len(data))
+ return ret + data
+
+
+class Agent(object):
+ def __init__(self):
+ path = os.environ['SSH_AUTH_SOCK']
+ self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.sock.connect(path)
+
+ def send(self, message_type, contents):
+ payload = struct.pack('!ib', len(contents) + 1, message_type)
+ payload += bytearray(contents)
+ self.sock.send(payload)
+
+ def recv(self):
+ buf = b''
+ while len(buf) < 5:
+ buf += self.sock.recv(1)
+ message_len, message_type = struct.unpack('!ib', buf[:5])
+ buf = buf[5:]
+ while len(buf) < message_len - 1:
+ buf += self.sock.recv(1)
+ return message_type, buf
+
+ def list(self):
+ self.send(SSH_AGENTC_REQUEST_IDENTITIES, b'')
+ mtype, data = self.recv()
+ if mtype != SSH_AGENT_IDENTITIES_ANSWER:
+ raise Exception("Invalid response to list")
+ (nkeys,) = struct.unpack('!i', data[:4])
+ data = data[4:]
+ keys = []
+ for i in range(nkeys):
+ blob, data = unpack_string(data)
+ comment, data = unpack_string(data)
+ keys.append((blob, comment))
+ return keys
+
+ def remove(self, blob):
+ self.send(SSH_AGENTC_REMOVE_IDENTITY, pack_string(blob))
+ mtype, data = self.recv()
+ if mtype != SSH_AGENT_SUCCESS:
+ raise Exception("Key was not removed")
+
+
+def run(remove):
+ a = Agent()
+ keys = a.list()
+ removed = []
+ to_remove = re.compile(remove)
+ for blob, comment in keys:
+ if not to_remove.match(comment.decode('utf8')):
+ continue
+ a.remove(blob)
+ removed.append(comment)
+ return removed
+
+
+def ansible_main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ remove=dict(required=True, type='str')))
+
+ removed = run(module.params.get('remove'))
+
+ module.exit_json(changed=(removed != []),
+ removed=removed)
+
+
+def cli_main():
+ parser = argparse.ArgumentParser(
+ description="Remove ssh keys from agent"
+ )
+ parser.add_argument('remove', nargs='+',
+ help='regex matching comments of keys to remove')
+ args = parser.parse_args()
+
+ removed = run(args.remove)
+ print(removed)
+
+
+if __name__ == '__main__':
+ if sys.stdin.isatty():
+ cli_main()
+ else:
+ ansible_main()