Class: Banzai::Filter::AssetProxyFilter
- Inherits:
-
HTML::Pipeline::Filter
- Object
- HTML::Pipeline::Filter
- Banzai::Filter::AssetProxyFilter
- Defined in:
- lib/banzai/filter/asset_proxy_filter.rb
Overview
Proxies images/assets through another server. Reduces mixed content warnings as well as hiding the customer’s IP address when requesting images. Copies the original img src to data-canonical-src and replaces the src with a new url to the proxy server.
See docs.gitlab.com/security/asset_proxy/ for more information.
Based on github.com/gjtorikian/html-pipeline/blob/v2.14.3/lib/html/pipeline/camo_filter.rb
Constant Summary
Constants included from Concerns::PipelineTimingCheck
Concerns::PipelineTimingCheck::MAX_PIPELINE_SECONDS
Class Method Summary collapse
- .csp_for_allowlist(allowlist) ⇒ Object
- .determine_allowlist(application_settings) ⇒ Object
- .host_regexp_for_allowlist(allowlist) ⇒ Object
-
.initialize_settings ⇒ Object
called during an initializer.
- .transform_context(context) ⇒ Object
Instance Method Summary collapse
- #call ⇒ Object
-
#initialize(text, context = nil, result = nil) ⇒ AssetProxyFilter
constructor
A new instance of AssetProxyFilter.
- #validate ⇒ Object
Methods included from Concerns::AssetProxying
#asset_proxy_enabled?, #asset_proxy_url, #can_skip_asset_proxy_for_url?, #validate_asset_proxying
Methods included from Concerns::PipelineTimingCheck
Constructor Details
#initialize(text, context = nil, result = nil) ⇒ AssetProxyFilter
Returns a new instance of AssetProxyFilter.
17 18 19 |
# File 'lib/banzai/filter/asset_proxy_filter.rb', line 17 def initialize(text, context = nil, result = nil) super end |
Class Method Details
.csp_for_allowlist(allowlist) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/banzai/filter/asset_proxy_filter.rb', line 80 def self.csp_for_allowlist(allowlist) return unless Gitlab.config.asset_proxy.enabled # See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#host-source. # Permit assets on the GitLab host itself. src = [:self] # We need to permit the asset proxy URL itself for it to work in the Mermaid sandbox. # The setting is already validated to be a valid URL; we need to ensure it ends in a # forward-slash for the CSP to ensure we permit the entire prefix. asset_proxy_url = Gitlab.config.asset_proxy.url asset_proxy_url += '/' unless asset_proxy_url.ends_with?('/') src << asset_proxy_url # We use HTTP (and not HTTPS) as the scheme as administrators may allowlist a host with the expectation that # they can use resources from it over HTTP, such as in an intranet. Allowing http://... in a CSP also # explicitly permits HTTPS for the same directive. ("When matching schemes, secure upgrades are allowed.") allowlist.each do |host| src << "http://#{host}:*" end src end |
.determine_allowlist(application_settings) ⇒ Object
105 106 107 108 109 |
# File 'lib/banzai/filter/asset_proxy_filter.rb', line 105 def self.determine_allowlist(application_settings) application_settings.try(:asset_proxy_allowlist).presence || application_settings.try(:asset_proxy_whitelist).presence || [Gitlab.config.gitlab.host] end |
.host_regexp_for_allowlist(allowlist) ⇒ Object
73 74 75 76 77 78 |
# File 'lib/banzai/filter/asset_proxy_filter.rb', line 73 def self.host_regexp_for_allowlist(allowlist) return if allowlist.empty? escaped = allowlist.map { |domain| Regexp.escape(domain).gsub('\*', '.*?') } Regexp.new("^(#{escaped.join('|')})$", Regexp::IGNORECASE) end |
.initialize_settings ⇒ Object
called during an initializer. Caching the values in Gitlab.config significantly increased performance, rather than querying Gitlab::CurrentSettings.current_application_settings over and over. However, this does mean that the Rails servers need to get restarted whenever the application settings are changed
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/banzai/filter/asset_proxy_filter.rb', line 57 def self.initialize_settings application_settings = Gitlab::CurrentSettings.current_application_settings Gitlab.config['asset_proxy'] ||= GitlabSettings::Options.build({}) if application_settings.respond_to?(:asset_proxy_enabled) Gitlab.config.asset_proxy['enabled'] = application_settings.asset_proxy_enabled Gitlab.config.asset_proxy['url'] = application_settings.asset_proxy_url Gitlab.config.asset_proxy['secret_key'] = application_settings.asset_proxy_secret_key Gitlab.config.asset_proxy['allowlist'] = determine_allowlist(application_settings) Gitlab.config.asset_proxy['domain_regexp'] = host_regexp_for_allowlist(Gitlab.config.asset_proxy.allowlist) Gitlab.config.asset_proxy['csp_directives'] = csp_for_allowlist(Gitlab.config.asset_proxy.allowlist) else Gitlab.config.asset_proxy['enabled'] = ::ApplicationSetting.defaults[:asset_proxy_enabled] end end |
.transform_context(context) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/banzai/filter/asset_proxy_filter.rb', line 40 def self.transform_context(context) context[:disable_asset_proxy] = !Gitlab.config.asset_proxy.enabled unless context[:disable_asset_proxy] context[:asset_proxy_enabled] = !context[:disable_asset_proxy] context[:asset_proxy] = Gitlab.config.asset_proxy.url context[:asset_proxy_secret_key] = Gitlab.config.asset_proxy.secret_key context[:asset_proxy_domain_regexp] = Gitlab.config.asset_proxy.domain_regexp end context end |
Instance Method Details
#call ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/banzai/filter/asset_proxy_filter.rb', line 21 def call return doc unless asset_proxy_enabled? doc.search('img').each do |element| original_src = element['src'] next unless original_src next if can_skip_asset_proxy_for_url?(original_src) element['src'] = asset_proxy_url(original_src) element['data-canonical-src'] = original_src end doc end |
#validate ⇒ Object
36 37 38 |
# File 'lib/banzai/filter/asset_proxy_filter.rb', line 36 def validate end |