It's going to depend on node['app']['web'].  If you have

node['app']['web']['endpoint'], I suspect that node['app']['web'] isn't
just a string, but rather a hash.  Easy to fix, but first, I'm not sure
precisely certain what you mean by apache and nginx.  Are these just
human-friendly labels?  Are they package names?  Are they service names?

If they are the names of the actual packages, I'd do something like

default['cluster']['web']['package']

or perhaps

default['cluster']['web']['service']

if it's just the name of the desired service.  Ensure that whichever you
choose is either going to be set to a string or something that can be
cast to a string.

Then try

node['cluster'][node['app']['web']['daemon']]['endpoint'] or even
node['cluster'][node['app']['web']['daemon'].to_s]['endpoint']

Actual code that's similar and has worked (that probably has more
".to_s" than it needs).

node['jdk']['versions'].each do |key, value|

[snip]

   package
node['jdk']['packages'][node['platform_family'].to_s][key.to_s]['package'].to_s
do
     version
node['jdk']['packages'][node['platform_family'].to_s][key.to_s]['version'].to_s
   end

where these attributes are defined.

default['jdk']['packages']['debian'] = {
   'oracle7' => {
     'package' => 'oracle-j2sdk1.7',
     'version' => '1.7.0+update55',
   },
}
default['jdk']['packages']['rhel'] = {
   'oracle7' => {
     'package' => 'jdk',
     'version' => '2000:1.7.0_55-fcs',
   },
}

default['jdk']['versions'] = {
   'oracle7' => true,
}

---