Class: Chef::Knife::Bootstrap
- Inherits:
-
Chef::Knife
- Object
- Chef::Knife
- Chef::Knife::Bootstrap
- Includes:
- DataBagSecretOptions, LicenseAcceptance::CLIFlags::MixlibCLI
- Defined in:
- lib/chef/knife/bootstrap.rb,
lib/chef/knife/bootstrap/client_builder.rb,
lib/chef/knife/bootstrap/train_connector.rb,
lib/chef/knife/bootstrap/chef_vault_handler.rb
Defined Under Namespace
Classes: ChefVaultHandler, ClientBuilder, RemoteExecutionFailed, TrainConnector
Constant Summary
Constants inherited from Chef::Knife
CHEF_ORGANIZATION_MANAGEMENT, OFFICIAL_PLUGINS, OPSCODE_HOSTED_CHEF_ACCESS_CONTROL
Instance Attribute Summary collapse
-
#connection ⇒ Object
readonly
Returns the value of attribute connection.
Attributes inherited from Chef::Knife
Instance Method Summary collapse
-
#base_opts ⇒ Object
Common configuration for all protocols.
-
#bootstrap_command(remote_path) ⇒ Object
build the command string for bootrapping.
-
#bootstrap_context ⇒ Object
Establish bootstrap context for template rendering.
-
#bootstrap_template ⇒ String
The CLI specific bootstrap template or the default.
-
#check_license ⇒ Object
Determine if we need to accept the Chef Infra license locally in order to successfully bootstrap the remote node.
- #chef_vault_handler ⇒ Object
- #client_builder ⇒ Object
-
#config_value(key, fallback_key = nil, default = nil) ⇒ Object
This is for deprecating config options.
- #connect! ⇒ Object
-
#connection_opts(reset: false) ⇒ Object
host via train.
-
#connection_protocol ⇒ Object
url values override CLI flags, if you provide both we’ll use the one that you gave in the URL.
-
#default_bootstrap_template ⇒ String
The default bootstrap template to use to bootstrap a server.
- #do_connect(conn_options) ⇒ Object
- #find_template ⇒ Object
- #first_boot_attributes ⇒ Object
-
#force_ssh_password_opts(password) ⇒ Object
Config overrides to force password auth.
- #force_winrm_password_opts(password) ⇒ Object
- #gateway_opts ⇒ Object
- #handle_ssh_error(e) ⇒ Object
- #host_descriptor ⇒ Object
- #host_verify_opts ⇒ Object
- #perform_bootstrap(remote_bootstrap_script_path) ⇒ Object
-
#plugin_create_instance! ⇒ TrueClass
Create the server that we will bootstrap, if necessary.
-
#plugin_finalize ⇒ void
Perform any teardown or cleanup necessary by the plugin.
-
#plugin_setup! ⇒ TrueClass
Perform any setup necessary by the plugin.
-
#plugin_validate_options! ⇒ TrueClass
Validate any additional options.
- #register_client ⇒ Object
- #render_template ⇒ Object
- #run ⇒ Object
- #secret ⇒ Object
-
#server_name ⇒ String
The server_name is the DNS or IP we are going to connect to, it is not necessarily the node name, the fqdn, or the hostname of the server.
- #ssh? ⇒ Boolean
-
#ssh_gateway ⇒ Object
SSH Authentication.
- #ssh_identity_opts ⇒ Object
- #ssh_opts ⇒ Object
-
#sudo_opts ⇒ Object
use_sudo - tells bootstrap to use the sudo command to run bootstrap use_sudo_password - tells bootstrap to use the sudo command to run bootstrap and to use the password specified with –password TODO: I’d like to make our sudo options sane: –sudo (bool) - use sudo –sudo-password PASSWORD (default: :password) - use this password for sudo –sudo-options “opt,opt,opt” to pass into sudo –sudo-command COMMAND sudo command other than sudo REVIEW NOTE: knife bootstrap did not pull sudo values from Chef::Config, should we change that for consistency?.
- #upload_bootstrap(content) ⇒ Object
-
#validate_first_boot_attributes! ⇒ Object
Fail if both first_boot_attributes and first_boot_attributes_from_file are set.
-
#validate_name_args! ⇒ Object
fail if the server_name is nil.
-
#validate_policy_options! ⇒ TrueClass
Ensure options are valid by checking policyfile values.
-
#validate_protocol! ⇒ TrueClass
Ensure a valid protocol is provided for target host connection.
-
#validate_winrm_transport_opts! ⇒ Object
Fail if using plaintext auth without ssl because this can expose keys in plaintext on the wire.
-
#warn_on_short_session_timeout ⇒ Object
If session_timeout is too short, it is likely a holdover from “–winrm-session-timeout” which used minutes as its unit, instead of seconds.
- #winrm? ⇒ Boolean
- #winrm_auth_method ⇒ Object
- #winrm_opts ⇒ Object
- #winrm_warn_no_ssl_verification ⇒ Object
Methods included from DataBagSecretOptions
#encryption_secret_provided?, #encryption_secret_provided_ignore_encrypt_flag?, included, #read_secret, #validate_secrets
Methods included from EncryptedDataBagItem::CheckEncrypted
Methods inherited from Chef::Knife
#api_key, #apply_computed_config, category, chef_config_dir, common_name, #config_file_defaults, #config_file_settings, config_loader, #config_source, #configure_chef, #create_object, #delete_object, dependency_loaders, deps, #format_rest_error, guess_category, #humanize_exception, #humanize_http_exception, inherited, #initialize, list_commands, load_commands, load_config, load_deps, #maybe_setup_fips, #merge_configs, msg, #noauth_rest, #parse_options, reset_config_loader!, reset_subcommands!, #rest, run, #run_with_pretty_exceptions, #server_url, #show_usage, snake_case_name, subcommand_category, subcommand_class_from, subcommand_files, subcommand_loader, subcommands, subcommands_by_category, #test_mandatory_field, ui, unnamed?, use_separate_defaults?, #username
Methods included from Mixin::ConvertToClassName
#constantize, #convert_to_class_name, #convert_to_snake_case, #filename_to_qualified_string, #normalize_snake_case_name, #snake_case_basename
Constructor Details
This class inherits a constructor from Chef::Knife
Instance Attribute Details
#connection ⇒ Object (readonly)
Returns the value of attribute connection.
403 404 405 |
# File 'lib/chef/knife/bootstrap.rb', line 403 def connection @connection end |
Instance Method Details
#base_opts ⇒ Object
Common configuration for all protocols
893 894 895 896 897 898 899 900 901 902 903 904 |
# File 'lib/chef/knife/bootstrap.rb', line 893 def base_opts port = config_for_protocol(:port) user = config_for_protocol(:user) {}.tap do |opts| opts[:logger] = Chef::Log opts[:password] = config[:connection_password] if config.key?(:connection_password) opts[:user] = user if user opts[:max_wait_until_ready] = config[:max_wait].to_f unless config[:max_wait].nil? # TODO - when would we need to provide rdp_port vs port? Or are they not mutually exclusive? opts[:port] = port if port end end |
#bootstrap_command(remote_path) ⇒ Object
build the command string for bootrapping
1078 1079 1080 1081 1082 1083 1084 |
# File 'lib/chef/knife/bootstrap.rb', line 1078 def bootstrap_command(remote_path) if connection.windows? "cmd.exe /C #{remote_path}" else "sh #{remote_path}" end end |
#bootstrap_context ⇒ Object
Establish bootstrap context for template rendering. Requires connection to be a live connection in order to determine the correct platform.
518 519 520 521 522 523 524 525 526 527 |
# File 'lib/chef/knife/bootstrap.rb', line 518 def bootstrap_context @bootstrap_context ||= if connection.windows? require_relative "core/windows_bootstrap_context" Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config, secret) else require_relative "core/bootstrap_context" Knife::Core::BootstrapContext.new(config, config[:run_list], Chef::Config, secret) end end |
#bootstrap_template ⇒ String
Returns The CLI specific bootstrap template or the default.
474 475 476 477 |
# File 'lib/chef/knife/bootstrap.rb', line 474 def bootstrap_template # Allow passing a bootstrap template or use the default config[:bootstrap_template] || default_bootstrap_template end |
#check_license ⇒ Object
Determine if we need to accept the Chef Infra license locally in order to successfully bootstrap the remote node. Remote ‘chef-client’ run will fail if it is >= 15 and the license is not accepted locally.
434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/chef/knife/bootstrap.rb', line 434 def check_license Chef::Log.debug("Checking if we need to accept Chef license to bootstrap node") version = config[:bootstrap_version] || Chef::VERSION.split(".").first acceptor = LicenseAcceptance::Acceptor.new(logger: Chef::Log, provided: Chef::Config[:chef_license]) if acceptor.license_required?("chef", version) Chef::Log.debug("License acceptance required for chef version: #{version}") license_id = acceptor.id_from_mixlib("chef") acceptor.check_and_persist(license_id, version) Chef::Config[:chef_license] ||= acceptor.acceptance_value end end |
#chef_vault_handler ⇒ Object
425 426 427 428 429 430 |
# File 'lib/chef/knife/bootstrap.rb', line 425 def chef_vault_handler @chef_vault_handler ||= Chef::Knife::Bootstrap::ChefVaultHandler.new( config: config, ui: ui ) end |
#client_builder ⇒ Object
417 418 419 420 421 422 423 |
# File 'lib/chef/knife/bootstrap.rb', line 417 def client_builder @client_builder ||= Chef::Knife::Bootstrap::ClientBuilder.new( chef_config: Chef::Config, config: config, ui: ui ) end |
#config_value(key, fallback_key = nil, default = nil) ⇒ Object
This is for deprecating config options. The fallback_key can be used to pull an old knife config option out of the config file when the cli value has been renamed. This is different from the deprecated cli values, since these are for config options that have no corresponding cli value.
DO NOT USE - this whole API is considered deprecated
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 |
# File 'lib/chef/knife/bootstrap.rb', line 1056 def config_value(key, fallback_key = nil, default = nil) Chef.deprecated(:knife_bootstrap_apis, "Use of config_value without a fallback_key is deprecated. Knife plugin authors should access the config hash directly, which does correct merging of cli and config options.") if fallback_key.nil? if config.key?(key) # the first key is the primary key so we check the merged hash first config[key] elsif config.key?(fallback_key) # we get the old config option here (the deprecated cli option shouldn't exist) config[fallback_key] else default end end |
#connect! ⇒ Object
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 |
# File 'lib/chef/knife/bootstrap.rb', line 604 def connect! ui.info("Connecting to #{ui.color(server_name, :bold)}") opts ||= connection_opts.dup do_connect(opts) rescue Train::Error => e # We handle these by message text only because train only loads the # transports and protocols that it needs - so the exceptions may not be defined, # and we don't want to require files internal to train. if e. =~ /fingerprint (\S+) is unknown for "(.+)"/ # Train::Transports::SSHFailed fingerprint = $1 hostname, ip = $2.split(",") # TODO: convert the SHA256 base64 value to hex with colons # 'ssh' example output: # RSA key fingerprint is e5:cb:c0:e2:21:3b:12:52:f8:ce:cb:00:24:e2:0c:92. # ECDSA key fingerprint is 5d:67:61:08:a9:d7:01:fd:5e:ae:7e:09:40:ef:c0:3c. # will exit 3 on N ui.confirm " The authenticity of host '\#{hostname} (\#{ip})' can't be established.\n fingerprint is \#{fingerprint}.\n\n Are you sure you want to continue connecting\n EOM\n # FIXME: this should save the key to known_hosts but doesn't appear to be\n config[:ssh_verify_host_key] = :accept_new\n conn_opts = connection_opts(reset: true)\n opts.merge! conn_opts\n retry\n elsif (ssh? && e.cause && e.cause.class == Net::SSH::AuthenticationFailed) || (ssh? && e.class == Train::ClientError && e.reason == :no_ssh_password_or_key_available)\n if connection.password_auth?\n raise\n else\n ui.warn(\"Failed to authenticate \#{opts[:user]} to \#{server_name} - trying password auth\")\n password = ui.ask(\"Enter password for \#{opts[:user]}@\#{server_name}:\") do |q|\n q.echo = false\n end\n end\n\n opts.merge! force_ssh_password_opts(password)\n retry\n else\n raise\n end\nrescue RuntimeError => e\n if winrm? && e.message == \"password is a required option\"\n if connection.password_auth?\n raise\n else\n ui.warn(\"Failed to authenticate \#{opts[:user]} to \#{server_name} - trying password auth\")\n password = ui.ask(\"Enter password for \#{opts[:user]}@\#{server_name}:\") do |q|\n q.echo = false\n end\n end\n\n opts.merge! force_winrm_password_opts(password)\n retry\n else\n raise\n end\nend\n" |
#connection_opts(reset: false) ⇒ Object
host via train
870 871 872 873 874 875 876 877 878 879 880 881 882 |
# File 'lib/chef/knife/bootstrap.rb', line 870 def connection_opts(reset: false) return @connection_opts unless @connection_opts.nil? || reset == true @connection_opts = {} @connection_opts.merge! base_opts @connection_opts.merge! host_verify_opts @connection_opts.merge! gateway_opts @connection_opts.merge! sudo_opts @connection_opts.merge! winrm_opts @connection_opts.merge! ssh_opts @connection_opts.merge! ssh_identity_opts @connection_opts end |
#connection_protocol ⇒ Object
url values override CLI flags, if you provide both we’ll use the one that you gave in the URL.
668 669 670 671 672 673 674 |
# File 'lib/chef/knife/bootstrap.rb', line 668 def connection_protocol return @connection_protocol if @connection_protocol from_url = host_descriptor =~ %r{^(.*)://} ? $1 : nil from_knife = config[:connection_protocol] @connection_protocol = from_url || from_knife || "ssh" end |
#default_bootstrap_template ⇒ String
The default bootstrap template to use to bootstrap a server. This is a public API hook which knife plugins use or inherit and override.
450 451 452 453 454 455 456 |
# File 'lib/chef/knife/bootstrap.rb', line 450 def default_bootstrap_template if connection.windows? "windows-chef-client-msi" else "chef-full" end end |
#do_connect(conn_options) ⇒ Object
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 |
# File 'lib/chef/knife/bootstrap.rb', line 676 def do_connect() @connection = TrainConnector.new(host_descriptor, connection_protocol, ) connection.connect! rescue Train::UserError => e limit ||= 1 if !.key?(:pty) && e.reason == :sudo_no_tty ui.warn("#{e.message} - trying with pty request") [:pty] = true # ensure we can talk to systems with requiretty set true in sshd config retry elsif config[:use_sudo_password] && (e.reason == :sudo_password_required || e.reason == :bad_sudo_password) && limit < 3 ui.warn("Failed to authenticate #{conn_options[:user]} to #{server_name} - #{e.message} \n sudo: #{limit} incorrect password attempt") sudo_password = ui.ask("Enter sudo password for #{conn_options[:user]}@#{server_name}:") do |q| q.echo = false end limit += 1 [:sudo_password] = sudo_password retry else raise end end |
#find_template ⇒ Object
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 |
# File 'lib/chef/knife/bootstrap.rb', line 479 def find_template template = bootstrap_template # Use the template directly if it's a path to an actual file if File.exists?(template) Chef::Log.trace("Using the specified bootstrap template: #{File.dirname(template)}") return template end # Otherwise search the template directories until we find the right one bootstrap_files = [] bootstrap_files << File.join(File.dirname(__FILE__), "bootstrap/templates", "#{template}.erb") bootstrap_files << File.join(Knife.chef_config_dir, "bootstrap", "#{template}.erb") if Chef::Knife.chef_config_dir Chef::Util::PathHelper.home(".chef", "bootstrap", "#{template}.erb") { |p| bootstrap_files << p } bootstrap_files << Gem.find_files(File.join("chef", "knife", "bootstrap", "#{template}.erb")) bootstrap_files.flatten! template_file = Array(bootstrap_files).find do |bootstrap_template| Chef::Log.trace("Looking for bootstrap template in #{File.dirname(bootstrap_template)}") File.exists?(bootstrap_template) end unless template_file ui.info("Can not find bootstrap definition for #{template}") raise Errno::ENOENT end Chef::Log.trace("Found bootstrap template: #{template_file}") template_file end |
#first_boot_attributes ⇒ Object
529 530 531 |
# File 'lib/chef/knife/bootstrap.rb', line 529 def first_boot_attributes @config[:first_boot_attributes] || @config[:first_boot_attributes_from_file] || {} end |
#force_ssh_password_opts(password) ⇒ Object
Config overrides to force password auth.
1030 1031 1032 1033 1034 1035 1036 1037 1038 |
# File 'lib/chef/knife/bootstrap.rb', line 1030 def force_ssh_password_opts(password) { password: password, non_interactive: false, keys_only: false, key_files: [], auth_methods: i{password keyboard_interactive}, } end |
#force_winrm_password_opts(password) ⇒ Object
1040 1041 1042 1043 1044 |
# File 'lib/chef/knife/bootstrap.rb', line 1040 def force_winrm_password_opts(password) { password: password, } end |
#gateway_opts ⇒ Object
959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 |
# File 'lib/chef/knife/bootstrap.rb', line 959 def gateway_opts opts = {} if config[:ssh_gateway] split = config[:ssh_gateway].split("@", 2) if split.length == 1 gw_host = split[0] else gw_user = split[0] gw_host = split[1] end gw_host, gw_port = gw_host.split(":", 2) # TODO - validate convertable port in config validation? gw_port = Integer(gw_port) rescue nil opts[:bastion_host] = gw_host opts[:bastion_user] = gw_user opts[:bastion_port] = gw_port end opts end |
#handle_ssh_error(e) ⇒ Object
664 |
# File 'lib/chef/knife/bootstrap.rb', line 664 def handle_ssh_error(e); end |
#host_descriptor ⇒ Object
458 459 460 |
# File 'lib/chef/knife/bootstrap.rb', line 458 def host_descriptor Array(@name_args).first end |
#host_verify_opts ⇒ Object
906 907 908 909 910 911 912 913 914 915 |
# File 'lib/chef/knife/bootstrap.rb', line 906 def host_verify_opts if winrm? { self_signed: config[:winrm_no_verify_cert] === true } elsif ssh? # Fall back to the old knife config key name for back compat. { verify_host_key: config_value(:ssh_verify_host_key, :host_key_verify, "always") } else {} end end |
#perform_bootstrap(remote_bootstrap_script_path) ⇒ Object
591 592 593 594 595 596 597 598 599 600 601 602 |
# File 'lib/chef/knife/bootstrap.rb', line 591 def perform_bootstrap(remote_bootstrap_script_path) ui.info("Bootstrapping #{ui.color(server_name, :bold)}") cmd = bootstrap_command(remote_bootstrap_script_path) r = connection.run_command(cmd) do |data| ui.msg("#{ui.color(" [#{connection.hostname}]", :cyan)} #{data}") end if r.exit_status != 0 ui.error("The following error occurred on #{server_name}:") ui.error(r.stderr) exit 1 end end |
#plugin_create_instance! ⇒ TrueClass
Create the server that we will bootstrap, if necessary
Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to call out to an API to build an instance of the server we wish to bootstrap
806 807 808 |
# File 'lib/chef/knife/bootstrap.rb', line 806 def plugin_create_instance! true end |
#plugin_finalize ⇒ void
This method returns an undefined value.
Perform any teardown or cleanup necessary by the plugin
Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to display a message or perform any cleanup
822 |
# File 'lib/chef/knife/bootstrap.rb', line 822 def plugin_finalize; end |
#plugin_setup! ⇒ TrueClass
Perform any setup necessary by the plugin
Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to create connection objects
815 |
# File 'lib/chef/knife/bootstrap.rb', line 815 def plugin_setup!; end |
#plugin_validate_options! ⇒ TrueClass
Validate any additional options
Plugins that subclass bootstrap, e.g. knife-ec2, can use this method to validate any additional options before any other actions are executed
797 798 799 |
# File 'lib/chef/knife/bootstrap.rb', line 797 def true end |
#register_client ⇒ Object
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 |
# File 'lib/chef/knife/bootstrap.rb', line 567 def register_client # chef-vault integration must use the new client-side hawtness, otherwise to use the # new client-side hawtness, just delete your validation key. if chef_vault_handler.doing_chef_vault? || (Chef::Config[:validation_key] && !File.exist?(File.(Chef::Config[:validation_key]))) unless config[:chef_node_name] ui.error("You must pass a node name with -N when bootstrapping with user credentials") exit 1 end client_builder.run chef_vault_handler.run(client_builder.client) bootstrap_context.client_pem = client_builder.client_path else ui.info " Performing legacy client registration with the validation key at \#{Chef::Config[:validation_key]}...\n Delete your validation key in order to use your user credentials for client registration instead.\n EOM\n\n end\nend\n" |
#render_template ⇒ Object
533 534 535 536 537 538 |
# File 'lib/chef/knife/bootstrap.rb', line 533 def render_template @config[:first_boot_attributes] = first_boot_attributes template_file = find_template template = IO.read(template_file).chomp Erubis::Eruby.new(template).evaluate(bootstrap_context) end |
#run ⇒ Object
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
# File 'lib/chef/knife/bootstrap.rb', line 540 def run check_license plugin_setup! validate_name_args! validate_protocol! validate_first_boot_attributes! validate_winrm_transport_opts! winrm_warn_no_ssl_verification warn_on_short_session_timeout plugin_create_instance! $stdout.sync = true connect! register_client content = render_template bootstrap_path = upload_bootstrap(content) perform_bootstrap(bootstrap_path) plugin_finalize ensure connection.del_file!(bootstrap_path) if connection && bootstrap_path end |
#secret ⇒ Object
511 512 513 |
# File 'lib/chef/knife/bootstrap.rb', line 511 def secret @secret ||= encryption_secret_provided_ignore_encrypt_flag? ? read_secret : nil end |
#server_name ⇒ String
The server_name is the DNS or IP we are going to connect to, it is not necessarily the node name, the fqdn, or the hostname of the server. This is a public API hook which knife plugins use or inherit and override.
467 468 469 470 471 |
# File 'lib/chef/knife/bootstrap.rb', line 467 def server_name if host_descriptor @server_name ||= host_descriptor.split("@").reverse[0] end end |
#ssh? ⇒ Boolean
888 889 890 |
# File 'lib/chef/knife/bootstrap.rb', line 888 def ssh? connection_protocol == "ssh" end |
#ssh_gateway ⇒ Object
SSH Authentication
114 115 116 117 |
# File 'lib/chef/knife/bootstrap.rb', line 114 option :ssh_gateway, short: "-G GATEWAY", long: "--ssh-gateway GATEWAY", description: "The SSH gateway." |
#ssh_identity_opts ⇒ Object
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 |
# File 'lib/chef/knife/bootstrap.rb', line 927 def ssh_identity_opts opts = {} return opts if winrm? identity_file = config[:ssh_identity_file] if identity_file opts[:key_files] = [identity_file] # We only set keys_only based on the explicit ssh_identity_file; # someone may use a gateway key and still expect password auth # on the target. Similarly, someone may have a default key specified # in knife config, but have provided a password on the CLI. # REVIEW NOTE: this is a new behavior. Originally, ssh_identity_file # could only be populated from CLI options, so there was no need to check # for this. We will also set keys_only to false only if there are keys # and no password. # If both are present, train(via net/ssh) will prefer keys, falling back to password. # Reference: https://github.com/chef/chef/blob/master/lib/chef/knife/ssh.rb#L272 opts[:keys_only] = config.key?(:connection_password) == false else opts[:key_files] = [] opts[:keys_only] = false end gateway_identity_file = config[:ssh_gateway] ? config[:ssh_gateway_identity] : nil unless gateway_identity_file.nil? opts[:key_files] << gateway_identity_file end opts end |
#ssh_opts ⇒ Object
917 918 919 920 921 922 923 924 925 |
# File 'lib/chef/knife/bootstrap.rb', line 917 def ssh_opts opts = {} return opts if winrm? opts[:non_interactive] = true # Prevent password prompts from underlying net/ssh opts[:forward_agent] = (config[:ssh_forward_agent] === true) opts[:connection_timeout] = session_timeout opts end |
#sudo_opts ⇒ Object
use_sudo - tells bootstrap to use the sudo command to run bootstrap use_sudo_password - tells bootstrap to use the sudo command to run bootstrap
and to use the password specified with --password
TODO: I’d like to make our sudo options sane: –sudo (bool) - use sudo –sudo-password PASSWORD (default: :password) - use this password for sudo –sudo-options “opt,opt,opt” to pass into sudo –sudo-command COMMAND sudo command other than sudo REVIEW NOTE: knife bootstrap did not pull sudo values from Chef::Config,
should we change that for consistency?
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 |
# File 'lib/chef/knife/bootstrap.rb', line 989 def sudo_opts return {} if winrm? opts = { sudo: false } if config[:use_sudo] opts[:sudo] = true if config[:use_sudo_password] opts[:sudo_password] = config[:connection_password] end if config[:preserve_home] opts[:sudo_options] = "-H" end end opts end |
#upload_bootstrap(content) ⇒ Object
1069 1070 1071 1072 1073 1074 |
# File 'lib/chef/knife/bootstrap.rb', line 1069 def upload_bootstrap(content) script_name = connection.windows? ? "bootstrap.bat" : "bootstrap.sh" remote_path = connection.normalize_path(File.join(connection.temp_dir, script_name)) connection.upload_file_content!(content, remote_path) remote_path end |
#validate_first_boot_attributes! ⇒ Object
Fail if both first_boot_attributes and first_boot_attributes_from_file are set.
701 702 703 704 705 706 707 |
# File 'lib/chef/knife/bootstrap.rb', line 701 def validate_first_boot_attributes! if @config[:first_boot_attributes] && @config[:first_boot_attributes_from_file] raise Chef::Exceptions::BootstrapCommandInputError end true end |
#validate_name_args! ⇒ Object
fail if the server_name is nil
738 739 740 741 742 743 |
# File 'lib/chef/knife/bootstrap.rb', line 738 def validate_name_args! if server_name.nil? ui.error("Must pass an FQDN or ip to bootstrap") exit 1 end end |
#validate_policy_options! ⇒ TrueClass
Ensure options are valid by checking policyfile values.
The method call will cause the program to exit(1) if:
* Only one of --policy-name and --policy-group is specified
* Policyfile are set and --run-list is set as well
752 753 754 755 756 757 758 759 760 |
# File 'lib/chef/knife/bootstrap.rb', line 752 def if ui.error("--policy-name and --policy-group must be specified together") exit 1 elsif policyfile_and_run_list_given? ui.error("Policyfile options and --run-list are exclusive") exit 1 end end |
#validate_protocol! ⇒ TrueClass
Ensure a valid protocol is provided for target host connection
The method call will cause the program to exit(1) if:
* Conflicting protocols are given via the target URI and the --protocol option
* The protocol is not a supported protocol
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 |
# File 'lib/chef/knife/bootstrap.rb', line 769 def validate_protocol! from_cli = config[:connection_protocol] if from_cli && connection_protocol != from_cli # Hanging indent to align with the ERROR: prefix ui.error " The URL '\#{host_descriptor}' indicates protocol is '\#{connection_protocol}'\n while the --protocol flag specifies '\#{from_cli}'. Please include\n only one or the other.\n EOM\n exit 1\n end\n\n unless SUPPORTED_CONNECTION_PROTOCOLS.include?(connection_protocol)\n ui.error <<~EOM\n Unsupported protocol '\#{connection_protocol}'.\n\n Supported protocols are: \#{SUPPORTED_CONNECTION_PROTOCOLS.join(\" \")}\n EOM\n exit 1\n end\n true\nend\n" |
#validate_winrm_transport_opts! ⇒ Object
Fail if using plaintext auth without ssl because this can expose keys in plaintext on the wire. TODO test for this method TODO check that the protoocol is valid.
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 |
# File 'lib/chef/knife/bootstrap.rb', line 717 def validate_winrm_transport_opts! return true unless winrm? if Chef::Config[:validation_key] && !File.exist?(File.(Chef::Config[:validation_key])) if winrm_auth_method == "plaintext" && config[:winrm_ssl] != true ui.error " Validatorless bootstrap over unsecure winrm channels could expose your\n key to network sniffing.\n Please use a 'winrm_auth_method' other than 'plaintext',\n or enable ssl on \#{server_name} then use the ---winrm-ssl flag\n to connect.\n EOM\n\n exit 1\n end\n end\n true\nend\n" |
#warn_on_short_session_timeout ⇒ Object
If session_timeout is too short, it is likely a holdover from “–winrm-session-timeout” which used minutes as its unit, instead of seconds. Warn the human so that they are not surprised.
829 830 831 832 833 834 835 836 |
# File 'lib/chef/knife/bootstrap.rb', line 829 def warn_on_short_session_timeout if session_timeout && session_timeout <= 15 ui.warn " You provided '--session-timeout \#{session_timeout}' second(s).\n Did you mean '--session-timeout \#{session_timeout * 60}' seconds?\n EOM\n end\nend\n" |
#winrm? ⇒ Boolean
884 885 886 |
# File 'lib/chef/knife/bootstrap.rb', line 884 def winrm? connection_protocol == "winrm" end |
#winrm_auth_method ⇒ Object
709 710 711 |
# File 'lib/chef/knife/bootstrap.rb', line 709 def winrm_auth_method config_value(:winrm_auth_method, :winrm_authentication_protocol, "negotiate") end |
#winrm_opts ⇒ Object
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 |
# File 'lib/chef/knife/bootstrap.rb', line 1005 def winrm_opts return {} unless winrm? opts = { winrm_transport: winrm_auth_method, # winrm gem and train calls auth method 'transport' winrm_basic_auth_only: config[:winrm_basic_auth_only] || false, ssl: config[:winrm_ssl] === true, ssl_peer_fingerprint: config[:winrm_ssl_peer_fingerprint], } if winrm_auth_method == "kerberos" opts[:kerberos_service] = config[:kerberos_service] if config[:kerberos_service] opts[:kerberos_realm] = config[:kerberos_realm] if config[:kerberos_service] end if config[:ca_trust_file] opts[:ca_trust_path] = config[:ca_trust_file] end opts[:operation_timeout] = session_timeout opts end |
#winrm_warn_no_ssl_verification ⇒ Object
838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 |
# File 'lib/chef/knife/bootstrap.rb', line 838 def winrm_warn_no_ssl_verification return unless winrm? # REVIEWER NOTE # The original check from knife plugin did not include winrm_ssl_peer_fingerprint # Reference: # https://github.com/chef/knife-windows/blob/92d151298142be4a4750c5b54bb264f8d5b81b8a/lib/chef/knife/winrm_knife_base.rb#L271-L273 # TODO Seems like we should also do a similar warning if ssh_verify_host == false if config[:ca_trust_file].nil? && config[:winrm_no_verify_cert] && config[:winrm_ssl_peer_fingerprint].nil? ui.warn " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n SSL validation of HTTPS requests for the WinRM transport is disabled.\n HTTPS WinRM connections are still encrypted, but knife is not able\n to detect forged replies or spoofing attacks.\n\n To work around this issue you can use the flag `--winrm-no-verify-cert`\n or add an entry like this to your knife configuration file:\n\n # Verify all WinRM HTTPS connections\n knife[:winrm_no_verify_cert] = true\n\n You can also specify a ca_trust_file via --ca-trust-file,\n or the expected fingerprint of the target host's certificate\n via --winrm-ssl-peer-fingerprint.\n WARN\n end\nend\n" |