diff --git a/omnibus/files/private-chef-cookbooks/private-chef/libraries/private_chef.rb b/omnibus/files/private-chef-cookbooks/private-chef/libraries/private_chef.rb index 3437b02862..f6650951a7 100644 --- a/omnibus/files/private-chef-cookbooks/private-chef/libraries/private_chef.rb +++ b/omnibus/files/private-chef-cookbooks/private-chef/libraries/private_chef.rb @@ -476,34 +476,94 @@ def gen_secrets_default(node_name) credentials.delete("postgresql", "sql_user") end - credentials.add("redis_lb", "password", length: 100) - credentials.add("rabbitmq", "password", length: 100) - credentials.add("rabbitmq", "management_password", length: 100) - credentials.add("drbd", "shared_secret", length: 60) - credentials.add("keepalived", "vrrp_instance_password", length: 100) - credentials.add("opscode_erchef", "sql_password", length: 100) - credentials.add("opscode_erchef", "sql_ro_password", length: 100) - # Freeze oc_bifrost superuser_id so it will not be rotated - credentials.add("oc_bifrost", "superuser_id", length: 32, frozen: true) - credentials.add("oc_bifrost", "sql_password", length: 100) - credentials.add("oc_bifrost", "sql_ro_password", length: 100) - credentials.add("oc_id", "secret_key_base", length: 100) - credentials.add("oc_id", "sql_password", length: 100) - credentials.add("oc_id", "sql_ro_password", length: 100) - credentials.add("bookshelf", "access_key_id", length: 40) - credentials.add("bookshelf", "secret_access_key", length: 80) - credentials.add("bookshelf", "sql_password", length: 100) - credentials.add("bookshelf", "sql_ro_password", length: 100) - # First attempt to pull in any configured token, + required_secrets = [ + {group: "postgresql", name: "db_superuser_password", length: 100, set_command: "set-db-superuser-password"}, + {group: "redis_lb", name: "password", length: 100}, + {group: "rabbitmq", name: "password", length: 100}, + {group: "rabbitmq", name: "management_password", length: 100}, + {group: "drbd", name: "shared_secret", length: 60}, + {group: "keepalived", name: "vrrp_instance_password", length: 100}, + {group: "opscode_erchef", name: "sql_password", length: 60}, + {group: "opscode_erchef", name: "sql_ro_password", length: 60}, + {group: "oc_bifrost", name: "superuser_id", length: 32, frozen: true}, + {group: "oc_bifrost", name: "sql_password", length: 100}, + {group: "oc_bifrost", name: "sql_ro_password", length: 100}, + {group: "oc_id", name: "secret_key_base", length: 100}, + {group: "oc_id", name: "sql_password", length: 100}, + {group: "oc_id", name: "sql_ro_password", length: 100}, + {group: "bookshelf", name: "access_key_id", length: 40}, + {group: "bookshelf", name: "secret_access_key", length: 80}, + {group: "bookshelf", name: "sql_password", length: 80}, + {group: "bookshelf", name: "sql_ro_password", length: 80} + ] + + optional_secrets = [ + {group: "ldap", name: "bind_password"}, + {group: "data_collector", name: "token"} + ] + + optional_secrets.each do |secret| + add_secret(secret, false) + end + + required_secrets.each do |secret| + add_secret(secret) + end generate_rabbit_actions_password - migrate_and_check_db_superuser_password - migrate_and_check_ldap_bind_password - migrate_and_check_data_collector_token + save_credentials_to_config if (PrivateChef["insecure_addon_compat"]) credentials.save end + def add_secret(secret_spec, create_if_missing = true) + group = secret_spec[:group] + name = secret_spec[:name] + + config_value = PrivateChef[group][name] + + if config_value + warn_if_cred_mismatch(secret_spec) + credentials.add(group, name, value: config_value, frozen: true, force: true) + elsif create_if_missing + credentials.add(group, name, length: secret_spec[:length], frozen: secret_spec[:frozen]) + end + end + + def warn_if_cred_mismatch(opts) + group = opts[:group] + name = opts[:name] + return if !credentials.exist?(group, name) + + pass_in_config = opts[:config_value] || PrivateChef[group][name] + pass_in_secrets = opts[:secrets_value] || credentials.get(group, name) + command_name = opts[:set_command] || "set-secret #{group} #{name}" + config_key_desc = opts[:config_key_desc] || "#{group}['#{name}']" + + if pass_in_secrets != pass_in_config + warning = < ["bind_password"], + "data_collector" => ["token"], + "rabbitmq" => ["password", "management_password"], + "redis_lb" => ["password"], + "drbd" => ["shared_secret"], + "keepalived" => ["vrrp_instance_password"], + "opscode_erchef" => ["sql_password", "sql_ro_password"], + "oc_bifrost" => ["superuser_id", "sql_password", "sql_ro_password"], + "oc_id" => ["secret_key_base", "sql_password", "sql_ro_password"], + "bookshelf" => ["access_key_id", "secret_access_key", "sql_password", "sql_ro_password"], +} + +add_command_under_category "set-secret", "Secrets Management", "Set or change secret NAME of GROUP", 2 do + group = ARGV[3] + name = ARGV[4] + + unless is_known_credential(group, name) + msg = "chef-server-ctl set-secret: Unknown credential: '#{name}' (group '#{group}')" + STDERR.puts msg + raise SystemExit.new(1, msg) + end + + env_name = "#{group.upcase}_#{name.upcase}" + disp_name = "#{group} #{name}" + password = get_secret(env_name, disp_name, ARGV[5]) + set_secret_(group, name, password) +end + +def is_known_credential(group, name) + return false unless KNOWN_CREDENTIALS[group] + + KNOWN_CREDENTIALS[group].member? name end def confirm_continue!(message) @@ -32,7 +56,7 @@ def confirm_continue!(message) end end -def set_secret(group, key, secret) +def set_secret_(group, key, secret) # TODO(ssd) 2017-03-07: We could just use veil directly here since we already require it other places # in the -ctl commands... require 'mixlib/shellout' @@ -40,8 +64,7 @@ def set_secret(group, key, secret) cmd.run_command end -def get_secret(env_key, prompt='secret') - password_arg = ARGV[3] +def get_secret(env_key, prompt='secret', password_arg = nil) if password_arg password_arg elsif ENV[env_key] diff --git a/omnibus/files/private-chef-ctl-commands/show_secrets.rb b/omnibus/files/private-chef-ctl-commands/show_secrets.rb new file mode 100644 index 0000000000..0c9320e408 --- /dev/null +++ b/omnibus/files/private-chef-ctl-commands/show_secrets.rb @@ -0,0 +1,8 @@ +add_command_under_category "show-secret", "Debug Tools", "Show the value of the given secret in the secret store", 2 do + require 'veil' + + group = ARGV[3] + name = ARGV[4] + veil = Veil::CredentialCollection::ChefSecretsFile.from_file("/etc/opscode/private-chef-secrets.json") + puts veil.get(group, name) +end