[SERVER-763] Add allow-header-cert-info authorization support to all Puppet Server service APIs Created: 2015/06/11  Updated: 2015/11/19  Resolved: 2015/10/21

Status: Closed
Project: Puppet Server
Component/s: Puppet Server
Affects Version/s: SERVER 1.1.0, SERVER 2.1.0
Fix Version/s: SERVER 2.2.0

Type: New Feature Priority: Normal
Reporter: Charlie Sharpsteen Assignee: Erik Dasher
Resolution: Fixed Votes: 1
Labels: calendaring, support
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
relates to TK-282 Add ability to obtain authenticated u... Resolved
relates to SERVER-765 Explicitly list endpoints in docs for... Closed
relates to SERVER-39 Need to accept a certificate via an H... Closed
Epic Link: Green: auth.conf replacement
Sub-team: emerald
Story Points: 3
Sprint: Server Emerald 2015-09-30, Server Emerald 2015-10-14, Server Emerald 2015-10-28
CS Priority: Reviewed
QA Contact: Erik Dasher


Puppet Server can be configured to with external SSL termination whereby another upstream server, such as Nginx or Apache, handles HTTPS connections and forwards plain HTTP traffic to Puppet Server. This configuration also includes the allow-header-cert-info option which allows Puppet Server to make authorization decisions based on client information forwarded by the upstream server through X-Client-* headers. However, this authorization only applies to API endpoints in the Puppet Master subsystem. Clojure-level Puppet Server APIs, such as the CA and Administrative API endpoints, ignore the certificate headers forwarded by the upstream server.

This is a feature request for allow-header-cert-info support in all Puppet Server APIs.

Implementation Notes

We've decided that we're going to facilitate this request via the work that we're doing in trapperkeeper-authorization (tk-authz) to provide unified endpoint authorization in Puppet Server. TK-282 would add support for the allow-header-cert-info feature to tk-authz, via a new authorization Trapperkeeper configuration section. When that lands, we'll need to update Puppet Server to be able to defer to / utilize authenticated user info from tk-authz, when available, while not breaking the allow-header-cert-info option in Puppet Server's master section. I'm envisioning the following implementation around Puppet Server's request-handler-service, where the allow-header-cert-info work is currently done:

1) In Puppet Server request-handler-core, attempt to derive authenticated user info from the authorization key in the Ring request map. If the authorization key is not available but the master.allow-header-cert-info setting is set to "true", attempt to derive the authenticated user info from X-Client-* headers on the Ring request map (using supporting Puppet configuration). If the authorization key is not available and the master.allow-header-cert-info setting is not specified or set to "false" (the default), attempt to derive the authenticated user info from the SSL client certificate, ssl-client-cert, on the Ring request map. If authenticated user info cannot be derived by any of the methods above, set the user identity as "unauthenticated".

2) If the master.allow-header-cert-info setting is present in configuration, log an appropriate deprecation warning. If the jruby-puppet.use-legacy-auth-conf setting is set to "false", the warning message should indicate that the master.allow-header-cert-info setting will be ignored in favor of the authorization.allow-header-cert-info setting. If the jruby-puppet.use-legacy-auth-conf setting is set to "true", the warning message should indicate that the user should consider setting the jruby-puppet.use-legacy-auth-conf setting to "false" and using the authorization.allow-header-cert-info setting as a replacement.

Comment by Jeremy Barlow [ 2015/06/16 ]

Charlie Sharpsteen, Kaitlin Carter - We do have the ability to turn off client certificate authentication completely for both the administrative API and the certificate-status APIs. See the documentation for the authorization-required key in the http://docs.puppetlabs.com/puppetserver/1.0/configuration.html#puppetserverconf and http://docs.puppetlabs.com/puppetserver/1.0/configuration.html#caconf sections, respectively. Would this approach be sufficient to meet the need for this request or would requests need to have the client-whitelist "authenticated" against the X-Client-* headers?

Comment by Charlie Sharpsteen [ 2015/06/16 ]

The user that requested this functionality was trying to control access using a whitelist and the X-Client- headers. I'm not sure whether this logic could be moved up to the Nginx layer or not.

Comment by Jeremy Barlow [ 2015/08/10 ]

Per some discussion on https://tickets.puppetlabs.com/browse/SERVER-801?focusedCommentId=204140&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-204140, the current proposal to support this ticket would be to add this logic to the "trapperkeeper-authorization" project. The Ring middleware function in "trapperkeeper-authorization" would be responsible for extracting the user identity from X-Client- headers vs. the subject CN on an SSL client certificate based on whether or not the allow-header-cert-info setting were set.

