Commit 92cb6d63 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch '44447-expose-deploy-token-to-ci-cd' into 'master'

Expose Deploy Token info as environment variables to CI/CD jobs

Closes #44447

See merge request gitlab-org/gitlab-ce!18414
parents 8a726a08 82d66ac9
...@@ -27,6 +27,7 @@ module Ci ...@@ -27,6 +27,7 @@ module Ci
has_one :metadata, class_name: 'Ci::BuildMetadata' has_one :metadata, class_name: 'Ci::BuildMetadata'
delegate :timeout, to: :metadata, prefix: true, allow_nil: true delegate :timeout, to: :metadata, prefix: true, allow_nil: true
delegate :gitlab_deploy_token, to: :project
## ##
# The "environment" field for builds is a String, and is the unexpanded name! # The "environment" field for builds is a String, and is the unexpanded name!
...@@ -604,6 +605,7 @@ module Ci ...@@ -604,6 +605,7 @@ module Ci
.append(key: 'CI_REGISTRY_USER', value: CI_REGISTRY_USER) .append(key: 'CI_REGISTRY_USER', value: CI_REGISTRY_USER)
.append(key: 'CI_REGISTRY_PASSWORD', value: token, public: false) .append(key: 'CI_REGISTRY_PASSWORD', value: token, public: false)
.append(key: 'CI_REPOSITORY_URL', value: repo_url, public: false) .append(key: 'CI_REPOSITORY_URL', value: repo_url, public: false)
.concat(deploy_token_variables)
end end
end end
...@@ -654,6 +656,15 @@ module Ci ...@@ -654,6 +656,15 @@ module Ci
end end
end end
def deploy_token_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless gitlab_deploy_token
variables.append(key: 'CI_DEPLOY_USER', value: gitlab_deploy_token.name)
variables.append(key: 'CI_DEPLOY_PASSWORD', value: gitlab_deploy_token.token, public: false)
end
end
def environment_url def environment_url
options&.dig(:environment, :url) || persisted_environment&.external_url options&.dig(:environment, :url) || persisted_environment&.external_url
end end
......
...@@ -4,6 +4,7 @@ class DeployToken < ActiveRecord::Base ...@@ -4,6 +4,7 @@ class DeployToken < ActiveRecord::Base
add_authentication_token_field :token add_authentication_token_field :token
AVAILABLE_SCOPES = %i(read_repository read_registry).freeze AVAILABLE_SCOPES = %i(read_repository read_registry).freeze
GITLAB_DEPLOY_TOKEN_NAME = 'gitlab-deploy-token'.freeze
default_value_for(:expires_at) { Forever.date } default_value_for(:expires_at) { Forever.date }
...@@ -17,6 +18,10 @@ class DeployToken < ActiveRecord::Base ...@@ -17,6 +18,10 @@ class DeployToken < ActiveRecord::Base
scope :active, -> { where("revoked = false AND expires_at >= NOW()") } scope :active, -> { where("revoked = false AND expires_at >= NOW()") }
def self.gitlab_deploy_token
active.find_by(name: GITLAB_DEPLOY_TOKEN_NAME)
end
def revoke! def revoke!
update!(revoked: true) update!(revoked: true)
end end
......
...@@ -1879,6 +1879,10 @@ class Project < ActiveRecord::Base ...@@ -1879,6 +1879,10 @@ class Project < ActiveRecord::Base
[] []
end end
def gitlab_deploy_token
@gitlab_deploy_token ||= deploy_tokens.gitlab_deploy_token
end
private private
def storage def storage
......
---
title: Expose Deploy Token data as environment varialbes on CI/CD jobs
merge_request: 18414
author:
type: added
...@@ -260,6 +260,8 @@ are unsupported in environment name context: ...@@ -260,6 +260,8 @@ are unsupported in environment name context:
- `CI_REGISTRY_PASSWORD` - `CI_REGISTRY_PASSWORD`
- `CI_REPOSITORY_URL` - `CI_REPOSITORY_URL`
- `CI_ENVIRONMENT_URL` - `CI_ENVIRONMENT_URL`
- `CI_DEPLOY_USER`
- `CI_DEPLOY_PASSWORD`
GitLab Runner exposes various [environment variables][variables] when a job runs, GitLab Runner exposes various [environment variables][variables] when a job runs,
and as such, you can use them as environment names. Let's add another job in and as such, you can use them as environment names. Let's add another job in
......
...@@ -87,6 +87,8 @@ future GitLab releases.** ...@@ -87,6 +87,8 @@ future GitLab releases.**
| **GITLAB_USER_LOGIN** | 10.0 | all | The login username of the user who started the job | | **GITLAB_USER_LOGIN** | 10.0 | all | The login username of the user who started the job |
| **GITLAB_USER_NAME** | 10.0 | all | The real name of the user who started the job | | **GITLAB_USER_NAME** | 10.0 | all | The real name of the user who started the job |
| **RESTORE_CACHE_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to restore the cache running a job | | **RESTORE_CACHE_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to restore the cache running a job |
| **CI_DEPLOY_USER** | 10.8 | all | Authentication username of the [GitLab Deploy Token][gitlab-deploy-token], only present if the Project has one related.|
| **CI_DEPLOY_PASSWORD** | 10.8 | all | Authentication password of the [GitLab Deploy Token][gitlab-deploy-token], only present if the Project has one related.|
## 9.0 Renaming ## 9.0 Renaming
...@@ -546,6 +548,8 @@ You can find a full list of unsupported variables below: ...@@ -546,6 +548,8 @@ You can find a full list of unsupported variables below:
- `CI_REGISTRY_PASSWORD` - `CI_REGISTRY_PASSWORD`
- `CI_REPOSITORY_URL` - `CI_REPOSITORY_URL`
- `CI_ENVIRONMENT_URL` - `CI_ENVIRONMENT_URL`
- `CI_DEPLOY_USER`
- `CI_DEPLOY_PASSWORD`
These variables are also not supported in a contex of a These variables are also not supported in a contex of a
[dynamic environment name][dynamic-environments]. [dynamic environment name][dynamic-environments].
...@@ -562,3 +566,4 @@ These variables are also not supported in a contex of a ...@@ -562,3 +566,4 @@ These variables are also not supported in a contex of a
[subgroups]: ../../user/group/subgroups/index.md [subgroups]: ../../user/group/subgroups/index.md
[builds-policies]: ../yaml/README.md#only-and-except-complex [builds-policies]: ../yaml/README.md#only-and-except-complex
[dynamic-environments]: ../environments.md#dynamic-environments [dynamic-environments]: ../environments.md#dynamic-environments
[gitlab-deploy-token]: ../../user/project/deploy_tokens/index.md#gitlab-deploy-token
...@@ -71,6 +71,16 @@ docker login registry.example.com -u <username> -p <deploy_token> ...@@ -71,6 +71,16 @@ docker login registry.example.com -u <username> -p <deploy_token>
Just replace `<username>` and `<deploy_token>` with the proper values. Then you can simply Just replace `<username>` and `<deploy_token>` with the proper values. Then you can simply
pull images from your Container Registry. pull images from your Container Registry.
### GitLab Deploy Token
> [Introduced][ce-18414] in GitLab 10.8.
There's a special case when it comes to Deploy Tokens, if a user creates one
named `gitlab-deploy-token`, the name and token of the Deploy Token will be
automatically exposed to the CI/CD jobs as environment variables: `CI_DEPLOY_USER` and
`CI_DEPLOY_PASSWORD`, respectively.
[ce-17894]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17894 [ce-17894]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17894
[ce-11845]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845 [ce-11845]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845
[ce-18414]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18414
[container registry]: ../container_registry.md [container registry]: ../container_registry.md
...@@ -10,5 +10,13 @@ FactoryBot.define do ...@@ -10,5 +10,13 @@ FactoryBot.define do
trait :revoked do trait :revoked do
revoked true revoked true
end end
trait :gitlab_deploy_token do
name DeployToken::GITLAB_DEPLOY_TOKEN_NAME
end
trait :expired do
expires_at { Date.today - 1.month }
end
end end
end end
...@@ -2035,6 +2035,34 @@ describe Ci::Build do ...@@ -2035,6 +2035,34 @@ describe Ci::Build do
expect(build).not_to be_persisted expect(build).not_to be_persisted
end end
end end
context 'for deploy tokens' do
let(:deploy_token) { create(:deploy_token, :gitlab_deploy_token) }
let(:deploy_token_variables) do
[
{ key: 'CI_DEPLOY_USER', value: deploy_token.name, public: true },
{ key: 'CI_DEPLOY_PASSWORD', value: deploy_token.token, public: false }
]
end
context 'when gitlab-deploy-token exists' do
before do
project.deploy_tokens << deploy_token
end
it 'should include deploy token variables' do
is_expected.to include(*deploy_token_variables)
end
end
context 'when gitlab-deploy-token does not exist' do
it 'should not include deploy token variables' do
expect(subject.find { |v| v[:key] == 'CI_DEPLOY_USER'}).to be_nil
expect(subject.find { |v| v[:key] == 'CI_DEPLOY_PASSWORD'}).to be_nil
end
end
end
end end
describe '#scoped_variables' do describe '#scoped_variables' do
...@@ -2083,7 +2111,9 @@ describe Ci::Build do ...@@ -2083,7 +2111,9 @@ describe Ci::Build do
CI_REGISTRY_USER CI_REGISTRY_USER
CI_REGISTRY_PASSWORD CI_REGISTRY_PASSWORD
CI_REPOSITORY_URL CI_REPOSITORY_URL
CI_ENVIRONMENT_URL] CI_ENVIRONMENT_URL
CI_DEPLOY_USER
CI_DEPLOY_PASSWORD]
build.scoped_variables.map { |env| env[:key] }.tap do |names| build.scoped_variables.map { |env| env[:key] }.tap do |names|
expect(names).not_to include(*keys) expect(names).not_to include(*keys)
......
...@@ -142,4 +142,23 @@ describe DeployToken do ...@@ -142,4 +142,23 @@ describe DeployToken do
end end
end end
end end
describe '.gitlab_deploy_token' do
let(:project) { create(:project ) }
subject { project.deploy_tokens.gitlab_deploy_token }
context 'with a gitlab deploy token associated' do
it 'should return the gitlab deploy token' do
deploy_token = create(:deploy_token, :gitlab_deploy_token, projects: [project])
is_expected.to eq(deploy_token)
end
end
context 'with no gitlab deploy token associated' do
it 'should return nil' do
is_expected.to be_nil
end
end
end
end end
...@@ -3585,4 +3585,44 @@ describe Project do ...@@ -3585,4 +3585,44 @@ describe Project do
it { is_expected.not_to be_valid } it { is_expected.not_to be_valid }
end end
end end
describe '#gitlab_deploy_token' do
let(:project) { create(:project) }
subject { project.gitlab_deploy_token }
context 'when there is a gitlab deploy token associated' do
let!(:deploy_token) { create(:deploy_token, :gitlab_deploy_token, projects: [project]) }
it { is_expected.to eq(deploy_token) }
end
context 'when there is no a gitlab deploy token associated' do
it { is_expected.to be_nil }
end
context 'when there is a gitlab deploy token associated but is has been revoked' do
let!(:deploy_token) { create(:deploy_token, :gitlab_deploy_token, :revoked, projects: [project]) }
it { is_expected.to be_nil }
end
context 'when there is a gitlab deploy token associated but it is expired' do
let!(:deploy_token) { create(:deploy_token, :gitlab_deploy_token, :expired, projects: [project]) }
it { is_expected.to be_nil }
end
context 'when there is a deploy token associated with a different name' do
let!(:deploy_token) { create(:deploy_token, projects: [project]) }
it { is_expected.to be_nil }
end
context 'when there is a deploy token associated to a different project' do
let(:project_2) { create(:project) }
let!(:deploy_token) { create(:deploy_token, projects: [project_2]) }
it { is_expected.to be_nil }
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment