Skip to content

Commit 437d4a2

Browse files
Allow setting a gitlab user and webhook secrets
1 parent 0c8e357 commit 437d4a2

File tree

11 files changed

+606
-1
lines changed

11 files changed

+606
-1
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<%#-- copyright
2+
OpenProject is an open source project management software.
3+
Copyright (C) the OpenProject GmbH
4+
5+
This program is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU General Public License version 3.
7+
8+
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
9+
Copyright (C) 2006-2013 Jean-Philippe Lang
10+
Copyright (C) 2010-2013 the ChiliProject Team
11+
12+
This program is free software; you can redistribute it and/or
13+
modify it under the terms of the GNU General Public License
14+
as published by the Free Software Foundation; either version 2
15+
of the License, or (at your option) any later version.
16+
17+
This program is distributed in the hope that it will be useful,
18+
but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
GNU General Public License for more details.
21+
22+
You should have received a copy of the GNU General Public License
23+
along with this program; if not, write to the Free Software
24+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+
26+
See COPYRIGHT and LICENSE files for more details.
27+
28+
++#%>
29+
30+
<%=
31+
render(Primer::OpenProject::PageHeader.new) do |header|
32+
header.with_title { t(:label_gitlab_integration) }
33+
header.with_breadcrumbs(breadcrumb_items)
34+
end
35+
%>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#-- copyright
2+
# OpenProject is an open source project management software.
3+
# Copyright (C) the OpenProject GmbH
4+
#
5+
# This program is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU General Public License version 3.
7+
#
8+
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
9+
# Copyright (C) 2006-2013 Jean-Philippe Lang
10+
# Copyright (C) 2010-2013 the ChiliProject Team
11+
#
12+
# This program is free software; you can redistribute it and/or
13+
# modify it under the terms of the GNU General Public License
14+
# as published by the Free Software Foundation; either version 2
15+
# of the License, or (at your option) any later version.
16+
#
17+
# This program is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with this program; if not, write to the Free Software
24+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+
#
26+
# See COPYRIGHT and LICENSE files for more details.
27+
#++
28+
29+
module GitlabIntegration
30+
module Admin
31+
class PageHeaderComponent < ApplicationComponent
32+
def breadcrumb_items
33+
[
34+
{ href: admin_index_path, text: t("label_administration") },
35+
t(:label_gitlab_integration)
36+
]
37+
end
38+
end
39+
end
40+
end
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#-- copyright
2+
# OpenProject is an open source project management software.
3+
# Copyright (C) the OpenProject GmbH
4+
#
5+
# This program is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU General Public License version 3.
7+
#
8+
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
9+
# Copyright (C) 2006-2013 Jean-Philippe Lang
10+
# Copyright (C) 2010-2013 the ChiliProject Team
11+
#
12+
# This program is free software; you can redistribute it and/or
13+
# modify it under the terms of the GNU General Public License
14+
# as published by the Free Software Foundation; either version 2
15+
# of the License, or (at your option) any later version.
16+
#
17+
# This program is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with this program; if not, write to the Free Software
24+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+
#
26+
# See COPYRIGHT and LICENSE files for more details.
27+
#++
28+
29+
module GitlabIntegration
30+
module Admin
31+
class SettingsController < ApplicationController
32+
layout "admin"
33+
34+
menu_item :admin_gitlab_integration
35+
36+
before_action :require_admin
37+
38+
def show
39+
settings = plugin_settings
40+
user_id = settings[:gitlab_user_id].presence
41+
@gitlab_comment_user = user_id ? User.find_by(id: user_id) : nil
42+
@webhook_secret = settings[:webhook_secret]
43+
end
44+
45+
def update
46+
merged = plugin_settings.merge(permitted_params)
47+
Setting.plugin_openproject_gitlab_integration = merged
48+
flash[:notice] = I18n.t(:notice_successful_update)
49+
redirect_to gitlab_integration_admin_settings_path
50+
end
51+
52+
private
53+
54+
def permitted_params
55+
params.permit(:gitlab_user_id, :webhook_secret).to_h
56+
end
57+
58+
def plugin_settings
59+
Hash(Setting.plugin_openproject_gitlab_integration).with_indifferent_access
60+
end
61+
end
62+
end
63+
end
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#-- copyright
2+
# OpenProject is an open source project management software.
3+
# Copyright (C) the OpenProject GmbH
4+
#
5+
# This program is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU General Public License version 3.
7+
#
8+
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
9+
# Copyright (C) 2006-2013 Jean-Philippe Lang
10+
# Copyright (C) 2010-2013 the ChiliProject Team
11+
#
12+
# This program is free software; you can redistribute it and/or
13+
# modify it under the terms of the GNU General Public License
14+
# as published by the Free Software Foundation; either version 2
15+
# of the License, or (at your option) any later version.
16+
#
17+
# This program is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with this program; if not, write to the Free Software
24+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+
#
26+
# See COPYRIGHT and LICENSE files for more details.
27+
#++
28+
29+
module GitlabIntegration
30+
module Admin
31+
class SettingsForm < ApplicationForm
32+
form do |f|
33+
f.autocompleter(
34+
name: :gitlab_user_id,
35+
label: I18n.t(:label_gitlab_actor),
36+
caption: I18n.t(:text_gitlab_actor_info),
37+
autocomplete_options: {
38+
component: "opce-user-autocompleter",
39+
allowEmpty: true,
40+
defaultData: false,
41+
model: @comment_user_model
42+
}
43+
)
44+
45+
f.text_field(
46+
name: :webhook_secret,
47+
label: I18n.t(:label_gitlab_webhook_secret),
48+
caption: I18n.t(:text_gitlab_webhook_secret_info),
49+
value: @webhook_secret,
50+
input_width: :xxlarge
51+
)
52+
53+
f.submit(
54+
name: :submit,
55+
label: I18n.t(:button_save),
56+
scheme: :primary
57+
)
58+
end
59+
60+
def initialize(comment_user: nil, webhook_secret: nil)
61+
super()
62+
@comment_user_model = comment_user.present? ? { id: comment_user.id, name: comment_user.name } : nil
63+
@webhook_secret = webhook_secret
64+
end
65+
end
66+
end
67+
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<%#-- copyright
2+
OpenProject is an open source project management software.
3+
Copyright (C) the OpenProject GmbH
4+
5+
This program is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU General Public License version 3.
7+
8+
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
9+
Copyright (C) 2006-2013 Jean-Philippe Lang
10+
Copyright (C) 2010-2013 the ChiliProject Team
11+
12+
This program is free software; you can redistribute it and/or
13+
modify it under the terms of the GNU General Public License
14+
as published by the Free Software Foundation; either version 2
15+
of the License, or (at your option) any later version.
16+
17+
This program is distributed in the hope that it will be useful,
18+
but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
GNU General Public License for more details.
21+
22+
You should have received a copy of the GNU General Public License
23+
along with this program; if not, write to the Free Software
24+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+
26+
See COPYRIGHT and LICENSE files for more details.
27+
28+
++#%>
29+
<% html_title t(:label_administration), t(:label_gitlab_integration), t(:label_setting_plural) %>
30+
31+
<%= render(GitlabIntegration::Admin::PageHeaderComponent.new) %>
32+
33+
<%= settings_primer_form_with(url: gitlab_integration_admin_settings_path, method: :patch) do |f| %>
34+
<% if @webhook_secret.blank? %>
35+
<%= render(Primer::Alpha::Banner.new(scheme: :warning, icon: :alert, mb: 4)) do %>
36+
<%= t(:text_gitlab_webhook_secret_missing_warning) %>
37+
<% end %>
38+
<% end %>
39+
<%= render GitlabIntegration::Admin::SettingsForm.new(f,
40+
comment_user: @gitlab_comment_user,
41+
webhook_secret: @webhook_secret) %>
42+
<% end %>

