From db6989ddb0dc1dc630803ea3748542779b5f9090 Mon Sep 17 00:00:00 2001 From: Vladimir Shushlin Date: Sat, 27 Apr 2019 04:38:01 +0000 Subject: Add Let's Encrypt application settings Store Let's Encrypt account email in application settings Also add explicit terms of service consent --- .../admin/application_settings_controller.rb | 10 +++++++ app/models/application_setting.rb | 10 +++++++ .../admin/application_settings/_pages.html.haml | 29 +++++++++++++++----- ...t_notification_email_to_application_settings.rb | 15 +++++++++++ ..._of_service_accepted_to_application_settings.rb | 21 +++++++++++++++ db/schema.rb | 2 ++ locale/gitlab.pot | 24 +++++++++++++++++ spec/features/admin/admin_settings_spec.rb | 31 ++++++++++++++++++++++ spec/models/application_setting_spec.rb | 14 ++++++++++ 9 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20190320174702_add_lets_encrypt_notification_email_to_application_settings.rb create mode 100644 db/migrate/20190329085614_add_lets_encrypt_terms_of_service_accepted_to_application_settings.rb diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index b681949ab36..d445be0eb19 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -127,6 +127,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController [ *::ApplicationSettingsHelper.visible_attributes, *::ApplicationSettingsHelper.external_authorization_service_attributes, + *lets_encrypt_visible_attributes, :domain_blacklist_file, disabled_oauth_sign_in_sources: [], import_sources: [], @@ -134,4 +135,13 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController restricted_visibility_levels: [] ] end + + def lets_encrypt_visible_attributes + return [] unless Feature.enabled?(:pages_auto_ssl) + + [ + :lets_encrypt_notification_email, + :lets_encrypt_terms_of_service_accepted + ] + end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 2f9b4c4eaa2..fb1e558e46c 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -229,6 +229,16 @@ class ApplicationSetting < ApplicationRecord presence: true, if: -> (setting) { setting.external_auth_client_cert.present? } + validates :lets_encrypt_notification_email, + devise_email: true, + format: { without: /@example\.(com|org|net)\z/, + message: N_("Let's Encrypt does not accept emails on example.com") }, + allow_blank: true + + validates :lets_encrypt_notification_email, + presence: true, + if: :lets_encrypt_terms_of_service_accepted? + validates_with X509CertificateCredentialsValidator, certificate: :external_auth_client_cert, pkey: :external_auth_client_key, diff --git a/app/views/admin/application_settings/_pages.html.haml b/app/views/admin/application_settings/_pages.html.haml index ad5c8d4da22..64e01fa2d00 100644 --- a/app/views/admin/application_settings/_pages.html.haml +++ b/app/views/admin/application_settings/_pages.html.haml @@ -5,16 +5,33 @@ .form-group = f.label :max_pages_size, 'Maximum size of pages (MB)', class: 'label-bold' = f.number_field :max_pages_size, class: 'form-control' - .form-text.text-muted 0 for unlimited + .form-text.text-muted + = _("0 for unlimited") .form-group .form-check = f.check_box :pages_domain_verification_enabled, class: 'form-check-input' = f.label :pages_domain_verification_enabled, class: 'form-check-label' do - Require users to prove ownership of custom domains + = _("Require users to prove ownership of custom domains") .form-text.text-muted - Domain verification is an essential security measure for public GitLab - sites. Users are required to demonstrate they control a domain before - it is enabled + = _("Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled") = link_to icon('question-circle'), help_page_path('user/project/pages/getting_started_part_three.md', anchor: 'dns-txt-record') + - if Feature.enabled?(:pages_auto_ssl) + %h5 + = _("Configure Let's Encrypt") + %p + - lets_encrypt_link_start = ''.html_safe % { url: "https://letsencrypt.org/" } + = _("%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites.").html_safe % { lets_encrypt_link_start: lets_encrypt_link_start, lets_encrypt_link_end: ''.html_safe } + .form-group + = f.label :lets_encrypt_notification_email, _("Email"), class: 'label-bold' + = f.text_field :lets_encrypt_notification_email, class: 'form-control' + .form-text.text-muted + = _("A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates.") + .form-group + .form-check + = f.check_box :lets_encrypt_terms_of_service_accepted, class: 'form-check-input' + = f.label :lets_encrypt_terms_of_service_accepted, class: 'form-check-label' do + // Terms of Service should actually be a link, but the best way to get the url is using API + // So it will be done in later MR + = _("I have read and agree to the Let's Encrypt Terms of Service") - = f.submit 'Save changes', class: "btn btn-success" + = f.submit _('Save changes'), class: "btn btn-success" diff --git a/db/migrate/20190320174702_add_lets_encrypt_notification_email_to_application_settings.rb b/db/migrate/20190320174702_add_lets_encrypt_notification_email_to_application_settings.rb new file mode 100644 index 00000000000..e9cf2af84a5 --- /dev/null +++ b/db/migrate/20190320174702_add_lets_encrypt_notification_email_to_application_settings.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddLetsEncryptNotificationEmailToApplicationSettings < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + def change + add_column :application_settings, :lets_encrypt_notification_email, :string + end +end diff --git a/db/migrate/20190329085614_add_lets_encrypt_terms_of_service_accepted_to_application_settings.rb b/db/migrate/20190329085614_add_lets_encrypt_terms_of_service_accepted_to_application_settings.rb new file mode 100644 index 00000000000..16de63f207f --- /dev/null +++ b/db/migrate/20190329085614_add_lets_encrypt_terms_of_service_accepted_to_application_settings.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddLetsEncryptTermsOfServiceAcceptedToApplicationSettings < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_column_with_default(:application_settings, :lets_encrypt_terms_of_service_accepted, :boolean, default: false) + end + + def down + remove_column :application_settings, :lets_encrypt_terms_of_service_accepted + end +end diff --git a/db/schema.rb b/db/schema.rb index a38c07a491e..5a486b369e3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -187,6 +187,8 @@ ActiveRecord::Schema.define(version: 20190426180107) do t.string "encrypted_external_auth_client_key_iv" t.string "encrypted_external_auth_client_key_pass" t.string "encrypted_external_auth_client_key_pass_iv" + t.string "lets_encrypt_notification_email" + t.boolean "lets_encrypt_terms_of_service_accepted", default: false, null: false t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 5bc9bb3434d..b973cd2dd8e 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -138,6 +138,9 @@ msgstr "" msgid "%{label_for_message} unavailable" msgstr "" +msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites." +msgstr "" + msgid "%{level_name} is not allowed in a %{group_level_name} group." msgstr "" @@ -245,6 +248,9 @@ msgstr "" msgid "- show less" msgstr "" +msgid "0 for unlimited" +msgstr "" + msgid "1 %{type} addition" msgid_plural "%{count} %{type} additions" msgstr[0] "" @@ -366,6 +372,9 @@ msgstr "" msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features." msgstr "" +msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates." +msgstr "" + msgid "A default branch cannot be chosen for an empty project." msgstr "" @@ -2525,6 +2534,9 @@ msgstr "" msgid "Configure Gitaly timeouts." msgstr "" +msgid "Configure Let's Encrypt" +msgstr "" + msgid "Configure automatic git checks and housekeeping on repositories." msgstr "" @@ -3280,6 +3292,9 @@ msgstr "" msgid "Domain" msgstr "" +msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled" +msgstr "" + msgid "Don't show again" msgstr "" @@ -4622,6 +4637,9 @@ msgstr "" msgid "I accept the|Terms of Service and Privacy Policy" msgstr "" +msgid "I have read and agree to the Let's Encrypt Terms of Service" +msgstr "" + msgid "ID" msgstr "" @@ -5311,6 +5329,9 @@ msgstr "" msgid "Leave the \"File type\" and \"Delivery method\" options on their default values." msgstr "" +msgid "Let's Encrypt does not accept emails on example.com" +msgstr "" + msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" msgstr[0] "" @@ -7626,6 +7647,9 @@ msgstr "" msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab." msgstr "" +msgid "Require users to prove ownership of custom domains" +msgstr "" + msgid "Resend invite" msgstr "" diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 3c9a9d61756..f9950b5b03f 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -375,6 +375,37 @@ describe 'Admin updates settings' do expect(Gitlab::CurrentSettings.pages_domain_verification_enabled?).to be_truthy expect(page).to have_content "Application settings saved successfully" end + + context 'When pages_auto_ssl is enabled' do + before do + stub_feature_flags(pages_auto_ssl: true) + visit preferences_admin_application_settings_path + end + + it "Change Pages Let's Encrypt settings" do + page.within('.as-pages') do + fill_in 'Email', with: 'my@test.example.com' + check "I have read and agree to the Let's Encrypt Terms of Service" + click_button 'Save changes' + end + + expect(Gitlab::CurrentSettings.lets_encrypt_notification_email).to eq 'my@test.example.com' + expect(Gitlab::CurrentSettings.lets_encrypt_terms_of_service_accepted).to eq true + end + end + + context 'When pages_auto_ssl is disabled' do + before do + stub_feature_flags(pages_auto_ssl: false) + visit preferences_admin_application_settings_path + end + + it "Doesn't show Let's Encrypt options" do + page.within('.as-pages') do + expect(page).not_to have_content('Email') + end + end + end end def check_all_events diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index c7d7dbac736..f8dc1541dd3 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -31,6 +31,20 @@ describe ApplicationSetting do it { is_expected.to allow_value("dev.gitlab.com").for(:commit_email_hostname) } it { is_expected.not_to allow_value("@dev.gitlab").for(:commit_email_hostname) } + it { is_expected.to allow_value("myemail@gitlab.com").for(:lets_encrypt_notification_email) } + it { is_expected.to allow_value(nil).for(:lets_encrypt_notification_email) } + it { is_expected.not_to allow_value("notanemail").for(:lets_encrypt_notification_email) } + it { is_expected.not_to allow_value("myemail@example.com").for(:lets_encrypt_notification_email) } + it { is_expected.to allow_value("myemail@test.example.com").for(:lets_encrypt_notification_email) } + + context "when user accepted let's encrypt terms of service" do + before do + setting.update(lets_encrypt_terms_of_service_accepted: true) + end + + it { is_expected.not_to allow_value(nil).for(:lets_encrypt_notification_email) } + end + describe 'default_artifacts_expire_in' do it 'sets an error if it cannot parse' do setting.update(default_artifacts_expire_in: 'a') -- cgit v1.2.3