From f719e20cb7c8859e473f0b42a29659cb3695406a Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Sat, 12 Sep 2026 15:55:58 +1000 Subject: [PATCH] allow catalog-diff to compile catalogs on the puppet compilers --- .../deployment_puppetserver-compiler.yaml | 13 + apps/base/puppet/kustomization.yaml | 10 + .../puppet/resources/compiler/10-auth-conf.sh | 14 + apps/base/puppet/resources/compiler/auth.conf | 320 ++++++++++++++++++ 4 files changed, 357 insertions(+) create mode 100755 apps/base/puppet/resources/compiler/10-auth-conf.sh create mode 100644 apps/base/puppet/resources/compiler/auth.conf diff --git a/apps/base/puppet/deployment_puppetserver-compiler.yaml b/apps/base/puppet/deployment_puppetserver-compiler.yaml index f0d23d2..60afefe 100644 --- a/apps/base/puppet/deployment_puppetserver-compiler.yaml +++ b/apps/base/puppet/deployment_puppetserver-compiler.yaml @@ -99,6 +99,12 @@ spec: - mountPath: /docker-custom-entrypoint.d/post-startup/additional-ruby-gems.sh name: additional-ruby-gems subPath: additional-ruby-gems.sh + - mountPath: /configmaps/auth.conf + name: compiler-auth-conf + subPath: auth.conf + - mountPath: /docker-custom-entrypoint.d/pre-default/10-auth-conf.sh + name: compiler-auth-conf-seed + subPath: 10-auth-conf.sh initContainers: - name: copy-configmaps image: busybox:1.35 @@ -234,5 +240,12 @@ spec: configMap: name: additional-ruby-gems defaultMode: 0755 + - name: compiler-auth-conf + configMap: + name: compiler-auth.conf + - name: compiler-auth-conf-seed + configMap: + name: compiler-auth-conf-seed + defaultMode: 0755 strategy: type: RollingUpdate diff --git a/apps/base/puppet/kustomization.yaml b/apps/base/puppet/kustomization.yaml index be51457..a09582e 100644 --- a/apps/base/puppet/kustomization.yaml +++ b/apps/base/puppet/kustomization.yaml @@ -54,6 +54,16 @@ configMapGenerator: - resources/compiler/puppetdb.conf options: disableNameSuffixHash: true + - name: compiler-auth.conf + files: + - resources/compiler/auth.conf + options: + disableNameSuffixHash: true + - name: compiler-auth-conf-seed + files: + - resources/compiler/10-auth-conf.sh + options: + disableNameSuffixHash: true - name: additional-ruby-gems files: - resources/additional-ruby-gems.sh diff --git a/apps/base/puppet/resources/compiler/10-auth-conf.sh b/apps/base/puppet/resources/compiler/10-auth-conf.sh new file mode 100755 index 0000000..0fd4147 --- /dev/null +++ b/apps/base/puppet/resources/compiler/10-auth-conf.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -euo pipefail + +SRC=/configmaps/auth.conf +DST=/etc/puppetlabs/puppetserver/conf.d/auth.conf + +# Copied rather than mounted: the entrypoint chowns conf.d and rewrites auth.conf, +# both of which fail on a read-only configmap mount and abort container startup. +if [ ! -s "$SRC" ]; then + echo "FATAL: $SRC missing or empty; refusing to start on the image default auth.conf" >&2 + exit 1 +fi + +cp "$SRC" "$DST" diff --git a/apps/base/puppet/resources/compiler/auth.conf b/apps/base/puppet/resources/compiler/auth.conf new file mode 100644 index 0000000..94241eb --- /dev/null +++ b/apps/base/puppet/resources/compiler/auth.conf @@ -0,0 +1,320 @@ +# Copied into conf.d at startup by 10-auth-conf.sh; the entrypoint then appends the +# admin API cache rule and re-renders the result, so the running file is not byte-identical. +authorization: { + version: 1 + rules: [ + { + # Allow nodes to retrieve their own catalog + match-request: { + path: "^/puppet/v3/catalog/([^/]+)$" + type: regex + method: [get, post] + } + allow: "$1" + sort-order: 500 + name: "puppetlabs v3 catalog from agents" + }, + { + # Allow catalog-diff to retrieve catalogs on behalf of others. + # sort-order 400 must stay lower than the puppetlabs deny that follows: rules + # sort by [sort-order, name] and the first match wins. + match-request: { + path: "^/puppet/v4/catalog/?$" + type: regex + method: post + } + allow: "catalog-diff.main.unkin.net" + sort-order: 400 + name: "unkin v4 catalog for catalog-diff" + }, + { + # Allow services to retrieve catalogs on behalf of others + match-request: { + path: "^/puppet/v4/catalog/?$" + type: regex + method: post + } + deny: "*" + sort-order: 500 + name: "puppetlabs v4 catalog for services" + }, + { + # Allow nodes to retrieve the certificate they requested earlier + match-request: { + path: "/puppet-ca/v1/certificate/" + type: path + method: get + } + allow-unauthenticated: true + sort-order: 500 + name: "puppetlabs certificate" + }, + { + # Allow all nodes to access the certificate revocation list + match-request: { + path: "/puppet-ca/v1/certificate_revocation_list/ca" + type: path + method: get + } + allow-unauthenticated: true + sort-order: 500 + name: "puppetlabs crl" + }, + { + # Allow nodes to request a new certificate + match-request: { + path: "/puppet-ca/v1/certificate_request" + type: path + method: [get, put] + } + allow-unauthenticated: true + sort-order: 500 + name: "puppetlabs csr" + }, + { + # Allow nodes to renew their certificate + match-request: { + path: "/puppet-ca/v1/certificate_renewal" + type: path + method: post + } + # this endpoint should never be unauthenticated, as it requires the cert to be provided. + allow: "*" + sort-order: 500 + name: "puppetlabs certificate renewal" + }, + { + # Allow the CA CLI to access the certificate_status endpoint + match-request: { + path: "/puppet-ca/v1/certificate_status" + type: path + method: [get, put, delete] + } + allow: { + extensions: { + pp_cli_auth: "true" + } + } + sort-order: 500 + name: "puppetlabs cert status" + }, + { + match-request: { + path: "^/puppet-ca/v1/certificate_revocation_list$" + type: regex + method: put + } + allow: { + extensions: { + pp_cli_auth: "true" + } + } + sort-order: 500 + name: "puppetlabs CRL update" + }, + { + # Allow the CA CLI to access the certificate_statuses endpoint + match-request: { + path: "/puppet-ca/v1/certificate_statuses" + type: path + method: get + } + allow: { + extensions: { + pp_cli_auth: "true" + } + } + sort-order: 500 + name: "puppetlabs cert statuses" + }, + { + # Allow authenticated access to the CA expirations endpoint + match-request: { + path: "/puppet-ca/v1/expirations" + type: path + method: get + } + allow: "*" + sort-order: 500 + name: "puppetlabs CA cert and CRL expirations" + }, + { + # Allow the CA CLI to access the certificate clean endpoint + match-request: { + path: "/puppet-ca/v1/clean" + type: path + method: put + } + allow: { + extensions: { + pp_cli_auth: "true" + } + } + sort-order: 500 + name: "puppetlabs cert clean" + }, + { + # Allow the CA CLI to access the certificate sign endpoint + match-request: { + path: "/puppet-ca/v1/sign" + type: path + method: post + } + allow: { + extensions: { + pp_cli_auth: "true" + } + } + sort-order: 500 + name: "puppetlabs cert sign" + }, + { + # Allow the CA CLI to access the certificate sign all endpoint + match-request: { + path: "/puppet-ca/v1/sign/all" + type: path + method: post + } + allow: { + extensions: { + pp_cli_auth: "true" + } + } + sort-order: 500 + name: "puppetlabs cert sign all" + }, + { + # Allow unauthenticated access to the status service endpoint + match-request: { + path: "/status/v1/services" + type: path + method: get + } + allow-unauthenticated: true + sort-order: 500 + name: "puppetlabs status service - full" + }, + { + match-request: { + path: "/status/v1/simple" + type: path + method: get + } + allow-unauthenticated: true + sort-order: 500 + name: "puppetlabs status service - simple" + }, + { + match-request: { + path: "/puppet/v3/environments" + type: path + method: get + } + allow: "*" + sort-order: 500 + name: "puppetlabs environments" + }, + { + # Allow nodes to access all file_bucket_files. Note that access for + # the 'delete' method is forbidden by Puppet regardless of the + # configuration of this rule. + match-request: { + path: "/puppet/v3/file_bucket_file" + type: path + method: [get, head, post, put] + } + allow: "*" + sort-order: 500 + name: "puppetlabs file bucket file" + }, + { + # Allow nodes to access all file_content. Note that access for the + # 'delete' method is forbidden by Puppet regardless of the + # configuration of this rule. + match-request: { + path: "/puppet/v3/file_content" + type: path + method: [get, post] + } + allow: "*" + sort-order: 500 + name: "puppetlabs file content" + }, + { + # Allow nodes to access all file_metadata. Note that access for the + # 'delete' method is forbidden by Puppet regardless of the + # configuration of this rule. + match-request: { + path: "/puppet/v3/file_metadata" + type: path + method: [get, post] + } + allow: "*" + sort-order: 500 + name: "puppetlabs file metadata" + }, + { + # Allow nodes to retrieve only their own node definition + match-request: { + path: "^/puppet/v3/node/([^/]+)$" + type: regex + method: get + } + allow: "$1" + sort-order: 500 + name: "puppetlabs node" + }, + { + # Allow nodes to store only their own reports + match-request: { + path: "^/puppet/v3/report/([^/]+)$" + type: regex + method: put + } + allow: "$1" + sort-order: 500 + name: "puppetlabs report" + }, + { + # Allow nodes to update their own facts + match-request: { + path: "^/puppet/v3/facts/([^/]+)$" + type: regex + method: put + } + allow: "$1" + sort-order: 500 + name: "puppetlabs facts" + }, + { + match-request: { + path: "/puppet/v3/static_file_content" + type: path + method: get + } + allow: "*" + sort-order: 500 + name: "puppetlabs static file content" + }, + { + match-request: { + path: "/puppet/v3/tasks" + type: path + } + allow: "*" + sort-order: 500 + name: "puppet tasks information" + }, + { + # Deny everything else. This ACL is not strictly + # necessary, but illustrates the default policy + match-request: { + path: "/" + type: path + } + deny: "*" + sort-order: 999 + name: "puppetlabs deny all" + } + ] +} -- 2.47.3