Skip to content

feat(api): add support for Gitlab Deploy Token API #1052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 7, 2020
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
13 changes: 13 additions & 0 deletions docs/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,19 @@ Get a specific user by id:

$ gitlab user get --id 3

Create a deploy token for a project:

.. code-block:: console

$ gitlab -v project-deploy-token create --project-id 2 \
--name bar --username root --expires-at "2021-09-09" --scopes "read_repository"

List deploy tokens for a group:

.. code-block:: console

$ gitlab -v group-deploy-token list --group-id 3

Get a list of snippets for this project:

.. code-block:: console
Expand Down
137 changes: 137 additions & 0 deletions docs/gl_objects/deploy_tokens.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#######
Deploy tokens
#######

Deploy tokens allow read-only access to your repository and registry images
without having a user and a password.

Deploy tokens
=============

This endpoint requires admin access.

Reference
---------

* v4 API:

+ :class:`gitlab.v4.objects.DeployToken`
+ :class:`gitlab.v4.objects.DeployTokenManager`
+ :attr:`gitlab.Gitlab.deploytokens`

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

Examples
--------

Use the ``list()`` method to list all deploy tokens across the GitLab instance.

::

# List deploy tokens
deploy_tokens = gl.deploytokens.list()

Project deploy tokens
=====================

This endpoint requires project maintainer access or higher.

Reference
---------

* v4 API:

+ :class:`gitlab.v4.objects.ProjectDeployToken`
+ :class:`gitlab.v4.objects.ProjectDeployTokenManager`
+ :attr:`gitlab.v4.objects.Project.deploytokens`

* GitLab API: https://docs.gitlab.com/ce/api/deploy_tokens.html#project-deploy-tokens

Examples
--------

List the deploy tokens for a project::

deploy_tokens = project.deploytokens.list()

Create a new deploy token to access registry images of a project:

In addition to required parameters ``name`` and ``scopes``, this method accepts
the following parameters:

* ``expires_at`` Expiration date of the deploy token. Does not expire if no value is provided.
* ``username`` Username for deploy token. Default is ``gitlab+deploy-token-{n}``


::

deploy_token = project.deploytokens.create({'name': 'token1', 'scopes': ['read_registry'], 'username':'', 'expires_at':''})
# show its id
print(deploy_token.id)
# show the token value. Make sure you save it, you won't be able to access it again.
print(deploy_token.token)

.. warning::

With GitLab 12.9, even though ``username`` and ``expires_at`` are not required, they always have to be passed to the API.
You can set them to empty strings, see: https://gitlab.com/gitlab-org/gitlab/-/issues/211878.
Also, the ``username``'s value is ignored by the API and will be overriden with ``gitlab+deploy-token-{n}``,
see: https://gitlab.com/gitlab-org/gitlab/-/issues/211963
These issues were fixed in GitLab 12.10.

Remove a deploy token from the project::

deploy_token.delete()
# or
project.deploytokens.delete(deploy_token.id)


Group deploy tokens
===================

Reference
---------

* v4 API:

+ :class:`gitlab.v4.objects.GroupDeployToken`
+ :class:`gitlab.v4.objects.GroupDeployTokenManager`
+ :attr:`gitlab.v4.objects.Group.deploytokens`

* GitLab API: https://docs.gitlab.com/ce/api/deploy_tokens.html#group-deploy-tokens

Examples
--------

List the deploy tokens for a group::

deploy_tokens = group.deploytokens.list()

Create a new deploy token to access all repositories of all projects in a group:

In addition to required parameters ``name`` and ``scopes``, this method accepts
the following parameters:

* ``expires_at`` Expiration date of the deploy token. Does not expire if no value is provided.
* ``username`` Username for deploy token. Default is ``gitlab+deploy-token-{n}``

::

deploy_token = group.deploytokens.create({'name': 'token1', 'scopes': ['read_repository'], 'username':'', 'expires_at':''})
# show its id
print(deploy_token.id)

.. warning::

With GitLab 12.9, even though ``username`` and ``expires_at`` are not required, they always have to be passed to the API.
You can set them to empty strings, see: https://gitlab.com/gitlab-org/gitlab/-/issues/211878.
Also, the ``username``'s value is ignored by the API and will be overriden with ``gitlab+deploy-token-{n}``,
see: https://gitlab.com/gitlab-org/gitlab/-/issues/211963
These issues were fixed in GitLab 12.10.

Remove a deploy token from the group::

deploy_token.delete()
# or
group.deploytokens.delete(deploy_token.id)

