diff options
author | Ben Brown <ben.brown@codethink.co.uk> | 2021-05-25 14:14:18 +0100 |
---|---|---|
committer | Ben Brown <ben.brown@codethink.co.uk> | 2021-06-03 09:22:10 +0100 |
commit | a81525a2377aaed797af0706b00be7f5d8616d22 (patch) | |
tree | df32c795081135a1f7abde8500b72c382f68c9b9 | |
parent | 74f5e62ef5bfffc7ba21494d05dbead60b59ecf0 (diff) | |
download | gitlab-a81525a2377aaed797af0706b00be7f5d8616d22.tar.gz |
feat: add keys endpoint
-rw-r--r-- | docs/api-objects.rst | 1 | ||||
-rw-r--r-- | docs/gl_objects/keys.rst | 28 | ||||
-rw-r--r-- | gitlab/client.py | 1 | ||||
-rw-r--r-- | gitlab/v4/objects/__init__.py | 1 | ||||
-rw-r--r-- | gitlab/v4/objects/keys.py | 26 | ||||
-rw-r--r-- | tests/functional/api/test_keys.py | 42 | ||||
-rw-r--r-- | tests/unit/objects/test_keys.py | 54 |
7 files changed, 153 insertions, 0 deletions
diff --git a/docs/api-objects.rst b/docs/api-objects.rst index 2f1be1a..567344f 100644 --- a/docs/api-objects.rst +++ b/docs/api-objects.rst @@ -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 diff --git a/docs/gl_objects/keys.rst b/docs/gl_objects/keys.rst new file mode 100644 index 0000000..6d35218 --- /dev/null +++ b/docs/gl_objects/keys.rst @@ -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") diff --git a/gitlab/client.py b/gitlab/client.py index d19acfb..f628d4f 100644 --- a/gitlab/client.py +++ b/gitlab/client.py @@ -119,6 +119,7 @@ class Gitlab(object): 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) diff --git a/gitlab/v4/objects/__init__.py b/gitlab/v4/objects/__init__.py index 3317396..2dd7973 100644 --- a/gitlab/v4/objects/__init__.py +++ b/gitlab/v4/objects/__init__.py @@ -43,6 +43,7 @@ from .groups import * from .hooks import * from .issues import * from .jobs import * +from .keys import * from .labels import * from .ldap import * from .members import * diff --git a/gitlab/v4/objects/keys.py b/gitlab/v4/objects/keys.py new file mode 100644 index 0000000..7f8fa0e --- /dev/null +++ b/gitlab/v4/objects/keys.py @@ -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) diff --git a/tests/functional/api/test_keys.py b/tests/functional/api/test_keys.py new file mode 100644 index 0000000..82a75e5 --- /dev/null +++ b/tests/functional/api/test_keys.py @@ -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() diff --git a/tests/unit/objects/test_keys.py b/tests/unit/objects/test_keys.py new file mode 100644 index 0000000..187a309 --- /dev/null +++ b/tests/unit/objects/test_keys.py @@ -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() |