summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGitLab Release Tools Bot <robert+release-tools@gitlab.com>2019-04-04 22:07:05 +0000
committerGitLab Release Tools Bot <robert+release-tools@gitlab.com>2019-04-04 22:07:05 +0000
commit4dda2b2bfcd32f4f7e0065773b2244d5dfab5561 (patch)
tree93672ac0cb5759f894b0c9c95988367230a353e0 /lib
parent35b61afd1e8659898d72a8ed1802e7bd66341acb (diff)
parentfe283d6fd5327bf71d5551dafda00f849047ba14 (diff)
downloadgitlab-ce-4dda2b2bfcd32f4f7e0065773b2244d5dfab5561.tar.gz
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/ci/build/policy/refs.rb2
-rw-r--r--lib/gitlab/ci/config/entry/policy.rb4
-rw-r--r--lib/gitlab/config/entry/validators.rb16
-rw-r--r--lib/gitlab/data_builder/pipeline.rb2
-rw-r--r--lib/gitlab/git/wiki.rb10
-rw-r--r--lib/gitlab/gitaly_client/wiki_service.rb9
-rw-r--r--lib/gitlab/graphql/authorize/authorize_field_service.rb31
-rw-r--r--lib/gitlab/graphql/query_analyzers/log_query_complexity.rb18
-rw-r--r--lib/gitlab/prometheus_client.rb32
-rw-r--r--lib/gitlab/untrusted_regexp/ruby_syntax.rb39
-rw-r--r--lib/gitlab/url_helpers.rb16
-rw-r--r--lib/gitlab/workhorse.rb14
12 files changed, 150 insertions, 43 deletions
diff --git a/lib/gitlab/ci/build/policy/refs.rb b/lib/gitlab/ci/build/policy/refs.rb
index 360424bec11..c3005303fd8 100644
--- a/lib/gitlab/ci/build/policy/refs.rb
+++ b/lib/gitlab/ci/build/policy/refs.rb
@@ -35,7 +35,7 @@ module Gitlab
# patterns can be matched only when branch or tag is used
# the pattern matching does not work for merge requests pipelines
if pipeline.branch? || pipeline.tag?
- if regexp = Gitlab::UntrustedRegexp::RubySyntax.fabricate(pattern)
+ if regexp = Gitlab::UntrustedRegexp::RubySyntax.fabricate(pattern, fallback: true)
regexp.match?(pipeline.ref)
else
pattern == pipeline.ref
diff --git a/lib/gitlab/ci/config/entry/policy.rb b/lib/gitlab/ci/config/entry/policy.rb
index adc3660d950..7b14218d3ea 100644
--- a/lib/gitlab/ci/config/entry/policy.rb
+++ b/lib/gitlab/ci/config/entry/policy.rb
@@ -17,7 +17,7 @@ module Gitlab
include ::Gitlab::Config::Entry::Validatable
validations do
- validates :config, array_of_strings_or_regexps: true
+ validates :config, array_of_strings_or_regexps_with_fallback: true
end
def value
@@ -38,7 +38,7 @@ module Gitlab
validate :variables_expressions_syntax
with_options allow_nil: true do
- validates :refs, array_of_strings_or_regexps: true
+ validates :refs, array_of_strings_or_regexps_with_fallback: true
validates :kubernetes, allowed_values: %w[active]
validates :variables, array_of_strings: true
validates :changes, array_of_strings: true
diff --git a/lib/gitlab/config/entry/validators.rb b/lib/gitlab/config/entry/validators.rb
index d0ee94370ba..746fe83f90f 100644
--- a/lib/gitlab/config/entry/validators.rb
+++ b/lib/gitlab/config/entry/validators.rb
@@ -129,6 +129,12 @@ module Gitlab
end
end
+ protected
+
+ def fallback
+ false
+ end
+
private
def matches_syntax?(value)
@@ -137,7 +143,7 @@ module Gitlab
def validate_regexp(value)
matches_syntax?(value) &&
- Gitlab::UntrustedRegexp::RubySyntax.valid?(value)
+ Gitlab::UntrustedRegexp::RubySyntax.valid?(value, fallback: fallback)
end
end
@@ -162,6 +168,14 @@ module Gitlab
end
end
+ class ArrayOfStringsOrRegexpsWithFallbackValidator < ArrayOfStringsOrRegexpsValidator
+ protected
+
+ def fallback
+ true
+ end
+ end
+
class ArrayOfStringsOrStringValidator < RegexpValidator
def validate_each(record, attribute, value)
unless validate_array_of_strings_or_string(value)
diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb
index 76c8b4ec5c2..fa06fb935f7 100644
--- a/lib/gitlab/data_builder/pipeline.rb
+++ b/lib/gitlab/data_builder/pipeline.rb
@@ -47,7 +47,7 @@ module Gitlab
user: build.user.try(:hook_attrs),
runner: build.runner && runner_hook_attrs(build.runner),
artifacts_file: {
- filename: build.artifacts_file.filename,
+ filename: build.artifacts_file&.filename,
size: build.artifacts_size
}
}
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index c43331bed60..a0dd4a24363 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -86,9 +86,9 @@ module Gitlab
end
end
- def pages(limit: 0)
+ def pages(limit: 0, sort: nil, direction_desc: false)
wrapped_gitaly_errors do
- gitaly_get_all_pages(limit: limit)
+ gitaly_get_all_pages(limit: limit, sort: sort, direction_desc: direction_desc)
end
end
@@ -168,8 +168,10 @@ module Gitlab
Gitlab::Git::WikiFile.new(wiki_file)
end
- def gitaly_get_all_pages(limit: 0)
- gitaly_wiki_client.get_all_pages(limit: limit).map do |wiki_page, version|
+ def gitaly_get_all_pages(limit: 0, sort: nil, direction_desc: false)
+ gitaly_wiki_client.get_all_pages(
+ limit: limit, sort: sort, direction_desc: direction_desc
+ ).map do |wiki_page, version|
Gitlab::Git::WikiPage.new(wiki_page, version)
end
end
diff --git a/lib/gitlab/gitaly_client/wiki_service.rb b/lib/gitlab/gitaly_client/wiki_service.rb
index 15c9463e2f2..e036cdcd800 100644
--- a/lib/gitlab/gitaly_client/wiki_service.rb
+++ b/lib/gitlab/gitaly_client/wiki_service.rb
@@ -87,8 +87,13 @@ module Gitlab
wiki_page_from_iterator(response)
end
- def get_all_pages(limit: 0)
- request = Gitaly::WikiGetAllPagesRequest.new(repository: @gitaly_repo, limit: limit)
+ def get_all_pages(limit: 0, sort: nil, direction_desc: false)
+ sort_value = Gitaly::WikiGetAllPagesRequest::SortBy.resolve(sort.to_s.upcase.to_sym)
+
+ params = { repository: @gitaly_repo, limit: limit, direction_desc: direction_desc }
+ params[:sort] = sort_value if sort_value
+
+ request = Gitaly::WikiGetAllPagesRequest.new(params)
response = GitalyClient.call(@repository.storage, :wiki_service, :wiki_get_all_pages, request, timeout: GitalyClient.medium_timeout)
pages = []
diff --git a/lib/gitlab/graphql/authorize/authorize_field_service.rb b/lib/gitlab/graphql/authorize/authorize_field_service.rb
index f3ca82ec697..8deff79fc84 100644
--- a/lib/gitlab/graphql/authorize/authorize_field_service.rb
+++ b/lib/gitlab/graphql/authorize/authorize_field_service.rb
@@ -14,9 +14,10 @@ module Gitlab
end
def authorized_resolve
- proc do |obj, args, ctx|
- resolved_obj = @old_resolve_proc.call(obj, args, ctx)
- checker = build_checker(ctx[:current_user])
+ proc do |parent_typed_object, args, ctx|
+ resolved_obj = @old_resolve_proc.call(parent_typed_object, args, ctx)
+ authorizing_obj = authorize_against(parent_typed_object)
+ checker = build_checker(ctx[:current_user], authorizing_obj)
if resolved_obj.respond_to?(:then)
resolved_obj.then(&checker)
@@ -51,22 +52,28 @@ module Gitlab
Array.wrap(@field.metadata[:authorize])
end
- def build_checker(current_user)
- lambda do |value|
+ # If it's a built-in/scalar type, authorize using its parent object.
+ # nil means authorize using the resolved object
+ def authorize_against(parent_typed_object)
+ parent_typed_object.object if built_in_type? && parent_typed_object.respond_to?(:object)
+ end
+
+ def build_checker(current_user, authorizing_obj)
+ lambda do |resolved_obj|
# Load the elements if they were not loaded by BatchLoader yet
- value = value.sync if value.respond_to?(:sync)
+ resolved_obj = resolved_obj.sync if resolved_obj.respond_to?(:sync)
check = lambda do |object|
authorizations.all? do |ability|
- Ability.allowed?(current_user, ability, object)
+ Ability.allowed?(current_user, ability, authorizing_obj || object)
end
end
- case value
+ case resolved_obj
when Array, ActiveRecord::Relation
- value.select(&check)
+ resolved_obj.select(&check)
else
- value if check.call(value)
+ resolved_obj if check.call(resolved_obj)
end
end
end
@@ -88,6 +95,10 @@ module Gitlab
def node_type_for_basic_connection(type)
type.unwrap
end
+
+ def built_in_type?
+ GraphQL::Schema::BUILT_IN_TYPES.has_value?(node_type_for_basic_connection(@field.type))
+ end
end
end
end
diff --git a/lib/gitlab/graphql/query_analyzers/log_query_complexity.rb b/lib/gitlab/graphql/query_analyzers/log_query_complexity.rb
new file mode 100644
index 00000000000..95db130dbfc
--- /dev/null
+++ b/lib/gitlab/graphql/query_analyzers/log_query_complexity.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module QueryAnalyzers
+ class LogQueryComplexity
+ class << self
+ def analyzer
+ GraphQL::Analysis::QueryComplexity.new do |query, complexity|
+ # temporary until https://gitlab.com/gitlab-org/gitlab-ce/issues/59587
+ Rails.logger.info("[GraphQL Query Complexity] #{complexity} | admin? #{query.context[:current_user]&.admin?}")
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index 45828c77a33..b4de7cd2bce 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -6,6 +6,14 @@ module Gitlab
Error = Class.new(StandardError)
QueryError = Class.new(Gitlab::PrometheusClient::Error)
+ # Target number of data points for `query_range`.
+ # Please don't exceed the limit of 11000 data points
+ # See https://github.com/prometheus/prometheus/blob/91306bdf24f5395e2601773316945a478b4b263d/web/api/v1/api.go#L347
+ QUERY_RANGE_DATA_POINTS = 600
+
+ # Minimal value of the `step` parameter for `query_range` in seconds.
+ QUERY_RANGE_MIN_STEP = 60
+
attr_reader :rest_client, :headers
def initialize(rest_client)
@@ -23,12 +31,18 @@ module Gitlab
end
def query_range(query, start: 8.hours.ago, stop: Time.now)
+ start = start.to_f
+ stop = stop.to_f
+ step = self.class.compute_step(start, stop)
+
get_result('matrix') do
- json_api_get('query_range',
- query: query,
- start: start.to_f,
- end: stop.to_f,
- step: 1.minute.to_i)
+ json_api_get(
+ 'query_range',
+ query: query,
+ start: start,
+ end: stop,
+ step: step
+ )
end
end
@@ -40,6 +54,14 @@ module Gitlab
json_api_get('series', 'match': matches, start: start.to_f, end: stop.to_f)
end
+ def self.compute_step(start, stop)
+ diff = stop - start
+
+ step = (diff / QUERY_RANGE_DATA_POINTS).ceil
+
+ [QUERY_RANGE_MIN_STEP, step].max
+ end
+
private
def json_api_get(type, args = {})
diff --git a/lib/gitlab/untrusted_regexp/ruby_syntax.rb b/lib/gitlab/untrusted_regexp/ruby_syntax.rb
index 91f300f97d0..6adf119aa75 100644
--- a/lib/gitlab/untrusted_regexp/ruby_syntax.rb
+++ b/lib/gitlab/untrusted_regexp/ruby_syntax.rb
@@ -6,7 +6,7 @@ module Gitlab
# and converts that to RE2 representation:
# /<regexp>/<flags>
class RubySyntax
- PATTERN = %r{^/(?<regexp>.+)/(?<flags>[ismU]*)$}.freeze
+ PATTERN = %r{^/(?<regexp>.*)/(?<flags>[ismU]*)$}.freeze
# Checks if pattern matches a regexp pattern
# but does not enforce it's validity
@@ -16,28 +16,47 @@ module Gitlab
# The regexp can match the pattern `/.../`, but may not be fabricatable:
# it can be invalid or incomplete: `/match ( string/`
- def self.valid?(pattern)
- !!self.fabricate(pattern)
+ def self.valid?(pattern, fallback: false)
+ !!self.fabricate(pattern, fallback: fallback)
end
- def self.fabricate(pattern)
- self.fabricate!(pattern)
+ def self.fabricate(pattern, fallback: false)
+ self.fabricate!(pattern, fallback: fallback)
rescue RegexpError
nil
end
- def self.fabricate!(pattern)
+ def self.fabricate!(pattern, fallback: false)
raise RegexpError, 'Pattern is not string!' unless pattern.is_a?(String)
matches = pattern.match(PATTERN)
raise RegexpError, 'Invalid regular expression!' if matches.nil?
- expression = matches[:regexp]
- flags = matches[:flags]
- expression.prepend("(?#{flags})") if flags.present?
+ begin
+ create_untrusted_regexp(matches[:regexp], matches[:flags])
+ rescue RegexpError
+ raise unless fallback &&
+ Feature.enabled?(:allow_unsafe_ruby_regexp, default_enabled: false)
- UntrustedRegexp.new(expression, multiline: false)
+ create_ruby_regexp(matches[:regexp], matches[:flags])
+ end
end
+
+ def self.create_untrusted_regexp(pattern, flags)
+ pattern.prepend("(?#{flags})") if flags.present?
+
+ UntrustedRegexp.new(pattern, multiline: false)
+ end
+ private_class_method :create_untrusted_regexp
+
+ def self.create_ruby_regexp(pattern, flags)
+ options = 0
+ options += Regexp::IGNORECASE if flags&.include?('i')
+ options += Regexp::MULTILINE if flags&.include?('m')
+
+ Regexp.new(pattern, options)
+ end
+ private_class_method :create_ruby_regexp
end
end
end
diff --git a/lib/gitlab/url_helpers.rb b/lib/gitlab/url_helpers.rb
new file mode 100644
index 00000000000..883585c196f
--- /dev/null
+++ b/lib/gitlab/url_helpers.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class UrlHelpers
+ WSS_PROTOCOL = "wss".freeze
+ def self.as_wss(url)
+ return unless url.present?
+
+ URI.parse(url).tap do |uri|
+ uri.scheme = WSS_PROTOCOL
+ end.to_s
+ rescue URI::InvalidURIError
+ nil
+ end
+ end
+end
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 83eabb8d674..533757d2237 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -162,16 +162,16 @@ module Gitlab
]
end
- def terminal_websocket(terminal)
+ def channel_websocket(channel)
details = {
- 'Terminal' => {
- 'Subprotocols' => terminal[:subprotocols],
- 'Url' => terminal[:url],
- 'Header' => terminal[:headers],
- 'MaxSessionTime' => terminal[:max_session_time]
+ 'Channel' => {
+ 'Subprotocols' => channel[:subprotocols],
+ 'Url' => channel[:url],
+ 'Header' => channel[:headers],
+ 'MaxSessionTime' => channel[:max_session_time]
}
}
- details['Terminal']['CAPem'] = terminal[:ca_pem] if terminal.key?(:ca_pem)
+ details['Channel']['CAPem'] = channel[:ca_pem] if channel.key?(:ca_pem)
details
end