Skip to content
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

New registration flow #198

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
12 changes: 6 additions & 6 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
* [`Gitlab_ci_runner::Keyserver`](#Gitlab_ci_runner--Keyserver): Type to match repo_keyserver Regex from: https://github.com/puppetlabs/puppetlabs-apt/blob/main/manifests/key.pp
* [`Gitlab_ci_runner::Log_format`](#Gitlab_ci_runner--Log_format): Gitlab Runner log format configuration
* [`Gitlab_ci_runner::Log_level`](#Gitlab_ci_runner--Log_level): Gitlab Runner log level configuration
* [`Gitlab_ci_runner::Register`](#Gitlab_ci_runner--Register): A struct of all possible additionl options for gitlab_ci_runner::register
* [`Gitlab_ci_runner::Register`](#Gitlab_ci_runner--Register): A struct of all possible additional options for gitlab_ci_runner::register
* [`Gitlab_ci_runner::Register_parameters`](#Gitlab_ci_runner--Register_parameters): A enum containing a possible keys used for Gitlab runner registrations
* [`Gitlab_ci_runner::Session_server`](#Gitlab_ci_runner--Session_server): Gitlab Runner session_server configuration

Expand Down Expand Up @@ -503,7 +503,7 @@ puppet apply -e "notice(gitlab_ci_runner::register('https://gitlab.com', 'regist

A function that registers a Gitlab runner on a Gitlab instance. Be careful, this will be triggered on noop runs as well!

Returns: `Struct[{ id => Integer[1], token => String[1], }]` Returns a hash with the runner id and authentcation token
Returns: `Struct[{ id => Integer[1], token => String[1], }]` Returns a hash with the runner id and authentication token

##### Examples

Expand Down Expand Up @@ -673,7 +673,7 @@ puppet apply -e "notice(gitlab_ci_runner::unregister('https://gitlab.com', 'runn

A function that unregisters a Gitlab runner from a Gitlab instance. Be careful, this will be triggered on noop runs as well!

Returns: `Struct[{ status => Enum['success'], }]` Returns a hash with the runner id and authentcation token
Returns: `Struct[{ status => Enum['success'], }]` Returns status

##### Examples

Expand Down Expand Up @@ -724,7 +724,7 @@ file { '/etc/gitlab-runner/auth-token-testrunner':
A function that unregisters a Gitlab runner from a Gitlab instance, if the local token is there.
This is meant to be used in conjunction with the gitlab_ci_runner::register_to_file function.

Returns: `Any`
Returns: `String` Returns status

##### Examples

Expand All @@ -747,7 +747,7 @@ The url to your Gitlab instance. Please only provide the host part (e.g https://

Data type: `String[1]`

The name of the runner. Use as identifier for the retrived auth token.
The name of the runner. Use as identifier for the retrieved auth token.

##### `proxy`

Expand Down Expand Up @@ -784,7 +784,7 @@ Alias of `Enum['debug', 'info', 'warn', 'error', 'fatal', 'panic']`

### <a name="Gitlab_ci_runner--Register"></a>`Gitlab_ci_runner::Register`

A struct of all possible additionl options for gitlab_ci_runner::register
A struct of all possible additional options for gitlab_ci_runner::register

Alias of

Expand Down
8 changes: 6 additions & 2 deletions lib/puppet/functions/gitlab_ci_runner/register.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# @param token Registration token.
# @param additional_options A hash with all additional configuration options for that runner
# @param ca_file An absolute path to a trusted certificate authority file.
# @return [Struct[{ id => Integer[1], token => String[1], }]] Returns a hash with the runner id and authentcation token
# @return [Struct[{ id => Integer[1], token => String[1], }]] Returns a hash with the runner id and authentication token
# @example Using it as a replacement for the Bolt 'register_runner' task
# puppet apply -e "notice(gitlab_ci_runner::register('https://gitlab.com', 'registration-token'))"
#
Expand All @@ -21,7 +21,11 @@
end

def register(url, token, additional_options = {}, ca_file = nil)
PuppetX::Gitlab::Runner.register(url, additional_options.merge('token' => token), ca_file: ca_file)
if token.start_with?('glrt-')
PuppetX::Gitlab::Runner.verify(url, token, ca_file: ca_file)
else
PuppetX::Gitlab::Runner.register(url, additional_options.merge('registration-token' => token), ca_file: ca_file)
end
rescue Net::HTTPError => e
raise "Gitlab runner failed to register: #{e.message}"
end
Expand Down
8 changes: 7 additions & 1 deletion lib/puppet/functions/gitlab_ci_runner/register_to_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ def register_to_file(url, regtoken, runner_name, additional_options = {}, proxy
# will be returned unmodified.
regtoken = call_function('unwrap', regtoken)

authtoken = PuppetX::Gitlab::Runner.register(url, additional_options.merge('token' => regtoken), proxy, ca_file)['token']
# Combine options based on the token
if regtoken.start_with?('glrt-')
PuppetX::Gitlab::Runner.verify(url, regtoken, proxy, ca_file)
authtoken = regtoken
else
authtoken = PuppetX::Gitlab::Runner.register(url, additional_options.merge('registration-token' => regtoken), proxy, ca_file)['token']
end

# If this function is used as a Deferred function the Gitlab Runner config dir
# will not exist on the first run, because the package isn't installed yet.
Expand Down
2 changes: 1 addition & 1 deletion lib/puppet/functions/gitlab_ci_runner/unregister.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# @param url The url to your Gitlab instance. Please only provide the host part (e.g https://gitlab.com)
# @param token Runners authentication token.
# @param ca_file An absolute path to a trusted certificate authority file.
# @return [Struct[{ id => Integer[1], token => String[1], }]] Returns a hash with the runner id and authentcation token
# @return [Struct[{ status => String[1], }]] Returns status
# @example Using it as a replacement for the Bolt 'unregister_runner' task
# puppet apply -e "notice(gitlab_ci_runner::unregister('https://gitlab.com', 'runner-auth-token'))"
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
# This is meant to be used in conjunction with the gitlab_ci_runner::register_to_file function.
Puppet::Functions.create_function(:'gitlab_ci_runner::unregister_from_file') do
# @param url The url to your Gitlab instance. Please only provide the host part (e.g https://gitlab.com)
# @param runner_name The name of the runner. Use as identifier for the retrived auth token.
# @param runner_name The name of the runner. Use as identifier for the retrieved auth token.
# @param proxy HTTP proxy to use when unregistering
# @param ca_file An absolute path to a trusted certificate authority file.
# @return [String] Returns status
# @example Using it as a Deferred function with a file resource
# file { '/etc/gitlab-runner/auth-token-testrunner':
# file => absent,
Expand Down
6 changes: 6 additions & 0 deletions lib/puppet_x/gitlab/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ def self.register(host, options, proxy = nil, ca_file = nil)
PuppetX::Gitlab::APIClient.post(url, options, proxy, ca_file)
end

def self.verify(host, token, proxy = nil, ca_file = nil)
url = "#{host}/api/v4/runners/verify"
Puppet.info "Verifying gitlab runner with #{host}"
PuppetX::Gitlab::APIClient.post(url, { 'token' => token }, proxy, ca_file)
end

def self.unregister(host, options, proxy = nil, ca_file = nil)
url = "#{host}/api/v4/runners"
Puppet.info "Unregistering gitlab runner with #{host}"
Expand Down
6 changes: 4 additions & 2 deletions manifests/runner.pp
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@
default => $config,
}

if $_config['registration-token'] {
if $_config['registration-token'] or $_config['token'] {
$register_additional_options = $config
.filter |$item| { $item[0] =~ Gitlab_ci_runner::Register_parameters } # Get all items use for the registration process
.reduce({}) |$memo, $item| { $memo + { regsubst($item[0], '-', '_', 'G') => $item[1] } } # Ensure all keys use '_' instead of '-'

$deferred_call = Deferred('gitlab_ci_runner::register_to_file', [$_config['url'], $_config['registration-token'], $_config['name'], $register_additional_options, $http_proxy, $ca_file])
$token = pick($_config['token'], $_config['registration-token'])

$deferred_call = Deferred('gitlab_ci_runner::register_to_file', [$_config['url'], $token, $_config['name'], $register_additional_options, $http_proxy, $ca_file])

# Remove registration-token and add a 'token' key to the config with a Deferred function to get it.
$__config = ($_config - (Array(Gitlab_ci_runner::Register_parameters) + 'registration-token')) + { 'token' => $deferred_call }
Expand Down
5 changes: 3 additions & 2 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{

Check warning on line 1 in metadata.json

View workflow job for this annotation

GitHub Actions / Setup Test Matrix

Skipping EOL operating system CentOS 8
"name": "puppet-gitlab_ci_runner",
"version": "5.1.1-rc0",
"version": "5.2.0-rc0",
"author": "Vox Pupuli",
"summary": "Installation and configuration of Gitlab CI Runner",
"license": "Apache-2.0",
Expand Down Expand Up @@ -64,7 +64,8 @@
{
"operatingsystem": "Debian",
"operatingsystemrelease": [
"11"
"11",
"12"
]
},
{
Expand Down
28 changes: 20 additions & 8 deletions spec/functions/register_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
describe 'gitlab_ci_runner::register' do
let(:url) { 'https://gitlab.example.org' }
let(:regtoken) { 'registration-token' }
let(:auth_token) { 'glrt-authentication-token' }
let(:return_hash) do
{
'id' => 1234,
Expand All @@ -20,17 +21,28 @@
it { is_expected.to run.with_params('https://gitlab.com', 1234).and_raise_error(ArgumentError) }
it { is_expected.to run.with_params('https://gitlab.com', 'registration-token', project: 1234).and_raise_error(ArgumentError) }

it "calls 'PuppetX::Gitlab::Runner.register'" do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'token' => regtoken }, ca_file: nil).and_return(return_hash)
context 'with registration token' do
it "calls 'PuppetX::Gitlab::Runner.register'" do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'registration-token' => regtoken }, ca_file: nil).and_return(return_hash)

is_expected.to run.with_params(url, regtoken).and_return(return_hash)
expect(PuppetX::Gitlab::Runner).to have_received(:register)
is_expected.to run.with_params(url, regtoken).and_return(return_hash)
expect(PuppetX::Gitlab::Runner).to have_received(:register)
end

it "passes additional args to 'PuppetX::Gitlab::Runner.register'" do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'registration-token' => regtoken, 'active' => false }, ca_file: nil).and_return(return_hash)

is_expected.to run.with_params(url, regtoken, 'active' => false).and_return(return_hash)
expect(PuppetX::Gitlab::Runner).to have_received(:register)
end
end

it "passes additional args to 'PuppetX::Gitlab::Runner.register'" do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'token' => regtoken, 'active' => false }, ca_file: nil).and_return(return_hash)
context 'with authentication token' do
it "calls 'PuppetX::Gitlab::Runner.verify'" do
allow(PuppetX::Gitlab::Runner).to receive(:verify).with(url, auth_token, ca_file: nil).and_return(return_hash)

is_expected.to run.with_params(url, regtoken, 'active' => false).and_return(return_hash)
expect(PuppetX::Gitlab::Runner).to have_received(:register)
is_expected.to run.with_params(url, auth_token).and_return(return_hash)
expect(PuppetX::Gitlab::Runner).to have_received(:verify)
end
end
end
83 changes: 64 additions & 19 deletions spec/functions/register_to_file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@

describe 'gitlab_ci_runner::register_to_file' do
let(:url) { 'https://gitlab.example.org' }
let(:regtoken) { 'registration-token' }
let(:token) do
{
reg_token: 'registration-token',
auth_token: 'glrt-authentication-token'
}
end
let(:runner_name) { 'testrunner' }
let(:filename) { "/etc/gitlab-runner/auth-token-#{runner_name}" }
let(:return_hash) do
Expand All @@ -30,42 +35,81 @@
allow(File).to receive(:read).with(filename).and_return(return_hash['token'])
end

it { is_expected.to run.with_params(url, regtoken, runner_name).and_return(return_hash['token']) }
it { is_expected.to run.with_params(url, token[:reg_token], runner_name).and_return(return_hash['token']) }
it { is_expected.to run.with_params(url, token[:auth_token], runner_name).and_return(return_hash['token']) }
end

context "retrieves from Gitlab and writes auth token to file if it doesn't exist" do
context 'retrieves from Gitlab and writes auth token to file if it doesn\'t exist' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'token' => regtoken }, nil, nil).and_return(return_hash)
allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with(File.dirname(filename)).and_return(true)
allow(File).to receive(:write).with(filename, return_hash['token'])
allow(File).to receive(:chmod).with(0o400, filename)
end

it { is_expected.to run.with_params(url, regtoken, runner_name).and_return(return_hash['token']) }

context 'with existing file ca_file option' do
context 'with registration token' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'token' => regtoken }, nil, '/tmp').and_return(return_hash)
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'registration-token' => token[:reg_token] }, nil, nil).and_return(return_hash)
allow(File).to receive(:write).with(filename, return_hash['token'])
end

