Commit b46db7b9 authored by Paul Slaughter's avatar Paul Slaughter

Merge branch 'jhyson/doorkeeper_upgrade' into 'master'

Upgrade Doorkeeper to 4.4.3

See merge request gitlab-org/gitlab!20953
parents 33780dd6 90aa9f5e
...@@ -26,7 +26,7 @@ gem 'marginalia', '~> 1.8.0' ...@@ -26,7 +26,7 @@ gem 'marginalia', '~> 1.8.0'
# Authentication libraries # Authentication libraries
gem 'devise', '~> 4.6' gem 'devise', '~> 4.6'
gem 'doorkeeper', '~> 4.3' gem 'doorkeeper', '~> 4.4.3'
gem 'doorkeeper-openid_connect', '~> 1.5' gem 'doorkeeper-openid_connect', '~> 1.5'
gem 'omniauth', '~> 1.8' gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0' gem 'omniauth-auth0', '~> 2.0.0'
......
...@@ -231,7 +231,7 @@ GEM ...@@ -231,7 +231,7 @@ GEM
docile (1.3.1) docile (1.3.1)
domain_name (0.5.20180417) domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (4.3.2) doorkeeper (4.4.3)
railties (>= 4.2) railties (>= 4.2)
doorkeeper-openid_connect (1.5.0) doorkeeper-openid_connect (1.5.0)
doorkeeper (~> 4.3) doorkeeper (~> 4.3)
...@@ -1180,7 +1180,7 @@ DEPENDENCIES ...@@ -1180,7 +1180,7 @@ DEPENDENCIES
diff_match_patch (~> 0.1.0) diff_match_patch (~> 0.1.0)
diffy (~> 3.1.0) diffy (~> 3.1.0)
discordrb-webhooks-blackst0ne (~> 3.3) discordrb-webhooks-blackst0ne (~> 3.3)
doorkeeper (~> 4.3) doorkeeper (~> 4.4.3)
doorkeeper-openid_connect (~> 1.5) doorkeeper-openid_connect (~> 1.5)
ed25519 (~> 1.2) ed25519 (~> 1.2)
elasticsearch-api (~> 6.8) elasticsearch-api (~> 6.8)
......
...@@ -55,6 +55,8 @@ class Admin::ApplicationsController < Admin::ApplicationController ...@@ -55,6 +55,8 @@ class Admin::ApplicationsController < Admin::ApplicationController
# Only allow a trusted parameter "white list" through. # Only allow a trusted parameter "white list" through.
def application_params def application_params
params.require(:doorkeeper_application).permit(:name, :redirect_uri, :trusted, :scopes) params
.require(:doorkeeper_application)
.permit(:name, :redirect_uri, :trusted, :scopes, :confidential)
end end
end end
...@@ -30,6 +30,14 @@ ...@@ -30,6 +30,14 @@
%span.form-text.text-muted %span.form-text.text-muted
Trusted applications are automatically authorized on GitLab OAuth flow. Trusted applications are automatically authorized on GitLab OAuth flow.
= content_tag :div, class: 'form-group row' do
.col-sm-2.col-form-label.pt-0
= f.label :confidential
.col-sm-10
= f.check_box :confidential
%span.form-text.text-muted
= _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
.form-group.row .form-group.row
.col-sm-2.col-form-label.pt-0 .col-sm-2.col-form-label.pt-0
= f.label :scopes = f.label :scopes
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
%th Callback URL %th Callback URL
%th Clients %th Clients
%th Trusted %th Trusted
%th Confidential
%th %th
%th %th
%tbody.oauth-applications %tbody.oauth-applications
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
%td= application.redirect_uri %td= application.redirect_uri
%td= @application_counts[application.id].to_i %td= @application_counts[application.id].to_i
%td= application.trusted? ? 'Y': 'N' %td= application.trusted? ? 'Y': 'N'
%td= application.confidential? ? 'Y': 'N'
%td= link_to 'Edit', edit_admin_application_path(application), class: 'btn btn-link' %td= link_to 'Edit', edit_admin_application_path(application), class: 'btn btn-link'
%td= render 'delete_form', application: application %td= render 'delete_form', application: application
= paginate @applications, theme: 'gitlab' = paginate @applications, theme: 'gitlab'
...@@ -36,6 +36,12 @@ ...@@ -36,6 +36,12 @@
%td %td
= @application.trusted? ? 'Y' : 'N' = @application.trusted? ? 'Y' : 'N'
%tr
%td
Confidential
%td
= @application.confidential? ? 'Y' : 'N'
= render "shared/tokens/scopes_list", token: @application = render "shared/tokens/scopes_list", token: @application
.form-actions .form-actions
......
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
%span.form-text.text-muted %span.form-text.text-muted
= _('Use <code>%{native_redirect_uri}</code> for local tests').html_safe % { native_redirect_uri: Doorkeeper.configuration.native_redirect_uri } = _('Use <code>%{native_redirect_uri}</code> for local tests').html_safe % { native_redirect_uri: Doorkeeper.configuration.native_redirect_uri }
.form-group.form-check
= f.check_box :confidential, class: 'form-check-input'
= f.label :confidential, class: 'label-bold form-check-label'
%span.form-text.text-muted
= _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
.form-group .form-group
= f.label :scopes, class: 'label-bold' = f.label :scopes, class: 'label-bold'
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes = render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes
......
...@@ -34,6 +34,12 @@ ...@@ -34,6 +34,12 @@
%div %div
%span.monospace= uri %span.monospace= uri
%tr
%td
= _('Confidential')
%td
= @application.confidential? ? _('Yes') : _('No')
= render "shared/tokens/scopes_list", token: @application = render "shared/tokens/scopes_list", token: @application
.form-actions .form-actions
......
---
title: Upgrade Doorkeeper to 4.4.3 to address CVE-2018-1000211
merge_request: 20953
author:
type: security
...@@ -118,8 +118,8 @@ end ...@@ -118,8 +118,8 @@ end
# app created does not match the complete list of scopes of the configured app. # app created does not match the complete list of scopes of the configured app.
# It also prevents the OAuth authorize application window to appear every time. # It also prevents the OAuth authorize application window to appear every time.
# Remove after we upgrade the doorkeeper gem from version 4.3.2 # Remove after we upgrade the doorkeeper gem from version 4.x
if Doorkeeper.gem_version > Gem::Version.new('4.3.2') if Doorkeeper.gem_version > Gem::Version.new('5.0.0')
raise "Doorkeeper was upgraded, please remove the monkey patch in #{__FILE__}" raise "Doorkeeper was upgraded, please remove the monkey patch in #{__FILE__}"
end end
......
# frozen_string_literal: true
class AddConfidentialToDoorkeeperApplication < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default( # rubocop:disable Migration/AddColumnWithDefault
:oauth_applications,
:confidential,
:boolean,
default: false, # assume all existing applications are non-confidential
allow_null: false
)
# set the default to true so that all future applications are confidential by default
change_column_default(:oauth_applications, :confidential, true)
end
def down
remove_column :oauth_applications, :confidential
end
end
...@@ -2853,6 +2853,7 @@ ActiveRecord::Schema.define(version: 2020_01_21_132641) do ...@@ -2853,6 +2853,7 @@ ActiveRecord::Schema.define(version: 2020_01_21_132641) do
t.integer "owner_id" t.integer "owner_id"
t.string "owner_type" t.string "owner_type"
t.boolean "trusted", default: false, null: false t.boolean "trusted", default: false, null: false
t.boolean "confidential", default: true, null: false
t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type" t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type"
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
end end
......
...@@ -23,10 +23,11 @@ POST /applications ...@@ -23,10 +23,11 @@ POST /applications
Parameters: Parameters:
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|:---------------|:-------|:---------|:---------------------------------| |:---------------|:--------|:---------|:---------------------------------|
| `name` | string | yes | Name of the application. | | `name` | string | yes | Name of the application. |
| `redirect_uri` | string | yes | Redirect URI of the application. | | `redirect_uri` | string | yes | Redirect URI of the application. |
| `scopes` | string | yes | Scopes of the application. | | `scopes` | string | yes | Scopes of the application. |
| `confidential` | boolean | no | The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential. Defaults to `true` if not supplied |
Example request: Example request:
...@@ -42,7 +43,8 @@ Example response: ...@@ -42,7 +43,8 @@ Example response:
"application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737", "application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737",
"application_name": "MyApplication", "application_name": "MyApplication",
"secret": "ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34", "secret": "ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34",
"callback_url": "http://redirect.uri" "callback_url": "http://redirect.uri",
"confidential": true
} }
``` ```
...@@ -68,7 +70,8 @@ Example response: ...@@ -68,7 +70,8 @@ Example response:
"id":1, "id":1,
"application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737", "application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737",
"application_name": "MyApplication", "application_name": "MyApplication",
"callback_url": "http://redirect.uri" "callback_url": "http://redirect.uri",
"confidential": true
} }
] ]
``` ```
......
...@@ -14,6 +14,9 @@ module API ...@@ -14,6 +14,9 @@ module API
requires :name, type: String, desc: 'Application name' requires :name, type: String, desc: 'Application name'
requires :redirect_uri, type: String, desc: 'Application redirect URI' requires :redirect_uri, type: String, desc: 'Application redirect URI'
requires :scopes, type: String, desc: 'Application scopes' requires :scopes, type: String, desc: 'Application scopes'
optional :confidential, type: Boolean, default: true,
desc: 'Application will be used where the client secret is confidential'
end end
post do post do
application = Doorkeeper::Application.new(declared_params) application = Doorkeeper::Application.new(declared_params)
......
...@@ -1828,6 +1828,7 @@ module API ...@@ -1828,6 +1828,7 @@ module API
expose :uid, as: :application_id expose :uid, as: :application_id
expose :name, as: :application_name expose :name, as: :application_name
expose :redirect_uri, as: :callback_url expose :redirect_uri, as: :callback_url
expose :confidential
end end
# Use with care, this exposes the secret # Use with care, this exposes the secret
......
...@@ -18420,6 +18420,9 @@ msgstr "" ...@@ -18420,6 +18420,9 @@ msgstr ""
msgid "The amount of seconds after which a request to get a secondary node status will time out." msgid "The amount of seconds after which a request to get a secondary node status will time out."
msgstr "" msgstr ""
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
msgid "The branch for this project has no active pipeline configuration." msgid "The branch for this project has no active pipeline configuration."
msgstr "" msgstr ""
......
...@@ -40,7 +40,7 @@ describe Admin::ApplicationsController do ...@@ -40,7 +40,7 @@ describe Admin::ApplicationsController do
describe 'POST #create' do describe 'POST #create' do
it 'creates the application' do it 'creates the application' do
create_params = attributes_for(:application, trusted: true) create_params = attributes_for(:application, trusted: true, confidential: false)
expect do expect do
post :create, params: { doorkeeper_application: create_params } post :create, params: { doorkeeper_application: create_params }
...@@ -60,16 +60,34 @@ describe Admin::ApplicationsController do ...@@ -60,16 +60,34 @@ describe Admin::ApplicationsController do
expect(response).to render_template :new expect(response).to render_template :new
expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes) expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes)
end end
context 'when the params are for a confidential application' do
it 'creates a confidential application' do
create_params = attributes_for(:application, confidential: true)
expect do
post :create, params: { doorkeeper_application: create_params }
end.to change { Doorkeeper::Application.count }.by(1)
application = Doorkeeper::Application.last
expect(response).to redirect_to(admin_application_path(application))
expect(application).to have_attributes(create_params.except(:uid, :owner_type))
end
end
end end
describe 'PATCH #update' do describe 'PATCH #update' do
it 'updates the application' do it 'updates the application' do
patch :update, params: { id: application.id, doorkeeper_application: { redirect_uri: 'http://example.com/', trusted: true } } doorkeeper_params = { redirect_uri: 'http://example.com/', trusted: true, confidential: false }
patch :update, params: { id: application.id, doorkeeper_application: doorkeeper_params }
application.reload application.reload
expect(response).to redirect_to(admin_application_path(application)) expect(response).to redirect_to(admin_application_path(application))
expect(application).to have_attributes(redirect_uri: 'http://example.com/', trusted: true) expect(application)
.to have_attributes(redirect_uri: 'http://example.com/', trusted: true, confidential: false)
end end
it 'renders the application form on errors' do it 'renders the application form on errors' do
...@@ -78,5 +96,16 @@ describe Admin::ApplicationsController do ...@@ -78,5 +96,16 @@ describe Admin::ApplicationsController do
expect(response).to render_template :edit expect(response).to render_template :edit
expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes) expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes)
end end
context 'when updating the application to be confidential' do
it 'successfully sets the application to confidential' do
doorkeeper_params = { confidential: true }
patch :update, params: { id: application.id, doorkeeper_application: doorkeeper_params }
expect(response).to redirect_to(admin_application_path(application))
expect(application).to be_confidential
end
end
end end
end end
...@@ -21,18 +21,21 @@ RSpec.describe 'admin manage applications' do ...@@ -21,18 +21,21 @@ RSpec.describe 'admin manage applications' do
expect(page).to have_content('Application ID') expect(page).to have_content('Application ID')
expect(page).to have_content('Secret') expect(page).to have_content('Secret')
expect(page).to have_content('Trusted Y') expect(page).to have_content('Trusted Y')
expect(page).to have_content('Confidential Y')
click_on 'Edit' click_on 'Edit'
expect(page).to have_content('Edit application') expect(page).to have_content('Edit application')
fill_in :doorkeeper_application_name, with: 'test_changed' fill_in :doorkeeper_application_name, with: 'test_changed'
uncheck :doorkeeper_application_trusted uncheck :doorkeeper_application_trusted
uncheck :doorkeeper_application_confidential
click_on 'Submit' click_on 'Submit'
expect(page).to have_content('test_changed') expect(page).to have_content('test_changed')
expect(page).to have_content('Application ID') expect(page).to have_content('Application ID')
expect(page).to have_content('Secret') expect(page).to have_content('Secret')
expect(page).to have_content('Trusted N') expect(page).to have_content('Trusted N')
expect(page).to have_content('Confidential N')
visit admin_applications_path visit admin_applications_path
page.within '.oauth-applications' do page.within '.oauth-applications' do
......
...@@ -20,16 +20,19 @@ describe 'User manages applications' do ...@@ -20,16 +20,19 @@ describe 'User manages applications' do
expect(page).to have_content 'Application: test' expect(page).to have_content 'Application: test'
expect(page).to have_content 'Application ID' expect(page).to have_content 'Application ID'
expect(page).to have_content 'Secret' expect(page).to have_content 'Secret'
expect(page).to have_content 'Confidential Yes'
click_on 'Edit' click_on 'Edit'
expect(page).to have_content 'Edit application' expect(page).to have_content 'Edit application'
fill_in :doorkeeper_application_name, with: 'test_changed' fill_in :doorkeeper_application_name, with: 'test_changed'
uncheck :doorkeeper_application_confidential
click_on 'Save application' click_on 'Save application'
expect(page).to have_content 'test_changed' expect(page).to have_content 'test_changed'
expect(page).to have_content 'Application ID' expect(page).to have_content 'Application ID'
expect(page).to have_content 'Secret' expect(page).to have_content 'Secret'
expect(page).to have_content 'Confidential No'
visit applications_profile_path visit applications_profile_path
......
...@@ -21,6 +21,7 @@ describe API::Applications, :api do ...@@ -21,6 +21,7 @@ describe API::Applications, :api do
expect(json_response['application_id']).to eq application.uid expect(json_response['application_id']).to eq application.uid
expect(json_response['secret']).to eq application.secret expect(json_response['secret']).to eq application.secret
expect(json_response['callback_url']).to eq application.redirect_uri expect(json_response['callback_url']).to eq application.redirect_uri
expect(json_response['confidential']).to eq application.confidential
end end
it 'does not allow creating an application with the wrong redirect_uri format' do it 'does not allow creating an application with the wrong redirect_uri format' do
...@@ -72,6 +73,16 @@ describe API::Applications, :api do ...@@ -72,6 +73,16 @@ describe API::Applications, :api do
expect(json_response).to be_a Hash expect(json_response).to be_a Hash
expect(json_response['error']).to eq('scopes is missing') expect(json_response['error']).to eq('scopes is missing')
end end
it 'does not allow creating an application with confidential set to nil' do
expect do
post api('/applications', admin_user), params: { name: 'application_name', redirect_uri: 'http://application.url', scopes: '', confidential: nil }
end.not_to change { Doorkeeper::Application.count }
expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash
expect(json_response['message']['confidential'].first).to eq('is not included in the list')
end
end end
context 'authorized user without authorization' do context 'authorized user without authorization' do
......
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