Commit 930a7030 authored by Kamil Trzcinski's avatar Kamil Trzcinski Committed by James Edwards-Jones

Implement proper verification of certificate's public_key against the private_key

parent 5f7257c2
...@@ -54,8 +54,9 @@ class Projects::PagesController < Projects::ApplicationController ...@@ -54,8 +54,9 @@ class Projects::PagesController < Projects::ApplicationController
return false unless certificate return false unless certificate
return false unless certificate_key return false unless certificate_key
certificate.verify(certificate_key) # We compare the public key stored in certificate with public key from certificate key
rescue OpenSSL::X509::CertificateError certificate.public_key.to_pem == certificate_key.public_key.to_pem
rescue OpenSSL::X509::CertificateError, OpenSSL::PKey::PKeyError
false false
end end
......
...@@ -76,8 +76,6 @@ class Project < ActiveRecord::Base ...@@ -76,8 +76,6 @@ class Project < ActiveRecord::Base
attr_accessor :new_default_branch attr_accessor :new_default_branch
attr_accessor :old_path_with_namespace attr_accessor :old_path_with_namespace
attr_encrypted :pages_custom_certificate_key, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base
alias_attribute :title, :name alias_attribute :title, :name
# Relations # Relations
...@@ -209,14 +207,16 @@ class Project < ActiveRecord::Base ...@@ -209,14 +207,16 @@ class Project < ActiveRecord::Base
validates :pages_custom_domain, hostname: true, allow_blank: true, allow_nil: true validates :pages_custom_domain, hostname: true, allow_blank: true, allow_nil: true
validates_uniqueness_of :pages_custom_domain, allow_nil: true, allow_blank: true validates_uniqueness_of :pages_custom_domain, allow_nil: true, allow_blank: true
validates :pages_custom_certificate, certificate: { intermediate: true } validates :pages_custom_certificate, certificate: true, allow_nil: true, allow_blank: true
validates :pages_custom_certificate_key, certificate_key: true validates :pages_custom_certificate_key, certificate_key: true, allow_nil: true, allow_blank: true
add_authentication_token_field :runners_token add_authentication_token_field :runners_token
before_save :ensure_runners_token before_save :ensure_runners_token
mount_uploader :avatar, AvatarUploader mount_uploader :avatar, AvatarUploader
attr_encrypted :pages_custom_certificate_key, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base
# Scopes # Scopes
default_scope { where(pending_delete: false) } default_scope { where(pending_delete: false) }
......
...@@ -16,6 +16,7 @@ class CertificateKeyValidator < ActiveModel::EachValidator ...@@ -16,6 +16,7 @@ class CertificateKeyValidator < ActiveModel::EachValidator
private private
def valid_private_key_pem?(value) def valid_private_key_pem?(value)
return unless value
pkey = OpenSSL::PKey::RSA.new(value) pkey = OpenSSL::PKey::RSA.new(value)
pkey.private? pkey.private?
rescue OpenSSL::PKey::PKeyError rescue OpenSSL::PKey::PKeyError
......
...@@ -3,26 +3,20 @@ ...@@ -3,26 +3,20 @@
# Custom validator for private keys. # Custom validator for private keys.
# #
# class Project < ActiveRecord::Base # class Project < ActiveRecord::Base
# validates :certificate_key, certificate_key: true # validates :certificate_key, certificate: true
# end # end
# #
class CertificateValidator < ActiveModel::EachValidator class CertificateValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
certificate = parse_certificate(value) unless valid_certificate_pem?(value)
unless certificate
record.errors.add(attribute, "must be a valid PEM certificate") record.errors.add(attribute, "must be a valid PEM certificate")
end end
if options[:intermediates]
unless certificate
record.errors.add(attribute, "certificate verification failed: missing intermediate certificates")
end
end
end end
private private
def parse_certificate(value) def valid_certificate_pem?(value)
return unless value
OpenSSL::X509::Certificate.new(value) OpenSSL::X509::Certificate.new(value)
rescue OpenSSL::X509::CertificateError rescue OpenSSL::X509::CertificateError
nil nil
......
...@@ -134,47 +134,6 @@ ...@@ -134,47 +134,6 @@
= link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" = link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
= f.submit 'Save changes', class: "btn btn-save" = f.submit 'Save changes', class: "btn btn-save"
- if Settings.pages.enabled
.pages-settings
.panel.panel-default
.panel-heading Pages
.errors-holder
.panel-body
- if @project.pages_url
%strong
Congratulations! Your pages are served at:
%p= link_to @project.pages_url, @project.pages_url
- else
%p
Learn how to upload your static site and have it served by
GitLab by following the #{link_to "documentation on GitLab Pages", "http://doc.gitlab.com/ee/pages/README.html", target: :blank}.
%p
In the example below we define a special job named
%code pages
which is using Jekyll to build a static site. The generated
HTML will be stored in the
%code public/
directory which will then be archived and uploaded to GitLab.
The name of the directory should not be different than
%code public/
in order for the pages to work.
%ul
%li
%pre
:plain
pages:
image: jekyll/jekyll
script: jekyll build -d public/
artifacts:
paths:
- public/
- if @project.pages_url && can?(current_user, :remove_pages, @project)
.form-actions
= link_to 'Remove pages', remove_pages_namespace_project_path(@project.namespace, @project),
data: { confirm: "Are you sure that you want to remove pages for this project?" },
method: :post, class: "btn btn-warning"
.row.prepend-top-default .row.prepend-top-default
%hr %hr
.row.prepend-top-default .row.prepend-top-default
......
...@@ -6,13 +6,3 @@ ...@@ -6,13 +6,3 @@
%p %p
Learn how to upload your static site and have it served by Learn how to upload your static site and have it served by
GitLab by following the #{link_to "documentation on GitLab Pages", "http://doc.gitlab.com/ee/pages/README.html", target: :blank}. GitLab by following the #{link_to "documentation on GitLab Pages", "http://doc.gitlab.com/ee/pages/README.html", target: :blank}.
%p
In the example below we define a special job named
%code pages
which is using Jekyll to build a static site. The generated
HTML will be stored in the
%code public/
directory which will then be archived and uploaded to GitLab.
The name of the directory should not be different than
%code public/
in order for the pages to work.
class AddPagesCustomDomainToProjects < ActiveRecord::Migration class AddPagesCustomDomainToProjects < ActiveRecord::Migration
def change def change
add_column :projects, :pages_custom_certificate, :text add_column :projects, :pages_custom_certificate, :text
add_column :projects, :pages_custom_certificate_key, :text add_column :projects, :encrypted_pages_custom_certificate_key, :text
add_column :projects, :pages_custom_certificate_key_iv, :string add_column :projects, :encrypted_pages_custom_certificate_key_iv, :string
add_column :projects, :pages_custom_certificate_key_salt, :string add_column :projects, :encrypted_pages_custom_certificate_key_salt, :string
add_column :projects, :pages_custom_domain, :string, unique: true add_column :projects, :pages_custom_domain, :string, unique: true
add_column :projects, :pages_redirect_http, :boolean, default: false, null: false add_column :projects, :pages_redirect_http, :boolean, default: false, null: false
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