it { is_expected.to run.with_params(url, regtoken, runner_name, {}, nil, '/tmp').and_return(return_hash['token']) }
end
it { is_expected.to run.with_params(url, token[:reg_token], runner_name).and_return(return_hash['token']) }

context 'with non existent ca_file option' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'token' => regtoken }, nil, '/path/to/ca_file').and_return(return_hash)
context 'with existing file ca_file option' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'registration-token' => token[:reg_token] }, nil, '/tmp').and_return(return_hash)
end

it { is_expected.to run.with_params(url, token[:reg_token], runner_name, {}, nil, '/tmp').and_return(return_hash['token']) }
end

it { is_expected.to run.with_params(url, regtoken, runner_name, {}, nil, '/path/to/ca_file').and_return('Specified CA file doesn\'t exist, not attempting to create authtoken') }
context 'with non existent ca_file option' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'registration-token' => token[:reg_token] }, nil, '/path/to/ca_file').and_return(return_hash)
end

it { is_expected.to run.with_params(url, token[:reg_token], runner_name, {}, nil, '/path/to/ca_file').and_return('Specified CA file doesn\'t exist, not attempting to create authtoken') }
end

context 'with sensitive token value' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'registration-token' => token[:reg_token] }, nil, '/tmp').and_return(return_hash)
end

