Commit f913f7a1 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'feature/ssh_host_fingerprint' into 'master'

Automatic configuration settings page

Closes #25142

See merge request gitlab-org/gitlab-ce!13850
parents 3ddffec0 294f40e2
......@@ -57,6 +57,10 @@ class HelpController < ApplicationController
def shortcuts
end
def instance_configuration
@instance_configuration = InstanceConfiguration.new
end
def ui
@user = User.new(id: 0, name: 'John Doe', username: '@johndoe')
end
......
module InstanceConfigurationHelper
def instance_configuration_cell_html(value, &block)
return '-' unless value.to_s.presence
block_given? ? yield(value) : value
end
def instance_configuration_host(host)
@instance_configuration_host ||= instance_configuration_cell_html(host).capitalize
end
# Value must be in bytes
def instance_configuration_human_size_cell(value)
instance_configuration_cell_html(value) do |v|
number_to_human_size(v, strip_insignificant_zeros: true, significant: false)
end
end
end
require 'resolv'
class InstanceConfiguration
SSH_ALGORITHMS = %w(DSA ECDSA ED25519 RSA).freeze
SSH_ALGORITHMS_PATH = '/etc/ssh/'.freeze
CACHE_KEY = 'instance_configuration'.freeze
EXPIRATION_TIME = 24.hours
def settings
@configuration ||= Rails.cache.fetch(CACHE_KEY, expires_in: EXPIRATION_TIME) do
{ ssh_algorithms_hashes: ssh_algorithms_hashes,
host: host,
gitlab_pages: gitlab_pages,
gitlab_ci: gitlab_ci }.deep_symbolize_keys
end
end
private
def ssh_algorithms_hashes
SSH_ALGORITHMS.map { |algo| ssh_algorithm_hashes(algo) }.compact
end
def host
Settings.gitlab.host
end
def gitlab_pages
Settings.pages.to_h.merge(ip_address: resolv_dns(Settings.pages.host))
end
def resolv_dns(dns)
Resolv.getaddress(dns)
rescue Resolv::ResolvError
end
def gitlab_ci
Settings.gitlab_ci
.to_h
.merge(artifacts_max_size: { value: Settings.artifacts.max_size&.megabytes,
default: 100.megabytes })
end
def ssh_algorithm_file(algorithm)
File.join(SSH_ALGORITHMS_PATH, "ssh_host_#{algorithm.downcase}_key.pub")
end
def ssh_algorithm_hashes(algorithm)
content = ssh_algorithm_file_content(algorithm)
return unless content.present?
{ name: algorithm,
md5: ssh_algorithm_md5(content),
sha256: ssh_algorithm_sha256(content) }
end
def ssh_algorithm_file_content(algorithm)
file = ssh_algorithm_file(algorithm)
return unless File.exist?(file)
File.read(file)
end
def ssh_algorithm_md5(ssh_file_content)
OpenSSL::Digest::MD5.hexdigest(ssh_file_content).scan(/../).join(':')
end
def ssh_algorithm_sha256(ssh_file_content)
OpenSSL::Digest::SHA256.hexdigest(ssh_file_content)
end
end
......@@ -11,6 +11,7 @@
%span= Gitlab::VERSION
%small= link_to Gitlab::REVISION, Gitlab::COM_URL + namespace_project_commits_path('gitlab-org', 'gitlab-ce', Gitlab::REVISION)
= version_status_badge
%p.slead
GitLab is open source software to collaborate on code.
%br
......@@ -23,6 +24,7 @@
Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises.
%br
Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank', rel: 'noopener noreferrer'}.
%p= link_to 'Check the current instance configuration ', help_instance_configuration_url
%hr
.row.prepend-top-default
......
- page_title 'Instance Configuration'
.wiki.documentation
%h1 Instance Configuration
%p
In this page you will find information about the settings that are used in your current instance.
= render 'help/instance_configuration/ssh_info'
= render 'help/instance_configuration/gitlab_pages'
= render 'help/instance_configuration/gitlab_ci'
%p
%strong Table of contents
%ul
= content_for :table_content
= content_for :settings_content
- content_for :table_content do
%li= link_to 'GitLab CI', '#gitlab-ci'
- content_for :settings_content do
%h2#gitlab-ci
GitLab CI
%p
Below are the current settings regarding
= succeed('.') { link_to('GitLab CI', 'https://about.gitlab.com/gitlab-ci', target: '_blank') }
.table-responsive
%table
%thead
%tr
%th Setting
%th= instance_configuration_host(@instance_configuration.settings[:host])
%th Default
%tbody
%tr
- artifacts_size = @instance_configuration.settings[:gitlab_ci][:artifacts_max_size]
%td Artifacts maximum size
%td= instance_configuration_human_size_cell(artifacts_size[:value])
%td= instance_configuration_human_size_cell(artifacts_size[:default])
- gitlab_pages = @instance_configuration.settings[:gitlab_pages]
- content_for :table_content do
%li= link_to 'GitLab Pages', '#gitlab-pages'
- content_for :settings_content do
%h2#gitlab-pages
GitLab Pages
%p
Below are the settings for
= succeed('.') { link_to('Gitlab Pages', gitlab_pages[:url], target: '_blank') }
.table-responsive
%table
%thead
%tr
%th Setting
%th= instance_configuration_host(@instance_configuration.settings[:host])
%tbody
%tr
%td Domain Name
%td
%code= instance_configuration_cell_html(gitlab_pages[:host])
%tr
%td IP Address
%td
%code= instance_configuration_cell_html(gitlab_pages[:ip_address])
%tr
%td Port
%td
%code= instance_configuration_cell_html(gitlab_pages[:port])
%br
%p
The maximum size of your Pages site is regulated by the artifacts maximum
size which is part of #{succeed('.') { link_to('GitLab CI', '#gitlab-ci') }}
- ssh_info = @instance_configuration.settings[:ssh_algorithms_hashes]
- if ssh_info.any?
- content_for :table_content do
%li= link_to 'SSH host keys fingerprints', '#ssh-host-keys-fingerprints'
- content_for :settings_content do
%h2#ssh-host-keys-fingerprints
SSH host keys fingerprints
%p
Below are the fingerprints for the current instance SSH host keys.
.table-responsive
%table
%thead
%tr
%th Algorithm
%th MD5
%th SHA256
%tbody
- ssh_info.each do |algorithm|
%tr
%td= algorithm[:name]
%td
%code= instance_configuration_cell_html(algorithm[:md5])
%td
%code= instance_configuration_cell_html(algorithm[:sha256])
---
title: Automatic configuration settings page
merge_request: 13850
author: Francisco Lopez
type: added
get 'help' => 'help#index'
get 'help/shortcuts' => 'help#shortcuts'
get 'help/ui' => 'help#ui'
get 'help/instance_configuration' => 'help#instance_configuration'
get 'help/*path' => 'help#show', as: :help_page
FactoryGirl.define do
factory :instance_configuration do
skip_create
end
end
require 'spec_helper'
describe InstanceConfigurationHelper do
describe '#instance_configuration_cell_html' do
describe 'if not block is passed' do
it 'returns the parameter if present' do
expect(helper.instance_configuration_cell_html('gitlab')).to eq('gitlab')
end
it 'returns "-" if the parameter is blank' do
expect(helper.instance_configuration_cell_html(nil)).to eq('-')
expect(helper.instance_configuration_cell_html('')).to eq('-')
end
end
describe 'if a block is passed' do
let(:upcase_block) { ->(value) { value.upcase } }
it 'returns the result of the block' do
expect(helper.instance_configuration_cell_html('gitlab', &upcase_block)).to eq('GITLAB')
expect(helper.instance_configuration_cell_html('gitlab') { |v| v.upcase }).to eq('GITLAB')
end
it 'returns "-" if the parameter is blank' do
expect(helper.instance_configuration_cell_html(nil, &upcase_block)).to eq('-')
expect(helper.instance_configuration_cell_html(nil) { |v| v.upcase }).to eq('-')
expect(helper.instance_configuration_cell_html('', &upcase_block)).to eq('-')
end
end
it 'boolean are valid values to display' do
expect(helper.instance_configuration_cell_html(true)).to eq(true)
expect(helper.instance_configuration_cell_html(false)).to eq(false)
end
end
describe '#instance_configuration_human_size_cell' do
it 'returns "-" if the parameter is blank' do
expect(helper.instance_configuration_human_size_cell(nil)).to eq('-')
expect(helper.instance_configuration_human_size_cell('')).to eq('-')
end
it 'accepts the value in bytes' do
expect(helper.instance_configuration_human_size_cell(1024)).to eq('1 KB')
end
it 'returns the value in human size readable format' do
expect(helper.instance_configuration_human_size_cell(1048576)).to eq('1 MB')
end
end
end
require 'spec_helper'
RSpec.describe InstanceConfiguration do
context 'without cache' do
describe '#settings' do
describe '#ssh_algorithms_hashes' do
let(:md5) { '54:e0:f8:70:d6:4f:4c:b1:b3:02:44:77:cf:cd:0d:fc' }
let(:sha256) { '9327f0d15a48c4d9f6a3aee65a1825baf9a3412001c98169c5fd022ac27762fc' }
it 'does not return anything if file does not exist' do
stub_pub_file(exist: false)
expect(subject.settings[:ssh_algorithms_hashes]).to be_empty
end
it 'does not return anything if file is empty' do
stub_pub_file
allow(File).to receive(:read).and_return('')
expect(subject.settings[:ssh_algorithms_hashes]).to be_empty
end
it 'returns the md5 and sha256 if file valid and exists' do
stub_pub_file
result = subject.settings[:ssh_algorithms_hashes].select { |o| o[:md5] == md5 && o[:sha256] == sha256 }
expect(result.size).to eq(InstanceConfiguration::SSH_ALGORITHMS.size)
end
def stub_pub_file(exist: true)
path = 'spec/fixtures/ssh_host_example_key.pub'
path << 'random' unless exist
allow(subject).to receive(:ssh_algorithm_file).and_return(Rails.root.join(path))
end
end
describe '#host' do
it 'returns current instance host' do
allow(Settings.gitlab).to receive(:host).and_return('exampledomain')
expect(subject.settings[:host]).to eq(Settings.gitlab.host)
end
end
describe '#gitlab_pages' do
let(:gitlab_pages) { subject.settings[:gitlab_pages] }
it 'returns Settings.pages' do
gitlab_pages.delete(:ip_address)
expect(gitlab_pages).to eq(Settings.pages.symbolize_keys)
end
it 'returns the Gitlab\'s pages host ip address' do
expect(gitlab_pages.keys).to include(:ip_address)
end
it 'returns the ip address as nil if the domain is invalid' do
allow(Settings.pages).to receive(:host).and_return('exampledomain')
expect(gitlab_pages[:ip_address]).to eq nil
end
it 'returns the ip address of the domain' do
allow(Settings.pages).to receive(:host).and_return('localhost')
expect(gitlab_pages[:ip_address]).to eq('127.0.0.1').or eq('::1')
end
end
describe '#gitlab_ci' do
let(:gitlab_ci) { subject.settings[:gitlab_ci] }
it 'returns Settings.gitalb_ci' do
gitlab_ci.delete(:artifacts_max_size)
expect(gitlab_ci).to eq(Settings.gitlab_ci.symbolize_keys)
end
it 'returns the key artifacts_max_size' do
expect(gitlab_ci.keys).to include(:artifacts_max_size)
end
end
end
end
context 'with cache', :use_clean_rails_memory_store_caching do
it 'caches settings content' do
expect(Rails.cache.read(described_class::CACHE_KEY)).to be_nil
settings = subject.settings
expect(Rails.cache.read(described_class::CACHE_KEY)).to eq(settings)
end
describe 'cached settings' do
before do
subject.settings
end
it 'expires after EXPIRATION_TIME' do
allow(Time).to receive(:now).and_return(Time.now + described_class::EXPIRATION_TIME)
Rails.cache.cleanup
expect(Rails.cache.read(described_class::CACHE_KEY)).to eq(nil)
end
end
end
end
......@@ -25,6 +25,14 @@ describe 'help/index' do
end
end
describe 'instance configuration link' do
it 'is visible to guests' do
render
expect(rendered).to have_link(nil, help_instance_configuration_url)
end
end
def stub_user(user = double)
allow(view).to receive(:user_signed_in?).and_return(user)
end
......
require 'rails_helper'
describe 'help/instance_configuration' do
describe 'General Sections:' do
let(:instance_configuration) { build(:instance_configuration)}
let(:settings) { instance_configuration.settings }
let(:ssh_settings) { settings[:ssh_algorithms_hashes] }
before do
assign(:instance_configuration, instance_configuration)
end
it 'has links to several sections' do
render
expect(rendered).to have_link(nil, '#ssh-host-keys-fingerprints') if ssh_settings.any?
expect(rendered).to have_link(nil, '#gitlab-pages')
expect(rendered).to have_link(nil, '#gitlab-ci')
end
it 'has several sections' do
render
expect(rendered).to have_css('h2#ssh-host-keys-fingerprints') if ssh_settings.any?
expect(rendered).to have_css('h2#gitlab-pages')
expect(rendered).to have_css('h2#gitlab-ci')
end
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