Ansible Amenities: Using Gitlab as Source of Truth - SSH
keys on the table -- Filip Szalbot @ unsplash
Ansible Amenities is a series of semi-regularly published posts documenting different uses of Ansible in the spirit of Hubert Klein Ikkinks Groovy Goodness.
Gitlab can do a whole host of different things for you. From building and testing to releasing and managing your software projects. We manage the SSH keys deployed to our engineering services through it as well. In this article we’re going to build a quick module for Ansible to fetch public SSH Key data from Gitlab to supply to our servers.
Gitlab API with Python
A module for Gitlab in Ansible is just a bit of Python written to interact with the API.
Interacting with the Gitlab API requires you to create an AccessToken. Make sure your account has created a valid Personal Access Token.
Using the Access Token we can log into Gitlab:
import gitlab
gitlab_url = "https://gitlab.example.org"
gitlab_token = "abcd"
gl = gitlab.Gitlab(gitlab_url, gitlab_token, per_page=100)
Retrieving Keys from Gitlab needs the username of the user to create:
user = "username"
gl_user = gl.users.list(search=user)[0] # We assume a single user matches the name we're looking for
Depending on your setup, your users may have multiple keys old and knew registered in Gitlab. Make sure you take the latest keys:
keys_data = gl_user.keys.list()
sanitized_keys_data = []
for k in keys_data:
if k.last_used_at is not None:
sanitized_keys_data.append(k)
ordered_keys_data = sorted(sanitized_keys_data, key=lambda key: key.last_used_at);
key = list(reversed(ordered_keys_data))[0].key
key now holds the public key bits of the SSH Key used by the user.
Ansible Module
With all the above learned, we can write our Ansible module:
class GitlabUserKeysInfo:
def __init__(self, module):
self.module = module
self.gitlab_url = module.params.get("gitlab_url")
self.gitlab_token = module.params.get("gitlab_token")
self.user = module.params.get("user")
self.gl = gitlab.Gitlab(self.gitlab_url, self.gitlab_token, per_page=100)
def lookupUser(self):
"""
- Finds the Username in Gitlab
- Look up his SSH Keys
- Grab last Used key
- Respond with the username and key public data
"""
user_data = self.gl.users.list(search=self.user)[0]
keys_data = user_data.keys.list()
sanitized_keys_data = []
for k in keys_data:
if k.last_used_at is not None:
sanitized_keys_data.append(k)
ordered_keys_data = sorted(sanitized_keys_data, key=lambda key: key.last_used_at);
key = list(reversed(ordered_keys_data))[0].key
user = {
"name": user_data.username,
"ssh_key": key
}
return user
def main():
module = AnsibleModule(
argument_spec=dict(
gitlab_url=dict(type='str'),
gitlab_token=dict(type='str', no_log=True),
user=dict(type='str')
)
)
gitlabUserKeysInfo = GitlabUserKeysInfo(module)
result = dict()
result = gitlabUserKeysInfo.lookupUser()
module.exit_json(**result)
if __name__ == '__main__':
main()
Placed in your Ansible modules directory, you can use it like this:
- name: "Get Keys for the user 'developer'"
gitlab_group_members_info:
gitlab_url: "https://gitlab.example.org"
gitlab_token: "T0KEN"
user: "developer"
register: "gitlab_user_key"
...
- name: Add key to users ~/.ssh/authorized_keys
ansible.posix.authorized_key:
user: developer
state: present
key: ""