it { is_expected.to run.with_params(url, sensitive(token[:reg_token]), runner_name, {}, nil, '/tmp').and_return(return_hash['token']) }
end
end

context 'with sensitive token value' do
context 'with authentication token' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:register).with(url, { 'token' => regtoken }, nil, '/tmp').and_return(return_hash)
allow(PuppetX::Gitlab::Runner).to receive(:verify).with(url, token[:auth_token], nil, nil).and_return(return_hash.merge('token' => token[:auth_token]))
allow(File).to receive(:write).with(filename, token[:auth_token])
end

it { is_expected.to run.with_params(url, token[:auth_token], runner_name).and_return(token[:auth_token]) }

context 'with existing file ca_file option' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:verify).with(url, token[:auth_token], nil, '/tmp').and_return(return_hash.merge('token' => token[:auth_token]))
end

it { is_expected.to run.with_params(url, token[:auth_token], runner_name, {}, nil, '/tmp').and_return(token[:auth_token]) }
end

it { is_expected.to run.with_params(url, sensitive(regtoken), runner_name, {}, nil, '/tmp').and_return(return_hash['token']) }
context 'with non existent ca_file option' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:verify).with(url, token[:auth_token], nil, '/path/to/ca_file').and_return(return_hash.merge('token' => token[:auth_token]))
end

