Skip to content

Commit

Permalink
Log on Conjur config permission issues
Browse files Browse the repository at this point in the history
  • Loading branch information
micahlee committed Feb 7, 2023
1 parent 38d7ecc commit b8617e3
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 50 deletions.
4 changes: 3 additions & 1 deletion bin/conjur-cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@
Anyway::Settings.default_config_path = "/etc/conjur/config"

begin
conjur_config = Conjur::ConjurConfig.new
conjur_config = Conjur::ConjurConfig.new(
logger: Logger.new($stderr)
)
rescue Conjur::ConfigValidationError => e
$stderr.puts e
exit 1
Expand Down
15 changes: 4 additions & 11 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
# require "sprockets/railtie"
# require "rails/test_unit/railtie"

require 'logger'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
Expand Down Expand Up @@ -47,15 +49,15 @@ class Application < Rails::Application
Sequel.extension(:core_extensions, :postgres_schemata)
Sequel::Model.db.extension(:pg_array, :pg_inet)
end

#The default connection pool does not support closing connections.
# We must be able to close connections on demand to clear the connection cache
# after policy loads [cyberark/conjur#2584](https://github.com/cyberark/conjur/pull/2584)
# The [ShardedThreadedConnectionPool](https://www.rubydoc.info/github/jeremyevans/sequel/Sequel/ShardedThreadedConnectionPool) does support closing connections on-demand.
# Sequel is configured to use the ShardedThreadedConnectionPool by setting the servers configuration on
# the database connection [docs](https://www.rubydoc.info/github/jeremyevans/sequel/Sequel%2FShardedThreadedConnectionPool:servers)
config.sequel.servers = {}

config.encoding = "utf-8"
config.active_support.escape_html_entities_in_json = true

Expand All @@ -73,14 +75,5 @@ class Application < Rails::Application
config.anyway_config.future.unwrap_known_environments = true

config.anyway_config.default_config_path = "/etc/conjur/config"

# Create a single instance of the ConjurConfig object for this process that
# loads configuration on server startup. This prevents config values from
# being loaded fresh every time a ConjurConfig object is instantiated, which
# could lead to inconsistent behavior.
#
# We create this in application.rb instead of an initializer so that it's
# guaranteed to be available for other initializers to use.
config.conjur_config = Conjur::ConjurConfig.new
end
end
12 changes: 12 additions & 0 deletions config/initializers/conjur_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Rails.application.configure do
# Create a single instance of the ConjurConfig object for this process that
# loads configuration on server startup. This prevents config values from
# being loaded fresh every time a ConjurConfig object is instantiated, which
# could lead to inconsistent behavior.
#
# We create this in application.rb instead of an initializer so that it's
# guaranteed to be available for other initializers to use.
config.conjur_config = Conjur::ConjurConfig.new(
logger: Rails.logger
)
end
76 changes: 74 additions & 2 deletions lib/conjur/conjur_config.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Conjur::ConjurConfig is also used in the conjurctl executable, so we cannot
# rely on Rails autoloading to make the `Anyway::Config` constant available.
require 'anyway_config'
require 'logger'

module Conjur
# We are temporarily avoiding hooking into the application error system
Expand Down Expand Up @@ -33,8 +34,21 @@ class ConjurConfig < Anyway::Config
extensions: []
)

def initialize(*args)
super(*args)
def initialize(
*args,
logger: Rails.logger,
**kwargs
)
# The permissions checks emit log messages, so we need to initialize the
# logger before verifying permissions.
@logger = logger

# First verify that we have the permissions necessary to read the config
# file.
verify_config_permissions

# Initialize Anyway::Config
super(*args, **kwargs)

# If the config file is not a valid YAML document, we want
# to raise a user-friendly ConfigValidationError rather than
Expand Down Expand Up @@ -101,6 +115,64 @@ def extensions=(val)

private

def verify_config_permissions
# Derived from:
# https://github.com/palkan/anyway_config/blob/83d79ccaf5619889c07c8ecdf8d66dcb22c9dc05/lib/anyway/config.rb#L358
config_path = resolve_config_path(
self.class.config_name,
self.class.env_prefix
)

config_dir = File.dirname(config_path)

# It may be acceptable for the config directory to not exist, so this is
# a log message for debugging the Conjur config, rather than alerting the
# user to an issue.
unless File.directory?(config_dir)
@logger.debug(
"Conjur config directory doesn't exist or has " \
"insufficient permission to list it: #{config_dir}"
)
return
end

# If the config direct does exist, we want to alert the user if the
# permissions will prevent Conjur from reading a config file in that
# directory.
unless File.executable?(config_dir)
@logger.warn(
"Conjur config directory exists but is missing " \
"search/execute permission required to list the config file: " \
"#{config_dir}"
)
return
end

# Similar to the directory, if the config file doesn't exist, this becomes
# debugging information.
unless File.file?(config_path)
@logger.debug(
"Conjur config file doesn't exist or has insufficient " \
"permission to list it: #{config_path}"
)
return
end

# If the file exists but we can detect it's not readable, let the user
# know. Conjur will also fail to start in this configuration.
unless File.readable?(config_path)
@logger.warn(
"Conjur config file exists but has insufficient permission to " \
"read it: #{config_path}"
)
return
end

# If we don't detect any issue, log where the config file is being read
# from.
@logger.info("Loading Conjur config file: #{config_path}")
end

def str_to_list(val)
val.is_a?(String) ? val.split(',') : val
end
Expand Down
8 changes: 4 additions & 4 deletions spec/conjurctl/configuration_show_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"conjurctl configuration show --output invalid"
)

expect(stderr).to eq(
"error: Unknown configuration output format 'invalid'\n"
expect(stderr).to include(
"error: Unknown configuration output format 'invalid'"
)
end

Expand All @@ -43,8 +43,8 @@
"CONJUR_TRUSTED_PROXIES=boop conjurctl configuration show"
)

expect(stderr).to eq(
"Invalid values for configured attributes: trusted_proxies\n"
expect(stderr).to include(
"Invalid values for configured attributes: trusted_proxies"
)

expect(status.exitstatus).to eq(1)
Expand Down
Loading

0 comments on commit b8617e3

Please sign in to comment.