mixlib-shellout 3.1.7 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 82102f99cbf59a6ec48f6b7685e470ecd94bc629e27ae83b36a3eaa7e02ace33
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 83d3a8aeb7bf139a209440bc8877b63f524b7d30c783b99af2c7406d237618ef
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 201ec59f8e4dd8f20443e9d78f880037cd65f91a890321647d95347d29bf478968554548efc311d2a1da82ae3a7c00220cb27021c13d21c8b2ecc28bdfbd20cc
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 3c1caed9698c8820fb70b2245b134e303fcb55343323ea1c51350d625ceeee5f9c3ec8a68d5f81355aafad3c30d89a244316576b674a13eb922f7b0d8fb10948
         
     | 
    
        data/lib/mixlib/shellout.rb
    CHANGED
    
    | 
         @@ -248,7 +248,7 @@ module Mixlib 
     | 
|
| 
       248 
248 
     | 
    
         
             
                # running or died without setting an exit status (e.g., terminated by
         
     | 
| 
       249 
249 
     | 
    
         
             
                # `kill -9`).
         
     | 
| 
       250 
250 
     | 
    
         
             
                def exitstatus
         
     | 
| 
       251 
     | 
    
         
            -
                  @status 
     | 
| 
      
 251 
     | 
    
         
            +
                  @status && @status.exitstatus
         
     | 
| 
       252 
252 
     | 
    
         
             
                end
         
     | 
| 
       253 
253 
     | 
    
         | 
| 
       254 
254 
     | 
    
         
             
                # Run the command, writing the command's standard out and standard error
         
     | 
    
        data/lib/mixlib/shellout/unix.rb
    CHANGED
    
    | 
         @@ -370,11 +370,11 @@ module Mixlib 
     | 
|
| 
       370 
370 
     | 
    
         
             
                    return if attempt_reap
         
     | 
| 
       371 
371 
     | 
    
         | 
| 
       372 
372 
     | 
    
         
             
                    @terminate_reason = "Command exceeded allowed execution time, process terminated"
         
     | 
| 
       373 
     | 
    
         
            -
                    logger 
     | 
| 
      
 373 
     | 
    
         
            +
                    logger.error("Command exceeded allowed execution time, sending TERM") if logger
         
     | 
| 
       374 
374 
     | 
    
         
             
                    Process.kill(:TERM, child_pgid)
         
     | 
| 
       375 
375 
     | 
    
         
             
                    sleep 3
         
     | 
| 
       376 
376 
     | 
    
         
             
                    attempt_reap
         
     | 
| 
       377 
     | 
    
         
            -
                    logger 
     | 
| 
      
 377 
     | 
    
         
            +
                    logger.error("Command exceeded allowed execution time, sending KILL") if logger
         
     | 
| 
       378 
378 
     | 
    
         
             
                    Process.kill(:KILL, child_pgid)
         
     | 
| 
       379 
379 
     | 
    
         
             
                    reap
         
     | 
| 
       380 
380 
     | 
    
         | 
| 
         @@ -89,7 +89,7 @@ module Mixlib 
     | 
|
| 
       89 
89 
     | 
    
         
             
                      # Start the process
         
     | 
| 
       90 
90 
     | 
    
         
             
                      #
         
     | 
| 
       91 
91 
     | 
    
         
             
                      process, profile, token = Process.create3(create_process_args)
         
     | 
| 
       92 
     | 
    
         
            -
                      logger 
     | 
| 
      
 92 
     | 
    
         
            +
                      logger.debug(format_process(process, app_name, command_line, timeout)) if logger
         
     | 
| 
       93 
93 
     | 
    
         
             
                      begin
         
     | 
| 
       94 
94 
     | 
    
         
             
                        # Start pushing data into input
         
     | 
| 
       95 
95 
     | 
    
         
             
                        stdin_write << input if input
         
     | 
| 
         @@ -124,7 +124,7 @@ module Mixlib 
     | 
|
| 
       124 
124 
     | 
    
         
             
                                kill_process_tree(process.process_id, wmi, logger)
         
     | 
| 
       125 
125 
     | 
    
         
             
                                Process.kill(:KILL, process.process_id)
         
     | 
| 
       126 
126 
     | 
    
         
             
                              rescue SystemCallError
         
     | 
| 
       127 
     | 
    
         
            -
                                logger 
     | 
| 
      
 127 
     | 
    
         
            +
                                logger.warn("Failed to kill timed out process #{process.process_id}") if logger
         
     | 
| 
       128 
128 
     | 
    
         
             
                              end
         
     | 
| 
       129 
129 
     | 
    
         | 
| 
       130 
130 
     | 
    
         
             
                              raise Mixlib::ShellOut::CommandTimeout, [
         
     | 
| 
         @@ -398,16 +398,20 @@ module Mixlib 
     | 
|
| 
       398 
398 
     | 
    
         | 
| 
       399 
399 
     | 
    
         
             
                  def kill_process(instance, logger)
         
     | 
| 
       400 
400 
     | 
    
         
             
                    child_pid = instance.wmi_ole_object.processid
         
     | 
| 
       401 
     | 
    
         
            -
                    logger 
     | 
| 
      
 401 
     | 
    
         
            +
                    if logger
         
     | 
| 
      
 402 
     | 
    
         
            +
                      logger.debug([
         
     | 
| 
       402 
403 
     | 
    
         
             
                        "killing child process #{child_pid}::",
         
     | 
| 
       403 
404 
     | 
    
         
             
                        "#{instance.wmi_ole_object.Name} of parent #{pid}",
         
     | 
| 
       404 
405 
     | 
    
         
             
                      ].join)
         
     | 
| 
      
 406 
     | 
    
         
            +
                    end
         
     | 
| 
       405 
407 
     | 
    
         
             
                    Process.kill(:KILL, instance.wmi_ole_object.processid)
         
     | 
| 
       406 
408 
     | 
    
         
             
                  rescue SystemCallError
         
     | 
| 
       407 
     | 
    
         
            -
                    logger 
     | 
| 
      
 409 
     | 
    
         
            +
                    if logger
         
     | 
| 
      
 410 
     | 
    
         
            +
                      logger.debug([
         
     | 
| 
       408 
411 
     | 
    
         
             
                        "Failed to kill child process #{child_pid}::",
         
     | 
| 
       409 
412 
     | 
    
         
             
                        "#{instance.wmi_ole_object.Name} of parent #{pid}",
         
     | 
| 
       410 
413 
     | 
    
         
             
                      ].join)
         
     | 
| 
      
 414 
     | 
    
         
            +
                    end
         
     | 
| 
       411 
415 
     | 
    
         
             
                  end
         
     | 
| 
       412 
416 
     | 
    
         | 
| 
       413 
417 
     | 
    
         
             
                  def format_process(process, app_name, command_line, timeout)
         
     | 
| 
         @@ -18,9 +18,11 @@ 
     | 
|
| 
       18 
18 
     | 
    
         
             
            #
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
            require "win32/process"
         
     | 
| 
      
 21 
     | 
    
         
            +
            require "ffi/win32/extensions"
         
     | 
| 
       21 
22 
     | 
    
         | 
| 
       22 
23 
     | 
    
         
             
            # Add new constants for Logon
         
     | 
| 
       23 
24 
     | 
    
         
             
            module Process::Constants
         
     | 
| 
      
 25 
     | 
    
         
            +
              private
         
     | 
| 
       24 
26 
     | 
    
         | 
| 
       25 
27 
     | 
    
         
             
              LOGON32_LOGON_INTERACTIVE = 0x00000002
         
     | 
| 
       26 
28 
     | 
    
         
             
              LOGON32_LOGON_BATCH = 0x00000004
         
     | 
| 
         @@ -44,6 +46,8 @@ module Process::Constants 
     | 
|
| 
       44 
46 
     | 
    
         
             
              WIN32_PROFILETYPE_PT_MANDATORY           = 0x04
         
     | 
| 
       45 
47 
     | 
    
         
             
              WIN32_PROFILETYPE_PT_ROAMING_PREEXISTING = 0x08
         
     | 
| 
       46 
48 
     | 
    
         | 
| 
      
 49 
     | 
    
         
            +
              # The environment block list ends with two nulls (\0\0).
         
     | 
| 
      
 50 
     | 
    
         
            +
              ENVIRONMENT_BLOCK_ENDS = "\0\0".freeze
         
     | 
| 
       47 
51 
     | 
    
         
             
            end
         
     | 
| 
       48 
52 
     | 
    
         | 
| 
       49 
53 
     | 
    
         
             
            # Structs required for data handling
         
     | 
| 
         @@ -77,6 +81,12 @@ module Process::Functions 
     | 
|
| 
       77 
81 
     | 
    
         
             
              attach_pfunc :UnloadUserProfile,
         
     | 
| 
       78 
82 
     | 
    
         
             
                %i{handle handle}, :bool
         
     | 
| 
       79 
83 
     | 
    
         | 
| 
      
 84 
     | 
    
         
            +
              attach_pfunc :CreateEnvironmentBlock,
         
     | 
| 
      
 85 
     | 
    
         
            +
                %i{pointer ulong bool}, :bool
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
              attach_pfunc :DestroyEnvironmentBlock,
         
     | 
| 
      
 88 
     | 
    
         
            +
                %i{pointer}, :bool
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
       80 
90 
     | 
    
         
             
              ffi_lib :advapi32
         
     | 
| 
       81 
91 
     | 
    
         | 
| 
       82 
92 
     | 
    
         
             
              attach_pfunc :LogonUserW,
         
     | 
| 
         @@ -147,13 +157,15 @@ module Process 
     | 
|
| 
       147 
157 
     | 
    
         
             
                  si_hash = {}
         
     | 
| 
       148 
158 
     | 
    
         | 
| 
       149 
159 
     | 
    
         
             
                  # If the startup_info key is present, validate its subkeys
         
     | 
| 
       150 
     | 
    
         
            -
                  hash["startup_info"] 
     | 
| 
       151 
     | 
    
         
            -
                     
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
       153 
     | 
    
         
            -
                       
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
      
 160 
     | 
    
         
            +
                  if hash["startup_info"]
         
     | 
| 
      
 161 
     | 
    
         
            +
                    hash["startup_info"].each do |key, val|
         
     | 
| 
      
 162 
     | 
    
         
            +
                      key = key.to_s.downcase
         
     | 
| 
      
 163 
     | 
    
         
            +
                      unless valid_si_keys.include?(key)
         
     | 
| 
      
 164 
     | 
    
         
            +
                        raise ArgumentError, "invalid startup_info key '#{key}'"
         
     | 
| 
      
 165 
     | 
    
         
            +
                      end
         
     | 
| 
       155 
166 
     | 
    
         | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
      
 167 
     | 
    
         
            +
                      si_hash[key] = val
         
     | 
| 
      
 168 
     | 
    
         
            +
                    end
         
     | 
| 
       157 
169 
     | 
    
         
             
                  end
         
     | 
| 
       158 
170 
     | 
    
         | 
| 
       159 
171 
     | 
    
         
             
                  # The +command_line+ key is mandatory unless the +app_name+ key
         
     | 
| 
         @@ -169,9 +181,25 @@ module Process 
     | 
|
| 
       169 
181 
     | 
    
         | 
| 
       170 
182 
     | 
    
         
             
                  env = nil
         
     | 
| 
       171 
183 
     | 
    
         | 
| 
      
 184 
     | 
    
         
            +
                  # Retrieve the environment variables for the specified user.
         
     | 
| 
      
 185 
     | 
    
         
            +
                  if hash["with_logon"]
         
     | 
| 
      
 186 
     | 
    
         
            +
                    logon, passwd, domain = format_creds_from_hash(hash)
         
     | 
| 
      
 187 
     | 
    
         
            +
                    logon_type = hash["elevated"] ? LOGON32_LOGON_BATCH : LOGON32_LOGON_INTERACTIVE
         
     | 
| 
      
 188 
     | 
    
         
            +
                    token = logon_user(logon, domain, passwd, logon_type)
         
     | 
| 
      
 189 
     | 
    
         
            +
                    logon_ptr = FFI::MemoryPointer.from_string(logon)
         
     | 
| 
      
 190 
     | 
    
         
            +
                    profile = PROFILEINFO.new.tap do |dat|
         
     | 
| 
      
 191 
     | 
    
         
            +
                      dat[:dwSize]     = dat.size
         
     | 
| 
      
 192 
     | 
    
         
            +
                      dat[:dwFlags]    = 1
         
     | 
| 
      
 193 
     | 
    
         
            +
                      dat[:lpUserName] = logon_ptr
         
     | 
| 
      
 194 
     | 
    
         
            +
                    end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                    load_user_profile(token, profile.pointer)
         
     | 
| 
      
 197 
     | 
    
         
            +
                    env_list = retrieve_environment_variables(token)
         
     | 
| 
      
 198 
     | 
    
         
            +
                  end
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
       172 
200 
     | 
    
         
             
                  # The env string should be passed as a string of ';' separated paths.
         
     | 
| 
       173 
201 
     | 
    
         
             
                  if hash["environment"]
         
     | 
| 
       174 
     | 
    
         
            -
                    env = hash["environment"]
         
     | 
| 
      
 202 
     | 
    
         
            +
                    env = env_list.nil? ? hash["environment"] : merge_env_variables(env_list, hash["environment"])
         
     | 
| 
       175 
203 
     | 
    
         | 
| 
       176 
204 
     | 
    
         
             
                    unless env.respond_to?(:join)
         
     | 
| 
       177 
205 
     | 
    
         
             
                      env = hash["environment"].split(File::PATH_SEPARATOR)
         
     | 
| 
         @@ -393,6 +421,33 @@ module Process 
     | 
|
| 
       393 
421 
     | 
    
         
             
                  true
         
     | 
| 
       394 
422 
     | 
    
         
             
                end
         
     | 
| 
       395 
423 
     | 
    
         | 
| 
      
 424 
     | 
    
         
            +
                # Retrieves the environment variables for the specified user.
         
     | 
| 
      
 425 
     | 
    
         
            +
                #
         
     | 
| 
      
 426 
     | 
    
         
            +
                # @param env_pointer [Pointer] The environment block is an array of null-terminated Unicode strings.
         
     | 
| 
      
 427 
     | 
    
         
            +
                # @param token [Integer] User token handle.
         
     | 
| 
      
 428 
     | 
    
         
            +
                # @return [Boolean] true if successfully retrieves the environment variables for the specified user.
         
     | 
| 
      
 429 
     | 
    
         
            +
                #
         
     | 
| 
      
 430 
     | 
    
         
            +
                def create_environment_block(env_pointer, token)
         
     | 
| 
      
 431 
     | 
    
         
            +
                  unless CreateEnvironmentBlock(env_pointer, token, false)
         
     | 
| 
      
 432 
     | 
    
         
            +
                    raise SystemCallError.new("CreateEnvironmentBlock", FFI.errno)
         
     | 
| 
      
 433 
     | 
    
         
            +
                  end
         
     | 
| 
      
 434 
     | 
    
         
            +
             
     | 
| 
      
 435 
     | 
    
         
            +
                  true
         
     | 
| 
      
 436 
     | 
    
         
            +
                end
         
     | 
| 
      
 437 
     | 
    
         
            +
             
     | 
| 
      
 438 
     | 
    
         
            +
                # Frees environment variables created by the CreateEnvironmentBlock function.
         
     | 
| 
      
 439 
     | 
    
         
            +
                #
         
     | 
| 
      
 440 
     | 
    
         
            +
                # @param env_pointer [Pointer] The environment block is an array of null-terminated Unicode strings.
         
     | 
| 
      
 441 
     | 
    
         
            +
                # @return [Boolean] true if successfully frees environment variables created by the CreateEnvironmentBlock function.
         
     | 
| 
      
 442 
     | 
    
         
            +
                #
         
     | 
| 
      
 443 
     | 
    
         
            +
                def destroy_environment_block(env_pointer)
         
     | 
| 
      
 444 
     | 
    
         
            +
                  unless DestroyEnvironmentBlock(env_pointer)
         
     | 
| 
      
 445 
     | 
    
         
            +
                    raise SystemCallError.new("DestroyEnvironmentBlock", FFI.errno)
         
     | 
| 
      
 446 
     | 
    
         
            +
                  end
         
     | 
| 
      
 447 
     | 
    
         
            +
             
     | 
| 
      
 448 
     | 
    
         
            +
                  true
         
     | 
| 
      
 449 
     | 
    
         
            +
                end
         
     | 
| 
      
 450 
     | 
    
         
            +
             
     | 
| 
       396 
451 
     | 
    
         
             
                def create_process_as_user(token, app, cmd, process_security,
         
     | 
| 
       397 
452 
     | 
    
         
             
                  thread_security, inherit, creation_flags, env, cwd, startinfo, procinfo)
         
     | 
| 
       398 
453 
     | 
    
         | 
| 
         @@ -527,5 +582,51 @@ module Process 
     | 
|
| 
       527 
582 
     | 
    
         
             
                  [ logon, passwd, domain ]
         
     | 
| 
       528 
583 
     | 
    
         
             
                end
         
     | 
| 
       529 
584 
     | 
    
         | 
| 
      
 585 
     | 
    
         
            +
                # Retrieves the environment variables for the specified user.
         
     | 
| 
      
 586 
     | 
    
         
            +
                #
         
     | 
| 
      
 587 
     | 
    
         
            +
                # @param token [Integer] User token handle.
         
     | 
| 
      
 588 
     | 
    
         
            +
                # @return env_list [Array<String>] Environment variables of specified user.
         
     | 
| 
      
 589 
     | 
    
         
            +
                #
         
     | 
| 
      
 590 
     | 
    
         
            +
                def retrieve_environment_variables(token)
         
     | 
| 
      
 591 
     | 
    
         
            +
                  env_list = []
         
     | 
| 
      
 592 
     | 
    
         
            +
                  env_pointer = FFI::MemoryPointer.new(:pointer)
         
     | 
| 
      
 593 
     | 
    
         
            +
                  create_environment_block(env_pointer, token)
         
     | 
| 
      
 594 
     | 
    
         
            +
                  str_ptr = env_pointer.read_pointer
         
     | 
| 
      
 595 
     | 
    
         
            +
                  offset = 0
         
     | 
| 
      
 596 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 597 
     | 
    
         
            +
                    new_str_pointer = str_ptr + offset
         
     | 
| 
      
 598 
     | 
    
         
            +
                    break if new_str_pointer.read_string(2) == ENVIRONMENT_BLOCK_ENDS
         
     | 
| 
      
 599 
     | 
    
         
            +
             
     | 
| 
      
 600 
     | 
    
         
            +
                    environment = new_str_pointer.read_wstring
         
     | 
| 
      
 601 
     | 
    
         
            +
                    env_list << environment
         
     | 
| 
      
 602 
     | 
    
         
            +
                    offset = offset + environment.length * 2 + 2
         
     | 
| 
      
 603 
     | 
    
         
            +
                  end
         
     | 
| 
      
 604 
     | 
    
         
            +
             
     | 
| 
      
 605 
     | 
    
         
            +
                  # To free the buffer when we have finished with the environment block
         
     | 
| 
      
 606 
     | 
    
         
            +
                  destroy_environment_block(str_ptr)
         
     | 
| 
      
 607 
     | 
    
         
            +
                  env_list
         
     | 
| 
      
 608 
     | 
    
         
            +
                end
         
     | 
| 
      
 609 
     | 
    
         
            +
             
     | 
| 
      
 610 
     | 
    
         
            +
                # Merge environment variables of specified user and current environment variables.
         
     | 
| 
      
 611 
     | 
    
         
            +
                #
         
     | 
| 
      
 612 
     | 
    
         
            +
                # @param fetched_env [Array<String>] environment variables of specified user.
         
     | 
| 
      
 613 
     | 
    
         
            +
                # @param current_env [Array<String>] current environment variables.
         
     | 
| 
      
 614 
     | 
    
         
            +
                # @return [Array<String>] Merged environment variables.
         
     | 
| 
      
 615 
     | 
    
         
            +
                #
         
     | 
| 
      
 616 
     | 
    
         
            +
                def merge_env_variables(fetched_env, current_env)
         
     | 
| 
      
 617 
     | 
    
         
            +
                  env_hash_1 = environment_list_to_hash(fetched_env)
         
     | 
| 
      
 618 
     | 
    
         
            +
                  env_hash_2 = environment_list_to_hash(current_env)
         
     | 
| 
      
 619 
     | 
    
         
            +
                  merged_env = env_hash_2.merge(env_hash_1)
         
     | 
| 
      
 620 
     | 
    
         
            +
                  merged_env.map { |k, v| "#{k}=#{v}" }
         
     | 
| 
      
 621 
     | 
    
         
            +
                end
         
     | 
| 
      
 622 
     | 
    
         
            +
             
     | 
| 
      
 623 
     | 
    
         
            +
                # Convert an array to a hash.
         
     | 
| 
      
 624 
     | 
    
         
            +
                #
         
     | 
| 
      
 625 
     | 
    
         
            +
                # @param env_var [Array<String>] Environment variables.
         
     | 
| 
      
 626 
     | 
    
         
            +
                # @return [Hash] Converted an array to hash.
         
     | 
| 
      
 627 
     | 
    
         
            +
                #
         
     | 
| 
      
 628 
     | 
    
         
            +
                def environment_list_to_hash(env_var)
         
     | 
| 
      
 629 
     | 
    
         
            +
                  Hash[ env_var.map { |pair| pair.split("=", 2) } ]
         
     | 
| 
      
 630 
     | 
    
         
            +
                end
         
     | 
| 
       530 
631 
     | 
    
         
             
              end
         
     | 
| 
       531 
632 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: mixlib-shellout
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 3. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 3.2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Chef Software Inc.
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2020- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2020-11-12 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: chef-utils
         
     |