it { is_expected.to run.with_params(url, token[:auth_token], runner_name, {}, nil, '/path/to/ca_file').and_return('Specified CA file doesn\'t exist, not attempting to create authtoken') }
end

context 'with sensitive token value' do
before do
allow(PuppetX::Gitlab::Runner).to receive(:verify).with(url, token[:auth_token], nil, '/tmp').and_return(return_hash.merge('token' => token[:auth_token]))
end

it { is_expected.to run.with_params(url, sensitive(token[:auth_token]), runner_name, {}, nil, '/tmp').and_return(token[:auth_token]) }
end
end
end

Expand All @@ -75,6 +119,7 @@
allow(Puppet.settings).to receive(:[]).with(:noop).and_return(true)
end

it { is_expected.to run.with_params(url, regtoken, runner_name).and_return('DUMMY-NOOP-TOKEN') }
it { is_expected.to run.with_params(url, token[:reg_token], runner_name).and_return('DUMMY-NOOP-TOKEN') }
it { is_expected.to run.with_params(url, token[:auth_token], runner_name).and_return('DUMMY-NOOP-TOKEN') }
end
end
23 changes: 19 additions & 4 deletions spec/unit/puppet_x/gitlab/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,26 +94,41 @@ module PuppetX::Gitlab
before do
PuppetX::Gitlab::APIClient.
stub(:post).
with('https://gitlab.example.org/api/v4/runners', { token: 'registrationtoken' }, nil, nil).
with('https://gitlab.example.org/api/v4/runners', { 'registration-token' => 'registrationtoken' }, nil, nil).
and_return('id' => 1234, 'token' => '1234567890abcd')
end