1 change: 1 addition & 0 deletions gitlab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ def __init__(

self.broadcastmessages = objects.BroadcastMessageManager(self)
self.deploykeys = objects.DeployKeyManager(self)
self.deploytokens = objects.DeployTokenManager(self)
self.geonodes = objects.GeoNodeManager(self)
self.gitlabciymls = objects.GitlabciymlManager(self)
self.gitignores = objects.GitignoreManager(self)
Expand Down
34 changes: 34 additions & 0 deletions gitlab/tests/test_gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,40 @@ def resp_application_create(url, request):
self.assertEqual(application.redirect_uri, "http://localhost:8080")
self.assertEqual(application.scopes, ["api", "email"])

def test_deploy_tokens(self):
@urlmatch(
scheme="http",
netloc="localhost",
path="/api/v4/projects/1/deploy_tokens",
method="post",
)
def resp_deploy_token_create(url, request):
headers = {"content-type": "application/json"}
content = """{
"id": 1,
"name": "test_deploy_token",
"username": "custom-user",
"expires_at": "2022-01-01T00:00:00.000Z",
"token": "jMRvtPNxrn3crTAGukpZ",
"scopes": [ "read_repository" ]}"""
content = content.encode("utf-8")
return response(200, content, headers, None, 5, request)

with HTTMock(resp_deploy_token_create):
deploy_token = self.gl.projects.get(1, lazy=True).deploytokens.create(
{
"name": "test_deploy_token",
"expires_at": "2022-01-01T00:00:00.000Z",
"username": "custom-user",
"scopes": ["read_repository"],
}
)
self.assertIsInstance(deploy_token, ProjectDeployToken)
self.assertEqual(deploy_token.id, 1),
self.assertEqual(deploy_token.expires_at, "2022-01-01T00:00:00.000Z"),
self.assertEqual(deploy_token.username, "custom-user")
self.assertEqual(deploy_token.scopes, ["read_repository"])

def _default_config(self):
fd, temp_path = tempfile.mkstemp()
os.write(fd, valid_config)
Expand Down
39 changes: 39 additions & 0 deletions gitlab/v4/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,43 @@ class DeployKeyManager(ListMixin, RESTManager):
_obj_cls = DeployKey


class DeployToken(ObjectDeleteMixin, RESTObject):
pass


class DeployTokenManager(ListMixin, RESTManager):
_path = "/deploy_tokens"
_obj_cls = DeployToken


class ProjectDeployToken(ObjectDeleteMixin, RESTObject):
pass


class ProjectDeployTokenManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
_path = "/projects/%(project_id)s/deploy_tokens"
_from_parent_attrs = {"project_id": "id"}
_obj_cls = ProjectDeployToken
_create_attrs = (
("name", "scopes",),
("expires_at", "username",),
)


class GroupDeployToken(ObjectDeleteMixin, RESTObject):
pass


class GroupDeployTokenManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
_path = "/groups/%(group_id)s/deploy_tokens"
_from_parent_attrs = {"group_id": "id"}
_obj_cls = GroupDeployToken
_create_attrs = (
("name", "scopes",),
("expires_at", "username",),
)


class NotificationSettings(SaveMixin, RESTObject):
_id_attr = None

Expand Down Expand Up @@ -1301,6 +1338,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
("subgroups", "GroupSubgroupManager"),
("variables", "GroupVariableManager"),
("clusters", "GroupClusterManager"),
("deploytokens", "GroupDeployTokenManager"),
)

@cli.register_custom_action("Group", ("to_project_id",))
Expand Down Expand Up @@ -4212,6 +4250,7 @@ class Project(SaveMixin, ObjectDeleteMixin, RESTObject):
("clusters", "ProjectClusterManager"),
("additionalstatistics", "ProjectAdditionalStatisticsManager"),
("issuesstatistics", "ProjectIssuesStatisticsManager"),
("deploytokens", "ProjectDeployTokenManager"),
)

@cli.register_custom_action("Project", ("submodule", "branch", "commit_sha"))
Expand Down
88 changes: 80 additions & 8 deletions tools/cli_test_v4.sh
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,6 @@ testcase "project upload" '
--filename '$(basename $0)' --filepath '$0' >/dev/null 2>&1
'

testcase "project deletion" '
GITLAB project delete --id "$PROJECT_ID"
'

testcase "group deletion" '
OUTPUT=$(try GITLAB group delete --id $GROUP_ID)
'

testcase "application settings get" '
GITLAB application-settings get >/dev/null 2>&1
'
Expand All @@ -222,3 +214,83 @@ testcase "values from files" '
echo $OUTPUT | grep -q "Multi line"
'

# Test deploy tokens
CREATE_PROJECT_DEPLOY_TOKEN_OUTPUT=$(GITLAB -v project-deploy-token create --project-id $PROJECT_ID \
--name foo --username root --expires-at "2021-09-09" --scopes "read_registry")
CREATED_DEPLOY_TOKEN_ID=$(echo "$CREATE_PROJECT_DEPLOY_TOKEN_OUTPUT" | grep ^id: | cut -d" " -f2)
testcase "create project deploy token" '
echo $CREATE_PROJECT_DEPLOY_TOKEN_OUTPUT | grep -q "name: foo"
'
testcase "create project deploy token" '
echo $CREATE_PROJECT_DEPLOY_TOKEN_OUTPUT | grep -q "expires-at: 2021-09-09T00:00:00.000Z"
'
testcase "create project deploy token" '
echo $CREATE_PROJECT_DEPLOY_TOKEN_OUTPUT | grep "scopes: " | grep -q "read_registry"
'
# Uncomment once https://gitlab.com/gitlab-org/gitlab/-/issues/211963 is fixed
#testcase "create project deploy token" '
# echo $CREATE_PROJECT_DEPLOY_TOKEN_OUTPUT | grep -q "username: root"
#'

# Remove once https://gitlab.com/gitlab-org/gitlab/-/issues/211963 is fixed
testcase "create project deploy token" '
echo $CREATE_PROJECT_DEPLOY_TOKEN_OUTPUT | grep -q "gitlab+deploy-token"
'

LIST_DEPLOY_TOKEN_OUTPUT=$(GITLAB -v deploy-token list)
testcase "list all deploy tokens" '
echo $LIST_DEPLOY_TOKEN_OUTPUT | grep -q "name: foo"
'
testcase "list all deploy tokens" '
echo $LIST_DEPLOY_TOKEN_OUTPUT | grep -q "id: $CREATED_DEPLOY_TOKEN_ID"
'
testcase "list all deploy tokens" '
echo $LIST_DEPLOY_TOKEN_OUTPUT | grep -q "expires-at: 2021-09-09T00:00:00.000Z"
'
testcase "list all deploy tokens" '
echo $LIST_DEPLOY_TOKEN_OUTPUT | grep "scopes: " | grep -q "read_registry"
'

testcase "list project deploy tokens" '
OUTPUT=$(GITLAB -v project-deploy-token list --project-id $PROJECT_ID)
echo $OUTPUT | grep -q "id: $CREATED_DEPLOY_TOKEN_ID"
'
testcase "delete project deploy token" '
GITLAB -v project-deploy-token delete --project-id $PROJECT_ID --id $CREATED_DEPLOY_TOKEN_ID
LIST_PROJECT_DEPLOY_TOKEN_OUTPUT=$(GITLAB -v project-deploy-token list --project-id $PROJECT_ID)
echo $LIST_PROJECT_DEPLOY_TOKEN_OUTPUT | grep -qv "id: $CREATED_DEPLOY_TOKEN_ID"
'
# Uncomment once https://gitlab.com/gitlab-org/gitlab/-/issues/212523 is fixed
#testcase "delete project deploy token" '
# LIST_DEPLOY_TOKEN_OUTPUT=$(GITLAB -v deploy-token list)
# echo $LIST_DEPLOY_TOKEN_OUTPUT | grep -qv "id: $CREATED_DEPLOY_TOKEN_ID"
#'

CREATE_GROUP_DEPLOY_TOKEN_OUTPUT=$(GITLAB -v group-deploy-token create --group-id $GROUP_ID \
--name bar --username root --expires-at "2021-09-09" --scopes "read_repository")
CREATED_DEPLOY_TOKEN_ID=$(echo "$CREATE_GROUP_DEPLOY_TOKEN_OUTPUT" | grep ^id: | cut -d" " -f2)
testcase "create group deploy token" '
echo $CREATE_GROUP_DEPLOY_TOKEN_OUTPUT | grep -q "name: bar"
'
testcase "list group deploy tokens" '
OUTPUT=$(GITLAB -v group-deploy-token list --group-id $GROUP_ID)
echo $OUTPUT | grep -q "id: $CREATED_DEPLOY_TOKEN_ID"
'
testcase "delete group deploy token" '
GITLAB -v group-deploy-token delete --group-id $GROUP_ID --id $CREATED_DEPLOY_TOKEN_ID
LIST_GROUP_DEPLOY_TOKEN_OUTPUT=$(GITLAB -v group-deploy-token list --group-id $GROUP_ID)
echo $LIST_GROUP_DEPLOY_TOKEN_OUTPUT | grep -qv "id: $CREATED_DEPLOY_TOKEN_ID"
'
# Uncomment once https://gitlab.com/gitlab-org/gitlab/-/issues/212523 is fixed
#testcase "delete group deploy token" '
# LIST_DEPLOY_TOKEN_OUTPUT=$(GITLAB -v deploy-token list)
# echo $LIST_DEPLOY_TOKEN_OUTPUT | grep -qv "id: $CREATED_DEPLOY_TOKEN_ID"
#'

testcase "project deletion" '
GITLAB project delete --id "$PROJECT_ID"
'

testcase "group deletion" '
OUTPUT=$(try GITLAB group delete --id $GROUP_ID)
'
Loading