Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api-objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ API examples
gl_objects/geo_nodes
gl_objects/groups
gl_objects/issues
gl_objects/keys
gl_objects/boards
gl_objects/labels
gl_objects/notifications
Expand Down
28 changes: 28 additions & 0 deletions docs/gl_objects/keys.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
####
Keys
####

Keys
====

Reference
---------

* v4 API

+ :class:`gitlab.v4.objects.Key`
+ :class:`gitlab.v4.objects.KeyManager`
+ :attr:`gitlab.Gitlab.keys`

* GitLab API: https://docs.gitlab.com/ce/api/keys.html

Examples
--------

Get an ssh key by its id (requires admin access)::

key = gl.keys.get(key_id)

Get an ssh key (requires admin access) or a deploy key by its fingerprint::

key = gl.keys.get(fingerprint="SHA256:ERJJ/OweAM6jA8OjJ/gXs4N5fqUaREEJnz/EyfywfXY")
1 change: 1 addition & 0 deletions gitlab/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ def __init__(
self.hooks = objects.HookManager(self)
self.issues = objects.IssueManager(self)
self.issues_statistics = objects.IssuesStatisticsManager(self)
self.keys = objects.KeyManager(self)
self.ldapgroups = objects.LDAPGroupManager(self)
self.licenses = objects.LicenseManager(self)
self.namespaces = objects.NamespaceManager(self)
Expand Down
1 change: 1 addition & 0 deletions gitlab/v4/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from .hooks import *
from .issues import *
from .jobs import *
from .keys import *
from .labels import *
from .ldap import *
from .members import *
Expand Down
26 changes: 26 additions & 0 deletions gitlab/v4/objects/keys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from gitlab.base import RESTManager, RESTObject
from gitlab.mixins import GetMixin

__all__ = [
"Key",
"KeyManager",
]


class Key(RESTObject):
pass


class KeyManager(GetMixin, RESTManager):
_path = "/keys"
_obj_cls = Key

def get(self, id=None, **kwargs):
if id is not None:
return super(KeyManager, self).get(id, **kwargs)

if "fingerprint" not in kwargs:
raise AttributeError("Missing attribute: id or fingerprint")

server_data = self.gitlab.http_get(self.path, **kwargs)
return self._obj_cls(self, server_data)
42 changes: 42 additions & 0 deletions tests/functional/api/test_keys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
GitLab API:
https://docs.gitlab.com/ce/api/keys.html
"""
import base64
import hashlib


def key_fingerprint(key):
key_part = key.split()[1]
decoded = base64.b64decode(key_part.encode("ascii"))
digest = hashlib.sha256(decoded).digest()
return "SHA256:" + base64.b64encode(digest).rstrip(b"=").decode("utf-8")


def test_keys_ssh(gl, user, SSH_KEY):
key = user.keys.create({"title": "foo@bar", "key": SSH_KEY})

# Get key by ID (admin only).
key_by_id = gl.keys.get(key.id)
assert key_by_id.title == key.title
assert key_by_id.key == key.key

fingerprint = key_fingerprint(SSH_KEY)
# Get key by fingerprint (admin only).
key_by_fingerprint = gl.keys.get(fingerprint=fingerprint)
assert key_by_fingerprint.title == key.title
assert key_by_fingerprint.key == key.key

key.delete()


def test_keys_deploy(gl, project, DEPLOY_KEY):
key = project.keys.create({"title": "foo@bar", "key": DEPLOY_KEY})

fingerprint = key_fingerprint(DEPLOY_KEY)
key_by_fingerprint = gl.keys.get(fingerprint=fingerprint)
assert key_by_fingerprint.title == key.title
assert key_by_fingerprint.key == key.key
assert len(key_by_fingerprint.deploy_keys_projects) == 1

key.delete()
54 changes: 54 additions & 0 deletions tests/unit/objects/test_keys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""
GitLab API: https://docs.gitlab.com/ce/api/keys.html
"""
import pytest
import responses

from gitlab.v4.objects import Key

key_content = {"id": 1, "title": "title", "key": "ssh-keytype AAAAC3Nza/key comment"}


@pytest.fixture
def resp_get_key_by_id():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/keys/1",
json=key_content,
content_type="application/json",
status=200,
)
yield rsps


@pytest.fixture
def resp_get_key_by_fingerprint():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/keys?fingerprint=foo",
json=key_content,
content_type="application/json",
status=200,
)
yield rsps


def test_get_key_by_id(gl, resp_get_key_by_id):
key = gl.keys.get(1)
assert isinstance(key, Key)
assert key.id == 1
assert key.title == "title"


def test_get_key_by_fingerprint(gl, resp_get_key_by_fingerprint):
key = gl.keys.get(fingerprint="foo")
assert isinstance(key, Key)
assert key.id == 1
assert key.title == "title"


def test_get_key_missing_attrs(gl):
with pytest.raises(AttributeError):
gl.keys.get()