let(:response) { described_class.register('https://gitlab.example.org', { token: 'registrationtoken' }, nil, nil) }
let(:response) { described_class.register('https://gitlab.example.org', { 'registration-token' => 'registrationtoken' }, nil, nil) }

it 'returns a token' do
expect(response['token']).to eq('1234567890abcd')
end
end

describe 'self.verify' do
before do
PuppetX::Gitlab::APIClient.
stub(:post).
with('https://gitlab.example.org/api/v4/runners/verify', { 'token' => 'glrt-authentication-token' }, nil, nil).
and_return('id' => 1234, 'token' => 'glrt-authentication-token')
end

let(:response) { described_class.verify('https://gitlab.example.org', 'glrt-authentication-token', nil, nil) }

it 'returns the authentication token' do
expect(response['token']).to eq('glrt-authentication-token')
end
end

describe 'self.unregister' do
before do
PuppetX::Gitlab::APIClient.
stub(:delete).
with('https://gitlab.example.org/api/v4/runners', { token: '1234567890abcd' }, nil, nil).
with('https://gitlab.example.org/api/v4/runners', { 'token' => '1234567890abcd' }, nil, nil).
and_return({})
end

let(:response) { described_class.unregister('https://gitlab.example.org', { token: '1234567890abcd' }, nil, nil) }
let(:response) { described_class.unregister('https://gitlab.example.org', { 'token' => '1234567890abcd' }, nil, nil) }

it 'returns an empty hash' do
expect(response).to eq({})
Expand Down
2 changes: 1 addition & 1 deletion types/register.pp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @summary A struct of all possible additionl options for gitlab_ci_runner::register
# @summary A struct of all possible additional options for gitlab_ci_runner::register
type Gitlab_ci_runner::Register = Struct[{
Optional[description] => String[1],
Optional[info] => Hash[String[1],String[1]],
Expand Down
Loading