Farmbot-Web-App/app/lib/rmq_config_writer.rb

64 lines
2.9 KiB
Ruby

# SCENARIO: RabbitMQ's HTTP auth backend plugin uses *files* instead of ENV vars
# for configuration.
# PROBLEM: 1. This is the only service that requires such configuration. All
# other services are configured in one place- the `.env` file.
# 2. When using files, it's easy to forget that the file needs updates.
# Refreshing the .env file will NOT refresh rabbit configs.
# 3. This adds an additional step to server provisioning procedures.
# SOLUTION: Since Rabbit requires the API to load ahead of itself, we can create
# the configuration on-the-fly when the API boots up by using custom
# ENV vars and string templates. Essentially, the API overwrites the
# contents of rabbitmq.conf every time it boots up, eliminating the
# need to refresh/create cumbersome config files.
class RmqConfigWriter
CONFIG_PATH = "docker_volumes/rabbit"
CONFIG_FILENAME = "farmbot_rmq_config.conf"
CONFIG_OUTPUT = "#{CONFIG_PATH}/#{CONFIG_FILENAME}"
NO_API_HOST = "\nYou MUST set API_HOST to a real IP address or " +
"domain name (not localhost).\n" +
"API_PORT is also mandatory."
PROTO = ENV["FORCE_SSL"] ? "https:" : "http:"
ADMIN_PASSWORD = ENV["ADMIN_PASSWORD"]
CFG_DATA = { admin_password: ADMIN_PASSWORD,
fully_formed_url: PROTO + ($API_URL || "") }
ENV_WARNING = "Warning: ENV[\"ADMIN_PASSWORD\"] not set. If you are not "\
"using 3rd party MQTT hosting, please set this value and "\
"re-build the server image."
BAD_PASSWORD = "Password is not strong enough. Use more characters"
TEMPLATE = <<~END
# THIS FILE WAS GENERATED BY THE `RmqConfigWriter` CLASS IN THE RAILS APP
# == DO NOT ATTEMPT TO MODIFY MANUALLY - IT WILL BE OVERWRITTEN ===
auth_backends.1 = cache
auth_cache.cache_ttl = 600000
auth_cache.cached_backend = http
auth_http.http_method = post
auth_http.resource_path = %{fully_formed_url}/api/rmq/resource
auth_http.topic_path = %{fully_formed_url}/api/rmq/topic
auth_http.user_path = %{fully_formed_url}/api/rmq/user
auth_http.vhost_path = %{fully_formed_url}/api/rmq/vhost
default_user = admin
default_user_tags.administrator = true
default_user_tags.management = true
default_pass = %{admin_password}
mqtt.allow_anonymous = false
END
def self.do_render
raise BAD_PASSWORD if ADMIN_PASSWORD.length < 5
FileUtils.mkdir_p CONFIG_PATH
File.open(CONFIG_OUTPUT, "w+") { |f| f.write(TEMPLATE % CFG_DATA) }
end
def self.dont_render
puts ENV_WARNING
end
def self.env_ok?
ADMIN_PASSWORD && ENV.key?("API_HOST") && ENV.key?("API_PORT")
end
def self.render
env_ok? ? do_render : dont_render
end
end