Skip to content

Commit

Permalink
feat(webhook certificates): support setting webhook certificates usin…
Browse files Browse the repository at this point in the history
…g environment variables
  • Loading branch information
bethesque committed Mar 28, 2022
1 parent 88f6708 commit 82c7a7e
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 9 deletions.
19 changes: 15 additions & 4 deletions docs/configuration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,6 @@ groups:
When setting the path, the full path to the certificate file in PEM format must be specified. When using Docker, you must ensure the
certificate file is [mounted into the container](https://docs.docker.com/storage/volumes/).
*NOTE: USING ENVIRONMENT VARIABLES TO SET THE WEBHOOK CERTIFICATES IS NOT SUPPORTED.*
YAML Example:
```yaml
Expand All @@ -291,10 +289,23 @@ groups:
jHT1Ty2CglM=
-----END CERTIFICATE-----
- description: "An example self signed certificate with a path"
path: /full/path/to/the/cert.pem
path: "/full/path/to/the/cert.pem"
```
Environment variable example:
```shell
PACT_BROKER_WEBHOOK_CERTIFICATES__0__LABEL="An example self signed certificate with content"
PACT_BROKER_WEBHOOK_CERTIFICATES__0__CONTENT="-----BEGIN CERTIFICATE-----
MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMRMwEQYKCZImiZPyLGQB
<REST OF CERTIFICATE>
jHT1Ty2CglM=
-----END CERTIFICATE-----"
PACT_BROKER_WEBHOOK_CERTIFICATES__1__LABEL="An example self signed certificate with a path"
PACT_BROKER_WEBHOOK_CERTIFICATES__1__PATH="/full/path/to/the/cert.pem"
```
supported_versions: From v2.90.0
supported_versions: From v2.90.0 for YAML and 2.97.0 for environment variables.
disable_ssl_verification:
description: "If set to true, SSL verification will be disabled for the HTTP requests made by the webhooks"
default_value: false
Expand Down
23 changes: 20 additions & 3 deletions lib/pact_broker/config/runtime_configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,12 @@ class RuntimeConfiguration < Anyway::Config
webhook_scheme_whitelist: ["https"],
webhook_host_whitelist: [],
disable_ssl_verification: false,
webhook_certificates: [],
user_agent: "Pact Broker v#{PactBroker::VERSION}",
user_agent: "Pact Broker v#{PactBroker::VERSION}"
)
# no default, if you set it to [] or nil, then anyway config blows up when it tries to merge in the
# numerically indexed hash from the environment variables.
attr_config :webhook_certificates
on_load :set_webhook_attribute_defaults

# resource attributes
attr_config(
Expand Down Expand Up @@ -178,8 +181,14 @@ def features= features
def webhook_certificates= webhook_certificates
if webhook_certificates.is_a?(Array)
super(webhook_certificates.collect(&:symbolize_keys))
elsif webhook_certificates.is_a?(Hash)
if all_keys_are_number_strings?(webhook_certificates)
super(convert_hash_with_number_string_keys_to_array(webhook_certificates).collect(&:symbolize_keys))
else
raise_validation_error("webhook_certificates must be an array, or a hash where each key is an integer in string format.")
end
elsif !webhook_certificates.nil?
raise_validation_error("webhook_certificates must be an array")
raise_validation_error("webhook_certificates cannot be set using a #{webhook_certificates.class}")
end
end

Expand Down Expand Up @@ -208,6 +217,14 @@ def validate_logging_attributes!
def raise_validation_error(msg)
raise PactBroker::ConfigurationError, msg
end

def set_webhook_attribute_defaults
# can't set a default on this, or anyway config blows up when trying to merge the
# hash from the env vars into an array/nil.
if webhook_certificates.nil?
self.webhook_certificates = []
end
end
end
end
end
11 changes: 11 additions & 0 deletions lib/pact_broker/config/runtime_configuration_coercion_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
module PactBroker
module Config
module RuntimeConfigurationCoercionMethods

def all_keys_are_number_strings?(hash)
hash.keys.all? { | k | k.to_s.to_i.to_s == k } # is an integer as a string
end

def convert_hash_with_number_string_keys_to_array(hash)
hash.keys.collect{ |k| [k, k.to_i]}.sort_by(&:last).collect(&:first).collect do | key |
hash[key]
end
end

def value_to_string_array value, property_name
if value.is_a?(String)
PactBroker::Config::SpaceDelimitedStringList.parse(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ def sensitive_value?(value)
module InstanceMethods
# base_url raises a not implemented error
def log_configuration(logger)
to_source_trace.without("base_url").each_with_object({})do | (key, details), new_hash |
new_hash[key] = details.merge(value: self.send(key.to_sym))
source_info = to_source_trace
(self.class.config_attributes - [:base_url]).collect(&:to_s).each_with_object({})do | (key, details), new_hash |
new_hash[key] = {
value: self.send(key.to_sym),
source: source_info.dig(key, :source) || {:type=>:defaults}
}
end.sort_by { |key, _| key }.each { |key, value| log_config_inner(key, value, logger) }
end

def log_config_inner(key, value, logger)
# TODO fix the source display for webhook_certificates set by environment variables
if !value.has_key? :value
value.sort_by { |inner_key, _| inner_key }.each { |inner_key, inner_value| log_config_inner("#{key}.#{inner_key}", inner_value, logger) }
elsif self.class.sensitive_value?(key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ module Config
expect(subject).to include "database_url=protocol://username:*****@host/database"
end

it "logs values that don't have an initial default, but get set afterward" do
expect(subject).to include "webhook_certificates=[] source={:type=>:defaults}"
end

context "with a database URL with no password" do
let(:initial_values) { { database_password: "foo", database_url: "sqlite:///pact_broker.sqlite3" } }

Expand Down
12 changes: 12 additions & 0 deletions spec/lib/pact_broker/config/runtime_configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ module Config

its(:base_urls) { is_expected.to eq %w[bar wiffle foo blah] }
end

describe "webhook_certificates" do
context "when setting using environment variables with indexes eg PACT_BROKER_WEBHOOK_CERTIFICATES__0__LABEL" do
subject do
runtime_configuration = RuntimeConfiguration.new
runtime_configuration.webhook_certificates = { "0" => { "description" => "cert1", "content" => "abc" }, "1" => { "description" => "cert1", "content" => "abc" } }
runtime_configuration
end

its(:webhook_certificates) { is_expected.to eq [{ description: "cert1", content: "abc" }, { description: "cert1", content: "abc" }] }
end
end
end
end
end

0 comments on commit 82c7a7e

Please sign in to comment.