This commit is contained in:
Jamil Bou Kheir
2022-02-05 15:42:25 -08:00
parent de578b54fd
commit 1e135cff85
23 changed files with 141 additions and 116 deletions

View File

@@ -25,6 +25,12 @@ repos:
language: system
pass_filenames: false
files: \.ex$
- id: rubocop
name: 'ruby: rubocop'
entry: rubocop
language: system
pass_filenames: false
files: \.rb$
# Standard pre-commit hooks
- repo: https://github.com/pre-commit/pre-commit-hooks

View File

@@ -2,6 +2,4 @@ AllCops:
TargetRubyVersion: 2.7
Exclude:
- "apps/fz_http/assets/node_modules/**/*"
Layout/LineLength:
Max: 120
- "omnibus/cookbooks/firezone/attributes/default.rb"

View File

@@ -56,6 +56,7 @@ version('18.3') { source sha256: 'a6d08eb7df06e749ccaf3049b33ceae617a3c466c
version('18.2') { source sha256: '3944ce41d13fbef1e1e80d7335b2167849e8566581513d5d9226cd211d3d58f9' }
version('18.1') { source sha256: '6b956dda690d3f3bf244249e8d422dd606231cc7229675bf5e34b5ba2ae83e9b' }
# rubocop:disable Metrics/BlockLength
build do
if version.satisfies?('>= 18.3')
# Don't listen on 127.0.0.1/::1 implicitly whenever ERL_EPMD_ADDRESS is given
@@ -145,3 +146,4 @@ build do
make "-j #{workers}", env: env
make 'install', env: env
end
# rubocop:enable Metrics/BlockLength

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
#
@@ -21,6 +22,7 @@ license :project_license
source path: 'cookbooks/firezone'
# rubocop:disable Metrics/BlockLength
build do
cookbooks_path = "#{install_dir}/embedded/cookbooks"
env = with_standard_compiler_flags(with_embedded_path)
@@ -44,17 +46,17 @@ build do
end
block do
open("#{cookbooks_path}/dna.json", 'w') do |file|
File.open("#{cookbooks_path}/dna.json", 'w') do |file|
file.write FFI_Yajl::Encoder.encode(run_list: ['recipe[firezone::default]'])
end
open("#{cookbooks_path}/show-config.json", 'w') do |file|
File.open("#{cookbooks_path}/show-config.json", 'w') do |file|
file.write FFI_Yajl::Encoder.encode(
run_list: ['recipe[firezone::show_config]']
)
end
open("#{cookbooks_path}/solo.rb", 'w') do |file|
File.open("#{cookbooks_path}/solo.rb", 'w') do |file|
file.write <<~SOLO
cookbook_path "#{cookbooks_path}"
cache_path "/var/opt/firezone/cache"
@@ -64,3 +66,5 @@ build do
end
end
end
# rubocop:enable Metrics/BlockLength
# rubocop:enable Naming/FileName

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
#
@@ -44,3 +45,4 @@ build do
# additional omnibus-ctl commands
sync "#{project_dir}/files/default/ctl-commands", "#{install_dir}/embedded/service/omnibus-ctl/"
end
# rubocop:enable Naming/FileName

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
#
@@ -30,3 +31,4 @@ source path: File.expand_path('files/firezone-scripts', Omnibus::Config.project_
build do
copy '*', "#{install_dir}/embedded/bin/"
end
# rubocop:enable Naming/FileName

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
#
@@ -45,3 +46,4 @@ build do
make "-j #{workers}", env: env
make "-j #{workers} install", env: env
end
# rubocop:enable Naming/FileName

View File

@@ -54,6 +54,7 @@ relative_path "ncurses-#{version}"
#
########################################################################
# rubocop:disable Metrics/BlockLength
build do
env = with_standard_compiler_flags(with_embedded_path)
env.delete('CPPFLAGS')
@@ -156,3 +157,4 @@ build do
# Ensure embedded ncurses wins in the LD search path
link "#{install_dir}/embedded/lib/libcurses.so", "#{install_dir}/embedded/lib/libcurses.so.1" if smartos?
end
# rubocop:enable Metrics/BlockLength

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
# Copyright 2012-2015 Chef Software, Inc.
@@ -43,3 +44,4 @@ build do
touch "#{install_dir}/embedded/service/omnibus-ctl/.gitkeep"
end
# rubocop:enable Naming/FileName

View File

@@ -35,7 +35,8 @@ lib_dirs lib_dirs.concat(["#{install_dir}/embedded/lib/engines-1.1"]) if version
# OpenSSL source ships with broken symlinks which windows doesn't allow.
# So skip error checking with `extract: :lax_tar`
if version.satisfies?('> 1.0.2u') && version.satisfies?('< 1.1.0')
# 1.0.2u was the last public release of 1.0.2. Subsequent releases come from a support contract with OpenSSL Software Services
# 1.0.2u was the last public release of 1.0.2. Subsequent releases come from a support contract with OpenSSL
# Software Services
source url: "https://s3.amazonaws.com/chef-releng/openssl/openssl-#{version}.tar.gz", extract: :lax_tar
else
# As of 2020-09-09 even openssl-1.0.0.tar.gz can be downloaded from /source/openssl-VERSION.tar.gz
@@ -55,6 +56,7 @@ version('1.0.2i') { source sha256: '9287487d11c9545b6efb287cdb70535d4e9b284dd10d
relative_path "openssl-#{version}"
# rubocop:disable Metrics/BlockLength
build do
env = with_standard_compiler_flags(with_embedded_path)
if aix?
@@ -172,3 +174,4 @@ build do
end
make "-j #{workers} install", env: env
end
# rubocop:enable Metrics/BlockLength

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
#
@@ -40,3 +41,4 @@ build do
make env: env
make 'install', env: env
end
# rubocop:enable Naming/FileName

View File

@@ -38,6 +38,7 @@ lib_dirs lib_dirs.concat ["#{install_dir}/embedded/lib/perl5/**"]
relative_path "perl-#{version}"
# rubocop:disable Metrics/BlockLength
build do
env = with_standard_compiler_flags(with_embedded_path)
@@ -74,3 +75,4 @@ build do
# us skip install the manpages
make 'install.perl', env: env
end
# rubocop:enable Metrics/BlockLength

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
#
@@ -62,3 +63,4 @@ build do
# exit with byte conversion errors.
copy "#{project_dir}/glib/glib/libcharset/charset.alias", "#{install_dir}/embedded/lib/charset.alias" if openbsd?
end
# rubocop:enable Naming/FileName

View File

@@ -104,6 +104,7 @@ else # including linux
end
end
# rubocop:disable Metrics/BlockLength
build do
env['CFLAGS'] << ' -fno-omit-frame-pointer'
@@ -183,7 +184,8 @@ build do
patch source: 'ruby-aix-vm-core.patch', plevel: 1, env: patch_env
# per IBM, just help ruby along on what it's running on
configure_command << '--host=powerpc-ibm-aix6.1.0.0 --target=powerpc-ibm-aix6.1.0.0 --build=powerpc-ibm-aix6.1.0.0 --enable-pthread'
configure_command << '--host=powerpc-ibm-aix6.1.0.0 --target=powerpc-ibm-aix6.1.0.0 --build=powerpc-ibm-aix6'\
'.1.0.0 --enable-pthread'
elsif freebsd?
# Disable optional support C level backtrace support. This requires the
@@ -209,7 +211,8 @@ build do
configure_command << ' debugflags=-g'
else
# TODO: Consider pulling in Gitlab's OhaiHelper if raspberry_pi is needed
# configure_command << %w(host target build).map { |w| "--#{w}=#{OhaiHelper.gcc_target}" } if OhaiHelper.raspberry_pi?
# configure_command << %w(host target build).map { |w| "--#{w}=#{OhaiHelper.gcc_target}" } if \
# OhaiHelper.raspberry_pi?
configure_command << "--with-opt-dir=#{install_dir}/embedded"
end
@@ -240,3 +243,4 @@ build do
end
end
end
# rubocop:enable Metrics/BlockLength

View File

@@ -40,8 +40,11 @@ build do
env = with_standard_compiler_flags(with_embedded_path)
# Put runit where we want it, not where they tell us to
command "sed -i -e \"s/^char\\ \\*varservice\\ \\=\\\"\\/service\\/\\\";$/char\\ \\*varservice\\ \\=\\\"#{install_dir.gsub('/', '\\/')}\\/service\\/\\\";/\" sv.c",
env: env
# rubocop:disable Style/StringConcatenation
cmd = 'sed -i -e "s/^char\ \*varservice\ \=\"\/service\/\";$/char\ \*varservice\ \=\"' + \
install_dir.gsub('/', '\\/') + '\/service\/\";/" sv.c'
# rubocop:enable Style/StringConcatenation
command cmd, env: env
# TODO: the following is not idempotent
command 'sed -i -e s:-static:: Makefile', env: env

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
# Copyright 2021 Firezone
@@ -41,3 +42,4 @@ build do
make "-j #{workers}", env: env
make "-j #{workers} install", env: env
end
# rubocop:enable Naming/FileName

View File

@@ -1,3 +1,4 @@
# rubocop:disable Naming/FileName
# frozen_string_literal: true
# Policyfile.rb - Describe how you want Chef Infra Client to build your system.
@@ -16,3 +17,4 @@ run_list 'firezone::default'
# Specify a custom source for a single cookbook:
cookbook 'firezone', path: '.'
# rubocop:enable Naming/FileName

View File

@@ -9,25 +9,28 @@ desc = <<~DESC
Resets the password for admin with email specified by default['firezone']['admin_email'] or creates a new admin if that email doesn't exist.
DESC
# rubocop:disable Metrics/MethodLength
def capture
telemetry_file = '/var/opt/firezone/cache/telemetry_id'
if File.exist?(telemetry_file)
telemetry_id = File.read(telemetry_file)
if telemetry_id
uri = URI('https://telemetry.firez.one/capture/')
data = {
api_key: 'phc_ubuPhiqqjMdedpmbWpG2Ak3axqv5eMVhFDNBaXl9UZK',
event: 'firezone-ctl create-or-reset-admin',
properties: {
distinct_id: telemetry_id
}
}
unless File.exist?('/var/opt/firezone/.disable_telemetry') || ENV['TELEMETRY_ENABLED'] == 'false'
Net::HTTP.post(uri, data.to_json, 'Content-Type' => 'application/json')
end
end
end
return unless File.exist?(telemetry_file)
telemetry_id = File.read(telemetry_file)
return unless telemetry_id
uri = URI('https://telemetry.firez.one/capture/')
data = {
api_key: 'phc_ubuPhiqqjMdedpmbWpG2Ak3axqv5eMVhFDNBaXl9UZK',
event: 'firezone-ctl create-or-reset-admin',
properties: {
distinct_id: telemetry_id
}
}
return if File.exist?('/var/opt/firezone/.disable_telemetry') || ENV['TELEMETRY_ENABLED'] == 'false'
Net::HTTP.post(uri, data.to_json, 'Content-Type' => 'application/json')
end
# rubocop:enable Metrics/MethodLength
add_command_under_category 'create-or-reset-admin', 'general', desc, 2 do
command = %W(

View File

@@ -5,25 +5,28 @@ require 'uri'
require 'net/http'
require 'json'
# rubocop:disable Metrics/MethodLength
def capture
telemetry_file = '/var/opt/firezone/cache/telemetry_id'
if File.exist?(telemetry_file)
telemetry_id = File.read(telemetry_file)
if telemetry_id
uri = URI('https://telemetry.firez.one/capture/')
data = {
api_key: 'phc_ubuPhiqqjMdedpmbWpG2Ak3axqv5eMVhFDNBaXl9UZK',
event: 'firezone-ctl create-or-reset-admin',
properties: {
distinct_id: telemetry_id
}
}
unless File.exist?('/var/opt/firezone/.disable_telemetry') || ENV['TELEMETRY_ENABLED'] == 'false'
Net::HTTP.post(uri, data.to_json, 'Content-Type' => 'application/json')
end
end
end
return unless File.exist?(telemetry_file)
telemetry_id = File.read(telemetry_file)
return unless telemetry_id
uri = URI('https://telemetry.firez.one/capture/')
data = {
api_key: 'phc_ubuPhiqqjMdedpmbWpG2Ak3axqv5eMVhFDNBaXl9UZK',
event: 'firezone-ctl create-or-reset-admin',
properties: {
distinct_id: telemetry_id
}
}
return if File.exist?('/var/opt/firezone/.disable_telemetry') || ENV['TELEMETRY_ENABLED'] == 'false'
Net::HTTP.post(uri, data.to_json, 'Content-Type' => 'application/json')
end
# rubocop:enable Metrics/MethodLength
add_command_under_category 'reconfigure', 'general', 'Reconfigure the application.', 2 do
status = run_chef("#{base_path}/embedded/cookbooks/dna.json", '--chef-license=accept')

View File

@@ -12,6 +12,7 @@ class Firezone
class IncompleteConfig < StandardError; end
class IncompatibleConfig < StandardError; end
# rubocop:disable Metrics/MethodLength
def self.load_or_create!(filename, node)
create_directory!(filename)
if File.exist?(filename)
@@ -30,6 +31,7 @@ class Firezone
rescue Errno::ENOENT => e
Chef::Log.warn "Could not create #{filename}: #{e}"
end
# rubocop:enable Metrics/MethodLength
def self.locale_variables
<<~LOCALE
@@ -56,7 +58,7 @@ class Firezone
create_directory!(filename)
if File.exist?(filename)
node.consume_attributes(
'firezone' => Chef::JSONCompat.from_json(open(filename).read)
'firezone' => Chef::JSONCompat.from_json(File.read(filename))
)
end
rescue StandardError => e
@@ -65,36 +67,14 @@ class Firezone
# Read in the filename (as JSON) and add its attributes to the node object.
# If it doesn't exist, create it with generated secrets.
# rubocop:disable Metrics/MethodLength
def self.load_or_create_secrets!(filename, node)
create_directory!(filename)
secrets = Chef::JSONCompat.from_json(File.open(filename).read)
secrets = Chef::JSONCompat.from_json(File.read(filename))
node.consume_attributes('firezone' => secrets)
rescue Errno::ENOENT
begin
secret_key_base =
node.dig('firezone', 'secret_key_base') || SecureRandom.base64(48)
live_view_signing_salt =
node.dig('firezone', 'live_view_signing_salt') || SecureRandom.base64(24)
cookie_signing_salt =
node.dig('firezone', 'cookie_signing_salt') || SecureRandom.base64(6)
wireguard_private_key =
node.dig('firezone',
'wireguard_private_key') || `#{node['firezone']['install_directory']}/embedded/bin/wg genkey`.chomp
database_encryption_key =
node.dig('firezone', 'database_encryption_key') || SecureRandom.base64(32)
default_admin_password =
node.dig('firezone', 'default_admin_password') || SecureRandom.base64(8)
secrets = {
'secret_key_base' => secret_key_base,
'live_view_signing_salt' => live_view_signing_salt,
'cookie_signing_salt' => cookie_signing_salt,
'wireguard_private_key' => wireguard_private_key,
'database_encryption_key' => database_encryption_key,
'default_admin_password' => default_admin_password
}
open(filename, 'w') do |file|
File.open(filename, 'w') do |file|
file.puts Chef::JSONCompat.to_json_pretty(secrets)
end
Chef::Log.info("Creating secrets file #{filename}")
@@ -104,49 +84,35 @@ class Firezone
node.consume_attributes('firezone' => secrets)
end
# rubocop:enable Metrics/MethodLength
def self.secrets(node)
{
'secret_key_base' => node.dig('firezone', 'secret_key_base') || SecureRandom.base64(48),
'live_view_signing_salt' => node.dig('firezone', 'live_view_signing_salt') || SecureRandom.base64(24),
'cookie_signing_salt' => node.dig('firezone', 'cookie_signing_salt') || SecureRandom.base64(6),
'wireguard_private_key' => node.dig('firezone', 'wireguard_private_key') || \
`#{node['firezone']['install_directory']}/embedded/bin/wg genkey`.chomp,
'database_encryption_key' => node.dig('firezone', 'database_encryption_key') || SecureRandom.base64(32),
'default_admin_password' => node.dig('firezone', 'default_admin_password') || SecureRandom.base64(8)
}
end
def self.audit_config(config)
audit_s3_config(config)
audit_fips_config(config)
end
def self.audit_s3_config(config)
required_s3_vars = %w[s3_bucket s3_region].freeze
any_required_s3_vars = required_s3_vars.any? { |key| !config[key].nil? }
all_required_s3_vars = required_s3_vars.all? { |key| !(config[key].nil? || config[key].empty?) }
if any_required_s3_vars && !all_required_s3_vars
raise IncompleteConfig,
"Got some, but not all, of the required S3 configs. Must provide #{required_s3_vars} to configure cookbook storage in an S3 bucket."
end
static_s3_creds = %w[s3_access_key_id s3_secret_access_key].freeze
any_static_s3_creds = static_s3_creds.any? { |key| !config[key].nil? }
all_static_s3_creds = static_s3_creds.all? { |key| !(config[key].nil? || config[key].empty?) }
if any_static_s3_creds && !all_static_s3_creds
raise IncompleteConfig,
"Got some, but not all, of AWS user credentials. To access an S3 bucket with IAM user credentials, provide #{static_s3_creds}. To use an IAM role, do not set these."
end
if config['s3_bucket'] =~ /\./ &&
(config['s3_domain_style'] != ':s3_path_url' || config['s3_region'] != 'us-east-1')
raise IncompatibleConfig,
"Incompatible S3 bucket settings. If the bucket name contains periods, the bucket must be in us-east-1 and the domain style must be :s3_path_url.\nAmazon recommends against periods in bucket names. See: https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html"
end
end
def self.audit_fips_config(config)
unless built_with_fips?(config['install_directory'])
if fips_enabled_in_kernel?
raise IncompatibleConfig,
'Detected FIPS is enabled in the kernel, but FIPS is not supported by this installer.'
end
if config['fips_enabled']
raise IncompatibleConfig,
'You have enabled FIPS in your configuration, but FIPS is not supported by this installer.'
end
return if built_with_fips?(config['install_directory'])
if fips_enabled_in_kernel?
raise IncompatibleConfig,
'Detected FIPS is enabled in the kernel, but FIPS is not supported by this installer.'
end
return unless config['fips_enabled']
raise IncompatibleConfig,
'You have enabled FIPS in your configuration, but FIPS is not supported by this installer.'
end
def self.built_with_fips?(install_directory)
@@ -158,6 +124,8 @@ class Firezone
(File.exist?(fips_path) && File.read(fips_path).chomp != '0')
end
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def self.maybe_turn_on_fips(node)
# the compexity of this method is currently needed to figure out what words to display
# to the poor human who has to deal with FIPS
@@ -172,16 +140,21 @@ class Firezone
node.normal['firezone']['fips_enabled'] = Firezone::Config.fips_enabled_in_kernel?
if node['firezone']['fips_enabled']
Chef::Log.warn('Detected FIPS-enabled kernel; enabling FIPS 140-2 for Firezone services.')
Chef::Log.warn('fips_enabled was set to false; ignoring this and setting to true or else Firezone services will fail with crypto errors.')
Chef::Log.warn('fips_enabled was set to false; ignoring this and setting to true or else Firezone services'\
' will fail with crypto errors.')
end
when true
Chef::Log.warn('Overriding FIPS detection: FIPS 140-2 mode is ON.')
else
node.normal['firezone']['fips_enabled'] = true
Chef::Log.warn('fips_enabled is set to something other than boolean true/false; assuming FIPS mode should be enabled.')
Chef::Log.warn(
'fips_enabled is set to something other than boolean true/false; assuming FIPS mode should be enabled.'
)
Chef::Log.warn('Overriding FIPS detection: FIPS 140-2 mode is ON.')
end
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
# Take some node attributes and return them on each line as:
#
@@ -199,6 +172,8 @@ class Firezone
end
end
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def self.app_env(attributes, reject = [])
attributes = attributes.reject { |k| reject.include?(k) }
@@ -255,6 +230,8 @@ class Firezone
env
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
def self.create_directory!(filename)
dir = File.dirname(filename)

View File

@@ -44,8 +44,9 @@ unless /[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/.match?(node['firezone']['tele
node.default['firezone']['telemetry_id'] = SecureRandom.uuid
end
node.default['firezone']['wireguard_public_key'] =
`echo '#{node['firezone']['wireguard_private_key']}' | #{node['firezone']['install_directory']}/embedded/bin/wg pubkey`.chomp
pkey = node['firezone']['wireguard_private_key']
wg = "#{node['firezone']['install_directory']}/embedded/bin/wg"
node.default['firezone']['wireguard_public_key'] = `echo '#{pkey}' | #{wg} pubkey`.chomp
Firezone::Config.audit_config(node['firezone'])
Firezone::Config.maybe_turn_on_fips(node)

View File

@@ -71,7 +71,8 @@ template "#{node['firezone']['var_directory']}/etc/logrotate.d/nginx" do
variables(
'log_directory' => node['firezone']['nginx']['log_directory'],
'log_rotation' => node['firezone']['nginx']['log_rotation'],
'postrotate' => "#{node['firezone']['install_directory']}/embedded/sbin/nginx -c #{node['firezone']['nginx']['directory']}/nginx.conf -s reopen",
'postrotate' => "#{node['firezone']['install_directory']}/embedded/sbin/nginx -c "\
"#{node['firezone']['nginx']['directory']}/nginx.conf -s reopen",
'owner' => 'root',
'group' => 'root'
)

View File

@@ -14,10 +14,10 @@
#
# Uncomment this line to change the default base directory to "local"
# -------------------------------------------------------------------
if ENV["CI"]
base_dir("/opt/runner/omnibus-local")
if ENV['CI']
base_dir('/opt/runner/omnibus-local')
else
base_dir("/tmp/omnibus-local")
base_dir('/tmp/omnibus-local')
end
#
# Alternatively you can tune the individual values
@@ -59,8 +59,8 @@ append_timestamp false
# Windows architecture defaults
# ------------------------------
windows_arch if %w[x86 x64].include?((ENV["OMNIBUS_WINDOWS_ARCH"] || "").downcase)
ENV["OMNIBUS_WINDOWS_ARCH"].downcase.to_sym
if %w[x86 x64].include?((ENV['OMNIBUS_WINDOWS_ARCH'] || '').downcase)
windows_arch(ENV['OMNIBUS_WINDOWS_ARCH'].downcase.to_sym)
else
:x86
windows_arch(:x86)
end