modules/gitlab_integration/config/locales/en.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ en:
5656
labels:
5757
invalid_schema: "must be an array of hashes with keys: color, title"
5858

59+
label_gitlab_integration: "GitLab Integration"
60+
label_gitlab_actor: "GitLab actor"
61+
label_gitlab_webhook_secret: "Webhook secret"
62+
text_gitlab_actor_info: >
63+
The OpenProject user whose API key must be used to authenticate incoming webhook requests.
64+
When set, requests authenticated with any other user's credentials are rejected.
65+
This user also posts automated comments on work packages. Defaults to the system user when not set.
66+
text_gitlab_webhook_secret_info: >
67+
A secret token shared with GitLab when configuring the webhook.
68+
When set, OpenProject verifies the X-Gitlab-Token header on every incoming request,
69+
rejecting payloads that do not match. Leave blank to skip verification (not recommended).
70+
text_gitlab_webhook_secret_missing_warning: >
71+
No webhook secret is configured. Any request to the GitLab webhook endpoint will be accepted
72+
without verification, which may allow unauthorized actors to forge events. It is strongly
73+
recommended to set a secret.
74+
5975
project_module_gitlab: "GitLab"
6076
permission_show_gitlab_content: "Show GitLab content"
6177

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#-- copyright
2+
# OpenProject is an open source project management software.
3+
# Copyright (C) the OpenProject GmbH
4+
#
5+
# This program is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU General Public License version 3.
7+
#
8+
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
9+
# Copyright (C) 2006-2013 Jean-Philippe Lang
10+
# Copyright (C) 2010-2013 the ChiliProject Team
11+
#
12+
# This program is free software; you can redistribute it and/or
13+
# modify it under the terms of the GNU General Public License
14+
# as published by the Free Software Foundation; either version 2
15+
# of the License, or (at your option) any later version.
16+
#
17+
# This program is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with this program; if not, write to the Free Software
24+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25+
#
26+
# See COPYRIGHT and LICENSE files for more details.
27+
#++
28+
29+
Rails.application.routes.draw do
30+
namespace "gitlab_integration" do
31+
namespace "admin" do
32+
resource :settings, only: %i[show update]
33+
end
34+
end
35+
end

