"Fossies" - the Fresh Open Source Software Archive

Member "puppet-7.10.0/lib/puppet/application/agent.rb" (16 Aug 2021, 17588 Bytes) of package /linux/misc/puppet-7.10.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "agent.rb": 7.6.1_vs_7.7.0.

    1 require_relative '../../puppet/application'
    2 require_relative '../../puppet/daemon'
    3 require_relative '../../puppet/util/pidlock'
    4 require_relative '../../puppet/agent'
    5 require_relative '../../puppet/configurer'
    6 require_relative '../../puppet/ssl/oids'
    7 
    8 class Puppet::Application::Agent < Puppet::Application
    9 
   10   run_mode :agent
   11 
   12   def app_defaults
   13     super.merge({
   14       :catalog_terminus => :rest,
   15       :catalog_cache_terminus => :json,
   16       :node_terminus => :rest,
   17       :facts_terminus => :facter,
   18     })
   19   end
   20 
   21   def preinit
   22     # Do an initial trap, so that cancels don't get a stack trace.
   23     Signal.trap(:INT) do
   24       $stderr.puts _("Cancelling startup")
   25       exit(0)
   26     end
   27 
   28     {
   29       :waitforcert => nil,
   30       :detailed_exitcodes => false,
   31       :verbose => false,
   32       :debug => false,
   33       :setdest => false,
   34       :enable => false,
   35       :disable => false,
   36       :fqdn => nil,
   37       :serve => [],
   38       :digest => 'SHA256',
   39       :graph => true,
   40       :fingerprint => false,
   41       :sourceaddress => nil,
   42       :start_time => Time.now,
   43     }.each do |opt,val|
   44       options[opt] = val
   45     end
   46 
   47     @argv = ARGV.dup
   48   end
   49 
   50   option("--disable [MESSAGE]") do |message|
   51     options[:disable] = true
   52     options[:disable_message] = message
   53   end
   54 
   55   option("--enable")
   56   option("--debug","-d")
   57   option("--fqdn FQDN","-f")
   58   option("--test","-t")
   59   option("--verbose","-v")
   60 
   61   option("--fingerprint")
   62   option("--digest DIGEST")
   63 
   64   option("--sourceaddress IP_ADDRESS")
   65 
   66   option("--detailed-exitcodes") do |arg|
   67     options[:detailed_exitcodes] = true
   68   end
   69 
   70   option("--logdest DEST", "-l DEST") do |arg|
   71     handle_logdest_arg(arg)
   72   end
   73 
   74   option("--waitforcert WAITFORCERT", "-w") do |arg|
   75     options[:waitforcert] = arg.to_i
   76   end
   77 
   78   option("--job-id ID") do |arg|
   79     options[:job_id] = arg
   80   end
   81 
   82   def summary
   83     _("The puppet agent daemon")
   84   end
   85 
   86   def help
   87     <<-HELP
   88 
   89 puppet-agent(8) -- #{summary}
   90 ========
   91 
   92 SYNOPSIS
   93 --------
   94 Retrieves the client configuration from the Puppet master and applies it to
   95 the local host.
   96 
   97 This service may be run as a daemon, run periodically using cron (or something
   98 similar), or run interactively for testing purposes.
   99 
  100 
  101 USAGE
  102 -----
  103 puppet agent [--certname <NAME>] [-D|--daemonize|--no-daemonize]
  104   [-d|--debug] [--detailed-exitcodes] [--digest <DIGEST>] [--disable [MESSAGE]] [--enable]
  105   [--fingerprint] [-h|--help] [-l|--logdest syslog|eventlog|<ABS FILEPATH>|console]
  106   [--serverport <PORT>] [--noop] [-o|--onetime] [--sourceaddress <IP_ADDRESS>] [-t|--test]
  107   [-v|--verbose] [-V|--version] [-w|--waitforcert <SECONDS>]
  108 
  109 
  110 DESCRIPTION
  111 -----------
  112 This is the main puppet client. Its job is to retrieve the local
  113 machine's configuration from a remote server and apply it. In order to
  114 successfully communicate with the remote server, the client must have a
  115 certificate signed by a certificate authority that the server trusts;
  116 the recommended method for this, at the moment, is to run a certificate
  117 authority as part of the puppet server (which is the default). The
  118 client will connect and request a signed certificate, and will continue
  119 connecting until it receives one.
  120 
  121 Once the client has a signed certificate, it will retrieve its
  122 configuration and apply it.
  123 
  124 
  125 USAGE NOTES
  126 -----------
  127 'puppet agent' does its best to find a compromise between interactive
  128 use and daemon use. If you run it with no arguments and no configuration, it
  129 goes into the background, attempts to get a signed certificate, and retrieves
  130 and applies its configuration every 30 minutes.
  131 
  132 Some flags are meant specifically for interactive use --- in particular,
  133 'test', 'tags' and 'fingerprint' are useful.
  134 
  135 '--test' runs once in the foreground with verbose logging, then exits.
  136 It also exits if it can't get a valid catalog. `--test` includes the 
  137 '--detailed-exitcodes' option by default and exits with one of the following 
  138 exit codes:
  139 
  140 * 0: The run succeeded with no changes or failures; the system was already in 
  141      the desired state.
  142 * 1: The run failed, or wasn't attempted due to another run already in progress.
  143 * 2: The run succeeded, and some resources were changed.
  144 * 4: The run succeeded, and some resources failed.
  145 * 6: The run succeeded, and included both changes and failures.
  146 
  147 '--tags' allows you to specify what portions of a configuration you want
  148 to apply. Puppet elements are tagged with all of the class or definition
  149 names that contain them, and you can use the 'tags' flag to specify one
  150 of these names, causing only configuration elements contained within
  151 that class or definition to be applied. This is very useful when you are
  152 testing new configurations --- for instance, if you are just starting to
  153 manage 'ntpd', you would put all of the new elements into an 'ntpd'
  154 class, and call puppet with '--tags ntpd', which would only apply that
  155 small portion of the configuration during your testing, rather than
  156 applying the whole thing.
  157 
  158 '--fingerprint' is a one-time flag. In this mode 'puppet agent' runs
  159 once and displays on the console (and in the log) the current certificate
  160 (or certificate request) fingerprint. Providing the '--digest' option
  161 allows to use a different digest algorithm to generate the fingerprint.
  162 The main use is to verify that before signing a certificate request on
  163 the master, the certificate request the master received is the same as
  164 the one the client sent (to prevent against man-in-the-middle attacks
  165 when signing certificates).
  166 
  167 '--skip_tags' is a flag used to filter resources. If this is set, then
  168 only resources not tagged with the specified tags will be applied.
  169 Values must be comma-separated.
  170 
  171 
  172 OPTIONS
  173 -------
  174 
  175 Note that any Puppet setting that's valid in the configuration file is also a
  176 valid long argument. For example, 'server' is a valid setting, so you can
  177 specify '--server <servername>' as an argument. Boolean settings accept a '--no-' 
  178 prefix to turn off a behavior, translating into '--setting' and '--no-setting' 
  179 pairs, such as `--daemonize` and `--no-daemonize`.
  180 
  181 See the configuration file documentation at
  182 https://puppet.com/docs/puppet/latest/configuration.html for the
  183 full list of acceptable settings. A commented list of all settings can also be
  184 generated by running puppet agent with '--genconfig'.
  185 
  186 * --certname:
  187   Set the certname (unique ID) of the client. The master reads this
  188   unique identifying string, which is usually set to the node's
  189   fully-qualified domain name, to determine which configurations the
  190   node will receive. Use this option to debug setup problems or
  191   implement unusual node identification schemes.
  192   (This is a Puppet setting, and can go in puppet.conf.)
  193 
  194 * --daemonize:
  195   Send the process into the background. This is the default.
  196   (This is a Puppet setting, and can go in puppet.conf. Note the special 'no-'
  197   prefix for boolean settings on the command line.)
  198 
  199 * --no-daemonize:
  200   Do not send the process into the background.
  201   (This is a Puppet setting, and can go in puppet.conf. Note the special 'no-'
  202   prefix for boolean settings on the command line.)
  203 
  204 * --debug:
  205   Enable full debugging.
  206 
  207 * --detailed-exitcodes:
  208   Provide extra information about the run via exit codes; works only if '--test'
  209   or '--onetime' is also specified. If enabled, 'puppet agent' uses the
  210   following exit codes:
  211 
  212   0: The run succeeded with no changes or failures; the system was already in
  213   the desired state.
  214 
  215   1: The run failed, or wasn't attempted due to another run already in progress.
  216 
  217   2: The run succeeded, and some resources were changed.
  218 
  219   4: The run succeeded, and some resources failed.
  220 
  221   6: The run succeeded, and included both changes and failures.
  222 
  223 * --digest:
  224   Change the certificate fingerprinting digest algorithm. The default is
  225   SHA256. Valid values depends on the version of OpenSSL installed, but
  226   will likely contain MD5, MD2, SHA1 and SHA256.
  227 
  228 * --disable:
  229   Disable working on the local system. This puts a lock file in place,
  230   causing 'puppet agent' not to work on the system until the lock file
  231   is removed. This is useful if you are testing a configuration and do
  232   not want the central configuration to override the local state until
  233   everything is tested and committed.
  234 
  235   Disable can also take an optional message that will be reported by the
  236   'puppet agent' at the next disabled run.
  237 
  238   'puppet agent' uses the same lock file while it is running, so no more
  239   than one 'puppet agent' process is working at a time.
  240 
  241   'puppet agent' exits after executing this.
  242 
  243 * --enable:
  244   Enable working on the local system. This removes any lock file,
  245   causing 'puppet agent' to start managing the local system again
  246   However, it continues to use its normal scheduling, so it might
  247   not start for another half hour.
  248 
  249   'puppet agent' exits after executing this.
  250   
  251 *  --evaltrace:
  252   Logs each resource as it is being evaluated. This allows you to interactively
  253   see exactly what is being done. (This is a Puppet setting, and can go in
  254   puppet.conf. Note the special 'no-' prefix for boolean settings on the command line.)
  255 
  256 * --fingerprint:
  257   Display the current certificate or certificate signing request
  258   fingerprint and then exit. Use the '--digest' option to change the
  259   digest algorithm used.
  260 
  261 * --help:
  262   Print this help message
  263 
  264 * --job-id:
  265   Attach the specified job id to the catalog request and the report used for
  266   this agent run. This option only works when '--onetime' is used.  When using
  267   Puppet Enterprise this flag should not be used as the orchestrator sets the
  268   job-id for you and it must be unique.
  269 
  270 * --logdest:
  271   Where to send log messages. Choose between 'syslog' (the POSIX syslog
  272   service), 'eventlog' (the Windows Event Log), 'console', or the path to a log
  273   file. If debugging or verbosity is enabled, this defaults to 'console'.
  274   Otherwise, it defaults to 'syslog' on POSIX systems and 'eventlog' on Windows.
  275   Multiple destinations can be set using a comma separated list 
  276   (eg: `/path/file1,console,/path/file2`)"
  277 
  278   A path ending with '.json' will receive structured output in JSON format. The
  279   log file will not have an ending ']' automatically written to it due to the
  280   appending nature of logging. It must be appended manually to make the content
  281   valid JSON.
  282 
  283   A path ending with '.jsonl' will receive structured output in JSON Lines
  284   format.
  285 
  286 * --masterport:
  287   The port on which to contact the Puppet Server.
  288   (This is a Puppet setting, and can go in puppet.conf.
  289   Deprecated in favor of the 'serverport' setting.)
  290 
  291 * --noop:
  292   Use 'noop' mode where the daemon runs in a no-op or dry-run mode. This
  293   is useful for seeing what changes Puppet would make without actually
  294   executing the changes.
  295   (This is a Puppet setting, and can go in puppet.conf. Note the special 'no-'
  296   prefix for boolean settings on the command line.)
  297 
  298 * --onetime:
  299   Run the configuration once. Runs a single (normally daemonized) Puppet
  300   run. Useful for interactively running puppet agent when used in
  301   conjunction with the --no-daemonize option.
  302   (This is a Puppet setting, and can go in puppet.conf. Note the special 'no-'
  303   prefix for boolean settings on the command line.)
  304 
  305 * --serverport:
  306   The port on which to contact the Puppet Server.
  307   (This is a Puppet setting, and can go in puppet.conf.)
  308 
  309 * --sourceaddress:
  310   Set the source IP address for transactions. This defaults to automatically selected.
  311   (This is a Puppet setting, and can go in puppet.conf.)
  312 
  313 * --test:
  314   Enable the most common options used for testing. These are 'onetime',
  315   'verbose', 'no-daemonize', 'no-usecacheonfailure', 'detailed-exitcodes',
  316   'no-splay', and 'show_diff'.
  317   
  318 * --trace
  319   Prints stack traces on some errors. (This is a Puppet setting, and can go in
  320   puppet.conf. Note the special 'no-' prefix for boolean settings on the command line.)
  321 
  322 * --verbose:
  323   Turn on verbose reporting.
  324 
  325 * --version:
  326   Print the puppet version number and exit.
  327 
  328 * --waitforcert:
  329   This option only matters for daemons that do not yet have certificates
  330   and it is enabled by default, with a value of 120 (seconds). This
  331   causes 'puppet agent' to connect to the server every 2 minutes and ask
  332   it to sign a certificate request. This is useful for the initial setup
  333   of a puppet client. You can turn off waiting for certificates by
  334   specifying a time of 0.
  335   (This is a Puppet setting, and can go in puppet.conf.)
  336 
  337 
  338 EXAMPLE
  339 -------
  340     $ puppet agent --server puppet.domain.com
  341 
  342 
  343 DIAGNOSTICS
  344 -----------
  345 
  346 Puppet agent accepts the following signals:
  347 
  348 * SIGHUP:
  349   Restart the puppet agent daemon.
  350 * SIGINT and SIGTERM:
  351   Shut down the puppet agent daemon.
  352 * SIGUSR1:
  353   Immediately retrieve and apply configurations from the puppet master.
  354 * SIGUSR2:
  355   Close file descriptors for log files and reopen them. Used with logrotate.
  356 
  357 AUTHOR
  358 ------
  359 Luke Kanies
  360 
  361 
  362 COPYRIGHT
  363 ---------
  364 Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
  365 
  366     HELP
  367   end
  368 
  369   def run_command
  370     if options[:fingerprint]
  371       fingerprint
  372     else
  373       # It'd be nice to daemonize later, but we have to daemonize before
  374       # waiting for certificates so that we don't block
  375       daemon = daemonize_process_when(Puppet[:daemonize])
  376 
  377       # Setup signal traps immediately after daemonization so we clean up the daemon
  378       daemon.set_signal_traps
  379 
  380       log_config if Puppet[:daemonize]
  381 
  382       # run ssl state machine, waiting if needed
  383       ssl_context = wait_for_certificates
  384 
  385       # Each application is responsible for pushing loaders onto the context.
  386       # Use the current environment that has already been established, though
  387       # it may change later during the configurer run.
  388       env = Puppet.lookup(:current_environment)
  389       Puppet.override(ssl_context: ssl_context,
  390                       current_environment: env,
  391                       loaders: Puppet::Pops::Loaders.new(env, true)) do
  392         if Puppet[:onetime]
  393           onetime(daemon)
  394         else
  395           main(daemon)
  396         end
  397       end
  398     end
  399   end
  400 
  401   def log_config
  402     #skip also config reading and parsing if debug is not enabled
  403     return unless Puppet::Util::Log.sendlevel?(:debug)
  404 
  405     Puppet.settings.stringify_settings(:agent, :all).each_pair do |k,v|
  406       next if k.include?("password") || v.to_s.empty?
  407       Puppet.debug("Using setting: #{k}=#{v}")
  408     end
  409   end
  410 
  411   def fingerprint
  412     Puppet::Util::Log.newdestination(:console)
  413     cert_provider = Puppet::X509::CertProvider.new
  414     client_cert = cert_provider.load_client_cert(Puppet[:certname])
  415     if client_cert
  416       puts Puppet::SSL::Digest.new(options[:digest].to_s, client_cert.to_der).to_s
  417     else
  418       csr = cert_provider.load_request(Puppet[:certname])
  419       if csr
  420         puts Puppet::SSL::Digest.new(options[:digest].to_s, csr.to_der).to_s
  421       else
  422         $stderr.puts _("Fingerprint asked but neither the certificate, nor the certificate request have been issued")
  423         exit(1)
  424       end
  425     end
  426   rescue => e
  427     Puppet.log_exception(e, _("Failed to generate fingerprint: %{message}") % {message: e.message})
  428     exit(1)
  429   end
  430 
  431   def onetime(daemon)
  432     begin
  433       exitstatus = daemon.agent.run({:job_id => options[:job_id], :start_time => options[:start_time]})
  434     rescue => detail
  435       Puppet.log_exception(detail)
  436     end
  437 
  438     daemon.stop(:exit => false)
  439 
  440     if not exitstatus
  441       exit(1)
  442     elsif options[:detailed_exitcodes] then
  443       exit(exitstatus)
  444     else
  445       exit(0)
  446     end
  447   end
  448 
  449   def main(daemon)
  450     Puppet.notice _("Starting Puppet client version %{version}") % { version: Puppet.version }
  451     daemon.start
  452   end
  453 
  454   # Enable all of the most common test options.
  455   def setup_test
  456     Puppet.settings.handlearg("--no-usecacheonfailure")
  457     Puppet.settings.handlearg("--no-splay")
  458     Puppet.settings.handlearg("--show_diff")
  459     Puppet.settings.handlearg("--no-daemonize")
  460     options[:verbose] = true
  461     Puppet[:onetime] = true
  462     options[:detailed_exitcodes] = true
  463   end
  464 
  465   def setup
  466     raise ArgumentError, _("The puppet agent command does not take parameters") unless command_line.args.empty?
  467 
  468     setup_test if options[:test]
  469 
  470     setup_logs
  471 
  472     exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
  473 
  474     Puppet::SSL::Oids.register_puppet_oids
  475 
  476     if options[:fqdn]
  477       Puppet[:certname] = options[:fqdn]
  478     end
  479 
  480     Puppet.settings.use :main, :agent, :ssl
  481 
  482     Puppet::Transaction::Report.indirection.terminus_class = :rest
  483     # we want the last report to be persisted locally
  484     Puppet::Transaction::Report.indirection.cache_class = :yaml
  485 
  486     if Puppet[:catalog_cache_terminus]
  487       Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
  488     end
  489 
  490     # In fingerprint mode we don't need to set up the whole agent
  491     unless options[:fingerprint]
  492       setup_agent
  493     end
  494   end
  495 
  496   private
  497 
  498   def enable_disable_client(agent)
  499     if options[:enable]
  500       agent.enable
  501     elsif options[:disable]
  502       agent.disable(options[:disable_message] || 'reason not specified')
  503     end
  504     exit(0)
  505   end
  506 
  507   def setup_agent
  508     agent = Puppet::Agent.new(Puppet::Configurer, (not(Puppet[:onetime])))
  509 
  510     enable_disable_client(agent) if options[:enable] or options[:disable]
  511 
  512     @agent = agent
  513   end
  514 
  515   def daemonize_process_when(should_daemonize)
  516     daemon = Puppet::Daemon.new(@agent, Puppet::Util::Pidlock.new(Puppet[:pidfile]))
  517     daemon.argv = @argv
  518 
  519     daemon.daemonize if should_daemonize
  520 
  521     daemon
  522   end
  523 
  524   def wait_for_certificates
  525     waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
  526     sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert)
  527     sm.ensure_client_certificate
  528   end
  529 end