{"host": "cp2058.codfw.wmnet", "state": "core_diff", "description": "Differences to core resources", "diff": {"full": {"total": 3969, "only_in_self": [], "only_in_other": [], "resource_diffs": [{"resource": "Haproxy::Confd_site[tls]"}, {"resource": "File[/etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl]", "content": "--- /etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl.orig\n+++ /etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl\n@@ -120,6 +120,7 @@\n     http-request del-header tracestate if !wikimedia_trust\n     http-request del-header traceparent if !wikimedia_trust\n     http-request del-header X-Experiment-Enrollments\n+    http-request del-header X-JWT-Sub\n \n     # Copy X-Analytics hdr into var to safely log it after deletion\n     http-response set-var(txn.x_analytics,ifnotempty) res.fhdr(X-Analytics)\n@@ -271,6 +272,23 @@\n     acl is_identified_bot_request var(req.trusted_request) -m str B\n     acl is_auth_request var(req.trusted_request) -m str C\n \n+    http-request set-var(req.bearer) http_auth_bearer if { req.fhdr(Authorization) -m found }\n+    http-request set-var(req.bearer,ifnotset) req.cook(sessionJwt)\n+    http-request set-var(req.jwt_alg) var(req.bearer),jwt_header_query('$.alg')\n+    http-request set-var(req.exp,ifnotempty) var(req.bearer),jwt_payload_query('$.exp','int')\n+    http-request set-var(req.exp,ifnotset) var(req.bearer),jwt_payload_query('$.sxp','int')\n+    http-request set-var(req.now) date()\n+    # validate the algorithm\n+    acl is_valid_jwt_alg var(req.jwt_alg) -m str \"RS256\"\n+    # validate the signature\n+    acl is_valid_jwt_sig var(req.bearer),jwt_verify(req.jwt_alg,\"/etc/haproxy/jwt/mw-oauth-2025-07-31.key\") 1\n+    # validate the exp date: this is part of the JWT payload so it should be validated after ensuring that the signature is valid\n+    acl is_valid_jwt_exp_date var(req.exp),sub(req.now) -m int ge 0\n+    # We exclude trusted (A) and bot (B) requests here to avoid downgrading to C, but we open the\n+    # door for potential upgrades from F to C.\n+    http-request set-var(req.trusted_request) str(C) if !is_trusted_request !is_identified_bot_request is_valid_jwt_alg is_valid_jwt_sig is_valid_jwt_exp_date\n+    # If the jwt is correctly signed, save the subject in a header we will remove in varnish. This also applies to trusted requests.\n+    http-request set-header X-JWT-Sub %[var(req.bearer),jwt_payload_query('$.sub')] if is_valid_jwt_alg is_valid_jwt_sig is_valid_jwt_exp_date\n \n     # Following configuration is used to classify clients as \"user|robot|other\" based on UA string\n     # Initialize req.ua_class"}, {"resource": "Confd::File[/etc/haproxy/conf.d/tls.cfg]"}, {"resource": "File[/etc/haproxy/jwt]", "parameters": "--- File[/etc/haproxy/jwt].orig\n+++ File[/etc/haproxy/jwt]\n\n@@\n-    ensure  => absent\n+    ensure  => directory\n@@\n-    recurse => False\n+    recurse => True\n"}], "perc_changed": "0.10%"}, "core": {"total": 3969, "only_in_self": [], "only_in_other": [], "resource_diffs": [{"resource": "File[/etc/haproxy/jwt]", "parameters": "--- File[/etc/haproxy/jwt].orig\n+++ File[/etc/haproxy/jwt]\n\n@@\n-    ensure  => absent\n+    ensure  => directory\n@@\n-    recurse => False\n+    recurse => True\n"}, {"resource": "File[/etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl]", "content": "--- /etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl.orig\n+++ /etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl\n@@ -120,6 +120,7 @@\n     http-request del-header tracestate if !wikimedia_trust\n     http-request del-header traceparent if !wikimedia_trust\n     http-request del-header X-Experiment-Enrollments\n+    http-request del-header X-JWT-Sub\n \n     # Copy X-Analytics hdr into var to safely log it after deletion\n     http-response set-var(txn.x_analytics,ifnotempty) res.fhdr(X-Analytics)\n@@ -271,6 +272,23 @@\n     acl is_identified_bot_request var(req.trusted_request) -m str B\n     acl is_auth_request var(req.trusted_request) -m str C\n \n+    http-request set-var(req.bearer) http_auth_bearer if { req.fhdr(Authorization) -m found }\n+    http-request set-var(req.bearer,ifnotset) req.cook(sessionJwt)\n+    http-request set-var(req.jwt_alg) var(req.bearer),jwt_header_query('$.alg')\n+    http-request set-var(req.exp,ifnotempty) var(req.bearer),jwt_payload_query('$.exp','int')\n+    http-request set-var(req.exp,ifnotset) var(req.bearer),jwt_payload_query('$.sxp','int')\n+    http-request set-var(req.now) date()\n+    # validate the algorithm\n+    acl is_valid_jwt_alg var(req.jwt_alg) -m str \"RS256\"\n+    # validate the signature\n+    acl is_valid_jwt_sig var(req.bearer),jwt_verify(req.jwt_alg,\"/etc/haproxy/jwt/mw-oauth-2025-07-31.key\") 1\n+    # validate the exp date: this is part of the JWT payload so it should be validated after ensuring that the signature is valid\n+    acl is_valid_jwt_exp_date var(req.exp),sub(req.now) -m int ge 0\n+    # We exclude trusted (A) and bot (B) requests here to avoid downgrading to C, but we open the\n+    # door for potential upgrades from F to C.\n+    http-request set-var(req.trusted_request) str(C) if !is_trusted_request !is_identified_bot_request is_valid_jwt_alg is_valid_jwt_sig is_valid_jwt_exp_date\n+    # If the jwt is correctly signed, save the subject in a header we will remove in varnish. This also applies to trusted requests.\n+    http-request set-header X-JWT-Sub %[var(req.bearer),jwt_payload_query('$.sub')] if is_valid_jwt_alg is_valid_jwt_sig is_valid_jwt_exp_date\n \n     # Following configuration is used to classify clients as \"user|robot|other\" based on UA string\n     # Initialize req.ua_class"}], "perc_changed": "0.05%"}, "main": {"total": 3969, "only_in_self": [], "only_in_other": [], "resource_diffs": [{"resource": "Confd::File[/etc/haproxy/conf.d/tls.cfg]"}, {"resource": "File[/etc/haproxy/jwt]", "parameters": "--- File[/etc/haproxy/jwt].orig\n+++ File[/etc/haproxy/jwt]\n\n@@\n-    ensure  => absent\n+    ensure  => directory\n@@\n-    recurse => False\n+    recurse => True\n"}, {"resource": "Haproxy::Confd_site[tls]"}, {"resource": "File[/etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl]", "content": "--- /etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl.orig\n+++ /etc/confd/templates/_etc_haproxy_conf.d_tls.cfg.tmpl\n@@ -120,6 +120,7 @@\n     http-request del-header tracestate if !wikimedia_trust\n     http-request del-header traceparent if !wikimedia_trust\n     http-request del-header X-Experiment-Enrollments\n+    http-request del-header X-JWT-Sub\n \n     # Copy X-Analytics hdr into var to safely log it after deletion\n     http-response set-var(txn.x_analytics,ifnotempty) res.fhdr(X-Analytics)\n@@ -271,6 +272,23 @@\n     acl is_identified_bot_request var(req.trusted_request) -m str B\n     acl is_auth_request var(req.trusted_request) -m str C\n \n+    http-request set-var(req.bearer) http_auth_bearer if { req.fhdr(Authorization) -m found }\n+    http-request set-var(req.bearer,ifnotset) req.cook(sessionJwt)\n+    http-request set-var(req.jwt_alg) var(req.bearer),jwt_header_query('$.alg')\n+    http-request set-var(req.exp,ifnotempty) var(req.bearer),jwt_payload_query('$.exp','int')\n+    http-request set-var(req.exp,ifnotset) var(req.bearer),jwt_payload_query('$.sxp','int')\n+    http-request set-var(req.now) date()\n+    # validate the algorithm\n+    acl is_valid_jwt_alg var(req.jwt_alg) -m str \"RS256\"\n+    # validate the signature\n+    acl is_valid_jwt_sig var(req.bearer),jwt_verify(req.jwt_alg,\"/etc/haproxy/jwt/mw-oauth-2025-07-31.key\") 1\n+    # validate the exp date: this is part of the JWT payload so it should be validated after ensuring that the signature is valid\n+    acl is_valid_jwt_exp_date var(req.exp),sub(req.now) -m int ge 0\n+    # We exclude trusted (A) and bot (B) requests here to avoid downgrading to C, but we open the\n+    # door for potential upgrades from F to C.\n+    http-request set-var(req.trusted_request) str(C) if !is_trusted_request !is_identified_bot_request is_valid_jwt_alg is_valid_jwt_sig is_valid_jwt_exp_date\n+    # If the jwt is correctly signed, save the subject in a header we will remove in varnish. This also applies to trusted requests.\n+    http-request set-header X-JWT-Sub %[var(req.bearer),jwt_payload_query('$.sub')] if is_valid_jwt_alg is_valid_jwt_sig is_valid_jwt_exp_date\n \n     # Following configuration is used to classify clients as \"user|robot|other\" based on UA string\n     # Initialize req.ua_class"}], "perc_changed": "0.10%"}}}