modules/gitlab_integration/lib/open_project/gitlab_integration/engine.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,27 @@ class Engine < ::Rails::Engine
4040

4141
include OpenProject::Plugins::ActsAsOpEngine
4242

43+
def self.settings
44+
{
45+
default: {
46+
"gitlab_user_id" => nil,
47+
"webhook_secret" => nil
48+
}
49+
}
50+
end
51+
4352
register "openproject-gitlab_integration",
4453
author_url: "https://github.com/btey/openproject",
45-
bundled: true do
54+
bundled: true,
55+
settings: do
56+
::Redmine::MenuManager.map(:admin_menu) do |menu|
57+
menu.push :admin_gitlab_integration,
58+
{ controller: "/gitlab_integration/admin/settings", action: "show" },
59+
if: ->(_) { User.current.admin? },
60+
caption: :label_gitlab_integration,
61+
icon: :"op-logo-gitlab"
62+
end
63+
4664
project_module(:gitlab, dependencies: :work_package_tracking) do
4765
permission(:show_gitlab_content,
4866
{},

modules/gitlab_integration/lib/open_project/gitlab_integration/hook_handler.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ def process(_hook, request, params, user)
5050
Rails.logger.debug { "Received gitlab webhook #{event_type}" }
5151

5252
return 404 unless KNOWN_EVENTS.include?(event_type)
53+
return 403 unless valid_token?(request)
5354
return 403 if user.blank?
55+
return 403 if configured_user_id.present? && user.id != configured_user_id
5456

5557
payload = params[:payload]
5658
.permit!
@@ -63,5 +65,25 @@ def process(_hook, request, params, user)
6365

6466
200
6567
end
68+
69+
private
70+
71+
def valid_token?(request)
72+
secret = plugin_settings[:webhook_secret].presence
73+
return true if secret.blank?
74+
75+
token_header = request.env["HTTP_X_GITLAB_TOKEN"]
76+
return false if token_header.blank?
77+
78+
ActiveSupport::SecurityUtils.secure_compare(secret, token_header)
79+
end
80+
81+
def configured_user_id
82+
plugin_settings[:gitlab_user_id].presence&.to_i
83+
end
84+
85+
def plugin_settings
86+
Hash(Setting.plugin_openproject_gitlab_integration).with_indifferent_access
87+
end
6688
end
6789
end

0 commit comments

Comments
 (0)