By keeping this logic in trapperkeeper-authorization, the planned Puppet "auth.conf" replacement which would cover both Clojure-backed and Ruby-backed endpoints that Puppet Server services, all Puppet Server endpoints would be able to utilize this capability - including the CA and Administrative endpoints mentioned in this ticket's description. As part of this, the allow-header-cert-info setting will likely need to migrate from the "master" section of Puppet Server's configuration to the "authorization" section of Trapperkeeper configuration that the "trapperkeeper-authorization" service will manage. This would hopefully make the scope of the setting as covering all "authorization" service controlled endpoints more clear. Note that "trapperkeeper-authorization" may, in the future, be used in a Clojure service stack where Puppet Server's "master" service is not present, so keeping it in the "master" section only would be problematic.

Comment by Jeremy Barlow [ 2015/09/02 ]

Eric Sorenson - so my understanding is that we're basically in agreement with the idea of adding an allow-header-cert-info setting to the authorization section that we'll be supporting for trapperkeeper-authorization. So for the case that someone wanted to enable authentication via X-Client headers, an authorization section would look something like:

authorization: {
  rules: [...]
  allow-header-cert-info: true

For the Puppet Server implementation of the X-Client auth feature, we consult puppet.conf settings for the names of the HTTP headers that we use for authentication - ssl_client_header (https://docs.puppetlabs.com/references/latest/configuration.html#sslclientheader) and ssl_client_verify_header (https://docs.puppetlabs.com/references/latest/configuration.html#sslclientverifyheader). This would allow the user to specify a custom name for the HTTP header rather than just using the defaults of X-Client-DN and X-Client-Verify, respectively.

For the trapperkeeper-authorization implementation of this feature, we'll need to avoid having any dependencies on puppet.conf settings - especially since it may eventually be used in an app stack where legacy Puppet is not involved. Do we think we need to preserve the ability for users to customize the client_dn and client_verify headers in the trapperkeeper-authorization implementation? If so, we'd presumably need to add those settings to the authorization configuration as well.

Not that this is a well used part of the feature yet, but I know that when we incorporated support for forwarding a client certificate via the X-Client-Cert header, we chose not to provide a configuration setting for that header and there was no existing setting for this in puppet.conf to draw from. Essentially, the "user" (i.e., load balancer) would be forced to specify the HTTP header as X-Client-Cert. To my knowledge, we haven't had any requests to create a new setting to allow users to change the name of the X-Client-Cert setting. If we think we need to add settings for customizing the client_dn and client_verify headers to trapperkeeper-authorization, though, it probably would make sense for the certificate one to be configurable as well.

Is this the kind of thing where, for trapperkeeper-authorization, it might make sense to do an initial implementation that doesn't allow for the header names to be configurable for now but add on later only when/if needed?

Comment by Jeremy Barlow [ 2015/09/30 ]

Merged to puppet-server master branch at 69e80d.

Comment by Jeremy Barlow [ 2015/09/30 ]

Full Jenkins acceptance test job passed at http://jenkins-enterprise.delivery.puppetlabs.net/view/puppet-server/view/all/job/enterprise_puppet-server_integration-system_no-conditional_full-master/163/.

Moving to testing.

Comment by Erik Dasher [ 2015/10/21 ]

Validated manually with 2015.3.0-rc3-515-g69d6950 on CentOS6. Example here:

Also validated the removing allow-header-cert-info from the configuration made it so the previously working curl command returns HTTP 403 Forbidden.

curl -k -w '%{http_code}\n' -v --header "X-Client-DN: CN=aiqp7m0uxf5q88u.delivery.puppetlabs.net" --header "X-Client-Verify: SUCCESS" --header "X-Client-Cert: -----BEGIN%20CERTIFICATE-----%0AMIIF0DCCA7igAwIBAgIBCzANBgkqhkiG9w0BAQsFADBmMWQwYgYDVQQDDFtQdXBw%0AZXQgQ0EgZ2VuZXJhdGVkIG9uIG1pc3oycWlqZ21uaW9oci5kZWxpdmVyeS5wdXBw%0AZXRsYWJzLm5ldCBhdCAyMDE1LTEwLTIxIDE0OjE1OjU4IC0wNzAwMB4XDTE1MTAy%0AMDIzMDEyNFoXDTIwMTAxOTIzMDEyNFowMjEwMC4GA1UEAwwnYWlxcDdtMHV4ZjVx%0AODh1LmRlbGl2ZXJ5LnB1cHBldGxhYnMubmV0MIICIjANBgkqhkiG9w0BAQEFAAOC%0AAg8AMIICCgKCAgEA8Oj7TwJj9xjRCn6zzkIY6N4TyhLIv6Riy8XnlFhNmun5QHZ%2B%0AGr0Zs5a4lQ9hkWhWyPdJL9C4xSKKwsxUSyM%2F%2BNcUet8vZQbHTTKBZf6HcXDtuNuP%0A8qLOzekO0UfMK4jpbFh8P2uVP9enXJdKHcTdICI0oFWdvwB2E7qfcdpZyqaPUnxa%0AOTb826%2BFkr68gkN0tl4awuK98Z8qFqoQDfW20QAPmkho8jp5TFj%2F%2FuP1DK%2FP%2FCbx%0Aoux%2FaLEFMwLOk%2FJ%2BMfcdnGlAx14znHGEVHREG8EyYjO5OWA5PUDqeGm1X1eca%2Bc2%0AeeXDeSKxVK5crYOnAP1enUjDJGFNOBKHebnDjyNgxIZKmODwtM4jRzouJrLf9roa%0ADamlhyPyzkiWrOllIgk3keMri56QtYqcHj4DE7VMCl2vAzRRXDLwY0HtxFJ0K39s%0ADFuejiKzlAYeOI4EYJIrJShR%2FRccRCn8%2BgEVknTg5ndq3ggSKrf%2FG0EvaTRDRvP3%0ANC1buy6FVPeS8hQsnm8%2F2hvgSYxHZohqrWN0jifai8P8hXfYjJbE349cnRbV4IiN%0AJn%2BbYJB5k7%2BuwJmRh9K0tRWdDlVolrVtwnzygZW9vkS4VoJpQkrZJeS1kEYu2RSN%0AHC2BUmeGk02FG17VFHCFoyiqE3H%2F8LTKChdvImULS4OBOxoh8qhchukzZ2kCAwEA%0AAaOBvDCBuTA3BglghkgBhvhCAQ0EKgwoUHVwcGV0IFJ1YnkvT3BlblNTTCBJbnRl%0Acm5hbCBDZXJ0aWZpY2F0ZTAOBgNVHQ8BAf8EBAMCBaAwIAYDVR0lAQH%2FBBYwFAYI%0AKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB%2FwQCMAAwHQYDVR0OBBYEFNVTMjgd%0AREon6UdUxck9LogMbe5XMB8GA1UdIwQYMBaAFIRjWQDgo%2BcnRMD0HETVMUv7ZKc2%0AMA0GCSqGSIb3DQEBCwUAA4ICAQAE22LaERU8pfED68wWXFcb7SpNlZ1SWO%2B%2F0S1R%0AvtDnajXo%2B9qnPqCaROmdwiLDHBygTjvwomR0uV0rXfkCzIDsXdAIbUOJ27BU4d64%0AXdpcNgCrgXb9pT%2F5otc2QWN1WrLnUMEeJwDsFWIXwaz5lwkX4WhQ%2FsTtM0Ju9iLX%0Ad6OxkEEFQKFTCuCMzT9FFyOTNEtWXrDA4owrlSPNRtHYNahdk5lMzi0aCGoDqJLH%0AFeYjhxWCL5z0wL69WqTFVovndmm7WcdeVIY8Ss3Z4yO4%2BFBVjDY1ORT5e%2BYi2lwX%0ASPIRS5OlEF56I1%2BrELkqN9Mr%2F5bzRBdlWKWb84Z6M2gMQDxoFVz5jR6lQX70hY2t%0ANX22dPNYmaYPsJBZ5ObdcoCD7AKgdcF2up3IP2SzaZLnRwltLOCEbYrOPAtRHxpZ%0A%2Fw3ED%2F%2Fi1PmxdlZNZiShndnGBhwU1uZ7BBwcfCv0GdVAbbBCiVjZc6txxll2yADG%0A%2FiHnUfdEILTZa4JTkeDYLb%2BWYMHGjevKy1PnO7GJ9izFtpT21KJtGLHffDh45SOT%0A0p7o0yMl7YWVAHGGYtZbc6q8lujrPhRrjKTR1GAaujxdfegDmnkSVMZCsZbBEGgy%0A%2Fi%2BLlCJnF2RSqDs5qcHM6LTtWgjz6pQaewBgd5B%2B7vma8nBAwc4t6d7h9X8i9WqP%0AtKKIMA%3D%3D%0A-----END%20CERTIFICATE-----" https://misz2qijgmniohr.delivery.puppetlabs.net:8140/puppet/v3/environments

Generated at Sun Aug 09 00:04:03 PDT 2020 using Jira 8.5.2#805002-sha1:a66f9354b9e12ac788984e5d84669c903a370049.