pax_global_header00006660000000000000000000000064147034533740014524gustar00rootroot0000000000000052 comment=cfdc2654a9c724fef9320dfc3204b594d3746600 puppetlabs-puppetserver-7e1a9a8/000077500000000000000000000000001470345337400170665ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.clj-kondo/000077500000000000000000000000001470345337400210245ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.clj-kondo/config.edn000066400000000000000000000065711470345337400227720ustar00rootroot00000000000000{:linters {:use {:level :error} :unresolved-symbol {:level :warning :exclude [(clojure.test/is [thrown+? thrown+-with-msg? logged?]) (puppetlabs.puppetserver.bootstrap-testutils/with-puppetserver-running [app]) (puppetlabs.puppetserver.bootstrap-testutils/with-puppetserver-running-with-mock-jrubies [app]) (puppetlabs.puppetserver.bootstrap-testutils/with-puppetserver-running-with-config [app]) (puppetlabs.puppetserver.bootstrap-testutils/with-puppetserver-running-with-mock-jruby-puppet-fn [app]) (puppetlabs.puppetserver.bootstrap-testutils/with-puppetserver-running-with-services [app]) (puppetlabs.puppetserver.bootstrap-testutils/with-puppetserver-running-with-services-and-mock-jruby-puppet-fn [app]) (puppetlabs.puppetserver.ruby.http-client-test/with-scripting-container [sc]) (puppetlabs.services.jruby.jruby-metrics-service-test/with-metrics-test-env) (puppetlabs.services.jruby.jruby-puppet-service/with-jruby-puppet [jruby-puppet]) (puppetlabs.services.jruby-pool-manager.jruby-core/with-jruby-instance [jruby-instance]) (puppetlabs.services.puppet-profiler.puppet-profiler-core-test/with-test-logs [logs]) (puppetlabs.trapperkeeper.core/defservice) (puppetlabs.trapperkeeper.core/service) (puppetlabs.trapperkeeper.services/service) (puppetlabs.trapperkeeper.testutils.bootstrap/with-app-with-config [app]) (puppetlabs.trapperkeeper.testutils.logging/with-log-output [logs]) (puppetlabs.trapperkeeper.testutils.webserver/with-test-webserver [port]) (slingshot.slingshot/try+ [&throw-context])]} :invalid-arity {:skip-args [puppetlabs.trapperkeeper.core/service puppetlabs.trapperkeeper.services/service]} :refer-all {:exclude [clojure.test slingshot.test]}} :lint-as {puppetlabs.comidi/GET compojure.core/GET puppetlabs.comidi/PUT compojure.core/PUT puppetlabs.comidi/POST compojure.core/POST puppetlabs.comidi/DELETE compojure.core/DELETE puppetlabs.comidi/PATCH compojure.core/PATCH puppetlabs.comidi/ANY compojure.core/ANY puppetlabs.comidi/HEAD compojure.core/HEAD liberator.core/defresource clojure.core/defn puppetlabs.trapperkeeper.core/defservice clojure.core/def slingshot.slingshot/try+ clojure.core/try} :config-in-call {puppetlabs.services.request-handler.request-handler-core/ssl-auth-info {:linters {:not-empty? {:level :off}}}} :output {:linter-name true}} puppetlabs-puppetserver-7e1a9a8/.clj-kondo/imports/000077500000000000000000000000001470345337400225215ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.clj-kondo/imports/clj-kondo/000077500000000000000000000000001470345337400244015ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.clj-kondo/imports/clj-kondo/slingshot/000077500000000000000000000000001470345337400264135ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.clj-kondo/imports/clj-kondo/slingshot/clj_kondo/000077500000000000000000000000001470345337400303555ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.clj-kondo/imports/clj-kondo/slingshot/clj_kondo/slingshot/000077500000000000000000000000001470345337400323675ustar00rootroot00000000000000try_plus.clj000066400000000000000000000032751470345337400346720ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.clj-kondo/imports/clj-kondo/slingshot/clj_kondo/slingshot(ns clj-kondo.slingshot.try-plus (:require [clj-kondo.hooks-api :as api])) (defn expand-catch [catch-node] (let [[catch catchee & exprs] (:children catch-node) catchee-sexpr (api/sexpr catchee)] (cond (vector? catchee-sexpr) (let [[selector & exprs] exprs] (api/list-node [catch (api/token-node 'Exception) (api/token-node '_e#) (api/list-node (list* (api/token-node 'let) (api/vector-node [selector (api/token-node nil)]) exprs))])) :else catch-node))) (defn try+ [{:keys [node]}] (let [children (rest (:children node)) [body catches] (loop [body children body-exprs [] catches []] (if (seq body) (let [f (first body) f-sexpr (api/sexpr f)] (if (and (seq? f-sexpr) (= 'catch (first f-sexpr))) (recur (rest body) body-exprs (conj catches (expand-catch f))) (recur (rest body) (conj body-exprs f) catches))) [body-exprs catches])) new-node (api/list-node [(api/token-node 'let) (api/vector-node [(api/token-node '&throw-context) (api/token-node nil)]) (api/token-node '&throw-context) ;; use throw-context to avoid warning (with-meta (api/list-node (list* (api/token-node 'try) (concat body catches))) (meta node))])] ;; (prn (api/sexpr new-node)) {:node new-node})) puppetlabs-puppetserver-7e1a9a8/.clj-kondo/imports/clj-kondo/slingshot/config.edn000066400000000000000000000001271470345337400303500ustar00rootroot00000000000000{:hooks {:analyze-call {slingshot.slingshot/try+ clj-kondo.slingshot.try-plus/try+}}} puppetlabs-puppetserver-7e1a9a8/.dir-locals.el000066400000000000000000000001011470345337400215070ustar00rootroot00000000000000((clojure-mode . ((cider-inject-dependencies-at-jack-in . ())))) puppetlabs-puppetserver-7e1a9a8/.dockerignore000066400000000000000000000001121470345337400215340ustar00rootroot00000000000000* !.git !project.clj !docker !documentation !ezbake !resources !ruby !src puppetlabs-puppetserver-7e1a9a8/.gitattributes000066400000000000000000000006201470345337400217570ustar00rootroot00000000000000project.clj merge=version-mergeup acceptance/config/beaker/options.rb merge=version-mergeup documentation/release_notes.markdown merge=ours resources/ext/build-scripts/mri-gem-list-no-deps.txt merge=ours docker/** text eol=lf resources/ext/build-scripts/* text eol=lf resources/ext/cli_defaults/* text eol=lf resources/ext/cli/* text eol=lf puppetlabs-puppetserver-7e1a9a8/.github/000077500000000000000000000000001470345337400204265ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.github/workflows/000077500000000000000000000000001470345337400224635ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/.github/workflows/clojure-linting.yaml000066400000000000000000000014121470345337400264520ustar00rootroot00000000000000name: Clojure Linting on: pull_request: types: [opened, reopened, edited, synchronize] paths: ['src/**','test/**','.clj-kondo/config.edn','project.clj','.github/**'] jobs: clojure-linting: name: Clojure Linting runs-on: ubuntu-latest steps: - name: setup java uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 - name: checkout repo uses: actions/checkout@v2 - name: install clj-kondo (this is quite fast) run: | curl -sLO https://raw.githubusercontent.com/clj-kondo/clj-kondo/master/script/install-clj-kondo chmod +x install-clj-kondo ./install-clj-kondo --dir . - name: kondo lint run: ./clj-kondo --lint src test puppetlabs-puppetserver-7e1a9a8/.github/workflows/docker.yml000066400000000000000000000030321470345337400244530ustar00rootroot00000000000000name: Docker test and publish on: push: branches: - main jobs: build-and-publish: env: PUPPERWARE_ANALYTICS_STREAM: production IS_LATEST: true DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: Set up Ruby 2.6 uses: actions/setup-ruby@v1 with: ruby-version: 2.6.x - run: gem install bundler - name: Build container working-directory: docker run: | docker system prune --all --force --volumes docker builder prune --force --keep-storage=10GB make lint build test - name: Publish container working-directory: docker run: | docker login -u "$DOCKERHUB_USERNAME" -p "$DOCKERHUB_PASSWORD" make publish - name: Build release container env: IS_RELEASE: true working-directory: docker shell: bash {0} run: | make prep if [ $? -eq 0 ]; then make lint build test else echo "Skipping release container building and testing" fi - name: Publish release container env: IS_RELEASE: true working-directory: docker shell: bash {0} run: | make prep if [ $? -eq 0 ]; then make publish else echo "Skipping release container publishing" fi puppetlabs-puppetserver-7e1a9a8/.github/workflows/mend.yaml000066400000000000000000000034631470345337400243000ustar00rootroot00000000000000name: mend_scan on: workflow_dispatch: push: branches: - main - 7.x jobs: build: runs-on: ubuntu-latest steps: - name: connect_twingate uses: twingate/github-action@v1 with: service-key: ${{ secrets.TWINGATE_PUBLIC_REPO_KEY }} - name: checkout repo content uses: actions/checkout@v2 # checkout the repository content to github runner. with: fetch-depth: 1 # install java which is required for mend and clojure - name: setup java uses: actions/setup-java@v3 with: distribution: temurin java-version: 17 # install clojure tools - name: Install Clojure tools uses: DeLaGuardo/setup-clojure@10.1 with: # Install just one or all simultaneously # The value must indicate a particular version of the tool, or use 'latest' # to always provision the latest version cli: latest # Clojure CLI based on tools.deps lein: latest # Leiningen boot: latest # Boot.clj bb: latest # Babashka clj-kondo: latest # Clj-kondo cljstyle: latest # cljstyle zprint: latest # zprint # run lein gen - name: create pom.xml run: lein pom # download mend - name: download_mend run: curl -o wss-unified-agent.jar https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar - name: run mend run: env WS_INCLUDES=pom.xml java -jar wss-unified-agent.jar env: WS_APIKEY: ${{ secrets.MEND_API_KEY }} WS_WSS_URL: https://saas-eu.whitesourcesoftware.com/agent WS_USERKEY: ${{ secrets.MEND_TOKEN }} WS_PRODUCTNAME: Puppet Enterprise WS_PROJECTNAME: ${{ github.event.repository.name }} puppetlabs-puppetserver-7e1a9a8/.github/workflows/pr-testing.yaml000066400000000000000000000017551470345337400254530ustar00rootroot00000000000000name: PR Testing on: workflow_dispatch: pull_request: types: [opened, reopened, edited, synchronize] paths: ['src/**','test/**','project.clj'] jobs: pr-testing: name: PR Testing strategy: fail-fast: false matrix: javaargs: ['with-profile fips', ''] filter: [':singlethreaded', ':multithreaded'] version: ['11', '17'] runs-on: ubuntu-latest steps: - name: checkout repo uses: actions/checkout@v3 with: submodules: recursive - name: setup java uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: ${{ matrix.version }} - name: setup ruby uses: ruby/setup-ruby@v1 with: ruby-version: '3.1' - name: setup gems run: ./dev-setup - name: clojure tests run: lein -U ${{ matrix.javaargs }} test ${{ matrix.filter }} timeout-minutes: 30 - name: rspec tests run: rake spec puppetlabs-puppetserver-7e1a9a8/.gitignore000066400000000000000000000007471470345337400210660ustar00rootroot00000000000000scratch pom.xml *jar /lib/ /classes/ /output/ /targets/ .lein-deps-sum .lein-failures target/ log .bundle .vagrant vendor .nrepl-port profiles.clj dev/user.clj .lein-repl-history ext/packaging checkouts .beaker .clj-kondo/.cache .eastwood # Bundler local state files Gemfile.lock Gemfile.local /.bundle/ # Local test runs drop files into junit and tmp /junit/ /tmp/ acceptance/scripts/hosts.cfg /resources/locales.clj /resources/puppetlabs/puppetserver/*.class /dev-resources/i18n/bin puppetlabs-puppetserver-7e1a9a8/.gitmodules000066400000000000000000000006161470345337400212460ustar00rootroot00000000000000[submodule "ruby/puppet"] path = ruby/puppet url = https://github.com/puppetlabs/puppet.git [submodule "ruby/hiera"] path = ruby/hiera url = https://github.com/puppetlabs/hiera.git [submodule "ruby/resource_api"] path = ruby/resource_api url = https://github.com/puppetlabs/puppet-resource_api.git [submodule "ruby/facter"] path = ruby/facter url = https://github.com/puppetlabs/facter.git puppetlabs-puppetserver-7e1a9a8/.travis.yml000066400000000000000000000021521470345337400211770ustar00rootroot00000000000000language: clojure lein: 2.9.10 dist: jammy os: linux script: - ./ext/travisci/install-java.sh - ./ext/travisci/test.sh jobs: # NOTE: Puppet does not officially support the s390x architecture. # Testing against this architecture provides value to the open source community, # but we make no promises about its functionality and may ignore any test failures # that arise when testing against s390x. allow_failures: - arch: s390x include: - name: "Java 17" env: - JAVA_VERSION=17 - name: "Java 17 w/ FIPS" env: - JAVA_VERSION=17 - ADDITIONAL_LEIN_ARGS="with-profile fips" - name: "Java 17 w/ multithreaded" env: - JAVA_VERSION=17 - MULTITHREADED=true - name: "Java 17 (s390x)" env: - JAVA_VERSION=17 arch: s390x - name: "Java 17 w/ FIPS (s390x)" env: - JAVA_VERSION=17 - ADDITIONAL_LEIN_ARGS="with-profile fips" arch: s390x - name: "Java 17 w/ multithreaded (s390x)" env: - JAVA_VERSION=17 - MULTITHREADED=true arch: s390x notifications: email: false puppetlabs-puppetserver-7e1a9a8/CODEOWNERS000066400000000000000000000001261470345337400204600ustar00rootroot00000000000000# This repo is owned by the dumpling team * @puppetlabs/dumpling @puppetlabs/skeletor puppetlabs-puppetserver-7e1a9a8/Gemfile000066400000000000000000000026501470345337400203640ustar00rootroot00000000000000source ENV['GEM_SOURCE'] || 'https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/' def location_for(place, fake_version = nil) if place.is_a?(String) && place =~ /^(git[:@][^#]*)#(.*)/ [fake_version, { :git => $1, :branch => $2, :require => false }].compact elsif place.is_a?(String) && place =~ /^file:\/\/(.*)/ ['>= 0', { :path => File.expand_path($1), :require => false }] else [place, { :require => false }] end end # The public_suffix gem used in the dependencies for the packaging gem no longer supports Ruby 2.5 # and bundler is not smart enough to realize that an older version would work in the mix. gem 'public_suffix', '= 4.0.7' gem 'packaging', *location_for(ENV['PACKAGING_LOCATION'] || '~> 0.99') gem 'rake', :group => [:development, :test] group :test do gem 'rspec' gem 'beaker', *location_for(ENV['BEAKER_VERSION'] || '~> 6.0') gem "beaker-hostgenerator", *location_for(ENV['BEAKER_HOSTGENERATOR_VERSION'] || "~> 2.4") gem "beaker-abs", *location_for(ENV['BEAKER_ABS_VERSION'] || "~> 1.0") gem "beaker-vmpooler", *location_for(ENV['BEAKER_VMPOOLER_VERSION'] || "~> 1.3") gem "beaker-puppet", *location_for(ENV['BEAKER_PUPPET_VERSION'] || "~> 4.0") gem 'uuidtools' gem 'httparty' gem 'master_manipulator' # docker-api 1.32.0 requires ruby 2.0.0 gem 'docker-api', '1.31.0' end if File.exist? "#{__FILE__}.local" eval(File.read("#{__FILE__}.local"), binding) end puppetlabs-puppetserver-7e1a9a8/LICENSE.md000066400000000000000000000260751470345337400205040ustar00rootroot00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. puppetlabs-puppetserver-7e1a9a8/Makefile000066400000000000000000000000441470345337400205240ustar00rootroot00000000000000include dev-resources/Makefile.i18n puppetlabs-puppetserver-7e1a9a8/README.md000066400000000000000000000125261470345337400203530ustar00rootroot00000000000000# Puppet Server [Puppet Server](https://puppet.com/docs/puppet/latest/server/about_server.html) implements Puppet's server-side components for managing [Puppet](https://puppet.com/docs/puppet/) agents in a distributed, service-oriented architecture. Puppet Server is built on top of the same technologies that make [PuppetDB](https://puppet.com/docs/puppetdb/) successful, and which allow us to greatly improve performance, scalability, advanced metrics collection, and fine-grained control over the Ruby runtime. ## Release notes For information about the current and most recent versions of Puppet Server, see the [release notes](https://puppet.com/docs/puppet/latest/server/release_notes.html). ## Installing Puppet Server See [Installing Puppet Server from Packages](https://puppet.com/docs/puppet/latest/server/install_from_packages.html) for complete installation requirements and instructions. ## Ruby and Puppet Server Puppet Server uses its own JRuby interpreter, which doesn't load gems or other code from your system Ruby. If you want Puppet Server to load additional gems, use the Puppet Server-specific `gem` command to install them. See [Puppet Server and Gems](https://puppet.com/docs/puppet/latest/server/gems.html) for more information about gems and Puppet Server. ## Configuration Puppet Server honors almost all settings in `puppet.conf` and should pick them up automatically. However, we have also introduced some new settings specific to Puppet Server. See the [Configuration](https://puppet.com/docs/puppet/latest/server/configuration.html) documentation for details. For more information on the differences between Puppet Server's support for `puppet.conf` settings and the Ruby master's, see our documentation of [differences in `puppet.conf`](https://puppet.com/docs/puppet/latest/server/puppet_conf_setting_diffs.html). ### Certificate authority configuration Puppet can use its built-in certificate authority (CA) and public key infrastructure (PKI) tools or use an existing external CA for all of its secure socket layer (SSL) communications. See certificate authority [docs](https://puppet.com/docs/puppet/latest/ssl_certificates.html) for details. ### SSL configuration In network configurations that require external SSL termination, you need to do a few things differently in Puppet Server. See [External SSL Termination](https://puppet.com/docs/puppet/latest/server/external_ssl_termination.html) for details. ## Command-line utilities Puppet Server provides several command-line utilities for development and debugging purposes. These commands are all aware of [`puppetserver.conf`](https://puppet.com/docs/puppet/latest/server/configuration.html), as well as the gems and Ruby code specific to Puppet Server and Puppet, while keeping them isolated from your system Ruby. For more information, see [Puppet Server Subcommands](https://puppet.com/docs/puppet/latest/server/subcommands.html). ## Known issues As this application is still in development, there are a few [known issues](https://puppet.com/docs/puppet/latest/server/known_issues.html) that you should be aware of. ## Developer documentation If want to play with our code, these documents should prove useful: - [Running Puppet Server from source](https://puppet.com/docs/puppet/latest/server/dev_running_from_source.html) - [Debugging](https://puppet.com/docs/puppet/latest/server/dev_debugging.html) - [Puppet Server subcommands](https://puppet.com/docs/puppet/latest/server/subcommands.html) Puppet Server also uses the [Trapperkeeper](https://github.com/puppetlabs/trapperkeeper) Clojure framework. ## Testing To run lein tests, do the following: - Clone the repo with the `--recursive` flag, or after cloning, do `git submodule init && git submodule update` - Run `./dev-setup` - Run `lein test` ## Branching strategy Puppet Server's branching strategy is documented on the [GitHub repo wiki](https://github.com/puppetlabs/puppetserver/wiki/Branching-Strategy). ## Issue tracker Have feature requests, found a bug, or want to see what issues are in flight? Visit our [JIRA project](https://tickets.puppetlabs.com/browse/SERVER). ## License Copyright © 2013---2018 Puppet Distributed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). ## Special thanks to ### Cursive Clojure [Cursive](https://cursiveclojure.com/) is a Clojure IDE based on [IntelliJ IDEA](http://www.jetbrains.com/idea/download/index.html). Several of us at Puppet use it regularly and couldn't live without it. It's got some really great editing, refactoring, and debugging features, and the author, Colin Fleming, has been amazingly helpful and responsive when we have feedback. If you're a Clojure developer, you should definitely check it out! ### JRuby [JRuby](http://jruby.org/) is an implementation of the Ruby programming language that runs on the JVM. It's a fantastic project, and the bridge that allows us to run Puppet Ruby code while taking advantage of the JVM's advanced features and libraries. We're very grateful to the developers for building such a great product and for helping us work through a few bugs that we've discovered along the way. ## Maintenance Maintainers: See the [MAINTAINERS file](./MAINTAINERS) Tickets: For issues in o/s only: https://tickets.puppetlabs.com/browse/SERVER. For issues in PE: https://tickets.puppetlabs.com/browse/PE. Set component = Puppet Server puppetlabs-puppetserver-7e1a9a8/Rakefile000066400000000000000000000310511470345337400205330ustar00rootroot00000000000000require 'open3' require 'open-uri' require 'json' require 'pp' PROJECT_ROOT = File.dirname(__FILE__) ACCEPTANCE_ROOT = ENV['ACCEPTANCE_ROOT'] || File.join(PROJECT_ROOT, 'acceptance') BEAKER_OPTIONS_FILE = File.join(ACCEPTANCE_ROOT, 'config', 'beaker', 'options.rb') PUPPET_SRC = File.join(PROJECT_ROOT, 'ruby', 'puppet') PUPPET_LIB = File.join(PROJECT_ROOT, 'ruby', 'puppet', 'lib') FACTER_LIB = File.join(PROJECT_ROOT, 'ruby', 'facter', 'lib') PUPPET_SERVER_RUBY_SRC = File.join(PROJECT_ROOT, 'src', 'ruby', 'puppetserver-lib') PUPPET_SERVER_RUBY_SPEC = File.join(PROJECT_ROOT, 'spec') PUPPET_SUBMODULE_PATH = File.join('ruby','puppet') FACTER_SUBMODULE_PATH = File.join('ruby','facter') # Branch of puppetserver for which to update submodule pins PUPPETSERVER_BRANCH = ENV['PUPPETSERVER_BRANCH'] || 'main' # Branch of puppet-agent to track for passing puppet SHA PUPPET_AGENT_BRANCH = ENV['PUPPET_AGENT_BRANCH'] || 'main' # Branch of puppet-agent to track for Facter's passing SHA. # This needs to be separate because for 6.x, we want to use facter#main # instead of Facter 3. FACTER_BRANCH = ENV['FACTER_BRANCH'] || 'main' TEST_GEMS_DIR = File.join(PROJECT_ROOT, 'vendor', 'test_gems') TEST_BUNDLE_DIR = File.join(PROJECT_ROOT, 'vendor', 'test_bundle') GEM_SOURCE = ENV['GEM_SOURCE'] || "https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/" # Jenkins uses `$LEIN` configure the lein version to use LEIN_PATH = ENV['LEIN'] || 'lein' def assemble_default_beaker_config if ENV["BEAKER_CONFIG"] return ENV["BEAKER_CONFIG"] end platform = ENV['PLATFORM'] layout = ENV['LAYOUT'] if platform and layout beaker_config = "#{ACCEPTANCE_ROOT}/config/beaker/jenkins/" beaker_config += "#{platform}-#{layout}.cfg" else abort "Must specify an appropriate value for BEAKER_CONFIG. See acceptance/README.md" end return beaker_config end def setup_smoke_hosts_config sh "bundle exec beaker-hostgenerator centos7-64m-64a > acceptance/scripts/hosts.cfg" end def basic_smoke_test(package_version) beaker = "PACKAGE_BUILD_VERSION=#{package_version}" beaker += " bundle exec beaker --debug --root-keys --repo-proxy" beaker += " --preserve-hosts always" beaker += " --type aio" beaker += " --helper acceptance/lib/helper.rb" beaker += " --options-file #{BEAKER_OPTIONS_FILE}" beaker += " --load-path acceptance/lib" beaker += " --config acceptance/scripts/hosts.cfg" beaker += " --keyfile ~/.ssh/id_rsa-acceptance" beaker += " --pre-suite acceptance/suites/pre_suite/foss" beaker += " --post-suite acceptance/suites/post_suite" beaker += " --tests acceptance/suites/tests/00_smoke" sh beaker end # TODO: this could be DRY'd up with the method above, but it seemed like it # might make it a little harder to read and didn't seem worth the effort yet def re_run_basic_smoke_test beaker = "bundle exec beaker --debug --root-keys --repo-proxy" beaker += " --preserve-hosts always" beaker += " --type aio" beaker += " --helper acceptance/lib/helper.rb" beaker += " --options-file #{BEAKER_OPTIONS_FILE}" beaker += " --load-path acceptance/lib" beaker += " --config acceptance/scripts/hosts.cfg" beaker += " --keyfile ~/.ssh/id_rsa-acceptance" beaker += " --tests acceptance/suites/tests/00_smoke" sh beaker end def jenkins_passing_json_parsed(branch) passing_url = "http://builds.delivery.puppetlabs.net/passing-agent-SHAs/api/v1/json/report-#{branch}" uri = URI.parse(passing_url) begin # DO NOT use uri-open if accepting user input for the uri # we've done some simple correction here, # but not enough to cleanse malicious user input jenkins_result = uri.open(redirect: false) rescue OpenURI::HTTPError => e abort "ERROR: Could not get last passing run data for #{branch} of puppet-agent: '#{e.message}'" end begin jenkins_result_parsed = JSON.parse(jenkins_result.read) rescue JSON::ParserError => e abort "ERROR: Could not get valid json for last passing run of #{branch}: '#{e.message}'" end end def lookup_passing_puppetagent_sha(my_jenkins_passing_json) begin my_jenkins_passing_json['suite-commit'] rescue => e abort "ERROR: Could not get last passing suite-commit value for #{PUPPET_AGENT_BRANCH}\n\n #{e}" end end def lookup_passing_puppet_sha(my_jenkins_passing_json) begin my_jenkins_passing_json['puppet'] rescue => e abort "ERROR: Could not get puppet's last passing SHA for #{PUPPET_AGENT_BRANCH}\n\n #{e}" end end def lookup_passing_facter_sha(my_jenkins_passing_json) begin my_jenkins_passing_json['facter'] rescue => e abort "ERROR: Could not get facter's last passing SHA for #{FACTER_BRANCH}\n\n #{e}" end end def update_submodule(submodule_path, submodule_sha, submodule_name) # ensure we fetch here, or the describe done later could be wrong git_checkout_command = "cd #{submodule_path} && git fetch origin && " \ "git checkout #{submodule_sha}" puts("checking out known passing #{submodule_name} version in submodule: `#{git_checkout_command}`") system(git_checkout_command) end def replace_puppet_pins(passing_puppetagent_sha) # read beaker options hash from its file puts("replacing puppet-agent SHA in #{BEAKER_OPTIONS_FILE} " \ "with #{passing_puppetagent_sha}") beaker_options_from_file = eval(File.read(BEAKER_OPTIONS_FILE)) # add puppet-agent version value beaker_options_from_file[:puppet_build_version] = passing_puppetagent_sha File.write(BEAKER_OPTIONS_FILE, beaker_options_from_file.pretty_inspect) end namespace :dev_deps_update do desc 'update puppet submodule commit' task :update_puppet_version do my_jenkins_passing_json = jenkins_passing_json_parsed(PUPPET_AGENT_BRANCH) puppet_sha = lookup_passing_puppet_sha(my_jenkins_passing_json) update_submodule(PUPPET_SUBMODULE_PATH, puppet_sha, 'puppet') # replace puppet-agent sha pin in beaker options file replace_puppet_pins(lookup_passing_puppetagent_sha(my_jenkins_passing_json)) end desc 'update facter submodule commit' task :update_facter_version do my_jenkins_passing_json = jenkins_passing_json_parsed(FACTER_BRANCH) facter_sha = lookup_passing_facter_sha(my_jenkins_passing_json) update_submodule(FACTER_SUBMODULE_PATH, facter_sha, 'facter') end desc 'commit and push; CAUTION: WILL commit and push, upstream, local changes to the puppet submodule and acceptance options' task :commit_push do git_commit_command = "git checkout #{PUPPETSERVER_BRANCH} && git add #{PUPPET_SUBMODULE_PATH} " \ "&& git add #{FACTER_SUBMODULE_PATH} && git add #{BEAKER_OPTIONS_FILE} " \ "&& git commit -m '(maint) update submodule versions and agent pin'" git_push_command = "git checkout #{PUPPETSERVER_BRANCH} && git push origin HEAD:#{PUPPETSERVER_BRANCH}" puts "committing submodules and agent pin via: `#{git_commit_command}`" system(git_commit_command) puts "pushing submodules and agent pin via: `#{git_push_command}`" system(git_push_command) end desc 'update puppet versions and commit and push; CAUTION: WILL commit and push, upstream, local changes to the puppet submodule and acceptance options' task :update_dev_deps_w_push => [:update_puppet_version, :update_facter_version, :commit_push] end namespace :spec do task :init do if ! Dir.exist? TEST_GEMS_DIR ## Install bundler ## Line 1 launches the JRuby that we depend on via leiningen ## Line 2 programmatically runs 'gem install bundler' via the gem command that comes with JRuby gem_install_bundler = <<-CMD GEM_HOME='#{TEST_GEMS_DIR}' GEM_PATH='#{TEST_GEMS_DIR}' \ #{LEIN_PATH} gem install -i '#{TEST_GEMS_DIR}' bundler --version 2.5.10 --no-document --source '#{GEM_SOURCE}' CMD sh gem_install_bundler path = ENV['PATH'] ## Install gems via bundler ## Line 1 makes sure that our local bundler script is on the path first ## Line 2 tells bundler to use puppet's Gemfile ## Line 3 tells JRuby where to look for gems ## Line 4 launches the JRuby that we depend on via leiningen ## Line 5 runs our bundle install script bundle_install = <<-CMD PATH='#{TEST_GEMS_DIR}/bin:#{path}' \ BUNDLE_GEMFILE='#{PUPPET_SRC}/Gemfile' \ GEM_HOME='#{TEST_GEMS_DIR}' GEM_PATH='#{TEST_GEMS_DIR}' \ #{LEIN_PATH} run -m org.jruby.Main \ -S bundle install --without extra development packaging --path='#{TEST_BUNDLE_DIR}' --retry=3 CMD sh bundle_install end end end desc "Run rspec tests" task :spec, [:rspec_opts] => ["spec:init"] do |t, args| rspec_opts = args[:rspec_opts] || './spec' ## Run RSpec via our JRuby dependency ## Line 1 tells bundler to use puppet's Gemfile ## Line 2 tells JRuby where to look for gems ## Line 3 launches the JRuby that we depend on via leiningen ## Line 4 adds all our Ruby source to the JRuby LOAD_PATH ## Line 5 runs our rspec wrapper script ## dang ole real easy man run_rspec_with_jruby = <<-CMD BUNDLE_GEMFILE='#{PUPPET_SRC}/Gemfile' \ GEM_HOME='#{TEST_GEMS_DIR}' GEM_PATH='#{TEST_GEMS_DIR}' \ #{LEIN_PATH} run -m org.jruby.Main \ -I'#{PUPPET_SERVER_RUBY_SPEC}' -I'#{PUPPET_LIB}' -I'#{FACTER_LIB}' -I'#{PUPPET_SERVER_RUBY_SRC}' \ ./spec/run_specs.rb #{rspec_opts} CMD sh run_rspec_with_jruby end namespace :test do namespace :acceptance do desc "Run beaker based acceptance tests" task :beaker do |t, args| # variables that take a limited set of acceptable strings type = ENV["BEAKER_TYPE"] || "pe" # variables that take pathnames beakeropts = ENV["BEAKER_OPTS"] || "" presuite = ENV["BEAKER_PRESUITE"] || "#{ACCEPTANCE_ROOT}/suites/pre_suite/#{type}" postsuite = ENV["BEAKER_POSTSUITE"] || "" helper = ENV["BEAKER_HELPER"] || "#{ACCEPTANCE_ROOT}/lib/helper.rb" testsuite = ENV["BEAKER_TESTSUITE"] || "#{ACCEPTANCE_ROOT}/suites/tests" loadpath = ENV["BEAKER_LOADPATH"] || "" options = ENV["BEAKER_OPTIONSFILE"] || "#{ACCEPTANCE_ROOT}/config/beaker/options.rb" # variables requiring some assembly config = assemble_default_beaker_config beaker = "beaker " beaker += " -c #{config}" beaker += " --helper #{helper}" beaker += " --type #{type}" beaker += " --options-file #{options}" if options != '' beaker += " --load-path #{loadpath}" if loadpath != '' beaker += " --pre-suite #{presuite}" if presuite != '' beaker += " --post-suite #{postsuite}" if postsuite != '' beaker += " --tests " + testsuite if testsuite != '' beaker += " " + beakeropts sh beaker end desc "Do an ezbake build, and then a beaker smoke test off of that build, preserving the vmpooler host" task :bakeNbeak do package_version = nil Open3.popen3("#{LEIN_PATH} with-profile ezbake ezbake build 2>&1") do |stdin, stdout, stderr, thread| # sleep 5 # puts "STDOUT IS: #{stdout}" success = true stdout.each do |line| if match = line.match(%r|^Your packages will be available at http://builds.delivery.puppetlabs.net/puppetserver/(.*)$|) package_version = match[1] elsif line =~ /^Packaging FAILURE\s*$/ success = false end puts line end exit_code = thread.value if success == true puts "PACKAGE VERSION IS #{package_version}" else puts "\n\nPACKAGING FAILED! exit code is '#{exit_code}'. STDERR IS:" puts stderr.read exit 1 end end begin setup_smoke_hosts_config() basic_smoke_test(package_version) rescue => e puts "\n\nJOB FAILED; PACKAGE VERSION WAS: #{package_version}\n\n" raise e end end desc "Do a basic smoke test, using the package version specified by PACKAGE_BUILD_VERSION, preserving the vmpooler host" task :smoke do package_version = ENV["PACKAGE_BUILD_VERSION"] unless package_version STDERR.puts("'smoke' task requires PACKAGE_BUILD_VERSION environment variable") exit 1 end setup_smoke_hosts_config() basic_smoke_test(package_version) end desc "Re-run the basic smoke test on the host preserved from a previous run of the 'smoke' task" task :resmoke do re_run_basic_smoke_test() end end end namespace :package do task :bootstrap do puts 'Bootstrap is no longer needed, using packaging-as-a-gem' end task :implode do puts 'Implode is no longer needed, using packaging-as-a-gem' end end begin require 'packaging' Pkg::Util::RakeUtils.load_packaging_tasks rescue LoadError => e puts "Error loading packaging rake tasks: #{e}" end puppetlabs-puppetserver-7e1a9a8/acceptance/000077500000000000000000000000001470345337400211545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/README.md000066400000000000000000000105411470345337400224340ustar00rootroot00000000000000# Puppet Server Acceptance Testing This directory is intended to manage acceptance testing for the Puppet Server. ## Acceptance Testing for Dummies The workflow described here is intended for developers who have access to the [vmpooler](http://vmpooler.delivery.puppetlabs.net), which currently requires [VPN access](https://confluence.puppetlabs.com/display/HELP/VPN+access) and as such is only applicable to Puppet employees. This workflow is intended to help developers new to the puppetserver project. The two primary goals of this workflow are to enable the developer to modify the behavior of acceptance tests in as little time as possible and to operate in a manner as similar to the production CI system as possible. If you would like to setup local VMs to develop and exercise acceptance tests, or would like to learn about additional options beyond the vmpooler configuration, please see the [README_LOCAL_VM.md](README_LOCAL_VM.md) document. ------------------------------------------------------------------------------- **Important:** The commands described in this document assume you are working at the root of the puppetserver repo, that is, in the directory that contains the acceptance directory. ------------------------------------------------------------------------------- ## Define environment variables You'll need to provide environment variables that specify against which builds of puppetserver and (optionally) puppet-agent to install and test. You can test an existing build or test a new build with local changes. ### PACKAGE_BUILD_VERSION when testing an existing build 1. Go to http://builds.delivery.puppetlabs.net/puppetserver/?C=M;O=D to find the most recent build, or copy the value of the `PACKAGE_BUILD_VERSION` parameter from a jenkins job you're trying to reproduce. 2. Set `PACKAGE_BUILD_VERSION` to this value. It should look something like: `6.15.1.SNAPSHOT.2021.01.29T0152` ### PACKAGE_BUILD_VERSION when testing a new build with local changes 1. Run ``` lein clean lein install EZBAKE_ALLOW_UNREPRODUCIBLE_BUILDS=true EZBAKE_NODEPLOY=true JENKINS_USER_AUTH=':' lein with-profile ezbake,provided ezbake build ``` This will take a while, and will result in a build appearing on http://builds.delivery.puppetlabs.net/puppetserver. 2. If successful, it will give you back a URL with the new puppetserver version at the end, which will look something like `6.15.1.SNAPSHOT.2021.01.29T0152`. Set `PACKAGE_BUILD_VERSION` to this value. ### PUPPET_BUILD_VERSION (optional) Define `PUPPET_BUILD_VERSION` as the version of the puppet-agent package upon which your version of puppetserver depends. This can be a tag or SHA. Unless you're making changes to the agent specifically, you probably won't need to set this value. By default, we test against the version defined in the [beaker options](https://github.com/puppetlabs/puppetserver/blob/6.x/acceptance/config/beaker/options.rb#L14) file. ### PUPPET_LEGACY_VERSION (optional) If you are testing backwards compatibility against a specific release of Puppet, the `PUPPET_LEGACY_VERSION` environment variable is available for this purpose, but is not required. ## Using the handy shell script We have a script that will run beaker tests for you, relying on the built-in defaults for all arguments. All you provide is the `PACKAGE_BUILD_VERSION` environment variable. Thus: ``` PACKAGE_BUILD_VERSION='6.15.1.SNAPSHOT.2021.01.29T0152' acceptance/scripts/generic/testrun.sh -p ``` Running with `-p` will preserve the hosts and leave a `hosts_preserved.yml` at the top level of the repo. To reuse the hosts saved from a previous run, specify `-r` instead of `-p`, that is, `acceptance/scripts/generic/testrun.sh -r`. See [the script](https://github.com/puppetlabs/puppetserver/blob/6.x/acceptance/scripts/generic/testrun.sh#L41-L50) for additional environment variables you can set and their defaults. ------------------------------------------------------------------------------- **Note:** You may need to obtain the `~/.ssh/id_rsa-acceptance` file from a colleague so that beaker can SSH into the target VM's located in the pooler. **Note:** [VPN access](https://confluence.puppetlabs.com/display/HELP/VPN+access) is required when executing tests against vmpooler. ------------------------------------------------------------------------------- puppetlabs-puppetserver-7e1a9a8/acceptance/config/000077500000000000000000000000001470345337400224215ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/000077500000000000000000000000001470345337400236525ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/local/000077500000000000000000000000001470345337400247445ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/local/el6/000077500000000000000000000000001470345337400254325ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/local/el6/1host.cfg000066400000000000000000000011251470345337400271500ustar00rootroot00000000000000HOSTS: centos6-64-1.local: roles: - master - agent - dashboard - database platform: el-6-x86_64 ip: 192.168.56.4 service-wait: true service-prefix: 'service ' puppetservice: puppetserver puppetpath: /etc/puppet group: puppet puppetbin: /usr/bin/puppet puppetbindir: /usr/bin puppetvardir: /opt/puppetlabs/puppet/cache hieradatadir: /etc/puppet/hieradata hieraconf: /etc/puppet/hiera.yaml distmoduledir: /etc/puppet/modules sitemoduledir: /usr/share/puppet/modules CONFIG: nfs_server: none consoleport: 443 puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/options.rb000066400000000000000000000010341470345337400256700ustar00rootroot00000000000000{:forge_host=>"forgeapi.puppet.com", :is_puppetserver=>true, :is_jvm_puppet=>true, "service-wait"=>true, "service-prefix"=>"service ", "service-num-retries"=>1500, "puppetservice"=>"puppetserver", "puppetserver-package"=>"puppetserver", "use-service"=>true, "master-start-curl-retries"=>60, "puppetserver-confdir"=>"/etc/puppetlabs/puppetserver/conf.d", "puppetserver-config"=> "/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf", :puppet_build_version=>"2b517c7dd5bed8c26bf13ad858eb43a981dc75d4", :ssh=>{:config=>true}} puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/vbox/000077500000000000000000000000001470345337400246305ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/vbox/el6/000077500000000000000000000000001470345337400253165ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/vbox/el6/64/000077500000000000000000000000001470345337400255475ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/vbox/el6/64/1host.cfg000066400000000000000000000013061470345337400272660ustar00rootroot00000000000000HOSTS: el6-64-1.vm: roles: - master - agent - dashboard - database platform: el-6-x86_64 hypervisor: vagrant box: centos-6.5-64-nocm box_url: https://vagrantcloud.com/puppetlabs/centos-6.5-64-nocm/version/2/provider/virtualbox.box service-wait: true service-prefix: 'service ' puppetservice: puppetserver puppetpath: /etc/puppet group: puppet puppetbin: /usr/bin/puppet puppetbindir: /usr/bin puppetvardir: /var/lib/puppet hieradatadir: /etc/puppet/hieradata hieraconf: /etc/puppet/hiera.yaml distmoduledir: /etc/puppet/modules sitemoduledir: /usr/share/puppet/modules CONFIG: nfs_server: none consoleport: 443 puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/vbox/el6/64/2hosts.cfg000066400000000000000000000017111470345337400274520ustar00rootroot00000000000000HOSTS: el6-64-1.vm: roles: - master - agent - database platform: el-6-x86_64 hypervisor: vagrant ip: 192.168.56.20 box: centos-65-x64-vbox4210-nocm box_url: http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box service-wait: true service-prefix: 'service ' puppetservice: puppetserver puppetpath: /etc/puppet group: puppet puppetbin: /usr/bin/puppet puppetbindir: /usr/bin puppetvardir: /var/lib/puppet hieradatadir: /etc/puppet/hieradata hieraconf: /etc/puppet/hiera.yaml distmoduledir: /etc/puppet/modules sitemoduledir: /usr/share/puppet/modules el6-64-2.vm: roles: - agent - dashboard platform: el-6-x86_64 hypervisor: vagrant ip: 192.168.56.21 box: centos-65-x64-vbox4210-nocm box_url: http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box CONFIG: nfs_server: none consoleport: 443 puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/vcenter_dual.cfg000066400000000000000000000020001470345337400267760ustar00rootroot00000000000000HOSTS: master: roles: - master - agent - dashboard - database platform: el-6-x86_64 template: Delivery/Quality Assurance/Templates/vCloud/centos-6-x86_64 hypervisor: vcloud service-wait: true service-prefix: 'service ' puppetservice: puppetserver puppetpath: /etc/puppet group: puppet puppetbin: /usr/bin/puppet puppetbindir: /usr/bin puppetvardir: /opt/puppetlabs/puppet/cache hieradatadir: /etc/puppet/hieradata hieraconf: /etc/puppet/hiera.yaml distmoduledir: /etc/puppet/modules sitemoduledir: /usr/share/puppet/modules agent: roles: - agent - dashboard platform: el-6-x86_64 template: Delivery/Quality Assurance/Templates/vCloud/centos-6-x86_64 hypervisor: vcloud CONFIG: pooling_api: http://vcloud.delivery.puppetlabs.net nfs_server: none consoleport: 443 datastore: instance0 folder: Delivery/Quality Assurance/Staging/Dynamic resourcepool: delivery/Quality Assurance/Staging/Dynamic puppetlabs-puppetserver-7e1a9a8/acceptance/config/beaker/vcenter_mono.cfg000066400000000000000000000015211470345337400270300ustar00rootroot00000000000000HOSTS: master: roles: - master - agent - dashboard - database platform: el-6-x86_64 template: Delivery/Quality Assurance/Templates/vCloud/centos-6-x86_64 hypervisor: vcloud service-wait: true service-prefix: 'service ' puppetservice: puppetserver puppetpath: /etc/puppet group: puppet puppetbin: /usr/bin/puppet puppetbindir: /usr/bin puppetvardir: /opt/puppetlabs/puppet/cache hieradatadir: /etc/puppet/hieradata hieraconf: /etc/puppet/hiera.yaml distmoduledir: /etc/puppet/modules sitemoduledir: /usr/share/puppet/modules CONFIG: pooling_api: http://vcloud.delivery.puppetlabs.net nfs_server: none consoleport: 443 datastore: instance0 folder: Delivery/Quality Assurance/Staging/Dynamic resourcepool: delivery/Quality Assurance/Staging/Dynamic puppetlabs-puppetserver-7e1a9a8/acceptance/config/nodes/000077500000000000000000000000001470345337400235315ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/config/nodes/redhat7-64m-windows2008r2-64a.yaml000066400000000000000000000013431470345337400312160ustar00rootroot00000000000000--- HOSTS: redhat7-64-1: roles: - agent - master hypervisor: vcloud pe_dir: pe_ver: pe_upgrade_dir: pe_upgrade_ver: platform: el-7-x86_64 template: Delivery/Quality Assurance/Templates/vCloud/redhat-7-x86_64 windows2008r2-64-2: roles: - agent hypervisor: vcloud pe_dir: pe_ver: pe_upgrade_dir: pe_upgrade_ver: platform: windows-2008r2-64 template: Delivery/Quality Assurance/Templates/vCloud/win-2008r2-x86_64 CONFIG: nfs_server: none consoleport: 443 datastore: instance0 folder: Delivery/Quality Assurance/Enterprise/Dynamic resourcepool: delivery/Quality Assurance/Enterprise/Dynamic pooling_api: http://vcloud.delivery.puppetlabs.net/ puppetlabs-puppetserver-7e1a9a8/acceptance/lib/000077500000000000000000000000001470345337400217225ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/lib/helper.rb000066400000000000000000000376501470345337400235410ustar00rootroot00000000000000require 'beaker/dsl/install_utils' require 'net/http' require 'json' require 'beaker-puppet' module PuppetServerExtensions # Configuration code largely obtained from: # https://github.com/puppetlabs/classifier/blob/master/integration/helper.rb # def self.initialize_config(options) base_dir = File.join(File.dirname(__FILE__), '..') install_type = get_option_value(options[:puppetserver_install_type], [:git, :package], "install type", "PUPPETSERVER_INSTALL_TYPE", :package, :symbol) install_mode = get_option_value(options[:puppetserver_install_mode], [:install, :upgrade], "install mode", "PUPPETSERVER_INSTALL_MODE", :install, :symbol) puppetserver_version = get_option_value(options[:puppetserver_version], nil, "Puppet Server Version", "PUPPETSERVER_VERSION", nil, :string) # puppet-agent version corresponds to packaged development version located at: # http://builds.delivery.puppetlabs.net/puppet-agent/ # This value now come from the beaker options file, or PUPPET_BUILD_VERSION env var # the beaker options file can have this value updated via the rake task puppet_build_version = get_option_value(options[:puppet_build_version], nil, "Puppet Agent Development Build Version", "PUPPET_BUILD_VERSION", nil, :string) # puppetdb version corresponds to packaged development version located at: # http://builds.delivery.puppetlabs.net/puppetdb/ puppetdb_build_version = get_option_value(options[:puppetdb_build_version], nil, "PuppetDB Version", "PUPPETDB_BUILD_VERSION", "5.2.4", :string) @config = { :base_dir => base_dir, :puppetserver_install_type => install_type, :puppetserver_install_mode => install_mode, :puppetserver_version => puppetserver_version, :puppet_build_version => puppet_build_version, :puppetdb_build_version => puppetdb_build_version, } end def self.print_config pp_config = PP.pp(@config, "") Beaker::Log.notify "Puppet Server Acceptance Configuration:\n\n#{pp_config}\n\n" end # PuppetDB development packages aren't available on as many platforms as # Puppet Server's packages, so we need to restrict the PuppetDB-related # testing to a subset of the platforms. # This guards both the installation of the PuppetDB package repository file # and the running of the PuppetDB test(s). def puppetdb_supported_platforms() [ /debian-11/, /debian-12/, /el-8/, /el-9/, /sles-12/, /sles-15/, /ubuntu-20.04/, /ubuntu-22.04/, /ubuntu-24.04/ ] end class << self attr_reader :config end # Return the configuration hash initialized by # PuppetServerExtensions.initialize_config # def test_config PuppetServerExtensions.config end def self.get_option_value(value, legal_values, description, env_var_name = nil, default_value = nil, value_type = :symbol) # precedence is environment variable, option file, default value value = ((env_var_name && ENV[env_var_name]) || value || default_value) if value == "" and value_type == :string value = default_value elsif value and value_type == :symbol value = value.to_sym end unless legal_values.nil? or legal_values.include?(value) raise ArgumentError, "Unsupported #{description} '#{value}'" end value end def puppetserver_initialize_ssl hostname = on(master, 'facter hostname').stdout.strip fqdn = on(master, 'facter fqdn').stdout.strip step "Clear SSL on all hosts" hosts.each do |host| ssldir = on(host, puppet('agent --configprint ssldir')).stdout.chomp cadir = on(host, puppet('agent --configprint cadir')).stdout.chomp on(master, 'puppet resource service puppetserver ensure=stopped') if host == master on(host, "rm -rf '#{ssldir}'/*") on(host, "rm -rf '#{cadir}'/*") if host == master on(host, 'puppetserver ca setup') on(master, 'puppet resource service puppetserver ensure=running') end end step "Server: Start Puppet Server" old_retries = master['master-start-curl-retries'] master['master-start-curl-retries'] = 300 with_puppet_running_on(master, "main" => { "autosign" => true, "dns_alt_names" => "puppet,#{hostname},#{fqdn}", "verbose" => true, "daemonize" => true }) do hosts.each do |host| step "Agents: Run agent --test first time to gen CSR" response = on(host, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [0,1]) if response.exit_code == 1 if response.stdout.match?(/Certificate (.+) has not been signed yet/) Beaker::Log.notify "Cert not signed, possibly due to 'puppet resource service puppetserver ensure=running' returning early, retrying in 20 seconds" sleep 20 on(host, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [0]) else fail_test("Exit code of 1 with unexpected stdout:\n#{response.stdout}") end end end end master['master-start-curl-retries'] = old_retries end def puppet_server_collect_data(host, relative_path) variant, version, _, _ = master['platform'].to_array # This is an ugly hack to accomodate the difficulty around getting systemd # to output the daemon's standard out to the same place that the init # scripts typically do. use_journalctl = false case variant when /^fedora$/ if version.to_i >= 15 use_journalctl = true end when /^(el|centos)$/ if version.to_i >= 7 use_journalctl = true end when /^debian$/ if version.to_i >= 8 use_journalctl = true end when /^ubuntu$/ if version.to_i >= 15 use_journalctl = true end when /^sles$/ if version.to_i >= 12 use_journalctl = true end end destination = File.join("./log/latest/puppetserver/", relative_path) FileUtils.mkdir_p(destination) scp_from master, "/var/log/puppetlabs/puppetserver/puppetserver.log", destination if use_journalctl puppetserver_daemon_log = on(master, "journalctl -u puppetserver", :acceptable_exit_codes => [0,1]).stdout.strip destination = File.join(destination, "puppetserver-daemon.log") File.open(destination, 'w') {|file| file.puts puppetserver_daemon_log } else scp_from master, "/var/log/puppetlabs/puppetserver/puppetserver-daemon.log", destination end end def install_puppet_server (host, make_env={}) install_puppet_server_deps case test_config[:puppetserver_install_type] when :package install_package host, 'puppetserver' when :git project_version = 'puppetserver-version=' project_version += test_config[:puppetserver_version] || `lein with-profile ci pprint :version | tail -n 1 | cut -d\\" -f2` install_from_ezbake host, 'puppetserver', project_version, make_env else abort("Invalid install type: " + test_config[:puppetserver_install_type]) end end def install_puppet_server_deps variant = master['platform'].variant version = master['platform'].version if variant == 'debian' && version == "8" create_remote_file(master, "/etc/apt/sources.list.d/jessie-backports.list", "deb https://artifactory.delivery.puppetlabs.net/artifactory/debian_archive__remote/ jessie-backports main") on master, 'apt-get update' master.install_package("openjdk-8-jre-headless") on master, 'update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java' end end def get_defaults_file package_name = options['puppetserver-package'] variant, _, _, _ = master['platform'].to_array case variant when /^(fedora|el|centos|sles)$/ defaults_dir = "/etc/sysconfig/" when /^(debian|ubuntu)$/ defaults_dir = "/etc/default/" else logger.warn("#{platform}: Unsupported platform for puppetserver.") end File.join(defaults_dir, package_name) end def get_defaults_var(host, varname) defaults_file = get_defaults_file on(host, "source #{defaults_file}; echo -n $#{varname}").stdout end # If we are getting the certificate for the first time, store it in the # beaker host options hash. Else, return the stored certificate from the # beaker host options hash def get_cert(host) if host.host_hash[:cert].class == OpenSSL::X509::Certificate then return host.host_hash[:cert] else cert = encode_cert(host, host.puppet['hostcert']) host.host_hash[:cert] = cert return cert end end # Convert the contents of the certificate file in cert_file on the host # specified by cert_host into an X.509 certificate and return it # cert_host: The host whose cert you want # cert_file: The specific cert file you want # silent : Suppress Beaker's output; set to false to see it def encode_cert(cert_host, cert_file, silent = true) rawcert = on(cert_host, "cat #{cert_file}", {:silent => silent}).stdout.strip OpenSSL::X509::Certificate.new(rawcert) end # Gets the key from the host hash if it is present, other wise uses # the encode_key method to get the key from the host, and stores it in the # host hash def get_key(host) if host.host_hash[:key].class == OpenSSL::PKey::RSA then return host.host_hash[:key] else key = encode_key(host, host.puppet['hostprivkey']) host.host_hash[:key] = key return key end end # Convert the contents of the private key file in key_file on the host # specified by key_host into an RSA private key and return it # key_host: The host whose key you want # key_file: The specific key file you want # silent : Suppress Beaker's output; set to false to see it def encode_key(key_host, key_file, silent = true) rawkey = on(key_host, "cat #{key_file}", {:silent => silent}).stdout.strip OpenSSL::PKey::RSA.new(rawkey) end # Issue an HTTP request and return the Net::HTTPResponse object. Lifted from # https://github.com/puppetlabs/pe_acceptance_tests/blob/2015.3.x/lib/http_calls.rb # and slightly modified. # url: (String) URL to poke # method: (Symbol) :post, :get # cert: (OpenSSL::X509::Certificate, nil) The certificate to # use for authentication. # key: (OpenSSL::PKey::RSA, nil) The private key to use for # authentication # body: (String) Request body (default empty) require 'net/http' require 'uri' def https_request(url, request_method, cert = nil, key = nil, body = nil, options = {}) # Make insecure https request uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) if cert if cert.is_a?(OpenSSL::X509::Certificate) http.cert = cert else raise TypeError, "cert must be an OpenSSL::X509::Certificate object, not #{cert.class}" end end if key if key.is_a?(OpenSSL::PKey::RSA) http.key = key else raise TypeError, "key must be an OpenSSL::PKey:RSA object, not #{key.class}" end end http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.read_timeout = options[:read_timeout] if options[:read_timeout] if request_method == :post request = Net::HTTP::Post.new(uri.request_uri) # Needs the content type even though no data is being sent request.content_type = 'application/json' request.body = body else request = Net::HTTP::Get.new(uri.request_uri) end start = Time.now response = http.request(request) stop = Time.now logger.debug "Remote took #{stop - start} to respond" response end def reload_server(host = master, opts = {}) service = options['puppetservice'] on(host, "service #{service} reload", opts) end def apply_one_hocon_setting(hocon_host, hocon_file_path, hocon_setting, hocon_value) hocon_manifest =<<-EOF.gsub(/^ {6}/, '') hocon_setting { "#{hocon_setting}": ensure => present, path => "#{hocon_file_path}", setting => "#{hocon_setting}", value => #{hocon_value}, } EOF apply_manifest_on(hocon_host, hocon_manifest, {:acceptable_exit_codes => [0,2]}) end def delete_one_hocon_setting(hocon_host, hocon_file_path, hocon_setting) hocon_manifest =<<-EOF.gsub(/^ {6}/, '') hocon_setting { "#{hocon_setting}": ensure => absent, path => "#{hocon_file_path}", setting => "#{hocon_setting}", } EOF apply_manifest_on(hocon_host, hocon_manifest, {:acceptable_exit_codes => [0,2]}) end # appends match-requests to TK auth.conf # Provides many defaults so that users of this method can simply # and easily allow a host in TK auth.conf # # NOTE: This method allows the caller to define invalid TK auth rules # by design. # # TK Auth is documented here: # https://github.com/puppetlabs/puppetserver/blob/master # /documentation/config_file_auth.md # # Arguments: # cn: The cannonical name, usually put in an "allow" or "deny" # name: The friendly name of the match-request # host: The system under test. Typcially master. # allow: hostname, glob, or regex lookback to allow. # allow_unauthenticated: # Boolean value. Only adds the allow-unauthenticated behavior if # true. # deny: hostname, glob or regex lookback to deny # sort_order: # path: # type: Valid values are 'path' or 'regex' # method: Should accept string or array or strings. # Valid strings include 'head', 'get', 'put', 'post', 'delete' # require 'hocon/config_factory' def append_match_request(args) cn = args[:cn] #The cannonical name to allow. name = args[:name] || args[:cn] #friendly name. host = args[:host] || master allow = args[:allow]|| args[:cn] allow_unauthenticated = args[:allow_unauthenticated] || false deny = args[:deny] || false sort_order = args[:sort_order] || 77 path = args[:path] || '/' type = args[:type] || 'path' default_http_methods = ['head', 'get', 'put', 'post', 'delete'] method = args[:method] || default_http_methods query_params = args[:query_params] || {} #TODO: handle TK-293 X509 extensions. authconf_file = args[:authconf_file] || options[:'puppetserver-confdir']+'/auth.conf' match_request = { 'match-request' => { 'path' => path, 'type' => type, 'method' => method, }, 'sort-order' => sort_order, 'name' => name } #Note: If you set 'allow', 'allow-unauthenticated', and 'deny' you will #have an invalid match-request. match_request.merge!('allow' => allow) if allow match_request.merge!('allow-unauthenticated' => true) if allow_unauthenticated match_request.merge!('deny' => deny) if deny authconf_text = on(master, "cat #{authconf_file}").stdout authconf_hash = Hocon.parse(authconf_text) authconf_hash['authorization']['rules'] << match_request modify_tk_config(host, authconf_file, authconf_hash, true) end # parses text into json if possible def parse_json(text) begin json = JSON.parse(text) rescue JSON::ParserError => e fail_test "Response body is not parseable JSON\n" + "Exception message: #{e.message}\n" + "Text to parse: #{text}\n" end return json end end Beaker::TestCase.send(:include, PuppetServerExtensions) puppetlabs-puppetserver-7e1a9a8/acceptance/lib/puppet_x/000077500000000000000000000000001470345337400235665ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/lib/puppet_x/acceptance/000077500000000000000000000000001470345337400256545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/lib/puppet_x/acceptance/external_cert_fixtures.rb000066400000000000000000000261601470345337400327760ustar00rootroot00000000000000module PuppetX module Acceptance class ExternalCertFixtures attr_reader :fixture_dir attr_reader :test_dir attr_reader :master_name attr_reader :agent_name ## # ExternalCerts provides a utility class to fill in fixture data and other # large blobs of text configuration for the acceptance testing of External CA # behavior. # # @param [String] fixture_dir The fixture directory to read from. # # @param [String] test_dir The directory on the remote system, used for # filling in templates. # # @param [String] master_name The common name the master should be reachable # at. This name should match up with the certificate files in the fixture # directory, e.g. master1.example.org. # # @param [String] agent_name The common name the agent is configured to use. # This name should match up with the certificate files in the fixture # directory, e.g. def initialize(fixture_dir, test_dir, master_name = "master1.example.org", agent_name = "agent1.example.org") @fixture_dir = fixture_dir @test_dir = test_dir @master_name = master_name @agent_name = agent_name end def master_short_name @master_short_name ||= master_name.gsub(/\..*/, '') end def host_entry @host_entry ||= "127.0.0.3 #{master_name} #{master_short_name} puppet" end def root_ca_cert @root_ca_cert ||= File.read(File.join(fixture_dir, 'root', 'ca-root.crt')) end def agent_ca_cert @agent_ca_cert ||= File.read(File.join(fixture_dir, 'agent-ca', 'ca-agent-ca.crt')) end def master_ca_cert @master_ca_cert ||= File.read(File.join(fixture_dir, 'master-ca', 'ca-master-ca.crt')) end def master_ca_crl @master_ca_crl ||= File.read(File.join(fixture_dir, 'master-ca', 'ca-master-ca.crl')) end def agent_cert @agent_cert ||= File.read(File.join(fixture_dir, 'leaves', "#{agent_name}.issued_by.agent-ca.crt")) end def agent_key @agent_key ||= File.read(File.join(fixture_dir, 'leaves', "#{agent_name}.issued_by.agent-ca.key")) end def agent_email_cert @agent_email_cert ||= File.read(File.join(fixture_dir, 'leaves', "#{agent_name}.email.issued_by.agent-ca.crt")) end def agent_email_key @agent_email_cert ||= File.read(File.join(fixture_dir, 'leaves', "#{agent_name}.email.issued_by.agent-ca.key")) end def master_cert @master_cert ||= File.read(File.join(fixture_dir, 'leaves', "#{master_name}.issued_by.master-ca.crt")) end def master_key @master_key ||= File.read(File.join(fixture_dir, 'leaves', "#{master_name}.issued_by.master-ca.key")) end def master_cert_rogue @master_cert_rogue ||= File.read(File.join(fixture_dir, 'leaves', "#{master_name}.issued_by.agent-ca.crt")) end def master_key_rogue @master_key_rogue ||= File.read(File.join(fixture_dir, 'leaves', "#{master_name}.issued_by.agent-ca.key")) end ## Configuration files def agent_conf @agent_conf ||= <<-EO_AGENT_CONF [main] color = false certname = #{agent_name} server = #{master_name} certificate_revocation = false # localcacert must contain the Root CA certificate to complete the 2 level CA # chain when an intermediate CA certificate is being used. Either the HTTP # server must send the intermediate certificate during the handshake, or the # agent must use the `ssl_client_ca_auth` setting to provide the client # certificate. localcacert = #{test_dir}/ca_root.crt EO_AGENT_CONF end def agent_conf_email @agent_conf ||= <<-EO_AGENT_CONF [main] color = false certname = #{agent_name} server = #{master_name} certificate_revocation = false hostcert = #{test_dir}/agent_email.crt hostkey = #{test_dir}/agent_email.key localcacert = #{test_dir}/ca_root.crt EO_AGENT_CONF end def agent_conf_crl @agent_conf_crl ||= <<-EO_AGENT_CONF [main] certname = #{agent_name} server = #{master_name} # localcacert must contain the Root CA certificate to complete the 2 level CA # chain when an intermediate CA certificate is being used. Either the HTTP # server must send the intermediate certificate during the handshake, or the # agent must use the `ssl_client_ca_auth` setting to provide the client # certificate. localcacert = #{test_dir}/ca_root.crt EO_AGENT_CONF end def master_conf @master_conf ||= <<-EO_MASTER_CONF [master] ca = false certname = #{master_name} ssl_client_header = HTTP_X_CLIENT_DN ssl_client_verify_header = HTTP_X_CLIENT_VERIFY EO_MASTER_CONF end ## # Passenger Rack compliant config.ru which is responsible for starting the # Puppet master. def config_ru @config_ru ||= <<-EO_CONFIG_RU \$0 = "master" ARGV << "--rack" ARGV << "--confdir=#{test_dir}/etc/master" ARGV << "--vardir=#{test_dir}/etc/master/var" require 'puppet/util/command_line' run Puppet::Util::CommandLine.new.execute EO_CONFIG_RU end ## # auth_conf should return auth authorization file that allows *.example.org # access to to the full REST API. def auth_conf @auth_conf_content ||= File.read(File.join(fixture_dir, 'auth.conf')) end ## # Apache configuration with Passenger def httpd_conf @httpd_conf ||= <<-EO_HTTPD_CONF User apache Group apache ServerRoot "/etc/httpd" PidFile run/httpd.pid Timeout 60 KeepAlive Off MaxKeepAliveRequests 100 KeepAliveTimeout 15 StartServers 8 MinSpareServers 5 MaxSpareServers 20 ServerLimit 256 MaxClients 256 MaxRequestsPerChild 4000 StartServers 4 MaxClients 300 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 LoadModule auth_basic_module modules/mod_auth_basic.so LoadModule auth_digest_module modules/mod_auth_digest.so LoadModule authn_file_module modules/mod_authn_file.so LoadModule authn_alias_module modules/mod_authn_alias.so LoadModule authn_anon_module modules/mod_authn_anon.so LoadModule authn_dbm_module modules/mod_authn_dbm.so LoadModule authn_default_module modules/mod_authn_default.so LoadModule authz_host_module modules/mod_authz_host.so LoadModule authz_user_module modules/mod_authz_user.so LoadModule authz_owner_module modules/mod_authz_owner.so LoadModule authz_groupfile_module modules/mod_authz_groupfile.so LoadModule authz_dbm_module modules/mod_authz_dbm.so LoadModule authz_default_module modules/mod_authz_default.so LoadModule ldap_module modules/mod_ldap.so LoadModule authnz_ldap_module modules/mod_authnz_ldap.so LoadModule include_module modules/mod_include.so LoadModule log_config_module modules/mod_log_config.so LoadModule logio_module modules/mod_logio.so LoadModule env_module modules/mod_env.so LoadModule ext_filter_module modules/mod_ext_filter.so LoadModule mime_magic_module modules/mod_mime_magic.so LoadModule expires_module modules/mod_expires.so LoadModule deflate_module modules/mod_deflate.so LoadModule headers_module modules/mod_headers.so LoadModule usertrack_module modules/mod_usertrack.so LoadModule setenvif_module modules/mod_setenvif.so LoadModule mime_module modules/mod_mime.so LoadModule dav_module modules/mod_dav.so LoadModule status_module modules/mod_status.so LoadModule autoindex_module modules/mod_autoindex.so LoadModule info_module modules/mod_info.so LoadModule dav_fs_module modules/mod_dav_fs.so LoadModule vhost_alias_module modules/mod_vhost_alias.so LoadModule negotiation_module modules/mod_negotiation.so LoadModule dir_module modules/mod_dir.so LoadModule actions_module modules/mod_actions.so LoadModule speling_module modules/mod_speling.so LoadModule userdir_module modules/mod_userdir.so LoadModule alias_module modules/mod_alias.so LoadModule substitute_module modules/mod_substitute.so LoadModule rewrite_module modules/mod_rewrite.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_balancer_module modules/mod_proxy_balancer.so LoadModule proxy_ftp_module modules/mod_proxy_ftp.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so LoadModule proxy_connect_module modules/mod_proxy_connect.so LoadModule cache_module modules/mod_cache.so LoadModule suexec_module modules/mod_suexec.so LoadModule disk_cache_module modules/mod_disk_cache.so LoadModule cgi_module modules/mod_cgi.so LoadModule version_module modules/mod_version.so LoadModule ssl_module modules/mod_ssl.so LoadModule passenger_module modules/mod_passenger.so ServerName #{master_name} DocumentRoot "#{test_dir}/etc/master/public" DefaultType text/plain TypesConfig /etc/mime.types # Same thing, just using a certificate issued by the Agent CA, which should not # be trusted by the clients. Listen 8140 https Listen 8141 https SSLEngine on SSLProtocol ALL -SSLv2 SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP SSLCertificateFile "#{test_dir}/master.crt" SSLCertificateKeyFile "#{test_dir}/master.key" # The chain file is sent to the client during handshake. SSLCertificateChainFile "#{test_dir}/ca_master_bundle.crt" # The CA cert file is used to authenticate clients SSLCACertificateFile "#{test_dir}/ca_agent_bundle.crt" SSLVerifyClient optional SSLVerifyDepth 2 SSLOptions +StdEnvVars RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e DocumentRoot "#{test_dir}/etc/master/public" PassengerRoot /usr/share/gems/gems/passenger-3.0.17 PassengerRuby /usr/bin/ruby RackAutoDetect On RackBaseURI / SSLEngine on SSLProtocol ALL -SSLv2 SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP SSLCertificateFile "#{test_dir}/master_rogue.crt" SSLCertificateKeyFile "#{test_dir}/master_rogue.key" SSLCertificateChainFile "#{test_dir}/ca_agent_bundle.crt" SSLCACertificateFile "#{test_dir}/ca_agent_bundle.crt" SSLVerifyClient optional SSLVerifyDepth 2 SSLOptions +StdEnvVars RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e DocumentRoot "#{test_dir}/etc/master/public" PassengerRoot /usr/share/gems/gems/passenger-3.0.17 PassengerRuby /usr/bin/ruby RackAutoDetect On RackBaseURI / EO_HTTPD_CONF end ## # webserver.conf for a trustworthy master for use with Jetty def jetty_webserver_conf_for_trustworthy_master @jetty_webserver_conf_for_trustworthy_master ||= <<-EO_WEBSERVER_CONF webserver: { client-auth: want ssl-host: 0.0.0.0 ssl-port: 8140 ssl-cert: "#{test_dir}/master.crt" ssl-key: "#{test_dir}/master.key" ssl-cert-chain: "#{test_dir}/ca_master_bundle.crt" ssl-ca-cert: "#{test_dir}/ca_agent_bundle.crt" } EO_WEBSERVER_CONF end ## # webserver.conf for a rogue master for use with Jetty def jetty_webserver_conf_for_rogue_master @jetty_webserver_conf_for_rogue_master ||= <<-EO_WEBSERVER_CONF webserver: { client-auth: want ssl-host: 0.0.0.0 ssl-port: 8140 ssl-cert: "#{test_dir}/master_rogue.crt" ssl-key: "#{test_dir}/master_rogue.key" ssl-cert-chain: "#{test_dir}/ca_agent_bundle.crt" ssl-ca-cert: "#{test_dir}/ca_agent_bundle.crt" } EO_WEBSERVER_CONF end end end end puppetlabs-puppetserver-7e1a9a8/acceptance/lib/puppet_x/acceptance/pki.rb000066400000000000000000000132371470345337400267720ustar00rootroot00000000000000require 'openssl' module PuppetX module Acceptance module PKI PRIVATE_KEY_LENGTH = 2048 FIVE_YEARS = 5 * 365 * 24 * 60 * 60 CA_EXTENSIONS = [ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "keyCertSign, cRLSign", true], ["subjectKeyIdentifier", "hash", false], ["authorityKeyIdentifier", "keyid:always", false] ] NODE_EXTENSIONS = [ ["keyUsage", "digitalSignature", true], ["subjectKeyIdentifier", "hash", false] ] DEFAULT_SIGNING_DIGEST = OpenSSL::Digest::SHA256.new DEFAULT_REVOCATION_REASON = OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE ROOT_CA_NAME = "/CN=root-ca-\u{2070E}" REVOKED_INT_CA_NAME = "/CN=revoked-int-ca-\u16A0" INT_CA_NAME = "/CN=unrevoked-int-ca\u06FF\u16A0\u{2070E}" LEAF_CA_NAME = "/CN=leaf-ca-\u06FF" EXPLANATORY_TEXT = <<-EOT # Root Issuer: #{ROOT_CA_NAME} # Intermediate Issuer: #{INT_CA_NAME} # Leaf Issuer: #{LEAF_CA_NAME} EOT def self.create_private_key(length = PRIVATE_KEY_LENGTH) OpenSSL::PKey::RSA.new(length) end def self.self_signed_ca(key, name) cert = OpenSSL::X509::Certificate.new cert.public_key = key.public_key cert.subject = OpenSSL::X509::Name.parse(name) cert.issuer = cert.subject cert.version = 2 cert.serial = rand(2**128) not_before = just_now cert.not_before = not_before cert.not_after = not_before + FIVE_YEARS ext_factory = extension_factory_for(cert, cert) CA_EXTENSIONS.each do |ext| extension = ext_factory.create_extension(*ext) cert.add_extension(extension) end cert.sign(key, DEFAULT_SIGNING_DIGEST) cert end def self.create_csr(key, name) csr = OpenSSL::X509::Request.new csr.public_key = key.public_key csr.subject = OpenSSL::X509::Name.parse(name) csr.version = 2 csr.sign(key, DEFAULT_SIGNING_DIGEST) csr end def self.sign(ca_key, ca_cert, csr, extensions = NODE_EXTENSIONS) cert = OpenSSL::X509::Certificate.new cert.public_key = csr.public_key cert.subject = csr.subject cert.issuer = ca_cert.subject cert.version = 2 cert.serial = rand(2**128) not_before = just_now cert.not_before = not_before cert.not_after = not_before + FIVE_YEARS ext_factory = extension_factory_for(ca_cert, cert) extensions.each do |ext| extension = ext_factory.create_extension(*ext) cert.add_extension(extension) end cert.sign(ca_key, DEFAULT_SIGNING_DIGEST) cert end def self.create_crl_for(ca_cert, ca_key) crl = OpenSSL::X509::CRL.new crl.version = 1 crl.issuer = ca_cert.subject ef = extension_factory_for(ca_cert) crl.add_extension( ef.create_extension(["authorityKeyIdentifier", "keyid:always", false])) crl.add_extension( OpenSSL::X509::Extension.new("crlNumber", OpenSSL::ASN1::Integer(0))) not_before = just_now crl.last_update = not_before crl.next_update = not_before + FIVE_YEARS crl.sign(ca_key, DEFAULT_SIGNING_DIGEST) crl end def self.revoke(serial, crl, ca_key) revoked = OpenSSL::X509::Revoked.new revoked.serial = serial revoked.time = Time.now revoked.add_extension( OpenSSL::X509::Extension.new("CRLReason", OpenSSL::ASN1::Enumerated(DEFAULT_REVOCATION_REASON))) crl.add_revoked(revoked) extensions = crl.extensions.group_by{|e| e.oid == 'crlNumber' } crl_number = extensions[true].first unchanged_exts = extensions[false] next_crl_number = crl_number.value.to_i + 1 new_crl_number_ext = OpenSSL::X509::Extension.new("crlNumber", OpenSSL::ASN1::Integer(next_crl_number)) crl.extensions = unchanged_exts + [new_crl_number_ext] crl.sign(ca_key, DEFAULT_SIGNING_DIGEST) crl end # Creates a self-signed root ca, an intermediate ca, and a leaf ca. # Creates CRLs for each ca # Returns the certs in a bundle, the crls in a bundle and the # private key for the leaf ca def self.create_chained_pki(leaf_name) root_key = create_private_key root_cert = self_signed_ca(root_key, ROOT_CA_NAME) root_crl = create_crl_for(root_cert, root_key) int_key = create_private_key int_csr = create_csr(int_key, INT_CA_NAME) int_cert = sign(root_key, root_cert, int_csr, CA_EXTENSIONS) int_crl = create_crl_for(int_cert, int_key) leaf_key = create_private_key leaf_csr = create_csr(leaf_key, "/CN=#{leaf_name}") leaf_cert = sign(int_key, int_cert, leaf_csr, CA_EXTENSIONS) leaf_crl = create_crl_for(leaf_cert, leaf_key) cert_bundle = bundle(leaf_cert, int_cert, root_cert) crl_chain = bundle(leaf_crl, int_crl, root_crl) { :private_key => leaf_key, :cert_bundle => cert_bundle, :crl_chain => crl_chain } end private def self.just_now # Give us some slack in possible clock skew between hosts Time.now - 300 end def self.extension_factory_for(ca, cert = nil) ef = OpenSSL::X509::ExtensionFactory.new ef.issuer_certificate = ca ef.subject_certificate = cert if cert ef end def self.bundle(*items) items.map {|i| EXPLANATORY_TEXT + i.to_pem }.join("\n") end end end end puppetlabs-puppetserver-7e1a9a8/acceptance/lib/puppetserver/000077500000000000000000000000001470345337400244665ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/lib/puppetserver/acceptance/000077500000000000000000000000001470345337400265545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/lib/puppetserver/acceptance/compat_utils.rb000066400000000000000000000020371470345337400316060ustar00rootroot00000000000000def sitepp '/etc/puppetlabs/code/environments/production/manifests/site.pp' end def nonmaster_agents() agents.reject { |agent| agent == master } end def apply_simmons_class(agent, studio, classname) create_remote_file(master, sitepp, < "#{studio}", exercises => [#{classname}], } SITEPP on(master, "chmod 644 #{sitepp}") with_puppet_running_on(master, {"master" => {"autosign" => true}}) do on(agent, puppet("agent --test --digest_algorithm sha256"), :acceptable_exit_codes => [0,2]) end end def rm_compat_test_files() # In order to prevent file caching and ensure agent-master HTTP communication # during agent runs we blow away the vardirs, which contains the cached files hosts.each do |host| vardir = on(host, puppet("config print vardir")).stdout.chomp on(host, "rm -rf #{vardir}") end # Remove any custom site.pp file which may have been laid down so that it # doesn't pollute the outcome from any additional tests which are run. on(master, "rm -f #{sitepp}") end puppetlabs-puppetserver-7e1a9a8/acceptance/lib/puppetserver/acceptance/gem_utils.rb000066400000000000000000000010221470345337400310640ustar00rootroot00000000000000def get_gem_list(host, gem_list_command) # regex for creating list of (gem, version) # NOTE: version here can take a few different forms: # (X.Y.Z) # (Z.Y.Z java) # (X.Y.Z, X.Y.Z2) # gem_list_regex = Regexp.new('(?[\w-]*) (?.*)') array = [] on(host, "#{gem_list_command}") do |result| split_output = result.stdout.split split_output.each do |line| match = gem_list_regex.match(line) if match array << match.captures end end end return array end puppetlabs-puppetserver-7e1a9a8/acceptance/scripts/000077500000000000000000000000001470345337400226435ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/scripts/external_ca/000077500000000000000000000000001470345337400251305ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/scripts/external_ca/retest.sh000077500000000000000000000017271470345337400270040ustar00rootroot00000000000000#!/bin/bash set -x export GEM_SOURCE=https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/ export GENCONFIG_LAYOUT="${GENCONFIG_LAYOUT:-redhat6-64ma-redhat6-64a-redhat6-64u}" export BEAKER_TESTSUITE="${BEAKER_TESTSUITE:-acceptance/suites/tests/020-external-ca/}" export BEAKER_PRESUITE="${BEAKER_PRESUITE:-acceptance/suites/pre_suite/foss}" export BEAKER_POSTSUITE="acceptance/suites/post_suite/" export BEAKER_OPTIONS="acceptance/config/beaker/options.rb" export BEAKER_CONFIG="hosts_preserved.yml" export BEAKER_KEYFILE="~/.ssh/id_rsa-acceptance" export BEAKER_HELPER="acceptance/lib/helper.rb" bundle install --path vendor/bundle bundle exec beaker \ --no-provision \ --hosts $BEAKER_CONFIG \ --type aio \ --helper $BEAKER_HELPER \ --options-file $BEAKER_OPTIONS \ --tests $BEAKER_TESTSUITE \ --post-suite $BEAKER_POSTSUITE \ --keyfile $BEAKER_KEYFILE \ --load-path "acceptance/lib" \ --preserve-hosts \ --debug \ --timeout 360 puppetlabs-puppetserver-7e1a9a8/acceptance/scripts/external_ca/test_preserve_hosts.sh000077500000000000000000000022151470345337400316010ustar00rootroot00000000000000#!/bin/bash set -x export GEM_SOURCE=https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/ export GENCONFIG_LAYOUT="${GENCONFIG_LAYOUT:-redhat6-64ma-redhat6-64a-redhat6-64u}" export BEAKER_TESTSUITE="${BEAKER_TESTSUITE:-acceptance/suites/tests/00_smoke}" export BEAKER_PRESUITE="${BEAKER_PRESUITE:-acceptance/suites/pre_suite/foss}" export BEAKER_POSTSUITE="acceptance/suites/post_suite/" export BEAKER_OPTIONS="acceptance/config/beaker/options.rb" export BEAKER_CONFIG="acceptance/scripts/hosts.cfg" export BEAKER_KEYFILE="~/.ssh/id_rsa-acceptance" export BEAKER_HELPER="acceptance/lib/helper.rb" # export PACKAGE_BUILD_VERSION="2.1.2.SNAPSHOT.2015.08.20T0208" bundle install --path vendor/bundle bundle exec beaker-hostgenerator $GENCONFIG_LAYOUT > $BEAKER_CONFIG bundle exec beaker \ --config $BEAKER_CONFIG \ --type aio \ --helper $BEAKER_HELPER \ --options-file $BEAKER_OPTIONS \ --tests $BEAKER_TESTSUITE \ --post-suite $BEAKER_POSTSUITE \ --pre-suite $BEAKER_PRESUITE \ --keyfile $BEAKER_KEYFILE \ --load-path "acceptance/lib" \ --preserve-hosts \ --debug \ --timeout 360 cp log/latest/hosts_preserved.yml . puppetlabs-puppetserver-7e1a9a8/acceptance/scripts/generic/000077500000000000000000000000001470345337400242575ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/scripts/generic/testrun.sh000077500000000000000000000051431470345337400263250ustar00rootroot00000000000000#!/bin/bash do_init() { if [ -z "$PACKAGE_BUILD_VERSION" ]; #TODO: Read last passing SHA file on builds.pl.d.net then echo "$0: PACKAGE_BUILD_VERSION not set. Please export PACKAGE_BUILD_VERSION." exit -1; fi bundle exec beaker-hostgenerator --hypervisor abs $GENCONFIG_LAYOUT > $BEAKER_CONFIG BEAKER_INIT="bundle exec beaker init --debug" BEAKER_INIT="$BEAKER_INIT --type aio" BEAKER_INIT="$BEAKER_INIT --keyfile $BEAKER_KEYFILE" BEAKER_INIT="$BEAKER_INIT --helper $BEAKER_HELPER" BEAKER_INIT="$BEAKER_INIT --options-file $BEAKER_OPTIONS" BEAKER_INIT="$BEAKER_INIT --load-path $BEAKER_LOADPATH" BEAKER_INIT="$BEAKER_INIT --hosts $BEAKER_CONFIG" BEAKER_INIT="$BEAKER_INIT --pre-suite $BEAKER_PRESUITE" BEAKER_INIT="$BEAKER_INIT --tests $BEAKER_TESTSUITE" BEAKER_INIT="$BEAKER_INIT --debug --timeout 360" $BEAKER_INIT if [ $? != 0 ] ; then echo "Initialization failed!" exit -1; fi bundle exec beaker provision if [ $? != 0 ] ; then echo "Provision failed!" exit -1; fi } set -x export GEM_SOURCE="https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/" export GENCONFIG_LAYOUT="${GENCONFIG_LAYOUT:-redhat9-64ma-debian12-64a}" export BEAKER_TESTSUITE="${BEAKER_TESTSUITE:-acceptance/suites/tests}" export BEAKER_PRESUITE="${BEAKER_PRESUITE:-acceptance/suites/pre_suite/foss}" export BEAKER_OPTIONS="${BEAKER_OPTIONS:-acceptance/config/beaker/options.rb}" export BEAKER_CONFIG="${BEAKER_CONFIG:-acceptance/scripts/hosts.cfg}" export BEAKER_KEYFILE="${BEAKER_KEYFILE:-~/.ssh/id_rsa-acceptance}" export BEAKER_HELPER="${BEAKER_HELPER:-acceptance/lib/helper.rb}" export BEAKER_LOADPATH="${BEAKER_LOADPATH:-acceptance/lib}" bundle install --path vendor/bundle case $1 in -p | --p* ) do_init bundle exec beaker exec echo "Preserving hosts, run `bundle exec beaker exec ` to use the same hosts again." ;; -r | --r* ) if [ ! -s ./.beaker/subcommand_options.yaml ]; then echo "$0: Can not find subcommand_options.yaml; cannot run without init.\n \ Use this script with -p to create new hosts and initialize them." exit -1; fi bundle exec beaker exec $BEAKER_TESTSUITE ;; * ) # Preserve hosts on failure do_init bundle exec beaker exec if [ $? = 0 ] ; then echo "Run completed successfully, destroying hosts." bundle exec beaker destroy rm .beaker/subcommand_options.yaml else echo "Run failed, preserving hosts. Run against these hosts again with `bundle exec beaker exec `." echo "Alternatively, run this script again with `-r`." fi ;; esac puppetlabs-puppetserver-7e1a9a8/acceptance/scripts/test-full-puppet3compat.sh000077500000000000000000000005161470345337400277250ustar00rootroot00000000000000#!/bin/bash set -x # command line parameters export GENCONFIG_LAYOUT="${GENCONFIG_LAYOUT:-redhat6-64ma-debian6-64a-windows2008r2-64a}" export BEAKER_TESTSUITE="${BEAKER_TESTSUITE:-acceptance/suites/puppet3_tests}" export BEAKER_PRESUITE="acceptance/suites/pre_suite/puppet3_compat" bash ./acceptance/scripts/generic/testrun-full.sh puppetlabs-puppetserver-7e1a9a8/acceptance/suites/000077500000000000000000000000001470345337400224705ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/000077500000000000000000000000001470345337400251755ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compat/000077500000000000000000000000001470345337400310625ustar00rootroot00000000000000binary_file_test.rb000066400000000000000000000017371470345337400346620ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compatrequire 'puppetserver/acceptance/compat_utils' test_name 'binary file resource' teardown do rm_compat_test_files() end agents.each do |agent| studio = agent.tmpdir('binary_file_test') step "Apply simmons::binary_file to agent #{agent.platform}" do apply_simmons_class(agent, studio, 'simmons::binary_file') end step "Validate binary-file" do sha256 = on(agent, "sha256sum #{studio}/binary-file | awk '{print $1}'").stdout.chomp assert_equal('55a26d3939c947e4455e8f48ffb4724170aa4f9aa4c8d58c57800ad2026f4d79', sha256) end step "Validate binary-file filebucket backup" do old_sha256 = on(agent, "sha256sum #{studio}/binary-file-old | awk '{print $1}'").stdout.chomp on(agent, puppet("filebucket restore #{studio}/binary-file-backup --digest_algorithm sha256 #{old_sha256}")) diff = on(agent, "diff #{studio}/binary-file-old #{studio}/binary-file-backup").exit_code assert_equal(0, diff, 'binary-file was not backed up to filebucket') end end content_file_test.rb000066400000000000000000000007751470345337400350510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compatrequire 'puppetserver/acceptance/compat_utils' test_name 'content file resource' teardown do rm_compat_test_files() end agents.each do |agent| studio = agent.tmpdir('content_file_test') step "Apply simmons::content_file to agent #{agent.platform}" do apply_simmons_class(agent, studio, 'simmons::content_file') end step "Validate content-file" do contents = on(agent, "cat #{studio}/content-file").stdout.chomp assert_equal('Static content defined in manifest', contents) end end custom_fact_output_test.rb000066400000000000000000000010451470345337400363160ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compatrequire 'puppetserver/acceptance/compat_utils' test_name 'custom fact' teardown do rm_compat_test_files() end agents.each do |agent| studio = agent.tmpdir('custom_fact_output_test') step "Apply simmons::custom_fact_output to agent #{agent.platform}" do apply_simmons_class(agent, studio, 'simmons::custom_fact_output') end step "Validate custom-fact-output" do expected = on(agent, "hostname").stdout.chomp content = on(agent, "cat #{studio}/custom-fact-output").stdout.chomp assert_equal(expected, content) end end external_fact_output_test.rb000066400000000000000000000010741470345337400366300ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compatrequire 'puppetserver/acceptance/compat_utils' test_name 'executable external fact' teardown do rm_compat_test_files() end agents.each do |agent| studio = agent.tmpdir('external_fact_output_test') step "Apply simmons::external_fact_output to agent #{agent.platform}" do apply_simmons_class(agent, studio, 'simmons::external_fact_output') end step "Validate external-fact-output" do expected = on(agent, "hostname").stdout.chomp content = on(agent, "cat #{studio}/external-fact-output").stdout.chomp assert_equal(expected, content) end end mount_point_binary_file_test.rb000066400000000000000000000011251470345337400373040ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compatrequire 'puppetserver/acceptance/compat_utils' test_name 'binary file resource from custom mount point' teardown do rm_compat_test_files() end agents.each do |agent| studio = agent.tmpdir('mount_point_binary_file_test') step "Apply simmons::mount_point_binary_file to agent #{agent.platform}" do apply_simmons_class(agent, studio, 'simmons::mount_point_binary_file') end step "Validate mount-point-binary-file" do md5 = on(agent, "md5sum #{studio}/mount-point-binary-file | awk '{print $1}'").stdout.chomp assert_equal('4b392568e0c19886bf274663a63b7d18', md5) end end mount_point_source_file_test.rb000066400000000000000000000011141470345337400373160ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compatrequire 'puppetserver/acceptance/compat_utils' test_name 'source file resource from custom mount point' teardown do rm_compat_test_files() end agents.each do |agent| studio = agent.tmpdir('mount_point_source_file_test') step "Apply simmons::mount_point_source_file to agent #{agent.platform}" do apply_simmons_class(agent, studio, 'simmons::mount_point_source_file') end step "Validate mount-point-source-file" do contents = on(agent, "cat #{studio}/mount-point-source-file").stdout.chomp assert_equal('File served from custom mount point', contents) end end recursive_directory_test.rb000066400000000000000000000021271470345337400364640ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compatrequire 'puppetserver/acceptance/compat_utils' test_name 'recursive directory file resource' teardown do rm_compat_test_files() end agents.each do |agent| studio = agent.tmpdir('recursive_directory_test') step "Apply simmons::recursive_directory to agent #{agent.platform}" do apply_simmons_class(agent, studio, 'simmons::recursive_directory') end step "Validate recursive-directory" do directory_exists = on(agent, "test -d #{studio}/recursive-directory").exit_code assert_equal(0, directory_exists) file1_contents = on(agent, "cat #{studio}/recursive-directory/file1").stdout.chomp assert_equal('recursive file 1', file1_contents) file2_contents = on(agent, "cat #{studio}/recursive-directory/file2").stdout.chomp assert_equal('recursive file 2', file2_contents) subdir_exists = on(agent, "test -d #{studio}/recursive-directory/subdir").exit_code assert_equal(0, subdir_exists) subfile_contents = on(agent, "cat #{studio}/recursive-directory/subdir/subfile").stdout.chomp assert_equal('recursive subfile contents', subfile_contents) end end source_file_test.rb000066400000000000000000000016461470345337400346750ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/compat_tests/020_backwards_compatrequire 'puppetserver/acceptance/compat_utils' test_name 'source file resource' teardown do rm_compat_test_files() end agents.each do |agent| studio = agent.tmpdir('source_file_test') step "Apply simmons::source_file to agent #{agent.platform}" do apply_simmons_class(agent, studio, 'simmons::source_file') end step "Validate source-file" do contents = on(agent, "cat #{studio}/source-file").stdout.chomp assert_equal('Static source file contents', contents) end step "Validate source-file filebucket backup" do old_sha256 = on(agent, "sha256sum #{studio}/source-file-old | awk '{print $1}'").stdout.chomp on(agent, puppet("filebucket restore #{studio}/source-file-backup --digest_algorithm sha256 #{old_sha256}")) diff = on(agent, "diff #{studio}/source-file-old #{studio}/source-file-backup").exit_code assert_equal(0, diff, 'source-file was not backed up to filebucket') end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/post_suite/000077500000000000000000000000001470345337400246665ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/post_suite/99_collect_data.rb000066400000000000000000000001321470345337400301460ustar00rootroot00000000000000step "Preserve Puppet Server Log Files" puppet_server_collect_data master, 'post_suite' puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/000077500000000000000000000000001470345337400244675ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/compat_common/000077500000000000000000000000001470345337400273225ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/compat_common/00_setup_environment.rb000066400000000000000000000001211470345337400337240ustar00rootroot00000000000000step "Initialize Test Config" PuppetServerExtensions.initialize_config options puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/compat_common/30_install_dev_repos.rb000066400000000000000000000012021470345337400336600ustar00rootroot00000000000000install_opts = options.merge({ :dev_builds_repos => ["PC1"]}) if test_config[:puppetserver_install_type] == :package package_build_version = ENV['PACKAGE_BUILD_VERSION'] if package_build_version.nil? abort("Environment variable PACKAGE_BUILD_VERSION required for package installs!") end step "Setup Puppet Server dev repository on the master." do install_puppetlabs_dev_repo(master, 'puppetserver', package_build_version, nil, install_opts) end step "Setup Puppet dev repository on the master." do install_puppetlabs_dev_repo(master, 'puppet-agent', test_config[:puppet_build_version], nil, install_opts) end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/compat_common/70_install_puppetmaster.rb000066400000000000000000000000731470345337400344340ustar00rootroot00000000000000step "Install Puppet Server." install_puppet_server master 71_install_simmons_module.rb000066400000000000000000000010321470345337400346530ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/compat_commonsimmons_version = '0.3.3' step "Install nwolfe-simmons module #{simmons_version}" do on(master, puppet("module install nwolfe-simmons --version #{simmons_version}")) end step "Configure file serving" do fileserverconf = on(master, puppet("config print fileserverconfig")).stdout.chomp create_remote_file(master, fileserverconf, < 'windows' GEOTRUST_GLOBAL_CA = <<-EOM -----BEGIN CERTIFICATE----- MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU 1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV 5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== -----END CERTIFICATE----- EOM USERTRUST_NETWORK_CA = <<-EOM -----BEGIN CERTIFICATE----- MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn 0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t 3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -----END CERTIFICATE----- EOM EQUIFAX_CA = <<-EOM -----BEGIN CERTIFICATE----- MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 -----END CERTIFICATE----- EOM hosts.each do |host| step "Installing Geotrust CA cert" create_remote_file(host, "geotrustglobal.pem", GEOTRUST_GLOBAL_CA) on host, "chmod 644 geotrustglobal.pem" on host, "cmd /c certutil -v -addstore Root `cygpath -w geotrustglobal.pem`" step "Installing Usertrust Network CA cert" create_remote_file(host, "usertrust-network.pem", USERTRUST_NETWORK_CA) on host, "chmod 644 usertrust-network.pem" on host, "cmd /c certutil -v -addstore Root `cygpath -w usertrust-network.pem`" step "Installing Equifax CA cert" create_remote_file(host, "equifax.pem", EQUIFAX_CA) on host, "chmod 644 equifax.pem" on host, "cmd /c certutil -v -addstore Root `cygpath -w equifax.pem`" end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/10_update_ca_certs.rb000066400000000000000000000013431470345337400314140ustar00rootroot00000000000000step 'Update CA certs on Centos' do hosts.each do |host| if host.platform =~ /el-6/ # Our EL6 images do not have recent enough repos to pull down the updated ca-certificates package, # so we need to edit their configs before attempting to upgrade it on(host, 'rm -f /etc/yum.repos.d/localmirror-extras.repo /etc/yum.repos.d/localmirror-optional.repo') on(host, "sed -i 's/68/610/' /etc/yum.repos.d/localmirror-os.repo") on(host, 'yum update -y ca-certificates') elsif host.platform =~ /el-7/ on(host, 'yum update -y ca-certificates') elsif host.platform =~ /debian|ubuntu/ on(host, 'apt-get update') on(host, 'apt-get install -y ca-certificates libgnutls30') end end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/20_install_released_puppet.rb000066400000000000000000000007451470345337400332040ustar00rootroot00000000000000# skip this step entirely unless we are running in :upgrade mode if (test_config[:puppetserver_install_mode] == :upgrade) step "Install released MRI Puppet for upgrade test" do hosts.each do |host| install_package host, 'puppet' end end step "Install released Puppet Server for upgrade test" do manifest = " package { 'puppetserver': ensure => 'installed' } " apply_manifest_on(master, manifest) puppetserver_initialize_ssl end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/30_install_dev_repos.rb000066400000000000000000000013231470345337400320030ustar00rootroot00000000000000install_opts = options.merge({ :dev_builds_repos => ["PC1"]}) if test_config[:puppetserver_install_type] == :package package_build_version = ENV['PACKAGE_BUILD_VERSION'] if package_build_version.nil? abort("Environment variable PACKAGE_BUILD_VERSION required for package installs!") end step "Setup Puppet Server dev repository on the master." do install_puppetlabs_dev_repo(master, 'puppetserver', package_build_version, nil, install_opts) end end confine_block :except, :platform => ['windows'] do step "Setup Puppet Labs Dev Repositories." do hosts.each do |host| install_puppetlabs_dev_repo(host, 'puppet-agent', test_config[:puppet_build_version], nil, install_opts) end end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/40_install_jvmpuppet_deps.rb000066400000000000000000000006401470345337400330640ustar00rootroot00000000000000case test_config[:puppetserver_install_type] when :git # only if installing from source step "Install Puppet Server Dependencies" `lein install` project_version = 'puppetserver-version=' project_version += test_config[:puppetserver_version] || `lein with-profile ci pprint :version | tail -n 1 | cut -d\\" -f2` ezbake_stage 'puppetserver', project_version install_ezbake_deps master end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/70_install_puppet.rb000066400000000000000000000025621470345337400313440ustar00rootroot00000000000000step "Install MRI Puppet Agents." do sha = test_config[:puppet_build_version] install_from_build_data_url('puppet-agent', "http://builds.delivery.puppetlabs.net/puppet-agent/#{sha}/artifacts/#{sha}.yaml", hosts) end step "Verify agent installs" do agents.each do |agent| on agent, puppet('--version') ruby = ruby_command(agent) on agent, "#{ruby} --version" end end step "Upgrade nss to version that is hopefully compatible with jdk version puppetserver will use." do nss_package_name=nil variant, _, _, _ = master['platform'].to_array case variant when /^(debian|ubuntu)$/ nss_package_name="libnss3" when /^(redhat|el|centos)$/ nss_package_name="nss" end if nss_package_name if master['platform'] == 'el-8-x86_64' || master['platform'] == 'el-9-x86_64' master.install_package(nss_package_name) else master.upgrade_package(nss_package_name) end else logger.warn("Don't know what nss package to use for #{variant} so not installing one") end end if (test_config[:puppetserver_install_mode] == :upgrade) step "Upgrade Puppet Server." upgrade_package(master, "puppetserver") else step "Install Puppet Server." make_env = { "prefix" => "/usr", "confdir" => "/etc/", "rundir" => "/var/run/puppetserver", "initdir" => "/etc/init.d", } install_puppet_server master, make_env end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/71_smoke_test_puppetserver.rb000066400000000000000000000020271470345337400332770ustar00rootroot00000000000000# This step needs to execute as quickly as possible after the # install_puppet_server master step located in 70_install_puppet.rb # # This is because beaker uses `puppet resource` to manage the puppetserver # service which has the side-effect of changing ownership and permissions of key # paths such as /var/run/puppetlabs and /etc/puppetlabs/puppet/ssl # # This side-effect masks legitimate issues we need to test, such as "the # puppetserver fails to start out of the package" step "(SERVER-414) Make sure puppetserver can start without puppet resource, "\ "apply, or agent affecting the known good state of the SUT in a way that "\ "causes the tests to pass with false positive successful results." variant = master['platform'].to_array.first case variant when /^(redhat|el|centos)$/ on(master, "puppetserver ca setup") on(master, "service puppetserver start") on(master, "service puppetserver status") on(master, "service puppetserver stop") else step "(SERVER-414) Skipped for platform variant #{variant}" end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/80_configure_puppet.rb000066400000000000000000000014701470345337400316550ustar00rootroot00000000000000step "Configure puppet.conf" do hostname = on(master, 'facter hostname').stdout.strip fqdn = on(master, 'facter fqdn').stdout.strip hosts.each do |host| dir = host.tmpdir('configure_puppet') if host == master lay_down_new_puppet_conf( host, {"main" => {"dns_alt_names" => "puppet,#{hostname},#{fqdn}", "verbose" => true, "server" => fqdn}}, dir) else lay_down_new_puppet_conf(host, {"main" => {"server" => fqdn}}, dir) end end config = { 'certificate-authority' => { 'allow-subject-alt-names' => true }, 'dropsonde' => { 'enabled' => false }} path = '/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf' modify_tk_config(master, path, config) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/85_configure_sut.rb000066400000000000000000000003561470345337400311620ustar00rootroot00000000000000step "Use Java 11 on RHEL 8" do if master['platform'].start_with?('el-8') on master, 'yum install -y java-11' on master, 'alternatives --set java java-11-openjdk.x86_64' on master, 'systemctl restart puppetserver' end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/90_validate_sign_cert.rb000066400000000000000000000003261470345337400321250ustar00rootroot00000000000000# SSL Initialization will already have occurred if we are installing in upgrade # mode. if not (test_config[:puppetserver_install_mode] == :upgrade) step "Validate Sign Cert." puppetserver_initialize_ssl end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/95_install_pdb.rb000066400000000000000000000031331470345337400305760ustar00rootroot00000000000000 matching_puppetdb_platform = puppetdb_supported_platforms.select { |r| r =~ master.platform } skip_test if matching_puppetdb_platform.length == 0 || master.fips_mode? test_name 'PuppetDB setup' sitepp = '/etc/puppetlabs/code/environments/production/manifests/site.pp' teardown do on(master, "rm -f #{sitepp}") end step 'Install Puppet nightly repo' do install_puppetlabs_release_repo_on(master, 'puppet8-nightly') end step 'Update EL postgresql repos' do # work around for testing on rhel and the repos on the image not finding the pg packages it needs if master.platform =~ /el-/ major_version = case master.platform when /-8/ then 8 when /-9/ then 9 end on master, "dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-#{major_version}-x86_64/pgdg-redhat-repo-latest.noarch.rpm" on master, "dnf -qy module disable postgresql" end end step 'Install PuppetDB module' do on(master, puppet('module install puppetlabs-puppetdb')) end if master.platform.variant == 'debian' master.install_package('apt-transport-https') end step 'Configure PuppetDB via site.pp' do create_remote_file(master, sitepp, < false, manage_package_repo => true, postgres_version => '14', } class { 'puppetdb::master::config': manage_report_processor => true, enable_reports => true, } } SITEPP on(master, "chmod 644 #{sitepp}") with_puppet_running_on(master, {}) do on(master, puppet_agent("--test --server #{master}"), :acceptable_exit_codes => [0,2]) end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/foss/99_collect_data.rb000066400000000000000000000001311470345337400307200ustar00rootroot00000000000000step "Preserve Puppet Server Log Files" puppet_server_collect_data master, 'pre_suite' puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/optional/000077500000000000000000000000001470345337400263145ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/optional/setup_puppetserver.rb000066400000000000000000000004511470345337400326250ustar00rootroot00000000000000step "Configure Puppet Server ." if master['platform'].include? 'el-6' on master, "sed -i.bak -e 's/localhost/#{master}/' /etc/puppetlabs/puppetserver/conf.d/puppetserver.conf" on master, "sed -i.bak -e 's/localhost/#{master}/' /etc/puppetlabs/puppetserver/conf.d/webserver.conf" end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/puppet3_compat/000077500000000000000000000000001470345337400274325ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/puppet3_compat/70_install_puppet.rb000066400000000000000000000010231470345337400333240ustar00rootroot00000000000000require 'puppetserver/acceptance/compat_utils' step "Install Legacy Puppet Agents." default_puppet_version = '3.8.7' puppet_version = ENV['PUPPET_LEGACY_VERSION'] if not puppet_version logger.info "PUPPET_LEGACY_VERSION is not set!" logger.info " using default value of #{default_puppet_version}" puppet_version = default_puppet_version end # Always force 3.x agents to use FOSS puppet install type nonmaster_agents.each { |agent| agent[:type] = 'foss' } install_puppet_on(nonmaster_agents, {:version => puppet_version}) puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/puppet3_compat/80_configure_agents.rb000066400000000000000000000006741470345337400336170ustar00rootroot00000000000000require 'puppetserver/acceptance/compat_utils' step "Perform agent upgrade steps" do step "Enable structured facts" do on(agents, puppet("config set stringify_facts false --section agent")) end end # Legacy agents have $ssldir under $vardir, and tests # need to be able to blow away $vardir after each run step "Relocate legacy agent $ssldir" do on(nonmaster_agents(), puppet("config set ssldir \$confdir/ssl --section agent")) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/puppet4_compat/000077500000000000000000000000001470345337400274335ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/puppet4_compat/70_install_puppet.rb000066400000000000000000000016251470345337400333350ustar00rootroot00000000000000require 'puppetserver/acceptance/compat_utils' # zypper installs of puppet-agent for SLES will fail if the package can't be # validated with the Puppet GPG key. Beaker doesn't implicitly install the # Puppet GPG key so need to install it before trying to install the # puppet-agent. step "Install Updated Puppet GPG key for Any SLES Agents." nonmaster_agents.each { |agent| variant = agent['platform'].variant if variant == 'sles' on(agent, 'rpmkeys --import https://yum.puppetlabs.com/RPM-GPG-KEY-puppet') end } step "Install Legacy Puppet Agents." default_puppet_version = '1.10.15' puppet_version = ENV['PUPPET_LEGACY_VERSION'] if not puppet_version logger.info "PUPPET_LEGACY_VERSION is not set!" logger.info " using default value of #{default_puppet_version}" puppet_version = default_puppet_version end install_puppet_agent_on(nonmaster_agents, {:puppet_agent_version => puppet_version}) puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/puppet5_compat/000077500000000000000000000000001470345337400274345ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/puppet5_compat/70_install_puppet.rb000066400000000000000000000016651470345337400333420ustar00rootroot00000000000000require 'puppetserver/acceptance/compat_utils' # zypper installs of puppet-agent for SLES will fail if the package can't be # validated with the Puppet GPG key. Beaker doesn't implicitly install the # Puppet GPG key so need to install it before trying to install the # puppet-agent. step "Install Updated Puppet GPG key for Any SLES Agents." nonmaster_agents.each { |agent| variant = agent['platform'].variant if variant == 'sles' on(agent, 'rpmkeys --import https://yum.puppetlabs.com/RPM-GPG-KEY-puppet') end } step "Install Legacy Puppet Agents." default_puppet_version = '5.5.19' puppet_version = ENV['PUPPET_LEGACY_VERSION'] if not puppet_version logger.info "PUPPET_LEGACY_VERSION is not set!" logger.info " using default value of #{default_puppet_version}" puppet_version = default_puppet_version end install_puppet_agent_on(nonmaster_agents, {:puppet_agent_version => puppet_version, :puppet_collection => 'puppet5'}) puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/puppet5_compat/80_configure_puppet.rb000066400000000000000000000014041470345337400336450ustar00rootroot00000000000000step "Configure puppet.conf" do hostname = on(master, 'facter hostname').stdout.strip fqdn = on(master, 'facter fqdn').stdout.strip hosts.each do |host| dir = host.tmpdir('configure_puppet') if host == master lay_down_new_puppet_conf( host, {"main" => {"dns_alt_names" => "puppet,#{hostname},#{fqdn}", "verbose" => true, "server" => fqdn}}, dir) else lay_down_new_puppet_conf(host, {"main" => {"server" => fqdn}}, dir) end end config = { 'certificate-authority' => { 'allow-subject-alt-names' => true }} path = '/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf' modify_tk_config(master, path, config) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/upgrade/000077500000000000000000000000001470345337400261165ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/upgrade/00_setup_environment.rb000066400000000000000000000001301470345337400325200ustar00rootroot00000000000000step "Initialize Test Config" do PuppetServerExtensions.initialize_config options end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/pre_suite/upgrade/10_install_puppet.rb000066400000000000000000000040521470345337400320070ustar00rootroot00000000000000def install_pc1_repo(host) variant, version, _, codename = host['platform'].to_array return if variant =~ /win/ variant = 'el' if variant =~ /redhat|centos/ debian = !!codename if debian pkg = "puppetlabs-release-pc1-#{codename}.deb" url = "http://release-archives.puppet.com/apt" else pkg = "puppetlabs-release-pc1-#{variant}-#{version}.noarch.rpm" url = "http://release-archives.puppet.com/yum" end on host, "wget #{url}/#{pkg}" if debian on host, "dpkg -i --force-all #{pkg}" on host, "apt-get update" else on host, "rpm -i --replacepkgs #{pkg}" end if variant =~ /sles/ # Hack around RE-12490's invalid sles repo lists for pc1. on host, "sed -i 's,==,=,' /etc/zypp/repos.d/puppetlabs-pc1.repo" on host, "rpmkeys --import https://yum.puppetlabs.com/RPM-GPG-KEY-puppet" end # cargo culted configure_type_defaults_on(host) end step "Install PC1 repository" do block_on(hosts) do |host| install_pc1_repo(host) end end step "Install legacy Puppet agents" do default_puppet_version = '1.10.1' puppet_version = ENV['PUPPET_LEGACY_VERSION'] if not puppet_version logger.info "PUPPET_LEGACY_VERSION is not set!" logger.info " using default value of #{default_puppet_version}" puppet_version = default_puppet_version end hosts.each { |host| host.install_package('puppet-agent') } end step "Install legacy Puppetserver" do master.install_package('puppetserver') end step "Configure puppet.conf" do hostname = on(master, 'facter hostname').stdout.strip fqdn = on(master, 'facter fqdn').stdout.strip hosts.each do |host| dir = host.tmpdir('configure_puppet') if host == master lay_down_new_puppet_conf( host, {"main" => {"dns_alt_names" => "puppet,#{hostname},#{fqdn}", "verbose" => true, "server" => fqdn}}, dir) else lay_down_new_puppet_conf(host, {"main" => {"server" => fqdn}}, dir) end end end puppetserver_initialize_ssl puppetlabs-puppetserver-7e1a9a8/acceptance/suites/puppet3_tests/000077500000000000000000000000001470345337400253125ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/puppet3_tests/README.markdown000066400000000000000000000002041470345337400300070ustar00rootroot00000000000000# Puppet 3 Compatibility This directory contains tests which exercises puppet 3 against puppet server 2.0 which includes Puppet 4. puppetlabs-puppetserver-7e1a9a8/acceptance/suites/puppet3_tests/puppet3_version_test.rb000066400000000000000000000014451470345337400320470ustar00rootroot00000000000000test_name "Testing Master/Agent backwards compatibility" # Agent running on the master is current, not legacy. legacy_agents = agents.reject { |agent| agent == master } step "Check that legacy agents have Puppet 3.x installed" on(legacy_agents, puppet("--version")) do |result| assert(result.stdout.start_with? "3.", "puppet --version does not start with major version 3.") end step "Check that Puppet Server has Puppet 6.x installed" on(master, puppet("--version")) do |result| assert_match(/\A6/, result.stdout, "puppet --version does not start with major version 6.x") end step "Check that the agent on the master runs against the master" with_puppet_running_on(master, {}) do agent_cmd = puppet("agent --test --server #{master}") on(master, agent_cmd, :acceptable_exit_codes => [0,2]) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/puppet4_tests/000077500000000000000000000000001470345337400253135ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/puppet4_tests/puppet4_version_test.rb000066400000000000000000000014431470345337400320470ustar00rootroot00000000000000test_name "Testing Master/Agent backwards compatibility" # Agent running on the master is current, not legacy. legacy_agents = agents.reject { |agent| agent == master } step "Check that legacy agents have Puppet 4.x installed" on(legacy_agents, puppet("--version")) do |result| assert_match(/\A4\./, result.stdout, "puppet --version does not start with major version 4.") end step "Check that Puppet Server has Puppet 6.x installed" on(master, puppet("--version")) do |result| assert_match(/\A6/, result.stdout, "puppet --version does not start with major version 6.x") end step "Check that the agent on the master runs against the master" with_puppet_running_on(master, {}) do agent_cmd = puppet("agent --test --server #{master}") on(master, agent_cmd, :acceptable_exit_codes => [0,2]) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/puppet5_tests/000077500000000000000000000000001470345337400253145ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/puppet5_tests/puppet5_version_test.rb000066400000000000000000000014431470345337400320510ustar00rootroot00000000000000test_name "Testing Master/Agent backwards compatibility" # Agent running on the master is current, not legacy. legacy_agents = agents.reject { |agent| agent == master } step "Check that legacy agents have Puppet 5.x installed" on(legacy_agents, puppet("--version")) do |result| assert_match(/\A5\./, result.stdout, "puppet --version does not start with major version 5.") end step "Check that Puppet Server has Puppet 8.x installed" on(master, puppet("--version")) do |result| assert_match(/\A8/, result.stdout, "puppet --version does not start with major version 8.x") end step "Check that the agent on the master runs against the master" with_puppet_running_on(master, {}) do agent_cmd = puppet("agent --test --server #{master}") on(master, agent_cmd, :acceptable_exit_codes => [0,2]) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/000077500000000000000000000000001470345337400236325ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/00_smoke/000077500000000000000000000000001470345337400252475ustar00rootroot00000000000000master_starts_if_agent_run_before_ssl_files_inited.rb000066400000000000000000000064151470345337400400570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/00_smoketest_name "Master can startup even if agent run before ssl files inited" skip_test 'Skipping for PE since it pre-configures a CRL file and Puppet ' \ 'Server does not yet update it at startup - SERVER-346 and SERVER-911' \ if options[:type] == 'pe' puppetservice=options['puppetservice'] ssldir = master.puppet['ssldir'] cadir = master.puppet['cadir'] backup_ssldir = master.tmpdir("agent_run_before_master_init_ssldir_backup") backup_cadir = master.tmpdir("agent_run_before_master_init_cadir_backup") step "Backup original SSL configuration so can be restored when test finishes" do on(master, "cp -pR #{ssldir} #{backup_ssldir}") on(master, "cp -pR #{cadir} #{backup_cadir}") end teardown do step 'Stop the server so the original SSL config can be restored' do # This is done as a 'service stop' as opposed to a resource 'ensure=stopped' # to ensure that the OS isn't trying to restart a failing service in the # background (e.g, on a system using systemd Restart=on-failure) and # potentially recreating part of the SSL state before the original state # can be restored. 'ensure=stopped' doesn't terminate the systemd # Restart=on-failure loop. on(master, "service #{puppetservice} stop") end # Re-enable PuppetDB facts terminus on(master, puppet("config set route_file /etc/puppetlabs/puppet/routes.yaml")) step 'Restore the original server SSL config' do on(master, "rm -rf #{ssldir}") on(master, "rm -rf #{cadir}") on(master, "mv #{backup_ssldir}/#{File.basename(ssldir)} #{File.dirname(ssldir)}") on(master, "mv #{backup_cadir}/#{File.basename(cadir)} #{File.dirname(cadir)}") end step 'Restart the server with original SSL config before ending the test' do on(master, puppet("resource service #{puppetservice} ensure=running")) end end step 'Disable facts reporting to PuppetDB while we munge certs' do on(master, puppet("config set route_file /tmp/nonexistant.yaml")) end step 'Ensure puppetserver has been stopped before nuking SSL directory' do on(master, puppet("resource service #{puppetservice} ensure=stopped")) end step 'Nuke the existing SSL directory' do on(master, "rm -rf #{ssldir}/*") on(master, "rm -rf #{cadir}/*") end step 'Do an agent run with the server stopped so a public/private key can be created' do # The agent run is expected to return a '1' (failure) here because the server # it tries to contact would be down. on(master, puppet('agent', '--test', '--certname', master), {:acceptable_exit_codes => [1]}) end step 'Ensure puppetserver can start successfully with the public/private key but no cert in place for master' do # Using 'service start' here instead of resource 'ensure=running' because # 'running' can return a 0 exit code whether or not the service is actually # started whereas 'service start' should only return a 0 exit code if the # startup was successful. on(master, 'puppetserver ca setup') on(master, "service #{puppetservice} start") end step 'Ensure an agent run with the generated master cert is now successful' do # Exit code of 0 (success, no changes) or 2 (success, some changes) allowed # since only interested in determining that the run is successful. on(master, puppet('agent', '--test', '--certname', master), {:acceptable_exit_codes => [0, 2]}) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/00_smoke/puppetdb_integration.rb000066400000000000000000000163001470345337400320220ustar00rootroot00000000000000## Tests that PuppetDB can be integrated with Puppet Server in a simple ## monolithic install (i.e. PuppetDB on same node as Puppet Server). ## ## In this context 'integrated' just means that Puppet Server is able to ## communicate over HTTP/S with PuppetDB to send it information, such as ## agent run reports. ## ## This test validates communication is successful by querying the PuppetDB HTTP ## API and asserting that an updated factset, catalog and report from an agent ## run made it into PuppetDB. Additionally, the STDOUT of the agent run is ## tested for the presence of a Notify resource that was exported by another ## node. ## ## Finally, the output of the Puppet Server HTTP /status API is tested ## to ensure that metrics related to PuppetDB communication were recorded. # # We only run this test if we'll have puppetdb installed, which is gated in # acceptance/suites/pre_suite/foss/95_install_pdb.rb using the same conditional matching_puppetdb_platform = puppetdb_supported_platforms.select { |r| r =~ master.platform } skip_test if matching_puppetdb_platform.length == 0 || master.fips_mode? skip_test if master.is_pe? require 'json' require 'time' require 'securerandom' run_timestamp = nil master_fqdn = on(master, '/opt/puppetlabs/bin/facter fqdn').stdout.chomp random_string = SecureRandom.urlsafe_base64.freeze puppetserver_conf_path = '/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf' old_puppetserver_conf = on(master, "cat #{puppetserver_conf_path}").stdout common_yaml_path = '/etc/puppetlabs/code/environments/production/data/common.yaml' create_remote_file(master, common_yaml_path, <> # Dummy query to record a hit for the PuppetDB query API to metrics. $_ = puppetdb_query(['from', 'nodes', ['extract', 'certname']]) } EOM on(master, "chmod 644 #{sitepp}") teardown do modify_tk_config(master, puppetserver_conf_path, read_tk_config_string(old_puppetserver_conf), replace=true) on(master, "rm -f #{sitepp} #{common_yaml_path}") end end with_puppet_running_on(master, {}) do step 'Enable PuppetDB' do apply_manifest_on(master, < true, manage_report_processor => true, } EOM end step 'Run agent to generate exported resources' do # This test compiles a catalog using a differnt certname so that # later runs can test collection. on(master, 'puppetserver ca generate --certname=resource-exporter.test') teardown do on(master, puppet('node', 'deactivate', 'resource-exporter.test')) on(master, "puppet ssl clean --certname resource-exporter.test") on(master, 'puppetserver ca clean --certname=resource-exporter.test') end on(master, puppet_agent('--test', '--noop', '--certname', 'resource-exporter.test'), :acceptable_exit_codes => [0,2]) end step 'Run agent to trigger data submission to PuppetDB' do # ISO 8601 timestamp, with milliseconds and time zone. Local time is used # instead of UTC as both PuppetDB and Puppet Server log in local time. run_timestamp = Time.iso8601(on(master, 'date +"%Y-%m-%dT%H:%M:%S.%3N%:z"').stdout.chomp) on(master, puppet_agent("--test"), :acceptable_exit_codes => [0,2]) do |result| assert_match(/Notice: #{random_string}/, result.stdout, 'Puppet run collects exported Notify') end end step 'Validate PuppetDB metrics captured by puppet-profiler service' do query = "curl -k https://localhost:8140/status/v1/services/puppet-profiler?level=debug" response = JSON.parse(on(master, query).stdout.chomp) pdb_metrics = response['status']['experimental']['puppetdb-metrics'] # NOTE: If these tests fail, then likely someone changed a metric # name passed to Puppet::Util::Profiler.profile over in the Ruby # terminus code of the PuppetDB project without realizing that is a # breaking change to metrics critical for measuring compiler performance. [ "query", "resource_search", "facts_find", "catalog_save", "facts_save", "command_submit_replace_catalog", "command_submit_replace_facts", "report_process", "command_submit_store_report", "payload_format", "facts_encode", "catalog_munge", "report_convert_to_wire_format_hash" ].each do |metric_name| metric_data = pdb_metrics.find {|m| m['metric'] == metric_name } || {} metric_count = metric_data.fetch('count', 0) logger.debug("PuppetDB metrics #{metric_name} recorded #{metric_count} times") assert_operator(metric_count, :>, 0, "PuppetDB metrics recorded for: #{metric_name}") end end end step 'Validate PuppetDB successfully stored agent data' do query = "curl http://localhost:8080/pdb/query/v4/nodes/#{master_fqdn}" agent_datasets = %w[facts_timestamp catalog_timestamp report_timestamp] missing_datasets = [ ] retries = 3 retries.times do |i| logger.debug("PuppetDB query attempt #{i} for updated agent data...") missing_datasets = [ ] response = JSON.parse(on(master, query).stdout.chomp) dataset_states = response.select {|k, v| agent_datasets.include?(k)}.map do |k, v| t = Time.iso8601(v) rescue nil [k, t] end.to_h missing_datasets = dataset_states.select {|k, v| v.nil? || (v < run_timestamp)}.keys break if missing_datasets.empty? sleep(1) # Give PuppetDB some time to catch up. end assert_empty(missing_datasets, <<-EOS) PuppetDB did not return updated data for #{master_fqdn} after #{retries} consecutive queries. The following timestamps were missing or not updated to be later than: #{run_timestamp.iso8601(3)}: #{missing_datasets.join(' ')} Check puppetserver.log for errors that may have ocurred during data submission. Check puppetdb.log for errors that may have ocurred during data processing. EOS end step 'Validate PuppetDB stored lookup data sent from puppetserver' do query = "curl -X POST http://localhost:8080/pdb/query/v4/catalog-input-contents" << " -H 'Content-Type:application/json'" << " -d '{\"query\": \"\" }'" retries = 3 (1..(retries + 1)).each do |i| if i > retries raise "Attempted #{retries} times to get lookup data from puppetdb, but none found" end logger.debug("PuppetDB query attempt #{i} for catalog inputs") response = JSON.parse(on(master, query).stdout.chomp) # Give PuppetDB some time to process it is running slow if response.empty? sleep 1 next end response.each do |input| assert_equal('some-test-key', input['name']) assert_equal('hiera', input['type']) end break end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/00_smoke/testtest.rb000066400000000000000000000002201470345337400274450ustar00rootroot00000000000000test_name "Testing Master/Agent connection" with_puppet_running_on( master, {} ) do on agents, puppet("agent --test --server #{master}") end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/00_smoke/validate-syslog-logback.rb000066400000000000000000000040001470345337400322750ustar00rootroot00000000000000test_name 'SERVER-1215: Validate that logback can be configured to work with syslog' service = options['puppetservice'] logback_path = '/etc/puppetlabs/puppetserver/logback.xml' logback_backup = '/etc/puppetlabs/puppetserver/logback.back' logback_config=<<-EOM %d %-5p [%t] [%c{2}] %m%n /var/log/puppetlabs/puppetserver/puppetserver.log true %d %-5p [%t] [%c{2}] %m%n localhost USER %thread: %-5level %logger{36} - %msg%n EOM teardown do on(master, "mv #{logback_backup} #{logback_path}") reload_server end step 'Backup logback' on(master, "mv #{logback_path} #{logback_backup}") step 'Modify logback configuration' do create_remote_file(master, logback_path, logback_config) on(master, "chmod +r #{logback_path}") end step 'Restart puppetserver' do bounce_service( master, service ) end step 'Validate that the puppetserver service is running' do result=on(master, "service #{service} status", :acceptable_exit_codes => [0,1]) assert_equal(0, result.exit_code, 'FAIL: The puppetserver service does not appear to be running') end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/010-puppetserver-cli/000077500000000000000000000000001470345337400274415ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/010-puppetserver-cli/subcommand/000077500000000000000000000000001470345337400315715ustar00rootroot00000000000000SERVER-297_common_behavior.rb000066400000000000000000000055611470345337400366220ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/010-puppetserver-cli/subcommandrequire 'json' test_name "Puppetserver subcommand consolidated ENV handling tests." proxy_env_vars = "HTTP_PROXY=foo http_proxy=foo HTTPS_PROXY=foo https_proxy=foo NO_PROXY=foo no_proxy=foo" step "ruby: Check that PATH, HOME, GEM_HOME JARS_REQUIRE and JARS_NO_REQUIRE are present" on(master, "puppetserver ruby -rjson -e 'puts JSON.pretty_generate(ENV.to_hash)'") do |result| env = JSON.parse(result.stdout) assert(env['PATH'], "PATH missing") assert(env['HOME'], "HOME missing") assert(env['GEM_HOME'], "GEM_HOME missing") assert(env['JARS_REQUIRE'], "JARS_REQUIRE missing") assert(env['JARS_NO_REQUIRE'], "JARS_NO_REQUIRE missing") end step "ruby: Check that proxy env-variables are present" on(master, "#{proxy_env_vars} puppetserver ruby -rjson -e 'puts JSON.pretty_generate(ENV.to_hash)'") do |result| env = JSON.parse(result.stdout) assert_equal(env['HTTP_PROXY'], "foo", "HTTP_PROXY is missing or has wrong value: '#{env['HTTP_PROXY']}'") assert_equal(env['http_proxy'], "foo", "http_proxy is missing or has wrong value: '#{env['http_proxy']}'") assert_equal(env['HTTPS_PROXY'], "foo", "HTTPS_PROXY is missing or has wrong value: '#{env['HTTPS_PROXY']}'") assert_equal(env['https_proxy'], "foo", "https_proxy is missing or has wrong value: '#{env['https_proxy']}'") assert_equal(env['NO_PROXY'], "foo", "NO_PROXY is missing or has wrong value: '#{env['NO_PROXY']}'") assert_equal(env['no_proxy'], "foo", "no_proxy is missing or has wrong value: '#{env['no_proxy']}'") end step "irb: Check that PATH, HOME, GEM_HOME JARS_REQUIRE and JARS_NO_REQUIRE are present" on(master, "echo 'puts JSON.pretty_generate(ENV.to_hash)' | puppetserver irb -f -rjson") do |result| assert_match(/\bPATH\b/, result.stdout, "PATH missing") assert_match(/\bHOME\b/, result.stdout, "HOME missing") assert_match(/\bGEM_HOME\b/, result.stdout, "GEM_HOME missing") assert_match(/\bJARS_REQUIRE\b/, result.stdout, "JARS_REQUIRE missing") assert_match(/\bJARS_NO_REQUIRE\b/, result.stdout, "JARS_NO_REQUIRE missing") end step "irb: Check that proxy env-variables are present" on(master, "echo 'puts JSON.pretty_generate(ENV.to_hash)' | #{proxy_env_vars} puppetserver irb -f -rjson") do |result| assert_match(/\bHTTP_PROXY\b\W\W\s\W\bfoo\b/, result.stdout, "HTTP_PROXY missing or has wrong value") assert_match(/\bhttp_proxy\b\W\W\s\W\bfoo\b/, result.stdout, "http_proxy missing or has wrong value") assert_match(/\bHTTPS_PROXY\b\W\W\s\W\bfoo\b/, result.stdout, "HTTPS_PROXY missing or has wrong value") assert_match(/\bhttps_proxy\b\W\W\s\W\bfoo\b/, result.stdout, "https_proxy missing or has wrong value") assert_match(/\bNO_PROXY\b\W\W\s\W\bfoo\b/, result.stdout, "NO_PROXY missing or has wrong value") assert_match(/\bno_proxy\b\W\W\s\W\bfoo\b/, result.stdout, "no_proxy missing or has wrong value") end foreground.rb000066400000000000000000000024511470345337400342130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/010-puppetserver-cli/subcommandtest_name "Puppetserver 'foreground' subcommand tests." cli = "puppetserver" service = options['puppetservice'] timout_length = "180s" foreground_cmd = "#{cli} foreground --debug" timeout_cmd = "timeout -s INT #{timout_length} #{foreground_cmd}" expected_messages = { / DEBUG .*Debug logging enabled/ => "Debug logging isn't enabled", /Initializing the JRuby service/ => "JRuby didn't initialize", /Starting web server/ => "Expected web server to start", /Puppet Server has successfully started and is now ready to handle requests/ => "puppetserver never finished starting", /Beginning shutdown sequence/ => "Test ended without puppetserver triggering shutdown" } # Start of test step "Stop puppetserver" on(master, puppet("resource service #{service} ensure=stopped")) step "Run #{cli} with foreground subcommand, wait for #{timout_length}" on(master, timeout_cmd, :acceptable_exit_codes => [124]) do |result| refute_match(/error:/i, result.stderr, "Unexpected error running puppetserver!") step "Check that #{cli} ran successfully and shutdown triggered" expected_messages.each do |message, explanation| assert_match(message, result.stdout, explanation) end end teardown do step "Teardown: Start puppetserver again" on(master, puppet("resource service #{service} ensure=running")) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/010-puppetserver-cli/subcommand/gem.rb000066400000000000000000000061221470345337400326670ustar00rootroot00000000000000require 'puppetserver/acceptance/gem_utils' skip_test if master['template'] =~ /fips/ test_name "Puppetserver 'gem' subcommand tests." cli = "puppetserver" # define gems to test gems = {'nokogiri' => '1.6.7', 'excon' => '0.45.4'} additional_gem_source = ENV['GEM_SOURCE'] # define command lines gem_install = "#{cli} gem install --minimal-deps --force --no-document" if additional_gem_source gem_install += " --clear-sources --source #{additional_gem_source}" end gem_uninstall = "#{cli} gem uninstall --silent" gem_list = "#{cli} gem list" gem_cleanup = "#{cli} gem cleanup" # teardown teardown do step "Teardown: Remove all installed gems." gems.keys.each do |gem_name| on(master, "#{gem_uninstall} #{gem_name}") end step "Teardown: Remove all gems not required to meet a dependency." on(master, "#{gem_cleanup}") end step "Clean up gems that are not required to meet a dependency." on(master, "#{gem_cleanup}") step "Get initial list of installed gems." initial_installed_gems = get_gem_list(master, "#{gem_list}") gems.each do |gem_name, gem_version| step "Install test gem." on(master, "#{gem_install} #{gem_name} -v #{gem_version}") step "Check that test gem is present." on(master, "#{gem_list}") do |result| assert(/^#{gem_name}/.match(result.stdout), "#{gem_name} was not found after installation.") end if gem_name == 'excon' step "SERVER-1601: Validate use of excon gem successful as puppet user" do if options[:type] == 'pe' runuser = 'pe-puppet' else runuser = 'puppet' end on(master, "su #{runuser} -s /bin/bash -c "\ "'/opt/puppetlabs/bin/puppetserver ruby "\ "-rexcon -e \"puts Excon::VERSION\"'") do |result| assert_equal(gems['excon'], result.stdout.strip, "Unexpected output for excon version") end end end step "Uninstall test gem." on(master, "#{gem_uninstall} #{gem_name}") step "Check that test gem is no longer present." on(master, "#{gem_list}") do |result| refute_match(/^#{gem_name}/, result.stdout, "#{gem_name} was found after uninstallation.") end end step "Clean up gems that are not required to meet a dependency." on(master, "#{gem_cleanup}") step "Verify that current list matchs initial list." final_installed_gems = get_gem_list(master, "#{gem_list}") initial_installed_gems.each do |gem_info| assert_send([final_installed_gems, :include?, gem_info]) end step "Verify that gem env operates" on(master, "#{cli} gem env", :acceptable_exit_codes => [0]) step "Verify that Java cli args passed through to gem command" on(master, "JAVA_ARGS_CLI=-Djruby.cli.version=true #{cli} gem help") do |result| assert_match(/jruby \d\.\d\.\d.*$/, result.stdout, 'jruby version not included in gem command output') end step "(SERVER-1759) Verify that installing a non-existent gem produces a non-zero exit return value" gem_name = 'if-this-gem-exists-then-someone-has-a-cruel-sense-of-humor' on(master, "#{cli} gem install #{gem_name}", :acceptable_exit_codes => [2]) do |result| assert_match(/Could not find a valid gem/, result.stderr) end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/010-puppetserver-cli/subcommand/irb.rb000066400000000000000000000030361470345337400326740ustar00rootroot00000000000000test_name "Puppetserver 'irb' subcommand tests." # -------------------------------------------------------------------------- # This behavior needs to be baked into Beaker but is not yet. SERVER-79 tracks # the need to fix this once Beaker has been modified to make the paths to these # commands available. # cli = "puppetserver" # -------------------------------------------------------------------------- step "Check that GEM_HOME is managed" cmd = "echo 'puts ENV.to_hash.to_yaml' | GEM_HOME=UHOH #{cli} irb -ryaml -f" on(master, cmd) do |result| assert_match(/GEM_HOME/, result.stdout) refute_match(/UHOH/, result.stdout) end step "Check that FOO_DEBUG is filtered" cmd = "echo 'puts ENV[%{FOO_DEBUG}] || %{OK}' | FOO_DEBUG=BAD #{cli} irb -f" on(master, cmd) do |result| assert_match(/^OK$/, result.stdout) refute_match(/^BAD$/, result.stdout, "FOO_DEBUG is not being filtered out") end step "Check that puppet is loadable" cmd = "echo 'puts %{GOOD: } + Puppet.version' | #{cli} irb -rpuppet -f" on(master, cmd) do |result| assert_match(/GOOD:/, result.stdout) refute_match(/error/i, result.stdout) end step "Verify that Java cli args passed through to irb command" on(master, "echo '' | JAVA_ARGS_CLI=-Djruby.cli.version=true #{cli} irb -f") do |result| assert_match(/jruby \d\.\d\.\d.*$/, result.stdout, 'jruby version not included in irb command output') end step "(SERVER-1759) Verify that the jruby irb exit code is used for the java return code" on(master, "echo 'exit!(4)' | #{cli} irb", :acceptable_exit_codes => [4]) puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/010-puppetserver-cli/subcommand/ruby.rb000066400000000000000000000030021470345337400330720ustar00rootroot00000000000000test_name "Puppetserver 'ruby' subcommand tests." # -------------------------------------------------------------------------- # This behavior needs to be baked into Beaker but is not yet. SERVER-79 tracks # the need to fix this once Beaker has been modified to make the paths to these # commands available. # cli = "puppetserver" # -------------------------------------------------------------------------- step "Check that GEM_HOME is managed" cmd = "GEM_HOME=UHOH #{cli} ruby -ryaml -e 'puts ENV.to_hash.to_yaml'" on(master, cmd) do |result| assert_match(/GEM_HOME/, result.stdout) refute_match(/UHOH/, result.stdout) end step "Check that FOO_DEBUG is filtered out" on(master, "FOO_DEBUG=BAD #{cli} ruby -e 'puts ENV[%{FOO_DEBUG}] || %{OK}'") do |result| assert_match(/^OK$/, result.stdout) refute_match(/BAD/, result.stdout, "FOO_DEBUG is not being filtered out") end step "Check that puppet is loadable" cmd = "#{cli} ruby -rpuppet -e 'puts %{GOOD: } + Puppet.version'" on(master, cmd) do |result| assert_match(/GOOD:/, result.stdout) refute_match(/error/i, result.stdout) end step "Verify that Java cli args passed through to ruby command" on(master, "JAVA_ARGS_CLI=-Djruby.cli.version=true #{cli} ruby -e ''") do |result| assert_match(/jruby \d\.\d\.\d.*$/, result.stdout, 'jruby version not included in ruby command output') end step "(SERVER-1759) Verify that the jruby irb exit code is used for the java return code" on(master, "echo 'exit!(8)' | #{cli} ruby", :acceptable_exit_codes => [8]) puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/authorization/000077500000000000000000000000001470345337400265325ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/authorization/default_rules.rb000066400000000000000000000157521470345337400317270ustar00rootroot00000000000000## These test the new trapperkeeper-authorization auth.conf default rules ## as they're specified in FOSS puppet server. ## The tests are written to assert the curl request was "not forbidden" rather ## than expecting something meaningful from the endpoint. We're just trying to ## test that authorization is allowing & rejecting requests as expected. ## ## The testing pattern is to call one of the two curl functions with a path, ## and then one of the two assertion functions to validate allowed/denied. ## The assertion functions look for regexes and status codes in the stdout ## of the previous curl invocation. test_name 'Default auth.conf rules' step 'Turn on new auth support' do modify_tk_config(master, options['puppetserver-config'], {'jruby-puppet' => {'use-legacy-auth-conf' => false}}) end def curl_authenticated(path, &block) curl = 'curl ' curl += '--cert $(puppet config print hostcert) ' curl += '--key $(puppet config print hostprivkey) ' curl += '--cacert $(puppet config print localcacert) ' curl += "--write-out '\\nSTATUSCODE=%{http_code}\\n' " curl += "https://#{master}:8140#{path}" result = on(master, curl) block.call(result.stdout) end def curl_unauthenticated(path) curl = 'curl --insecure ' curl += "--write-out '\\nSTATUSCODE=%{http_code}\\n' " curl += "https://#{master}:8140#{path}" on(master, curl) end def assert_allowed(stdout, expected_statuscode = 200) refute_match(/Forbidden request/, stdout) assert_match(/STATUSCODE=#{expected_statuscode}/, stdout) end def assert_denied(stdout, expected_stdout) assert_match(/Forbidden request/, stdout) assert_match(expected_stdout, stdout) assert_match(/STATUSCODE=403/, stdout) end def report_query(node) curl = "/puppet/v3/report/#{node}?environment=production " curl += '-X PUT -H "Content-Type: application/json" ' curl += '--data "{\"host\":\"' + node curl += '\",\"metrics\":{},\"logs\":[],\"resource_statuses\":{}}"' end with_puppet_running_on(master, {}) do masterfqdn = on(master, '/opt/puppetlabs/bin/facter fqdn').stdout.chomp step 'environments endpoint' do curl_authenticated('/puppet/v3/environments') do |stdout| assert_allowed(stdout) end curl_unauthenticated('/puppet/v3/environments') do |stdout| assert_denied(stdout, /\/puppet\/v3\/environments \(method :get\)/) end end step 'catalog endpoint' do curl_authenticated("/puppet/v3/catalog/#{masterfqdn}?environment=production") do |stdout| assert_allowed(stdout) end curl_authenticated('/puppet/v3/catalog/notme?environment=production') do |stdout| assert_denied(stdout, /\/puppet\/v3\/catalog\/notme \(method :get\)/) end curl_unauthenticated("/puppet/v3/catalog/#{masterfqdn}?environment=production") do |stdout| assert_denied(stdout, /\/puppet\/v3\/catalog\/#{masterfqdn} \(method :get\)/) end end step 'node endpoint' do curl_authenticated("/puppet/v3/node/#{masterfqdn}?environment=production") do |stdout| assert_allowed(stdout) end curl_authenticated('/puppet/v3/node/notme?environment=production') do |stdout| assert_denied(stdout, /\/puppet\/v3\/node\/notme \(method :get\)/) end curl_unauthenticated("/puppet/v3/node/#{masterfqdn}?environment=production") do |stdout| assert_denied(stdout, /\/puppet\/v3\/node\/#{masterfqdn} \(method :get\)/) end end step 'report endpoint' do curl_authenticated(report_query(masterfqdn)) do |stdout| assert_allowed(stdout) end # In PE, the master (specifically the orchestrator) # is allowed to make report submissions on behalf of # other nodes curl_authenticated(report_query('notme')) do |stdout| if master.is_pe? assert_allowed(stdout) else assert_denied(stdout, /\/puppet\/v3\/report\/notme \(method :put\)/) end end curl_unauthenticated(report_query(masterfqdn)) do |stdout| assert_denied(stdout, /\/puppet\/v3\/report\/#{masterfqdn} \(method :put\)/) end end step 'file_metadata endpoint' do # We'd actually need to install a module in order to get back a 200, # but we know that a 404 means we got past authorization curl_authenticated('/puppet/v3/file_metadata/modules/foo?environment=production') do |stdout| assert_allowed(stdout, 404) end curl_unauthenticated('/puppet/v3/file_metadata/modules/foo?environment=production') do |stdout| assert_denied(stdout, /\/puppet\/v3\/file_metadata\/modules\/foo \(method :get\)/) end end step 'file_content endpoint' do # We'd actually need to install a module in order to get back a 200, # but we know that a 404 means we got past authorization curl_authenticated('/puppet/v3/file_content/modules/foo?environment=production') do |stdout| assert_allowed(stdout, 404) end curl_unauthenticated('/puppet/v3/file_content/modules/foo?environment=production') do |stdout| assert_denied(stdout, /\/puppet\/v3\/file_content\/modules\/foo \(method :get\)/) end end step 'file_bucket_file endpoint' do # We'd actually need to store a file in the filebucket in order to get # back a 200, but we know that a 500 means we got past authorization curl_authenticated('/puppet/v3/file_bucket_file/md5/123?environment=production') do |stdout| assert_allowed(stdout, 500) end curl_unauthenticated('/puppet/v3/file_bucket_file/md5/123?environment=production') do |stdout| assert_denied(stdout, /\/puppet\/v3\/file_bucket_file\/md5\/123 \(method :get\)/) end end step 'status service endpoint' do curl_unauthenticated('/status/v1/services') do |stdout| assert_allowed(stdout) end end step 'static file content endpoint' do # We'd actually need to perform a commit and use its code-id in order to # get back a 200, but we know that a 400 means we got past authorization curl_authenticated('/puppet/v3/static_file_content/foo/bar?environment=production') do |stdout| assert_allowed(stdout, 400) end curl_unauthenticated('/puppet/v3/static_file_content/foo/bar?environment=production') do |stdout| assert_denied(stdout, /\/puppet\/v3\/static_file_content\/foo\/bar \(method :get\)/) end end step 'certificate_revocation_list endpoint' do curl_authenticated('/puppet-ca/v1/certificate_revocation_list/ca?environment=production') do |stdout| assert_allowed(stdout) end curl_unauthenticated('/puppet-ca/v1/certificate_revocation_list/ca?environment=production') do |stdout| assert_allowed(stdout) end end step 'certificate endpoint' do curl_unauthenticated('/puppet-ca/v1/certificate/ca?environment=production') do |stdout| assert_allowed(stdout) end end step 'certificate_request endpoint' do # We'd actually need to store a CSR file on the server in order to get # back a 200, but we know that a 404 means we got past authorization curl_unauthenticated('/puppet-ca/v1/certificate_request/foo?environment=production') do |stdout| assert_allowed(stdout, 404) end end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/authorization/fixtures/000077500000000000000000000000001470345337400304035ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/authorization/fixtures/csr_attributes.yaml000066400000000000000000000003601470345337400343230ustar00rootroot00000000000000--- custom_attributes: 1.2.840.113549.1.9.7: 342thbjkt82094y0uthhor289jnqthpc2290 extension_requests: pp_uuid: ED803750-E3C7-44F5-BB08-41A04433FE2E pp_image_name: my_ami_image pp_preshared_key: 342thbjkt82094y0uthhor289jnqthpc2290 extensions_test_auth.conf000066400000000000000000000067761470345337400354720ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/authorization/fixturesauthorization: { version: 1 rules: [ { # Allow only nodes with test extensions to retrieve any catalog match-request: { path: "/puppet/v3/catalog" type: path method: [get, post] } allow: [ {extensions:{pp_uuid: ED803750-E3C7-44F5-BB08-41A04433FE2E}} ] sort-order: 123 name: "extensions test puppetlabs catalog" }, { # 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" }, { match-request: { path: "/puppet/v3/environments" type: path method: get } allow: "*" sort-order: 500 name: "puppetlabs environments" }, { # Allow nodes to access all file services; this is necessary for # pluginsync, file serving from modules, and file serving from # custom mount points (see fileserver.conf). Note that the `/file` # prefix matches requests to file_metadata, file_content, and # file_bucket_file paths. match-request: { path: "/puppet/v3/file" type: path } allow: "*" sort-order: 500 name: "puppetlabs file" }, { # 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" }, { match-request: { path: "/puppet/v3/static_file_content" type: path method: get } allow: "*" sort-order: 500 name: "puppetlabs static file content" }, { # 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" } ] } puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/authorization/x509_auth.rb000066400000000000000000000110301470345337400306000ustar00rootroot00000000000000test_name "(SERVER-1268)/(TK-293) TK-AUTH uses certificate extensions for authentication" do confine :except, :platform => 'windows' server = master.puppet['certname'] ssldir = master.puppet['ssldir'] confdir = master.puppet['confdir'] teardown do # restore the original tk auth.conf file on master, 'cp /etc/puppetlabs/puppetserver/conf.d/auth.bak /etc/puppetlabs/puppetserver/conf.d/auth.conf' # re-enable puppetdb facts terminus on master, puppet('config set route_file /etc/puppetlabs/puppet/routes.yaml') end step "Backup the tk auth.conf file" do on master, 'cp /etc/puppetlabs/puppetserver/conf.d/auth.conf /etc/puppetlabs/puppetserver/conf.d/auth.bak' end # Do we have a functioning cert? with_puppet_running_on master, {} do step "Confirm agent can connect with existing cert" do agents.each do |a| if (not_controller(a)) rc = on(a, puppet("agent --test --detailed-exitcodes"), {:acceptable_exit_codes => [0,2]}) end end end end step "Disconnect the facts terminus from PuppetDB while we're munging certs" do on master, puppet('config set route_file /tmp/nonexistant.yaml') end # Not anymore we don't step "Revoke and destroy the existing cert on the server" do agents.each do |a| if (not_controller(a)) rc = on(master, "puppetserver ca clean --certname=#{a.hostname}", {:acceptable_exit_codes => [0,2]}) end end end with_puppet_running_on master, {} do # After a server HUP, the agent cert should be rejected step "Confirm agent can't connect with existing cert" do agents.each do |a| if (not_controller(a)) rc = on(a, puppet("agent --test --detailed-exitcodes"), {:acceptable_exit_codes => [1]}) end end end step "Remove the old certs on the agents so they'll make new ones" do agents.each do |a| if (not_controller(a)) rc = on(a, "find #{confdir} -name #{a.hostname}.pem -delete", {:acceptable_exit_codes => [0,1]}) end end end # Lay down an attributes file for puppet to read when creating # a new cert # TODO: Make this a here doc with extensions that exist as vars so that they # can be passed into our tk auth.conf rule generator. step "Copy the CSR attributes file into place" do agents.each do |a| if (not_controller(a)) rc = scp_to(a, 'acceptance/suites/tests/authorization/fixtures/csr_attributes.yaml', "#{confdir}", {:acceptable_exit_codes => [0]}) end end end step "Generate a new cert with a cert extension" do agents.each do |a| if (not_controller(a)) rc = on(a, puppet("agent --test --detailed-exitcodes"), {:acceptable_exit_codes => [1]}) end end end step "Sign the certs" do rc = on(master, 'puppetserver ca sign --all', {:accept_all_exit_codes => true}) end end # tk_auth file that allows catalogs based on extensions rather than node names. # This will create a weakness in that if the DEFAULT tk_auth.conf file is # modified in the future, # we may need to modify our test tk_auth.conf file. # FIXME / TODO: create helper methods so that we can modify the tk auth.conf # file in place (and therefore test more use cases.) step "Lay down a test tk-auth.conf file" do scp_to( master, 'acceptance/suites/tests/authorization/fixtures/extensions_test_auth.conf', '/etc/puppetlabs/puppetserver/conf.d/auth.conf', :acceptable_exit_codes => 0 ) end with_puppet_running_on master, {} do # Confirm agents can connect with new cert step "Confirm agent can connect with the new cert" do agents.each do |a| if (not_controller(a)) rc = on(a, puppet("agent --test --detailed-exitcodes"), {:acceptable_exit_codes => [0,2]}) end step "Try to query locked down catalog endpoint" do cert = get_cert(a) key = get_key(a) rc = https_request("https://#{server}:8140/puppet/v3/catalog/#{a.hostname}?environment=production", :get, cert, key) if not_controller(a) if rc.code != '200' fail_test "Unexpected HTTP status code: #{rc.code}. Expected 200." end else if rc.code != '403' fail_test "Unexpected HTTP status code: #{rc.code}. Expected 403." end end end end end end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/catalog/000077500000000000000000000000001470345337400252445ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/catalog/v4_catalog.rb000066400000000000000000000203771470345337400276250ustar00rootroot00000000000000require 'json' skip_test if master.is_pe? # Here we test our v4 compile endpoint by: # - use "compile_service" to compile a catalog for "compile_subject" # - compile_subject can successfully apply the compiled catalog # - and if PDB is present we: # - facts may be found from PDB (by compiling and applying a second catalog) # - the catalog is successfully saved (by comparing catalog_uuids) test_name "v4 catalog endpoint workflows" do no_change = { acceptable_exit_codes: 0 } allow_failure = { acceptable_exit_codes: [0, 1] } allow_change = { acceptable_exit_codes: [0, 2] } auth_path = '/etc/puppetlabs/puppetserver/conf.d/auth.conf' site_path = '/etc/puppetlabs/code/environments/production/manifests/site.pp' compile_subject = 'compile-node-one' compile_service = 'compile-node-two' catalog_path = "/home/#{compile_subject}/catalog.json" request_path = "/home/#{compile_service}/request.json" v4_catalog = "https://#{master}:8140/puppet/v4/catalog" pdb_catalog = "https://#{master}:8081/pdb/query/v4/catalogs/#{compile_subject}" path_fact_value = "/home/#{compile_subject}/test-file" content_fact_value = 'Fooberry Blueberry' old_config_string = on(master, "cat #{auth_path}").stdout old_config = read_tk_config_string(old_config_string) old_puppet_conf = puppet_conf_for(master, {}) testdir = master.tmpdir('v4catalog') pdb = on(master, '[ -d /etc/puppetlabs/puppetdb ]', allow_failure). exit_code == 0 def conf_for(non_root_agent) < { "values" => { "test_fact_path" => path_fact_value } }, "trusted_facts" => { "values" => { "extensions" => { "test_fact_content" => content_fact_value } } } } base_request = { "certname" => compile_subject, "environment" => "production", "persistence" => { "facts" => false, "catalog" => false } } persist = { "persistence" => { "facts" => true, "catalog" => true } } def as(user, command) %Q[su - #{user} -c '#{command}; exit \$?'] end def curl(url:, request:false) cmd = %Q[curl -k \ --cert $(puppet config print --section agent hostcert) \ --cacert $(puppet config print --section agent localcacert) \ --key $(puppet config print --section agent hostprivkey) \ --tlsv1 \ --url #{url}] if request cmd << %Q[ -d@#{request} \ -H "Content-Type: application/json" ] end cmd end teardown do on(master, "puppet resource user #{compile_subject} ensure=absent managehome=true") on(master, "puppet resource user #{compile_service} ensure=absent managehome=true") on(master, "puppet resource group compile-nodes ensure=absent") on(master, "rm -f #{site_path}") modify_tk_config(master, auth_path, old_config, replace=true) on(master, 'echo "" > /etc/puppetlabs/puppet/puppet.conf') lay_down_new_puppet_conf(master, old_puppet_conf, testdir) reload_server end step 'allow access via tk auth' do config = read_tk_config_string(old_config_string) rules = config['authorization']['rules'] i = rules.index {|r| r['name'] =~ /.*v4.*catalog.*services.*/ } new_rule = { 'match-request' => { 'path' => '^/puppet/v4/catalog/?$', 'type' => 'regex', 'method' => ['get', 'post'] }, 'allow' => "*", 'sort-order' => 10, 'name' => 'v4 catalog rule for testing' } if i rules[i] = new_rule else rules.unshift(new_rule) end config['authorization']['rules'] = rules modify_tk_config(master, auth_path, config, replace=true) end step 'allow autosigning, maybe enable storeconfigs' do new_puppet_conf = puppet_conf_for(master, {}) new_puppet_conf['master']['autosign'] = true # Despite PDB being enabled this setting may not be set, which is # required for saving catalogs (facts are managed by the routes.yaml # file and reports are a different setting. if pdb new_puppet_conf['master']['storeconfigs'] = true end lay_down_new_puppet_conf(master, new_puppet_conf, testdir) reload_server end step 'create test users' do user_attrs = 'ensure=present managehome=true shell=/bin/bash gid=compile-nodes' on(master, 'puppet resource group compile-nodes ensure=present') [compile_subject, compile_service].each do |user| on(master, "puppet resource user #{user} #{user_attrs}") on(master, "mkdir -p #{userdir_for(user)}/etc/puppet") create_remote_file(master, userdir_for(user) + '/etc/puppet/puppet.conf', conf_for(user)) on(master, "chown -R #{user}: #{userdir_for(user)}") on(master, "su -l #{user} -c '/opt/puppetlabs/bin/puppet agent -t'", allow_change) on(master, "su -l #{user} -c '/opt/puppetlabs/bin/puppet agent -t'", allow_change) end end step 'create site.pp' do create_remote_file(master, site_path, < present, content => "$foo_content", } } SITEPP on(master, "chmod 644 #{site_path}") end step 'send initial request to v4 catalog endpoint' do first_request = base_request.merge(facts) first_request = first_request.merge!(persist) if pdb create_remote_file(master, request_path, JSON.dump(first_request)) on(master, "chown #{compile_service}: #{request_path}") reply = on(master, as(compile_service, curl(request: request_path, url: v4_catalog))).stdout catalog = JSON.parse(reply)['catalog'] create_remote_file(master, catalog_path, JSON.dump(catalog)) on(master, "chown #{compile_subject}: #{catalog_path}") end step 'apply catalog from endpoint' do on(master, as(compile_subject, "/opt/puppetlabs/bin/puppet apply --detailed-exitcodes --catalog #{catalog_path}"), allow_change) content = on(master, "cat #{path_fact_value}").stdout.strip assert_equal(content, content_fact_value) end if pdb step 'test that facts are filled in by pdb fact storage' second_request = base_request.merge({'persistence' => { 'catalog' => true, 'facts' => false }}) create_remote_file(master, request_path, JSON.dump(second_request)) on(master, "chown #{compile_service}: #{request_path}") reply = on(master, as(compile_service, curl(request: request_path, url: v4_catalog))).stdout catalog = JSON.parse(reply)['catalog'] catalog_uuid = catalog['catalog_uuid'] create_remote_file(master, catalog_path, JSON.dump(catalog)) on(master, "chown #{compile_subject}: #{catalog_path}") on(master, as(compile_subject, "/opt/puppetlabs/bin/puppet apply --detailed-exitcodes --catalog #{catalog_path}"), no_change) content = on(master, "cat #{path_fact_value}").stdout.strip assert_equal(content, content_fact_value) step 'test that catalogs are saved to PDB' do stored_catalog = on(master, curl(url: pdb_catalog)).stdout stored_catalog_uuid = JSON.parse(stored_catalog)['catalog_uuid'] assert_equal(catalog_uuid, stored_catalog_uuid) end else logger.warn 'Could not find PDB, skipping PBD integration' end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/000077500000000000000000000000001470345337400302245ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/000077500000000000000000000000001470345337400320755ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca/000077500000000000000000000000001470345337400335545ustar00rootroot00000000000000ca-agent-ca.crl000066400000000000000000000012661470345337400362440ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca-----BEGIN X509 CRL----- MIIB2TCBwjANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRlcm1lZGlhdGUg Q0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLm9yZzEZ MBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2VydmVyIE9wZXJh dGlvbnMXDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFowFDASAgECFw0yMzA0 MTIyMjQxNThaMA0GCSqGSIb3DQEBCwUAA4IBAQCSrVWjsTA8YeO27GH/RIb/JJ+8 jxAdKDlm1Fu96WkJriAmOHp08cByiNmVsyFvKClCeGHzXfFM5sUdWlfaCftK4hXd Mva9ErcDgYILuJJoCAqWUj4/KmA6kJbxpeBx/kh+FUfe+ptTu5aRrECITEozf83p 0QfKGdE3i/Hts9kC8bWR/rcYokUhkjlCZW+WvMAH+a5FjvkessfG1YrVESYSrp27 sqX6fdw9vUQiSRZnzP6cfIqEzkJXBqaMXaHrzCjU2GjOCGakjQVSmIs4jgHRLr8h FFTBEnNCiL0THWGjR422M5IA+enyZi8OOn7f2c3tvptitAF+4kfl8LTiBQfH -----END X509 CRL----- ca-agent-ca.crt000066400000000000000000000026131470345337400362510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca-----BEGIN CERTIFICATE----- MIID6jCCAtKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBJMRAwDgYDVQQDDAdSb290 IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBs ZSBPcmcsIExMQzAeFw0yMzA0MTIyMjQxNTdaFw00MzA0MDcyMjQxNTdaMH0xIzAh BgNVBAMMGkludGVybWVkaWF0ZSBDQSAoYWdlbnQtY2EpMR8wHQYJKoZIhvcNAQkB FhB0ZXN0QGV4YW1wbGUub3JnMRkwFwYDVQQKDBBFeGFtcGxlIE9yZywgTExDMRow GAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAJ1EAzT0LLWHkeo8meKuMjMR2RI53lHwkSWNohBOPVA3lY+5UGei lyrkIb9H22ZR8DnNz7JjkJkC6Uu55PwFh2d2Q60wZLqlX21jRvmsCzfdGt/brD6Q q43mAJp7MyD3+31lmv2wmKvMPWoq6u+tjjDbtEey7HAiJxQ/KCGPqcUv5RFmqKz2 pfteWFxqHQUmn4JABZpte7Fl4/dQyw/6r7ctEnKqVuF2lQzCS0awy3oYQr6Qwwbs HNTApjmW2EXTuWYTYQ/ftQeGN5QdQm+9fiKi45Z/HsY1z7vyUY5TjjSLITV0a420 v2WhW8ckMWrllwaCEzmfNcjx9W5FQm4w8+MCAwEAAaOBqDCBpTCBhAYDVR0jBH0w e4AU9ZCGS16tJfUQP94+xtSfQj+Hqq+hTaRLMEkxEDAOBgNVBAMMB1Jvb3QgQ0Ex GjAYBgNVBAsMEVNlcnZlciBPcGVyYXRpb25zMRkwFwYDVQQKDBBFeGFtcGxlIE9y ZywgTExDghQvFOXf1u6BVLQnDLhlalXcghZONzAPBgNVHRMBAf8EBTADAQH/MAsG A1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEALw/RGiXdEZQ+rj43BqeOlAas mUpHnhmc9XPVNtkgRTf9DYc/NxRFBLNC8eBnThcZGTlN7c025xYkjQsIvs6gKD+y SKFLv0+eHuCywrDgAZCAcFC+ekXu5b7BfKMfjkWJHELYEIomgVHY4mj6blZ5lmWk Mmr8qYzDAWYD6Rits21YMKyMWcAcoTed9GQFwZOhLJHAG4lvoRd6qXAK+U7dIoQh vf5CGFP2YO71un22IGRy5QJhoDyxV3yHbbiv7zS+NPn1bOQOfKRGu58PxfsyO3BT aWGyMzLhxPB6ufAQo7fWX1jOqPxJ1aMS9+aAba7QW/QrOX+LAlAulS034izUFA== -----END CERTIFICATE----- ca-agent-ca.key000066400000000000000000000032501470345337400362470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdRAM09Cy1h5Hq PJnirjIzEdkSOd5R8JEljaIQTj1QN5WPuVBnopcq5CG/R9tmUfA5zc+yY5CZAulL ueT8BYdndkOtMGS6pV9tY0b5rAs33Rrf26w+kKuN5gCaezMg9/t9ZZr9sJirzD1q KurvrY4w27RHsuxwIicUPyghj6nFL+URZqis9qX7Xlhcah0FJp+CQAWabXuxZeP3 UMsP+q+3LRJyqlbhdpUMwktGsMt6GEK+kMMG7BzUwKY5lthF07lmE2EP37UHhjeU HUJvvX4iouOWfx7GNc+78lGOU440iyE1dGuNtL9loVvHJDFq5ZcGghM5nzXI8fVu RUJuMPPjAgMBAAECggEAXeXv7DwmPbTWYH8Seo/7lRaA/yriHRZ/82Yfb5Dndu/Z Mtk4ssgXbhqMM8NZsjwWLM0/x4k/GrzsQrSZjghXEmVAfzW3zuFSmuN9yzD3+cDg fOySaUDDzZOYpKQOoQ6vb+2snvBEF794o91ALR75GR71AyJHnaQmpSYYdgFrIjpI 3At32/zOpy/grTpq/2bsHmht1KsfrapXKiz4/cz9c/qUmgjxEj67A59tfvcpB2Ps s2jGHsTB3X2x0FKurKJThsgf+F1b96JC/vamzJsS9P5BdXV4aL5MxcGbzrNVsWE0 ca1W3Txltj6mOcOyliwYU2aJvynW7a49/aIdiJjd4QKBgQDOlRWgseev3jNfAhk5 mDV+rCU4yjDeKNrfc1UAU9BsSzbv1LPCUgIY9BeB+9sH9cZqoD7atX91yc9COmYr BXa8XBTmwL/l1lQgTAyRHFjSzjStwrvLFS4CS7oyh0VVfZ07skprU3/R/kEqQ0Ji W5ULnLEnEm91MUug2JI9VFrH+wKBgQDC4tGt8v51IEdNlYrxd2xV/YZkoHITpI6Y 7kF1sXZG0T/CJ0af5Z5LfBtsmThyn9SSXmy/P5+m77rYcxcXAWt41pLq4rxj9RwX dOiM+0unhZF7vXKb5BGefZAhiavqGQFoJKR0vevKmDfZvbQQE/fhUSVgQSzcKi0n +u8fdjK3OQKBgGDiapJC3XYNr+oPAeWRDQWrlolbyi9m2b+SR3sv07/2Rn2UM/oe m/03/Q5pIABLtBKttMy98lk7nIhi+yeSGG2ege721wjjy/CZugsUUFQNgYc8nPZR qJJLEbhA2LOPhf5JT72mG3xQ0h8QDEI00WHwyuSYMM21oNJ+v5cjyK+hAoGBAJ/x /frQsow4SKzhLd6Nj+lnIJSXpeh/JtVWvXy1gAgRFk3nZCw5DNiQ7AUOH2jbyl+y hXfU5NfiaqvYkTu9W5IaMQv7uHglI8AQoAeM+wNrOQKgcl6FKPy1usP7tI91pFTv tdVmRg3JLhVTf2Our8NJkO5Vr1ametcUOIrOvELpAoGBAK6UhYxGdO79MC+NUxdA iArCtuajvpGCnFYVbgkgRGaw2NV+GzcTbDXded9D+8K78k2Cmfr6ENv1qpOl7rJw 5Z8n4XfrlHjzoTA02yR77Ap2FLeqDrNZb29+JsKH5qCJlJdqnbYyN/LudbQud0BD ey0bJbXH61JPvr6r6bIuUsQ1 -----END PRIVATE KEY----- certs/000077500000000000000000000000001470345337400346155ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca01.pem000066400000000000000000000024721470345337400355450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca/certs-----BEGIN CERTIFICATE----- MIIDsDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjAd MRswGQYDVQQDDBJhZ2VudDEuZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQDa8oNyLxOwgoJa0thHlB3CPLAm2mcrStPD0RHmHxlRihsa 3BrGdvOekD79eBi+7RmIsnRpUL0F+7oCS7skQ4z+TkS3hgoXyOgTgK8UWY3osNny B/Y/61KIzCIlZXXey2sQYx6jsaxxsyfrs/ErdFFYbEE1MLvRJadSw3MTcML8WhCH S0jB2DVp9wmKDGWtWHBRFpvkxwGt2u4Zlux9iVOz4XPNxxh19W+vFBms9DQDmJmN c3X0ZefKlrilKdXMg2BkFEIawMRVJgfNvb5uoAjik6KQdFG3Vnt9VXMwDmO5DmXT wElOKAwqouGeF9qp3t6DPLOylyIYjeC0uPbCy6ETAgMBAAGjgZowgZcwWwYDVR0j BFQwUqFNpEswSTEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9w ZXJhdGlvbnMxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/ BAIwADALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC MA0GCSqGSIb3DQEBCwUAA4IBAQAmSiSyp5nlk1Cwn3Rw23bqCIQ/WlZzJE/Uh1+Z TuiwVbZknaJ0gsZELmkFGsvX56OS0nTPUyl6m3Ct5vCAX33nhOH94njX5yFte1sO zT3AkJZqz4elf5Li+aGvgLplN04XH5snnw23c2cwhbTu3GwZok07MpUp09jonNfK RfV295tTfC/L7+XXz9uOPwI/oCNiZNTbpl+pshXaG9t2vtDiIgQUWF4jXzWpUu9I wFo48IM1OVQrujb3LliD4fLZItfJK/xJKIKixTxrPy0Xu5zdz7DyTBJnvZYiUVtU 8CKZR+5wtc8aKdDxfNaY7nORiZEyd/uprVb6okCpZnVxxXum -----END CERTIFICATE----- 02.pem000066400000000000000000000024721470345337400355460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca/certs-----BEGIN CERTIFICATE----- MIIDsDCCApigAwIBAgIBAjANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjAd MRswGQYDVQQDDBJhZ2VudDIuZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQDs8wg1+xrBWHcp9d4b3dbIqHQiuYtKbXlGU52lKoU3vArM b2lu39EWMXrxg9Dn3joI3X8nUynGlB1mHvog6/RXggw2T5WtPIviAMIR3niQWS3g YrgpT90GVeIPIiuVh76IUFnz+a9wfxZ3rsXRU74kXOzWXVZr2pSH1HjSpWmR6Hgj HUPi7/CRPL/V+/nvyY66cvxqgtOchGYhZO3+0zeGnXzVlXwdleCQnJ72EAOIyvQh rJhKiHvYw9/ZTD3VMHntBUu/QFB6a9ILKxggB3iOQXE2HwPBqO+cJfoi4qTpywE7 MOdI0q6MK9pr6r8TAGAlEPYoImbUFHIehJmPvSZDAgMBAAGjgZowgZcwWwYDVR0j BFQwUqFNpEswSTEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9w ZXJhdGlvbnMxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/ BAIwADALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC MA0GCSqGSIb3DQEBCwUAA4IBAQBPtNXbJI3C0/8gHvB2g6tfSGBHVvOH1lRpQ8FY EYW4m8EubV0cFdDpd02/gG4hOiCYFOOcMFENGOTRGSIMDWUED7doNttxHFWxVOEX 6M98cTlTpWW3PThCru5Oa4CGFcGFbo8Khb4vvZv5vIwf8ShUe2sl0I3REZXUx5ad fQc4sXiiPdf/P1D9ppulz/UchMfg9sg0ZRjQmVmCBZvA4/P+rBS+T+nJQ0bfpTmV EOVG149Lt+61kotJmxv5/J2UYRneWBmRE7P8d8DTqhOHQI5cHICgVq5Jw9m7nGlS LB7F4lKYXXU/9Z5JVKtM7/m4+MfCHlQyocd0cL9laKseE2Ek -----END CERTIFICATE----- 03.pem000066400000000000000000000024721470345337400355470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca/certs-----BEGIN CERTIFICATE----- MIIDsDCCApigAwIBAgIBAzANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjAd MRswGQYDVQQDDBJhZ2VudDMuZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQDImAML5qGenaZ1oXlNyDTnPg/0bq5ft2jTZjPTUijBiuYI ZqANvqjf+bicC+9LdQwpRoIm4hS+cnvaEdXSV73cWjgFzAFJTBYaRXLst8/r0QlU BNkHgDpgCFVwR+YIEmHeesprzId/uDE1tf13IRI1NpDgU+jlBH3wOiUDr8QbPWPG IUV4bbEzLCGoP2fO5Le5p8+NdRI7XCHo7ac8eRL90pyBFBKzdc93cYMI7PvimuX7 MiVObjil3FF+tsdkAAAJezLKlW2CKjRUdHCr5/2WIRpjiIs4k/hCDToBm+8ye9m4 3NWn68XMIOjCiXl8wjdbTA3z2A0iRE9hGh+pYhQzAgMBAAGjgZowgZcwWwYDVR0j BFQwUqFNpEswSTEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9w ZXJhdGlvbnMxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/ BAIwADALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC MA0GCSqGSIb3DQEBCwUAA4IBAQAJvTvSc/J7QUZXtwIDoRSpEw1BBb+AKsa4D4ui qQXxiiRAe+HkSVvDnYU6gDTiEwtjccC/78KYti6QKWsYXhdW298ALdP9guAL78Lt A1olS9hNLXMiqWWEGPu0UAmNuTpdiwYbTL6vb7tcgBsnXONS1N8i7N1SRNyGRURL E2h5n8LGupXtum71XKMpNDT7XKKh75O8jsfGwkl2g4DQKmU5+9X2RXX+btooIsBi xgsOcq6Tb1qHdZRvqH75iypj8osiy+4cflgvdjuElHBvIlFRlyJyJPhAPk1xWNRq 5+tDXG9cxNfWCGp2rCtVTxx2LGkCj1SQulMc6y6OZin+J/QQ -----END CERTIFICATE----- 04.pem000066400000000000000000000026241470345337400355470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca/certs-----BEGIN CERTIFICATE----- MIID8DCCAtigAwIBAgIBBDANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjAe MRwwGgYDVQQDDBNtYXN0ZXIxLmV4YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA6RLLxx3df3Ln6TG3iORiJNsQfZsRa00XgGhzbdTGOJ0v X5Yjq3igQeGVd3aCqAEivaDmk0Mk6mWyH5l1ODn75PdYUFMVblmNaCZ1sY6lc3uJ qWPEz6AZYojkLrhumtInUD6y9N3q2CllgT/B1yb4Hfs2WsTGtZjmYOqdKv0gaTw0 p46Uj0UrE42GOVjrrIQfomq16XwUDh1kqfIxuob4J/ZHN4pHsFtIvh3F3ZD2OGPi YLyPGyP3C1ssUnCoqfMM2TUO9LGeWquRvCLoYe+jA5Q8lbDU1NjxrRlfS+LyeCgn 96vWWmh/THVnaCiSj4O68pZABsgmHhg+diC8t+/sbQIDAQABo4HZMIHWMFsGA1Ud IwRUMFKhTaRLMEkxEDAOBgNVBAMMB1Jvb3QgQ0ExGjAYBgNVBAsMEVNlcnZlciBP cGVyYXRpb25zMRkwFwYDVQQKDBBFeGFtcGxlIE9yZywgTExDggEBMAwGA1UdEwEB /wQCMAAwCwYDVR0PBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD AjA9BgNVHREENjA0ghNtYXN0ZXIxLmV4YW1wbGUub3JnggdtYXN0ZXIxggZwdXBw ZXSCDHB1cHBldG1hc3RlcjANBgkqhkiG9w0BAQsFAAOCAQEAP5IbZHIFdRjh7f1p 9SHcGEJ9O/OYZfkmqzKfNsnQ3q/Honz3C9SxWkAdOTSQClayi/x+RkOL0h+50+Mw X/rC3qkIRce0JV+Uym/T4WsGz4Oko37xlt6Mlm9x194mTk3wcy22kY6jEOfp+YO3 Chsdw62yyp09v5YkwE9obPfSB3LshgabLBDsZPOqRM1IFmpQ7gkuwa/RlvQfidrs G9A4EzbWAt8d7v59HsL9u0+p3NT7JM1IH3pU0u5UWQwrMVkpiurtrz+ysTXp8XPT QUaA2LkGb4omiW7n1FsablFS6uByD7v41P7oDW5dMkOsKl+mw1Qeh/wZOplmoQVx 6xT00Q== -----END CERTIFICATE----- 05.pem000066400000000000000000000025571470345337400355550ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca/certs-----BEGIN CERTIFICATE----- MIID1zCCAr+gAwIBAgIBBTANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjBE MSEwHwYDVQQDDBhhZ2VudC1lbWFpbDEuZXhhbXBsZS5vcmcxHzAdBgkqhkiG9w0B CQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQDIKXR0WvZcBrJPE8JFaKB8/CMi0jUshP3f38O4YcBh0nF8AcAwwC9/iLFe xXHY27lRO1V0XpvebRzlFDMSoeqS5wGYge7ola9t5nR0njwWAfsAIe/dt9ZdJuxn mk56IQV/cQXw8h/qHSZP2/utmHycWRkHY5U4VcAZX0IQwLBqk6+/ywxtl9MvIOuY 8yImz7BNwnm2ZfWhHm3EHqF7hOhPNnaOq0R4y0TCd+gUfdSF5t1KIQ7dLyrw2Bvd c472rGpM89oQRuw6YvYe8/K4XLbtyZs3FwAOUW5ijJwUIRQMPVuJj60TQHcH9mIm byL+ZCOI9DQgr3Swx05wMNddXSjpAgMBAAGjgZowgZcwWwYDVR0jBFQwUqFNpEsw STEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9wZXJhdGlvbnMx GTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/BAIwADALBgNV HQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3 DQEBCwUAA4IBAQA4q8Vg2LMKmvDy+Q+lBIZh6rbcTafMu//H9+AhPcGh1gR0J0Wj SDps/woYSle04b7MvwC6+yPCiT79nIpZBQ5jHIcWxnE9tQa7DcPuTyPyalNUlzuE 1Pp2cYkFiYMv2lGU4z13y8PynoL+vqoij0LPXa6SP4lhmbvC/qWkf8IF6C6kGTWB ZQTTOa0/MWirGlKDsUh4UygzpRICjO4ouzBKDTEmfLEZKpWiCY3WtrCWO6zK6OOa O85k5MnBXjV/Z2Yv9MRABZDjQaFtJ6zTktlakjOyqoPMaPu5aV7B2T1fN4myM1NB m+vtQqWUNYDOpTGk7QML5Bfz7LH/c5NohQbq -----END CERTIFICATE----- 06.pem000066400000000000000000000025571470345337400355560ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca/certs-----BEGIN CERTIFICATE----- MIID1zCCAr+gAwIBAgIBBjANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjBE MSEwHwYDVQQDDBhhZ2VudC1lbWFpbDIuZXhhbXBsZS5vcmcxHzAdBgkqhkiG9w0B CQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCl93N93Sxm3Odr8PUOV7iQDDFy3399SkTSq6jGV1P9KIh2hszlSoLKYhKA PVlIlYvCcbVflsixHDcyd/8SywstNndhdIhM1mpi6QBhEtnOoFjfYTfbVKSC6PUl PoUIVqwumiB2VLiHCy5AHij1Ak7EMD/4gpvvVfGoG3j9jLNl+csu79j2yQYiDk9a wQkoI4dO4jBAdq983Hz3lfKFj1qgrwUMSpMsN3KMi/6osJTzdOFFe8UuizHQFrnh 4Y9/26zZGdgOd31kmb0Vka1c3+TIwr9JbiQqWo/ZYSX6j187aRpPCl6tvUqVPSO1 TPSCKHrkVauR8ZsuwgOGo+mR31VLAgMBAAGjgZowgZcwWwYDVR0jBFQwUqFNpEsw STEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9wZXJhdGlvbnMx GTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/BAIwADALBgNV HQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3 DQEBCwUAA4IBAQBeSAbhGhWQCclBrX8DYvQa+HvZIcsw18UILA2zuGvNoUgbWjob 3w8nMYSjQ6YGJns/H8jHOTShut8wsrKCRuEzI80LzYUF6MgpEDrxwlxbKQLBHg3K XnCNSEwDYVJOllIUEAK0TByPP1YFHtd2IdZ9kTticVJdmravZFM18SbLt4J6X/t/ EBuiJE27fdMqJSv9OP6PUg+MYakvBz3EGwzbjwn7NAB8OB+PPXd14Er2P8B1C8of Hubiv5Hk3NX5QbXGkoetjzRLkpXCaOZNkWPcWxkPMv7cVozpDtm7E1UC2i7BUdPh FAPv+O7WxDixLb9O5uuE4jnszg4Jhp7JfOqU -----END CERTIFICATE----- 07.pem000066400000000000000000000025571470345337400355570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca/certs-----BEGIN CERTIFICATE----- MIID1zCCAr+gAwIBAgIBBzANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjBE MSEwHwYDVQQDDBhhZ2VudC1lbWFpbDMuZXhhbXBsZS5vcmcxHzAdBgkqhkiG9w0B CQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCqcD47G2JXhzySuwJX+2jkDW1CFe7WrmWtTaeneszgSz2juuFA39KGS2lC /RBU6okPwhYoaCFLZYTeGx7NNaUYc+GJf//IMerzqbXTLsjh96686+7Iwqjn+B5O Z3XfCF2quEC1g/uT+/ziqN1YmRMzMGXMlSQGp17sCP0EqW4Xcry9fLhCV9Z9kJyJ fxqIG8fmjCyhUwL3x8iLmaRVFovhfLvyNPLLYkOcpDdeBuASn/7/rtV+bWfVWd/Y a5wNqvIbtlp/FUt7VZ35B66SXp3yF1kaVl159BbkL2xzThch+0rRUH6OD3UyOv8Y Ubmkl2Q7ykNJNh2nKwtNIqPt5PZ3AgMBAAGjgZowgZcwWwYDVR0jBFQwUqFNpEsw STEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9wZXJhdGlvbnMx GTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/BAIwADALBgNV HQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3 DQEBCwUAA4IBAQCMrpNT6pqqkKn+usB8sFWIcASP3OTnaEQVCpnoCoudrB4UHDZO oQzzY3Ys5fcTK7rnXS7J1daS6Qi1g/XSiTCB8xVWXjz8uQtXGQXjVWNpxI9clFyo IJBZ7Cm9h8QatFIF5G+e5E8G7HEe4Cx88ESAAuQ2cnJsARRB7DyEuegPqZunGc1M T6Z5Y4Xn45zorp+TLLjE5zbrInrNeaVzcqFQYpMbzvFoWwba8G/1YobKggNIgLk5 rlqUKrZKawRjtMHBnIJf74RLBZ8qQezycIUso8vTi3is1BdRgSfPEdlWAxIwyOoj uSnhq4DT4QfDZK9u1J9e7pxthhQdEW9Eo6/v -----END CERTIFICATE----- inventory.txt000066400000000000000000000007371470345337400363020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-caV 430407224158Z 01 unknown /CN=agent1.example.org R 430407224158Z 230412224158Z 02 unknown /CN=agent2.example.org V 430407224158Z 03 unknown /CN=agent3.example.org V 430407224158Z 04 unknown /CN=master1.example.org V 430407224158Z 05 unknown /CN=agent-email1.example.org/emailAddress=test@example.com V 430407224158Z 06 unknown /CN=agent-email2.example.org/emailAddress=test@example.com V 430407224158Z 07 unknown /CN=agent-email3.example.org/emailAddress=test@example.com inventory.txt.attr000066400000000000000000000000251470345337400372410ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-caunique_subject = yes inventory.txt.attr.old000066400000000000000000000000251470345337400400160ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-caunique_subject = yes inventory.txt.old000066400000000000000000000007221470345337400370510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-caV 430407224158Z 01 unknown /CN=agent1.example.org V 430407224158Z 02 unknown /CN=agent2.example.org V 430407224158Z 03 unknown /CN=agent3.example.org V 430407224158Z 04 unknown /CN=master1.example.org V 430407224158Z 05 unknown /CN=agent-email1.example.org/emailAddress=test@example.com V 430407224158Z 06 unknown /CN=agent-email2.example.org/emailAddress=test@example.com V 430407224158Z 07 unknown /CN=agent-email3.example.org/emailAddress=test@example.com openssl.conf000066400000000000000000000052561470345337400360370ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-caSAN = DNS:puppet [ca] default_ca = master_ca_config # Root CA [root_ca_config] certificate = /tmp/certchain.HHLFb2ep/agent-ca/ca-agent-ca.crt private_key = /tmp/certchain.HHLFb2ep/agent-ca/ca-agent-ca.key database = /tmp/certchain.HHLFb2ep/agent-ca/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/agent-ca/certs serial = /tmp/certchain.HHLFb2ep/agent-ca/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 policy = root_ca_policy x509_extensions = root_ca_exts [root_ca_policy] commonName = supplied emailAddress = supplied organizationName = supplied organizationalUnitName = supplied [root_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:true keyUsage = keyCertSign, cRLSign # Master CA [master_ca_config] certificate = /tmp/certchain.HHLFb2ep/agent-ca/ca-agent-ca.crt private_key = /tmp/certchain.HHLFb2ep/agent-ca/ca-agent-ca.key database = /tmp/certchain.HHLFb2ep/agent-ca/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/agent-ca/certs serial = /tmp/certchain.HHLFb2ep/agent-ca/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 policy = master_ca_policy x509_extensions = master_ca_exts # Master CA (Email) [master_ca_email_config] certificate = /tmp/certchain.HHLFb2ep/agent-ca/ca-agent-ca.crt private_key = /tmp/certchain.HHLFb2ep/agent-ca/ca-agent-ca.key database = /tmp/certchain.HHLFb2ep/agent-ca/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/agent-ca/certs serial = /tmp/certchain.HHLFb2ep/agent-ca/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 email_in_dn = yes policy = master_ca_email_policy x509_extensions = master_ca_exts [master_ca_policy] commonName = supplied [master_ca_email_policy] commonName = supplied emailAddress = supplied # default extensions for clients [master_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth [master_ssl_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth subjectAltName = $ENV::SAN # extensions for the master certificate (specifically adding subjectAltName) [master_self_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth # include the master's fqdn here, as well as in the CN, to work # around https://bugs.ruby-lang.org/issues/6493 # NOTE: Alt Names should be set in the request, so they know # their FQDN # subjectAltName = DNS:puppet,DNS:agent-ca.example.org serial000066400000000000000000000000031470345337400346700ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca08 serial.old000066400000000000000000000000031470345337400354450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/agent-ca07 puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/auth.conf000066400000000000000000000101141470345337400337020ustar00rootroot00000000000000# Puppetserver 2.2.0 auth.conf, modified to allow requests from example.org for # external ca testing. authorization: { version: 1 rules: [ { # Allow nodes to retrieve their own catalog match-request: { path: "^/puppet/v3/catalog/([^/]+)$" type: regex method: [get, post] } allow: [ "$1", "*.example.org" ] sort-order: 500 name: "puppetlabs catalog" }, { # 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" }, { match-request: { path: "/puppet/v3/environments" type: path method: get } allow: "*" sort-order: 500 name: "puppetlabs environments" }, { # Allow nodes to access all file services; this is necessary for # pluginsync, file serving from modules, and file serving from # custom mount points (see fileserver.conf). Note that the `/file` # prefix matches requests to file_metadata, file_content, and # file_bucket_file paths. match-request: { path: "/puppet/v3/file" type: path } allow: "*" sort-order: 500 name: "puppetlabs file" }, { # Allow nodes to retrieve only their own node definition match-request: { path: "^/puppet/v3/node/([^/]+)$" type: regex method: get } allow: [ "$1", "*.example.org" ] 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", "*.example.org" ] sort-order: 500 name: "puppetlabs report" }, { match-request: { path: "/puppet/v3/static_file_content" type: path method: get } allow: "*" sort-order: 500 name: "puppetlabs static file content" }, { # Allow all users access to the experimental endpoint # which currently only provides a dashboard web ui. match-request: { path: "/puppet/experimental" type: path } allow-unauthenticated: true sort-order: 500 name: "puppetlabs experimental" }, { # 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" } ] } puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/certchain.sh000077500000000000000000000450531470345337400344030ustar00rootroot00000000000000#! /bin/bash ## NOTE: ## This script requires the following in /etc/hosts: ## 127.0.0.2 puppet master1.example.org # This will fail with a stock puppet 3.1.1, but will succeed if all of the # certificate subjects contain only the "CN" portion, and no O, OU, or # emailAddress. # basic config to describe the environment B="/tmp/certchain" #B="$(mktemp -d -t certchain.XXXXXXXX)" HTTPS_PORT=8443 OPENSSL=$(which openssl) # utility method to dedent a heredoc dedent() { python3 -c 'import sys, textwrap; print(textwrap.dedent(sys.stdin.read()))' } # invoke openssl openssl() { echo "----" echo "running" "${OPENSSL}" "$@" echo " in $PWD" "${OPENSSL}" "$@" } show_cert() { local cert="$1" # openssl x509 -in "${cert}" -noout -text -nameopt RFC2253 openssl x509 -in "${cert}" -noout -text } hash_cert() { local cert="$1" local certdir="${B}/certdir" local h=$("${OPENSSL}" x509 -hash -noout -in "${cert}") mkdir -p "${certdir}" ln -s "$cert" "${certdir}/${h}.0" } show_crl() { local crl="$1" openssl crl -in "${crl}" -noout -text } hash_crl() { local crl="$1" local certdir="${B}/certdir" local h=$("${OPENSSL}" crl -hash -noout -in "${crl}") mkdir -p "${certdir}" ln -s "$crl" "${certdir}/${h}.r0" } # clean out any messes this script has made clean_up() { stop_apache rm -rf "$B" } stop_apache() { local pid pidfile="${B}/apache/httpd.pid" while true; do pid=$(cat "${pidfile}" 2>/dev/null || true) [ -z "$pid" ] && break # break if the pid is gone kill "$pid" || break # break if the kill fails (process is gone) sleep 0.1 done } # perform basic setup: make directories, etc. set_up() { mkdir -p "$B" } # create CA certificates: # # * $B/root_ca # * $B/master{1..2}_ca # # with each containing: # # * openssl.conf -- suitable for signing certificates # * ca-$name.key -- PEM format certificate key, with no password # * ca-$name.crt -- PEM format certificate create_ca_certs() { local name cn dir subj ca_config for name in root agent-ca master-ca; do dir="${B}/${name}" mkdir -p "${dir}" ( cd "${dir}" # if this is the root cert, make a self-signed cert if [ "$name" = "root" ]; then subj="/CN=Root CA/OU=Server Operations/O=Example Org, LLC" openssl req -new -newkey rsa:2048 -days 7300 -nodes -x509 \ -subj "${subj}" -keyout "ca-${name}.key" -out "ca-${name}.crt" else # make a new key for the CA openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out "ca-${name}.key" # build a CSR out of it dedent > openssl.tmp << OPENSSL_TMP [req] prompt = no distinguished_name = dn_config [dn_config] commonName = Intermediate CA (${name}) emailAddress = test@example.org organizationalUnitName = Server Operations organizationName = Example Org, LLC OPENSSL_TMP openssl req -config openssl.tmp -new -key "ca-${name}.key" -out "ca-${name}.csr" rm openssl.tmp # sign it with the root CA openssl ca -config ../root/openssl.conf -in "ca-${name}.csr" -notext -out "ca-${name}.crt" -batch # clean up the now-redundant csr rm "ca-${name}.csr" fi # set up the CA config; this uses the same file for all, but with different options # for the root and master CAs [ "$name" = "root" ] && ca_config=root_ca_config || ca_config=master_ca_config dedent > openssl.conf << OPENSSL_CONF SAN = DNS:puppet [ca] default_ca = ${ca_config} # Root CA [root_ca_config] certificate = ${dir}/ca-${name}.crt private_key = ${dir}/ca-${name}.key database = ${dir}/inventory.txt new_certs_dir = ${dir}/certs serial = ${dir}/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 policy = root_ca_policy x509_extensions = root_ca_exts [root_ca_policy] commonName = supplied emailAddress = supplied organizationName = supplied organizationalUnitName = supplied [root_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:true keyUsage = keyCertSign, cRLSign # Master CA [master_ca_config] certificate = ${dir}/ca-${name}.crt private_key = ${dir}/ca-${name}.key database = ${dir}/inventory.txt new_certs_dir = ${dir}/certs serial = ${dir}/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 policy = master_ca_policy x509_extensions = master_ca_exts # Master CA (Email) [master_ca_email_config] certificate = ${dir}/ca-${name}.crt private_key = ${dir}/ca-${name}.key database = ${dir}/inventory.txt new_certs_dir = ${dir}/certs serial = ${dir}/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 email_in_dn = yes policy = master_ca_email_policy x509_extensions = master_ca_exts [master_ca_policy] commonName = supplied [master_ca_email_policy] commonName = supplied emailAddress = supplied # default extensions for clients [master_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth [master_ssl_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth subjectAltName = \$ENV::SAN # extensions for the master certificate (specifically adding subjectAltName) [master_self_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth # include the master's fqdn here, as well as in the CN, to work # around https://bugs.ruby-lang.org/issues/6493 # NOTE: Alt Names should be set in the request, so they know # their FQDN # subjectAltName = DNS:puppet,DNS:${name}.example.org OPENSSL_CONF touch inventory.txt mkdir certs echo 01 > serial show_cert "${dir}/ca-${name}.crt" hash_cert "${dir}/ca-${name}.crt" # generate an empty CRL for this CA openssl ca -config "${dir}/openssl.conf" -gencrl -out "${dir}/ca-${name}.crl" show_crl "${dir}/ca-${name}.crl" hash_crl "${dir}/ca-${name}.crl" ) done } # revoke leaf cert for $1 issued by master CA $2 revoke_leaf_cert() { local fqdn="$1" local ca="${2:-agent-ca}" local dir="${B}/${ca}" # revoke the cert and regenerate the crl openssl ca -config "${dir}/openssl.conf" -revoke "${B}/leaves/${fqdn}.issued_by.${ca}.crt" openssl ca -config "${dir}/openssl.conf" -gencrl -out "${dir}/ca-${ca}.crl" show_crl "${dir}/ca-${ca}.crl" # kill -HUP $(< "${B}/apache/httpd.pid") } # revoke CA cert for $1 revoke_ca_cert() { local master="$1" local dir="${B}/root" # revoke the cert and regenerate the crl openssl ca -config "${dir}/openssl.conf" -revoke "${B}/${master}/ca-${master}.crt" openssl ca -config "${dir}/openssl.conf" -gencrl -out "${dir}/ca-root.crl" show_crl "${dir}/ca-root.crl" kill -HUP "$(< "${B}/apache/httpd.pid")" } # create a "leaf" certificate for the given fqdn, signed by the given ca name. # $fqdn.issued_by.${ca}.{key,crt} will be placed in "${B}/leaves" create_leaf_cert() { local fqdn="$1" ca="$2" exts="$3" local masterdir="${B}/${ca}" local dir="${B}/leaves" local fname="${fqdn}.issued_by.${ca}" if [[ -n "$exts" ]]; then exts="-extensions $exts" else exts= fi mkdir -p "${dir}" ( cd "${dir}" openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out "${fname}.key" openssl req -subj "/CN=${fqdn}" -new -key "${fname}.key" -out "${fname}.csr" CN="${fqdn}" SAN="DNS:${fqdn}, DNS:${fqdn%%.*}, DNS:puppet, DNS:puppetmaster" \ openssl ca -config "${B}/${ca}/openssl.conf" -in "${fname}.csr" -notext \ -out "${fname}.crt" -batch $exts ) show_cert "${dir}/${fname}.crt" } # Note, we can parameterize SubjectAltNames using environment variables. create_leaf_certs() { create_leaf_cert master1.example.org master-ca master_ssl_exts create_leaf_cert master2.example.org master-ca master_ssl_exts create_leaf_cert agent1.example.org agent-ca create_leaf_cert agent2.example.org agent-ca create_leaf_cert agent3.example.org agent-ca create_leaf_cert master1.example.org agent-ca master_ssl_exts # rogue # create_leaf_cert master1.example.org root master_ssl_exts # rogue create_leaf_cert agent1.example.org master-ca # rogue # create_leaf_cert agent1.example.org root # rogue } # create a "leaf" certificate for the given fqdn, signed by the given ca name, # with an email address in the subject. # $fqdn.issued_by.${ca}.{key,crt} will be placed in "${B}/leaves" create_leaf_email_cert() { local fqdn="$1" ca="$2" exts="$3" local masterdir="${B}/${ca}" local dir="${B}/leaves" local fname="${fqdn}.issued_by.${ca}" if [[ -n "$exts" ]]; then exts="-extensions $exts" else exts= fi if [[ -n "$exts" ]]; then exts="-extensions $exts" else exts= fi mkdir -p "${dir}" ( cd "${dir}" openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out "${fname}.key" openssl req -subj "/CN=${fqdn}/emailAddress=test@example.com" -new -key "${fname}.key" -out "${fname}.csr" openssl ca -config "${B}/${ca}/openssl.conf" -name master_ca_email_config \ -in "${fname}.csr" -notext -out "${fname}.crt" -batch $exts ) show_cert "${dir}/${fname}.crt" } create_leaf_email_certs() { create_leaf_email_cert master-email1.example.org master-ca master_self_ca_exts create_leaf_email_cert master-email2.example.org master-ca master_self_ca_exts create_leaf_email_cert agent-email1.example.org agent-ca create_leaf_email_cert agent-email2.example.org agent-ca create_leaf_email_cert agent-email3.example.org agent-ca } set_up_apache() { local apachedir="${B}/apache" mkdir -p "${apachedir}/puppetmaster/public" echo 'passed'> "${apachedir}/puppetmaster/public/test.txt" dedent > "${apachedir}/httpd.conf" < Require all granted RackAutoDetect On RackBaseURI / HTTPD_CONF } set_up_puppetmaster() { local apachedir="${B}/apache" local masterdir="${B}/puppetmaster" local confdir="${masterdir}/conf" local environmentdir="${confdir}/environments/production" mkdir -p "${confdir}" "${masterdir}/var" "${environmentdir}/manifests" dedent > "${apachedir}/puppetmaster/config.ru" < "${masterdir}/conf/puppet.conf" < "${environmentdir}/manifests/site.pp" < "yes I was" } } SITE_PP } start_apache() { local apachedir="${B}/apache" if ! httpd -f "${apachedir}/httpd.conf"; then [ -f "${apachedir}/error_log" ] && tail "${apachedir}/error_log" false fi } check_apache() { # verify the SSL config with openssl. Note that s_client exits with 0 # no matter what, so this greps the output for an OK status. Also note # that this only checks that the validation of the server certs is OK, since # client validation is optional in the httpd config. echo $'GET /test.txt HTTP/1.0\n' | \ openssl s_client -connect "127.0.0.1:${HTTPS_PORT}" -verify 2 \ -cert "${B}/leaves/client2a.example.org.crt" \ -key "${B}/leaves/client2a.example.org.key" \ -CAfile "${B}/root/ca-root.crt" \ | tee "${B}/verify.out" cat "${B}/apache/error_log" grep -q "Verify return code: 0 (ok)" "${B}/verify.out" } check_puppetmaster() { # this is insecure, because otherwise curl will check that 127.0.0.1 == # master1.example.org and fail; validation of the server certs is done # above in check_apache, so this is fine. curl -vks --fail \ --header 'Accept: yaml' \ --cert "${B}/leaves/client2a.example.org.crt" \ --key "${B}/leaves/client2a.example.org.key" \ "https://127.0.0.1:${HTTPS_PORT}/puppet/v3/catalog/client2a.example.org?environment=production" >/dev/null echo } # set up the agent with the given fqdn set_up_agent() { local fqdn="$1" local agentdir="${B}/agent" mkdir -p "${agentdir}/conf" "${agentdir}/var" mkdir -p "${agentdir}/conf/ssl/private_keys" "${agentdir}/conf/ssl/certs" dedent > "${agentdir}/conf/puppet.conf" < StartServers 8 MinSpareServers 5 MaxSpareServers 20 ServerLimit 256 MaxClients 256 MaxRequestsPerChild 4000 StartServers 4 MaxClients 300 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 LoadModule auth_basic_module modules/mod_auth_basic.so LoadModule auth_digest_module modules/mod_auth_digest.so LoadModule authn_file_module modules/mod_authn_file.so LoadModule authn_alias_module modules/mod_authn_alias.so LoadModule authn_anon_module modules/mod_authn_anon.so LoadModule authn_dbm_module modules/mod_authn_dbm.so LoadModule authn_default_module modules/mod_authn_default.so LoadModule authz_host_module modules/mod_authz_host.so LoadModule authz_user_module modules/mod_authz_user.so LoadModule authz_owner_module modules/mod_authz_owner.so LoadModule authz_groupfile_module modules/mod_authz_groupfile.so LoadModule authz_dbm_module modules/mod_authz_dbm.so LoadModule authz_default_module modules/mod_authz_default.so LoadModule ldap_module modules/mod_ldap.so LoadModule authnz_ldap_module modules/mod_authnz_ldap.so LoadModule include_module modules/mod_include.so LoadModule log_config_module modules/mod_log_config.so LoadModule logio_module modules/mod_logio.so LoadModule env_module modules/mod_env.so LoadModule ext_filter_module modules/mod_ext_filter.so LoadModule mime_magic_module modules/mod_mime_magic.so LoadModule expires_module modules/mod_expires.so LoadModule deflate_module modules/mod_deflate.so LoadModule headers_module modules/mod_headers.so LoadModule usertrack_module modules/mod_usertrack.so LoadModule setenvif_module modules/mod_setenvif.so LoadModule mime_module modules/mod_mime.so LoadModule dav_module modules/mod_dav.so LoadModule status_module modules/mod_status.so LoadModule autoindex_module modules/mod_autoindex.so LoadModule info_module modules/mod_info.so LoadModule dav_fs_module modules/mod_dav_fs.so LoadModule vhost_alias_module modules/mod_vhost_alias.so LoadModule negotiation_module modules/mod_negotiation.so LoadModule dir_module modules/mod_dir.so LoadModule actions_module modules/mod_actions.so LoadModule speling_module modules/mod_speling.so LoadModule userdir_module modules/mod_userdir.so LoadModule alias_module modules/mod_alias.so LoadModule substitute_module modules/mod_substitute.so LoadModule rewrite_module modules/mod_rewrite.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_balancer_module modules/mod_proxy_balancer.so LoadModule proxy_ftp_module modules/mod_proxy_ftp.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so LoadModule proxy_connect_module modules/mod_proxy_connect.so LoadModule cache_module modules/mod_cache.so LoadModule suexec_module modules/mod_suexec.so LoadModule disk_cache_module modules/mod_disk_cache.so LoadModule cgi_module modules/mod_cgi.so LoadModule version_module modules/mod_version.so LoadModule ssl_module modules/mod_ssl.so LoadModule passenger_module modules/mod_passenger.so PassengerRoot /usr/share/gems/gems/passenger-3.0.17 PassengerRuby /usr/bin/ruby Listen 8140 https SSLRandomSeed startup file:/dev/urandom 256 SSLRandomSeed connect builtin SSLEngine on SSLProtocol all -SSLv2 SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5 # puppet-relevant SSL config: SSLCertificateFile "${B}/leaves/master1.example.org.crt" SSLCertificateKeyFile "${B}/leaves/master1.example.org.key" # chain in the intermediate cert for this master SSLCertificateChainFile "${B}/master1/ca-master1.crt" SSLCACertificatePath "${B}/certdir" SSLCARevocationPath "${B}/certdir" SSLCARevocationCheck chain SSLVerifyClient optional SSLVerifyDepth 2 SSLOptions +StdEnvVars RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e ServerName master1.example.org DocumentRoot "${apachedir}/puppetmaster/public" # NOTE: this is httpd-2.4 syntax Require all granted RackAutoDetect On RackBaseURI / httpd.conf.el6.orig000066400000000000000000001031621470345337400354370ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures# # This is the main Apache server configuration file. It contains the # configuration directives that give the server its instructions. # See for detailed information. # In particular, see # # for a discussion of each configuration directive. # # # Do NOT simply read the instructions in here without understanding # what they do. They're here only as hints or reminders. If you are unsure # consult the online docs. You have been warned. # # The configuration directives are grouped into three basic sections: # 1. Directives that control the operation of the Apache server process as a # whole (the 'global environment'). # 2. Directives that define the parameters of the 'main' or 'default' server, # which responds to requests that aren't handled by a virtual host. # These directives also provide default values for the settings # of all virtual hosts. # 3. Settings for virtual hosts, which allow Web requests to be sent to # different IP addresses or hostnames and have them handled by the # same Apache server process. # # Configuration and logfile names: If the filenames you specify for many # of the server's control files begin with "/" (or "drive:/" for Win32), the # server will use that explicit path. If the filenames do *not* begin # with "/", the value of ServerRoot is prepended -- so "logs/foo.log" # with ServerRoot set to "/etc/httpd" will be interpreted by the # server as "/etc/httpd/logs/foo.log". # ### Section 1: Global Environment # # The directives in this section affect the overall operation of Apache, # such as the number of concurrent requests it can handle or where it # can find its configuration files. # # # Don't give away too much information about all the subcomponents # we are running. Comment out this line if you don't mind remote sites # finding out what major optional modules you are running ServerTokens OS # # ServerRoot: The top of the directory tree under which the server's # configuration, error, and log files are kept. # # NOTE! If you intend to place this on an NFS (or otherwise network) # mounted filesystem then please read the LockFile documentation # (available at ); # you will save yourself a lot of trouble. # # Do NOT add a slash at the end of the directory path. # ServerRoot "/etc/httpd" # # PidFile: The file in which the server should record its process # identification number when it starts. Note the PIDFILE variable in # /etc/sysconfig/httpd must be set appropriately if this location is # changed. # PidFile run/httpd.pid # # Timeout: The number of seconds before receives and sends time out. # Timeout 60 # # KeepAlive: Whether or not to allow persistent connections (more than # one request per connection). Set to "Off" to deactivate. # KeepAlive Off # # MaxKeepAliveRequests: The maximum number of requests to allow # during a persistent connection. Set to 0 to allow an unlimited amount. # We recommend you leave this number high, for maximum performance. # MaxKeepAliveRequests 100 # # KeepAliveTimeout: Number of seconds to wait for the next request from the # same client on the same connection. # KeepAliveTimeout 15 ## ## Server-Pool Size Regulation (MPM specific) ## # prefork MPM # StartServers: number of server processes to start # MinSpareServers: minimum number of server processes which are kept spare # MaxSpareServers: maximum number of server processes which are kept spare # ServerLimit: maximum value for MaxClients for the lifetime of the server # MaxClients: maximum number of server processes allowed to start # MaxRequestsPerChild: maximum number of requests a server process serves StartServers 8 MinSpareServers 5 MaxSpareServers 20 ServerLimit 256 MaxClients 256 MaxRequestsPerChild 4000 # worker MPM # StartServers: initial number of server processes to start # MaxClients: maximum number of simultaneous client connections # MinSpareThreads: minimum number of worker threads which are kept spare # MaxSpareThreads: maximum number of worker threads which are kept spare # ThreadsPerChild: constant number of worker threads in each server process # MaxRequestsPerChild: maximum number of requests a server process serves StartServers 4 MaxClients 300 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 # # Listen: Allows you to bind Apache to specific IP addresses and/or # ports, in addition to the default. See also the # directive. # # Change this to Listen on specific IP addresses as shown below to # prevent Apache from glomming onto all bound IP addresses (0.0.0.0) # #Listen 12.34.56.78:80 Listen 80 # # Dynamic Shared Object (DSO) Support # # To be able to use the functionality of a module which was built as a DSO you # have to place corresponding `LoadModule' lines at this location so the # directives contained in it are actually available _before_ they are used. # Statically compiled modules (those listed by `httpd -l') do not need # to be loaded here. # # Example: # LoadModule foo_module modules/mod_foo.so # LoadModule auth_basic_module modules/mod_auth_basic.so LoadModule auth_digest_module modules/mod_auth_digest.so LoadModule authn_file_module modules/mod_authn_file.so LoadModule authn_alias_module modules/mod_authn_alias.so LoadModule authn_anon_module modules/mod_authn_anon.so LoadModule authn_dbm_module modules/mod_authn_dbm.so LoadModule authn_default_module modules/mod_authn_default.so LoadModule authz_host_module modules/mod_authz_host.so LoadModule authz_user_module modules/mod_authz_user.so LoadModule authz_owner_module modules/mod_authz_owner.so LoadModule authz_groupfile_module modules/mod_authz_groupfile.so LoadModule authz_dbm_module modules/mod_authz_dbm.so LoadModule authz_default_module modules/mod_authz_default.so LoadModule ldap_module modules/mod_ldap.so LoadModule authnz_ldap_module modules/mod_authnz_ldap.so LoadModule include_module modules/mod_include.so LoadModule log_config_module modules/mod_log_config.so LoadModule logio_module modules/mod_logio.so LoadModule env_module modules/mod_env.so LoadModule ext_filter_module modules/mod_ext_filter.so LoadModule mime_magic_module modules/mod_mime_magic.so LoadModule expires_module modules/mod_expires.so LoadModule deflate_module modules/mod_deflate.so LoadModule headers_module modules/mod_headers.so LoadModule usertrack_module modules/mod_usertrack.so LoadModule setenvif_module modules/mod_setenvif.so LoadModule mime_module modules/mod_mime.so LoadModule dav_module modules/mod_dav.so LoadModule status_module modules/mod_status.so LoadModule autoindex_module modules/mod_autoindex.so LoadModule info_module modules/mod_info.so LoadModule dav_fs_module modules/mod_dav_fs.so LoadModule vhost_alias_module modules/mod_vhost_alias.so LoadModule negotiation_module modules/mod_negotiation.so LoadModule dir_module modules/mod_dir.so LoadModule actions_module modules/mod_actions.so LoadModule speling_module modules/mod_speling.so LoadModule userdir_module modules/mod_userdir.so LoadModule alias_module modules/mod_alias.so LoadModule substitute_module modules/mod_substitute.so LoadModule rewrite_module modules/mod_rewrite.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_balancer_module modules/mod_proxy_balancer.so LoadModule proxy_ftp_module modules/mod_proxy_ftp.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so LoadModule proxy_connect_module modules/mod_proxy_connect.so LoadModule cache_module modules/mod_cache.so LoadModule suexec_module modules/mod_suexec.so LoadModule disk_cache_module modules/mod_disk_cache.so LoadModule cgi_module modules/mod_cgi.so LoadModule version_module modules/mod_version.so # # The following modules are not loaded by default: # #LoadModule asis_module modules/mod_asis.so #LoadModule authn_dbd_module modules/mod_authn_dbd.so #LoadModule cern_meta_module modules/mod_cern_meta.so #LoadModule cgid_module modules/mod_cgid.so #LoadModule dbd_module modules/mod_dbd.so #LoadModule dumpio_module modules/mod_dumpio.so #LoadModule filter_module modules/mod_filter.so #LoadModule ident_module modules/mod_ident.so #LoadModule log_forensic_module modules/mod_log_forensic.so #LoadModule unique_id_module modules/mod_unique_id.so # # # Load config files from the config directory "/etc/httpd/conf.d". # Include conf.d/*.conf # # ExtendedStatus controls whether Apache will generate "full" status # information (ExtendedStatus On) or just basic information (ExtendedStatus # Off) when the "server-status" handler is called. The default is Off. # #ExtendedStatus On # # If you wish httpd to run as a different user or group, you must run # httpd as root initially and it will switch. # # User/Group: The name (or #number) of the user/group to run httpd as. # . On SCO (ODT 3) use "User nouser" and "Group nogroup". # . On HPUX you may not be able to use shared memory as nobody, and the # suggested workaround is to create a user www and use that user. # NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET) # when the value of (unsigned)Group is above 60000; # don't use Group #-1 on these systems! # User apache Group apache ### Section 2: 'Main' server configuration # # The directives in this section set up the values used by the 'main' # server, which responds to any requests that aren't handled by a # definition. These values also provide defaults for # any containers you may define later in the file. # # All of these directives may appear inside containers, # in which case these default settings will be overridden for the # virtual host being defined. # # # ServerAdmin: Your address, where problems with the server should be # e-mailed. This address appears on some server-generated pages, such # as error documents. e.g. admin@your-domain.com # ServerAdmin root@localhost # # ServerName gives the name and port that the server uses to identify itself. # This can often be determined automatically, but we recommend you specify # it explicitly to prevent problems during startup. # # If this is not set to valid DNS name for your host, server-generated # redirections will not work. See also the UseCanonicalName directive. # # If your host doesn't have a registered DNS name, enter its IP address here. # You will have to access it by its address anyway, and this will make # redirections work in a sensible way. # #ServerName www.example.com:80 # # UseCanonicalName: Determines how Apache constructs self-referencing # URLs and the SERVER_NAME and SERVER_PORT variables. # When set "Off", Apache will use the Hostname and Port supplied # by the client. When set "On", Apache will use the value of the # ServerName directive. # UseCanonicalName Off # # DocumentRoot: The directory out of which you will serve your # documents. By default, all requests are taken from this directory, but # symbolic links and aliases may be used to point to other locations. # DocumentRoot "/var/www/html" # # Each directory to which Apache has access can be configured with respect # to which services and features are allowed and/or disabled in that # directory (and its subdirectories). # # First, we configure the "default" to be a very restrictive set of # features. # Options FollowSymLinks AllowOverride None # # Note that from this point forward you must specifically allow # particular features to be enabled - so if something's not working as # you might expect, make sure that you have specifically enabled it # below. # # # This should be changed to whatever you set DocumentRoot to. # # # Possible values for the Options directive are "None", "All", # or any combination of: # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews # # Note that "MultiViews" must be named *explicitly* --- "Options All" # doesn't give it to you. # # The Options directive is both complicated and important. Please see # http://httpd.apache.org/docs/2.2/mod/core.html#options # for more information. # Options Indexes FollowSymLinks # # AllowOverride controls what directives may be placed in .htaccess files. # It can be "All", "None", or any combination of the keywords: # Options FileInfo AuthConfig Limit # AllowOverride None # # Controls who can get stuff from this server. # Order allow,deny Allow from all # # UserDir: The name of the directory that is appended onto a user's home # directory if a ~user request is received. # # The path to the end user account 'public_html' directory must be # accessible to the webserver userid. This usually means that ~userid # must have permissions of 711, ~userid/public_html must have permissions # of 755, and documents contained therein must be world-readable. # Otherwise, the client will only receive a "403 Forbidden" message. # # See also: http://httpd.apache.org/docs/misc/FAQ.html#forbidden # # # UserDir is disabled by default since it can confirm the presence # of a username on the system (depending on home directory # permissions). # UserDir disabled # # To enable requests to /~user/ to serve the user's public_html # directory, remove the "UserDir disabled" line above, and uncomment # the following line instead: # #UserDir public_html # # Control access to UserDir directories. The following is an example # for a site where these directories are restricted to read-only. # # # AllowOverride FileInfo AuthConfig Limit # Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec # # Order allow,deny # Allow from all # # # Order deny,allow # Deny from all # # # # DirectoryIndex: sets the file that Apache will serve if a directory # is requested. # # The index.html.var file (a type-map) is used to deliver content- # negotiated documents. The MultiViews Option can be used for the # same purpose, but it is much slower. # DirectoryIndex index.html index.html.var # # AccessFileName: The name of the file to look for in each directory # for additional configuration directives. See also the AllowOverride # directive. # AccessFileName .htaccess # # The following lines prevent .htaccess and .htpasswd files from being # viewed by Web clients. # Order allow,deny Deny from all Satisfy All # # TypesConfig describes where the mime.types file (or equivalent) is # to be found. # TypesConfig /etc/mime.types # # DefaultType is the default MIME type the server will use for a document # if it cannot otherwise determine one, such as from filename extensions. # If your server contains mostly text or HTML documents, "text/plain" is # a good value. If most of your content is binary, such as applications # or images, you may want to use "application/octet-stream" instead to # keep browsers from trying to display binary files as though they are # text. # DefaultType text/plain # # The mod_mime_magic module allows the server to use various hints from the # contents of the file itself to determine its type. The MIMEMagicFile # directive tells the module where the hint definitions are located. # # MIMEMagicFile /usr/share/magic.mime MIMEMagicFile conf/magic # # HostnameLookups: Log the names of clients or just their IP addresses # e.g., www.apache.org (on) or 204.62.129.132 (off). # The default is off because it'd be overall better for the net if people # had to knowingly turn this feature on, since enabling it means that # each client request will result in AT LEAST one lookup request to the # nameserver. # HostnameLookups Off # # EnableMMAP: Control whether memory-mapping is used to deliver # files (assuming that the underlying OS supports it). # The default is on; turn this off if you serve from NFS-mounted # filesystems. On some systems, turning it off (regardless of # filesystem) can improve performance; for details, please see # http://httpd.apache.org/docs/2.2/mod/core.html#enablemmap # #EnableMMAP off # # EnableSendfile: Control whether the sendfile kernel support is # used to deliver files (assuming that the OS supports it). # The default is on; turn this off if you serve from NFS-mounted # filesystems. Please see # http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile # #EnableSendfile off # # ErrorLog: The location of the error log file. # If you do not specify an ErrorLog directive within a # container, error messages relating to that virtual host will be # logged here. If you *do* define an error logfile for a # container, that host's errors will be logged there and not here. # ErrorLog logs/error_log # # LogLevel: Control the number of messages logged to the error_log. # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. # LogLevel warn # # The following directives define some format nicknames for use with # a CustomLog directive (see below). # LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent # "combinedio" includes actual counts of actual bytes received (%I) and sent (%O); this # requires the mod_logio module to be loaded. #LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio # # The location and format of the access logfile (Common Logfile Format). # If you do not define any access logfiles within a # container, they will be logged here. Contrariwise, if you *do* # define per- access logfiles, transactions will be # logged therein and *not* in this file. # #CustomLog logs/access_log common # # If you would like to have separate agent and referer logfiles, uncomment # the following directives. # #CustomLog logs/referer_log referer #CustomLog logs/agent_log agent # # For a single logfile with access, agent, and referer information # (Combined Logfile Format), use the following directive: # CustomLog logs/access_log combined # # Optionally add a line containing the server version and virtual host # name to server-generated pages (internal error documents, FTP directory # listings, mod_status and mod_info output etc., but not CGI generated # documents or custom error documents). # Set to "EMail" to also include a mailto: link to the ServerAdmin. # Set to one of: On | Off | EMail # ServerSignature On # # Aliases: Add here as many aliases as you need (with no limit). The format is # Alias fakename realname # # Note that if you include a trailing / on fakename then the server will # require it to be present in the URL. So "/icons" isn't aliased in this # example, only "/icons/". If the fakename is slash-terminated, then the # realname must also be slash terminated, and if the fakename omits the # trailing slash, the realname must also omit it. # # We include the /icons/ alias for FancyIndexed directory listings. If you # do not use FancyIndexing, you may comment this out. # Alias /icons/ "/var/www/icons/" Options Indexes MultiViews FollowSymLinks AllowOverride None Order allow,deny Allow from all # # WebDAV module configuration section. # # Location of the WebDAV lock database. DAVLockDB /var/lib/dav/lockdb # # ScriptAlias: This controls which directories contain server scripts. # ScriptAliases are essentially the same as Aliases, except that # documents in the realname directory are treated as applications and # run by the server when requested rather than as documents sent to the client. # The same rules about trailing "/" apply to ScriptAlias directives as to # Alias. # ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" # # "/var/www/cgi-bin" should be changed to whatever your ScriptAliased # CGI directory exists, if you have that configured. # AllowOverride None Options None Order allow,deny Allow from all # # Redirect allows you to tell clients about documents which used to exist in # your server's namespace, but do not anymore. This allows you to tell the # clients where to look for the relocated document. # Example: # Redirect permanent /foo http://www.example.com/bar # # Directives controlling the display of server-generated directory listings. # # # IndexOptions: Controls the appearance of server-generated directory # listings. # IndexOptions FancyIndexing VersionSort NameWidth=* HTMLTable Charset=UTF-8 # # AddIcon* directives tell the server which icon to show for different # files or filename extensions. These are only displayed for # FancyIndexed directories. # AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip AddIconByType (TXT,/icons/text.gif) text/* AddIconByType (IMG,/icons/image2.gif) image/* AddIconByType (SND,/icons/sound2.gif) audio/* AddIconByType (VID,/icons/movie.gif) video/* AddIcon /icons/binary.gif .bin .exe AddIcon /icons/binhex.gif .hqx AddIcon /icons/tar.gif .tar AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip AddIcon /icons/a.gif .ps .ai .eps AddIcon /icons/layout.gif .html .shtml .htm .pdf AddIcon /icons/text.gif .txt AddIcon /icons/c.gif .c AddIcon /icons/p.gif .pl .py AddIcon /icons/f.gif .for AddIcon /icons/dvi.gif .dvi AddIcon /icons/uuencoded.gif .uu AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl AddIcon /icons/tex.gif .tex AddIcon /icons/bomb.gif core AddIcon /icons/back.gif .. AddIcon /icons/hand.right.gif README AddIcon /icons/folder.gif ^^DIRECTORY^^ AddIcon /icons/blank.gif ^^BLANKICON^^ # # DefaultIcon is which icon to show for files which do not have an icon # explicitly set. # DefaultIcon /icons/unknown.gif # # AddDescription allows you to place a short description after a file in # server-generated indexes. These are only displayed for FancyIndexed # directories. # Format: AddDescription "description" filename # #AddDescription "GZIP compressed document" .gz #AddDescription "tar archive" .tar #AddDescription "GZIP compressed tar archive" .tgz # # ReadmeName is the name of the README file the server will look for by # default, and append to directory listings. # # HeaderName is the name of a file which should be prepended to # directory indexes. ReadmeName README.html HeaderName HEADER.html # # IndexIgnore is a set of filenames which directory indexing should ignore # and not include in the listing. Shell-style wildcarding is permitted. # IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t # # DefaultLanguage and AddLanguage allows you to specify the language of # a document. You can then use content negotiation to give a browser a # file in a language the user can understand. # # Specify a default language. This means that all data # going out without a specific language tag (see below) will # be marked with this one. You probably do NOT want to set # this unless you are sure it is correct for all cases. # # * It is generally better to not mark a page as # * being a certain language than marking it with the wrong # * language! # # DefaultLanguage nl # # Note 1: The suffix does not have to be the same as the language # keyword --- those with documents in Polish (whose net-standard # language code is pl) may wish to use "AddLanguage pl .po" to # avoid the ambiguity with the common suffix for perl scripts. # # Note 2: The example entries below illustrate that in some cases # the two character 'Language' abbreviation is not identical to # the two character 'Country' code for its country, # E.g. 'Danmark/dk' versus 'Danish/da'. # # Note 3: In the case of 'ltz' we violate the RFC by using a three char # specifier. There is 'work in progress' to fix this and get # the reference data for rfc1766 cleaned up. # # Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl) # English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de) # Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja) # Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn) # Norwegian (no) - Polish (pl) - Portugese (pt) # Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv) # Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW) # AddLanguage ca .ca AddLanguage cs .cz .cs AddLanguage da .dk AddLanguage de .de AddLanguage el .el AddLanguage en .en AddLanguage eo .eo AddLanguage es .es AddLanguage et .et AddLanguage fr .fr AddLanguage he .he AddLanguage hr .hr AddLanguage it .it AddLanguage ja .ja AddLanguage ko .ko AddLanguage ltz .ltz AddLanguage nl .nl AddLanguage nn .nn AddLanguage no .no AddLanguage pl .po AddLanguage pt .pt AddLanguage pt-BR .pt-br AddLanguage ru .ru AddLanguage sv .sv AddLanguage zh-CN .zh-cn AddLanguage zh-TW .zh-tw # # LanguagePriority allows you to give precedence to some languages # in case of a tie during content negotiation. # # Just list the languages in decreasing order of preference. We have # more or less alphabetized them here. You probably want to change this. # LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW # # ForceLanguagePriority allows you to serve a result page rather than # MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback) # [in case no accepted languages matched the available variants] # ForceLanguagePriority Prefer Fallback # # Specify a default charset for all content served; this enables # interpretation of all content as UTF-8 by default. To use the # default browser choice (ISO-8859-1), or to allow the META tags # in HTML content to override this choice, comment out this # directive: # AddDefaultCharset UTF-8 # # AddType allows you to add to or override the MIME configuration # file mime.types for specific file types. # #AddType application/x-tar .tgz # # AddEncoding allows you to have certain browsers uncompress # information on the fly. Note: Not all browsers support this. # Despite the name similarity, the following Add* directives have nothing # to do with the FancyIndexing customization directives above. # #AddEncoding x-compress .Z #AddEncoding x-gzip .gz .tgz # If the AddEncoding directives above are commented-out, then you # probably should define those extensions to indicate media types: # AddType application/x-compress .Z AddType application/x-gzip .gz .tgz # # MIME-types for downloading Certificates and CRLs # AddType application/x-x509-ca-cert .crt AddType application/x-pkcs7-crl .crl # # AddHandler allows you to map certain file extensions to "handlers": # actions unrelated to filetype. These can be either built into the server # or added with the Action directive (see below) # # To use CGI scripts outside of ScriptAliased directories: # (You will also need to add "ExecCGI" to the "Options" directive.) # #AddHandler cgi-script .cgi # # For files that include their own HTTP headers: # #AddHandler send-as-is asis # # For type maps (negotiated resources): # (This is enabled by default to allow the Apache "It Worked" page # to be distributed in multiple languages.) # AddHandler type-map var # # Filters allow you to process content before it is sent to the client. # # To parse .shtml files for server-side includes (SSI): # (You will also need to add "Includes" to the "Options" directive.) # AddType text/html .shtml AddOutputFilter INCLUDES .shtml # # Action lets you define media types that will execute a script whenever # a matching file is called. This eliminates the need for repeated URL # pathnames for oft-used CGI file processors. # Format: Action media/type /cgi-script/location # Format: Action handler-name /cgi-script/location # # # Customizable error responses come in three flavors: # 1) plain text 2) local redirects 3) external redirects # # Some examples: #ErrorDocument 500 "The server made a boo boo." #ErrorDocument 404 /missing.html #ErrorDocument 404 "/cgi-bin/missing_handler.pl" #ErrorDocument 402 http://www.example.com/subscription_info.html # # # Putting this all together, we can internationalize error responses. # # We use Alias to redirect any /error/HTTP_.html.var response to # our collection of by-error message multi-language collections. We use # includes to substitute the appropriate text. # # You can modify the messages' appearance without changing any of the # default HTTP_.html.var files by adding the line: # # Alias /error/include/ "/your/include/path/" # # which allows you to create your own set of files by starting with the # /var/www/error/include/ files and # copying them to /your/include/path/, even on a per-VirtualHost basis. # Alias /error/ "/var/www/error/" AllowOverride None Options IncludesNoExec AddOutputFilter Includes html AddHandler type-map var Order allow,deny Allow from all LanguagePriority en es de fr ForceLanguagePriority Prefer Fallback # ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var # ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var # ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var # ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var # ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var # ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var # ErrorDocument 410 /error/HTTP_GONE.html.var # ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var # ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var # ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var # ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var # ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var # ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var # ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var # ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var # ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var # ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var # # The following directives modify normal HTTP response behavior to # handle known problems with browser implementations. # BrowserMatch "Mozilla/2" nokeepalive BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 BrowserMatch "RealPlayer 4\.0" force-response-1.0 BrowserMatch "Java/1\.0" force-response-1.0 BrowserMatch "JDK/1\.0" force-response-1.0 # # The following directive disables redirects on non-GET requests for # a directory that does not include the trailing slash. This fixes a # problem with Microsoft WebFolders which does not appropriately handle # redirects for folders with DAV methods. # Same deal with Apple's DAV filesystem and Gnome VFS support for DAV. # BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully BrowserMatch "MS FrontPage" redirect-carefully BrowserMatch "^WebDrive" redirect-carefully BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully BrowserMatch "^gnome-vfs/1.0" redirect-carefully BrowserMatch "^XML Spy" redirect-carefully BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully # # Allow server status reports generated by mod_status, # with the URL of http://servername/server-status # Change the ".example.com" to match your domain to enable. # # # SetHandler server-status # Order deny,allow # Deny from all # Allow from .example.com # # # Allow remote server configuration reports, with the URL of # http://servername/server-info (requires that mod_info.c be loaded). # Change the ".example.com" to match your domain to enable. # # # SetHandler server-info # Order deny,allow # Deny from all # Allow from .example.com # # # Proxy Server directives. Uncomment the following lines to # enable the proxy server: # # #ProxyRequests On # # # Order deny,allow # Deny from all # Allow from .example.com # # # Enable/disable the handling of HTTP/1.1 "Via:" headers. # ("Full" adds the server version; "Block" removes all outgoing Via: headers) # Set to one of: Off | On | Full | Block # #ProxyVia On # # To enable a cache of proxied content, uncomment the following lines. # See http://httpd.apache.org/docs/2.2/mod/mod_cache.html for more details. # # # CacheEnable disk / # CacheRoot "/var/cache/mod_proxy" # # # # End of proxy directives. ### Section 3: Virtual Hosts # # VirtualHost: If you want to maintain multiple domains/hostnames on your # machine you can setup VirtualHost containers for them. Most configurations # use only name-based virtual hosts so the server doesn't need to worry about # IP addresses. This is indicated by the asterisks in the directives below. # # Please see the documentation at # # for further details before you try to setup virtual hosts. # # You may use the command line option '-S' to verify your virtual host # configuration. # # Use name-based virtual hosting. # #NameVirtualHost *:80 # # NOTE: NameVirtualHost cannot be used without a port specifier # (e.g. :80) if mod_ssl is being used, due to the nature of the # SSL protocol. # # # VirtualHost example: # Almost any Apache directive may go into a VirtualHost container. # The first VirtualHost section is used for requests without a known # server name. # # # ServerAdmin webmaster@dummy-host.example.com # DocumentRoot /www/docs/dummy-host.example.com # ServerName dummy-host.example.com # ErrorLog logs/dummy-host.example.com-error_log # CustomLog logs/dummy-host.example.com-access_log common # puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves/000077500000000000000000000000001470345337400333545ustar00rootroot00000000000000agent-email1.example.org.issued_by.agent-ca.crt000066400000000000000000000025571470345337400441470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIID1zCCAr+gAwIBAgIBBTANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjBE MSEwHwYDVQQDDBhhZ2VudC1lbWFpbDEuZXhhbXBsZS5vcmcxHzAdBgkqhkiG9w0B CQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQDIKXR0WvZcBrJPE8JFaKB8/CMi0jUshP3f38O4YcBh0nF8AcAwwC9/iLFe xXHY27lRO1V0XpvebRzlFDMSoeqS5wGYge7ola9t5nR0njwWAfsAIe/dt9ZdJuxn mk56IQV/cQXw8h/qHSZP2/utmHycWRkHY5U4VcAZX0IQwLBqk6+/ywxtl9MvIOuY 8yImz7BNwnm2ZfWhHm3EHqF7hOhPNnaOq0R4y0TCd+gUfdSF5t1KIQ7dLyrw2Bvd c472rGpM89oQRuw6YvYe8/K4XLbtyZs3FwAOUW5ijJwUIRQMPVuJj60TQHcH9mIm byL+ZCOI9DQgr3Swx05wMNddXSjpAgMBAAGjgZowgZcwWwYDVR0jBFQwUqFNpEsw STEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9wZXJhdGlvbnMx GTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/BAIwADALBgNV HQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3 DQEBCwUAA4IBAQA4q8Vg2LMKmvDy+Q+lBIZh6rbcTafMu//H9+AhPcGh1gR0J0Wj SDps/woYSle04b7MvwC6+yPCiT79nIpZBQ5jHIcWxnE9tQa7DcPuTyPyalNUlzuE 1Pp2cYkFiYMv2lGU4z13y8PynoL+vqoij0LPXa6SP4lhmbvC/qWkf8IF6C6kGTWB ZQTTOa0/MWirGlKDsUh4UygzpRICjO4ouzBKDTEmfLEZKpWiCY3WtrCWO6zK6OOa O85k5MnBXjV/Z2Yv9MRABZDjQaFtJ6zTktlakjOyqoPMaPu5aV7B2T1fN4myM1NB m+vtQqWUNYDOpTGk7QML5Bfz7LH/c5NohQbq -----END CERTIFICATE----- agent-email1.example.org.issued_by.agent-ca.csr000066400000000000000000000016741470345337400441450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICiTCCAXECAQAwRDEhMB8GA1UEAwwYYWdlbnQtZW1haWwxLmV4YW1wbGUub3Jn MR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAyCl0dFr2XAayTxPCRWigfPwjItI1LIT939/DuGHA YdJxfAHAMMAvf4ixXsVx2Nu5UTtVdF6b3m0c5RQzEqHqkucBmIHu6JWvbeZ0dJ48 FgH7ACHv3bfWXSbsZ5pOeiEFf3EF8PIf6h0mT9v7rZh8nFkZB2OVOFXAGV9CEMCw apOvv8sMbZfTLyDrmPMiJs+wTcJ5tmX1oR5txB6he4ToTzZ2jqtEeMtEwnfoFH3U hebdSiEO3S8q8Ngb3XOO9qxqTPPaEEbsOmL2HvPyuFy27cmbNxcADlFuYoycFCEU DD1biY+tE0B3B/ZiJm8i/mQjiPQ0IK90sMdOcDDXXV0o6QIDAQABoAAwDQYJKoZI hvcNAQELBQADggEBABdsPmfrkx45UDPmHZlsWwfLoY5HTFSC0TevLfPwraUXpg19 tj9cN3REv0meCi7OvsC9Gqf6HfisoyeBAdXR6DYIwTo+aWE/p8RR/cvR20eJlIE3 qcWlK1H0yylYKYhOzgNxWyXiPOsZcMt1o4WH5YREiDWza1VLV1lOTwk/lYYAeq0s juEkh9RZq1NOZsD2GuoLPAAs8I1lqQayVBXiJe9JT0w1+2t6xXNQVNYlitlV9DDz 5DMRqflqIKcnQT7WV9su/F0JhoQuMB/gw4ScAnRf1djP6TrIu9NeE8i943AdNn6L De8Isu+F/rGxCoObvCFOmudBQQ4oBWUe/CtedT8= -----END CERTIFICATE REQUEST----- agent-email1.example.org.issued_by.agent-ca.key000066400000000000000000000032541470345337400441420ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDIKXR0WvZcBrJP E8JFaKB8/CMi0jUshP3f38O4YcBh0nF8AcAwwC9/iLFexXHY27lRO1V0XpvebRzl FDMSoeqS5wGYge7ola9t5nR0njwWAfsAIe/dt9ZdJuxnmk56IQV/cQXw8h/qHSZP 2/utmHycWRkHY5U4VcAZX0IQwLBqk6+/ywxtl9MvIOuY8yImz7BNwnm2ZfWhHm3E HqF7hOhPNnaOq0R4y0TCd+gUfdSF5t1KIQ7dLyrw2Bvdc472rGpM89oQRuw6YvYe 8/K4XLbtyZs3FwAOUW5ijJwUIRQMPVuJj60TQHcH9mImbyL+ZCOI9DQgr3Swx05w MNddXSjpAgMBAAECggEAAaoels0e2VsQ5olyhyM8mm16WVLIMGuWtOLmfMULVYTr fq2BDKa8fmIDn5ciwDvriZpltocG4s2jfOAzIIeKLNiQ8dS6yOJdyBsvgrzCISi5 DqI5nW1m8fVd5+qnlmpp4kptUzigPVEqvWVF7YakGqS/CYmxdvt3kn5xTTRdAzXd aWSE3T8rrvoXml7mx7h0VuYvy0g1VGvYf5tsEONsNuMkFyqn/cJd4S9MRxBjoqwB iN/5ertVS83rSfvivbOtPCp75RVOTrMZqbFGda1bPfA/GA+ZQrPXYAAbDAWhzdcs rDCyvlZ5SQ1v9WCZgKqmfc7BwxvGtah57BYwugZNAQKBgQD9Pl+qtFDOVbCIBHbL YogcU1UoOoBm6G7cOqcVrxNXXdFTkEnp978Z6ZNdMzLLBhnGERiL9ebQyUHvkk9O NRYJYpj0qlzzp4C+uGr7OVHTKMgEBXXbt2GnGNHqshNZZ4Rn3mte5cHeX9bxbd9O 2EIhjJmPFimbvdpTv7ku8LYEoQKBgQDKVy1B5HnIL4EG06lclLopp4IhWhNNmop/ eYicF9b6fEREMxvClnyZ6bgr01ueX479caF5pZvzOGVHHQbKHAxPI8shueZ/2hcg AvuCFmFbaS4y/4Nl9affyb0E7x8wyse98tXkeQSlF5PtSPmSu2736AoN2luoXP8G o0Mi6+93SQKBgQCAHIfFEcc3Or49cRSvuz7kJXwVB9NhPACpRLq2C4WbUwjMX1gl FoIEl9dG9NmjP4jWXFuwokuMH+RNUBTymYR2Zvy9+VlgocJNuXnVcZ/lVOIqtqBy 8IhkQfgf5MpJFkczTJ/AuDalSpKwPEcV2e1Kj5g3fJy7/wVuDLWf+4H5QQKBgQCP BmI6QnsG0vVcUv9TLtoMmZg1ZQth/oxJoSm8VGmkc3R51LqZqG/5B6kkaWlIoHld kxW1/CcpHEMSqmTjNkJJKp7qfxJ8azePbCxF/vXgfI+ogs5pouSAHoTa2P/uKFha Xy1sK1LqM6lfwAaR/qVo3P9GXYQOlXW7RmotZCLH6QKBgQDfy1V0wSFjTJFOIW1h K9VoeT5HOf/lbnohVpxjEeKZLybV6EvXdxYDIgFOiBLN5SFeiyg6SyZHQBDAUGO4 vYrSPyaAdiX4GFWhzf3lfqrlm8krVfJ87KKoMg334aMdf42qRWBbFlZ3Q1oK1QSK 8vhrTD92eBqd2+9m4Kfs8FBSAg== -----END PRIVATE KEY----- agent-email2.example.org.issued_by.agent-ca.crt000066400000000000000000000025571470345337400441500ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIID1zCCAr+gAwIBAgIBBjANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjBE MSEwHwYDVQQDDBhhZ2VudC1lbWFpbDIuZXhhbXBsZS5vcmcxHzAdBgkqhkiG9w0B CQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCl93N93Sxm3Odr8PUOV7iQDDFy3399SkTSq6jGV1P9KIh2hszlSoLKYhKA PVlIlYvCcbVflsixHDcyd/8SywstNndhdIhM1mpi6QBhEtnOoFjfYTfbVKSC6PUl PoUIVqwumiB2VLiHCy5AHij1Ak7EMD/4gpvvVfGoG3j9jLNl+csu79j2yQYiDk9a wQkoI4dO4jBAdq983Hz3lfKFj1qgrwUMSpMsN3KMi/6osJTzdOFFe8UuizHQFrnh 4Y9/26zZGdgOd31kmb0Vka1c3+TIwr9JbiQqWo/ZYSX6j187aRpPCl6tvUqVPSO1 TPSCKHrkVauR8ZsuwgOGo+mR31VLAgMBAAGjgZowgZcwWwYDVR0jBFQwUqFNpEsw STEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9wZXJhdGlvbnMx GTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/BAIwADALBgNV HQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3 DQEBCwUAA4IBAQBeSAbhGhWQCclBrX8DYvQa+HvZIcsw18UILA2zuGvNoUgbWjob 3w8nMYSjQ6YGJns/H8jHOTShut8wsrKCRuEzI80LzYUF6MgpEDrxwlxbKQLBHg3K XnCNSEwDYVJOllIUEAK0TByPP1YFHtd2IdZ9kTticVJdmravZFM18SbLt4J6X/t/ EBuiJE27fdMqJSv9OP6PUg+MYakvBz3EGwzbjwn7NAB8OB+PPXd14Er2P8B1C8of Hubiv5Hk3NX5QbXGkoetjzRLkpXCaOZNkWPcWxkPMv7cVozpDtm7E1UC2i7BUdPh FAPv+O7WxDixLb9O5uuE4jnszg4Jhp7JfOqU -----END CERTIFICATE----- agent-email2.example.org.issued_by.agent-ca.csr000066400000000000000000000016741470345337400441460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICiTCCAXECAQAwRDEhMB8GA1UEAwwYYWdlbnQtZW1haWwyLmV4YW1wbGUub3Jn MR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEApfdzfd0sZtzna/D1Dle4kAwxct9/fUpE0quoxldT /SiIdobM5UqCymISgD1ZSJWLwnG1X5bIsRw3Mnf/EssLLTZ3YXSITNZqYukAYRLZ zqBY32E321Skguj1JT6FCFasLpogdlS4hwsuQB4o9QJOxDA/+IKb71XxqBt4/Yyz ZfnLLu/Y9skGIg5PWsEJKCOHTuIwQHavfNx895XyhY9aoK8FDEqTLDdyjIv+qLCU 83ThRXvFLosx0Ba54eGPf9us2RnYDnd9ZJm9FZGtXN/kyMK/SW4kKlqP2WEl+o9f O2kaTwperb1KlT0jtUz0gih65FWrkfGbLsIDhqPpkd9VSwIDAQABoAAwDQYJKoZI hvcNAQELBQADggEBAKR6UVOIL9SHpM7amIzCKmZARbWMuXN3FOfpl2Jo/5VHrrqy M5T2R45HJKD4tsNul/amcZ+9A878HAlXIAxM5DzyOXS5xJRiGYtcUhhTuVxDXesS Qlx4JAbaObhhgcoqYMlMqq8jPJtNNainEcrpGRH/yfwwJ+EwTccOYvYmPJavQWQs BYP1Xb8R0hLIByZpldQimjegpfurolvzonupdjn+HPWMENR/jgqUDgqB6Mke7hkz wbIM3Fa+lyvMvGH2NRNWNsD7h9aZll8UJD0zg28dGBaj3CLf4cVOVM6lOnizc6Wk yvGlHCV0tVcXoWMX11PLn4RtLEQ3jvFwymv1uCw= -----END CERTIFICATE REQUEST----- agent-email2.example.org.issued_by.agent-ca.key000066400000000000000000000032541470345337400441430ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCl93N93Sxm3Odr 8PUOV7iQDDFy3399SkTSq6jGV1P9KIh2hszlSoLKYhKAPVlIlYvCcbVflsixHDcy d/8SywstNndhdIhM1mpi6QBhEtnOoFjfYTfbVKSC6PUlPoUIVqwumiB2VLiHCy5A Hij1Ak7EMD/4gpvvVfGoG3j9jLNl+csu79j2yQYiDk9awQkoI4dO4jBAdq983Hz3 lfKFj1qgrwUMSpMsN3KMi/6osJTzdOFFe8UuizHQFrnh4Y9/26zZGdgOd31kmb0V ka1c3+TIwr9JbiQqWo/ZYSX6j187aRpPCl6tvUqVPSO1TPSCKHrkVauR8ZsuwgOG o+mR31VLAgMBAAECggEADRuWC4LEVvtra6MEN7XF5dqQrTnpn8OV2+2izsdm4r+o x3OuCw3vdnx4aZhuzMTC3QCOCpamExbfZSUFCD7xCwkaNKA3g5oLnPQ6C3CpsyAG 5N2Qw8nTlGNBuUdOynHN94BEwBPA3ymK5ZV8Np2QCv6kjsQB/M0U4OoKjDvoj00i lvcUJeKvPcpae8fxuCmjfUUkxjquZh7ussUTREA19GUpD0SzGlFs9o4XRVTS63ma VYENqXXRGH+sBcAtJ5bQswQpyxM1yZ3SvMeuvHD6z5VRV9kM3IvmUsVQjUBf9M1F BECbZYtyFp597/0tqoxeQxcbGPlmtR+MaI3IBrW7QQKBgQDbpoHBLVU9nQgHsGAW whGoEHdni4dK6V+F7de/oQck2mydZX2/5ozAONdKnmIVhUI59m8/cR89F1ruyYY5 Rt8Znm+gVuQnZJzp4JziwAZK2oOlbxT1FbaaD+bIO84mNzhWB+lH/Gmp53rs57Nj NV7OcaoD7id5jddRm27C0irU3wKBgQDBbqD7DZDPOPoAJCAuI9OSJEV9XLok1U0+ 91r7bthsJkDytY0BN/1tex8/Jc0ZulbEofj6VsVAYNs5ODLVpAR5a3zfhRPjBClS FsPzKbkxcf+/YldeSNThrGn6szwE7WDy5FQl0dQ9Q0tJeZAv+mMnh2ArylfMPICU PQDk2FkBFQKBgQC38yE1i+aYO/tunQpL5Olui6PEBrkeRoWmHwMRTCU0eux9gHKo lMcJcFD0/+F6zmghLL4MLouP2RBhbEpJi43p4aLwb/SQ/RTgVShuSYy7gXbAxF+T xURwj6KhzFwf6xz2B5gZnk1Laj2rS3wTOK4WTGCq+/b5OI27nWVMKUCPlwKBgQCT TyL9zoj3p1aNAPYY7WPUqhbZr+J65o6bY1lAnlvnkQJpVGX8BZ3U4K0dNDaMX2Jx AUFRtP8nVhvd6bSdCvn1ViyVNQ2+F484WuoDp0TIKR8xqz0KKsEk1F8pc5JD1lu8 3rJO0wulVDhjzlZGk5MrqWdOMhzHB1SMkCC8Jx8xOQKBgQCwiiGdXo8OjhOBOP7i 0lDfH1vjY9XiVyyOLgLnyd+LcQZs0c1B3vc+fX29WGJMLENLeGfuRPD+tE3dMYTV OV0BZ1+EM07s6zeVBdfNE7hPqTUY6Cmn30ajm0ECFDP7H9w3RvAdTdVJ8pAhyTgy KF1hWgqSdhKqd+epUTWV8kgBDw== -----END PRIVATE KEY----- agent-email3.example.org.issued_by.agent-ca.crt000066400000000000000000000025571470345337400441510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIID1zCCAr+gAwIBAgIBBzANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjBE MSEwHwYDVQQDDBhhZ2VudC1lbWFpbDMuZXhhbXBsZS5vcmcxHzAdBgkqhkiG9w0B CQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCqcD47G2JXhzySuwJX+2jkDW1CFe7WrmWtTaeneszgSz2juuFA39KGS2lC /RBU6okPwhYoaCFLZYTeGx7NNaUYc+GJf//IMerzqbXTLsjh96686+7Iwqjn+B5O Z3XfCF2quEC1g/uT+/ziqN1YmRMzMGXMlSQGp17sCP0EqW4Xcry9fLhCV9Z9kJyJ fxqIG8fmjCyhUwL3x8iLmaRVFovhfLvyNPLLYkOcpDdeBuASn/7/rtV+bWfVWd/Y a5wNqvIbtlp/FUt7VZ35B66SXp3yF1kaVl159BbkL2xzThch+0rRUH6OD3UyOv8Y Ubmkl2Q7ykNJNh2nKwtNIqPt5PZ3AgMBAAGjgZowgZcwWwYDVR0jBFQwUqFNpEsw STEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9wZXJhdGlvbnMx GTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/BAIwADALBgNV HQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3 DQEBCwUAA4IBAQCMrpNT6pqqkKn+usB8sFWIcASP3OTnaEQVCpnoCoudrB4UHDZO oQzzY3Ys5fcTK7rnXS7J1daS6Qi1g/XSiTCB8xVWXjz8uQtXGQXjVWNpxI9clFyo IJBZ7Cm9h8QatFIF5G+e5E8G7HEe4Cx88ESAAuQ2cnJsARRB7DyEuegPqZunGc1M T6Z5Y4Xn45zorp+TLLjE5zbrInrNeaVzcqFQYpMbzvFoWwba8G/1YobKggNIgLk5 rlqUKrZKawRjtMHBnIJf74RLBZ8qQezycIUso8vTi3is1BdRgSfPEdlWAxIwyOoj uSnhq4DT4QfDZK9u1J9e7pxthhQdEW9Eo6/v -----END CERTIFICATE----- agent-email3.example.org.issued_by.agent-ca.csr000066400000000000000000000016741470345337400441470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICiTCCAXECAQAwRDEhMB8GA1UEAwwYYWdlbnQtZW1haWwzLmV4YW1wbGUub3Jn MR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAqnA+OxtiV4c8krsCV/to5A1tQhXu1q5lrU2np3rM 4Es9o7rhQN/ShktpQv0QVOqJD8IWKGghS2WE3hsezTWlGHPhiX//yDHq86m10y7I 4feuvOvuyMKo5/geTmd13whdqrhAtYP7k/v84qjdWJkTMzBlzJUkBqde7Aj9BKlu F3K8vXy4QlfWfZCciX8aiBvH5owsoVMC98fIi5mkVRaL4Xy78jTyy2JDnKQ3Xgbg Ep/+/67Vfm1n1Vnf2GucDaryG7ZafxVLe1Wd+Qeukl6d8hdZGlZdefQW5C9sc04X IftK0VB+jg91Mjr/GFG5pJdkO8pDSTYdpysLTSKj7eT2dwIDAQABoAAwDQYJKoZI hvcNAQELBQADggEBAHsn0ZZ3xnuaSGhRhjNFexlCKI/UKSLiAcDQQzegBjAIP8xG vOxaUx+VE6q6m1/H4naZkB47z/agFK3ne7lCtlugJOiSmONgRWyE5S2kF+K+76S+ 5hl3G3zrdOWkTteSd9XTEoLJ78dLdkneSWXgpvxbgGpMUb1CJcsacpXymBXGXgwK oOiOntggQwCOyksOcSNY1C/Q5nXe9eV+YS7C5RR9rsa8Lr1niuBMgsCS5YDOJLY5 495fJzohhykfIrppWrH/pGCkT7/I1fpJtTO+DetgSZZyOILxls/c5Qrjv7J/CZVK V0BkcpMElGGSJZwJHWNtsIHMqic2NvBtxifhW3w= -----END CERTIFICATE REQUEST----- agent-email3.example.org.issued_by.agent-ca.key000066400000000000000000000032501470345337400441400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqcD47G2JXhzyS uwJX+2jkDW1CFe7WrmWtTaeneszgSz2juuFA39KGS2lC/RBU6okPwhYoaCFLZYTe Gx7NNaUYc+GJf//IMerzqbXTLsjh96686+7Iwqjn+B5OZ3XfCF2quEC1g/uT+/zi qN1YmRMzMGXMlSQGp17sCP0EqW4Xcry9fLhCV9Z9kJyJfxqIG8fmjCyhUwL3x8iL maRVFovhfLvyNPLLYkOcpDdeBuASn/7/rtV+bWfVWd/Ya5wNqvIbtlp/FUt7VZ35 B66SXp3yF1kaVl159BbkL2xzThch+0rRUH6OD3UyOv8YUbmkl2Q7ykNJNh2nKwtN IqPt5PZ3AgMBAAECggEARg8LVYqFGwuI95uNdBLw48UtIxwW6AIZ42nnP223536m ILZBv0QBqpg29YVGgFFD88lJCGT9QpvBSPcG6z1g1rNTgwytXGJAfNZG2j8B7fi8 yAWHStjRS0DvXDUk+3/Z2MISP0q4T/Ul1xmomrGZddIwFi879sw3tXhgYNkwWsxv yaTKnh8OPSCE5phgi9WRbd4ZOzEu58Kb8Bowi7flN/M7rj8WN/jPBd39IUmYv882 dEx2ws+iliqKCrMn4Us6RsNDJf100MMeJ+l7M32/e6eB/JuVNpU9ucdvJIQXJCJS cbC6uvjAE5hfKD7HmxjrlcT165yKfperlByVAVP9cQKBgQDiMNMXrCds7LfpMZ7L Ie/GuVyO7kbJ8Jw9kenwPhSvYui67hxpSmIEXvV2hMQtKbA8E0qbrmK5DOO6x7DP C8QtxP5YuYZzu3fhT9T3aVHJ0gWBaW2VBYIu10hgudG+NxZiJX0HF1YBWcTzqkts kkC4wpADkYnT+4+EmC4ImKCZDwKBgQDA5nXB+KvaLvzGA/ZnNiSUjbsgvgnpoaK7 VD+NkNclaXye5ylcyE+T5XUF3bEHHJhQEN1XItsu51q6D1JFuBm50a6NZWud/3rD tjrn65Xj0gDHVdsqwHbYVRNvUOJw2AbDLCSKtcgMcM7j3PZxKj4z5p7NdUMR8ZrN ZsESN0G8GQKBgC2j/HRCYJIyEcoUIR6L8n3+2RZeLhqBWoVx8+puHG5nXt6ZPVJh l/WZ053enFcgmlcE7YEMZw8/8pO1x49/qE4z+b6dcOvZYA8utKJXthErN8EtLNdt DR+2gPxDgncHVpTnS5sqskgDfSJNsnpt6HFfkP+nVlBX6lWu/1rssTsxAoGAT2RK oQvUxxbBqEnnNvF8urteggpVEBgbXtg80+oB8n7o8ImZZ3t17RvqPwDQJGorcgCO 6JcK+NH1cFBv/wvXYrgfDEjqsvt8LmKo+dznMv2ynlgCvSS7hSv2tMDogaMXnWpk m8ZXUG95ZyUBNPA666eGQm95rD/xA4q/+dxOLLkCgYEAkkGgQQftl67cw14iqW06 T6dOkt38TTalM7ctGJmvMIdBf4heJjhTBY6FChkgTBRP9h2VClXHCDHpbr2+vWYh lGD7QQltNp2IH4VRLe1DP35DOqF9ZeDPML+C81TqyS63+Ev9RJOb02vaoxwzuRli 5ZGbmT45XuebdLvyVX7BPGI= -----END PRIVATE KEY----- agent1.example.org.email.issued_by.agent-ca.crt000066400000000000000000000015331470345337400441410ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIICTTCCAfegAwIBAgIBBTANBgkqhkiG9w0BAQUFADB9MSMwIQYDVQQDExpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UEChMQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECxMRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMTMwMzMwMDU1MDQ4WhcNMzMwMzI1MDU1MDQ4WjBE MSEwHwYDVQQDDBhhZ2VudC1lbWFpbDEuZXhhbXBsZS5vcmcxHzAdBgkqhkiG9w0B CQEWEHRlc3RAZXhhbXBsZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA1yGO Vq1tH18qqfGofLz4jsQK8L1+sH/Rqv41YwsOwVEvBbvDLhbaokbqdPj49Oilk8jd 2WCFhfeQR2EHYwDbvQIDAQABo4GaMIGXMFsGA1UdIwRUMFKhTaRLMEkxEDAOBgNV BAMMB1Jvb3QgQ0ExGjAYBgNVBAsMEVNlcnZlciBPcGVyYXRpb25zMRkwFwYDVQQK DBBFeGFtcGxlIE9yZywgTExDggEBMAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgWg MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQUFAANB AKAeQNxCcQfbMaxxp84Qqi2dTUKnKE4IKOOCgQEPIE9gzZ5Tjig2bJIBfer3hXia Mudl4EXigQpy2zJ+CIE/Pl4= -----END CERTIFICATE----- agent1.example.org.email.issued_by.agent-ca.key000066400000000000000000000007611470345337400441430ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN RSA PRIVATE KEY----- MIIBPQIBAAJBANchjlatbR9fKqnxqHy8+I7ECvC9frB/0ar+NWMLDsFRLwW7wy4W 2qJG6nT4+PTopZPI3dlghYX3kEdhB2MA270CAwEAAQJBAMsqgYYSGm/6LAx6kCfd Ps91DO/1xWNiEtxtXnW+x5yAFjdiM0uhRupci78kHJ+00dDqPGDHpWkmQ/bqzdHM A/ECIQD+b+ezEA4sUfiSHRkfH4EsBMtDAxS6NyrEk8I1EQYukwIhANhz1+PrDnpI BO0ql2sIaAO333zYXTT6JAyWBs2zou5vAiEAkw4uhknDR05hMmHrARf+Wmiy6ho/ wpjb+R3FY1Jhlk0CIQDJPyO5+EEUtkNGUvRHgqBa3KmAxRYb/Hpp7U9UD7HsJwIh AJR9GTJSdpPz7HSS2GtBxK2AlwWvqIj3zLyL/u4aZRJs -----END RSA PRIVATE KEY----- agent1.example.org.issued_by.agent-ca.crt000066400000000000000000000024721470345337400430560ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIIDsDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjAd MRswGQYDVQQDDBJhZ2VudDEuZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQDa8oNyLxOwgoJa0thHlB3CPLAm2mcrStPD0RHmHxlRihsa 3BrGdvOekD79eBi+7RmIsnRpUL0F+7oCS7skQ4z+TkS3hgoXyOgTgK8UWY3osNny B/Y/61KIzCIlZXXey2sQYx6jsaxxsyfrs/ErdFFYbEE1MLvRJadSw3MTcML8WhCH S0jB2DVp9wmKDGWtWHBRFpvkxwGt2u4Zlux9iVOz4XPNxxh19W+vFBms9DQDmJmN c3X0ZefKlrilKdXMg2BkFEIawMRVJgfNvb5uoAjik6KQdFG3Vnt9VXMwDmO5DmXT wElOKAwqouGeF9qp3t6DPLOylyIYjeC0uPbCy6ETAgMBAAGjgZowgZcwWwYDVR0j BFQwUqFNpEswSTEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9w ZXJhdGlvbnMxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/ BAIwADALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC MA0GCSqGSIb3DQEBCwUAA4IBAQAmSiSyp5nlk1Cwn3Rw23bqCIQ/WlZzJE/Uh1+Z TuiwVbZknaJ0gsZELmkFGsvX56OS0nTPUyl6m3Ct5vCAX33nhOH94njX5yFte1sO zT3AkJZqz4elf5Li+aGvgLplN04XH5snnw23c2cwhbTu3GwZok07MpUp09jonNfK RfV295tTfC/L7+XXz9uOPwI/oCNiZNTbpl+pshXaG9t2vtDiIgQUWF4jXzWpUu9I wFo48IM1OVQrujb3LliD4fLZItfJK/xJKIKixTxrPy0Xu5zdz7DyTBJnvZYiUVtU 8CKZR+5wtc8aKdDxfNaY7nORiZEyd/uprVb6okCpZnVxxXum -----END CERTIFICATE----- agent1.example.org.issued_by.agent-ca.csr000066400000000000000000000016071470345337400430540ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICYjCCAUoCAQAwHTEbMBkGA1UEAwwSYWdlbnQxLmV4YW1wbGUub3JnMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2vKDci8TsIKCWtLYR5QdwjywJtpn K0rTw9ER5h8ZUYobGtwaxnbznpA+/XgYvu0ZiLJ0aVC9Bfu6Aku7JEOM/k5Et4YK F8joE4CvFFmN6LDZ8gf2P+tSiMwiJWV13strEGMeo7GscbMn67PxK3RRWGxBNTC7 0SWnUsNzE3DC/FoQh0tIwdg1afcJigxlrVhwURab5McBrdruGZbsfYlTs+FzzccY dfVvrxQZrPQ0A5iZjXN19GXnypa4pSnVzINgZBRCGsDEVSYHzb2+bqAI4pOikHRR t1Z7fVVzMA5juQ5l08BJTigMKqLhnhfaqd7egzyzspciGI3gtLj2wsuhEwIDAQAB oAAwDQYJKoZIhvcNAQELBQADggEBAHb7MMkCcYBMjtVscja7jHrRMPRJmiqL8jmh Y0JRrS3u7zUK/8IDkR5lbh1O3/Ou5UKCWdrkC0aaqv/xhP+oFcTCi8bj59nsBZin 35tkfnWlGuf5T5bbp7P+/7XzynUciEULCGwvLVS9V8xDY5z5FvHx9IFyzkPMQXJN uuucShja9jVTqN2x94jkjXSX/dRPKnHdE2p3jExgRddwGYNGvCgoxK8oHN7wspT2 Sze5Lxt6wIW8xbZk5yhJUdNYdyYiK0FZ2eIvE6LLA1ZI+VfFb4O1lxR6g1OQ93v4 0LQ40jPU5JlDaPAalJzIv+/9SRB9OEavo61TZSD6dRsiMumG0r0= -----END CERTIFICATE REQUEST----- agent1.example.org.issued_by.agent-ca.key000066400000000000000000000032541470345337400430550ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDa8oNyLxOwgoJa 0thHlB3CPLAm2mcrStPD0RHmHxlRihsa3BrGdvOekD79eBi+7RmIsnRpUL0F+7oC S7skQ4z+TkS3hgoXyOgTgK8UWY3osNnyB/Y/61KIzCIlZXXey2sQYx6jsaxxsyfr s/ErdFFYbEE1MLvRJadSw3MTcML8WhCHS0jB2DVp9wmKDGWtWHBRFpvkxwGt2u4Z lux9iVOz4XPNxxh19W+vFBms9DQDmJmNc3X0ZefKlrilKdXMg2BkFEIawMRVJgfN vb5uoAjik6KQdFG3Vnt9VXMwDmO5DmXTwElOKAwqouGeF9qp3t6DPLOylyIYjeC0 uPbCy6ETAgMBAAECggEATiG6zJWGJjf8gqK5MZnmoLj9d2/63xUdysQh6gfxBgsN ryEaoPYz68K358XitsdvlDtylV6NhcQV1dnml4NPnjSaCw/XLDOytbr3P4DRxlbN /7PdqWO1mUGXcdbqIC5hL4DfnzS5P/3Z4h/dkU859B71iiCw9WrFciBzQV29B0YH n29XP9xHistbBZ1Kygp9uAF2VZPKr/b9ltCHc/h2fC+OuIFPem2sOs4xkUbRY2Ob F77E6Q8i5xhZNcsLwp39r9pOUyMDoaGRsZrcBynxL0FIk9gr6goUu1SmRdOAuX8l noORneVcxR7e22gd9eZSbaNruu7pCs1hGzx6/LyYaQKBgQDwoJkwWH9/FpKV5kbD 5AHtXZHvHU5XoivqisSWdLJNKJCXxP4D+v20ziszwlI+cS7QtfVTv9JLbAnW5nFl eIIJYjbTOfZKKvXoffUzAOiA+9XVJhDN6TGX0ylUx6bdkR+IYMCO/bqTJVPyrt4Y E1460uYYIPp8jx+pZADgf9WOJwKBgQDo71f3pa0uFn/fxGNtwVrkhUxoT1iF7PjU UOW62uCnPTEmNJePMNDt5NAcmU8IvI5tZJdmveLJFQ3vTky17ZhGQBKWD5JNt0hw +tAAyHj9uYGh9+/9on2RQcB6SRQj8jtuzBlwaTMAY0OSRXt9A2okKljNyUym1OZ7 yc+hQTQVNQKBgQDG+ubydZwoyc+5qUzHXFrDoGa3JrLMAMz0DIB4MlPnPi4jcsDj JcB6rSpIiN5dyFaAPJd8A9mwiMyyKqmG0VomzFKt5PZnapMjCFWlMZESaC3xLqMi wz1BYVqCQv8XpZQ/wFI7bFHGsE11F2mM2ydG2XNwbIT2T5xNBOc8vjkobQKBgQDG e8wVddNPxlRINGwVBgGRYBRvfc0MsZSGNjjLM97iIr5Ss9XBafNeAu9irzAtXZ5v kJuCLKOmfI5XL/0luMNceRRdUf90wYy02MONJ0YRzZSskzyof2FH+SMuED9dMfd6 veefZcTTu8HETfif2d0D3CG3mKP8NMYBDUIjQhBDUQKBgQDuPGcH48BRhibhzY6M 8jmbAmn23+pfqb/Te3Nut1UpaNFOExSu7WDD1QWRjqHwysV4kMGQQaH9gwk7ydjk O5Qu6NMxz2jzmJBJwXhiAFirrfNs6DSgdSFZ/9Xx2bICWFge80wUP4I0XCnyt/f7 xCTCfGsaffgjGa0a0THnmjwS6Q== -----END PRIVATE KEY----- agent1.example.org.issued_by.master-ca.crt000066400000000000000000000024761470345337400432570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIIDsTCCApmgAwIBAgIBAzANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFow HTEbMBkGA1UEAwwSYWdlbnQxLmV4YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA30VndhiWyA0M9LXkutDYYdN9W945RiHn6mjBrCaTyxYh GunD7Ub2mjoivkgSQt3NlQRRI8bbgKGXYuAJD8tFiZtBYbh394mPHBS3j/cbkc4k mbnO2v2nR9DUd2TgHJ/gpvSQij7ullKpOc59h36wNAtKtlLpacEEdd6rJBVwIDOy oUlfO5lW/8Aw9K6nh/SuKLV7a1qIu/s4Lkv+8tQpzkgrnRPh1Nd0OJpoXNuBOfx4 Nipj07yGV6PWtBWAvOkKXSC7ZxudmlUFc4UHPwLZsh49xjZJGSrspJETexknu9pA FGqXAqE2kJhAWtehOiy7TKbIuOj1qKE+nEm1Ru44jwIDAQABo4GaMIGXMFsGA1Ud IwRUMFKhTaRLMEkxEDAOBgNVBAMMB1Jvb3QgQ0ExGjAYBgNVBAsMEVNlcnZlciBP cGVyYXRpb25zMRkwFwYDVQQKDBBFeGFtcGxlIE9yZywgTExDggECMAwGA1UdEwEB /wQCMAAwCwYDVR0PBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD AjANBgkqhkiG9w0BAQsFAAOCAQEAHwlUEuXe8jtnvdX49q3JVYs/wu+NsMg0+jHO 3JKWHz+2xjOYrWK1CgoAADAXE7/KH/7XPho9EqSlR0eANtUvHcOLuruYxrQgPX0T nkyjLLEF4Bc5rh45XrDtZuvHbhtqhEKMRs9yjlVCCKBUJF4mVH3dNapSnZaXfSOh VsmK0Ylt2iP11zbD4ncOnCCb4GKIqi0QW4rILdSHy8L3NxWCKP5QV7G0dQAYw0TX syfA4NvG9SgGA/tR62B/+IO62ZYPTBdVceTWZDs1DolimM5g80DTl9kz3nLaPvNv k5pnJWP5FV07PVgEf6I5xVok+l2wibewBBTAROa9I0FMfK/k8g== -----END CERTIFICATE----- agent1.example.org.issued_by.master-ca.csr000066400000000000000000000016071470345337400432510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICYjCCAUoCAQAwHTEbMBkGA1UEAwwSYWdlbnQxLmV4YW1wbGUub3JnMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA30VndhiWyA0M9LXkutDYYdN9W945 RiHn6mjBrCaTyxYhGunD7Ub2mjoivkgSQt3NlQRRI8bbgKGXYuAJD8tFiZtBYbh3 94mPHBS3j/cbkc4kmbnO2v2nR9DUd2TgHJ/gpvSQij7ullKpOc59h36wNAtKtlLp acEEdd6rJBVwIDOyoUlfO5lW/8Aw9K6nh/SuKLV7a1qIu/s4Lkv+8tQpzkgrnRPh 1Nd0OJpoXNuBOfx4Nipj07yGV6PWtBWAvOkKXSC7ZxudmlUFc4UHPwLZsh49xjZJ GSrspJETexknu9pAFGqXAqE2kJhAWtehOiy7TKbIuOj1qKE+nEm1Ru44jwIDAQAB oAAwDQYJKoZIhvcNAQELBQADggEBAHsE+gAgj/uSpCso9Q8kPIpAj4/+KKqK3gfm 3JSdet8/Cu7BCujHFO5QWmgufGpUb3vrdVu30QDK1l7qQynwh9FVdoyPab8d4FAx /4kjh964VmFRjBSS4hflwgdaTJ/px1CcD0+l+HSJY7rrmM+r1AObIs/Nuon50o+P 3orjdir3lBacV35nXTnQ6MN4XCPj8Er/k+1KqAzERz+NxkAgrZsFIFdb3qzt4uPG 9iODdBahzUEE1bAkABXS3E5cguL2BfaV8NcGwxrEMZWwwgl0CW/jVjGkzS+StMgx //LCjgsdpRIWLnUFuJQxUegGu/vHv4H5c3ewcVwXn87eto0s8ag= -----END CERTIFICATE REQUEST----- agent1.example.org.issued_by.master-ca.key000066400000000000000000000032541470345337400432520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDfRWd2GJbIDQz0 teS60Nhh031b3jlGIefqaMGsJpPLFiEa6cPtRvaaOiK+SBJC3c2VBFEjxtuAoZdi 4AkPy0WJm0FhuHf3iY8cFLeP9xuRziSZuc7a/adH0NR3ZOAcn+Cm9JCKPu6WUqk5 zn2HfrA0C0q2UulpwQR13qskFXAgM7KhSV87mVb/wDD0rqeH9K4otXtrWoi7+zgu S/7y1CnOSCudE+HU13Q4mmhc24E5/Hg2KmPTvIZXo9a0FYC86QpdILtnG52aVQVz hQc/AtmyHj3GNkkZKuykkRN7GSe72kAUapcCoTaQmEBa16E6LLtMpsi46PWooT6c SbVG7jiPAgMBAAECggEAGeGkvabaC7SflNpk+lbtTmHCvVyETSHvDVg5YyhRp5AY JFOG18GLIpOspVwbac7mXujSMxCBL2cL8nU/96m7lNj/ekF0/qfehAXOxYyCkKNR 0NQeK3qN4qBNkM2LwSWzWAcvnibvZ1OLtFzAZm2EJXRNo9b2ocCzMKqwMg2eIs1D 7Y6jc6NshteDR3aznOSilDR1keC+upG5ovMHdKjKgiueQ22Cyin48Xz8wkXRVcYd R4AdX425lj2YN7ZX4jFuX6TmPbUnU6D/p50V+FGc/mSpiwdP/5Ye+PXfBSwdYikm YMYU+V2+i7dy7LwoS7ZP8jiORcSDjrUrpkscvFgIYQKBgQD0ibbBc10TBEoWnTOb WDqERnxC6Ly5xpZcIEjxEwYUgAf/xo1nMgBKr0sJAud7vd5MI0B2/sLqBEIIAb+8 Jp7c0x7fF6FF72buXH6//1AOTvhQO8kIzgC+tTuLcOZjtY2HdRhfqPo7++CYVdf3 C1e7eiNutBYSZhD2tja07yQqEQKBgQDpvIDBoIKe0mH7PV2giVquwiRnPMA6Eobr vCwER+wI32Gvhry5hs/p5mKJu+0Xy91eu/X+OySAuoYmziZ4YQDd4CmgpTmKfanP OekCW4NN3SUNzLbyWsvf/WQoIp/cCqmSyFlm+78tNnc0f43EImktxIuf5YanK31u kV3gUJ6YnwKBgQCWXCs0beP38nY/y29VAH4SoWh8l7CbpmEDypIvMVxWtJa2jfaa UmNdiMVhiBifvJJ4TGCyCln9HJshYznqzfB2pZXg5R2z681lmRgSpEEsWyBR7UDi mhBZMwSm68et3Y9lj/lpsHQU9/4UjQwbCi1qyGILCs5bh8i8ejPPMxAQkQKBgQCF h2sHMutsUEQpg6U5UT69F6w0TkCC7JKnmZiL2Yq+ht8Hp7GpS5r7xOIGTZXlQlH1 DOw7kQ4JfIWnJZ5UpxYXqzgczkdRFvkrqamz7xPUJ8JDX/AkBDr0e438X8tzqaO2 dz6b1rYg3jy7gSM8KWxs+RvK/RUv62h9Ag7fVy9DgQKBgQCWXj/8MTmV12VRP5OI Mg2jT2rH6AoLThg7ILOJtRUHFetXxiGsN9RTeu42budtNkZy1RQRB51xyJU76lyT 1TDBrFdeUL1OW1YgSgg7h2K/5mn618O6OqGpaFxXL9l0YRwNXWo10Lv8PF+otZ9G ztAEC8EKtu0Fj1boLrLkQ66HBA== -----END PRIVATE KEY----- agent2.example.org.issued_by.agent-ca.crt000066400000000000000000000024721470345337400430570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIIDsDCCApigAwIBAgIBAjANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjAd MRswGQYDVQQDDBJhZ2VudDIuZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQDs8wg1+xrBWHcp9d4b3dbIqHQiuYtKbXlGU52lKoU3vArM b2lu39EWMXrxg9Dn3joI3X8nUynGlB1mHvog6/RXggw2T5WtPIviAMIR3niQWS3g YrgpT90GVeIPIiuVh76IUFnz+a9wfxZ3rsXRU74kXOzWXVZr2pSH1HjSpWmR6Hgj HUPi7/CRPL/V+/nvyY66cvxqgtOchGYhZO3+0zeGnXzVlXwdleCQnJ72EAOIyvQh rJhKiHvYw9/ZTD3VMHntBUu/QFB6a9ILKxggB3iOQXE2HwPBqO+cJfoi4qTpywE7 MOdI0q6MK9pr6r8TAGAlEPYoImbUFHIehJmPvSZDAgMBAAGjgZowgZcwWwYDVR0j BFQwUqFNpEswSTEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9w ZXJhdGlvbnMxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/ BAIwADALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC MA0GCSqGSIb3DQEBCwUAA4IBAQBPtNXbJI3C0/8gHvB2g6tfSGBHVvOH1lRpQ8FY EYW4m8EubV0cFdDpd02/gG4hOiCYFOOcMFENGOTRGSIMDWUED7doNttxHFWxVOEX 6M98cTlTpWW3PThCru5Oa4CGFcGFbo8Khb4vvZv5vIwf8ShUe2sl0I3REZXUx5ad fQc4sXiiPdf/P1D9ppulz/UchMfg9sg0ZRjQmVmCBZvA4/P+rBS+T+nJQ0bfpTmV EOVG149Lt+61kotJmxv5/J2UYRneWBmRE7P8d8DTqhOHQI5cHICgVq5Jw9m7nGlS LB7F4lKYXXU/9Z5JVKtM7/m4+MfCHlQyocd0cL9laKseE2Ek -----END CERTIFICATE----- agent2.example.org.issued_by.agent-ca.csr000066400000000000000000000016071470345337400430550ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICYjCCAUoCAQAwHTEbMBkGA1UEAwwSYWdlbnQyLmV4YW1wbGUub3JnMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7PMINfsawVh3KfXeG93WyKh0IrmL Sm15RlOdpSqFN7wKzG9pbt/RFjF68YPQ5946CN1/J1MpxpQdZh76IOv0V4IMNk+V rTyL4gDCEd54kFkt4GK4KU/dBlXiDyIrlYe+iFBZ8/mvcH8Wd67F0VO+JFzs1l1W a9qUh9R40qVpkeh4Ix1D4u/wkTy/1fv578mOunL8aoLTnIRmIWTt/tM3hp181ZV8 HZXgkJye9hADiMr0IayYSoh72MPf2Uw91TB57QVLv0BQemvSCysYIAd4jkFxNh8D wajvnCX6IuKk6csBOzDnSNKujCvaa+q/EwBgJRD2KCJm1BRyHoSZj70mQwIDAQAB oAAwDQYJKoZIhvcNAQELBQADggEBANxNVI7ySbxEI3azUWdlKSU9MIVLC+gXIQww xYEU4zs3EhrwAI5TD+Ot/8vRSUO3LdSqSO/WiZTdxp2/MAUzyH/iLrcY287o/UAX RVkqiWxyPG9KnUljz9crHnYaV0zwtMBOKtvNEN8gah1X+y/iWjgO0y8fZsWOVzAS y1na8ZpVsvw1A61EuDrhwkprsyWJBCldeBBd0Epwaa77wHHk7IdHTepXE0bGH3pv EVHPspQHOxk93MEs4yPAysXu9GTSqnMtjiZKlMJ7qz3zgnkLBLVphQH/gIsmPRp3 BaEMFJM2LTZd3f26P/WG1VJDWE+s9kx2FBy6MTesAtmS2gj5n1Q= -----END CERTIFICATE REQUEST----- agent2.example.org.issued_by.agent-ca.key000066400000000000000000000032501470345337400430520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDs8wg1+xrBWHcp 9d4b3dbIqHQiuYtKbXlGU52lKoU3vArMb2lu39EWMXrxg9Dn3joI3X8nUynGlB1m Hvog6/RXggw2T5WtPIviAMIR3niQWS3gYrgpT90GVeIPIiuVh76IUFnz+a9wfxZ3 rsXRU74kXOzWXVZr2pSH1HjSpWmR6HgjHUPi7/CRPL/V+/nvyY66cvxqgtOchGYh ZO3+0zeGnXzVlXwdleCQnJ72EAOIyvQhrJhKiHvYw9/ZTD3VMHntBUu/QFB6a9IL KxggB3iOQXE2HwPBqO+cJfoi4qTpywE7MOdI0q6MK9pr6r8TAGAlEPYoImbUFHIe hJmPvSZDAgMBAAECggEAcSh3aWAsHN3kutNCaUh+RIG+RL8beEXjvuQ7yx8NU9qn xY4Haf3VWqXysthisfj8+jLdgKhEsSMXDygICCTnIctnjaBgOMVLgHkgNWxrY3RT Zm9+x6vuQBJPzS5iZhzXrz3AV7WMRUtMLYf3zMoTakY+jPkyRnuyp1OfB+obCqRx TUfapIszdifeKKzhqZDDD049Dr7F8JqNfqd7BTWH1lxH8BYeZtYbRFUT1EoNBgNr T2K7kzOct+Y8zFyYAL0D2L5QbhOvVL3vZGgmqUtCe28hvBBusVx/j3ObpZNDfoeC /zlbROeX4lUBCt/QYiXLV3dtvMCO9Yhkh/rH5qTK0QKBgQD2u+pEQQWP9vxwKJ02 hZ6j1xrUwn6lCjtO2+4aUVjRCfVYWUuKh+vDoxYFXZq1QTEbjjIkRkaNYi4P8sB/ r9LII6Obxlyzg9I7CaO+YVeKg9zapOQHb/fumIP3Cv9SPJ+i5QloIm8XV9HQiHuE ffdwuvMGIwA/tTHI8FuSmQqDbQKBgQD12QwpyToo1yT5FdRU8Ik0eD+hRsfUFEkS 4JZek0AWuNLixNcI9CIBnwyo3RF9U8jiH4KLAFq7caMSza9zgYHXwe/efmBnSUzR C2Fn1ZtNmnwrB9jkQcO2AljpYkOq/+u0If/Sh2w879Vfj5JoD2XXZ96WD6ZVufCp 3UVxi+KSbwKBgDWXjYPzx5yEnkJSYAuGrHWT9G0ALff1J/qyBJ7MyojlK9hb1O+r JEejNdZGhaMXHO6KTVPZu9tb1vt509woOZVlQFVGmb4YROKz7lAc3qHkkGUhabI/ 3M+Day6OwfR/3IDKVOe8ivq8BYPREVsu7T8cLEtJ8PTli4HEy28lNMZlAoGAGXLe T3UFEDU1HpOj5yb/DO9lpsws40c2ST32UtPrTm7TZaX6nHKpEoHkTZaUuORzZvTc Dod63OxmdQvVnZ9KUYtByUZLtGViDkGfU6BI8z+Kmum1CevE1pJnocEKQCk9vOfI E4LxMV2iOMIj5aGyaRnXcLEuBrG4t9yv05EnYwECgYBnPPyG0fX/gfyfv3kBzhcf cpVSLSQhpgzuxHUac0sCGTfa+O6u14inw1DeirrZQJTTmDAFfFThg883x0/rqbbi WDaSG0Sw0j/m0tJgkz1ENRwFg+5KBfjthODJ0EhvgOoNbK548boouzGe4GtGNuDn d/HI8SbFU33L2FdVWNoGyw== -----END PRIVATE KEY----- agent3.example.org.issued_by.agent-ca.crt000066400000000000000000000024721470345337400430600ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIIDsDCCApigAwIBAgIBAzANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjAd MRswGQYDVQQDDBJhZ2VudDMuZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQDImAML5qGenaZ1oXlNyDTnPg/0bq5ft2jTZjPTUijBiuYI ZqANvqjf+bicC+9LdQwpRoIm4hS+cnvaEdXSV73cWjgFzAFJTBYaRXLst8/r0QlU BNkHgDpgCFVwR+YIEmHeesprzId/uDE1tf13IRI1NpDgU+jlBH3wOiUDr8QbPWPG IUV4bbEzLCGoP2fO5Le5p8+NdRI7XCHo7ac8eRL90pyBFBKzdc93cYMI7PvimuX7 MiVObjil3FF+tsdkAAAJezLKlW2CKjRUdHCr5/2WIRpjiIs4k/hCDToBm+8ye9m4 3NWn68XMIOjCiXl8wjdbTA3z2A0iRE9hGh+pYhQzAgMBAAGjgZowgZcwWwYDVR0j BFQwUqFNpEswSTEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9w ZXJhdGlvbnMxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEOCAQEwDAYDVR0TAQH/ BAIwADALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC MA0GCSqGSIb3DQEBCwUAA4IBAQAJvTvSc/J7QUZXtwIDoRSpEw1BBb+AKsa4D4ui qQXxiiRAe+HkSVvDnYU6gDTiEwtjccC/78KYti6QKWsYXhdW298ALdP9guAL78Lt A1olS9hNLXMiqWWEGPu0UAmNuTpdiwYbTL6vb7tcgBsnXONS1N8i7N1SRNyGRURL E2h5n8LGupXtum71XKMpNDT7XKKh75O8jsfGwkl2g4DQKmU5+9X2RXX+btooIsBi xgsOcq6Tb1qHdZRvqH75iypj8osiy+4cflgvdjuElHBvIlFRlyJyJPhAPk1xWNRq 5+tDXG9cxNfWCGp2rCtVTxx2LGkCj1SQulMc6y6OZin+J/QQ -----END CERTIFICATE----- agent3.example.org.issued_by.agent-ca.csr000066400000000000000000000016071470345337400430560ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICYjCCAUoCAQAwHTEbMBkGA1UEAwwSYWdlbnQzLmV4YW1wbGUub3JnMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyJgDC+ahnp2mdaF5Tcg05z4P9G6u X7do02Yz01IowYrmCGagDb6o3/m4nAvvS3UMKUaCJuIUvnJ72hHV0le93Fo4BcwB SUwWGkVy7LfP69EJVATZB4A6YAhVcEfmCBJh3nrKa8yHf7gxNbX9dyESNTaQ4FPo 5QR98DolA6/EGz1jxiFFeG2xMywhqD9nzuS3uafPjXUSO1wh6O2nPHkS/dKcgRQS s3XPd3GDCOz74prl+zIlTm44pdxRfrbHZAAACXsyypVtgio0VHRwq+f9liEaY4iL OJP4Qg06AZvvMnvZuNzVp+vFzCDowol5fMI3W0wN89gNIkRPYRofqWIUMwIDAQAB oAAwDQYJKoZIhvcNAQELBQADggEBACqpOYBQRXhBBRs64ctwvV26jrwJMd3cyej3 JYiB2vwr17pHKlwDlM9gKp/ZvfNFs5K7Q53xUK5bm0xPkXNeuicvgCCUi0h7hOdo 902JZ5lH1nos+ZV42Q+RjmPC8/X354F2PW0Be8gL3atQw6Grl/Ffu5jcynPe7cxu GYodZ8Vzn2uAOWURSaQqu8KZA+hDzCrE6faO7DSJKZ9foVS4aFnsoUcCeTGnJLh5 DmQKO1BGC1gdF5S7e+Jld3705oOeQIjL4JutkuDZR9QUajTNn8LtlncjffAdatvK 3sNceBdxXPy/XxVyVYkW7Ybq9RZw1FanjUNMEj8SzSBWsw3819o= -----END CERTIFICATE REQUEST----- agent3.example.org.issued_by.agent-ca.key000066400000000000000000000032501470345337400430530ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDImAML5qGenaZ1 oXlNyDTnPg/0bq5ft2jTZjPTUijBiuYIZqANvqjf+bicC+9LdQwpRoIm4hS+cnva EdXSV73cWjgFzAFJTBYaRXLst8/r0QlUBNkHgDpgCFVwR+YIEmHeesprzId/uDE1 tf13IRI1NpDgU+jlBH3wOiUDr8QbPWPGIUV4bbEzLCGoP2fO5Le5p8+NdRI7XCHo 7ac8eRL90pyBFBKzdc93cYMI7PvimuX7MiVObjil3FF+tsdkAAAJezLKlW2CKjRU dHCr5/2WIRpjiIs4k/hCDToBm+8ye9m43NWn68XMIOjCiXl8wjdbTA3z2A0iRE9h Gh+pYhQzAgMBAAECggEAUmCrD54dTWhsze4MRPctUrHYF4fEsKY/tGFKc0RQXHtQ UK7kmABuldyWBe+YzCI7ZlAAbzt1TWjyl/GvH/zMicu7KhZHiPRoN03CDpjGGI/2 Br0e68erMXj6rWu5eiMich13N6H9G2RnQSmF+ABq29OW16leAX9AwQD/5m2uWYi4 XiXLX0CCOLjugq5Z4qCK+iT5AigYNxjUufLXx7dWw0krpAvX8AFHZ/dqbJrdzxv0 1xaiS6AX6f0HSDqSMEd+ZjUssaIWDmEoRpjeCpmKxwAWtN781w94SLl5Te71kxyY +b9VNJZN25TAQHARczz2QtCzWVmA91QX/aOWOu90YQKBgQDn1lQ9WxByTX6qS6Re VHYzKgUriNBAXu9q7T0d7FxjmT1GfUPT2PsVRTb6yUsd98G+5D3FdvuGbxYRj1Kz TUQFp9TD2tzCbk0qID0gG4x7uJ/RfvV/OyYSNoBMfRRN4PcsjLSkPL6hDYPgVqim 2nZWPiOYpiv0Ht/Bak+54H2fSwKBgQDdgBLypWv+c+MBftb+b26ZAT6VuIBFoIdP t0QV7gQVRvH9rUyaSDb4lOVhCnL9J39higOZXcnnjiQBOLWIiv2B+/RJxpXDVASy nzGVIT6sanE7TQkg+PSvzp7PRp/orNRnQfR/Ocu9GveMbv66mEReq+bTTF7b67LJ L9ilwYiFuQKBgQCS9VrK1dnUCuma+34CyZlvj1hdo0kXNNahOic+u6BJBk9ASpFf TbDDZ++VA1pZcb7fyYCalnSUYABmOyraO8U9rIiDak379b12UZ9NpgjkOEEepFLs Rss4SlIDqlnfkBY+qCat4U+ZeZ6561TXB65xtswLrHI6OgPub/x/wB0BhwKBgQDA S7And/WJspIhejysJ5Gcw7fRw5uY1wSh8Djr0Pc6gZ0U3p7iUk9m/90joi6yGNg9 ldQKEaJ3pK8dYF45bHEpp9MtOXpLWWW6rPoevf3rMX2cPgTu2zOSbY7x5B5voZvF CT16NnLqeb7v7Gy5EfhJOHPsfSDdTIKqpx8uyBX+AQKBgGLGIQFnX/4DVANpv4Nx ssSHRNg/w1RllijaTK0dZaGsp1XVJVSlKEljWcTJkpGOMyKFmVnvbjEROOqhATDT iwLPBaJ3391TCqiEXHbutN5NlL8Iy+aqMS8CRL+8JhFpgN56GtcP+4Y0BpApfBga 3trJ2pT23VNfbf8zFwNfKsnb -----END PRIVATE KEY----- master-email1.example.org.issued_by.master-ca.crt000066400000000000000000000025631470345337400445360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIID2TCCAsGgAwIBAgIBBDANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFow RTEiMCAGA1UEAwwZbWFzdGVyLWVtYWlsMS5leGFtcGxlLm9yZzEfMB0GCSqGSIb3 DQEJARYQdGVzdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAK+DZO+xbJow5kzEP13hC2XkPjY5MZZg7sX5VuGtwhSD0vberSxijokB RR9U5RAp5AmWEpbJcNuL4wUyQ0yA/E0FSc6BhDwT25aA2l8CiIGpMmLmMw4M80K1 SXuHeXU/g+7MBmaYC4AxYbsxr1us+c1IpNYl9rO/4ZuUIgOHKjnnBHKYZqpNVmXS 4ss3o74rrHkIWLvBI43Mz4Ct2LZMSkaqqESvIfBKpW9LndtoKyIaaoxnXivC7oiG pbEfot0pvoCNV7Wfj7zFVQUdKdJTa5XHvshXoFdrnNHfZKVb6AIAbvZidzcBuT54 Ib4KFjIV3VxfJkQ/U0VTn4zhK+t2EuMCAwEAAaOBmjCBlzBbBgNVHSMEVDBSoU2k SzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9u czEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMBAf8EAjAAMAsG A1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZI hvcNAQELBQADggEBAJ083++L/CwcyFhC3FvaRX6dYQB5LlqPQs7E6GRZq4wL2Boo rNeWVTOhhjdxjmbLBLJ/VDOzxW5mCIVil8mHbTYUrmt77lfXkeB1Gb4sx8s3SbdK 10mmAhrV7eLjeV1Y/Tt9G4ZU3RbK78O/GXCg5Vp1S6GPUBMxlgm5K1IibpKxz5Cz yU6EN0seAhKB/MWiSWILcJy8sbySThLDy0wLzvUDFqHlVvj3XtBd08qp1Pov+r73 pBjgDHJvunxJ93DDfhiMPgoOIMcvijZmOQ+2cFfbhwlyJH3m90PbpaW8H0BNFBLT csvsTzHsS78o9usu+Sv/NpmDnzvOu1rzSCMmu58= -----END CERTIFICATE----- master-email1.example.org.issued_by.master-ca.csr000066400000000000000000000016741470345337400445370ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICijCCAXICAQAwRTEiMCAGA1UEAwwZbWFzdGVyLWVtYWlsMS5leGFtcGxlLm9y ZzEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAK+DZO+xbJow5kzEP13hC2XkPjY5MZZg7sX5VuGt whSD0vberSxijokBRR9U5RAp5AmWEpbJcNuL4wUyQ0yA/E0FSc6BhDwT25aA2l8C iIGpMmLmMw4M80K1SXuHeXU/g+7MBmaYC4AxYbsxr1us+c1IpNYl9rO/4ZuUIgOH KjnnBHKYZqpNVmXS4ss3o74rrHkIWLvBI43Mz4Ct2LZMSkaqqESvIfBKpW9Lndto KyIaaoxnXivC7oiGpbEfot0pvoCNV7Wfj7zFVQUdKdJTa5XHvshXoFdrnNHfZKVb 6AIAbvZidzcBuT54Ib4KFjIV3VxfJkQ/U0VTn4zhK+t2EuMCAwEAAaAAMA0GCSqG SIb3DQEBCwUAA4IBAQAO5+r9Dw3IAxhrrQeHA4Gc4z9ZAUKyPkS6saU59eR/2i/P e+j/pSMG8Mwbm/Q+AHkzeQfPKA01NOs3Xdtx3b1AlD5pP7ZDOHwRFaQIAukaXGmh 8Ow09pi/4HPvdzSZTLnoq3YoSrmKGRWad2WFQ80x7mo2vC+4WSg4VnKMZ0CjF4fO RxY1fCe7DMoEVAo9ROC1yDjpVvHyWemCSz2ckFEm/dzOBoZzKW4isPYccmfuuI/C D27/TQcWOkbU8LgLuSylzEb/WOW7RhvQuhZIj/r4aHudIemfC83pKxZAp47wpnOk a8KxcizMloGxfNCbxvkKTcZ1jyz4dL0xzdyGXhRR -----END CERTIFICATE REQUEST----- master-email1.example.org.issued_by.master-ca.key000066400000000000000000000032541470345337400445340ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCvg2TvsWyaMOZM xD9d4Qtl5D42OTGWYO7F+VbhrcIUg9L23q0sYo6JAUUfVOUQKeQJlhKWyXDbi+MF MkNMgPxNBUnOgYQ8E9uWgNpfAoiBqTJi5jMODPNCtUl7h3l1P4PuzAZmmAuAMWG7 Ma9brPnNSKTWJfazv+GblCIDhyo55wRymGaqTVZl0uLLN6O+K6x5CFi7wSONzM+A rdi2TEpGqqhEryHwSqVvS53baCsiGmqMZ14rwu6IhqWxH6LdKb6AjVe1n4+8xVUF HSnSU2uVx77IV6BXa5zR32SlW+gCAG72Ync3Abk+eCG+ChYyFd1cXyZEP1NFU5+M 4SvrdhLjAgMBAAECggEBAIcVwTU+wJC4fDivfvn5gLVOg5dmU8UjHAOh0f3mp470 mwXJA047GOtX3+SqiZb0NwAt0mbd6hAATZ2tPuD+EbISFOltA+LdgdAHoosnvvrU x+QYu0jgLMa2EzWRYqkcVqYPwAlsksV6vHbAWfBcZPNcKwprs8JLOBBvZfKDMLvY zVf0Dj9V+S6YQPQjkAa7uShXJ7sxt53RqwI0ueR2h5ZBLVm0LvijghDvSh0O+II5 4j/dkBPaXaPcf/pPMUiPcdj23RguX6ArAHzbROkclg6J859pGHs3GCsrguE2iKgR s/AK8tLj304h60K1vJ5tZqWokDqBWS4bwyKLCE8En3ECgYEA2BRMyHun6N+xXQTi SjCTIDfBY2QfYL4Nc0o47ds2WfXnmsoLUg37F9NXD3iqx5WmkZk/AjZ73dElEbBY P+/Wv8zgew6Qoa5s+bd36OxFiv0NAQjclQ0QPP+dSoRuqmT+0YI3Yf6Vl7vaumUZ sh6L2nTWX+Dk/0snQrjvDs3CNdkCgYEAz/B6/9FPvW+Mi948MjQLa9wDtL99PuDG AnfL8SXsSTgwVvgWPW8UhP6I7jRTirvJiliJVQDAHgmlHCwvvY09v3eoLqhznlYo E+KiqUdzVzGv2AaUwC9+8IpUGT3qFFfvgvuOTe/eTB8zMoLR5GSHlcLcC4CX6umW dEDvhBZVbRsCgYEAtJfSzMS8w18iJ7JLRuJuNMEkumMV7o8pQrBIAFP0ix+A4Nf4 ui3BLFqQKvgZFBI5UvsXtEvBHtUL/Eq8l0Nm4orjGzZDHz5fCh6S83N1dAKm+bRk V5bBeZnR5lPlAjjC2GvSye4zLMvutVaGMV5iWMTJ3vxhqBUxzQwvkNnbdZECgYA8 y4maq77NmwSTjDk7UF4afewTd30N2jfqVs4oxjasPaJcexI9ifGM5MJyKphWUosd SL92O87vuVAtyXl3yQjJpxlj8tpC69ux3KxEI+DEGIHZ/iqVeg16FGd8Lc73fbJI MHYtsTjkNqcIWJk3VnERxzQApOtFwl+7w5SDoOf/CwKBgQCQh5QQCeWbO9ndQfGX ztCxCmUVB4/8GfIkgx7/QECNLJKmTmqShG8dRU/SVzjIEnEOOoKsdeiPZAOvKrI8 jsz7N6cA3YRkbmQlku/FjWb+0CL4Kms+bfotisQA+k6ipjj5yBPmB4JVJ7xthpPi MMufQQcUhmOG9p3WXv0f71jPEA== -----END PRIVATE KEY----- master-email2.example.org.issued_by.master-ca.crt000066400000000000000000000025631470345337400445370ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIID2TCCAsGgAwIBAgIBBTANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFow RTEiMCAGA1UEAwwZbWFzdGVyLWVtYWlsMi5leGFtcGxlLm9yZzEfMB0GCSqGSIb3 DQEJARYQdGVzdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAL5w5qggNQUtGSgga5SPGHr5J8uIrg1IE/WR/p83V2pV+QyAJQChmIhT sBx87INcl89jo39a7LWoeXa3gUaXgP+6JY4A7E4nEbTveqBr+vKLdeZjyC0DwhIx 4Y6scXD9O2OeXH/qKdEHLnHAtKZBFIHY0YDDVVOrpS7DNtCZe4KTuX/97dxl+Qez nejIIY8vhYz5Cnhfad5KEKIuoKzj25ZGxcPr3/BeZ8IOr2/vqW6r1qWFCx/7X23Z VX94c7RYacqiixIUAf1Q6+9EoVhLUctuwnfTCqb5HX2zKrcsVAG9tirg5bQeqF9i MQDblarSN1LRbItL/0q7ZRSgZ8kMnKUCAwEAAaOBmjCBlzBbBgNVHSMEVDBSoU2k SzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9u czEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMBAf8EAjAAMAsG A1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZI hvcNAQELBQADggEBABhJx2HxQf/RMxdTzikFAqFL4e6xlOSZtTBO2jgD6gGJiBmR qHB/2XXhOg6lUUm3woVCC6CCNYv47OHtA2geDA5lBEfLGQJOPMMCR/z98QKX6jVE SVQNy3DwNmuWBTCBA3L9ArQ9FL2NhXnDhyOjVM/u4/dpYNXegzeA4du8BVblObo+ UY28OtNkZ72MSSGV95kAiqltBSYEJhFw8c57kAeIrgOgWy2XKaUToLICSV19BYAM IzR2HLwtmAYvga59xqSKyqmnJXiZpJqEae9XwR4JsWuYN5nwualobsAR8JPI46vU 05SYeaz1hwYollWM0iIQcXwArWFyvLXGFApQdQc= -----END CERTIFICATE----- master-email2.example.org.issued_by.master-ca.csr000066400000000000000000000016741470345337400445400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICijCCAXICAQAwRTEiMCAGA1UEAwwZbWFzdGVyLWVtYWlsMi5leGFtcGxlLm9y ZzEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAL5w5qggNQUtGSgga5SPGHr5J8uIrg1IE/WR/p83 V2pV+QyAJQChmIhTsBx87INcl89jo39a7LWoeXa3gUaXgP+6JY4A7E4nEbTveqBr +vKLdeZjyC0DwhIx4Y6scXD9O2OeXH/qKdEHLnHAtKZBFIHY0YDDVVOrpS7DNtCZ e4KTuX/97dxl+QeznejIIY8vhYz5Cnhfad5KEKIuoKzj25ZGxcPr3/BeZ8IOr2/v qW6r1qWFCx/7X23ZVX94c7RYacqiixIUAf1Q6+9EoVhLUctuwnfTCqb5HX2zKrcs VAG9tirg5bQeqF9iMQDblarSN1LRbItL/0q7ZRSgZ8kMnKUCAwEAAaAAMA0GCSqG SIb3DQEBCwUAA4IBAQA5VE3jNZ8m0+R0rVBkOHleizlI5SQm1Zup6fEJIyCGmrEU KYjF1H41MHxjvbs1pIbgLnzWBg3HBKYF4gBlsSV9nbIl2Pe541iOgj+ASc4T0VeT yyiz1hBN+iZqp1AaYDQr6rN0aSUf/z7NhS2Rm5I9ZuyFOm8PWSgpQPAGd4Xc1qo4 du3hUYt3vMyKIeEfQYJ/FyHo79PMbUeFXTwex/7NCmxfIUvO5qtg9t0pS+w73DYu 2T5z3Bq0mZBAs5gWrCTVBZ+HE1xBQxVgK+Qcq9Qg5hQbVA7jSTNAa+YfUyb1gDW+ rV2e5L/j4M075s2dB23IeaVlDMTIexnIPdzvXJkh -----END CERTIFICATE REQUEST----- master-email2.example.org.issued_by.master-ca.key000066400000000000000000000032501470345337400445310ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+cOaoIDUFLRko IGuUjxh6+SfLiK4NSBP1kf6fN1dqVfkMgCUAoZiIU7AcfOyDXJfPY6N/Wuy1qHl2 t4FGl4D/uiWOAOxOJxG073qga/ryi3XmY8gtA8ISMeGOrHFw/Ttjnlx/6inRBy5x wLSmQRSB2NGAw1VTq6UuwzbQmXuCk7l//e3cZfkHs53oyCGPL4WM+Qp4X2neShCi LqCs49uWRsXD69/wXmfCDq9v76luq9alhQsf+19t2VV/eHO0WGnKoosSFAH9UOvv RKFYS1HLbsJ30wqm+R19syq3LFQBvbYq4OW0HqhfYjEA25Wq0jdS0WyLS/9Ku2UU oGfJDJylAgMBAAECggEBAIWYAdazMT5+UoV5qL5AW7X4jtgS+7ZJd+bvEaVzVxk7 UkhYpJx6v9vyiTqSz/+etsg/Z3Rxvlf45axIMqHoqg+675lcQGjas2swC9/5n8MB 3iVOniAl4MCOyWIiyjmvCzho4Q7Cn68I0KXvv0pZoR8tkFo5rOPTJz9UpmFTKfeA nyufEPsIEvgISjW+Lt7ZjQghsqQCyjVfpUvT2La5srz0yBbNp1QEcP9hqH6d6zjV dtXB2JfDk3x9GkBi/DHCNnJbseF/FyXI5ezqhVkYvxVA19uY1fx3nB9gyurSMY3Q KdvnGK+m/eVTJ2UZXlX4h5+7w7hfeH9YBuVmhlWj3QkCgYEA7UgeTJCqyPPQGzZC U/c28z2NTO/sEZn9d+2l5N3PiIoZFlsNNDkpLmCebdYkeCtLigfR1XfcQ2s5B/e8 so7G84ZqDrtWR4mEHS/8pvORvWN1gx7gv+X3t8yWkKUzOsLaEQBNwM+kiYN4VWs7 MJnVAO0egHKWO2uplpLMjVmBA+sCgYEAzXbW3LLXHmRYNgJ4l24Sf50KMH/EX9mZ WNx8gKLi9VE04oS2i12Dk5bQLXbJ5sbMASK2nZCIcdzp99uyjWPl8a44IMQZMNHc T8GPzCI0Z9v2i9InnfL9RfrmCpY0Ulf4gY/TGVyfMn3Hr66c9Ol7eMsAg8+5clAD 7dDP/YP4Da8CgYARtU8lkapdQuzmCv+aOpnsP0y7UDCDA8YJ3D+EPBWP8BZ9N6Bd pGJxZp6MPe4M1dZWX80GLGLQ2UCxWojHnqY0aHSj0tFWl2m3r+wgHY9j3fdYKMbH K4d4PRmDhAC1wvL5T9d9q0FxTdF+Nnl9YA2oewnKtkKF/rvyU9RWPDbHrwKBgQC8 VlT6FQ1PlJevWnCEDqfyRldSwauWWPZSGDogCC+Ww4uAoDpcYan8nd/R7POCEXRr DhDrOdN43BGz27U+GfZrpVFZ56dXsucKTNmtOyVilqTW4hrilBxKC4TW63ymhnEL AnV06Awd0mI6zgqeDW/a9+pO6RiKioIveptNPa0hjQKBgCBs2yZ2BMDVQ1/IlxSA Ot2ufhzw39VYG66NX/LaX6ii+sBkV3WsUYpLCbSadKyHAJlBXz7V/OTRvDx69Zy6 MAJuSuQW64EJzDEGO/OHpIzel6pmb/C1w55bcDf0FASHhnjfDX9P68woQX7J1PWf sy5mAMn4VfEqifyN8oeaasy1 -----END PRIVATE KEY----- master1.example.org.issued_by.agent-ca.crt000066400000000000000000000026241470345337400432520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIID8DCCAtigAwIBAgIBBDANBgkqhkiG9w0BAQsFADB9MSMwIQYDVQQDDBpJbnRl cm1lZGlhdGUgQ0EgKGFnZW50LWNhKTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFt cGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEaMBgGA1UECwwRU2Vy dmVyIE9wZXJhdGlvbnMwHhcNMjMwNDEyMjI0MTU4WhcNNDMwNDA3MjI0MTU4WjAe MRwwGgYDVQQDDBNtYXN0ZXIxLmV4YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA6RLLxx3df3Ln6TG3iORiJNsQfZsRa00XgGhzbdTGOJ0v X5Yjq3igQeGVd3aCqAEivaDmk0Mk6mWyH5l1ODn75PdYUFMVblmNaCZ1sY6lc3uJ qWPEz6AZYojkLrhumtInUD6y9N3q2CllgT/B1yb4Hfs2WsTGtZjmYOqdKv0gaTw0 p46Uj0UrE42GOVjrrIQfomq16XwUDh1kqfIxuob4J/ZHN4pHsFtIvh3F3ZD2OGPi YLyPGyP3C1ssUnCoqfMM2TUO9LGeWquRvCLoYe+jA5Q8lbDU1NjxrRlfS+LyeCgn 96vWWmh/THVnaCiSj4O68pZABsgmHhg+diC8t+/sbQIDAQABo4HZMIHWMFsGA1Ud IwRUMFKhTaRLMEkxEDAOBgNVBAMMB1Jvb3QgQ0ExGjAYBgNVBAsMEVNlcnZlciBP cGVyYXRpb25zMRkwFwYDVQQKDBBFeGFtcGxlIE9yZywgTExDggEBMAwGA1UdEwEB /wQCMAAwCwYDVR0PBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD AjA9BgNVHREENjA0ghNtYXN0ZXIxLmV4YW1wbGUub3JnggdtYXN0ZXIxggZwdXBw ZXSCDHB1cHBldG1hc3RlcjANBgkqhkiG9w0BAQsFAAOCAQEAP5IbZHIFdRjh7f1p 9SHcGEJ9O/OYZfkmqzKfNsnQ3q/Honz3C9SxWkAdOTSQClayi/x+RkOL0h+50+Mw X/rC3qkIRce0JV+Uym/T4WsGz4Oko37xlt6Mlm9x194mTk3wcy22kY6jEOfp+YO3 Chsdw62yyp09v5YkwE9obPfSB3LshgabLBDsZPOqRM1IFmpQ7gkuwa/RlvQfidrs G9A4EzbWAt8d7v59HsL9u0+p3NT7JM1IH3pU0u5UWQwrMVkpiurtrz+ysTXp8XPT QUaA2LkGb4omiW7n1FsablFS6uByD7v41P7oDW5dMkOsKl+mw1Qeh/wZOplmoQVx 6xT00Q== -----END CERTIFICATE----- master1.example.org.issued_by.agent-ca.csr000066400000000000000000000016071470345337400432510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICYzCCAUsCAQAwHjEcMBoGA1UEAwwTbWFzdGVyMS5leGFtcGxlLm9yZzCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOkSy8cd3X9y5+kxt4jkYiTbEH2b EWtNF4Boc23UxjidL1+WI6t4oEHhlXd2gqgBIr2g5pNDJOplsh+ZdTg5++T3WFBT FW5ZjWgmdbGOpXN7ialjxM+gGWKI5C64bprSJ1A+svTd6tgpZYE/wdcm+B37NlrE xrWY5mDqnSr9IGk8NKeOlI9FKxONhjlY66yEH6Jqtel8FA4dZKnyMbqG+Cf2RzeK R7BbSL4dxd2Q9jhj4mC8jxsj9wtbLFJwqKnzDNk1DvSxnlqrkbwi6GHvowOUPJWw 1NTY8a0ZX0vi8ngoJ/er1lpof0x1Z2goko+DuvKWQAbIJh4YPnYgvLfv7G0CAwEA AaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBG8OVju6WneRUM7/m9dERatLoaWbaUwy+Z U9IztgtrT5n4wgp8mCh/Ue9NxJRTtxh+AvML/lb7J14xi9D3X7dizbpRBknLlRYn ctIxXiL0NopwlqEUwkJAZzEvTX6HN2IJ1pA1GHzqznAHBn/waNdhLBy4T4by08dB Vvclkr4lPhJkHBw0TRLk4SRz5iLQ8Fl09a0HLhqOgMcoj3mTeR7PajjAEI4c9jau Eivt9SjFeHXF56/uCJV5clbDQr97qUxIfwN/XtovWCPf6NZNulcLK5hBbBV+oR/9 DXtRLseO+Yn6v/B1FgEKO9pBsW7/tYTos4WR6C6Kws/wLm/pZ0g6 -----END CERTIFICATE REQUEST----- master1.example.org.issued_by.agent-ca.key000066400000000000000000000032541470345337400432520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDpEsvHHd1/cufp MbeI5GIk2xB9mxFrTReAaHNt1MY4nS9fliOreKBB4ZV3doKoASK9oOaTQyTqZbIf mXU4Ofvk91hQUxVuWY1oJnWxjqVze4mpY8TPoBliiOQuuG6a0idQPrL03erYKWWB P8HXJvgd+zZaxMa1mOZg6p0q/SBpPDSnjpSPRSsTjYY5WOushB+iarXpfBQOHWSp 8jG6hvgn9kc3ikewW0i+HcXdkPY4Y+JgvI8bI/cLWyxScKip8wzZNQ70sZ5aq5G8 Iuhh76MDlDyVsNTU2PGtGV9L4vJ4KCf3q9ZaaH9MdWdoKJKPg7rylkAGyCYeGD52 ILy37+xtAgMBAAECggEBALcd/2BnhHj3rGE4oHw7Ayj1vBUTWjI1lXtblST7gOlG BcxRx6CW20InnCkJwUmB6uuVmNKmdEB8ud+9z6znUZLpCkfBnxrd3Q2w+dMQwcjj jJq7OgvuO0OBTdWvLacR6bVQLYXZPQOsMoXDs+X4RgQ4NNJHu989S/NlISp/SZGj Ld7BMd7JzWcd0YW2VEUdb9Sebgt4/ZoC/4iAsJCTche7zKkTPYXz6JjgO9ggNLUj AEFMrdvC5VZbth5E45Or8+HUPw9Zdq0ypI8WaKeWVmOQ1vF3M4fOW5MhEwJ9DArD h3D5xooK5cicSLTcf/RkCKBt1bTB3ra68+MpB3QcKwECgYEA9IH0iu30dRYDl14t qKsVHrClxGfF4WlvwYYnMoFudMWPT77HMBLYfkh6zRcXTAIfUDGUaGMKbAza4GTM xFqaBzi7+cWFUO0KXx0JpsMVswim5H4Nowl9chxszXhsE0KsPoDrEWi8q7Cezmpf qPyNWhoNH0TCi1+JCOB2mZbDE80CgYEA9AdCHM033uJYwiRJHN1KL/9kDw9N9n0t 0s/yXl4n4gCoCUGxyYqhdFVa9MGaRB0ScCKz5NmbMW9lfvquabs/ujwmi7mRCq7X /RYHuhaUBgaa1sDeQ9PCqDeqPfutIcXZNmVGoi6MmChufZ7i5CPw+UzOBuvY3EzQ uaLYaXxC2yECgYEAqbRVNeRIysd3wKTWTf5Ij1+N/o8EMhrLPWfOZuic8KF6gZ/p gn1iE+xch2KigdfrQe7XkchEIJCfjiWIVjSIOcDv/0FP8cZEb5Wo8DzxH60+oNK4 xlM85WnDPq15Xbjl8g/ql8+5O/U/lAcS1ChON55jQzOnT7MEWsvopVuVlHUCgYBL Oe2UiWLez7IC70KmpkUXdMh4qAQlp0M4CKizlJ0A26jxaZIQCi9peGKYrxIKS1gC v3/rXXWtEKUeNtMLfxDPLXnIewUOYQXuXBs3r3wkO2cCKuSZzi7kwnw1rV8a2S3z ydazalwnD9e33AIfyECh6Z5dndj1WKzDfULvicHmYQKBgQDhKXZf5yoxqpvAlycx xG6KNmCaV21wTXqu4xdNWV6hziejInNiJUX98H/Nfj0Nt/yKSAMo18K1xYs8ZmWy ADho8EcKYkko19IgO6XDMrFNrNr+y9GoIqfVrOKJPwu20hCV0z5fn7YeezRI+TW0 uI6IO5dYe482sNCxm5zWsvH3dw== -----END PRIVATE KEY----- master1.example.org.issued_by.master-ca.crt000066400000000000000000000026241470345337400434470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIBATANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1N1oXDTQzMDQwNzIyNDE1N1ow HjEcMBoGA1UEAwwTbWFzdGVyMS5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAJnqPmMTC+OK9BL8P3+IcSZg5PBFwUU7Z0clkn42nwJP WyD9C1/EbQNIsEiY2m0dy0ygr+35naIxmEWJ0nsUjhgMpS3QngXjHNKNlR1Zi2Vy /LYdQ1orRH/BKytuc9lTiau9SqsM3qVlp16CrKc3rzyU3cxN2aTYpo2vrHcF9KNV aFrmE+n3U8GfxX0XossPkZeyd6RYoaSZqLtTw9CfYqmEOJ0u8kicTmAK+1mK0sAO prBjSiBdwVVZHnmv8VOy1GcfB21N9uEafHmzbn160E4ARs+HLtVc3uPWsC0i7jaq eDUajpcRmxYSZ/htN06rEwywplJRJGjMipM2fsMU8L0CAwEAAaOB2TCB1jBbBgNV HSMEVDBSoU2kSzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIg T3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMB Af8EAjAAMAsGA1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH AwIwPQYDVR0RBDYwNIITbWFzdGVyMS5leGFtcGxlLm9yZ4IHbWFzdGVyMYIGcHVw cGV0ggxwdXBwZXRtYXN0ZXIwDQYJKoZIhvcNAQELBQADggEBAEonitEmfeJx6Onu Qjo660ZVkd0t/e60aS5o2QnMD6Bc8sljovRh36/PDU+I3pHSkCCo53npsNAFDdL7 pOv+y7rLNeNHTQ3/LglWQwMwDasJM0HcV35UatYf9q4ooHSXDOtZzcu6t20/KpW5 2IQtr6f+JFlNa388/aTURJzXqeMHTTPEQMRicp0V/svHogWYEZiKCfDlW7k3va8V eBd7m6LI8iBc0V9b2ieRkA16e1sZ2A48iaKTiErTZl3xEc25/S+HOpp/OKEdFr1+ CxJ5eNKi2i8o3nyRcGz7wa5QgU7esL3V3x+h8ycCtHgAFUqGveqwDSHbBeD5+85y Dj+STIQ= -----END CERTIFICATE----- master1.example.org.issued_by.master-ca.csr000066400000000000000000000016071470345337400434460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICYzCCAUsCAQAwHjEcMBoGA1UEAwwTbWFzdGVyMS5leGFtcGxlLm9yZzCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnqPmMTC+OK9BL8P3+IcSZg5PBF wUU7Z0clkn42nwJPWyD9C1/EbQNIsEiY2m0dy0ygr+35naIxmEWJ0nsUjhgMpS3Q ngXjHNKNlR1Zi2Vy/LYdQ1orRH/BKytuc9lTiau9SqsM3qVlp16CrKc3rzyU3cxN 2aTYpo2vrHcF9KNVaFrmE+n3U8GfxX0XossPkZeyd6RYoaSZqLtTw9CfYqmEOJ0u 8kicTmAK+1mK0sAOprBjSiBdwVVZHnmv8VOy1GcfB21N9uEafHmzbn160E4ARs+H LtVc3uPWsC0i7jaqeDUajpcRmxYSZ/htN06rEwywplJRJGjMipM2fsMU8L0CAwEA AaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBfmS58AudJWE8dqHMn6y2htfFZRjQMvcUg floAn/Y1sKDKwWF2XStb4GHq2fBEUxGHJ7euXriCf+/3tWddeowH03h1Ek7I5SHb 6xh59OIMAeMpwxyswHtVtVAmxCqqrBchMjLK59EbIDzIMo2c2g5cX0LxeJD2Wl5X +oE0NPgYINfY9LyAfRY3IAlo8qESC5DBROgmys4cz9yU+FfSslC4+fkmgnEENsg7 S636TqO1QeymRnOKp7NQu7xSIJXFw/nwlR7+Llg94dYPk76BQWg8RCZgX3xsiUCC ps99dYsIYfuapICLlzqOLbRhH5GMzW2ms4/shAawK1E2O2CCUhej -----END CERTIFICATE REQUEST----- master1.example.org.issued_by.master-ca.key000066400000000000000000000032501470345337400434430ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCZ6j5jEwvjivQS /D9/iHEmYOTwRcFFO2dHJZJ+Np8CT1sg/QtfxG0DSLBImNptHctMoK/t+Z2iMZhF idJ7FI4YDKUt0J4F4xzSjZUdWYtlcvy2HUNaK0R/wSsrbnPZU4mrvUqrDN6lZade gqynN688lN3MTdmk2KaNr6x3BfSjVWha5hPp91PBn8V9F6LLD5GXsnekWKGkmai7 U8PQn2KphDidLvJInE5gCvtZitLADqawY0ogXcFVWR55r/FTstRnHwdtTfbhGnx5 s259etBOAEbPhy7VXN7j1rAtIu42qng1Go6XEZsWEmf4bTdOqxMMsKZSUSRozIqT Nn7DFPC9AgMBAAECggEAVtAlsjIbAZPtiQvYMPHfiFscpl1h3s/bt+h8UU4zr9Tc vKWdlb2wEysbq0bz5JnqgmUb9ilV/RbmIUrUenGkl/IB9O53QzDPn/8VvUE1e9o4 qeulgqVm9HwbAltBYrJYs5KIHCSdLENC/O7NvV+OKqh41fSPLwi4ILCWoWetjbYN wnhOC44uUTGJFEeSzhfAxkY8vfwCEtNa/oCApsmxORcmu7M5RU1dzp2qIBe/DOGG hB3NbfyU3q9iKzcI7+iNOMzzV1TqQMlEYiSwit1W+wFj/0NZCVTWHgK5vnOjhp1N i+j0ykuEGNXgG3BCewXXltND4WqNJQYXBXdlrppP4QKBgQDG9d7l1Mmi9kjqDfKM BCw27DwySEiPvHjAii3Ah6J/8ANoge9rj7+2OsxC17LbHYawgYyAvaW8oEanGgE1 fdMNb/Ujrl2jOE8c8dwZP24MRjJG+ACEFHeQvzR9lPbsIru0h5Bxabn9ZNI03B9t E9emhKR3HRukD6FaPb9UT55FRQKBgQDGCmTbdnyX5sy/X5l/pQoaZPCaMfGcgBri EiPEljmoFMyO2UiJV923Ki+/6YaVy1+f/bUgBlN37nKpfwTWSMHiz3OopFYV6fdn dRt0Pm58NgJEES2eA0qElA791cAjHFBNM9Bf/EJi/yC81dBbPYD41HUSm5zombES WYHPKpnJGQKBgQCaQrYw4pv34xbDik7darrRVraRkePYthu1xS0WEtPWeERcOipk 7k6JPutyhAUjyK/OmJNUmjYvmuFM3GfFjqodyAl8QcxOKfGFEq1BUiHEGIUQ62aT Ab92lhlfqSkOCxwYK+e9V2kiY5Jr86PWEcVpUXym8gWlXY0QB8IZ36VqNQKBgHmx A160BUWWJjRmez0rXfTwF8S4cd4X/ezy9pWjNhSpizUwIVl765rUynij9/Zt/Pmj /buLB5lHpZ+vlHpURQepMEntiZR3q3YgSNl6T4v16BiJcb2KCi1DiZ7CzQkGKfX2 o9GHggew/B3tSNX4Chtc+f+QLa/kWSGMbK6vX8ZpAoGACIjRquyI2jQBCJmj3XcT HlWNB2Pn8VMKC1exDxwTDinhQKoiwIyIRpgHYcLF/POBA22TGC6bfxHjAc3c405j wRYfluCJGaoYbELGqo/6OgDq5ZRIHRHEShX7m4kuT6qJ4Tf0UV9CgZeLEgwvOxas 7wf6BWMsOPt01Tr2uvOtiFI= -----END PRIVATE KEY----- master2.example.org.issued_by.master-ca.crt000066400000000000000000000026241470345337400434500ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFow HjEcMBoGA1UEAwwTbWFzdGVyMi5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBALPe3Hu82akfIiNLnG8vYZVK1+T298lkpWepwGUvdWWL FO51J/+B9av9dERwA7EQMB2EsqiDRLw90Mb76T5MBqNmgNn4cwjP/Ur6+jCAf7LD MO9y9tFd+CFcG4gi+mKAUS1o9Yq6wcc3lnAIHZYaYIFsLwE8m0L1IRGbHwrVCwRR Wm61BqBVVC9s4vGopPJ930IH+D1kNXc5veNwatiWwdK4oXt3ti6NoTbpeAwLWYEo /62Tw9WJl56TGgLrEamA0vmwZqRQiVPiCcsFGSaSagI6LfsznkjWcdkMWnZBJtky Ijc6kgTv514oJ9DgorO8cmQ1Nh/8sYWWuu38a/Ec4MkCAwEAAaOB2TCB1jBbBgNV HSMEVDBSoU2kSzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIg T3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMB Af8EAjAAMAsGA1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH AwIwPQYDVR0RBDYwNIITbWFzdGVyMi5leGFtcGxlLm9yZ4IHbWFzdGVyMoIGcHVw cGV0ggxwdXBwZXRtYXN0ZXIwDQYJKoZIhvcNAQELBQADggEBAFIbMGPuJ6FvHeiU h0BQ9DaPj1kGpqW7SpR9KcfboQDodL7yrkSGdOJ+64zKZr7r388HFpaS/xN+ilay VRXG1l99O7pOKmvr7t0V9CqWMvuALYV9CLmGIVKzrc2X36nngzaNIHlgiJ6PsbAh w3V5+z+xUIiHPRU+KHzU0ka5Hn/zTkqkWm0Ci7fTyZAfUMD8gPo0cM79NWlCulej bAkD3H/KRxBAVo6P0e5xB1bWlS+4LDd8Y6G1l29PAc/FrSgTaW7zz0A9Rf8UMQM+ Ye/f609U/IIr3W+Q64AU50xlY+ufSuP7KeZanCi0FAS0HuuNdqG4MQWyHXppTgkg HwYbNEo= -----END CERTIFICATE----- master2.example.org.issued_by.master-ca.csr000066400000000000000000000016071470345337400434470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN CERTIFICATE REQUEST----- MIICYzCCAUsCAQAwHjEcMBoGA1UEAwwTbWFzdGVyMi5leGFtcGxlLm9yZzCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPe3Hu82akfIiNLnG8vYZVK1+T2 98lkpWepwGUvdWWLFO51J/+B9av9dERwA7EQMB2EsqiDRLw90Mb76T5MBqNmgNn4 cwjP/Ur6+jCAf7LDMO9y9tFd+CFcG4gi+mKAUS1o9Yq6wcc3lnAIHZYaYIFsLwE8 m0L1IRGbHwrVCwRRWm61BqBVVC9s4vGopPJ930IH+D1kNXc5veNwatiWwdK4oXt3 ti6NoTbpeAwLWYEo/62Tw9WJl56TGgLrEamA0vmwZqRQiVPiCcsFGSaSagI6Lfsz nkjWcdkMWnZBJtkyIjc6kgTv514oJ9DgorO8cmQ1Nh/8sYWWuu38a/Ec4MkCAwEA AaAAMA0GCSqGSIb3DQEBCwUAA4IBAQA+giJgUBjZV/MKb0KQ4QWLXPa7zisiNtk+ nRHHeqynRE9u4UAxWCKp9onBeEKnsqLHcrEQl4jvWBGwmMPr47fgFOVqZjJC1om5 O4pyZctG4xPrCFiH6DspoSiYAoyMt/SCnroMaYKUuMYyUsMCf380HLmsd3IU7Vt/ nMXKLTofaL1J3K3ymJawRHPFXUac4OqpeHVvdNacxi72Vagyzpctbq3Gz8K5Qose rUPYQY5mr8JsNC5t7D4kgINaWfocAuf3LZ5gc88Qk7RJNZSSra7qg816aOuA97SF yFBxOXCv7mvoy3xXSjgYATMoa5tg31Ib0suSUr4nq01V4wl3fF8y -----END CERTIFICATE REQUEST----- master2.example.org.issued_by.master-ca.key000066400000000000000000000032501470345337400434440ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/leaves-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCz3tx7vNmpHyIj S5xvL2GVStfk9vfJZKVnqcBlL3VlixTudSf/gfWr/XREcAOxEDAdhLKog0S8PdDG ++k+TAajZoDZ+HMIz/1K+vowgH+ywzDvcvbRXfghXBuIIvpigFEtaPWKusHHN5Zw CB2WGmCBbC8BPJtC9SERmx8K1QsEUVputQagVVQvbOLxqKTyfd9CB/g9ZDV3Ob3j cGrYlsHSuKF7d7YujaE26XgMC1mBKP+tk8PViZeekxoC6xGpgNL5sGakUIlT4gnL BRkmkmoCOi37M55I1nHZDFp2QSbZMiI3OpIE7+deKCfQ4KKzvHJkNTYf/LGFlrrt /GvxHODJAgMBAAECggEATFC8P4vK1eStuUf1YX866frNSwo1667WNvtg9A2Ew8aU 5O+0PsZHE+f/kqHsDw4NPBj3LGQ1n6Cimip7tcDP+DgfZ1vwgsasc0m1KSr8Az6p 3o5qhj5WbuEDlWkxzuUejCPCOlAus3W0UGhBFVSvqXnbH601Ot2CYFPugcwOVo/v H2sc/EldV9QVXl1SDVQWT3EjZ4ONz7txqrUael1GhUlx8jSiL8MHKrDjYxdyXfV7 kUCoDe84wZWD+Xpi/wR07VFWnC2QSzPz0YsXMsmdyQKwHP6Atf3+CSJVxop1EZbm n0D7jXzJmyeFjXkt6ONOKQynbzQ6yx+XbNlBYybNAQKBgQDoftA6EbdmK9wOMaRd xRjYgh3oAoPIqT6QjKrjQ2h/D7QfBLLeJ5VlUg105PPfAXhaUxMAYWzOfYmBuntG 6JB3JsnjTiaS2XiJIok9y+f7ItItDF/59DBYqnx5v20SzTy0n9w8H5YL85xdQ4Gs BfIBu+/elKh6L7taA1/Gf3Ky0QKBgQDGDhIqakjFjIdymmRa0X4bzOaYCllLy9C0 AysMsoPuAA7Ytwtc97Gg/EyNuzgOfex5nX0M5hQ3lT3DhtFN73ltgK7CHKhY6JhR c3tjws3IBilxfw1oOaFK0FHC6dTDYK201LTxuSftuDP0C+/rMDgnvMaZTKc5KgxV oANtVb+ceQKBgBZdHGp5icqqLWCwJb9fViR9X6MRmtuSbBI7dbSmp0aRnCHfsdTs udIlMmYsH8kzuv/1Pb6roGu8Z52y8mi/tiW/9WuH+O3nPVDzoX/wPUBK+SycJB9G /d+Jhq+vWi6Uz2IQfn7KCwTbSg8ujyqc58qC6W/fnNUkAkGGUZAmckIBAoGAGA1n aV1E/zDE1kcnvtvIO+oTaw1+sLTM4L+tv7oCSaoaI3l/WMf/+3QIfAHrmd7zFAXr RODAPcvTF2bNDnDxxzmkf5BpZXrB3MpwhroGsa8F43GxmCG/k81e0JQDMcMQ9XAL lXuN/NGtBYtZlK9jcnf7imyDtm6D1vY61FFglskCgYB5VL93u6Y4feGCRUNmFKvF QJv+5D4yaQyRUuRtAX1YB7O+gLBLAgwNH9v/gzW43/nLEkqzEQuNSx+bgaLlYjIr 5ZhYZ8kFBxkT2MAjVxx9ZPmJ5DAmKMiAO1dFTboEdiCyoM/xHJW8J4zfej7U4F/Y z66hiTF02DptvhkA+XVJyw== -----END PRIVATE KEY----- puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca/000077500000000000000000000000001470345337400337515ustar00rootroot00000000000000ca-master-ca.crl000066400000000000000000000012721470345337400366330ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca-----BEGIN X509 CRL----- MIIB2jCBwzANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRlcm1lZGlhdGUg Q0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5vcmcx GTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNlcnZlciBPcGVy YXRpb25zFw0yMzA0MTIyMjQxNThaFw00MzA0MDcyMjQxNThaMBQwEgIBARcNMjMw NDEyMjI0MTU4WjANBgkqhkiG9w0BAQsFAAOCAQEApEjVOh+q7CWOFlvAstOfYrp9 SsgJp9k3Lcw2IHNqKxcrpszvLRjjCoUuc/qF6SIOidT1wmG6wXfSm5mlXHZ67KEm tJh3OgAQhOlbFrOOk0T7+C3qWKEnCaOzuYhH757VwCuU5n9zZQBo9ucHZAPC+Je5 oTrGA9NHW65/HNFYKNwpHsdLOKmnTGnSRqWhf3CmS9tzQU3tXWz4g1iQoCMFjkYD h9BoKm9/b989aI2T+dYPdzcWccfONt7cboPZzgYtb0iuq7aXXFqLDJl9wkxtyF+I hIkzb0F/Rp6D4Wt0rRw5AOMlRObWxM1pKu/jUv3O/dcpMUonp6oDn3e1NJBFFg== -----END X509 CRL----- ca-master-ca.crt000066400000000000000000000026131470345337400366430ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca-----BEGIN CERTIFICATE----- MIID6zCCAtOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBJMRAwDgYDVQQDDAdSb290 IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBs ZSBPcmcsIExMQzAeFw0yMzA0MTIyMjQxNTdaFw00MzA0MDcyMjQxNTdaMH4xJDAi BgNVBAMMG0ludGVybWVkaWF0ZSBDQSAobWFzdGVyLWNhKTEfMB0GCSqGSIb3DQEJ ARYQdGVzdEBleGFtcGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEa MBgGA1UECwwRU2VydmVyIE9wZXJhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDAEPlZmffi8ZVgLS29BkwS1xSvWa/LAzL0oSN99sRcEXf5Aq94 n9uEq7XkooaM+/gfUBI1KGJBLwbKKtXc0xL0i9JGjMcFPMnlU5wCcgzK5KArB5OZ RV5MM06j86+/wDYDNojYxb1lvePJzv3qdKwkEVtIWRfA29FaMoEsqWWZvEsW5fb2 hE16JEsTJmHDdPu/AlvwXTmy4lkitS8quTMLkpedtz/Sp5wEuQFmgEmeHkZzRuD0 rpQe+xbDTSsnlib30Mjqi/dUgolseJqCX0RZ8rdxTARUXn+3aYwnZtS18Y12aj5h igBzVBZvxETE++MluDnZKATH2Tupejzx0Ts9AgMBAAGjgagwgaUwgYQGA1UdIwR9 MHuAFPWQhkterSX1ED/ePsbUn0I/h6qvoU2kSzBJMRAwDgYDVQQDDAdSb290IENB MRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBP cmcsIExMQ4IULxTl39bugVS0Jwy4ZWpV3IIWTjcwDwYDVR0TAQH/BAUwAwEB/zAL BgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAKqGMvKEylycCdwVe5idgQhF u0L81gLr4lcAo6AxCDQXbijD2G1n3SZFl6L/kbUf+S/n3Gk23uE6/Ml5EZYh4Z1V faNQeH2FHJmsLlPluNAlyCnL5x4KzExM4kRa/UKAf1nOg1ulkRzAAD5WofWipU9k W+x29VO1eibL0rsJehiASj5SqW9Vm5ZFz4vHeFxBPDNkyAqjPGXc8yZELjrWb0id nIP2nMN7PNZlWivwBzUwszJU0AxpNYDGbFBlI3ImpUxC5JvpF48ST0V7JzX4HWl7 IqJqxuDCIkFyiX6eU58n1MxXMsfzCZwR/F3iFOxHDmZjpRDqZAa77WkNYI6QVXA= -----END CERTIFICATE----- ca-master-ca.key000066400000000000000000000032501470345337400366410ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAEPlZmffi8ZVg LS29BkwS1xSvWa/LAzL0oSN99sRcEXf5Aq94n9uEq7XkooaM+/gfUBI1KGJBLwbK KtXc0xL0i9JGjMcFPMnlU5wCcgzK5KArB5OZRV5MM06j86+/wDYDNojYxb1lvePJ zv3qdKwkEVtIWRfA29FaMoEsqWWZvEsW5fb2hE16JEsTJmHDdPu/AlvwXTmy4lki tS8quTMLkpedtz/Sp5wEuQFmgEmeHkZzRuD0rpQe+xbDTSsnlib30Mjqi/dUgols eJqCX0RZ8rdxTARUXn+3aYwnZtS18Y12aj5higBzVBZvxETE++MluDnZKATH2Tup ejzx0Ts9AgMBAAECggEAHM1u10UDq4DXCck8prAfEGQ4seMdPbCJH65aiDVNVRE5 kJoaflharxag/FxzGQlgODHlyRr5QRUwS3kJAUiV+x5Mtk++OMbY8A8NwkAgMvz+ F/XW6JFChuLa1DNjE7pbXzf6Zaehs3Q6iLUF1vcQKYiAy+SwbzeHuaMBRBVTKy6S XGZ8KSCnCHFNtGl+0IKM7ARDl1kLoYc1lnP+81S7TI294GavrYoKr6EA8JETahUB 99k31JFSd7vGSbmJzAPy+bdztsQA6o82WNS/1CtO44Oa1uGPBEuQWSSzoNDFCLcM neAeTTc30xGY5+LSD6oLS4SZVWjfkvs5df9XofOFgQKBgQD+93bvzWmxZ/0h4V40 mNchMD4v768Zb/3rh0XSFw9MpxCKmPeMpCbA2VqCc/Hi0620EjIuS6h7kcAmE7Pp /gRJweyrL3tg32n9iTVKv2sriKK5Q3pL955drHQdjncZiOWJN0toRFjCtbaFRg8J QcQAsBrkS/T+V3S9IagMrQw0mQKBgQDA2D+bH5ntn/Mc9ZRpwQjSXSPUmHizuvOp yXJZPT6eJ2ygz7NMi+s6+42TbrNj5TTDo8j1Zp+Yk4cNTLmRCYmOFddDY/exsGC6 WzYqioD9PMYV3rofkYI54maQhkaURg0GGRI5eoJGiZYriXe1WkSfhwR2UdtFD/Ek X1+jk1o+RQKBgDWIP7CZsFdPPhae+uiQLpsJRgVKjbkJioapID+8F7pAWXjAJTmi PYDAIgDB10eIqi/koiSWPgmz0GQuPtgiPUQ/MzG+BmmQfvB8nnPTPO0nAwNi54qL svR4AOkzwE3cMFVfBrYdo4U+IdRZoU6QQFbkosDMMeQ0+I29Q0tmCeoBAoGBAI1S 7OolsoyuF2A1qNoHmQtxLnzycCJm84KOGrrDY0xL4BPJosCKGY1UJGDTU6v1oUFu misdVgBevS5F+AgOUTxLTUIZ1L/nXjuz9HIgpn7vNst4OjZAUItTG472mGq5G3pI jU6KNUa0NdUaHRxOVtQCAocjXemy0Smyq0gZCJ1xAoGADPwqlCmAcjdzm533xFA/ Tswtk/tJx+Pg3HNmTYHaiMGEHjZLgL0IzRUL63zmP26SlU22GeG3uyGLYE5Pzy+S nLPzLvMwaeOuZ/jOEPXE42q/HFaKhRhPLQEcNRPZ2to9loSfVcQJ2J+88QieGjjR DXf3wIoS0S4rMf1fbG9RjD4= -----END PRIVATE KEY----- certs/000077500000000000000000000000001470345337400350125ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca01.pem000066400000000000000000000026241470345337400357410ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca/certs-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIBATANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1N1oXDTQzMDQwNzIyNDE1N1ow HjEcMBoGA1UEAwwTbWFzdGVyMS5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAJnqPmMTC+OK9BL8P3+IcSZg5PBFwUU7Z0clkn42nwJP WyD9C1/EbQNIsEiY2m0dy0ygr+35naIxmEWJ0nsUjhgMpS3QngXjHNKNlR1Zi2Vy /LYdQ1orRH/BKytuc9lTiau9SqsM3qVlp16CrKc3rzyU3cxN2aTYpo2vrHcF9KNV aFrmE+n3U8GfxX0XossPkZeyd6RYoaSZqLtTw9CfYqmEOJ0u8kicTmAK+1mK0sAO prBjSiBdwVVZHnmv8VOy1GcfB21N9uEafHmzbn160E4ARs+HLtVc3uPWsC0i7jaq eDUajpcRmxYSZ/htN06rEwywplJRJGjMipM2fsMU8L0CAwEAAaOB2TCB1jBbBgNV HSMEVDBSoU2kSzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIg T3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMB Af8EAjAAMAsGA1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH AwIwPQYDVR0RBDYwNIITbWFzdGVyMS5leGFtcGxlLm9yZ4IHbWFzdGVyMYIGcHVw cGV0ggxwdXBwZXRtYXN0ZXIwDQYJKoZIhvcNAQELBQADggEBAEonitEmfeJx6Onu Qjo660ZVkd0t/e60aS5o2QnMD6Bc8sljovRh36/PDU+I3pHSkCCo53npsNAFDdL7 pOv+y7rLNeNHTQ3/LglWQwMwDasJM0HcV35UatYf9q4ooHSXDOtZzcu6t20/KpW5 2IQtr6f+JFlNa388/aTURJzXqeMHTTPEQMRicp0V/svHogWYEZiKCfDlW7k3va8V eBd7m6LI8iBc0V9b2ieRkA16e1sZ2A48iaKTiErTZl3xEc25/S+HOpp/OKEdFr1+ CxJ5eNKi2i8o3nyRcGz7wa5QgU7esL3V3x+h8ycCtHgAFUqGveqwDSHbBeD5+85y Dj+STIQ= -----END CERTIFICATE----- 02.pem000066400000000000000000000026241470345337400357420ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca/certs-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFow HjEcMBoGA1UEAwwTbWFzdGVyMi5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBALPe3Hu82akfIiNLnG8vYZVK1+T298lkpWepwGUvdWWL FO51J/+B9av9dERwA7EQMB2EsqiDRLw90Mb76T5MBqNmgNn4cwjP/Ur6+jCAf7LD MO9y9tFd+CFcG4gi+mKAUS1o9Yq6wcc3lnAIHZYaYIFsLwE8m0L1IRGbHwrVCwRR Wm61BqBVVC9s4vGopPJ930IH+D1kNXc5veNwatiWwdK4oXt3ti6NoTbpeAwLWYEo /62Tw9WJl56TGgLrEamA0vmwZqRQiVPiCcsFGSaSagI6LfsznkjWcdkMWnZBJtky Ijc6kgTv514oJ9DgorO8cmQ1Nh/8sYWWuu38a/Ec4MkCAwEAAaOB2TCB1jBbBgNV HSMEVDBSoU2kSzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIg T3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMB Af8EAjAAMAsGA1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH AwIwPQYDVR0RBDYwNIITbWFzdGVyMi5leGFtcGxlLm9yZ4IHbWFzdGVyMoIGcHVw cGV0ggxwdXBwZXRtYXN0ZXIwDQYJKoZIhvcNAQELBQADggEBAFIbMGPuJ6FvHeiU h0BQ9DaPj1kGpqW7SpR9KcfboQDodL7yrkSGdOJ+64zKZr7r388HFpaS/xN+ilay VRXG1l99O7pOKmvr7t0V9CqWMvuALYV9CLmGIVKzrc2X36nngzaNIHlgiJ6PsbAh w3V5+z+xUIiHPRU+KHzU0ka5Hn/zTkqkWm0Ci7fTyZAfUMD8gPo0cM79NWlCulej bAkD3H/KRxBAVo6P0e5xB1bWlS+4LDd8Y6G1l29PAc/FrSgTaW7zz0A9Rf8UMQM+ Ye/f609U/IIr3W+Q64AU50xlY+ufSuP7KeZanCi0FAS0HuuNdqG4MQWyHXppTgkg HwYbNEo= -----END CERTIFICATE----- 03.pem000066400000000000000000000024761470345337400357500ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca/certs-----BEGIN CERTIFICATE----- MIIDsTCCApmgAwIBAgIBAzANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFow HTEbMBkGA1UEAwwSYWdlbnQxLmV4YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA30VndhiWyA0M9LXkutDYYdN9W945RiHn6mjBrCaTyxYh GunD7Ub2mjoivkgSQt3NlQRRI8bbgKGXYuAJD8tFiZtBYbh394mPHBS3j/cbkc4k mbnO2v2nR9DUd2TgHJ/gpvSQij7ullKpOc59h36wNAtKtlLpacEEdd6rJBVwIDOy oUlfO5lW/8Aw9K6nh/SuKLV7a1qIu/s4Lkv+8tQpzkgrnRPh1Nd0OJpoXNuBOfx4 Nipj07yGV6PWtBWAvOkKXSC7ZxudmlUFc4UHPwLZsh49xjZJGSrspJETexknu9pA FGqXAqE2kJhAWtehOiy7TKbIuOj1qKE+nEm1Ru44jwIDAQABo4GaMIGXMFsGA1Ud IwRUMFKhTaRLMEkxEDAOBgNVBAMMB1Jvb3QgQ0ExGjAYBgNVBAsMEVNlcnZlciBP cGVyYXRpb25zMRkwFwYDVQQKDBBFeGFtcGxlIE9yZywgTExDggECMAwGA1UdEwEB /wQCMAAwCwYDVR0PBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD AjANBgkqhkiG9w0BAQsFAAOCAQEAHwlUEuXe8jtnvdX49q3JVYs/wu+NsMg0+jHO 3JKWHz+2xjOYrWK1CgoAADAXE7/KH/7XPho9EqSlR0eANtUvHcOLuruYxrQgPX0T nkyjLLEF4Bc5rh45XrDtZuvHbhtqhEKMRs9yjlVCCKBUJF4mVH3dNapSnZaXfSOh VsmK0Ylt2iP11zbD4ncOnCCb4GKIqi0QW4rILdSHy8L3NxWCKP5QV7G0dQAYw0TX syfA4NvG9SgGA/tR62B/+IO62ZYPTBdVceTWZDs1DolimM5g80DTl9kz3nLaPvNv k5pnJWP5FV07PVgEf6I5xVok+l2wibewBBTAROa9I0FMfK/k8g== -----END CERTIFICATE----- 04.pem000066400000000000000000000025631470345337400357460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca/certs-----BEGIN CERTIFICATE----- MIID2TCCAsGgAwIBAgIBBDANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFow RTEiMCAGA1UEAwwZbWFzdGVyLWVtYWlsMS5leGFtcGxlLm9yZzEfMB0GCSqGSIb3 DQEJARYQdGVzdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAK+DZO+xbJow5kzEP13hC2XkPjY5MZZg7sX5VuGtwhSD0vberSxijokB RR9U5RAp5AmWEpbJcNuL4wUyQ0yA/E0FSc6BhDwT25aA2l8CiIGpMmLmMw4M80K1 SXuHeXU/g+7MBmaYC4AxYbsxr1us+c1IpNYl9rO/4ZuUIgOHKjnnBHKYZqpNVmXS 4ss3o74rrHkIWLvBI43Mz4Ct2LZMSkaqqESvIfBKpW9LndtoKyIaaoxnXivC7oiG pbEfot0pvoCNV7Wfj7zFVQUdKdJTa5XHvshXoFdrnNHfZKVb6AIAbvZidzcBuT54 Ib4KFjIV3VxfJkQ/U0VTn4zhK+t2EuMCAwEAAaOBmjCBlzBbBgNVHSMEVDBSoU2k SzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9u czEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMBAf8EAjAAMAsG A1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZI hvcNAQELBQADggEBAJ083++L/CwcyFhC3FvaRX6dYQB5LlqPQs7E6GRZq4wL2Boo rNeWVTOhhjdxjmbLBLJ/VDOzxW5mCIVil8mHbTYUrmt77lfXkeB1Gb4sx8s3SbdK 10mmAhrV7eLjeV1Y/Tt9G4ZU3RbK78O/GXCg5Vp1S6GPUBMxlgm5K1IibpKxz5Cz yU6EN0seAhKB/MWiSWILcJy8sbySThLDy0wLzvUDFqHlVvj3XtBd08qp1Pov+r73 pBjgDHJvunxJ93DDfhiMPgoOIMcvijZmOQ+2cFfbhwlyJH3m90PbpaW8H0BNFBLT csvsTzHsS78o9usu+Sv/NpmDnzvOu1rzSCMmu58= -----END CERTIFICATE----- 05.pem000066400000000000000000000025631470345337400357470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca/certs-----BEGIN CERTIFICATE----- MIID2TCCAsGgAwIBAgIBBTANBgkqhkiG9w0BAQsFADB+MSQwIgYDVQQDDBtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsMEVNl cnZlciBPcGVyYXRpb25zMB4XDTIzMDQxMjIyNDE1OFoXDTQzMDQwNzIyNDE1OFow RTEiMCAGA1UEAwwZbWFzdGVyLWVtYWlsMi5leGFtcGxlLm9yZzEfMB0GCSqGSIb3 DQEJARYQdGVzdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAL5w5qggNQUtGSgga5SPGHr5J8uIrg1IE/WR/p83V2pV+QyAJQChmIhT sBx87INcl89jo39a7LWoeXa3gUaXgP+6JY4A7E4nEbTveqBr+vKLdeZjyC0DwhIx 4Y6scXD9O2OeXH/qKdEHLnHAtKZBFIHY0YDDVVOrpS7DNtCZe4KTuX/97dxl+Qez nejIIY8vhYz5Cnhfad5KEKIuoKzj25ZGxcPr3/BeZ8IOr2/vqW6r1qWFCx/7X23Z VX94c7RYacqiixIUAf1Q6+9EoVhLUctuwnfTCqb5HX2zKrcsVAG9tirg5bQeqF9i MQDblarSN1LRbItL/0q7ZRSgZ8kMnKUCAwEAAaOBmjCBlzBbBgNVHSMEVDBSoU2k SzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9u czEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMBAf8EAjAAMAsG A1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZI hvcNAQELBQADggEBABhJx2HxQf/RMxdTzikFAqFL4e6xlOSZtTBO2jgD6gGJiBmR qHB/2XXhOg6lUUm3woVCC6CCNYv47OHtA2geDA5lBEfLGQJOPMMCR/z98QKX6jVE SVQNy3DwNmuWBTCBA3L9ArQ9FL2NhXnDhyOjVM/u4/dpYNXegzeA4du8BVblObo+ UY28OtNkZ72MSSGV95kAiqltBSYEJhFw8c57kAeIrgOgWy2XKaUToLICSV19BYAM IzR2HLwtmAYvga59xqSKyqmnJXiZpJqEae9XwR4JsWuYN5nwualobsAR8JPI46vU 05SYeaz1hwYollWM0iIQcXwArWFyvLXGFApQdQc= -----END CERTIFICATE----- inventory.txt000066400000000000000000000005301470345337400364660ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-caR 430407224157Z 230412224158Z 01 unknown /CN=master1.example.org V 430407224158Z 02 unknown /CN=master2.example.org V 430407224158Z 03 unknown /CN=agent1.example.org V 430407224158Z 04 unknown /CN=master-email1.example.org/emailAddress=test@example.com V 430407224158Z 05 unknown /CN=master-email2.example.org/emailAddress=test@example.com inventory.txt.attr000066400000000000000000000000251470345337400374360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-caunique_subject = yes inventory.txt.attr.old000066400000000000000000000000251470345337400402130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-caunique_subject = yes inventory.txt.old000066400000000000000000000005131470345337400372440ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-caV 430407224157Z 01 unknown /CN=master1.example.org V 430407224158Z 02 unknown /CN=master2.example.org V 430407224158Z 03 unknown /CN=agent1.example.org V 430407224158Z 04 unknown /CN=master-email1.example.org/emailAddress=test@example.com V 430407224158Z 05 unknown /CN=master-email2.example.org/emailAddress=test@example.com openssl.conf000066400000000000000000000053041470345337400362260ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-caSAN = DNS:puppet [ca] default_ca = master_ca_config # Root CA [root_ca_config] certificate = /tmp/certchain.HHLFb2ep/master-ca/ca-master-ca.crt private_key = /tmp/certchain.HHLFb2ep/master-ca/ca-master-ca.key database = /tmp/certchain.HHLFb2ep/master-ca/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/master-ca/certs serial = /tmp/certchain.HHLFb2ep/master-ca/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 policy = root_ca_policy x509_extensions = root_ca_exts [root_ca_policy] commonName = supplied emailAddress = supplied organizationName = supplied organizationalUnitName = supplied [root_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:true keyUsage = keyCertSign, cRLSign # Master CA [master_ca_config] certificate = /tmp/certchain.HHLFb2ep/master-ca/ca-master-ca.crt private_key = /tmp/certchain.HHLFb2ep/master-ca/ca-master-ca.key database = /tmp/certchain.HHLFb2ep/master-ca/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/master-ca/certs serial = /tmp/certchain.HHLFb2ep/master-ca/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 policy = master_ca_policy x509_extensions = master_ca_exts # Master CA (Email) [master_ca_email_config] certificate = /tmp/certchain.HHLFb2ep/master-ca/ca-master-ca.crt private_key = /tmp/certchain.HHLFb2ep/master-ca/ca-master-ca.key database = /tmp/certchain.HHLFb2ep/master-ca/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/master-ca/certs serial = /tmp/certchain.HHLFb2ep/master-ca/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 email_in_dn = yes policy = master_ca_email_policy x509_extensions = master_ca_exts [master_ca_policy] commonName = supplied [master_ca_email_policy] commonName = supplied emailAddress = supplied # default extensions for clients [master_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth [master_ssl_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth subjectAltName = $ENV::SAN # extensions for the master certificate (specifically adding subjectAltName) [master_self_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth # include the master's fqdn here, as well as in the CN, to work # around https://bugs.ruby-lang.org/issues/6493 # NOTE: Alt Names should be set in the request, so they know # their FQDN # subjectAltName = DNS:puppet,DNS:master-ca.example.org serial000066400000000000000000000000031470345337400350650ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca06 serial.old000066400000000000000000000000031470345337400356420ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/master-ca05 puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root/000077500000000000000000000000001470345337400330605ustar00rootroot00000000000000ca-root.crl000066400000000000000000000011211470345337400350420ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root-----BEGIN X509 CRL----- MIIBjjB4MA0GCSqGSIb3DQEBCwUAMEkxEDAOBgNVBAMMB1Jvb3QgQ0ExGjAYBgNV BAsMEVNlcnZlciBPcGVyYXRpb25zMRkwFwYDVQQKDBBFeGFtcGxlIE9yZywgTExD Fw0yMzA0MTIyMjQxNTdaFw00MzA0MDcyMjQxNTdaMA0GCSqGSIb3DQEBCwUAA4IB AQAtt9DKR6C9F5ARt9YxGa+p9sSsNDKm8GrD1Tj2+wuYzybH6hMH8sPD1+MQ3LfH +L01Bu92Lnc9t3V8UCnjQuW8UbqzbxaYOUxGmdr8waQ9Sk8FvzxjZq2635OyZHDM LcsGPCZvXG3pNN9V/hnjxSK9EpXz8Tw3t0Wb9+fR5aRWnW8Cx/8vkyj9IZQEgPJ9 YWngFA0LJuAHNNXcCiu1KDVFbeiaoAY6nbI8u/ZGtfab+EMfNVkbKWr0/j/kVis/ LdvRRLFg2Dej6UfaktgfJTIircbPMt0+0M/EqW+ifkljlqaUv1wMawJOw+gJdNxc 12GvgcZUh5Gj1HaYV2SY7OD/ -----END X509 CRL----- ca-root.crt000066400000000000000000000023511470345337400350600ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root-----BEGIN CERTIFICATE----- MIIDczCCAlugAwIBAgIULxTl39bugVS0Jwy4ZWpV3IIWTjcwDQYJKoZIhvcNAQEL BQAwSTEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9wZXJhdGlv bnMxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMwHhcNMjMwNDEyMjI0MTU3WhcN NDMwNDA3MjI0MTU3WjBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2 ZXIgT3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzCCASIwDQYJ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7EDBWTX9RTzT1VrDqPM1TKtQejvJ+8 RXmOleEWc9dF6nREnwPOozrCx9E2AgopEFLGpo/2oYFOPMoXAMCTmga1YYq+mls5 9lYFB2eaL9hbTe6GaDXV13c2eQexfR+3I/b3aRmQv/w6jnHlQCqmvxZ3ttVoc6f2 +aVjBvOTG9Bt2/N9BrslW1//9QaNUIVR7QRa9mOEICZ/ZCwdDDt5L0co5jsqRMgO tiWsu4Q2XtLWiBzhp61+cVLSdxabkWy127qN/dBRMbGk2aCCjqIvQaAZy2rv4LL/ JDhnLC5s/e5IdQ0ArJBhaOhDz5n38u3TSWpiWMywmMEbs+IDHySvqakCAwEAAaNT MFEwHQYDVR0OBBYEFPWQhkterSX1ED/ePsbUn0I/h6qvMB8GA1UdIwQYMBaAFPWQ hkterSX1ED/ePsbUn0I/h6qvMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL BQADggEBAGMECPlztKldxlL6+s5XdHx7hEm27DnJ/YhFZek6kE23dIkaAszHvmNU Z7HY64XcwS95XHC/0mwnv5t/aIrxvAXHsVrvOB4t6BrvVxXeUaF51LxoE69gDHsZ Y1BhwULu6+i2i779O5AKniAh7gvD3MzEp62cD4ZIjauB/UXu9l9ww75kqKBiNuUL vA7Wttc5u/3b3i2nqJOXZUcl5AVzLyDfBofh+yENiZ7Ra0gy0lLiZ6PF5eevMrhC 46HWVIPk7YAeqGMCeu/wSh177AOI7C1uQ7QLXOM09NUHB0AACmNIxY0TOGJCM8Vn 10RDUEG3ImtPZhKxXZIVUOcT162RYbI= -----END CERTIFICATE----- ca-root.key000066400000000000000000000032501470345337400350570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOxAwVk1/UU809 Vaw6jzNUyrUHo7yfvEV5jpXhFnPXRep0RJ8DzqM6wsfRNgIKKRBSxqaP9qGBTjzK FwDAk5oGtWGKvppbOfZWBQdnmi/YW03uhmg11dd3NnkHsX0ftyP292kZkL/8Oo5x 5UAqpr8Wd7bVaHOn9vmlYwbzkxvQbdvzfQa7JVtf//UGjVCFUe0EWvZjhCAmf2Qs HQw7eS9HKOY7KkTIDrYlrLuENl7S1ogc4aetfnFS0ncWm5Fstdu6jf3QUTGxpNmg go6iL0GgGctq7+Cy/yQ4ZywubP3uSHUNAKyQYWjoQ8+Z9/Lt00lqYljMsJjBG7Pi Ax8kr6mpAgMBAAECggEBALGzA7+3PPC6ZPWFn9NkJvWEkTjTm9ScdgkWZfFg3oXw 7KKoJxGakeZ6aEiBZhddW04ItDWd/QeoOc5lHpxjPkjtsbsQPJCSrAcZo1eCyAPl 1IBeu0kpU1h9VF8sRyDuwNYLpCP4p0ca/DkekZsWW7vvfw7CCkQcmkltZhgIIitp 8qW7izPYoggPBJqaJP/8z3j6J3oCJ/r6GGzV2h/yKXLVcgw5SZ8sLQxwoakbFqAy dxRSwQ3Rb3IUX0GTbFHePZ4CJ57PpZgyFfPfUwRmIKnS/UJpymywBBVvIpEKOduC xqRUSu/kR8GEnsJsZtOzkFdaXIN7OBzWbJYPtOW1VVECgYEA+NQ+O38EhOU0GjGY JCniB7F4RQVKVi95PWODOsgnx18ItFKGK5eHsrStpsOgni0Ks4JMQvUdpgGfrYYa 5jhIPQTcylbrvwiEydUh4pIzsKm5wrRzEr5lHHyAL4dFMO0S62QUgqFucDfGJqOB hJpzx94delXIrPfIcdu6J4At+b8CgYEA1Ll6moOKyQ8uVfFqedCQ5VodLXMNnpAY OcTYZnfTUU3HMoBJraGoGdrtPIX8WLHTpsIQNv5coAgTv0PzTnpuBbOHnWO6efOm D4NJOWrTWJpddOFvKlHIsjTJxVQtCrOX9RMQtcJNIVngiuoogOfcWf31LzIhVkT+ 7h6EsfNBJpcCgYBMsOXJYpma+CW52QVCSCJhKqKd60aBD7q3X/9nU59nBHRjV3gA 4YAyZRuMZYkQl2NP9l3Y2UFdE+0KB2YtBLXHEMOYHXglddOvfWAnO9Zwoa8eQo2g /kudnwXHIFMEBF2rbTohFO476gTJjeVyYERFGsFNHjlujiQaa5WRbSE+cwKBgQCt ZB4eUfhPGFOxc91RO4LPn5tGz5AbXeKRO/UT2LnjfJ1QeacUoz7tDDjxa1kcRp55 P5eN69k+DDdkYJOytTJ27TYuQPrfqo0B+gY2ie+JOhHRUmuVOCJ5t3N7p7grD+Zd udOWA7Fw7NyM/n5TTCqdI9a1SIxJ0GVnXHLWxaumMwKBgBBtS0ZpDBv3YtTpOUFe BekF2VrWh+1OXWZhmAEbBYHiaYJ3JVapcZbiU4uoVzo5mDRiXL8MxfJE+VmKrewl IKIjAuA6PhsNKJWCBptoIOOdmQnl0F/NRiy7+7sc+oNeHggp0zrRGoowtAUWgOzr 6EKRSKjF3GiMdb5RfS6DDNBO -----END PRIVATE KEY----- puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root/certs/000077500000000000000000000000001470345337400342005ustar00rootroot0000000000000001.pem000066400000000000000000000026131470345337400350460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root/certs-----BEGIN CERTIFICATE----- MIID6jCCAtKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBJMRAwDgYDVQQDDAdSb290 IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBs ZSBPcmcsIExMQzAeFw0yMzA0MTIyMjQxNTdaFw00MzA0MDcyMjQxNTdaMH0xIzAh BgNVBAMMGkludGVybWVkaWF0ZSBDQSAoYWdlbnQtY2EpMR8wHQYJKoZIhvcNAQkB FhB0ZXN0QGV4YW1wbGUub3JnMRkwFwYDVQQKDBBFeGFtcGxlIE9yZywgTExDMRow GAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAJ1EAzT0LLWHkeo8meKuMjMR2RI53lHwkSWNohBOPVA3lY+5UGei lyrkIb9H22ZR8DnNz7JjkJkC6Uu55PwFh2d2Q60wZLqlX21jRvmsCzfdGt/brD6Q q43mAJp7MyD3+31lmv2wmKvMPWoq6u+tjjDbtEey7HAiJxQ/KCGPqcUv5RFmqKz2 pfteWFxqHQUmn4JABZpte7Fl4/dQyw/6r7ctEnKqVuF2lQzCS0awy3oYQr6Qwwbs HNTApjmW2EXTuWYTYQ/ftQeGN5QdQm+9fiKi45Z/HsY1z7vyUY5TjjSLITV0a420 v2WhW8ckMWrllwaCEzmfNcjx9W5FQm4w8+MCAwEAAaOBqDCBpTCBhAYDVR0jBH0w e4AU9ZCGS16tJfUQP94+xtSfQj+Hqq+hTaRLMEkxEDAOBgNVBAMMB1Jvb3QgQ0Ex GjAYBgNVBAsMEVNlcnZlciBPcGVyYXRpb25zMRkwFwYDVQQKDBBFeGFtcGxlIE9y ZywgTExDghQvFOXf1u6BVLQnDLhlalXcghZONzAPBgNVHRMBAf8EBTADAQH/MAsG A1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEALw/RGiXdEZQ+rj43BqeOlAas mUpHnhmc9XPVNtkgRTf9DYc/NxRFBLNC8eBnThcZGTlN7c025xYkjQsIvs6gKD+y SKFLv0+eHuCywrDgAZCAcFC+ekXu5b7BfKMfjkWJHELYEIomgVHY4mj6blZ5lmWk Mmr8qYzDAWYD6Rits21YMKyMWcAcoTed9GQFwZOhLJHAG4lvoRd6qXAK+U7dIoQh vf5CGFP2YO71un22IGRy5QJhoDyxV3yHbbiv7zS+NPn1bOQOfKRGu58PxfsyO3BT aWGyMzLhxPB6ufAQo7fWX1jOqPxJ1aMS9+aAba7QW/QrOX+LAlAulS034izUFA== -----END CERTIFICATE----- 02.pem000066400000000000000000000026131470345337400350470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root/certs-----BEGIN CERTIFICATE----- MIID6zCCAtOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBJMRAwDgYDVQQDDAdSb290 IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBs ZSBPcmcsIExMQzAeFw0yMzA0MTIyMjQxNTdaFw00MzA0MDcyMjQxNTdaMH4xJDAi BgNVBAMMG0ludGVybWVkaWF0ZSBDQSAobWFzdGVyLWNhKTEfMB0GCSqGSIb3DQEJ ARYQdGVzdEBleGFtcGxlLm9yZzEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQzEa MBgGA1UECwwRU2VydmVyIE9wZXJhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDAEPlZmffi8ZVgLS29BkwS1xSvWa/LAzL0oSN99sRcEXf5Aq94 n9uEq7XkooaM+/gfUBI1KGJBLwbKKtXc0xL0i9JGjMcFPMnlU5wCcgzK5KArB5OZ RV5MM06j86+/wDYDNojYxb1lvePJzv3qdKwkEVtIWRfA29FaMoEsqWWZvEsW5fb2 hE16JEsTJmHDdPu/AlvwXTmy4lkitS8quTMLkpedtz/Sp5wEuQFmgEmeHkZzRuD0 rpQe+xbDTSsnlib30Mjqi/dUgolseJqCX0RZ8rdxTARUXn+3aYwnZtS18Y12aj5h igBzVBZvxETE++MluDnZKATH2Tupejzx0Ts9AgMBAAGjgagwgaUwgYQGA1UdIwR9 MHuAFPWQhkterSX1ED/ePsbUn0I/h6qvoU2kSzBJMRAwDgYDVQQDDAdSb290IENB MRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBP cmcsIExMQ4IULxTl39bugVS0Jwy4ZWpV3IIWTjcwDwYDVR0TAQH/BAUwAwEB/zAL BgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAKqGMvKEylycCdwVe5idgQhF u0L81gLr4lcAo6AxCDQXbijD2G1n3SZFl6L/kbUf+S/n3Gk23uE6/Ml5EZYh4Z1V faNQeH2FHJmsLlPluNAlyCnL5x4KzExM4kRa/UKAf1nOg1ulkRzAAD5WofWipU9k W+x29VO1eibL0rsJehiASj5SqW9Vm5ZFz4vHeFxBPDNkyAqjPGXc8yZELjrWb0id nIP2nMN7PNZlWivwBzUwszJU0AxpNYDGbFBlI3ImpUxC5JvpF48ST0V7JzX4HWl7 IqJqxuDCIkFyiX6eU58n1MxXMsfzCZwR/F3iFOxHDmZjpRDqZAa77WkNYI6QVXA= -----END CERTIFICATE----- inventory.txt000066400000000000000000000004031470345337400355740ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/rootV 430407224157Z 01 unknown /CN=Intermediate CA (agent-ca)/emailAddress=test@example.org/O=Example Org, LLC/OU=Server Operations V 430407224157Z 02 unknown /CN=Intermediate CA (master-ca)/emailAddress=test@example.org/O=Example Org, LLC/OU=Server Operations inventory.txt.attr000066400000000000000000000000251470345337400365450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/rootunique_subject = yes inventory.txt.attr.old000066400000000000000000000000251470345337400373220ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/rootunique_subject = yes inventory.txt.old000066400000000000000000000002011470345337400363450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/rootV 430407224157Z 01 unknown /CN=Intermediate CA (agent-ca)/emailAddress=test@example.org/O=Example Org, LLC/OU=Server Operations openssl.conf000066400000000000000000000051241470345337400353350ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/rootSAN = DNS:puppet [ca] default_ca = root_ca_config # Root CA [root_ca_config] certificate = /tmp/certchain.HHLFb2ep/root/ca-root.crt private_key = /tmp/certchain.HHLFb2ep/root/ca-root.key database = /tmp/certchain.HHLFb2ep/root/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/root/certs serial = /tmp/certchain.HHLFb2ep/root/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 policy = root_ca_policy x509_extensions = root_ca_exts [root_ca_policy] commonName = supplied emailAddress = supplied organizationName = supplied organizationalUnitName = supplied [root_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:true keyUsage = keyCertSign, cRLSign # Master CA [master_ca_config] certificate = /tmp/certchain.HHLFb2ep/root/ca-root.crt private_key = /tmp/certchain.HHLFb2ep/root/ca-root.key database = /tmp/certchain.HHLFb2ep/root/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/root/certs serial = /tmp/certchain.HHLFb2ep/root/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 policy = master_ca_policy x509_extensions = master_ca_exts # Master CA (Email) [master_ca_email_config] certificate = /tmp/certchain.HHLFb2ep/root/ca-root.crt private_key = /tmp/certchain.HHLFb2ep/root/ca-root.key database = /tmp/certchain.HHLFb2ep/root/inventory.txt new_certs_dir = /tmp/certchain.HHLFb2ep/root/certs serial = /tmp/certchain.HHLFb2ep/root/serial default_crl_days = 7300 default_days = 7300 default_md = sha256 email_in_dn = yes policy = master_ca_email_policy x509_extensions = master_ca_exts [master_ca_policy] commonName = supplied [master_ca_email_policy] commonName = supplied emailAddress = supplied # default extensions for clients [master_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth [master_ssl_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth subjectAltName = $ENV::SAN # extensions for the master certificate (specifically adding subjectAltName) [master_self_ca_exts] authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:false keyUsage = keyEncipherment, digitalSignature extendedKeyUsage = serverAuth, clientAuth # include the master's fqdn here, as well as in the CN, to work # around https://bugs.ruby-lang.org/issues/6493 # NOTE: Alt Names should be set in the request, so they know # their FQDN # subjectAltName = DNS:puppet,DNS:root.example.org puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root/serial000066400000000000000000000000031470345337400342530ustar00rootroot0000000000000003 serial.old000066400000000000000000000000031470345337400347510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/fixtures/root02 puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/intermediate_ca.rb000066400000000000000000000126761470345337400337020ustar00rootroot00000000000000# Test setting up Puppet Server as an Intermediate CA # using the `puppetserver ca` subcommand. require 'puppet_x/acceptance/pki' test_name 'Intermediate CA import' do test_agent = (agents - [master]).first skip_test 'requires an agent not running on the CA' unless test_agent def fixture(filename) File.read( File.expand_path( File.join('..', 'fixtures', 'chain', filename), __FILE__)) end # We set these variables outside of a step block so that we can use it # in multiple steps and the teardown below ssl_directory = puppet_config(master, 'ssldir', section: 'master') ca_directory = puppet_config(master, 'cadir', section: 'master') auth_conf = "/etc/puppetlabs/puppetserver/conf.d/auth.conf" test_directory = master.tmpdir('intermediate_ca_files') backup_directory = master.tmpdir('intermediate_ca_backup') pki = PuppetX::Acceptance::PKI.create_chained_pki(master.to_s) cert_bundle_path = test_directory + '/' + 'cert_bundle.pem' private_key_path = test_directory + '/' + 'private_key.pem' crl_chain_path = test_directory + '/' + 'crl_chain.pem' step 'Stop and backup the CA' do on master, "service #{master['puppetservice']} stop" on master, "mkdir -p #{backup_directory}/{ca,ssl}" on master, "cp -pR #{ca_directory}/* #{backup_directory}/ca" on master, "rm -rf #{ca_directory}/*" on master, "cp -pR #{ssl_directory}/* #{backup_directory}/ssl" on master, "rm -rf #{ssl_directory}/*" on master, "mv #{auth_conf} #{backup_directory}/" end step 'Disable communication to services already configured to use older PKI' do on master, puppet('config set --section master route_file /tmp/nonexistent.yaml') if master.is_pe? on master, puppet('config set --section master report false') on master, puppet('config set --section master storeconfigs false') on master, puppet('config set --section master node_terminus plain') end end step 'Put test specific files in place' do create_remote_file master, auth_conf, <<-AUTHCONF authorization: { version: 1 rules: [ { match-request: { path: "/" type: path } allow-unauthenticated: true sort-order: 999 name: "allow all" } ] } AUTHCONF on master, "chmod go+r #{auth_conf}" create_remote_file master, cert_bundle_path, pki[:cert_bundle] create_remote_file master, private_key_path, pki[:private_key] create_remote_file master, crl_chain_path, pki[:crl_chain] end teardown do on master, "service #{master['puppetservice']} stop" on master, "rm -rf #{ssl_directory}/*" on master, "cp -pR #{backup_directory}/ssl/* #{ssl_directory}/" on master, "rm -rf #{ca_directory}/*" on master, "cp -pR #{backup_directory}/ca/* #{ca_directory}/" on master, puppet('config set --section master route_file /etc/puppetlabs/puppet/routes.yaml') if master.is_pe? on master, puppet('config set --section master report true') on master, puppet("config set --section master storeconfigs true") on master, puppet("config set --section master node_terminus classifier") end on master, "service #{master['puppetservice']} start" end step 'Import External CA infrastructure and restart Puppet Server' do ca_cli = '/opt/puppetlabs/bin/puppetserver' on master, [ca_cli, 'ca', 'import', '--private-key', private_key_path, '--cert-bundle', cert_bundle_path, '--crl-chain', crl_chain_path].join(' ') on master, "service #{master['puppetservice']} start" end step 'Remove the old CA infrastructure from an agent' do ssldir = puppet_config(test_agent, 'ssldir', section: 'agent') on test_agent, "rm -rf #{ssldir}" end # We use the master's PKI with curl since it won't change again until after # the test, though all curl calls below need to happen on the master. cert = puppet_config(master, 'hostcert', section: 'master') cacert = puppet_config(master, 'localcacert', section: 'master') key = puppet_config(master, 'hostprivkey', section: 'master') ssl_options = "--cert #{cert} --cacert #{cacert} --key #{key}" step 'Download the intermediate PKI and submit a test CSR' do on test_agent, puppet("agent -t --certname fake_agent_name --server #{master}"), :acceptable_exit_codes => [1] end step 'Sign the cert and verify the agent runs correctly with its new PKI' do on master, "curl -XPUT #{ssl_options} " + %q<-H 'Content-Type: application/json' -d '{"desired_state":"signed"}' > + "--url https://#{master}:8140/puppet-ca/v1/certificate_status/fake_agent_name?environment=production" on test_agent, puppet("agent -t --certname fake_agent_name --server #{master} --noop") end step 'Verify revocation works as expected' do on master, "curl -XPUT #{ssl_options} " + %q<-H 'Content-Type: application/json' -d '{"desired_state":"revoked"}' > + "--url https://#{master}:8140/puppet-ca/v1/certificate_status/fake_agent_name?environment=production" on master, "curl -XDELETE -H 'Content-Type: application/json' #{ssl_options} " + "--url https://#{master}:8140/puppet-ca/v1/certificate_status/fake_agent_name?environment=production" on test_agent, puppet("agent -t --certname fake_agent_name --server #{master}"), :acceptable_exit_codes => [1] end end puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/certificate_authority/split_external_cas.rb000066400000000000000000000167231470345337400344450ustar00rootroot00000000000000require 'puppet_x/acceptance/external_cert_fixtures' confine :except, :type => 'pe' # Verify that a trivial manifest can be run to completion. # Supported Setup: Single, Root CA # - Agent and Master SSL cert issued by the Root CA # - Revocation disabled on the agent `certificate_revocation = false` # - CA disabled on the master `ca = false` # test_name "Puppet agent and master work when both configured with externally issued certificates from independent intermediate CAs" tag 'audit:medium', 'audit:integration', # This could also be a component in a platform workflow test. 'server' step "Copy certificates and configuration files to the master..." fixture_dir = File.expand_path('../fixtures', __FILE__) testdir = master.tmpdir('jetty_external_root_ca') backupdir = master.tmpdir('jetty_external_root_ca_backup') fixtures = PuppetX::Acceptance::ExternalCertFixtures.new(fixture_dir, testdir) jetty_confdir = master['puppetserver-confdir'] # Register our cleanup steps early in a teardown so that they will happen even # if execution aborts part way. teardown do step "Restore /etc/hosts and puppetserver configs; Restart puppetserver" on master, "cp -p '#{backupdir}/hosts' /etc/hosts" on master, puppet('config set route_file /etc/puppetlabs/puppet/routes.yaml') # Please note that the escaped `\cp` command below is intentional. Most # linux systems alias `cp` to `cp -i` which causes interactive mode to be # invoked when copying directories that do not yet exist at the target # location, even when using the force flag. The escape ensures that an # alias is not used. on master, "\\cp -frp #{backupdir}/puppetserver/* #{jetty_confdir}/../" on(master, "service #{master['puppetservice']} restart") end # Backup files in scope for modification by test on master, "cp -p /etc/hosts '#{backupdir}/hosts'" on master, "cp -rp '#{jetty_confdir}/..' '#{backupdir}/puppetserver'" # Read all of the CA certificates. # Copy all of the x.509 fixture data over to the master. create_remote_file master, "#{testdir}/ca_root.crt", fixtures.root_ca_cert create_remote_file master, "#{testdir}/ca_agent.crt", fixtures.agent_ca_cert create_remote_file master, "#{testdir}/ca_master.crt", fixtures.master_ca_cert create_remote_file master, "#{testdir}/ca_master.crl", fixtures.master_ca_crl create_remote_file master, "#{testdir}/ca_master_bundle.crt", "#{fixtures.master_ca_cert}\n#{fixtures.root_ca_cert}\n" create_remote_file master, "#{testdir}/ca_agent_bundle.crt", "#{fixtures.agent_ca_cert}\n#{fixtures.root_ca_cert}\n" create_remote_file master, "#{testdir}/agent.crt", fixtures.agent_cert create_remote_file master, "#{testdir}/agent.key", fixtures.agent_key create_remote_file master, "#{testdir}/agent_email.crt", fixtures.agent_email_cert create_remote_file master, "#{testdir}/agent_email.key", fixtures.agent_email_key create_remote_file master, "#{testdir}/master.crt", fixtures.master_cert create_remote_file master, "#{testdir}/master.key", fixtures.master_key create_remote_file master, "#{testdir}/master_rogue.crt", fixtures.master_cert_rogue create_remote_file master, "#{testdir}/master_rogue.key", fixtures.master_key_rogue ## # Now create the master and agent puppet.conf # on master, "mkdir -p #{testdir}/etc/agent" # Make master1.example.org resolve if it doesn't already. on master, "grep -q -x '#{fixtures.host_entry}' /etc/hosts || echo '#{fixtures.host_entry}' >> /etc/hosts" create_remote_file master, "#{testdir}/etc/agent/puppet.conf", fixtures.agent_conf create_remote_file master, "#{testdir}/etc/agent/puppet.conf.crl", fixtures.agent_conf_crl create_remote_file master, "#{testdir}/etc/agent/puppet.conf.email", fixtures.agent_conf_email # auth.conf to allow *.example.com access to the rest API create_remote_file master, "#{jetty_confdir}/auth.conf", fixtures.auth_conf # set use-legacy-auth-conf = false # to override the default setting in older puppetserver versions modify_tk_config(master, options['puppetserver-config'], {'jruby-puppet' => {'use-legacy-auth-conf' => false}}) step "Set filesystem permissions and ownership for the master" # These permissions are required for the JVM to start Puppet as puppet on master, "chown -R puppet:puppet #{testdir}/*.{crt,key,crl}" # These permissions are just for testing, end users should protect their # private keys. on master, "chmod -R a+rX #{testdir}" agent_cmd_prefix = "--confdir #{testdir}/etc/agent --vardir #{testdir}/etc/agent/var" # Move the agent SSL cert and key into place. # The filename must match the configured certname, otherwise Puppet will try # and generate a new certificate and key step "Configure the agent with the externally issued certificates" on master, "mkdir -p #{testdir}/etc/agent/ssl/{public_keys,certs,certificate_requests,private_keys,private}" create_remote_file master, "#{testdir}/etc/agent/ssl/certs/#{fixtures.agent_name}.pem", fixtures.agent_cert create_remote_file master, "#{testdir}/etc/agent/ssl/private_keys/#{fixtures.agent_name}.pem", fixtures.agent_key create_remote_file master, "#{jetty_confdir}/webserver.conf", fixtures.jetty_webserver_conf_for_trustworthy_master master_opts = { 'master' => { 'certname' => fixtures.master_name, 'ssl_client_header' => "HTTP_X_CLIENT_DN", 'ssl_client_verify_header' => "HTTP_X_CLIENT_VERIFY" } } # disable CA service # https://github.com/puppetlabs/puppetserver/blob/master/documentation/configuration.markdown#service-bootstrapping create_remote_file master, "#{jetty_confdir}/../services.d/ca.cfg", "puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service" # disable pdb connectivity on master, puppet('config set --section master route_file /tmp/nonexistent.yaml') # restart master on(master, "service #{master['puppetservice']} restart") step "Start the Puppet master service..." with_puppet_running_on(master, master_opts) do # Now, try and run the agent on the master against itself. step "Successfully run the puppet agent on the master" on master, puppet_agent("#{agent_cmd_prefix} --test"), :acceptable_exit_codes => (0..255) do |result| refute_match /Creating a new SSL key/, result.stdout refute_match /\Wfailed\W/i, result.stderr refute_match /\Wfailed\W/i, result.stdout refute_match /\Werror\W/i, result.stderr refute_match /\Werror\W/i, result.stdout # Assert the exit code so we get a "Failed test" instead of an "Errored test" assert result.exit_code == 0 end step "Master accepts client cert with email address in subject" on master, "cp #{testdir}/etc/agent/puppet.conf{,.no_email}" on master, "cp #{testdir}/etc/agent/puppet.conf{.email,}" on master, puppet_agent("#{agent_cmd_prefix} --test"), :acceptable_exit_codes => (0..255) do |result| refute_match /\Wfailed\W/i, result.stdout refute_match /\Wfailed\W/i, result.stderr refute_match /\Werror\W/i, result.stdout refute_match /\Werror\W/i, result.stderr # Assert the exit code so we get a "Failed test" instead of an "Errored test" assert result.exit_code == 0 end step "Agent refuses to connect to revoked master" on master, "cp #{testdir}/etc/agent/puppet.conf{,.no_crl}" on master, "cp #{testdir}/etc/agent/puppet.conf{.crl,}" revoke_opts = "--hostcrl #{testdir}/ca_master.crl" on master, puppet_agent("#{agent_cmd_prefix} #{revoke_opts} --test"), :acceptable_exit_codes => (0..255) do |result| assert_match /certificate revoked.*?example.org/, result.stderr assert result.exit_code == 1 end end step "Finished testing External Certificates" puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/code_commands/000077500000000000000000000000001470345337400264255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/code_commands/code_scripts.rb000066400000000000000000000164661470345337400314500ustar00rootroot00000000000000require 'json' skip_test 'SKIP: This test should only run in puppetserver FOSS.' if options[:type] == 'pe' skip_test 'SKIP: The required puppet module does not support Debian 8+' if master['platform'] =~ /debian/ test_name 'SERVER-1118: Validate code-id-command feature in FOSS' git_repo_parentdir=master.tmpdir('code_scripts_gitrepo') git_repo="#{git_repo_parentdir}/gitdir" git_local_repo=master.tmpdir('code_scripts_gitlocalrepo') hostname=on(master, 'facter hostname').stdout.strip fqdn=on(master, 'facter fqdn').stdout.strip def cicsetting(present_or_absent='present') cicsetting=<<-CICS hocon_setting { 'code-id-command-script' : ensure => #{present_or_absent}, path => '/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf', setting => 'versioned-code.code-id-command', value => '/opt/puppetlabs/server/apps/puppetserver/code-id-command_script.sh', } hocon_setting { 'code-content-command-script' : ensure => #{present_or_absent}, path => '/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf', setting => 'versioned-code.code-content-command', value => '/opt/puppetlabs/server/apps/puppetserver/code-content-command_script.sh', } CICS return cicsetting end teardown do # Remove the code-id script configuration from puppetserver.conf remove_cicsetting=cicsetting('absent') create_remote_file(master, '/tmp/config_code_id_command_script_disable.pp', remove_cicsetting) on master, 'puppet apply /tmp/config_code_id_command_script_disable.pp' reload_server on(master, 'puppet resource user git ensure=absent') on(master, "rm -rf #{git_repo_parentdir}", :accept_all_exit_codes => true) on(master, "rm -rf #{git_local_repo}", :accept_all_exit_codes => true) #remove code_* scripts. on(master, 'rm -rf /opt/puppetlabs/server/apps/puppetserver/code-id-command_script.sh') on(master, 'rm -rf /opt/puppetlabs/server/apps/puppetserver/code_content_script.sh') #uninstall r10k on(master, '/opt/puppetlabs/puppet/bin/gem uninstall r10k') #return /etc/puppetlabs/code to original state on(master, 'rm -rf /etc/puppetlabs/code') on(master, 'puppet resource file /etc/puppetlabs/code ensure=directory') end step 'SETUP: Install and configure git server' do on(master, 'puppet module install puppetlabs-git') git_config=<<-GIT user { 'git': ensure => present, # shell => '/usr/bin/git-shell', home => '/home/git', password => '*', managehome => true, system => true, } file { '/home/git': owner => 'git', ensure => 'directory', recurse => 'true', require => User['git'], } class { 'git': } GIT create_remote_file(master, '/tmp/git_setup.pp', git_config) on master, puppet_apply('/tmp/git_setup.pp') end step 'SETUP: Initialize the git control repository' do on master, "chown git #{git_repo_parentdir}" on master, "sudo -u git git init --bare #{git_repo}", :pty => true end step 'SETUP: Initialize the local git repository' do on master, "chown git #{git_local_repo}" on master, "git config --system --add safe.directory '*'" on master, "cd #{git_local_repo} && git config --global user.name 'TestUser'" on master, "cd #{git_local_repo} && git config --global user.email 'you@example.com'" on master, "cd #{git_local_repo} && git init" on master, "cd #{git_local_repo} && touch .gitignore" on master, "cd #{git_local_repo} && git add ." on master, "cd #{git_local_repo} && git commit -m 'initial commit'" on master, "cd #{git_local_repo} && git remote add origin file://#{git_repo}" on master, "cd #{git_local_repo} && git push origin master" end step 'SETUP: Install and configure r10k, and perform the initial commit' do on master, "puppet config set server #{fqdn}" on master, '/opt/puppetlabs/puppet/bin/gem install r10k --no-document' on master, "cd #{git_local_repo} && git checkout -b production" r10k_yaml=<<-R10K # The location to use for storing cached Git repos :cachedir: '/opt/puppetlabs/r10k/cache' # A list of git repositories to create :sources: # This will clone the git repository and instantiate an environment per # branch in /etc/puppetlabs/code/environments :my-org: remote: file://#{git_repo} basedir: '/etc/puppetlabs/code/environments' R10K on master, 'mkdir -p /etc/puppetlabs/r10k' create_remote_file(master, '/etc/puppetlabs/r10k/r10k.yaml', r10k_yaml) on master, 'chown puppet:root /etc/puppetlabs/r10k/r10k.yaml' on master, "cd #{git_local_repo} && mkdir -p {modules,site/profile/manifests,hieradata}" on master, "cd #{git_local_repo} && touch site/profile/manifests/base.pp" on master, "cd #{git_local_repo} && echo 'manifest = site.pp\nmodulepath = modules:site' > environment.conf" on master, "cd #{git_local_repo} && echo 'hiera_include(\'classes\')' > site.pp" common_yaml=<<-YAML --- classes: - 'profile::base' ntp::servers: - 0.us.pool.ntp.org - 1.us.pool.ntp.org YAML create_remote_file(master, "#{git_local_repo}/hieradata/common.yaml", common_yaml) hiera_yaml=<<-YAML --- version: 5 hierarchy: - name: Common path: common.yaml defaults: data_hash: yaml_data datadir: hieradata YAML create_remote_file(master, "#{git_local_repo}/hiera.yaml", hiera_yaml) puppetfile=<<-EOF forge 'forge.puppetlabs.com' # Forge Modules mod 'puppetlabs/ntp' mod 'puppetlabs/stdlib' EOF create_remote_file(master, "#{git_local_repo}/Puppetfile", puppetfile) base_pp=<<-PP class profile::base { class { '::ntp': } } PP create_remote_file(master, "#{git_local_repo}/site/profile/manifests/base.pp", base_pp) on master, "cd #{git_local_repo} && git add ." on master, "cd #{git_local_repo} && git commit -m 'commit to setup r10k example'" on master, "cd #{git_local_repo} && git push origin production" on master, "/opt/puppetlabs/puppet/bin/r10k deploy environment -p" end step 'SETUP: Install the code-id-command script' do code_id_command_script=<<-CIC #!/usr/bin/env sh /opt/puppetlabs/puppet/bin/r10k deploy display -p --detail $1 | grep signature | grep -oE '[0-9a-f]{40}' CIC create_remote_file(master, '/opt/puppetlabs/server/apps/puppetserver/code-id-command_script.sh', code_id_command_script) on(master, 'chown puppet:root /opt/puppetlabs/server/apps/puppetserver/code-id-command_script.sh') on(master, 'chmod 770 /opt/puppetlabs/server/apps/puppetserver/code-id-command_script.sh') end step 'SETUP: Configure the code-id script' do on master, 'puppet module install puppetlabs-hocon' create_remote_file(master, '/tmp/config_code_id_command_script.pp', cicsetting() ) on master, 'puppet apply /tmp/config_code_id_command_script.pp' reload_server end step 'Get the current code-id' current_code_id=on(master, '/opt/puppetlabs/server/apps/puppetserver/code-id-command_script.sh production').stdout.chomp step 'Pull the catalog, validate that it contains the current code-id' cacert ='/etc/puppetlabs/puppet/ssl/certs/ca.pem' key ="/etc/puppetlabs/puppet/ssl/private_keys/#{fqdn}.pem" hostcert ="/etc/puppetlabs/puppet/ssl/certs/#{fqdn}.pem" auth_str ="--cacert #{cacert} --key #{key} --cert #{hostcert}" result=on(master, "curl --silent #{auth_str} https://#{fqdn}:8140/puppet/v3/catalog/#{fqdn}?environment=production").stdout catalog=JSON.parse(result) assert_match(current_code_id, catalog['code_id'], "FAIL: Expected catalog to contain current_code_id #{current_code_id}.") puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/https/000077500000000000000000000000001470345337400247745ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/acceptance/suites/tests/https/client_may_use_external_cert_chains.rb000066400000000000000000000075441470345337400345770ustar00rootroot00000000000000test_name "Ensure Puppet Server's HTTP client may use external cert chains" do ## This test currently fails on FIPS (see PE-34102). Remove this once that is resolved. skip_test if master.fips_mode? reports_tmpdir = master.tmpdir('external-reports') server_key = reports_tmpdir + '/server.key' server_cert = reports_tmpdir + '/server.crt' server_rb = reports_tmpdir + '/server.rb' directory_to_serve = reports_tmpdir + '/public' generate_self_signed_cert = "openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout #{server_key} -out #{server_cert} -batch -addext 'subjectAltName = DNS:#{master}'" run_server = "/opt/puppetlabs/puppet/bin/ruby #{server_rb} &" kill_server = 'ps -ef | grep server.rb | grep -v grep | ruby -ne \'puts $_.split[1]\' | xargs -r kill' # `xargs -r` is a GNUism. wait_for_server = "for i in {1..40}; do if [[ 0 -ne `curl -ksw '%{exitcode}' 'https://#{master}:7777/' | tail -1` ]]; then echo 'sleeping and waiting'; sleep 2; else break; fi; done" check_for_webrick = %q{/opt/puppetlabs/puppet/bin/ruby -e "require 'webrick'"} server_script = < { 'reporturl' => "https://#{master}:7777/", 'report_include_system_store' => true, 'reports' => stores, 'ssl_trust_store' => server_cert } } teardown do on master, kill_server end # Test on master, generate_self_signed_cert # required so Puppet Server can read generated cert on master, "chmod +rx #{reports_tmpdir}" exit_code = on(master, check_for_webrick, acceptable_exit_codes: [0, 1]).exit_code if exit_code == 1 on master, '/opt/puppetlabs/puppet/bin/gem install webrick' end create_remote_file(master, server_rb, server_script) on master, "mkdir #{directory_to_serve}" on master, run_server on master, wait_for_server with_puppet_running_on(master, enable_https_report_processor_config) do on master, 'puppet agent -t', acceptable_exit_codes: [0,2] end report_content = on(master, "cat #{directory_to_serve}/#{master}").stdout.chomp assert_match /(un)?changed/, report_content system_ssl_tmpdir = master.tmpdir('system_ssl_store') script_location = system_ssl_tmpdir + '/connection_test.rb' test_script = < ["PC1"]}) package_build_version = ENV['PACKAGE_BUILD_VERSION'] if package_build_version.nil? abort("Environment variable PACKAGE_BUILD_VERSION required for package installs!") end step "Setup Puppet Server dev repository on the master." do install_puppetlabs_dev_repo(master, 'puppetserver', package_build_version, nil, install_opts) end step "Setup Puppet dev repository on all nodes." do hosts.each do |host| install_puppetlabs_dev_repo(host, 'puppet-agent', test_config[:puppet_build_version], nil, install_opts) end end step "Upgrade Puppet Server." do install_puppet_server_deps master.upgrade_package('puppetserver') on(master, puppet("resource service puppetserver ensure=stopped")) on(master, puppet("resource service puppetserver ensure=running")) end step "Upgrade Puppet agents" do nonmaster_agents.each do |agent| agent.upgrade_package('puppet-agent') end end step "Check that the master has Puppetserver 5.x installed" do on(master, "puppetserver --version") do |result| assert_match(/\Apuppetserver version: 5\./i, result.stdout, "puppetserver --version does not start with major version 5.") end end step "Verify that agents can connect to the server" do on hosts, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [0] end puppetlabs-puppetserver-7e1a9a8/dev-resources/000077500000000000000000000000001470345337400216545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/Makefile.i18n000066400000000000000000000141031470345337400240710ustar00rootroot00000000000000# -*- Makefile -*- # This file was generated by the i18n leiningen plugin # Do not edit this file; it will be overwritten the next time you run # lein i18n init # # The name of the package into which the translations bundle will be placed BUNDLE=puppetlabs.puppetserver # The name of the POT file into which the gettext code strings (msgid) will be placed POT_NAME=puppetserver.pot # The list of names of packages covered by the translation bundle; # by default it contains a single package - the same where the translations # bundle itself is placed - but this can be overridden - preferably in # the top level Makefile PACKAGES?=$(BUNDLE) LOCALES=$(basename $(notdir $(wildcard locales/*.po))) BUNDLE_DIR=$(subst .,/,$(BUNDLE)) BUNDLE_FILES=$(patsubst %,resources/$(BUNDLE_DIR)/Messages_%.class,$(LOCALES)) FIND_SOURCES=find src -name \*.clj # xgettext before 0.19 does not understand --add-location=file. Even CentOS # 7 ships with an older gettext. We will therefore generate full location # info on those systems, and only file names where xgettext supports it LOC_OPT=$(shell xgettext --add-location=file -f - /dev/null 2>&1 && echo --add-location=file || echo --add-location) LOCALES_CLJ=resources/locales.clj define LOCALES_CLJ_CONTENTS { :locales #{$(patsubst %,"%",$(LOCALES))} :packages [$(patsubst %,"%",$(PACKAGES))] :bundle $(patsubst %,"%",$(BUNDLE).Messages) } endef export LOCALES_CLJ_CONTENTS i18n: msgfmt # Update locales/.pot update-pot: locales/$(POT_NAME) locales/$(POT_NAME): $(shell $(FIND_SOURCES)) | locales @tmp=$$(mktemp $@.tmp.XXXX); \ $(FIND_SOURCES) \ | xgettext --from-code=UTF-8 --language=lisp \ --copyright-holder='Puppet ' \ --package-name="$(BUNDLE)" \ --package-version="$(BUNDLE_VERSION)" \ --msgid-bugs-address="docs@puppet.com" \ -k \ -kmark:1 -ki18n/mark:1 \ -ktrs:1 -ki18n/trs:1 \ -ktru:1 -ki18n/tru:1 \ -ktrun:1,2 -ki18n/trun:1,2 \ -ktrsn:1,2 -ki18n/trsn:1,2 \ $(LOC_OPT) \ --add-comments --sort-by-file \ -o $$tmp -f -; \ sed -i.bak -e 's/charset=CHARSET/charset=UTF-8/' $$tmp; \ sed -i.bak -e 's/POT-Creation-Date: [^\\]*/POT-Creation-Date: /' $$tmp; \ rm -f $$tmp.bak; \ if ! diff -q -I POT-Creation-Date $$tmp $@ >/dev/null 2>&1; then \ mv $$tmp $@; \ else \ rm $$tmp; touch $@; \ fi # Run msgfmt over all .po files to generate Java resource bundles # and create the locales.clj file msgfmt: $(BUNDLE_FILES) $(LOCALES_CLJ) clean-orphaned-bundles # Force rebuild of locales.clj if its contents is not the the desired one. The # shell echo is used to add a trailing newline to match the one from `cat` ifneq ($(shell cat $(LOCALES_CLJ) 2> /dev/null),$(shell echo '$(LOCALES_CLJ_CONTENTS)')) .PHONY: $(LOCALES_CLJ) endif $(LOCALES_CLJ): | resources @echo "Writing $@" @echo "$$LOCALES_CLJ_CONTENTS" > $@ # Remove every resource bundle that wasn't generated from a PO file. # We do this because we used to generate the english bundle directly from the POT. .PHONY: clean-orphaned-bundles clean-orphaned-bundles: @for bundle in resources/$(BUNDLE_DIR)/Messages_*.class; do \ locale=$$(basename "$$bundle" | sed -E -e 's/\$$?1?\.class$$/_class/' | cut -d '_' -f 2;); \ if [ ! -f "locales/$$locale.po" ]; then \ rm "$$bundle"; \ fi \ done resources/$(BUNDLE_DIR)/Messages_%.class: locales/%.po | resources msgfmt --java2 -d resources -r $(BUNDLE).Messages -l $(*F) $< # Use this to initialize translations. Updating the PO files is done # automatically through a CI job that utilizes the scripts in the project's # `bin` file, which themselves come from the `clj-i18n` project. locales/%.po: | locales @if [ ! -f $@ ]; then \ touch $@ && msginit --no-translator -l $(*F) -o $@ -i locales/$(POT_NAME); \ fi resources locales: @mkdir $@ help: $(info $(HELP)) @echo .PHONY: help define HELP This Makefile assists in handling i18n related tasks during development. Files that need to be checked into source control are put into the locales/ directory. They are locales/$(POT_NAME) - the POT file generated by 'make update-pot' locales/$$LANG.po - the translations for $$LANG Only the $$LANG.po files should be edited manually; this is usually done by translators. You can use the following targets: i18n: refresh all the files in locales/ and recompile resources update-pot: extract strings and update locales/$(POT_NAME) locales/LANG.po: create translations for LANG msgfmt: compile the translations into Java classes; this step is needed to make translations available to the Clojure code and produces Java class files in resources/ endef # @todo lutter 2015-04-20: for projects that use libraries with their own # translation, we need to combine all their translations into one big po # file and then run msgfmt over that so that we only have to deal with one # resource bundle puppetlabs-puppetserver-7e1a9a8/dev-resources/README.md000066400000000000000000000003411470345337400231310ustar00rootroot00000000000000This directory should only contain files (sample data, ssl files, etc.) that are referenced by tests. When possible, files should be placed in a package/directory structure that corresponds with the test that is using them. puppetlabs-puppetserver-7e1a9a8/dev-resources/java.security.jdk11on-fips000066400000000000000000001277111470345337400266040ustar00rootroot00000000000000# # This is the "master security properties file". # # An alternate java.security properties file may be specified # from the command line via the system property # # -Djava.security.properties= # # This properties file appends to the master security properties file. # If both properties files specify values for the same key, the value # from the command-line properties file is selected, as it is the last # one loaded. # # Also, if you specify # # -Djava.security.properties== (2 equals), # # then that properties file completely overrides the master security # properties file. # # To disable the ability to specify an additional properties file from # the command line, set the key security.overridePropertiesFile # to false in the master security properties file. It is set to true # by default. # In this file, various security properties are set for use by # java.security classes. This is where users can statically register # Cryptography Package Providers ("providers" for short). The term # "provider" refers to a package or set of packages that supply a # concrete implementation of a subset of the cryptography aspects of # the Java Security API. A provider may, for example, implement one or # more digital signature algorithms or message digest algorithms. # # Each provider must implement a subclass of the Provider class. # To register a provider in this master security properties file, # specify the provider and priority in the format # # security.provider.= # # This declares a provider, and specifies its preference # order n. The preference order is the order in which providers are # searched for requested algorithms (when no specific provider is # requested). The order is 1-based; 1 is the most preferred, followed # by 2, and so on. # # must specify the name of the Provider as passed to its super # class java.security.Provider constructor. This is for providers loaded # through the ServiceLoader mechanism. # # must specify the subclass of the Provider class whose # constructor sets the values of various properties that are required # for the Java Security API to look up the algorithms or other # facilities implemented by the provider. This is for providers loaded # through classpath. # # Note: Providers can be dynamically registered instead by calls to # either the addProvider or insertProviderAt method in the Security # class. # # List of providers and their preference orders (see above): # security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider security.provider.3=SUN security.provider.4=SunRsaSign #security.provider.5=SunEC #security.provider.6=SunJSSE #security.provider.7=SunJCE #security.provider.8=SunJGSS #security.provider.9=SunSASL #security.provider.10=XMLDSig #security.provider.11=SunPCSC #security.provider.12=JdkLDAP #security.provider.13=JdkSASL #security.provider.14=SunPKCS11 # # A list of preferred providers for specific algorithms. These providers will # be searched for matching algorithms before the list of registered providers. # Entries containing errors (parsing, etc) will be ignored. Use the # -Djava.security.debug=jca property to debug these errors. # # The property is a comma-separated list of serviceType.algorithm:provider # entries. The serviceType (example: "MessageDigest") is optional, and if # not specified, the algorithm applies to all service types that support it. # The algorithm is the standard algorithm name or transformation. # Transformations can be specified in their full standard name # (ex: AES/CBC/PKCS5Padding), or as partial matches (ex: AES, AES/CBC). # The provider is the name of the provider. Any provider that does not # also appear in the registered list will be ignored. # # There is a special serviceType for this property only to group a set of # algorithms together. The type is "Group" and is followed by an algorithm # keyword. Groups are to simplify and lessen the entries on the property # line. Current groups are: # Group.SHA2 = SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256 # Group.HmacSHA2 = HmacSHA224, HmacSHA256, HmacSHA384, HmacSHA512 # Group.SHA2RSA = SHA224withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA # Group.SHA2DSA = SHA224withDSA, SHA256withDSA, SHA384withDSA, SHA512withDSA # Group.SHA2ECDSA = SHA224withECDSA, SHA256withECDSA, SHA384withECDSA, \ # SHA512withECDSA # Group.SHA3 = SHA3-224, SHA3-256, SHA3-384, SHA3-512 # Group.HmacSHA3 = HmacSHA3-224, HmacSHA3-256, HmacSHA3-384, HmacSHA3-512 # # Example: # jdk.security.provider.preferred=AES/GCM/NoPadding:SunJCE, \ # MessageDigest.SHA-256:SUN, Group.HmacSHA2:SunJCE # #jdk.security.provider.preferred= # # Sun Provider SecureRandom seed source. # # Select the primary source of seed data for the "NativePRNG", "SHA1PRNG" # and "DRBG" SecureRandom implementations in the "Sun" provider. # (Other SecureRandom implementations might also use this property.) # # On Unix-like systems (for example, Solaris/Linux/MacOS), the # "NativePRNG", "SHA1PRNG" and "DRBG" implementations obtains seed data from # special device files such as file:/dev/random. # # On Windows systems, specifying the URLs "file:/dev/random" or # "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding # mechanism for SHA1PRNG and DRBG. # # By default, an attempt is made to use the entropy gathering device # specified by the "securerandom.source" Security property. If an # exception occurs while accessing the specified URL: # # NativePRNG: # a default value of /dev/random will be used. If neither # are available, the implementation will be disabled. # "file" is the only currently supported protocol type. # # SHA1PRNG and DRBG: # the traditional system/thread activity algorithm will be used. # # The entropy gathering device can also be specified with the System # property "java.security.egd". For example: # # % java -Djava.security.egd=file:/dev/random MainClass # # Specifying this System property will override the # "securerandom.source" Security property. # # In addition, if "file:/dev/random" or "file:/dev/urandom" is # specified, the "NativePRNG" implementation will be more preferred than # DRBG and SHA1PRNG in the Sun provider. # securerandom.source=file:/dev/random # # A list of known strong SecureRandom implementations. # # To help guide applications in selecting a suitable strong # java.security.SecureRandom implementation, Java distributions should # indicate a list of known strong implementations using the property. # # This is a comma-separated list of algorithm and/or algorithm:provider # entries. # securerandom.strongAlgorithms=NativePRNGBlocking:SUN,DRBG:SUN # # Sun provider DRBG configuration and default instantiation request. # # NIST SP 800-90Ar1 lists several DRBG mechanisms. Each can be configured # with a DRBG algorithm name, and can be instantiated with a security strength, # prediction resistance support, etc. This property defines the configuration # and the default instantiation request of "DRBG" SecureRandom implementations # in the SUN provider. (Other DRBG implementations can also use this property.) # Applications can request different instantiation parameters like security # strength, capability, personalization string using one of the # getInstance(...,SecureRandomParameters,...) methods with a # DrbgParameters.Instantiation argument, but other settings such as the # mechanism and DRBG algorithm names are not currently configurable by any API. # # Please note that the SUN implementation of DRBG always supports reseeding. # # The value of this property is a comma-separated list of all configurable # aspects. The aspects can appear in any order but the same aspect can only # appear at most once. Its BNF-style definition is: # # Value: # aspect { "," aspect } # # aspect: # mech_name | algorithm_name | strength | capability | df # # // The DRBG mechanism to use. Default "Hash_DRBG" # mech_name: # "Hash_DRBG" | "HMAC_DRBG" | "CTR_DRBG" # # // The DRBG algorithm name. The "SHA-***" names are for Hash_DRBG and # // HMAC_DRBG, default "SHA-256". The "AES-***" names are for CTR_DRBG, # // default "AES-128" when using the limited cryptographic or "AES-256" # // when using the unlimited. # algorithm_name: # "SHA-224" | "SHA-512/224" | "SHA-256" | # "SHA-512/256" | "SHA-384" | "SHA-512" | # "AES-128" | "AES-192" | "AES-256" # # // Security strength requested. Default "128" # strength: # "112" | "128" | "192" | "256" # # // Prediction resistance and reseeding request. Default "none" # // "pr_and_reseed" - Both prediction resistance and reseeding # // support requested # // "reseed_only" - Only reseeding support requested # // "none" - Neither prediction resistance not reseeding # // support requested # pr: # "pr_and_reseed" | "reseed_only" | "none" # # // Whether a derivation function should be used. only applicable # // to CTR_DRBG. Default "use_df" # df: # "use_df" | "no_df" # # Examples, # securerandom.drbg.config=Hash_DRBG,SHA-224,112,none # securerandom.drbg.config=CTR_DRBG,AES-256,192,pr_and_reseed,use_df # # The default value is an empty string, which is equivalent to # securerandom.drbg.config=Hash_DRBG,SHA-256,128,none # securerandom.drbg.config= # # Class to instantiate as the javax.security.auth.login.Configuration # provider. # login.configuration.provider=sun.security.provider.ConfigFile # # Default login configuration file # #login.config.url.1=file:${user.home}/.java.login.config # # Class to instantiate as the system Policy. This is the name of the class # that will be used as the Policy object. The system class loader is used to # locate this class. # policy.provider=sun.security.provider.PolicyFile # The default is to have a single system-wide policy file, # and a policy file in the user's home directory. # policy.url.1=file:${java.home}/conf/security/java.policy policy.url.2=file:${user.home}/.java.policy # whether or not we expand properties in the policy file # if this is set to false, properties (${...}) will not be expanded in policy # files. # policy.expandProperties=true # whether or not we allow an extra policy to be passed on the command line # with -Djava.security.policy=somefile. Comment out this line to disable # this feature. # policy.allowSystemProperty=true # whether or not we look into the IdentityScope for trusted Identities # when encountering a 1.1 signed JAR file. If the identity is found # and is trusted, we grant it AllPermission. Note: the default policy # provider (sun.security.provider.PolicyFile) does not support this property. # policy.ignoreIdentityScope=false # # Default keystore type. # keystore.type=pkcs12 # # Controls compatibility mode for JKS and PKCS12 keystore types. # # When set to 'true', both JKS and PKCS12 keystore types support loading # keystore files in either JKS or PKCS12 format. When set to 'false' the # JKS keystore type supports loading only JKS keystore files and the PKCS12 # keystore type supports loading only PKCS12 keystore files. # keystore.type.compat=true # # List of comma-separated packages that start with or equal this string # will cause a security exception to be thrown when passed to the # SecurityManager::checkPackageAccess method unless the corresponding # RuntimePermission("accessClassInPackage."+package) has been granted. # package.access=sun.misc.,\ sun.reflect.,\ org.GNOME.Accessibility. # # List of comma-separated packages that start with or equal this string # will cause a security exception to be thrown when passed to the # SecurityManager::checkPackageDefinition method unless the corresponding # RuntimePermission("defineClassInPackage."+package) has been granted. # # By default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # package.definition=sun.misc.,\ sun.reflect. # # Determines whether this properties file can be appended to # or overridden on the command line via -Djava.security.properties # security.overridePropertiesFile=true # # Determines the default key and trust manager factory algorithms for # the javax.net.ssl package. # ssl.KeyManagerFactory.algorithm=BCFKS ssl.TrustManagerFactory.algorithm=PKIX # # The Java-level namelookup cache policy for successful lookups: # # any negative value: caching forever # any positive value: the number of seconds to cache an address for # zero: do not cache # # default value is forever (FOREVER). For security reasons, this # caching is made forever when a security manager is set. When a security # manager is not set, the default behavior in this implementation # is to cache for 30 seconds. # # NOTE: setting this to anything other than the default value can have # serious security implications. Do not set it unless # you are sure you are not exposed to DNS spoofing attack. # #networkaddress.cache.ttl=-1 # The Java-level namelookup cache policy for failed lookups: # # any negative value: cache forever # any positive value: the number of seconds to cache negative lookup results # zero: do not cache # # In some Microsoft Windows networking environments that employ # the WINS name service in addition to DNS, name service lookups # that fail may take a noticeably long time to return (approx. 5 seconds). # For this reason the default caching policy is to maintain these # results for 10 seconds. # networkaddress.cache.negative.ttl=10 # # Properties to configure OCSP for certificate revocation checking # # Enable OCSP # # By default, OCSP is not used for certificate revocation checking. # This property enables the use of OCSP when set to the value "true". # # NOTE: SocketPermission is required to connect to an OCSP responder. # # Example, # ocsp.enable=true # # Location of the OCSP responder # # By default, the location of the OCSP responder is determined implicitly # from the certificate being validated. This property explicitly specifies # the location of the OCSP responder. The property is used when the # Authority Information Access extension (defined in RFC 5280) is absent # from the certificate or when it requires overriding. # # Example, # ocsp.responderURL=http://ocsp.example.net:80 # # Subject name of the OCSP responder's certificate # # By default, the certificate of the OCSP responder is that of the issuer # of the certificate being validated. This property identifies the certificate # of the OCSP responder when the default does not apply. Its value is a string # distinguished name (defined in RFC 2253) which identifies a certificate in # the set of certificates supplied during cert path validation. In cases where # the subject name alone is not sufficient to uniquely identify the certificate # then both the "ocsp.responderCertIssuerName" and # "ocsp.responderCertSerialNumber" properties must be used instead. When this # property is set then those two properties are ignored. # # Example, # ocsp.responderCertSubjectName=CN=OCSP Responder, O=XYZ Corp # # Issuer name of the OCSP responder's certificate # # By default, the certificate of the OCSP responder is that of the issuer # of the certificate being validated. This property identifies the certificate # of the OCSP responder when the default does not apply. Its value is a string # distinguished name (defined in RFC 2253) which identifies a certificate in # the set of certificates supplied during cert path validation. When this # property is set then the "ocsp.responderCertSerialNumber" property must also # be set. When the "ocsp.responderCertSubjectName" property is set then this # property is ignored. # # Example, # ocsp.responderCertIssuerName=CN=Enterprise CA, O=XYZ Corp # # Serial number of the OCSP responder's certificate # # By default, the certificate of the OCSP responder is that of the issuer # of the certificate being validated. This property identifies the certificate # of the OCSP responder when the default does not apply. Its value is a string # of hexadecimal digits (colon or space separators may be present) which # identifies a certificate in the set of certificates supplied during cert path # validation. When this property is set then the "ocsp.responderCertIssuerName" # property must also be set. When the "ocsp.responderCertSubjectName" property # is set then this property is ignored. # # Example, # ocsp.responderCertSerialNumber=2A:FF:00 # # Policy for failed Kerberos KDC lookups: # # When a KDC is unavailable (network error, service failure, etc), it is # put inside a blacklist and accessed less often for future requests. The # value (case-insensitive) for this policy can be: # # tryLast # KDCs in the blacklist are always tried after those not on the list. # # tryLess[:max_retries,timeout] # KDCs in the blacklist are still tried by their order in the configuration, # but with smaller max_retries and timeout values. max_retries and timeout # are optional numerical parameters (default 1 and 5000, which means once # and 5 seconds). Please notes that if any of the values defined here is # more than what is defined in krb5.conf, it will be ignored. # # Whenever a KDC is detected as available, it is removed from the blacklist. # The blacklist is reset when krb5.conf is reloaded. You can add # refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is # reloaded whenever a JAAS authentication is attempted. # # Example, # krb5.kdc.bad.policy = tryLast # krb5.kdc.bad.policy = tryLess:2,2000 # krb5.kdc.bad.policy = tryLast # # Algorithm restrictions for certification path (CertPath) processing # # In some environments, certain algorithms or key lengths may be undesirable # for certification path building and validation. For example, "MD2" is # generally no longer considered to be a secure hash algorithm. This section # describes the mechanism for disabling algorithms based on algorithm name # and/or key length. This includes algorithms used in certificates, as well # as revocation information such as CRLs and signed OCSP Responses. # The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: # AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: # KeySizeConstraint | CAConstraint | DenyAfterConstraint | # UsageConstraint # # KeySizeConstraint: # keySize Operator KeyLength # # Operator: # <= | < | == | != | >= | > # # KeyLength: # Integer value of the algorithm's key length in bits # # CAConstraint: # jdkCA # # DenyAfterConstraint: # denyAfter YYYY-MM-DD # # UsageConstraint: # usage [TLSServer] [TLSClient] [SignedJAR] # # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name # Documentation" for information about Standard Algorithm Names. Matching # is performed using a case-insensitive sub-element matching rule. (For # example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and # "ECDSA" for signatures.) If the assertion "AlgorithmName" is a # sub-element of the certificate algorithm name, the algorithm will be # rejected during certification path building and validation. For example, # the assertion algorithm name "DSA" will disable all certificate algorithms # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # will not disable algorithms related to "ECDSA". # # A "Constraint" defines restrictions on the keys and/or certificates for # a specified AlgorithmName: # # KeySizeConstraint: # keySize Operator KeyLength # The constraint requires a key of a valid size range if the # "AlgorithmName" is of a key algorithm. The "KeyLength" indicates # the key size specified in number of bits. For example, # "RSA keySize <= 1024" indicates that any RSA key with key size less # than or equal to 1024 bits should be disabled, and # "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key # with key size less than 1024 or greater than 2048 should be disabled. # This constraint is only used on algorithms that have a key size. # # CAConstraint: # jdkCA # This constraint prohibits the specified algorithm only if the # algorithm is used in a certificate chain that terminates at a marked # trust anchor in the lib/security/cacerts keystore. If the jdkCA # constraint is not set, then all chains using the specified algorithm # are restricted. jdkCA may only be used once in a DisabledAlgorithm # expression. # Example: To apply this constraint to SHA-1 certificates, include # the following: "SHA1 jdkCA" # # DenyAfterConstraint: # denyAfter YYYY-MM-DD # This constraint prohibits a certificate with the specified algorithm # from being used after the date regardless of the certificate's # validity. JAR files that are signed and timestamped before the # constraint date with certificates containing the disabled algorithm # will not be restricted. The date is processed in the UTC timezone. # This constraint can only be used once in a DisabledAlgorithm # expression. # Example: To deny usage of RSA 2048 bit certificates after Feb 3 2020, # use the following: "RSA keySize == 2048 & denyAfter 2020-02-03" # # UsageConstraint: # usage [TLSServer] [TLSClient] [SignedJAR] # This constraint prohibits the specified algorithm for # a specified usage. This should be used when disabling an algorithm # for all usages is not practical. 'TLSServer' restricts the algorithm # in TLS server certificate chains when server authentication is # performed. 'TLSClient' restricts the algorithm in TLS client # certificate chains when client authentication is performed. # 'SignedJAR' constrains use of certificates in signed jar files. # The usage type follows the keyword and more than one usage type can # be specified with a whitespace delimiter. # Example: "SHA1 usage TLSServer TLSClient" # # When an algorithm must satisfy more than one constraint, it must be # delimited by an ampersand '&'. For example, to restrict certificates in a # chain that terminate at a distribution provided trust anchor and contain # RSA keys that are less than or equal to 1024 bits, add the following # constraint: "RSA keySize <= 1024 & jdkCA". # # All DisabledAlgorithms expressions are processed in the order defined in the # property. This requires lower keysize constraints to be specified # before larger keysize constraints of the same algorithm. For example: # "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". # # Note: The algorithm restrictions do not apply to trust anchors or # self-signed certificates. # # Note: This property is currently used by Oracle's PKIX implementation. It # is not guaranteed to be examined and used by other implementations. # # Example: # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 # # Algorithm restrictions for signed JAR files # # In some environments, certain algorithms or key lengths may be undesirable # for signed JAR validation. For example, "MD2" is generally no longer # considered to be a secure hash algorithm. This section describes the # mechanism for disabling algorithms based on algorithm name and/or key length. # JARs signed with any of the disabled algorithms or key sizes will be treated # as unsigned. # # The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: # AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: # KeySizeConstraint | DenyAfterConstraint # # KeySizeConstraint: # keySize Operator KeyLength # # DenyAfterConstraint: # denyAfter YYYY-MM-DD # # Operator: # <= | < | == | != | >= | > # # KeyLength: # Integer value of the algorithm's key length in bits # # Note: This property is currently used by the JDK Reference # implementation. It is not guaranteed to be examined and used by other # implementations. # # See "jdk.certpath.disabledAlgorithms" for syntax descriptions. # jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ DSA keySize < 1024 # # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS/DTLS) processing # # In some environments, certain algorithms or key lengths may be undesirable # when using SSL/TLS/DTLS. This section describes the mechanism for disabling # algorithms during SSL/TLS/DTLS security parameters negotiation, including # protocol version negotiation, cipher suites selection, peer authentication # and key exchange mechanisms. # # Disabled algorithms will not be negotiated for SSL/TLS connections, even # if they are enabled explicitly in an application. # # For PKI-based peer authentication and key exchange mechanisms, this list # of disabled algorithms will also be checked during certification path # building and validation, including algorithms used in certificates, as # well as revocation information such as CRLs and signed OCSP Responses. # This is in addition to the jdk.certpath.disabledAlgorithms property above. # # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # # Note: The algorithm restrictions do not apply to trust anchors or # self-signed certificates. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \ EC keySize < 224, 3DES_EDE_CBC, anon, NULL # # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. # # In some environments, a certain algorithm may be undesirable but it # cannot be disabled because of its use in legacy applications. Legacy # algorithms may still be supported, but applications should not use them # as the security strength of legacy algorithms are usually not strong enough # in practice. # # During SSL/TLS security parameters negotiation, legacy algorithms will # not be negotiated unless there are no other candidates. # # The syntax of the legacy algorithms string is described as this Java # BNF-style: # LegacyAlgorithms: # " LegacyAlgorithm { , LegacyAlgorithm } " # # LegacyAlgorithm: # AlgorithmName (standard JSSE algorithm name) # # See the specification of security property "jdk.certpath.disabledAlgorithms" # for the syntax and description of the "AlgorithmName" notation. # # Per SSL/TLS specifications, cipher suites have the form: # SSL_KeyExchangeAlg_WITH_CipherAlg_MacAlg # or # TLS_KeyExchangeAlg_WITH_CipherAlg_MacAlg # # For example, the cipher suite TLS_RSA_WITH_AES_128_CBC_SHA uses RSA as the # key exchange algorithm, AES_128_CBC (128 bits AES cipher algorithm in CBC # mode) as the cipher (encryption) algorithm, and SHA-1 as the message digest # algorithm for HMAC. # # The LegacyAlgorithm can be one of the following standard algorithm names: # 1. JSSE cipher suite name, e.g., TLS_RSA_WITH_AES_128_CBC_SHA # 2. JSSE key exchange algorithm name, e.g., RSA # 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC # 4. JSSE message digest algorithm name, e.g., SHA # # See SSL/TLS specifications and "Java Cryptography Architecture Standard # Algorithm Name Documentation" for information about the algorithm names. # # Note: If a legacy algorithm is also restricted through the # jdk.tls.disabledAlgorithms property or the # java.security.AlgorithmConstraints API (See # javax.net.ssl.SSLParameters.setAlgorithmConstraints()), # then the algorithm is completely disabled and will not be negotiated. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # There is no guarantee the property will continue to exist or be of the # same syntax in future releases. # # Example: # jdk.tls.legacyAlgorithms=DH_anon, DES_CBC, SSL_RSA_WITH_RC4_128_MD5 # jdk.tls.legacyAlgorithms= \ K_NULL, C_NULL, M_NULL, \ DH_anon, ECDH_anon, \ RC4_128, RC4_40, DES_CBC, DES40_CBC, \ 3DES_EDE_CBC # # The pre-defined default finite field Diffie-Hellman ephemeral (DHE) # parameters for Transport Layer Security (SSL/TLS/DTLS) processing. # # In traditional SSL/TLS/DTLS connections where finite field DHE parameters # negotiation mechanism is not used, the server offers the client group # parameters, base generator g and prime modulus p, for DHE key exchange. # It is recommended to use dynamic group parameters. This property defines # a mechanism that allows you to specify custom group parameters. # # The syntax of this property string is described as this Java BNF-style: # DefaultDHEParameters: # DefinedDHEParameters { , DefinedDHEParameters } # # DefinedDHEParameters: # "{" DHEPrimeModulus , DHEBaseGenerator "}" # # DHEPrimeModulus: # HexadecimalDigits # # DHEBaseGenerator: # HexadecimalDigits # # HexadecimalDigits: # HexadecimalDigit { HexadecimalDigit } # # HexadecimalDigit: one of # 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f # # Whitespace characters are ignored. # # The "DefinedDHEParameters" defines the custom group parameters, prime # modulus p and base generator g, for a particular size of prime modulus p. # The "DHEPrimeModulus" defines the hexadecimal prime modulus p, and the # "DHEBaseGenerator" defines the hexadecimal base generator g of a group # parameter. It is recommended to use safe primes for the custom group # parameters. # # If this property is not defined or the value is empty, the underlying JSSE # provider's default group parameter is used for each connection. # # If the property value does not follow the grammar, or a particular group # parameter is not valid, the connection will fall back and use the # underlying JSSE provider's default group parameter. # # Note: This property is currently used by OpenJDK's JSSE implementation. It # is not guaranteed to be examined and used by other implementations. # # Example: # jdk.tls.server.defaultDHEParameters= # { \ # FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 \ # 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD \ # EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 \ # E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED \ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} # # TLS key limits on symmetric cryptographic algorithms # # This security property sets limits on algorithms key usage in TLS 1.3. # When the amount of data encrypted exceeds the algorithm value listed below, # a KeyUpdate message will trigger a key change. This is for symmetric ciphers # with TLS 1.3 only. # # The syntax for the property is described below: # KeyLimits: # " KeyLimit { , KeyLimit } " # # WeakKeyLimit: # AlgorithmName Action Length # # AlgorithmName: # A full algorithm transformation. # # Action: # KeyUpdate # # Length: # The amount of encrypted data in a session before the Action occurs # This value may be an integer value in bytes, or as a power of two, 2^29. # # KeyUpdate: # The TLS 1.3 KeyUpdate handshake process begins when the Length amount # is fulfilled. # # Note: This property is currently used by OpenJDK's JSSE implementation. It # is not guaranteed to be examined and used by other implementations. # jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37 # # Cryptographic Jurisdiction Policy defaults # # Import and export control rules on cryptographic software vary from # country to country. By default, Java provides two different sets of # cryptographic policy files[1]: # # unlimited: These policy files contain no restrictions on cryptographic # strengths or algorithms # # limited: These policy files contain more restricted cryptographic # strengths # # The default setting is determined by the value of the "crypto.policy" # Security property below. If your country or usage requires the # traditional restrictive policy, the "limited" Java cryptographic # policy is still available and may be appropriate for your environment. # # If you have restrictions that do not fit either use case mentioned # above, Java provides the capability to customize these policy files. # The "crypto.policy" security property points to a subdirectory # within /conf/security/policy/ which can be customized. # Please see the /conf/security/policy/README.txt file or consult # the Java Security Guide/JCA documentation for more information. # # YOU ARE ADVISED TO CONSULT YOUR EXPORT/IMPORT CONTROL COUNSEL OR ATTORNEY # TO DETERMINE THE EXACT REQUIREMENTS. # # [1] Please note that the JCE for Java SE, including the JCE framework, # cryptographic policy files, and standard JCE providers provided with # the Java SE, have been reviewed and approved for export as mass market # encryption item by the US Bureau of Industry and Security. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # crypto.policy=unlimited # # The policy for the XML Signature secure validation mode. The mode is # enabled by setting the property "org.jcp.xml.dsig.secureValidation" to # true with the javax.xml.crypto.XMLCryptoContext.setProperty() method, # or by running the code with a SecurityManager. # # Policy: # Constraint {"," Constraint } # Constraint: # AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | # ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint # AlgConstraint # "disallowAlg" Uri # MaxTransformsConstraint: # "maxTransforms" Integer # MaxReferencesConstraint: # "maxReferences" Integer # ReferenceUriSchemeConstraint: # "disallowReferenceUriSchemes" String { String } # KeySizeConstraint: # "minKeySize" KeyAlg Integer # OtherConstraint: # "noDuplicateIds" | "noRetrievalMethodLoops" # # For AlgConstraint, Uri is the algorithm URI String that is not allowed. # See the XML Signature Recommendation for more information on algorithm # URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm # name of the key type (ex: "RSA"). If the MaxTransformsConstraint, # MaxReferencesConstraint or KeySizeConstraint (for the same key type) is # specified more than once, only the last entry is enforced. # # Note: This property is currently used by the JDK Reference implementation. It # is not guaranteed to be examined and used by other implementations. # jdk.xml.dsig.secureValidationPolicy=\ disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ maxTransforms 5,\ maxReferences 30,\ disallowReferenceUriSchemes file http https,\ minKeySize RSA 1024,\ minKeySize DSA 1024,\ minKeySize EC 224,\ noDuplicateIds,\ noRetrievalMethodLoops # # Serialization process-wide filter # # A filter, if configured, is used by java.io.ObjectInputStream during # deserialization to check the contents of the stream. # A filter is configured as a sequence of patterns, each pattern is either # matched against the name of a class in the stream or defines a limit. # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # # If the system property jdk.serialFilter is also specified, it supersedes # the security property value defined here. # # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the # sequence of patterns. # If any of the limits are exceeded, the filter status is REJECTED. # # maxdepth=value - the maximum depth of a graph # maxrefs=value - the maximum number of internal references # maxbytes=value - the maximum number of bytes in the input stream # maxarray=value - the maximum array length allowed # # Other patterns, from left to right, match the class or package name as # returned from Class.getName. # If the class is an array type, the class or package to be matched is the # element type. # Arrays of any number of dimensions are treated the same as the element type. # For example, a pattern of "!example.Foo", rejects creation of any instance or # array of example.Foo. # # If the pattern starts with "!", the status is REJECTED if the remaining # pattern is matched; otherwise the status is ALLOWED if the pattern matches. # If the pattern contains "/", the non-empty prefix up to the "/" is the # module name; # if the module name matches the module name of the class then # the remaining pattern is matched with the class name. # If there is no "/", the module name is not compared. # If the pattern ends with ".**" it matches any class in the package and all # subpackages. # If the pattern ends with ".*" it matches any class in the package. # If the pattern ends with "*", it matches any class with the pattern as a # prefix. # If the pattern is equal to the class name, it matches. # Otherwise, the status is UNDECIDED. # #jdk.serialFilter=pattern;pattern # # RMI Registry Serial Filter # # The filter pattern uses the same format as jdk.serialFilter. # This filter can override the builtin filter if additional types need to be # allowed or rejected from the RMI Registry or to decrease limits but not # to increase limits. # If the limits (maxdepth, maxrefs, or maxbytes) are exceeded, the object is rejected. # # Each non-array type is allowed or rejected if it matches one of the patterns, # evaluated from left to right, and is otherwise allowed. Arrays of any # component type, including subarrays and arrays of primitives, are allowed. # # Array construction of any component type, including subarrays and arrays of # primitives, are allowed unless the length is greater than the maxarray limit. # The filter is applied to each array element. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # # The built-in filter allows subclasses of allowed classes and # can approximately be represented as the pattern: # #sun.rmi.registry.registryFilter=\ # maxarray=1000000;\ # maxdepth=20;\ # java.lang.String;\ # java.lang.Number;\ # java.lang.reflect.Proxy;\ # java.rmi.Remote;\ # sun.rmi.server.UnicastRef;\ # sun.rmi.server.RMIClientSocketFactory;\ # sun.rmi.server.RMIServerSocketFactory;\ # java.rmi.activation.ActivationID;\ # java.rmi.server.UID # # RMI Distributed Garbage Collector (DGC) Serial Filter # # The filter pattern uses the same format as jdk.serialFilter. # This filter can override the builtin filter if additional types need to be # allowed or rejected from the RMI DGC. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # # The builtin DGC filter can approximately be represented as the filter pattern: # #sun.rmi.transport.dgcFilter=\ # java.rmi.server.ObjID;\ # java.rmi.server.UID;\ # java.rmi.dgc.VMID;\ # java.rmi.dgc.Lease;\ # maxdepth=5;maxarray=10000 # CORBA ORBIorTypeCheckRegistryFilter # Type check enhancement for ORB::string_to_object processing # # An IOR type check filter, if configured, is used by an ORB during # an ORB::string_to_object invocation to check the veracity of the type encoded # in the ior string. # # The filter pattern consists of a semi-colon separated list of class names. # The configured list contains the binary class names of the IDL interface types # corresponding to the IDL stub class to be instantiated. # As such, a filter specifies a list of IDL stub classes that will be # allowed by an ORB when an ORB::string_to_object is invoked. # It is used to specify a white list configuration of acceptable # IDL stub types which may be contained in a stringified IOR # parameter passed as input to an ORB::string_to_object method. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name # # JCEKS Encrypted Key Serial Filter # # This filter, if configured, is used by the JCEKS KeyStore during the # deserialization of the encrypted Key object stored inside a key entry. # If not configured or the filter result is UNDECIDED (i.e. none of the patterns # matches), the filter configured by jdk.serialFilter will be consulted. # # If the system property jceks.key.serialFilter is also specified, it supersedes # the security property value defined here. # # The filter pattern uses the same format as jdk.serialFilter. The default # pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, # and javax.crypto.spec.SecretKeySpec and rejects all the others. jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep;\ java.base/java.security.KeyRep$Type;java.base/javax.crypto.spec.SecretKeySpec;!* # # Enhanced exception message information # # By default, exception messages should not include potentially sensitive # information such as file names, host names, or port numbers. This property # accepts one or more comma separated values, each of which represents a # category of enhanced exception message information to enable. Values are # case-insensitive. Leading and trailing whitespaces, surrounding each value, # are ignored. Unknown values are ignored. # # NOTE: Use caution before setting this property. Setting this property # exposes sensitive information in Exceptions, which could, for example, # propagate to untrusted code or be emitted in stack traces that are # inadvertently disclosed and made accessible over a public network. # # The categories are: # # hostInfo - IOExceptions thrown by java.net.Socket and the socket types in the # java.nio.channels package will contain enhanced exception # message information # # The property setting in this file can be overridden by a system property of # the same name, with the same syntax and possible values. # #jdk.includeInExceptions=hostInfo # # Policies for distrusting Certificate Authorities (CAs). # # This is a comma separated value of one or more case-sensitive strings, each # of which represents a policy for determining if a CA should be distrusted. # The supported values are: # # SYMANTEC_TLS : Distrust TLS Server certificates anchored by a Symantec # root CA and issued after April 16, 2019 unless issued by one of the # following subordinate CAs which have a later distrust date: # 1. Apple IST CA 2 - G1, SHA-256 fingerprint: # AC2B922ECFD5E01711772FEA8ED372DE9D1E2245FCE3F57A9CDBEC77296A424B # Distrust after December 31, 2019. # 2. Apple IST CA 8 - G1, SHA-256 fingerprint: # A4FE7C7F15155F3F0AEF7AAA83CF6E06DEB97CA3F909DF920AC1490882D488ED # Distrust after December 31, 2019. # # Leading and trailing whitespace surrounding each value are ignored. # Unknown values are ignored. If the property is commented out or set to the # empty String, no policies are enforced. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be supported by other SE implementations. Also, this # property does not override other security properties which can restrict # certificates such as jdk.tls.disabledAlgorithms or # jdk.certpath.disabledAlgorithms; those restrictions are still enforced even # if this property is not enabled. # jdk.security.caDistrustPolicies=SYMANTEC_TLS puppetlabs-puppetserver-7e1a9a8/dev-resources/java.security.jdk8-fips000066400000000000000000001226601470345337400261730ustar00rootroot00000000000000# # This is the "master security properties file". # # An alternate java.security properties file may be specified # from the command line via the system property # # -Djava.security.properties= # # This properties file appends to the master security properties file. # If both properties files specify values for the same key, the value # from the command-line properties file is selected, as it is the last # one loaded. # # Also, if you specify # # -Djava.security.properties== (2 equals), # # then that properties file completely overrides the master security # properties file. # # To disable the ability to specify an additional properties file from # the command line, set the key security.overridePropertiesFile # to false in the master security properties file. It is set to true # by default. # In this file, various security properties are set for use by # java.security classes. This is where users can statically register # Cryptography Package Providers ("providers" for short). The term # "provider" refers to a package or set of packages that supply a # concrete implementation of a subset of the cryptography aspects of # the Java Security API. A provider may, for example, implement one or # more digital signature algorithms or message digest algorithms. # # Each provider must implement a subclass of the Provider class. # To register a provider in this master security properties file, # specify the Provider subclass name and priority in the format # # security.provider.= # # This declares a provider, and specifies its preference # order n. The preference order is the order in which providers are # searched for requested algorithms (when no specific provider is # requested). The order is 1-based; 1 is the most preferred, followed # by 2, and so on. # # must specify the subclass of the Provider class whose # constructor sets the values of various properties that are required # for the Java Security API to look up the algorithms or other # facilities implemented by the provider. # # There must be at least one provider specification in java.security. # There is a default provider that comes standard with the JDK. It # is called the "SUN" provider, and its Provider subclass # named Sun appears in the sun.security.provider package. Thus, the # "SUN" provider is registered via the following: # # security.provider.1=sun.security.provider.Sun # # (The number 1 is used for the default provider.) # # Note: Providers can be dynamically registered instead by calls to # either the addProvider or insertProviderAt method in the Security # class. # # List of providers and their preference orders (see above): # security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider security.provider.3=sun.security.provider.Sun security.provider.4=sun.security.rsa.SunRsaSign #security.provider.5=sun.security.ec.SunEC #security.provider.6=com.sun.net.ssl.internal.ssl.Provider #security.provider.7=com.sun.crypto.provider.SunJCE #security.provider.8=sun.security.jgss.SunProvider #security.provider.9=com.sun.security.sasl.Provider #security.provider.10=org.jcp.xml.dsig.internal.dom.XMLDSigRI #security.provider.11=sun.security.smartcardio.SunPCSC # # Sun Provider SecureRandom seed source. # # Select the primary source of seed data for the "SHA1PRNG" and # "NativePRNG" SecureRandom implementations in the "Sun" provider. # (Other SecureRandom implementations might also use this property.) # # On Unix-like systems (for example, Solaris/Linux/MacOS), the # "NativePRNG" and "SHA1PRNG" implementations obtains seed data from # special device files such as file:/dev/random. # # On Windows systems, specifying the URLs "file:/dev/random" or # "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding # mechanism for SHA1PRNG. # # By default, an attempt is made to use the entropy gathering device # specified by the "securerandom.source" Security property. If an # exception occurs while accessing the specified URL: # # SHA1PRNG: # the traditional system/thread activity algorithm will be used. # # NativePRNG: # a default value of /dev/random will be used. If neither # are available, the implementation will be disabled. # "file" is the only currently supported protocol type. # # The entropy gathering device can also be specified with the System # property "java.security.egd". For example: # # % java -Djava.security.egd=file:/dev/random MainClass # # Specifying this System property will override the # "securerandom.source" Security property. # # In addition, if "file:/dev/random" or "file:/dev/urandom" is # specified, the "NativePRNG" implementation will be more preferred than # SHA1PRNG in the Sun provider. # securerandom.source=file:/dev/random # # A list of known strong SecureRandom implementations. # # To help guide applications in selecting a suitable strong # java.security.SecureRandom implementation, Java distributions should # indicate a list of known strong implementations using the property. # # This is a comma-separated list of algorithm and/or algorithm:provider # entries. # securerandom.strongAlgorithms=NativePRNGBlocking:SUN # # Class to instantiate as the javax.security.auth.login.Configuration # provider. # login.configuration.provider=sun.security.provider.ConfigFile # # Default login configuration file # #login.config.url.1=file:${user.home}/.java.login.config # # Class to instantiate as the system Policy. This is the name of the class # that will be used as the Policy object. # policy.provider=sun.security.provider.PolicyFile # The default is to have a single system-wide policy file, # and a policy file in the user's home directory. policy.url.1=file:${java.home}/lib/security/java.policy policy.url.2=file:${user.home}/.java.policy # whether or not we expand properties in the policy file # if this is set to false, properties (${...}) will not be expanded in policy # files. policy.expandProperties=true # whether or not we allow an extra policy to be passed on the command line # with -Djava.security.policy=somefile. Comment out this line to disable # this feature. policy.allowSystemProperty=true # whether or not we look into the IdentityScope for trusted Identities # when encountering a 1.1 signed JAR file. If the identity is found # and is trusted, we grant it AllPermission. policy.ignoreIdentityScope=false # # Default keystore type. # keystore.type=jks # # Controls compatibility mode for the JKS keystore type. # # When set to 'true', the JKS keystore type supports loading # keystore files in either JKS or PKCS12 format. When set to 'false' # it supports loading only JKS keystore files. # keystore.type.compat=true # # List of comma-separated packages that start with or equal this string # will cause a security exception to be thrown when # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. package.access=sun.,\ org.GNOME.Accessibility.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ com.sun.org.apache.xpath.internal.,\ com.sun.org.apache.xalan.internal.extensions.,\ com.sun.org.apache.xalan.internal.lib.,\ com.sun.org.apache.xalan.internal.res.,\ com.sun.org.apache.xalan.internal.templates.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.xslt.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ com.sun.org.apache.xalan.internal.xsltc.compiler.,\ com.sun.org.apache.xalan.internal.xsltc.trax.,\ com.sun.org.apache.xalan.internal.xsltc.util.,\ com.sun.org.apache.xml.internal.res.,\ com.sun.org.apache.xml.internal.resolver.helpers.,\ com.sun.org.apache.xml.internal.resolver.readers.,\ com.sun.org.apache.xml.internal.security.,\ com.sun.org.apache.xml.internal.serializer.utils.,\ com.sun.org.apache.xml.internal.utils.,\ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ oracle.jrockit.jfr.,\ org.jcp.xml.dsig.internal.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools.,\ jdk.xml.internal.,\ com.sun.activation.registries. # # List of comma-separated packages that start with or equal this string # will cause a security exception to be thrown when # passed to checkPackageDefinition unless the # corresponding RuntimePermission ("defineClassInPackage."+package) has # been granted. # # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # package.definition=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ com.sun.org.apache.xpath.internal.,\ com.sun.org.apache.xalan.internal.extensions.,\ com.sun.org.apache.xalan.internal.lib.,\ com.sun.org.apache.xalan.internal.res.,\ com.sun.org.apache.xalan.internal.templates.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.xslt.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ com.sun.org.apache.xalan.internal.xsltc.compiler.,\ com.sun.org.apache.xalan.internal.xsltc.trax.,\ com.sun.org.apache.xalan.internal.xsltc.util.,\ com.sun.org.apache.xml.internal.res.,\ com.sun.org.apache.xml.internal.resolver.helpers.,\ com.sun.org.apache.xml.internal.resolver.readers.,\ com.sun.org.apache.xml.internal.security.,\ com.sun.org.apache.xml.internal.serializer.utils.,\ com.sun.org.apache.xml.internal.utils.,\ com.sun.org.glassfish.,\ com.oracle.xmlns.internal.,\ com.oracle.webservices.internal.,\ oracle.jrockit.jfr.,\ org.jcp.xml.dsig.internal.,\ jdk.internal.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools.,\ jdk.xml.internal.,\ com.sun.activation.registries. # # Determines whether this properties file can be appended to # or overridden on the command line via -Djava.security.properties # security.overridePropertiesFile=true # # Determines the default key and trust manager factory algorithms for # the javax.net.ssl package. # ssl.KeyManagerFactory.algorithm=BCFKS ssl.TrustManagerFactory.algorithm=PKIX # # The Java-level namelookup cache policy for successful lookups: # # any negative value: caching forever # any positive value: the number of seconds to cache an address for # zero: do not cache # # default value is forever (FOREVER). For security reasons, this # caching is made forever when a security manager is set. When a security # manager is not set, the default behavior in this implementation # is to cache for 30 seconds. # # NOTE: setting this to anything other than the default value can have # serious security implications. Do not set it unless # you are sure you are not exposed to DNS spoofing attack. # #networkaddress.cache.ttl=-1 # The Java-level namelookup cache policy for failed lookups: # # any negative value: cache forever # any positive value: the number of seconds to cache negative lookup results # zero: do not cache # # In some Microsoft Windows networking environments that employ # the WINS name service in addition to DNS, name service lookups # that fail may take a noticeably long time to return (approx. 5 seconds). # For this reason the default caching policy is to maintain these # results for 10 seconds. # # networkaddress.cache.negative.ttl=10 # # Properties to configure OCSP for certificate revocation checking # # Enable OCSP # # By default, OCSP is not used for certificate revocation checking. # This property enables the use of OCSP when set to the value "true". # # NOTE: SocketPermission is required to connect to an OCSP responder. # # Example, # ocsp.enable=true # # Location of the OCSP responder # # By default, the location of the OCSP responder is determined implicitly # from the certificate being validated. This property explicitly specifies # the location of the OCSP responder. The property is used when the # Authority Information Access extension (defined in RFC 3280) is absent # from the certificate or when it requires overriding. # # Example, # ocsp.responderURL=http://ocsp.example.net:80 # # Subject name of the OCSP responder's certificate # # By default, the certificate of the OCSP responder is that of the issuer # of the certificate being validated. This property identifies the certificate # of the OCSP responder when the default does not apply. Its value is a string # distinguished name (defined in RFC 2253) which identifies a certificate in # the set of certificates supplied during cert path validation. In cases where # the subject name alone is not sufficient to uniquely identify the certificate # then both the "ocsp.responderCertIssuerName" and # "ocsp.responderCertSerialNumber" properties must be used instead. When this # property is set then those two properties are ignored. # # Example, # ocsp.responderCertSubjectName="CN=OCSP Responder, O=XYZ Corp" # # Issuer name of the OCSP responder's certificate # # By default, the certificate of the OCSP responder is that of the issuer # of the certificate being validated. This property identifies the certificate # of the OCSP responder when the default does not apply. Its value is a string # distinguished name (defined in RFC 2253) which identifies a certificate in # the set of certificates supplied during cert path validation. When this # property is set then the "ocsp.responderCertSerialNumber" property must also # be set. When the "ocsp.responderCertSubjectName" property is set then this # property is ignored. # # Example, # ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp" # # Serial number of the OCSP responder's certificate # # By default, the certificate of the OCSP responder is that of the issuer # of the certificate being validated. This property identifies the certificate # of the OCSP responder when the default does not apply. Its value is a string # of hexadecimal digits (colon or space separators may be present) which # identifies a certificate in the set of certificates supplied during cert path # validation. When this property is set then the "ocsp.responderCertIssuerName" # property must also be set. When the "ocsp.responderCertSubjectName" property # is set then this property is ignored. # # Example, # ocsp.responderCertSerialNumber=2A:FF:00 # # Policy for failed Kerberos KDC lookups: # # When a KDC is unavailable (network error, service failure, etc), it is # put inside a blacklist and accessed less often for future requests. The # value (case-insensitive) for this policy can be: # # tryLast # KDCs in the blacklist are always tried after those not on the list. # # tryLess[:max_retries,timeout] # KDCs in the blacklist are still tried by their order in the configuration, # but with smaller max_retries and timeout values. max_retries and timeout # are optional numerical parameters (default 1 and 5000, which means once # and 5 seconds). Please notes that if any of the values defined here is # more than what is defined in krb5.conf, it will be ignored. # # Whenever a KDC is detected as available, it is removed from the blacklist. # The blacklist is reset when krb5.conf is reloaded. You can add # refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is # reloaded whenever a JAAS authentication is attempted. # # Example, # krb5.kdc.bad.policy = tryLast # krb5.kdc.bad.policy = tryLess:2,2000 krb5.kdc.bad.policy = tryLast # Algorithm restrictions for certification path (CertPath) processing # # In some environments, certain algorithms or key lengths may be undesirable # for certification path building and validation. For example, "MD2" is # generally no longer considered to be a secure hash algorithm. This section # describes the mechanism for disabling algorithms based on algorithm name # and/or key length. This includes algorithms used in certificates, as well # as revocation information such as CRLs and signed OCSP Responses. # The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: # AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: # KeySizeConstraint | CAConstraint | DenyAfterConstraint | # UsageConstraint # # KeySizeConstraint: # keySize Operator KeyLength # # Operator: # <= | < | == | != | >= | > # # KeyLength: # Integer value of the algorithm's key length in bits # # CAConstraint: # jdkCA # # DenyAfterConstraint: # denyAfter YYYY-MM-DD # # UsageConstraint: # usage [TLSServer] [TLSClient] [SignedJAR] # # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name # Documentation" for information about Standard Algorithm Names. Matching # is performed using a case-insensitive sub-element matching rule. (For # example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and # "ECDSA" for signatures.) If the assertion "AlgorithmName" is a # sub-element of the certificate algorithm name, the algorithm will be # rejected during certification path building and validation. For example, # the assertion algorithm name "DSA" will disable all certificate algorithms # that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion # will not disable algorithms related to "ECDSA". # # A "Constraint" defines restrictions on the keys and/or certificates for # a specified AlgorithmName: # # KeySizeConstraint: # keySize Operator KeyLength # The constraint requires a key of a valid size range if the # "AlgorithmName" is of a key algorithm. The "KeyLength" indicates # the key size specified in number of bits. For example, # "RSA keySize <= 1024" indicates that any RSA key with key size less # than or equal to 1024 bits should be disabled, and # "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key # with key size less than 1024 or greater than 2048 should be disabled. # This constraint is only used on algorithms that have a key size. # # CAConstraint: # jdkCA # This constraint prohibits the specified algorithm only if the # algorithm is used in a certificate chain that terminates at a marked # trust anchor in the lib/security/cacerts keystore. If the jdkCA # constraint is not set, then all chains using the specified algorithm # are restricted. jdkCA may only be used once in a DisabledAlgorithm # expression. # Example: To apply this constraint to SHA-1 certificates, include # the following: "SHA1 jdkCA" # # DenyAfterConstraint: # denyAfter YYYY-MM-DD # This constraint prohibits a certificate with the specified algorithm # from being used after the date regardless of the certificate's # validity. JAR files that are signed and timestamped before the # constraint date with certificates containing the disabled algorithm # will not be restricted. The date is processed in the UTC timezone. # This constraint can only be used once in a DisabledAlgorithm # expression. # Example: To deny usage of RSA 2048 bit certificates after Feb 3 2020, # use the following: "RSA keySize == 2048 & denyAfter 2020-02-03" # # UsageConstraint: # usage [TLSServer] [TLSClient] [SignedJAR] # This constraint prohibits the specified algorithm for # a specified usage. This should be used when disabling an algorithm # for all usages is not practical. 'TLSServer' restricts the algorithm # in TLS server certificate chains when server authentication is # performed. 'TLSClient' restricts the algorithm in TLS client # certificate chains when client authentication is performed. # 'SignedJAR' constrains use of certificates in signed jar files. # The usage type follows the keyword and more than one usage type can # be specified with a whitespace delimiter. # Example: "SHA1 usage TLSServer TLSClient" # # When an algorithm must satisfy more than one constraint, it must be # delimited by an ampersand '&'. For example, to restrict certificates in a # chain that terminate at a distribution provided trust anchor and contain # RSA keys that are less than or equal to 1024 bits, add the following # constraint: "RSA keySize <= 1024 & jdkCA". # # All DisabledAlgorithms expressions are processed in the order defined in the # property. This requires lower keysize constraints to be specified # before larger keysize constraints of the same algorithm. For example: # "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". # # Note: The algorithm restrictions do not apply to trust anchors or # self-signed certificates. # # Note: This property is currently used by Oracle's PKIX implementation. It # is not guaranteed to be examined and used by other implementations. # # Example: # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 # # Algorithm restrictions for signed JAR files # # In some environments, certain algorithms or key lengths may be undesirable # for signed JAR validation. For example, "MD2" is generally no longer # considered to be a secure hash algorithm. This section describes the # mechanism for disabling algorithms based on algorithm name and/or key length. # JARs signed with any of the disabled algorithms or key sizes will be treated # as unsigned. # # The syntax of the disabled algorithm string is described as follows: # DisabledAlgorithms: # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: # AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: # KeySizeConstraint | DenyAfterConstraint # # KeySizeConstraint: # keySize Operator KeyLength # # DenyAfterConstraint: # denyAfter YYYY-MM-DD # # Operator: # <= | < | == | != | >= | > # # KeyLength: # Integer value of the algorithm's key length in bits # # Note: This property is currently used by the JDK Reference # implementation. It is not guaranteed to be examined and used by other # implementations. # # See "jdk.certpath.disabledAlgorithms" for syntax descriptions. # jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, DSA keySize < 1024 # # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing # # In some environments, certain algorithms or key lengths may be undesirable # when using SSL/TLS. This section describes the mechanism for disabling # algorithms during SSL/TLS security parameters negotiation, including # protocol version negotiation, cipher suites selection, peer authentication # and key exchange mechanisms. # # Disabled algorithms will not be negotiated for SSL/TLS connections, even # if they are enabled explicitly in an application. # # For PKI-based peer authentication and key exchange mechanisms, this list # of disabled algorithms will also be checked during certification path # building and validation, including algorithms used in certificates, as # well as revocation information such as CRLs and signed OCSP Responses. # This is in addition to the jdk.certpath.disabledAlgorithms property above. # # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # # Note: The algorithm restrictions do not apply to trust anchors or # self-signed certificates. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \ EC keySize < 224, 3DES_EDE_CBC, anon, NULL # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. # # In some environments, a certain algorithm may be undesirable but it # cannot be disabled because of its use in legacy applications. Legacy # algorithms may still be supported, but applications should not use them # as the security strength of legacy algorithms are usually not strong enough # in practice. # # During SSL/TLS security parameters negotiation, legacy algorithms will # not be negotiated unless there are no other candidates. # # The syntax of the legacy algorithms string is described as this Java # BNF-style: # LegacyAlgorithms: # " LegacyAlgorithm { , LegacyAlgorithm } " # # LegacyAlgorithm: # AlgorithmName (standard JSSE algorithm name) # # See the specification of security property "jdk.certpath.disabledAlgorithms" # for the syntax and description of the "AlgorithmName" notation. # # Per SSL/TLS specifications, cipher suites have the form: # SSL_KeyExchangeAlg_WITH_CipherAlg_MacAlg # or # TLS_KeyExchangeAlg_WITH_CipherAlg_MacAlg # # For example, the cipher suite TLS_RSA_WITH_AES_128_CBC_SHA uses RSA as the # key exchange algorithm, AES_128_CBC (128 bits AES cipher algorithm in CBC # mode) as the cipher (encryption) algorithm, and SHA-1 as the message digest # algorithm for HMAC. # # The LegacyAlgorithm can be one of the following standard algorithm names: # 1. JSSE cipher suite name, e.g., TLS_RSA_WITH_AES_128_CBC_SHA # 2. JSSE key exchange algorithm name, e.g., RSA # 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC # 4. JSSE message digest algorithm name, e.g., SHA # # See SSL/TLS specifications and "Java Cryptography Architecture Standard # Algorithm Name Documentation" for information about the algorithm names. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # There is no guarantee the property will continue to exist or be of the # same syntax in future releases. # # Example: # jdk.tls.legacyAlgorithms=DH_anon, DES_CBC, SSL_RSA_WITH_RC4_128_MD5 # jdk.tls.legacyAlgorithms= \ K_NULL, C_NULL, M_NULL, \ DH_anon, ECDH_anon, \ RC4_128, RC4_40, DES_CBC, DES40_CBC, \ 3DES_EDE_CBC # The pre-defined default finite field Diffie-Hellman ephemeral (DHE) # parameters for Transport Layer Security (SSL/TLS/DTLS) processing. # # In traditional SSL/TLS/DTLS connections where finite field DHE parameters # negotiation mechanism is not used, the server offers the client group # parameters, base generator g and prime modulus p, for DHE key exchange. # It is recommended to use dynamic group parameters. This property defines # a mechanism that allows you to specify custom group parameters. # # The syntax of this property string is described as this Java BNF-style: # DefaultDHEParameters: # DefinedDHEParameters { , DefinedDHEParameters } # # DefinedDHEParameters: # "{" DHEPrimeModulus , DHEBaseGenerator "}" # # DHEPrimeModulus: # HexadecimalDigits # # DHEBaseGenerator: # HexadecimalDigits # # HexadecimalDigits: # HexadecimalDigit { HexadecimalDigit } # # HexadecimalDigit: one of # 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f # # Whitespace characters are ignored. # # The "DefinedDHEParameters" defines the custom group parameters, prime # modulus p and base generator g, for a particular size of prime modulus p. # The "DHEPrimeModulus" defines the hexadecimal prime modulus p, and the # "DHEBaseGenerator" defines the hexadecimal base generator g of a group # parameter. It is recommended to use safe primes for the custom group # parameters. # # If this property is not defined or the value is empty, the underlying JSSE # provider's default group parameter is used for each connection. # # If the property value does not follow the grammar, or a particular group # parameter is not valid, the connection will fall back and use the # underlying JSSE provider's default group parameter. # # Note: This property is currently used by OpenJDK's JSSE implementation. It # is not guaranteed to be examined and used by other implementations. # # Example: # jdk.tls.server.defaultDHEParameters= # { \ # FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 \ # 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD \ # EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 \ # E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED \ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} # Cryptographic Jurisdiction Policy defaults # # Import and export control rules on cryptographic software vary from # country to country. By default, the JDK provides two different sets of # cryptographic policy files: # # unlimited: These policy files contain no restrictions on cryptographic # strengths or algorithms. # # limited: These policy files contain more restricted cryptographic # strengths, and are still available if your country or # usage requires the traditional restrictive policy. # # The JDK JCE framework uses the unlimited policy files by default. # However the user may explicitly choose a set either by defining the # "crypto.policy" Security property or by installing valid JCE policy # jar files into the traditional JDK installation location. To better # support older JDK Update releases, the "crypto.policy" property is not # defined by default. See below for more information. # # The following logic determines which policy files are used: # # refers to the directory where the JRE was # installed and may be determined using the "java.home" # System property. # # 1. If the Security property "crypto.policy" has been defined, # then the following mechanism is used: # # The policy files are stored as jar files in subdirectories of # /lib/security/policy. Each directory contains a complete # set of policy files. # # The "crypto.policy" Security property controls the directory # selection, and thus the effective cryptographic policy. # # The default set of directories is: # # limited | unlimited # # 2. If the "crypto.policy" property is not set and the traditional # US_export_policy.jar and local_policy.jar files # (e.g. limited/unlimited) are found in the legacy # /lib/security directory, then the rules embedded within # those jar files will be used. This helps preserve compatibility # for users upgrading from an older installation. # # 3. If the jar files are not present in the legacy location # and the "crypto.policy" Security property is not defined, # then the JDK will use the unlimited settings (equivalent to # crypto.policy=unlimited) # # Please see the JCA documentation for additional information on these # files and formats. # # YOU ARE ADVISED TO CONSULT YOUR EXPORT/IMPORT CONTROL COUNSEL OR ATTORNEY # TO DETERMINE THE EXACT REQUIREMENTS. # # Please note that the JCE for Java SE, including the JCE framework, # cryptographic policy files, and standard JCE providers provided with # the Java SE, have been reviewed and approved for export as mass market # encryption item by the US Bureau of Industry and Security. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # crypto.policy=unlimited # # The policy for the XML Signature secure validation mode. The mode is # enabled by setting the property "org.jcp.xml.dsig.secureValidation" to # true with the javax.xml.crypto.XMLCryptoContext.setProperty() method, # or by running the code with a SecurityManager. # # Policy: # Constraint {"," Constraint } # Constraint: # AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | # ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint # AlgConstraint # "disallowAlg" Uri # MaxTransformsConstraint: # "maxTransforms" Integer # MaxReferencesConstraint: # "maxReferences" Integer # ReferenceUriSchemeConstraint: # "disallowReferenceUriSchemes" String { String } # KeySizeConstraint: # "minKeySize" KeyAlg Integer # OtherConstraint: # "noDuplicateIds" | "noRetrievalMethodLoops" # # For AlgConstraint, Uri is the algorithm URI String that is not allowed. # See the XML Signature Recommendation for more information on algorithm # URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm # name of the key type (ex: "RSA"). If the MaxTransformsConstraint, # MaxReferencesConstraint or KeySizeConstraint (for the same key type) is # specified more than once, only the last entry is enforced. # # Note: This property is currently used by the JDK Reference implementation. It # is not guaranteed to be examined and used by other implementations. # jdk.xml.dsig.secureValidationPolicy=\ disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ maxTransforms 5,\ maxReferences 30,\ disallowReferenceUriSchemes file http https,\ minKeySize RSA 1024,\ minKeySize DSA 1024,\ minKeySize EC 224,\ noDuplicateIds,\ noRetrievalMethodLoops # # Serialization process-wide filter # # A filter, if configured, is used by java.io.ObjectInputStream during # deserialization to check the contents of the stream. # A filter is configured as a sequence of patterns, each pattern is either # matched against the name of a class in the stream or defines a limit. # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # # If the system property jdk.serialFilter is also specified, it supersedes # the security property value defined here. # # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. # If any of the limits are exceeded, the filter status is REJECTED. # # maxdepth=value - the maximum depth of a graph # maxrefs=value - the maximum number of internal references # maxbytes=value - the maximum number of bytes in the input stream # maxarray=value - the maximum array length allowed # # Other patterns, from left to right, match the class or package name as # returned from Class.getName. # If the class is an array type, the class or package to be matched is the element type. # Arrays of any number of dimensions are treated the same as the element type. # For example, a pattern of "!example.Foo", rejects creation of any instance or # array of example.Foo. # # If the pattern starts with "!", the status is REJECTED if the remaining pattern # is matched; otherwise the status is ALLOWED if the pattern matches. # If the pattern ends with ".**" it matches any class in the package and all subpackages. # If the pattern ends with ".*" it matches any class in the package. # If the pattern ends with "*", it matches any class with the pattern as a prefix. # If the pattern is equal to the class name, it matches. # Otherwise, the status is UNDECIDED. # # Primitive types are not configurable with this filter. # #jdk.serialFilter=pattern;pattern # # RMI Registry Serial Filter # # The filter pattern uses the same format as jdk.serialFilter. # This filter can override the builtin filter if additional types need to be # allowed or rejected from the RMI Registry or to decrease limits but not # to increase limits. # If the limits (maxdepth, maxrefs, or maxbytes) are exceeded, the object is rejected. # # The maxdepth of any array passed to the RMI Registry is set to # 10000. The maximum depth of the graph is set to 20. # These limits can be reduced via the maxarray, maxdepth limits. # #sun.rmi.registry.registryFilter=pattern;pattern # # Array construction of any component type, including subarrays and arrays of # primitives, are allowed unless the length is greater than the maxarray limit. # The filter is applied to each array element. # # The built-in filter allows subclasses of allowed classes and # can approximately be represented as the pattern: # #sun.rmi.registry.registryFilter=\ # maxarray=1000000;\ # maxdepth=20;\ # java.lang.String;\ # java.lang.Number;\ # java.lang.reflect.Proxy;\ # java.rmi.Remote;\ # sun.rmi.server.UnicastRef;\ # sun.rmi.server.RMIClientSocketFactory;\ # sun.rmi.server.RMIServerSocketFactory;\ # java.rmi.activation.ActivationID;\ # java.rmi.server.UID # # RMI Distributed Garbage Collector (DGC) Serial Filter # # The filter pattern uses the same format as jdk.serialFilter. # This filter can override the builtin filter if additional types need to be # allowed or rejected from the RMI DGC. # # The builtin DGC filter can approximately be represented as the filter pattern: # #sun.rmi.transport.dgcFilter=\ # java.rmi.server.ObjID;\ # java.rmi.server.UID;\ # java.rmi.dgc.VMID;\ # java.rmi.dgc.Lease;\ # maxdepth=5;maxarray=10000 # CORBA ORBIorTypeCheckRegistryFilter # Type check enhancement for ORB::string_to_object processing # # An IOR type check filter, if configured, is used by an ORB during # an ORB::string_to_object invocation to check the veracity of the type encoded # in the ior string. # # The filter pattern consists of a semi-colon separated list of class names. # The configured list contains the binary class names of the IDL interface types # corresponding to the IDL stub class to be instantiated. # As such, a filter specifies a list of IDL stub classes that will be # allowed by an ORB when an ORB::string_to_object is invoked. # It is used to specify a white list configuration of acceptable # IDL stub types which may be contained in a stringified IOR # parameter passed as input to an ORB::string_to_object method. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name # # JCEKS Encrypted Key Serial Filter # # This filter, if configured, is used by the JCEKS KeyStore during the # deserialization of the encrypted Key object stored inside a key entry. # If not configured or the filter result is UNDECIDED (i.e. none of the patterns # matches), the filter configured by jdk.serialFilter will be consulted. # # If the system property jceks.key.serialFilter is also specified, it supersedes # the security property value defined here. # # The filter pattern uses the same format as jdk.serialFilter. The default # pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, # and javax.crypto.spec.SecretKeySpec and rejects all the others. jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!* # # Policies for distrusting Certificate Authorities (CAs). # # This is a comma separated value of one or more case-sensitive strings, each # of which represents a policy for determining if a CA should be distrusted. # The supported values are: # # # SYMANTEC_TLS : Distrust TLS Server certificates anchored by a Symantec # root CA and issued after April 16, 2019 unless issued by one of the # following subordinate CAs which have a later distrust date: # 1. Apple IST CA 2 - G1, SHA-256 fingerprint: # AC2B922ECFD5E01711772FEA8ED372DE9D1E2245FCE3F57A9CDBEC77296A424B # Distrust after December 31, 2019. # 2. Apple IST CA 8 - G1, SHA-256 fingerprint: # A4FE7C7F15155F3F0AEF7AAA83CF6E06DEB97CA3F909DF920AC1490882D488ED # Distrust after December 31, 2019. # Leading and trailing whitespace surrounding each value are ignored. # Unknown values are ignored. If the property is commented out or set to the # empty String, no policies are enforced. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be supported by other SE implementations. Also, this # property does not override other security properties which can restrict # certificates such as jdk.tls.disabledAlgorithms or # jdk.certpath.disabledAlgorithms; those restrictions are still enforced even # if this property is not enabled. # jdk.security.caDistrustPolicies=SYMANTEC_TLS puppetlabs-puppetserver-7e1a9a8/dev-resources/logback-test.xml000066400000000000000000000006261470345337400247610ustar00rootroot00000000000000 %d %-5p [%t] [%c{2}] %m%n puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/000077500000000000000000000000001470345337400240335ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/general_puppet/000077500000000000000000000000001470345337400270455ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/general_puppet/general_puppet_int_test/000077500000000000000000000000001470345337400337705ustar00rootroot00000000000000csr_attributes.yaml000066400000000000000000000001431470345337400376300ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/general_puppet/general_puppet_int_test--- extension_requests: 1.3.6.1.4.1.34380.1.2.2: 'Burning Finger' 1.3.6.1.4.1.34380.1.2.3: '22'custom_trusted_oid_mapping.yaml000066400000000000000000000004271470345337400422320ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/general_puppet/general_puppet_int_test--- oid_mapping: 1.3.6.1.4.1.34380.1.2.2: shortname: 'sf' longname: 'Shining Finger' 1.3.6.1.4.1.34380.1.2.3: shortname: 'short' longname: 'A Very Long Name' 1.3.6.1.4.1.34380.1.3.39: shortname: 'pp_auth_doodad' longname: 'PP Auth Doodad Long Name' puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/general_puppet/general_puppet_int_test/echo000077500000000000000000000000331470345337400346300ustar00rootroot00000000000000#!/usr/bin/env sh echo $@ echo_foo000077500000000000000000000000351470345337400354160ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/general_puppet/general_puppet_int_test#!/usr/bin/env sh echo foo puppet.conf000066400000000000000000000005351470345337400361000ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/general_puppet/general_puppet_int_test[main] cadir = $confdir/ca certname = localhost environmentpath = $confdir/environments environment_timeout = unlimited trusted_oid_mapping_file = ./dev-resources/puppetlabs/general_puppet/general_puppet_int_test/custom_trusted_oid_mapping.yaml csr_attributes = ./dev-resources/puppetlabs/general_puppet/general_puppet_int_test/csr_attributes.yaml warn_echo_and_error000077500000000000000000000000571470345337400376410ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/general_puppet/general_puppet_int_test#!/usr/bin/env sh echo $@ echo $@ 1>&2 exit 1 puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/000077500000000000000000000000001470345337400265775ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/auth_conf_test/000077500000000000000000000000001470345337400316045ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/auth_conf_test/auth.conf000066400000000000000000000040371470345337400334200ustar00rootroot00000000000000# SERVER-547, SERVER-526, see https://goo.gl/PeZj37 # The ACLs are evaluated in top-down order. More specific stanzas should # be towards the top of the file and more general ones at the bottom. ### Authenticated ACLs - these rules apply only when the client ### has a valid certificate and is thus authenticated path /puppet/v3/environments method find allow * # allow nodes to retrieve their own catalog path ~ ^/puppet/v3/catalog/public$ method find allow public, localhost # allow nodes to retrieve their own catalog path ~ ^/puppet/v3/catalog/([^/]+)$ method find allow $1 path ~ ^/puppet/v3/node/public$ method find allow public, localhost # allow nodes to retrieve their own node definition path ~ ^/puppet/v3/node/([^/]+)$ method find allow $1 # allow all nodes to store their own reports path ~ ^/puppet/v3/report/([^/]+)$ method save allow $1 # Allow all nodes to access all file services; this is necessary for # pluginsync, file serving from modules, and file serving from custom # mount points (see fileserver.conf). Note that the `/file` prefix matches # requests to both the file_metadata and file_content paths. See "Examples" # above if you need more granular access control for custom mount points. path /puppet/v3/file allow * # allow all nodes to access the certificates services path /puppet-ca/v1/certificate_revocation_list/ca method find allow * ### Unauthenticated ACLs, for clients without valid certificates; authenticated ### clients can also access these paths, though they rarely need to. # allow access to the CA certificate; unauthenticated nodes need this # in order to validate the puppet master's certificate path /puppet-ca/v1/certificate/ca auth any method find allow * # allow nodes to retrieve the certificate they requested earlier path /puppet-ca/v1/certificate/ auth any method find allow * # allow nodes to request a new certificate path /puppet-ca/v1/certificate_request auth any method find, save allow * # deny everything else; this ACL is not strictly necessary, but # illustrates the default policy. path / auth any csr_attributes.yaml000066400000000000000000000001031470345337400354400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/auth_conf_test--- extension_requests: 1.3.6.1.4.1.34380.1.2.2: 'Burning Finger'custom_trusted_oid_mapping.yaml000066400000000000000000000001511470345337400400400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/auth_conf_test--- oid_mapping: 1.3.6.1.4.1.34380.1.2.2: shortname: 'shiningfinger' longname: 'Shining Finger'puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/auth_conf_test/echo000077500000000000000000000000331470345337400324440ustar00rootroot00000000000000#!/usr/bin/env sh echo $@ puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/auth_conf_test/puppet.conf000066400000000000000000000005211470345337400337660ustar00rootroot00000000000000[main] cadir = $confdir/ca certname = localhost rest_authconfig = ./dev-resources/puppetlabs/puppetserver/auth_conf_test/auth.conf trusted_oid_mapping_file = ./dev-resources/puppetlabs/puppetserver/auth_conf_test/custom_trusted_oid_mapping.yaml csr_attributes = ./dev-resources/puppetlabs/puppetserver/auth_conf_test/csr_attributes.yaml puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/000077500000000000000000000000001470345337400342305ustar00rootroot00000000000000autosign_confs/000077500000000000000000000000001470345337400371725ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_testautosign-whitelist.conf000066400000000000000000000003561470345337400437100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/autosign_confs# This is an autosign.conf whitelist (non-executable) for testing. # This file is a list of certnames and domain-name globs. # Blank lines and comment lines are allowed. # aaa bbb123 test-agent *.red *.blACk.6 #*.white # coffee#tea qux autosign_exes/000077500000000000000000000000001470345337400370265ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_testbash-autosign-executable000077500000000000000000000005341470345337400436410ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/autosign_exes#!/usr/bin/env bash echo "print to stdout" echo "print to stderr" 1>&2 SUBJECT=$1 if [ $SUBJECT ]; then echo "subject: $SUBJECT" else echo "subject argument missing" 1>&2 fi CSR=$(cat) if [ "$CSR" ]; then echo "CSR: $CSR" else echo "CSR must be provided on stdin" 1>&2 fi if [ $SUBJECT == "test-agent" ]; then exit 0 else exit 1 fi ruby-autosign-executable000077500000000000000000000006501470345337400437040ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/autosign_exes#!/usr/bin/env ruby require 'puppet' STDOUT.puts 'print to stdout' STDERR.puts 'print to stderr' subject = ARGV.pop if subject STDOUT.puts "subject: #{subject}" else STDERR.puts 'subject argument missing' end csr = Puppet::SSL::CertificateRequest.from_s(STDIN.read) if csr STDOUT.puts "CSR for: #{csr.name}" else STDERR.puts 'CSR must be provided on stdin' end if subject == csr.name exit 0 else exit 1 end csr_attributes/000077500000000000000000000000001470345337400372065ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_testcsr_attributes.yaml000066400000000000000000000011161470345337400431260ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/csr_attributes--- extension_requests: 1.3.6.1.4.1.34380.1.1.1: ED803750-E3C7-44F5-BB08-41A04433FE2E 1.3.6.1.4.1.34380.1.1.1.4: I am undefined but still work pp_image_name: my_ami_image pp_preshared_key: 342thbjkt82094y0uthhor289jnqthpc2290 pp_instance_id: thisisanid pp_cost_center: center pp_product: product pp_project: project pp_application: application pp_service: service pp_employee: employee pp_created_by: created pp_environment: environment pp_role: role pp_software_version: version pp_department: deparment pp_cluster: cluster pp_provisioner: provisioner csr_attributes_with_auth.yaml000066400000000000000000000011731470345337400452050ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/csr_attributes--- extension_requests: 1.3.6.1.4.1.34380.1.1.1: ED803750-E3C7-44F5-BB08-41A04433FE2E 1.3.6.1.4.1.34380.1.1.1.4: I am undefined but still work pp_image_name: my_ami_image pp_preshared_key: 342thbjkt82094y0uthhor289jnqthpc2290 pp_instance_id: thisisanid pp_cost_center: center pp_product: product pp_project: project pp_application: application pp_service: service pp_employee: employee pp_created_by: created pp_environment: environment pp_role: role pp_software_version: version pp_department: deparment pp_cluster: cluster pp_provisioner: provisioner pp_auth_role: com pp_authorization: true insecure_csr_attributes.yaml000066400000000000000000000003501470345337400450220ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/csr_attributes--- extension_requests: 1.3.6.1.4.1.34380.1.1.1: ED803750-E3C7-44F5-BB08-41A04433FE2E pp_image_name: my_ami_image pp_preshared_key: 342thbjkt82094y0uthhor289jnqthpc2290 pp_instance_id: thisisanid 1.2.3.4: I am insecure!!! master/000077500000000000000000000000001470345337400354445ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_testconf/000077500000000000000000000000001470345337400363715ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/masterca/000077500000000000000000000000001470345337400367545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/confca_crl.pem000066400000000000000000000017531470345337400407100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca-----BEGIN X509 CRL----- MIICvTCBpgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMjAwODIwMjAzNTM0WhcNMjUwODIwMjAzNTM1WjAiMCACAQQX DTIwMDgyMDIwMzUzNVowDDAKBgNVHRUEAwoBAaAvMC0wCgYDVR0UBAMCAQEwHwYD VR0jBBgwFoAUZJODtkR2pYd8nASfjQN5gUGDYBgwDQYJKoZIhvcNAQELBQADggIB ABwQ2e2XXCd8b54HzCBOxo8IBypsILzn3rA0HJzgsaT1ioMQKXaBt942J695Cagx Q21NAIKSilbZTqUOevvEHaTS1AeyRr5Ua38oTaHecI5bA+ZDm7EFtdEIRvAMI3pD KCOQlImPJTYO1IQP/3ikSWwVhkDs080/3Axy+V0QfauifBxOcFpjp6qStdAaW8Yw k5JL1hXE5ywJVOSaZtUTkcnLNq0J1BhIlAyQ41A9gl29+XU2CdwhvuAXSFwCxT0n xdPeqQNjZoGB6RsRRGuTBLucmcH1xio4hTxWxgBW0wyMMwyfPcboZ9Wfy1hC4AFy 2g1LwY9RrfF45wUOlWAvWtjvBQzv2LqFcnS9q0uy8T/TL2dSJPq5bjXI0R/cbPhh ukliIbmGhAWZ4B7lsPHa1L2CSsGNBXjYDevXKMnR2BY62Y4KL2mx7AAz/IyAWa99 rdHvU76KHRiuDCSpEoPxhmDvG6lpBEQzOO6izyBZ6VrGXNZeZEPJ81+wbr9o5ODc xqAJBnKyhiveBuggmkzi+sHRqa0sRat3ltrF8xmNoT/RtzqD2RCpe6WUzY9JWnXV ISwNTvFR9AbjEIS4Vuy5RwKLqxmcRqvN9GQsuo5RralJIxogstLddQRNw+c+h3Zu zA6SmZ55ocyn3FN9V4ubrdNF+W4BFEwe82gfspJmKZaz -----END X509 CRL----- ca_crt.pem000066400000000000000000000036071470345337400407200ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca-----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDA4MTkyMDIzNTJaFw0yNTA4MTkyMDIzNTJa MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogbG9jYWxob3N0MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAj9E21xV0npvm8tuz5c8ByDWUz7q6lJA6cmT2ruV3 jCPdm7WdrTQSbIRPHEiG4XhREXdgyGCADbfxo4GOMsPPqOk5LfMBqZaAc7eD/NSh OZVclbPvDk3FVWIdKYTpQuRoNWtDCSiBfz+QJMBbHqTlhL8tBRM74NO7Hv+qq/HQ JtfFe54LWA9mLtKMdUSeuIofiW75wztchVC9AnbyW8HryD58hO7RQcSpjHok0U4j vr8s8dMdLmarPF96ixLHGmGuqIh5n2ns9wCYqvcqIZoO8S54BkJOKqrWFMnyKnl7 pOy5hFYfRatrOEapBrrSMRXdUd+wy2TO6bf5DxlLPhYyJSBtZp9sMp2RrgmOhqx1 vYdRRFKWYKsDGAZDgblfTfzloyeAVr4l/KJGhUh+APDhw4wHIylRJMa0ky/6Xaav e8Vvp/9udSbDnmhE0eVHt1H2Z07f7yn09inbUEjeTu5cFDzGqoHVa/qD5ymGMIR2 TgOgxeU7y2bPBIZl2ufBoExR5nxLd9s/4sdUlPICuIFKeZW32ed8NA7sUQQf23Tn Dc0f8L5PB7ksKl6cX6aZz/UJUb5ApZxLu4gqmYASVvOde+jydg/sNQsQGPktlntL vfjpxdDDr44eDtj6SIzGclv1yZe0DecJilg9LeaBvnD99FthUwYORZjSlb2yl15/ o7cCAwEAAaOBqTCBpjAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRl cm5hbCBDZXJ0aWZpY2F0ZTAxBgNVHSMEKjAooSOkITAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdIIBATAdBgNVHQ4EFgQUZJODtkR2pYd8nASfjQN5gUGD YBgwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL BQADggIBABZw4RFuG4miYx5d/mp0sdAWEZcoT5uVX22AS+6nJeBqZDpU+wKG+ywR RnMF6qnUXVtBEjsGyPzMKT/H6JjvBBRyoGNQQIzcycsYT1VjlGrsw0JWVsVXdEUp Ofh4+dcwNkufkk4s0XfXJ1JHQyhmWOaAqztx1mw8flZivLe8mintioILalw+IdLv p6etfRwmvfea8yVZAdOLuehuvVDg4l0O7UZniJjclIWFEd31CE7E1wxlJiN6+e1m M04VD7Hl6ZcqlWRA4zHEpapV5Mmm5iSEXV1KjDSpyoQ31kuVBhCpyEYRG+PpDYQz BP89vnNtawS/yGvwCE3dW3dGT+FMU4DSk64NAPB6aYprBo72tiWR897mlDt+Z/s5 7z8eXwqM4MgknbOFMU1wveeReX40ZaQxUOMA0AQuHtSDiSQMnokfst0joSZf2POF lmjYxRZxDc7zgdoJLQ+d9xN92IJFWy7JMGALb9NCiuFgF7xe8wIJF5nhYAjZNbSW D5P8E5rcT+XACo/tc7iqX/r01dzU+vHUX1t0MgRJ8Bv2sMb+UDm6WHSGNdJNLWsp 1EAhQq2LnXDzl/EDvPRsDqIIfI3B5fh7SsT1/Hxr/tQFAceyd//S1tSj0xdaa1UU VQ5Nj5Ljt05lp6xRp6JqbdQezqWNeUPKNU3cuGg0iy4dkeWtF4U2 -----END CERTIFICATE----- ca_key.pem000066400000000000000000000062531470345337400407200ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca-----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEAj9E21xV0npvm8tuz5c8ByDWUz7q6lJA6cmT2ruV3jCPdm7Wd rTQSbIRPHEiG4XhREXdgyGCADbfxo4GOMsPPqOk5LfMBqZaAc7eD/NShOZVclbPv Dk3FVWIdKYTpQuRoNWtDCSiBfz+QJMBbHqTlhL8tBRM74NO7Hv+qq/HQJtfFe54L WA9mLtKMdUSeuIofiW75wztchVC9AnbyW8HryD58hO7RQcSpjHok0U4jvr8s8dMd LmarPF96ixLHGmGuqIh5n2ns9wCYqvcqIZoO8S54BkJOKqrWFMnyKnl7pOy5hFYf RatrOEapBrrSMRXdUd+wy2TO6bf5DxlLPhYyJSBtZp9sMp2RrgmOhqx1vYdRRFKW YKsDGAZDgblfTfzloyeAVr4l/KJGhUh+APDhw4wHIylRJMa0ky/6Xaave8Vvp/9u dSbDnmhE0eVHt1H2Z07f7yn09inbUEjeTu5cFDzGqoHVa/qD5ymGMIR2TgOgxeU7 y2bPBIZl2ufBoExR5nxLd9s/4sdUlPICuIFKeZW32ed8NA7sUQQf23TnDc0f8L5P B7ksKl6cX6aZz/UJUb5ApZxLu4gqmYASVvOde+jydg/sNQsQGPktlntLvfjpxdDD r44eDtj6SIzGclv1yZe0DecJilg9LeaBvnD99FthUwYORZjSlb2yl15/o7cCAwEA AQKCAgAUpBRY3k10ji+hX4L8Uq+Qyo/nGIe61tBspqz5ARodVPBzbqeIulaCmKK6 Dna9WYVZGmcbmy4Fyga2TtvX0V62gXKhc6Ujb+RTt10MJoBVQWieW8rNpL/Tt1c0 JE1OOnXyZMikQdoEJ11KyQjK5yPB36ZYeiA37muG0W7vaq9TQ9imG1LJerxRsApU slqNZdWM5g6WxKhMwf++oM+796MdhEpe0d/arp0e+lDacXqT3+BVfNVNWZLuAU4X M8S7tpVYvu2lwZAvCzjeIMc9N105pE+5pj6NxSMgrLNDAViLnSYrJikq2KV02D9e JeYRAXBYVeCL8JX52Vu3nQu9h3X+wwqh2A887TYp0Hqf++HSBj/3kNmVW9sPeP5A hNcRv1tj5NRj3m3xAVqc0TCYs8NUui0W4KlVLiRkPxqUfn6yOlmre8FJw9VFH1Xa Xy0owlrejXL3WmhPEhjFzsdBTBTwze6OTG0BgeyD9/hKgL2AjqMN0AKVIf4o6FqL 5LYIlhElI/nPKmC3qLkvSnavawZkpTUEReV9Te7c1yHKf+UFEMnM4WDdesC/Zs9x Au5UEXtxAfCLhkbiplEsLVC+QkwENdMLyrl5BedJws/jUKaXcCjADVs5x9/qvDXE 23ah3YmGsWaST/JLYilKaGvSdzWXVnAd6DJiCti+wO0k2tR3UQKCAQEAwCUbr/MO BEYWV4fml1+Bs599vfqQIwzkCIRTBo4jJKrOY/qG9yvfRo9xu10SshveJPjO7FDw yucHa8EqAzkRYzvx7MrfCAY5hOA3/Pn5XLoycC2W7bEmyDy1EklOWzG+RmoWTcCq VgVssv4RTNpuIYZOlv2RO4BDZeBbWXAWe73ONJXOmE1FqrEty4Xzvaa+sWE73RwR iRN+mnvdcUgt4Ngw90N+VE4O9phJq6VghB52zXzisebQHDkTf+MZR3LzyYE/YZam bOwQk8I1Y7tDo1WBi4k72NERDeiT7zwnY0o7M2WIFUNIkW4HsyrW6yZoh8ExYcQ3 zTf0mYAwSyZiEwKCAQEAv5yV+u3gKfMOV7WBzbrlqDPSbLtvRiPyBDtbr2YiqwTo dm/3AFrbrShm5OQhrMgrQQMWTMfebb5ZNi8yaWd7LM5Agy+oDXTO9l0Y7UUWwH/X q9534NN5T6krQYx0Q4XeWTrg35CmBQD1QF0NY7Mi/ujBlAQPsgyl14qNyIJ+N7yr VBg1egmVZcYTms/kPA0fOTWJON45ZosR779F+8uXv+S+cGTklIuHCHZmlf+68f4A oA1ernOzRKW9IN+5sqLeuwhwmrQrSzr1V357XmJ6seSawxkNq5C+ico0m+vNHetK mNrcFQmb9dI8hquv+QV5Gc4QUstveD7BwYMULJ/MTQKCAQA/LzS2nFecoiuQpxj1 6CsvlR/1TCL/06pc/p6KxkzaLuzlxamCOEQY4OzGbynJtg5L3CG3Zjp4jpZLId8d 5jNIjZrVgjTrX5ikkFL49n7Atl4Fs4gxK5MUP5pPpBmHNYlbgGFLOjMJTIldJt0r h5y1m4PWdRXAGkKPisKfW5OZJ2ZatnSUcryZD+B+T9NCJ0YH8HCOGj/N8sIsLNU5 /kFP8efQN7qgIHcdMiDvt9dQOvBYTFwDomIHFeHKqTRT4YI3XjAoeDDMGqis3i1O WXM5j9GkwAEVIFLaXwPepMpTBUMIeLfSPijr4eHYUhsQgrXXBnmlq6+p5V+i5pt6 6ulPAoIBACF5QHZCwitx66qE6fU/1kkJLJSUNf9B3lDA8eZ1aE8KH3Y5XyQvuzrH 2RnZhMyDd5L28BlfvUrcuwcNPbhOPKV6Lqj8VVZsdo9xeh5ROIVOkCXVSon7R7ET 85uS5ui45TwfXhOQWIB9R1sEJoepTs7LaK3r+7X2Ia7C5LwHl/cyvZeGVylHrVLH RLuB3/RhsnezE5Lct5hjaTHB737qdUsvsdk+tvQAYAmpbYh80XLfFcrgKw885S9z 6NNqYi2D6HcyJUHRgdK1rRCo5vJ5L8gOEL9OjCXRtoepzIEEs6OrbC/B5DrEn/tU zAAW1Dojq6FHb3CXW5TdGcotlQOqsu0CggEAYH4l0wT4WPi7s+z1StsBoFrsn3oG wzTkEILJbpRTWSnM+ETzjbEJbugNsOsNItcr3t/HhMLmhWwY4WSk9J261UdPda8u Uo3VRPw5yxlvlCqESBt65v9KPOQfSzN/eSrqqpS6b4ujWSc0ulmJBoXZ/3rqjl/1 5V2qSFf1KYmVYta0jzp9WsFdRgitimKumG11JUl6tBsp1byyrgC39tRbdQL08sxV mLrF5rPAefkPwWynWJlzrJnI2hanWB+dEGWZoyrTUkhCroj5Rx9tKMgfrzfuVjHA OQ4msb5BrC4ceQng02i9XCfui4vQ5pmcwWbfY/EIGhAY71q5y9lglXL4QQ== -----END RSA PRIVATE KEY----- ca_pub.pem000066400000000000000000000014401470345337400407070ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAj9E21xV0npvm8tuz5c8B yDWUz7q6lJA6cmT2ruV3jCPdm7WdrTQSbIRPHEiG4XhREXdgyGCADbfxo4GOMsPP qOk5LfMBqZaAc7eD/NShOZVclbPvDk3FVWIdKYTpQuRoNWtDCSiBfz+QJMBbHqTl hL8tBRM74NO7Hv+qq/HQJtfFe54LWA9mLtKMdUSeuIofiW75wztchVC9AnbyW8Hr yD58hO7RQcSpjHok0U4jvr8s8dMdLmarPF96ixLHGmGuqIh5n2ns9wCYqvcqIZoO 8S54BkJOKqrWFMnyKnl7pOy5hFYfRatrOEapBrrSMRXdUd+wy2TO6bf5DxlLPhYy JSBtZp9sMp2RrgmOhqx1vYdRRFKWYKsDGAZDgblfTfzloyeAVr4l/KJGhUh+APDh w4wHIylRJMa0ky/6Xaave8Vvp/9udSbDnmhE0eVHt1H2Z07f7yn09inbUEjeTu5c FDzGqoHVa/qD5ymGMIR2TgOgxeU7y2bPBIZl2ufBoExR5nxLd9s/4sdUlPICuIFK eZW32ed8NA7sUQQf23TnDc0f8L5PB7ksKl6cX6aZz/UJUb5ApZxLu4gqmYASVvOd e+jydg/sNQsQGPktlntLvfjpxdDDr44eDtj6SIzGclv1yZe0DecJilg9LeaBvnD9 9FthUwYORZjSlb2yl15/o7cCAwEAAQ== -----END PUBLIC KEY----- infra_crl.pem000066400000000000000000000000001470345337400414040ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/cainfra_serials000066400000000000000000000000001470345337400415060ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/cainventory.txt000066400000000000000000000004331470345337400415520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca0x0001 2020-08-19T20:23:52UTC 2025-08-19T20:23:52UTC /CN=Puppet CA: localhost 0x0002 2020-08-19T20:26:02UTC 2025-08-19T20:26:02UTC /CN=localhost 0x0003 2020-08-19T20:26:50UTC 2025-08-19T20:26:50UTC /CN=test_cert 0x0004 2020-08-19T20:35:29UTC 2025-08-19T20:35:29UTC /CN=revoked-agent requests/000077500000000000000000000000001470345337400406275ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/catest-agent.pem000066400000000000000000000030621470345337400434060ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca/requests-----BEGIN CERTIFICATE REQUEST----- MIIEWjCCAkICAQAwFTETMBEGA1UEAwwKdGVzdC1hZ2VudDCCAiIwDQYJKoZIhvcN AQEBBQADggIPADCCAgoCggIBAMz6FYtLcze9UX7lc58zxMGQ4d4Xloeh//HyD9Lc YYu2JMbR+tyBfdA1AeNbTIbTRT8nP36UULZFDuHFDksPUp8EOOnA/rA2M0IRwkK5 sEb80U88B3CA2BGPcUNn+u9n5DVwPYFwNsBREI7kFFmuEXnlwJEKmWi+6V12hxB9 ETMuIBjLZ4jPWqwsSyym9tLTxDGF/YhcY0Qf3nt5qHLsu1h6EJhj2521pKJOXzD9 JYBASv/33MzRfBDp2gt1qiTycf33tq3ANT6LReBCJgtrKK67fRu8pdX//Eo3GXsS yYubi0RbM0VnfQHleqn62kQ7y0Y4Tj4uN+5YS6foRRgMTHeimTHkbhLGAEQmS8Nw /o2nqUEqv5O4cOkWavX2Z85tZLuvMMCxHFwBVQ0CJmov9VM3dFv5yXfsr4aeSspU RZUZ66Sn/VbQhN5z1kXZwqwrpnhSLIWWfzFkk3VDFSNkedhSaVNy2BifHS4yz3u+ vXmwf8IXMLO7XebkDrvDwlxxBkPYlpCB4ytwnIx7CR+F77sz9FFgVGQNWCqEe7QJ SrH3BwiLsLtqPe0Tb3K91JrrM9IbM+fGC1IA47eS60areyS7Sr6BlllrYMzpM80g SH9RFZZmLkDGClnx/XaJtQxkkM80BEzVftlrdMaF2pKZrCPCMGCx/rwffxlzSgVm H/trAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEAxJv8yZSBEM12qiz8t8Ekp7Xa OpoeRl0W2mI7VZXjJahPIfSYCrfUaGU1ulEnI6PHFPEWpoSYX6fEKthT0tzJzNSW T9yPtXRwx4X8FjRwYIT9XTNJAUcy3G2HeB9vO2GTMFiCMrlnpiuxaCn3CkURl2rr /dFJTBSZhmvn3HIegtOUuF37IfF6GdGAIQ2dgE2RUJIMev1GaLoIknXnjafFp/Gw XTJ9nSmjkDaJRkEWqJIPx9eTJLzKIHXX5vQBEHgpuYwrVeV/TymxglGgkz6N0WpQ rxxUH6vD95VgZavx78YBzfpSON2mbSJR8jXqXxdeNXKXF4EIh8/frvVaxIJe5u1+ S/a3v6Kak3y98HIUr6bzeOHTqCWlCUjqAeH9daROG2c+TTjus4FH+5Hqq/Rsp5PU oBX8bFdT4LeY2e9RrMFfRniONuteT7zDy+KVugs2Y8PKazBJ2nLJJwvnqReqSkJe mcFA0I+LfMbhfZCBFMkS1b+E/TbIynr5GoM76VeOSjYbNxMHc9qQtrpxDPaPypoQ yZm0hu58Yfr4p6zn9xC4CCjn9LfwL/mM/+feBOvTf8zYM074eH5KlMSAGSLEVkvz cQjyd/qnyCM0NFLnzLR/m4kKOfmMX3Z5VIwxQXe/4d1gturCgjZyFNK9im0lvTGx ptmBtibvUhT92nFKSyk= -----END CERTIFICATE REQUEST----- serial000066400000000000000000000000041470345337400401500ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca0005signed/000077500000000000000000000000001470345337400402255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/calocalhost.pem000066400000000000000000000037241470345337400427260ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIFmjCCA4KgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDA4MTkyMDI2MDJaFw0yNTA4MTkyMDI2MDJa MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAJO9DZ9MoNvhoaLgNwukmmKyUwzVyhjvq4Jv284iZKKpsINg/tCOCXAW 4VH66kd4xJHO8vyvReWtiVowAN8iuLSaGqisAMjq1/HFuXOSxkFTyLwhl1kcW7uc uqhNXlPoHTSAK4unqIqYLkMgyqqFUGRPiJ89io0Cm7TqRQOgwn7qYYeJxswLi6dk mb+jOiBgsXhdnyASSgi68UOrM81Tjvnm7pAPeGlCd2EnJuKVfTW/dtaUopOrDnKW iD7w1XYxHiIyTBfbrugQ8MoOa3VWehXZN2yTv79MrIWBAQrzB6atWNmR8Wbm+MiF wyZvY0KbwbCxvkDoyZV6tThoepOuLqSuJ6ZFw9UInEvibGHmHqKln0ww5jjZz2tD QkuZHUdpQ6oMl/VlNoZgfVpONW/MlLNBFQxmHLEU79P358ARGtvpgvMn2yH38iKh b8Sb6tQXvCmw69PUtTgm96Hc6YpycwZ/Mz7r++l4idbIXqtF3lIYWL+MfVvw0sKC 9rA89OlrxYustGIdz3FhfH1nSOObdh0egr7NLYinaMd8ONG9CJgoF18fRcNyV304 I3N43lHoxXikYNlkImwlgq0wdydGFpNKbJnBcIcKx+I55q4dSFYsGsGw2WYal1jh K3z1Y9HUExeTpoP3x1IWXSw5jvsfLcc7cf9EqVuoaXF5FogBscU7AgMBAAGjgesw gegwMQYJYIZIAYb4QgENBCQWIlB1cHBldCBTZXJ2ZXIgSW50ZXJuYWwgQ2VydGlm aWNhdGUwHwYDVR0jBBgwFoAUZJODtkR2pYd8nASfjQN5gUGDYBgwHQYDVR0OBBYE FI4SYP5J8pSrTk0gKITaaWWbxUH6MBUGCysGAQQBgoxMAQMnBAYMBHRydWUwHAYD VR0RBBUwE4IGcHVwcGV0gglsb2NhbGhvc3QwDAYDVR0TAQH/BAIwADAgBgNVHSUB Af8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMA0GCSqG SIb3DQEBCwUAA4ICAQAfkdx2vufI12mLptg1cyd6NaLrcxI+K4tIEV+VcH4DKTWl beMY3PHapcP++At2pDSmZzvSLIo4ZCCo/hsO/HEo8cKEAy/+V0FGPducYq59YkJk 0H492Sc8JowLXQERbb0fQC3frymFZ58iTWizMI28kqv/3O2Q1t94aZbZi1pXjPd6 BSww2kKOFzEI1ddulZFjGf09T10fqc/Q57hOkmFu/0+FLvG3Ds2kqmK4QBbxREKr WDx/ht1tTKguluXB49phIiTKYMZSZyt6lq5gpxuQTdeRIfpvcAeLUeNyFuWwIoPG IR99+P2Brl0TzTMW3tcpwl9GN66mUI1sPhosHcbcJVi3GaXsQ0JuJ00K804YQ8bd 0jywbIUpL9WGmdz865LbSqQIYg+OMYF0Pr1MYvh7z3BCrHUP5IaPiC3kG4+uq46K SIrWZMg6ASOLy05y04tTvzggwwXE4Blozyw9sk4VR7ymwvGjFPtJPAOS2lr3+g3v BOe8Yl8v3zQWXFHQv5a+XYp6iqlz6V9DMenjkETOCy+96uOLBcUmJz0n5lh0jXiq 90RIGJHhUcsXTinqCnI23sdg8QmmJieaVKlF2R0hlwOcVaXH+rZ5r3Xn5KaVYhEW R2QPSMIunERO9AOM09syE2Flb5JnJGzSBlwINKVYxxHTXIJaQqSbHs3+gJXTGg== -----END CERTIFICATE----- revoked-agent.pem000066400000000000000000000036171470345337400434720ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIBBDANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDA4MTkyMDM1MjlaFw0yNTA4MTkyMDM1Mjla MBgxFjAUBgNVBAMMDXJldm9rZWQtYWdlbnQwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCrb+rpcdYrTzvmKe6hGJYtGAjrpZHlsDjLcK+rWG38zJi852N/ qH+/r+AetQ1+Uv6zDbtTY7DiH5JrFNMJGM4iE6rw47dI1DgMS1zyek0C6wP0o7Q1 NOc3QjuPSQcp1O8HJZIvlH9gqJ6XF3ijEPNxqKTi8BgQEKucZedxSOpHjc2yG/9b /u1iX43Z1QadNl87n6ktAja8dZSTm7axfkzkQ1RQrTcDLjy4bYc0xn1Jjl9np6bt 6c5rUL/wcAFrmTIOlaSj4TBezE+70+4HjGBtWRN2i1v/A13p5C/JlRTYlzsaF9hU pvsqlN5qQOnvLO1hj46SIXysC1FLql2QjRRVfnygLw888Z45fxG9xxQajX56U3Kb TBIwmWEcz0GtzRI1AniKwmpbi9t2Ni4aRfY7DL01nRURvDfiLxU8XvrwbHgo2T92 hLqCXB3l1mHLgAkQRSbxKhtx3pcxNYB95gDpT74plnXtrg9upEIlhzxtgNoe3Ti7 +UkRl5ss76M/nIvxiw2rcqcSrh7/quqWsUa2X1RbHu7QBGGnKHlsnT01ZncDbojl XGkM6o1YlkL9jPIGqp2YKrWiPKCt4ooY6PfKzeUinV1c6/Ob20dfB7kGIMihNucU 88af1+8lf8pEGvxM68CgS60id53BqA5ZxuIAde5tvum7ehromwBQZ3PLfwIDAQAB o4G2MIGzMDEGCWCGSAGG+EIBDQQkFiJQdXBwZXQgU2VydmVyIEludGVybmFsIENl cnRpZmljYXRlMB8GA1UdIwQYMBaAFGSTg7ZEdqWHfJwEn40DeYFBg2AYMB0GA1Ud DgQWBBTNWorLNL814BhCjBgvmUS2hiGRdDAMBgNVHRMBAf8EAjAAMCAGA1UdJQEB /wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwDQYJKoZI hvcNAQELBQADggIBACcdqHyjTLM/yN7p5PEQENAYowPQAcfh6CZwKm/s3FdWvWs+ Rlrz8mN+sfvjbzvU1sfn6t/huJ+lV76aS9HKF9Z67mEQIni+FtQDiAad82Mn00B+ RlsW2h57z1Hvy7KBlzwmPBmITC3dmp5MRwD3d8XHaPY7jDWBbQvgtCFftSJ+tUeR mn4HGFz0UHIj/5yMX7kwWEfsb+IMaBjl7VyvoAkRw5eV9n8lzve8Lq0TtahUJ3Sr ujzxoBwL8ax2GAj4tnZeiivr52RzyYvb2T2VrhGq2A1nXqYgBdHIyl7Ym8Q65swU eeW7YKWjQqe/0Rsi7Z9bMkbMNkyXtt+nMj04lzAUeQHJWJHFwbpq+DSHfN2fXnOI J4jq3oBEkiWVH7/Rx71WyPg5aFkF1KyNR6yzBNVmWrhNxt/akzxugTblNv0yd/PF f/9dECAd6ORfp49hT9IM3DZK063ya6eO0/s0O6lA2a/1In2kau8JAuTLhBEASDIP t2Hk+7z6f5nYVDW0dan5pFAkOOOqZn6tJbM/p0bvT3Zo1t2tRWi/TYPRKmlJZbmN hWPnkS5TAx8bcTXh8zhBlH+DySPerR7jcgHPnFj2raEki7/+8ouFvFCr7FFEus6M ifBF7dgWvHXk/a7sO5Wd7qQ0PEzfku8QFmuwAQL+1+74EFtj5ABisyRr6OGq -----END CERTIFICATE----- test_cert.pem000066400000000000000000000036131470345337400427270ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIFZTCCA02gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDA4MTkyMDI2NTBaFw0yNTA4MTkyMDI2NTBa MBQxEjAQBgNVBAMMCXRlc3RfY2VydDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAMI9gHOAmJ1mOcQHKqaS6yu6sICDicaK+YHpNmrscMtJo2yIcA1Oajib y0AEAw6HrUxBk961tQ22z6UV2KQ1lvAcFbR8Y0YetUhtx4Uh+V+h8lkZvcLWYHj9 1d6ZGXnFGcYGK0ib12wS9/7HbGhMEkrb/zXKfLx0iHObtMaA4R5NUim2NhZOn0M9 Ip038O8bZBd1Er1hivcnXN6R3Zdab/YkmnZRanPBC9KmrGD1iaahdJU7bo/jHsHr nt+CxhTq4Qvrm6Qj53p1Bho00oonS+fFVNJPKYM9DdRSwz0LjuW1XU45UhRNgYFC DvJ8GCAmOypw9pGkscHn14yQlgkAkzyJyuyyvWNbIYwl81lhKorPoAjDtGZYlMs0 05dTlnRchFa/4omyHWkwcGOLoHxck2mbiaqs8USDOfHAgEUztBJaRG4qzle97bPb be3eKfj6ZXQ6G2MTt54YAXAEhpK8r5wcFIzrwkpg0DbF8d61lHbPPYuhNyFDM1Rv zFvfFDlJNX7xw5eb5fLIvplbLld+csXSI6Ckh1kaerzp2ZPV9oGDZsvc6mWW/Ab7 /pLCr1zu7KG06lJgbabLXJGVTg7wTqp5J8lD4g8yj48llprrAdIChcCXhQXGUa/k T8nitWG3ABVjDzstp3Fh+wLu4TFa0TpSMv+wrfVoBjIKjxv0FxAHAgMBAAGjgbYw gbMwMQYJYIZIAYb4QgENBCQWIlB1cHBldCBTZXJ2ZXIgSW50ZXJuYWwgQ2VydGlm aWNhdGUwHwYDVR0jBBgwFoAUZJODtkR2pYd8nASfjQN5gUGDYBgwHQYDVR0OBBYE FCZ6xNaf6uWS02v4icj+icAzyFEgMAwGA1UdEwEB/wQCMAAwIAYDVR0lAQH/BBYw FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDANBgkqhkiG9w0B AQsFAAOCAgEAMGWUFrangEqbkKlsPI164mwSjEvIWggyWynODAcc2sQyKSBtwF87 0yI2gd2o8KHX8rOv4DkXsmBYnp6kWZyPTzAcYSFZ6wFymNnpSWZPZZvUteB7F2Mw y8XOEdWFXI6IYOme9A4luTv8CikNMQfDwHj6nl8dl3CTWktst5T8mpqRGJXGZsAq UzUgfRChbULE0ZipEKMWysrtsDHeTgo6F5Wlvrinoz5zk95AIAyOoyx9bSWTWeEN XBZj7an2ak9epSTtP9/Cdr0wpR/uiiRaLC1+JWRpv3F/oQa/YxZQoiWY7VK1p/fL VuMngMIaBe/IeQ7/i798V6beDPd6C86F3ZlDEvZt2XiqzlrATx545184bC+p9rJc xTVfmWRqETRgc5SrowQKOM9OQ/pVQdwjnJwxL1yhWN02n3FkDnKzFpfGubWuPCf7 GeyhPmw7M7HsQX2QFb/qCfN+6ygwqu4Dk8gX7/KUDRDwCd1HznFCXwRjBZS8f0Q0 UMVBl/cb/OPbMpJtteeucjsaNgxMcz/dcbk6m2jbYQZXraMGl5m99cuq11GiLQnL afU6l+H7uh133eMFSDHAGJ9qDLqa2cONyJ6e4xMVM1F2iI8f6SzjLTH+qVXDdBDp WfC0hvlPl/Y04WFQxvFPPwHB4IKmFXkEc3+gQn7nXtNIJJ6/XwgpJkA= -----END CERTIFICATE----- pems/000077500000000000000000000000001470345337400351155ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_testbad-subject-name-1.pem000066400000000000000000000010321470345337400410530ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIBUzCBvQIBADAUMRIwEAYDVQQDDAlzdXBlci9iYWQwgZ8wDQYJKoZIhvcNAQEB BQADgY0AMIGJAoGBANLmX2CG6mv5dQS3nzthRZ2NCRb8mZgUwM9otNR1Y7L2tPsu w++4C0pOAwxjX8Xt9gSoQtgf1DouPInvRV6//hi5Ccp77mY1ee3MhQd4SWLrNpM7 mJAtf/8qCuqR4XJjlQ+Os9sY6n5HC+48DU7tyOiqnyaoCPla8L6xVKKrzW8JAgMB AAGgADANBgkqhkiG9w0BAQsFAAOBgQDKR+92hZPwYr79noUK5RUIofuNQsA61ycU u7CoIhwyyDSKYzBIgd4VwAWae8dHzdWc0/pi1APg7l7FTGmzF8aggcSKmfgRjGVp 5DXFqidReWZiinhxKvk0Xa7dW8EIzEn3jrAD1HmwS6AiMsQ5qyFl7cCa7J6iUaPc 0qsAX1FwDQ== -----END CERTIFICATE REQUEST----- bad-subject-name-wildcard.pem000066400000000000000000000010261470345337400425070ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIBUTCBuwIBADASMRAwDgYDVQQDDAdmb28qYmFyMIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQCcNsSxbXFNI/RzaBCoAFcZnYRtMstELzgf4rfOK9QNfamuzReN ewApICsSYn+lU2UTUR3zeg1j5QmjIn7JNioUlM7C/0VNXJlPjO23W2UqRzWK72b+ 8jkRuW2aPykzNufHO1DAGewoGZjLVFJNHa7s7DSaB4a71G4bvd3McGBFuwIDAQAB oAAwDQYJKoZIhvcNAQELBQADgYEAHymMy3A5mBd3lVbdwLU2zrddTtD/vkm5VVqh khTPoGQF/wBvk1PQjl3y5W8azOAJFX3OnzHj21DCCBChkNv3olZz5omkj9PM0MMp v7dOwtET7LA3PwBBRapv8vl76C99zVOHopNvn0AnoomAH6URC0eIY4XxzCDSOqMo ZbFKNhk= -----END CERTIFICATE REQUEST----- bundle/000077500000000000000000000000001470345337400363665ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pemsca/000077500000000000000000000000001470345337400367515ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundleca_crl.pem000066400000000000000000000045521470345337400407050ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/caissuer=C = US, ST = Oregon, O = Puppet, CN = intermediateca.example.org, emailAddress = intermediateca@example.org -----BEGIN X509 CRL----- MIIC+jCB4wIBATANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJVUzEPMA0GA1UE CAwGT3JlZ29uMQ8wDQYDVQQKDAZQdXBwZXQxIzAhBgNVBAMMGmludGVybWVkaWF0 ZWNhLmV4YW1wbGUub3JnMSkwJwYJKoZIhvcNAQkBFhppbnRlcm1lZGlhdGVjYUBl eGFtcGxlLm9yZxcNMTYwOTExMDY0MDQ3WhcNMTYxMDExMDY0MDQ3WqAwMC4wHwYD VR0jBBgwFoAUy1hfHx/TaKYKoTJFy6LEDYKutGEwCwYDVR0UBAQCAhAAMA0GCSqG SIb3DQEBCwUAA4ICAQAZFPRFwG9Jk6WLEZDqiOBPR2XpHmeUQFx9NsIJvwkBublv RZzoUloVLhCl/YNobNPbNejz9IQ+dWzUhnHlqWaGfABd3/p8Lt4rVngzmzBrHO3u o8Wrca84Q3scgGbKtYMVYhfzpZxf79Zj4VEiVn5dG7ZxtLUyuWGztPE/sW08YS9R cEgza16upwQOofnZPL7bS2Yv0yDFzNwIyJKfZZlWaMfIvivGyLDl/2zu7PBsYiTx QgY7r37UqZrXhXPUnvnHzoqknd0NwPYO+gH7/z4Vo0DLzBP4vebuulufC47GH9Eq 2D48nU560sUes1G/HSnDfZaQgH6yypnNEiJ1K6E9hSbFuKMwVo1v7LaqgO+xPhnL NzZIz5K+JkVCmEKsQkufnu6ZsHz3qAC3/egZDn6P+z8XtlWfVSdawrfiEzXGQh3m vMsrAmylp8ZgwTDaIwXweiEQF/fNYSBf28vjUDfBCWlrUYD3at8x/JBbGBvTwQ0G 1FS33eVRb4MjKuG4tfS1Xt4MTGfu6ewAqtbemp9fP83h+cGYSqUbdkCqOy9/cYYZ pLmC41MAXOvvsE2Tz6PtShAXLBak6BkFNFxGCTWzZ/wjwsCzFpcrw78tZdpfT76E ttYGX24dUfGqQIlR9YG8r+LJzpC3/lLa/kLS849Ik3GyaQO+T04P7JWefZzOjA== -----END X509 CRL----- issuer=C = US, ST = Oregon, L = Portland, O = Puppet, CN = rootca.example.org, emailAddress = rootca@example.org -----BEGIN X509 CRL----- MIIC/jCB5wIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCVVMxDzANBgNV BAgMBk9yZWdvbjERMA8GA1UEBwwIUG9ydGxhbmQxDzANBgNVBAoMBlB1cHBldDEb MBkGA1UEAwwScm9vdGNhLmV4YW1wbGUub3JnMSEwHwYJKoZIhvcNAQkBFhJyb290 Y2FAZXhhbXBsZS5vcmcXDTE2MDkxMTA2NDI1MloXDTE2MTAxMTA2NDI1MlqgMDAu MB8GA1UdIwQYMBaAFMSJKl5+TQSAE8fdaNf7ap9vZFVtMAsGA1UdFAQEAgIQADAN BgkqhkiG9w0BAQsFAAOCAgEAQ7Mrn46KzqMxW3DWrL5vA0fgdNImN5fI2qm6IK+3 w8lJciL+buiMB6ttNLin/A1BLv/kJdJ6eR5ZRiluytihePNIq2QVSo2MWVBDOOxE rm4wcKTfKpcT/Fql60grkaeEJxwf/99fny/SWU6vD2bTx2geZapXmO/LWGwRADbX uLu7/uTcYnXdz8j7VPOg0DJJmNiR2cIVkgS5y3BSfxXUV/rRQEFGzUF3YTq4akbz 0TuJGgHo6kY3P4zJn+fsVYWeEiYclvpH82wPvjRMEw8QiOvlw15/0v8O1mo/5YHV yYQbVO9JaXpYB6hS40joPvZRG++Yi94KUukYRw6n4JOXcuW9Icfw+vp91hZkZXkZ YHdfnE4fCLyX1II5dy1F2soAknk607+ylkwh2fTjsVnJ+1QcIW59+m7R82fX1ecU CUMmLLfeMSQeJQeB/rrhJpoI0s28OSnxXp0WgPhcw5fBy8Of/tuEjlicoWpEd10L pWIbFf24ZTo/FjxNERM0vFnhgggtdwWqAVVx/2I2UmMZLnu+LktykIT9hXYlfJ8s at5AJS8EFUo4lNygEeiNdoNgMGsuFLDegiCEFma4fvcE3qhAnD1YliBZcGMCfn8f jH25PmwILQw8zMmnCYKDLNQv6j8CgWf8zytD+krImJ/ebgu9pVnJLznnuiFB7a/7 Cpg= -----END X509 CRL----- ca_crt.pem000066400000000000000000000101701470345337400407060ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/ca-----BEGIN CERTIFICATE----- MIIF5DCCA8ygAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVT MQ8wDQYDVQQIDAZPcmVnb24xETAPBgNVBAcMCFBvcnRsYW5kMQ8wDQYDVQQKDAZQ dXBwZXQxGzAZBgNVBAMMEnJvb3RjYS5leGFtcGxlLm9yZzEhMB8GCSqGSIb3DQEJ ARYScm9vdGNhQGV4YW1wbGUub3JnMB4XDTE2MDkxMTA2MDkxNFoXDTM2MDkwNjA2 MDkxNFowfzELMAkGA1UEBhMCVVMxDzANBgNVBAgMBk9yZWdvbjEPMA0GA1UECgwG UHVwcGV0MSMwIQYDVQQDDBppbnRlcm1lZGlhdGVjYS5leGFtcGxlLm9yZzEpMCcG CSqGSIb3DQEJARYaaW50ZXJtZWRpYXRlY2FAZXhhbXBsZS5vcmcwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCe7OxftRyyPPQ2la/OIKkFVqnqvYOZnXwu HFE7pktZaGr0ZEow1W3RxcoG3TwpCS+6GKQLCqY4eslh5qJVqkpBDcafxSQA1B6f Pigbq4PrMKIh8O1Qn/06Cyd4fRaMagwE/BHzPFprNcwg+5YzvP1+H920VpB/Snko SH4EFZz3hvbxyLZhn7wXVsZYzrUTo6sy18oTbqcA3ZA6cZf7L6cqXVJwaTkH30uI himpl2X4sFslBQ7tQcYaIKwXQZVplxYSLlDEjeMRpLLuofekNonHHTJ/ia3xFOZK K6+FO6I2RVRngQw/fIoGWNZnqK+U7yK0/Sarbisp8C5fRmNk575Jw1SAkalHo4xi TLAS1if8YsqpsohCfbS5b+HrTPtdBgmdDukUUBgkwvcx+HAlrE605ubfw0Bvdue2 CZXyutw8IqIB19gwAydeRv8ypHGJqOfLh4pupamxD83Re5ciG79C2YqFI6c1xSDq b+mHBNOSDJnQ8KR7WZLgqLKvDOEECHpdU6s4pE9Yu26y3W2VR6vWoRJtsN9L8C+2 PLqO8Dd3PqWmzShDemy80FN6pdqvdZQz1liL0wFIb2Wb+rSIbPGQqKa+usAC1ciu ZN4py/t/seyuxTm9s3ETBFImQsoD/MdPb/x34YEXw1rYwbvHTJLtlcKhLDdcMsPA mvqW6z9GVQIDAQABo2YwZDAdBgNVHQ4EFgQUy1hfHx/TaKYKoTJFy6LEDYKutGEw HwYDVR0jBBgwFoAUxIkqXn5NBIATx91o1/tqn29kVW0wEgYDVR0TAQH/BAgwBgEB /wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJkWRIUzllPR 2N8otNIkAKH7amcwt7iy4FQPGcs0iNvXWFM+inOhPWkdWEgTyI+9HG7fsnLgMKv/ XXFS5dQr9sytQLfHVfGguUq72mBcejtxDL16lLVfJ+fqLL7IP2zI7Q/tR0MJAh1k l3/rLPN9FbogSYPoI0BeM4J6rlVCIVYwwHylyHgkdvF18UvpxL6Wy3ZM5+7zRoHL RdhCIP7ZkrxEg+fGt0KPN41iFYFKof7jJWJGB9q/ld2YelDTJIYixCow2zu7rxN7 Zrv0Sou0ZRcNI0hE81BAEnC4/+W9mLKsUCTix1i4wklPtMkjA4MSme+GgqjJ2o4c FcYKASa/6Q0zALeFuj30aRbw6T+MxKEMuwS6+MfQfB58QPUQi38MIAiG64d+3uUu RuGuOuRZsq5KS2R8OXPbQ3ztyIHlHoz06wRLviEYid9KRranEi8/jO37sgdmEGtU AREM23Zkmi0T6cPujOORTVicdD7HW8l0M1rNvptDz/5AnNJLWT8TWkjeVrYCE0oC IUShmjUI/ICSekKTOuTpazN8s3Jw68CP3BUf6mdFx/wSeHvolso5lDBlT8Y5uoiI mGLzEO7Wsj1+TlvJiW5t2If/EjT6hO0OVlZ0HOEZ+2BZGJFJYqzyWAPTQxznFiEA G2F1qUEXqZGtcAar8MyYwnsZ8v5vwxgJ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF7DCCA9SgAwIBAgIJAI2MD2/6KsbRMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD VQQGEwJVUzEPMA0GA1UECAwGT3JlZ29uMREwDwYDVQQHDAhQb3J0bGFuZDEPMA0G A1UECgwGUHVwcGV0MRswGQYDVQQDDBJyb290Y2EuZXhhbXBsZS5vcmcxITAfBgkq hkiG9w0BCQEWEnJvb3RjYUBleGFtcGxlLm9yZzAeFw0xNjA5MTEwNTU4MzNaFw0z NjA5MDYwNTU4MzNaMIGCMQswCQYDVQQGEwJVUzEPMA0GA1UECAwGT3JlZ29uMREw DwYDVQQHDAhQb3J0bGFuZDEPMA0GA1UECgwGUHVwcGV0MRswGQYDVQQDDBJyb290 Y2EuZXhhbXBsZS5vcmcxITAfBgkqhkiG9w0BCQEWEnJvb3RjYUBleGFtcGxlLm9y ZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMCqFvzFEpxbfW8t8FXC GqLMVahFKTM9hpexFVI7e0AHz15eN/mqCihYRCD3wAwUOFi8W/uVxm1Ma1Z3q1QC y43wQ4uQsYJEzPlNgNnfgLExPg2DRFt61W9lPdhwaCjnsZNvythmsv0k6FCDc62J CWuYasdakOhJa0GdHEwy1QwQ1sEHYN663+XWGPfh1inNSzK3UqjqR6g8VWlT8QA0 HUiKGCb0vGDcIxIt0VlbqCIvJiZpnBJC6PVSo7pr84QuSSVdjP2hcmHYWPBWpOYg 8/1ZHIaSZUF/6dc+vWRGG3/W7FI+2F4t/fNU0AJay8WilStZkJB9nBjrwrAOESSU Bx7WgLbBBAUgHqXD8IROenWdUAQA4TmxikVZ/mb7B4MFHlLgMpn4FbAfPloFMYm+ r0ukxbMgAeklwtM25jxPB7qUza4fkNzTCIERX0SH4RzXNhBsAjRsr1Uc8shYgx3+ qcY5ZH1XpceupCrkOGHzRTg1BZR8cOuSr5No1B2WNGtsstk6wwibRik9SeHqRl8F Jb2D3RinnZXVdelfFn1hBrvGp2vGoKSi4TM4CC8CbGGN4hWpZsJA0tDXLd5WLSxo wAPtk98LUsluQdNYIjtMpFvavSASTOUqvMk+cJOYPDk0uTfsMzrLvRslKzo+Wd9B 1uHuUgW4iWsOIU6QnD+z1vb1AgMBAAGjYzBhMB0GA1UdDgQWBBTEiSpefk0EgBPH 3WjX+2qfb2RVbTAfBgNVHSMEGDAWgBTEiSpefk0EgBPH3WjX+2qfb2RVbTAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEA u+yDfMI8+WzjxV/NGwFUn4WGifq9utiQpRJdeXxgVMqwGTc62zhcEDvUlKclt2la CsCj2UxpPgTTmd9z15ID5KBoLn7S2o0PbruUM7gI1nO1hf8+7ng8RmG84M0Ec/aR 9PrbAuP61j1tuIhVUvwzUj+PAFu7/jNsq7AfyihGi4OFfD0lydS0S8rY/KksnjZ6 l0tveuzO7aKqFtByJBVnVi292tLA0Wjy9Hyx77uzf2Zo6wWrxTShQi6XrTl3i5aj ODEBEoVpuup7/YuaK5iBKL1Gm00fx7Q7iJq6kHfpl7qM0E70sCrfG9+qbtoH5EbR A4okxWSrKcPVkADWZScKiLzbOmPHR3rT4a3wAkRl++2BxC5WoKX2Q0E4v4WYfArj swwWhxPYvFnGGjrCjxg5Adr/w8TL4Vgupi898f1beS1/mQJYPAELhZBWbGcKwqMt 0vadLdAKQ9VQ/BGweaSwRLDQjLtnqPgVkhjddfi32/y+Tezc1F2NqZr6faKt3oPE K8Qaz7jFtO2XmBk2HSyG1GqyvYaesgSxKT76cpKuPSDrZ6wehzpzsqvanvAG0kfo gb8fxTf3YMhP2QKIpP2DYy8UePXUVQnuSxfrs5XPkVxzLMbDT0WUgrrAFLTnSvAS xzvFs6Cox2dd/ipsuXcu0SfwgGhufcs8jZWAHNPNqrY= -----END CERTIFICATE----- ca_key.pem000066400000000000000000000062531470345337400407150ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/ca-----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEAnuzsX7Ucsjz0NpWvziCpBVap6r2DmZ18LhxRO6ZLWWhq9GRK MNVt0cXKBt08KQkvuhikCwqmOHrJYeaiVapKQQ3Gn8UkANQenz4oG6uD6zCiIfDt UJ/9OgsneH0WjGoMBPwR8zxaazXMIPuWM7z9fh/dtFaQf0p5KEh+BBWc94b28ci2 YZ+8F1bGWM61E6OrMtfKE26nAN2QOnGX+y+nKl1ScGk5B99LiIYpqZdl+LBbJQUO 7UHGGiCsF0GVaZcWEi5QxI3jEaSy7qH3pDaJxx0yf4mt8RTmSiuvhTuiNkVUZ4EM P3yKBljWZ6ivlO8itP0mq24rKfAuX0ZjZOe+ScNUgJGpR6OMYkywEtYn/GLKqbKI Qn20uW/h60z7XQYJnQ7pFFAYJML3MfhwJaxOtObm38NAb3bntgmV8rrcPCKiAdfY MAMnXkb/MqRxiajny4eKbqWpsQ/N0XuXIhu/QtmKhSOnNcUg6m/phwTTkgyZ0PCk e1mS4KiyrwzhBAh6XVOrOKRPWLtust1tlUer1qESbbDfS/Avtjy6jvA3dz6lps0o Q3psvNBTeqXar3WUM9ZYi9MBSG9lm/q0iGzxkKimvrrAAtXIrmTeKcv7f7HsrsU5 vbNxEwRSJkLKA/zHT2/8d+GBF8Na2MG7x0yS7ZXCoSw3XDLDwJr6lus/RlUCAwEA AQKCAgAFTQ3NW3MrltDmiTOmAnzgyrU8OToMg65Cs3saLD/TKaJ3qGi5HEVfe+Nz OynojH/lCzFdlOtacu4Ir/K2PMnhRZ5ccezzgh/LW/1mfuAVljeyPiEMUWnW58xX PoTkBh2EhQvsOxUhAlheuUWXUDR8Yn+4pjKHrGpCJ7jcVgQ4VW4jPnim5PcXKDPR foOXthvdxEjfQQ+c/cbzzBovrLU8uoQnb7sRQid41FDLcVtbYjaIE5Ud4NXExVY4 KF3decaosJbNF5Z9XisBvrFN7uvFknm+u07r/bB4xOBD52tPuBxKn4lTDMplz8zH BF9m7lsQAmmpyjDyYyqIzwY9tWUpbzy4cHkpa7N93TogkRnCvyf8Jl8mtgJYAKnx XZjYemDyZEgcClQwPoUvR4fGJWg4Lqq2j7l+Yk756t9d/x4foTGQYZ4h+bt9klqw k6JTeH4XMlruZrCikdYJnobr/RldMf7cZKSGtpNy3qvK0cEoiDnaDaIU9C0DimjG FlkscYaiNvY2K94nUuk8uJxIUYa/bKl2wdAhS4T8l7C1RzRqzODQF5t59yR4WyfH 1TscgKZutSF6odowudJbsuxI69gso8Ee5H08ST0oLkGlMClFgXVrtWu4LybC6+JQ 7RlktLk9WJqNP29xSZVwcG6FLZw6HvQWFlTNNlRLP/25iYuQAQKCAQEA0lrAXT+f CmrdM9L7HWjPRvc13ngGfRBpphS+QeCaIMhlH4nVNjqgDb3o+WGjYuIYLE/ACDOx lXbOv+VZnu+GaMa1cfLlvm6YenoT2Go4//QvLKIw5jOY80t3ZTsD4efXSsKjL+lX BC0OGWkOfz3sV+6REdJ4M8Ay9qa5+0lD1uN9zV35BvYgYB12/S68jo68OXMSyoGy r3aA6zho8AFp4DaFwOCrT2MLHxDy0zC6Hp0MV5IMBHB3wR/hBDwBvYh7nbIOXNO5 1y+ztg59GRc/6fZi78q6JE0d9aSCzBomvQfBq4suq39hSXMl9RNZjYUjPtUjL6JD RsDhtVqz0r5CAQKCAQEAwWlGvXoQ9U5OcLJBRMVIo5YrLdnE4k3iSmS2HVlJ5VJ1 29+PYuoZWmoGoQMR9Uwaolxs+KSAiesjf+C+wuhoC7FsWPQX7WvL6CCIKDRjxRvu v18in3yBOE9bMTtEZqcjBnWgbeVLTTrkwXY5kgAuy5PLhkUtvsVcfU+WjCza0AdT +myAP9uKNU7vTfngtXm99TheB4VJMP914hpGzS/2Q4tbFbLqilBAm+4Yr2uwCghT 0ELliSQSBq4Da5Tie8EXZLB0r+JbcTH9y9/mkr/8AbSUG8QUyg12vQaL4Egg7Jt5 4I+EeDWf3wCF2EGnHUdwfvRllEBdLlpIfuxMHFtcVQKCAQAz0UcxsUpsNobnDUHu rLLiuGL8unReunxL/TAg6kMNcE/4xOtQwIBM4ktRo0usQCXURJD5dEJ6nxmvC8BX 9okVpl1sBHmzv2qwQQJCfWgtJOm6BPomuu8if6SZuz/plkLil6+7Ta+xx6eBeu+n SIm/33S8/yu9E8t6FvgZfqLHfKKwxEVkAZ1YD+oP1EN+moqjXEV0vR5XOsnnJ64x 8SczpDqumKmalLtYm8Q1Yft3LxirOb7cGRhm6oNzl5SWK9jHr+T52O4epBGQ92C5 nZCRAbC9gSL5bkXDDRNrU8XXKuH6b/6/IFHG1iaziGC3C+TyxW41fbM06q6vDfje ISABAoIBAEJxWh3pez3qQsQwWH+5jnS0N+0ubJaZzu1jn7SBYgNnyplYObfvV/pZ hiF2Hos4M8YnHkBkssuufamGmcH3eRbbQq9kW3vylkAOPPgi10t1hxUzJ3/Gk9W2 XUuSYrMpI70qV4ypQq8rVj6n0Ks5aNoC0d40kbyBrH5YAw3wstLYUZ8r+vr0/ovF rCwLdYiiZAGD9bl7rmMov2SHRl9i5KTbkNTpe+08GJX4u3437mfj6HcZJCVywMaO rRoeMZf2A4VRoSRzDJrcY6XQKzOqxHYJhP/s4n9vFKVnRFIuNTFTUBE2/HkXYu6H DXP3SeOjESBr8SF24wvzdAg2QQdU02kCggEAdFFoh4igxOz0cb+tcMjI6KLjseQh PxLUZ/SPpVK8f/jw8eaMi/lLliP+D+xFwxMPVYA7q3QkSZSCt/tg0rgOEEW/oyvM 0Mg8BtaYBcqG/J2yBvsT2C8LhO8WDFk+zMPgdyyCWdRjSh7Pmf1xDXLg0Esb8839 gZJi8B4l4/0w8ybdgJzPwDkmsbbRFKVVyhfU6DPp2jKUZ3HYXz2GaTpfRozUGoDk BhT4WCsOWVtWn99zzxKrR2fSMAQAlXfxN5HvZJEYAjveT7Q241CpnSXsLYMdeTy1 PRaeLZL/GkFue15R++YA46oBZRxsPp6nGpRsxSkEii2d4n7sQyJrYKM9uA== -----END RSA PRIVATE KEY----- ca_pub.pem000066400000000000000000000014401470345337400407040ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/ca-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAj9E21xV0npvm8tuz5c8B yDWUz7q6lJA6cmT2ruV3jCPdm7WdrTQSbIRPHEiG4XhREXdgyGCADbfxo4GOMsPP qOk5LfMBqZaAc7eD/NShOZVclbPvDk3FVWIdKYTpQuRoNWtDCSiBfz+QJMBbHqTl hL8tBRM74NO7Hv+qq/HQJtfFe54LWA9mLtKMdUSeuIofiW75wztchVC9AnbyW8Hr yD58hO7RQcSpjHok0U4jvr8s8dMdLmarPF96ixLHGmGuqIh5n2ns9wCYqvcqIZoO 8S54BkJOKqrWFMnyKnl7pOy5hFYfRatrOEapBrrSMRXdUd+wy2TO6bf5DxlLPhYy JSBtZp9sMp2RrgmOhqx1vYdRRFKWYKsDGAZDgblfTfzloyeAVr4l/KJGhUh+APDh w4wHIylRJMa0ky/6Xaave8Vvp/9udSbDnmhE0eVHt1H2Z07f7yn09inbUEjeTu5c FDzGqoHVa/qD5ymGMIR2TgOgxeU7y2bPBIZl2ufBoExR5nxLd9s/4sdUlPICuIFK eZW32ed8NA7sUQQf23TnDc0f8L5PB7ksKl6cX6aZz/UJUb5ApZxLu4gqmYASVvOd e+jydg/sNQsQGPktlntLvfjpxdDDr44eDtj6SIzGclv1yZe0DecJilg9LeaBvnD9 9FthUwYORZjSlb2yl15/o7cCAwEAAQ== -----END PUBLIC KEY----- inventory.txt000066400000000000000000000003271470345337400415510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/ca0x0001 2014-10-07T18:03:58UTC 2019-10-07T18:03:58UTC /C=US/ST=Oregon/O=Puppet/CN=intermediateca.example.org/emailAddress=intermediateca@example.org 0x0002 2017-08-16T19:15:24UTC 2022-08-16T19:15:24UTC /CN=localhost requests/000077500000000000000000000000001470345337400406245ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/catest-agent.pem000066400000000000000000000030621470345337400434030ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/ca/requests-----BEGIN CERTIFICATE REQUEST----- MIIEWjCCAkICAQAwFTETMBEGA1UEAwwKdGVzdC1hZ2VudDCCAiIwDQYJKoZIhvcN AQEBBQADggIPADCCAgoCggIBAM2lbWXwIkH1eT+IFwEMEshvzX7tt43HyOC5n0Ae GMEf2QSHh/4jb2gk4KZ0jcXixIRmrD+bmme6oNZuq+aFFvDtgGshcZfZKB0wvWYN +Tdu51Z6Xth9cWiG3/8S1SEXEtreVDs6RzHe5GfuEtwtmVQAKpMqrS+xSSwlhz/P +7CqLS7MaXjXZ0vPW7UGVlP6UUn+1vun3doQWYxkwlIHGuN2C7rCgXZaPPOHNKa+ lskcCQSOPrnnbNjfti9SPZaqgdHS5SWBkbsLDs5ho1XQgna4uhLS14xAXDExqHWd V4te1+nXA+/uEO6MhSG3kXj05VtH0v72HjFQC7kWKHPa9XKX2kLnO6eCGhpizpgd 5vCTcb5KitK4Hu1+n2oLZo5Aw3m2EsrvRh1rFmjv6nWgKCrG6UlEJciq3aQJVLds wY5+CEgvcMlFgMYe0+FR/9I1KgmEjD5ZGgtj820FyztFFkr+/oXwZ2NJ1Wb/nsVb jditsYlct5cksXH6DJsOyt9hLSFuEYuHGUsQS+CAsyvo1b3lLprkI3ncofp3FVaU /WoqDgAIPuVMymhli4mgsiHT6xTWltphwP3W/YbnYG5sAqn4B/xDSdrSp+7VTkS4 gogHFRCT7LuyYAo1TI8IY2ApCNZ8/Pj6yGjMjBcSGVJROF7ZX5iBiWvfQ/Sa9fMz 3uaRAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEAK9+2osaxnW1L0gBegaTl5h+X YUON93iE64pY2EF7MhdsgoQCmcrMfaZ3kFd+MpXMjYz7tc/83u1wvd0HYAsnRcJE Hu3ZdHA9kEqtpjm0xLCeWip/u3b2QzjcjatKk4MuxwtjrCKeM6kTGAXuaQnB9C89 4t/AbT1Vd54BlBaj69SI8HmMEzY3GZ6B+OLfkQ/YTtkLDVPkC2I6gHEOcrYuf1IW g9/E0TZe0MbjfVljDXkOPQpGlSCk9lKNRg09IhrFI/mNjb45itbTAiWNS40cyGSy 874766BEPIACnZT5O8cLAFhFzXLfAo/1RNSbwHsgosBdtq/3byl6ujvGOKE8uYEl /WiWDzHaI5KUd+8xt7yE7qCQHpqfCjiYZ2KFzjaTWh4QE9txIerXS5nPTCJ9SOti 9Ti5gQjPoQpj8XF8fZNFQThp5yQbS2EHub0IvGbluU6YEMsE6/prdvsHsmg4IZUV b7F4pt0n/rV/MTFtCP+IREHI8vAOZL1UmqxW9jyH3CVysYTqg1E5iXnyfWHm3sfX yf9s63zsHQmuKLvJO6KLBOdCm6Bpmgmq2K7zLdDhtPT9mKxtd4F+MECcyMS+CRcN /HxnOLdGGFM5JQ26vAwNmAfhxcZU5t10PfiCURZk67TanI6mFzctZYnu+dsMD/jo Sftq7LHr104iC3tlNWE= -----END CERTIFICATE REQUEST----- serial000066400000000000000000000000041470345337400401450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/ca0003signed/000077500000000000000000000000001470345337400402225ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/calocalhost.pem000066400000000000000000000040251470345337400427160ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems/bundle/ca/signed-----BEGIN CERTIFICATE----- MIIFyzCCA7OgAwIBAgIBAjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJVUzEP MA0GA1UECAwGT3JlZ29uMQ8wDQYDVQQKDAZQdXBwZXQxIzAhBgNVBAMMGmludGVy bWVkaWF0ZWNhLmV4YW1wbGUub3JnMSkwJwYJKoZIhvcNAQkBFhppbnRlcm1lZGlh dGVjYUBleGFtcGxlLm9yZzAeFw0xNzA4MTYxOTE1MjRaFw0yMjA4MTYxOTE1MjRa MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBALblxul9nLcM5zBaVktTiTE5iR7n0sp4k73xO5VJO+C3MdYcVxHwi3jC skkCHH1y0Zdpzffo7vnBw8XRJTjYLeIfx+gp7c/PPD3eVm51qrr1ZdO8jLgdcAJS ql1rLVMWOjfp9Ju8NSepykHoQQz3E8xvmOisJP1gXHo4apzFQXWBg7l943Ek81Vo lvjzoTIBpsPGWbddHqVXk/ymYIryBHz6ya6ehOjLQdj/8dfdZWoG6uha0EZpmsef TtyuIBkb+XUQfUTtCYoZmOJIi9ifCudGWpqa/wtUIwasBwdFsMghyxZLVtzAX4K9 gxgeDwnTi4rxDswZLmhEcngOaKXamKmSlQD3cbIiI7BcDfDL5mAOmsANnTHW0d9G vUzltZgZl0G7yBHVS5GPbqiCA/mI1180bTTvWvjW/lwvv32MNTIIT7A1xmuPoDcc 7/m1QuT7tcZ5OrDoT1hLHa+RkXJJE8LEg24xUwO0bXKcHJaLlW4YQfH+fOGpNfUg Qf4fJiypOlyCV12G1bo8v38up3g1P+zh7DT8EEqMNPojtSGFddcd6uCRisWFOfka ZTw+F/4mcZX2aWqr/XuAz7Xrys/RdB3AaMffc0xSUNwvUFuuCQiCtvNoX5Av9Ozk E+PbyRU93sJ9U3qKdadXOTb2xv8ofMzhMbW3stPkR94W/4fx1kGlAgMBAAGjgbww gbkwNwYJYIZIAYb4QgENBCoMKFB1cHBldCBSdWJ5L09wZW5TU0wgSW50ZXJuYWwg Q2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUF BwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQiJDt9BRlsqY4z HO7+6CZAOC8B0zAfBgNVHSMEGDAWgBTLWF8fH9NopgqhMkXLosQNgq60YTANBgkq hkiG9w0BAQsFAAOCAgEALA8PogSLRczMuif5XzuMP4ANIpb+tzHpF6I34T2qodir jWLukH0f8io6jl076GiNOM3nopAdHuU9Y73ttlQl0A9OVoWTPUhtA9vllXVPaaF7 8yzOSccbgo5fOd+f4v7eTLnI9AoCf5i+ODoQaWQHs0bxP+hwbZtAGT33hVmyZx+r Wyj92PDT9fRxCfEt31HrJrftICrX05RBvEuhJUeWlFoE1hsi2NckstUHqiJw98SY /RX92vdHCFPUWbltO3YQD1NuHiFqmD1w9TKyTFk2bXZH2j9ZPOiYTbi9jsRyoIE7 w8uoOApchDsXUyxj5oZzCU0o+c64MM5Qg485gbK3O+ZuRYPYyRCqWefrbK6izsZW ySlupZ2OWxOYGIdGnt6ALRt/hSgL4bT5LCGBKFbRpLhL9hkSmKfVzsDGS51JoPqN BRLGlfy2yWbMXiUj2XYSEvGwY0LwtMyOdDyc2LXs/RdLYpRmKQObPcRgUIDC9Y5f F/cTl25MA5B8knJtxy0McwezMqo3sY/WebJIhxgIxfc7pzIVTiMrTi4yt8MKZoKa YLhME/69d5ndd1eApXKjGuc8Nov4TrR0yJN64Nl+YU/SXPhqUpDWBWVzpW/QHo4i Hr8Mq94Hk8+aZl0SDu5b2wbDwtDJupjsXc5VoExEEh7y3CZoAVJHykFQFbnYEkE= -----END CERTIFICATE----- hostwithaltnames.pem000066400000000000000000000032071470345337400412200ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIEmjCCAoICAQAwGzEZMBcGA1UEAwwQaG9zdHdpdGhhbHRuYW1lczCCAiIwDQYJ KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKgUzmEZkPmZ0/NWU98HWrcav8pwaVRe jxORdl6FrhFl266IlPimVT30xSmRoc8qBiKgmil8akalVkHyWOHmsX04DwBijNC/ do5BbAsgj0FG0Qj7CzCzqqWuVMWZ0BnComGXM0+PhEfftwvBQc6LzTktjWmzJG58 HeY6T/PQk2sXqmMd+skVWatN+63CWNmxRM9OndX7CoBhdRA0DSYsr7bUmHVCx/R1 D0LxVCdC0jdQSNhrInXx2USRHyqGPLdsV0MtPhBM0nTYK0uATCVIMNb4FJfzntcv Agsj+sjN0kAfzyIk2PyBVrvnV9rfFZN1fpbXIg0Lpr+qcAo9xC9qJn0luepR6xVh /wfQvZevwwOz0K49y9jZrQBg+Y+JEIRSmnMcqV7mChuPSrld/IvkxbQPDZLAXVzB dKj4gT+NXSGdDR7u7hneXkeoSlgGuV33bBMn4BoMmNU24/VrjyvIfaKvHGZYp3XP xRlZFQ1YlYU+kfFtonhGRxTMslhTwTTOdmyQHQrvRueTNG9MZ/XIbrs+Y3PLGtWY 9iyAhFFopYe0X1r/ajWGPXJOvVhWOfiLvyPGKAaxCvnOD2EiDF6C1Wc6FdPtdUHM RCLwTqDfkX0wAFw8PiDJqFzFAWlJzRkoXcQxItS/t0i8qjkHKZPvpfwu4qD9FV2Q kifSNQY12n0PAgMBAAGgOjA4BgkqhkiG9w0BCQ4xKzApMCcGA1UdEQQgMB6CCGFs dG5hbWUxgghhbHRuYW1lMoIIYWx0bmFtZTMwDQYJKoZIhvcNAQEFBQADggIBAAnK GrD+ZRNpHJ28CBnqoPaV8obbI1IkzN2dvNHpnSsLxAlbICS1XQTuhsQtSX8ROHtQ cgRqVwmM6sr3AxvSl6BQAEdyHJ//fdQ50Wzrd7cMrgGVSW+Bl5m5nR95upCDTe4N SSbg6xl5UJ/K7M7gJFgHNgJTRqRPnHl6CCRVI8BHh22l/AjHk05KNb9ddR9Z8azc gCPw2exG16swwaZgKrHCihTvKl00oun/5QhvsBVM9RWnFVMW1iPs+mLyyFyVXB/1 uh+vRJ5tQynda00LCc6VOq/ZlWh+ue2KcVERijdRyhTyP/9ljWfWGZSNkQqW+oL6 J64AvvaDUnDcmCvrMVH+lpJyVoHHI4XGHMBPgT6uACRtH5f7UHr8ik7nMcWb/AbV AipsLqbI3UVuGgeoDR4ULoNETOjd9UBGdtIJC2lozeDT5Br4IfHFCzrat6A8TUI1 z7pFonP0W60IELPCNePlcd+lbrMIdLBr+s1IzPbJ3DvT8EJwUUs0sbOM+gnhIWfW cI0Qz+iLu9qH4IuGDq/JvoaqFwwRRjYjFFn6i/4FEkp8OIyACzGcTdt0L4EwevZX Eo6EsG8euPXTylkiA+F5F1PsGw8ZGR0LowO4dxVYMflt35IXsYjtnBQbaht6oP8S LNa26jDNcvCf/F0F1DIagsbJJoEQx8XDzG7chtZv -----END CERTIFICATE REQUEST----- localhost-csr.pem000066400000000000000000000017311470345337400403770ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems-----BEGIN CERTIFICATE REQUEST----- MIICnjCCAYYCAQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAxMJbG9j YWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzYPe2EjEsKBY mdfFALKSKkS+Nb2R1gind1ginQrGHfUHMWsjTK9W4qcd3iYsPXmz/6cdSNBBZN1f W3K0xGjC5DbWcqlq5lRPxg1R0BQ5zRojgzQBcOtnFqQPO0XWB+mZqC/iewsvgiOd OgdUlRD3StRujK+yS5RF1GlOqW3yJxTs/dMoNcOU4B6FjlQ7wk0HYsa04Yp8J+Lc UmBbEodbZ5WM8Gq0PxK+XGQX2E2aOxcBD2rmh0Sz92xxG6RY47LWlopyrirghdBI q9juYunfyFZhj54SSTFb16jNLPaXpXTamPdtQPJZqd+XMzfEmQXH9siWA9KmR18k O+gUFXh8BwIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAMjRJ5oHv9n+UjXj0WFE ey8VT32Lykt7tIaieU9MQZ9FGPApchb5IWPKnMImR0OH99JJGAFEg5ibkfh7n5Rb TdZUxddE8h7lhHxd7lZiD0hr7YRVEEsSMe9MIwiBFx9evyBHEj0go8K+B+Ok5ptB 8OIJtPQShvOvMXjrUk0tkPKbWUOwAKWiZhDf3T5lgreag9qh30GsdeITFK0pyII7 NSanOzU3cRgLBfLWTLFY4bfb7Y8t+nu4f+UH4QBU19daqq50JhE1NA98Vf9dIp9w DDBWjPYSL/r5E9oKed3hAomPTmSma8UBkOgyZWF7Zwt5kt7sBsv5EM+6aE2gvrms M5c= -----END CERTIFICATE REQUEST----- luke.madstop.com-bad-public-key.pem000066400000000000000000000005531470345337400435740ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems-----BEGIN CERTIFICATE REQUEST----- MIHVMIGAAgEAMBsxGTAXBgNVBAMMEGx1a2UubWFkc3RvcC5jb20wXDANBgkqhkiG 9w0BAQEFAANLADBIAkEAowXc8bSQDvflUcH6/sddPHh3xPxXWorNyuYbLsQTql44 xk4XlRtx5ghTOIDCkPoezkQy7UUbiDlCTQuCvKF3iwIDAQABoAAwDQYJKoZIhvcN AQELBQADQQCWw/BnnOnuPbfPO28qoNjgZOXV4w6cxfiMW3n5cvQ8N4w8g+IpAjxB VlB5LoyIOWk4S4PFHou5n1r92sYTQfME -----END CERTIFICATE REQUEST----- meow-bad-extension.pem000066400000000000000000000031631470345337400413300ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIEijCCAnICAQAwDzENMAsGA1UEAwwEbWVvdzCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAL23VOzktmj9I5xDcT77Jx6E48bYf/Asd5Z+biTugWLgurO7 2IgS1T+4E25hr0O+PgnOGxt9Tgs6kWdi/lKJjPEciTZ7P+sBo7I25sCDOvSUrdP1 7YMAvu9SFdrotSTo0rseZDhxndJvyk/9f43VwUEDIAHQSxAU/Ovfj/IXQaSCSi3L LgWAYAmdFd4F7GaUYVS4E9MmTc+R5lSjOS95wyF/n/RevGFgKv1aiWc0JPkTxAm4 OCM0zb3ikyhs+pYBamKDApEZVgYYuXn9Eq+XO3KLB+E4oyJUlpd7YSDK+3KsWIH2 oC4TlDgULp69JBgh3WyRHhCgCwqAR3gVgX51eTE7w6Q84QTTG+ejXuRbzZALdZ+q Rd2Dacd3nnmf2MOPhnodoGDd3qD0LcfGAZDYy5o1Q84+uofuTifnlqcPBukogWiQ iq/rGTGyVWXF9138AlJDmRwdOX2kS4VwMjWl47dQX8PWBEHoioWv1XKclKY4omFI +tx0J9/2eMTda6mnqnH5t6lmI4ZgSXwq2goEctPFSNW2NenDDzm5zb7wm73IA3Im jIbkZbWd8fms/KYzuFgfQYRO0+gQNeaW8hgSstJaJ02x+fWOZTDyzIgoamvNfGi+ 1ozXWoGv/HwF4bq8hqZTMW4TTTQ81Ypw3yY1M8pwx46gJ6rP7Z+olC3xr/rnAgMB AAGgNjA0BgkqhkiG9w0BCQ4xJzAlMCMGBjEJCQkJCQQZdGhpc19zaG91bGRfYmVf ZGlzYWxsb3dlZDANBgkqhkiG9w0BAQsFAAOCAgEAtABuOOHLMl5wP7pjLhaQMJ2U EDPGIXP28m/tl6PLQQXrl2o9uJnJA74wwSK7fvxbSQI85KmxXYZr0fk7mmbpeIe0 HLewF3Q6xCHPpIhrSyWzjbu1S/xkqoAaQ6FZtvhHnlNPwFrzkuYO08HgcsmwxEGk vbJ+yZ0EcB1Z3SC0MuWMjPFsMj4GTQOwQTb4sDfTlDlHfGnBCv7m4q/OniSCmuTE 8yWDnlvbb9bph660TmcPNaGo2aTWYf5JYZTf+ScrXItMWFyrNJuPqPAxZLfsX0vN 5j16ng4OUyDbkYZuOYdRY9sROn8Weg1nUKwXcGWcsw727dMbzrGa6Wv0QJ5tOi58 nIXbZTgm5GxBvXRdqrRW0ofJjy+KV2XPxAPewJHTik/SbT5ccgD4ljLgzTgJqXrf F71q2awVF0HETq7UgdeJJZ3wne2uMwwhL8m2cLAoqhlOKDz4/lPMlQSnyuezoglR +P/n2wsutYKLr6HKIvFP7UKZRA9oigkQWcMsRB5jwMk0vyZQoyoGkvacCPqdZifd kf6OMe6rzndr3+/Nwwgx3hJk8R/daW3Mic4gzTcgKJ2JGuVLekMReFlM/g3KvCrX ma24qPEAcw5/ryj7GTjRsrqmL3gqkHgdW2g1y2L99EOaldfu56f/JFZw+aOOC/BH CdXdbI2Ff7usKKxnqsc= -----END CERTIFICATE REQUEST----- revoked-agent-csr.pem000066400000000000000000000017351470345337400411460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/pems-----BEGIN CERTIFICATE REQUEST----- MIICojCCAYoCAQAwXTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEWMBQGA1UEAxMNcmV2 b2tlZC1hZ2VudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOlP8Dte xhXBSDSOfacWmk0B9SDQc8zNK9kBTva7qOuUyrTFDhnzl2d8XSgTZqF8T20pgb4c 6UlANPVPJ/Ui/I9wXtjOzFl2ykt1PLXmXWaUgT3G1nNSME3Z9siP7gZJT4M1Sy67 9NXYSUKqfL5Yz4dWJgSf476eTBaDCAEE2AbYorXPNBTThq2rg8PrYowCSCKmKjk1 g6MYwogq3wVxnYmKTzZotjp1JSKmQ9IgmelylOSal3uVMswIo++R6EGtwWpsNOfb y+BCrVhV1+acuPZhzKbEWALHYx8wm2NSzT9DWKFAP2YDV77EJs1qfSIIjt0j6We7 1RDtp/ICmJlbgVUCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQCVd9Zi1bZ4MOPk OVYTTA/xIMjnx19oGsZHqxKixz8rLJcghxnfxJY3gFGX/FiL3QMmPIGapj157tDH nsp7yeHo9L8vwx16D/aKn8DviELAQd1iYgMNc+Fo+ClsKuP6Nafism+boeduu9sR CYCXLt9S/NOMI5compeYtCFDnl7xhSW1vS90O5dzVQR96sSqOfgxgxPKpCCLz5wS qNp4t4+mAVuMyDFn3XlMnnXpUerp8PVVS4CstzqYdM9f0nUFoYUtyyHLhwskxTRr 74DxQ5SNuhm7WMPyQolLqMh7iDUwPQZEkFGzSNjepZB2z16Fu/oy/KjcCiXscmBl TKg95EUp -----END CERTIFICATE REQUEST----- update_crls/000077500000000000000000000000001470345337400364565ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_testca_crl.pem000066400000000000000000000022521470345337400404050ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAxFw0yMTA1MTMxNzEwMjlaFw0yNjA1MTMxNzEwMjlaoC8wLTAfBgNVHSME GDAWgBQl9rvh0XacxLAt5gBaLUhtGxByWjAKBgNVHRQEAwIBADANBgkqhkiG9w0B AQsFAAOCAQEALkpYMTwasy0PT6IROnlfIihY1oRwUS+yz/9E7Gh85nHe2oXkRO7g 1h4+DSBEOGuPXqp69Fr2xkSSK3vEx3hgOl3Zz1d3BkRkGeR67cTWzTZoCY0II4WN /Tk3SJ/5uxzOsIiwrG+WPufdL1HdJEJ0amq2Jn4Ri7lnuzY2UD7+FNleGDeK6qxg 1XqKYBz4o+0+wh4/HQKfc5qdnANZyzyLFmtwaxY1IXEsYcwke+6GX+sdL+x+4bBM NlLZh6ApQ9wcIDbuHXV9SsgV+FR1DzpDqLOiu8ur4qalgna9sv984VHPbhqC7Mcz 4TTTYwLvjGZQgobxv+FVtWPy3xQULooqOA== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCQ hCaMUIuL4R25bXhpI9oNBAMvi96bCGDwtphRmk2Vm1QAwe9lTK4Ebf3tvPIMi7hz 5cSntni1855BBc7qNCJXs1UsQtCfnBW7LKpSFLLQvTkzXJN3xo+hc1y42j2Pa85Y ZDuu61vx28M/AhCe/qGyYMRk66wwwuU9ACxn8sOzvfhG7Fn3c4+xlNws+Mp6CrvD 9+b/GONkqogDSPie2FM4Rbbc7e3luFhzD0HhJ7MZKkaO5vaaeTaUvH+UQYxlumS/ Qxtjj4KdaWVBr+++b0EqLFC1oFL895j8UWYQ7Orkt3Wlm+x/b30WsuNmRJKqjLYm 4YCAH34bvjD7Tgre9fBp -----END X509 CRL----- ca_crt.pem000066400000000000000000000043161470345337400404200ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN CERTIFICATE----- MIIDGzCCAgOgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 IENBMB4XDTIxMDUxMjE3MTAyOVoXDTI2MDUxMzE3MTAyOVowHDEaMBgGA1UEAwwR SW50ZXJtZWRpYXRlIENBIDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQC/oc9oNhOuqHm4gCrPJLRbEjVdel0LUtgyd4ECCO2Qj7Li1xdN0y0GJkeJQvL1 LdFeLu/QD73wBzYQhZMyN81crtNBiTcjtyRY+C60luhRJP+8CdppeVn400fiqmVK TOEk0Q3mb6jwyBZPgS4K46bZb1YX+HBcp0I5CRHT0epEXjkAOLl+Bym8xpQ1dhw7 AxQhrSG04QJeJZvUHSpyy5bH25HsAG3jdjdT2y3LiKBAyMptH0AHkXhDIHvOZ8Ry rPQsxAnUKOq5UcNPY+JdvhsOBVDmbIVmvkkAb8vy0+aK96U+zDJFnoYMs9K+jlKK t0SnJw37WAaTwGYeOd/mdeT3AgMBAAGjcjBwMC4GA1UdIwQnMCWhIKQeMBwxGjAY BgNVBAMMEUludGVybWVkaWF0ZSBDQSAxggEBMB0GA1UdDgQWBBQl9rvh0XacxLAt 5gBaLUhtGxByWjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkq hkiG9w0BAQsFAAOCAQEAQk7Z8sC6sSrb0yJGZ7ij77iUqLujvZOUSGZMdNBUZu34 zzGJ6+70Tro3Yvw6Q7PlEhmvF8vpbOxFpZL6Rh34+O41c8FOIgwcOjABvjS61jkG hJagK38J+AdKBE7lVGJudttW6JrCHsPncHMia6iiTQz6QcHjDrE2FJ3L1Cy8zm0m U8zo8hAGqQlEuAacMff606JtBcLSVpgYTfp5BixmkpmK56rBc5vPtE2N9tdJci5U +GEmvBeQaO28JPqSKaBQ4rEaudBETl1E7mQy7TklFpeXqPxSuu38m8iMy55aunYN dZzhmfmk4DbT8TDduHO5P8xrfuhdBpkri7KWyCaU0g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v dCBDQTAeFw0yMTA1MTIxNzEwMjdaFw0yNjA1MTMxNzEwMjdaMBIxEDAOBgNVBAMM B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVnTfyQPtV f2moAdKhS7e7PI9vabK3xR39SEz0LVrHfF4kgy61iNNjkghbuDgHgDZnIPsiMBE7 HpGutRpp7AnkDX+uSpY9VOY369zGLxl/6YenNLMfZ69Q7aHCPIpWkoC+mMzU2j2n PR0FwZf633n7gB4pwlplY5Z4fhIwKGSYqlmFVC6h/f1DYQ0jfYsdVYIMct5NShfo phUvrzVSB6SPHU5Q6Z6bGGofy93ptr89cs6r2WiwXsN9tcshFJsHAzj3wpLVzT6K YZthi3K3myYPL3B8Kw9dQ+ShtHU3NiH413s1YbPfgvtCYGNc07EGfYA66nZuncJh mdtkcEzET7ibAgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv b3QgQ0GCAgKaMB0GA1UdDgQWBBSAHOzSNiXrK3J8u8ofAdn8whLXuzAPBgNVHRMB Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAc4KU gHhl2394zOrW3/rPNbQbjb3aKTvl5wK2E9rQFlCGe7X9NuMCdKAmThkBf3+i3625 ddaJavO2VJc0JPb2mxhPwEbx2O9wa9eTZ8uhhmEE56B8h1CDafklbC3KEvfl2W0h 9HskkQ6yJrJ48kJgaZu8T3H0fQq4quhI1ACzEfYBOTvhlm0Se2JHdHJF1m5YVlgI 5UbuitqL6911+khJ4veFWwkjRjKzPJQZoqoc2bKJHx2p2ufod2FXGc+trNe5AkTB f2uyNSkPEkfz2SaNYVQA+bisgTfNuNYXOVRW2Gc9K4XKqH0p6u1QgfUOa44YTtaA TVB93iVXQ7UgTbSXLg== -----END CERTIFICATE----- chain_with_new_root.pem000066400000000000000000000022521470345337400432130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAxFw0yMTA1MTMxNzEwMjlaFw0yNjA1MTMxNzEwMjlaoC8wLTAfBgNVHSME GDAWgBQl9rvh0XacxLAt5gBaLUhtGxByWjAKBgNVHRQEAwIBADANBgkqhkiG9w0B AQsFAAOCAQEALkpYMTwasy0PT6IROnlfIihY1oRwUS+yz/9E7Gh85nHe2oXkRO7g 1h4+DSBEOGuPXqp69Fr2xkSSK3vEx3hgOl3Zz1d3BkRkGeR67cTWzTZoCY0II4WN /Tk3SJ/5uxzOsIiwrG+WPufdL1HdJEJ0amq2Jn4Ri7lnuzY2UD7+FNleGDeK6qxg 1XqKYBz4o+0+wh4/HQKfc5qdnANZyzyLFmtwaxY1IXEsYcwke+6GX+sdL+x+4bBM NlLZh6ApQ9wcIDbuHXV9SsgV+FR1DzpDqLOiu8ur4qalgna9sv984VHPbhqC7Mcz 4TTTYwLvjGZQgobxv+FVtWPy3xQULooqOA== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAn j87vWjd9qr9BZq2rf92Ku/owQlAJTHwIPAKmmUyzMF+Aw0P2nlF7FPDiOaXXGm9x KWwstCaefp4jbru+pD5cH/UFSCyLBuUlfzqtMvF4SL7/CjGZa4W3WW4a+fqlv/HI U8Wxjqa00LBV77rqJm54z2QUlqgCPD/7r2Pqy5rrfrZTGGy58727whtSsV5sAWOw kxzRogsSm23Uh4//lmEx0BYJYTaz+HdWaEckpJU1S3DfBBrh5Rv2AG/OjsRfUvgC tB0SGdKL0EM8KG4GxbeXTvq8HuTKUp2HaWvGWpdojyxqwwiAtNaOHt76qpBkRe3f igWihATMaKzytX4xXk1C -----END X509 CRL----- delta_crl.pem000066400000000000000000000011451470345337400411130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBmzCBhAIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290IENBFw0y MTA1MTMxNzEwNDBaFw0yNjA1MTMxNzEwNDBaoD4wPDAfBgNVHSMEGDAWgBSAHOzS NiXrK3J8u8ofAdn8whLXuzAKBgNVHRQEAwIBATANBgNVHRsBAf8EAwIBADANBgkq hkiG9w0BAQsFAAOCAQEAWsS4GUUVQF0Hrv6HxKtjzjjmcFWGyLQN8R2/lOGlxoTc loHFNEV2C3GXwlWmG3xfHtpF92XvrHY7AgDNKZZG9Ss/AhrFFqYx3LM9d5hxsv7v bm30tiFIBwd+SN+s1Dnyql4WYo1wHW+PqFuImZGo2OoFW+LEuBHusdTm4fkmro/v hA4SJpFgipJq1TWXPea9yTbYaFQO5xPL1Ec6+jYWT0G5u7iLPhEaBCPT1u4sjgnq xqHoeSl+eNFFBCrvtRnjU9SOlNVT+sDYPcG7dl/5gVmr/OugRPSoHmWLElt8fK77 RQhIlfGuqokb+PSUy8pduiUrW1vHoHm8MIsdVDCbRQ== -----END X509 CRL----- missing_auth_id_crl.pem000066400000000000000000000020231470345337400431640ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIC2TCBwgIBATANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJVUzELMAkGA1UE CBMCT1IxETAPBgNVBAcTCFBvcnRsYW5kMQ8wDQYDVQQKEwZQdXBwZXQxDDAKBgNV BAsTA0VuZzEPMA0GA1UEAxMGbWFnZ2llMSAwHgYJKoZIhvcNAQkBFhFtYWdnaWVA cHVwcGV0LmNvbRcNMjExMDA3MDAwNjA3WhcNMjExMTA2MDAwNjA3WqAPMA0wCwYD VR0UBAQCAhAFMA0GCSqGSIb3DQEBCwUAA4ICAQAJ5isxYQ07FVr01zPthFqIqCBV Z2+hlWrKZ63VeXdds6nfhCwMc+8EfDnxSj/IPDEURhCWZppyUMGiNU166xK0KjNL /Wp/KjGMgdIuuI1zNKyrDiK1S+nC1cf8yOTSw8U4lvBKGBepTLRblmZBis5FiTxm wpJaUBA3xJKEXAvb+XuFv14z1HgVsEFy8TjJsZ6F1q5ZXroMG3hiwO3nLdX7BhQ8 JZjTL8i5ktrZjk729PfkjhwQPxUTcxOyibctw6Uvzn7vou50Bk0IvSWC6PJW6v3/ gmJUj7hjzjbnUiAM1lg1OeudNmkWyVBzYcBUH9dWagzLzbMbho2YeS8Ptzs+R6lL H9pD2FO4DL/FQOE6cMqml/LWZjWjsOcVKQle+tzuTHj9t5VcSugiJVvty/H73aCP besumbf8Bmm+4G9+KbxvbRW2AB+iZFfL849bk/SEjPTM1/8Ru/iIHoUAeTFP5fX8 w9/Mi9vgUjx5NPgkSgWVC6oBOL2tQpeLWDh3C16GTqQ96lKt8GLqhFmDANF5Ccjz g43AC60xn03BZMJWO/yXFp0JyOalrPOIZr2wHXxfA7QAyYwelSbTYmVTY5YzPSaj E5n809YjDGQnVAo8ha/fK5FdF6wohwKu3tAbkI0rXZiCdyT6/ea3V35tJw2gavXF +LlG2FUCv5RswKmYcA== -----END X509 CRL-----multiple_new_root_crls.pem000066400000000000000000000022321470345337400437520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAn j87vWjd9qr9BZq2rf92Ku/owQlAJTHwIPAKmmUyzMF+Aw0P2nlF7FPDiOaXXGm9x KWwstCaefp4jbru+pD5cH/UFSCyLBuUlfzqtMvF4SL7/CjGZa4W3WW4a+fqlv/HI U8Wxjqa00LBV77rqJm54z2QUlqgCPD/7r2Pqy5rrfrZTGGy58727whtSsV5sAWOw kxzRogsSm23Uh4//lmEx0BYJYTaz+HdWaEckpJU1S3DfBBrh5Rv2AG/OjsRfUvgC tB0SGdKL0EM8KG4GxbeXTvq8HuTKUp2HaWvGWpdojyxqwwiAtNaOHt76qpBkRe3f igWihATMaKzytX4xXk1C -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEKMA0GCSqGSIb3DQEBCwUAA4IBAQBH oMkgd9OWEENL65+C/ZOOIMCuNQp8yakvHr37vWj4v2rs0P4GlEKECghaf67WIpBS 3IB20IZpvFbETg79HcIUkrO02dTy2OUPdLpzEfSCvkxMl2/IofSyirGQycQcH+tg LRGlsDFQJFPFNs6/rr56t5ztYx/OaareJkHmvhwSd5w4O4Rimzxjx/UVQfnJ3Tju 1D7he3ueC0JbbWg7dA74d02akiXLLQVwqsDLgW3R1+RTyxPjn9LqrvlOfhYihD/3 NcWjMEU7+T3XN21Q3hhsBCipuBBQJdS5TWlVEFRX44IM6ykEsJFvLZbVZVJPYTej WkeaCQRskegBikdaMipH -----END X509 CRL----- multiple_newest_root_crls.pem000066400000000000000000000022321470345337400444660ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEKMA0GCSqGSIb3DQEBCwUAA4IBAQBH oMkgd9OWEENL65+C/ZOOIMCuNQp8yakvHr37vWj4v2rs0P4GlEKECghaf67WIpBS 3IB20IZpvFbETg79HcIUkrO02dTy2OUPdLpzEfSCvkxMl2/IofSyirGQycQcH+tg LRGlsDFQJFPFNs6/rr56t5ztYx/OaareJkHmvhwSd5w4O4Rimzxjx/UVQfnJ3Tju 1D7he3ueC0JbbWg7dA74d02akiXLLQVwqsDLgW3R1+RTyxPjn9LqrvlOfhYihD/3 NcWjMEU7+T3XN21Q3hhsBCipuBBQJdS5TWlVEFRX44IM6ykEsJFvLZbVZVJPYTej WkeaCQRskegBikdaMipH -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIx MDUxMzE3MTAzMFoXDTI2MDUxMzE3MTAzMFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEKMA0GCSqGSIb3DQEBCwUAA4IBAQA/ xc3Wlh4dlg1ICxynOsLSisEzDTQfhiT0FjnKpE7Cz3ZcR8VrKuEs+jvixSanIooZ 8e4+NnLXIX9xq1Pzz5wI0YBCmVkUpJGyNOYGjpY5R1VJzVtB1YRaJRf3lyCYz1jd fnv6Glidw5zHykoYHwHBbU0A2pWX14+LvQKC3aNQ5m0UGzg6QCSa83oiVVI2Gftf jwIhHQHHyrcKo2nTX3tBo2jYuD+cqxVndbBPO5B//XQOmF+p6nTygOR65P0yMrV7 gXzOpuPZEWx4lhHEmw+xP5w5b74EQ02Opy5HV1n0G3ZgMFnfJP5VHDG0a4fXhuNe N4L9YpQHT8XbLdm12ZcW -----END X509 CRL----- new_crls_and_unrelated_crls.pem000066400000000000000000000045241470345337400447120ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAxFw0yMTA1MTMxNzEwMjlaFw0yNjA1MTMxNzEwMjlaoC8wLTAfBgNVHSME GDAWgBQl9rvh0XacxLAt5gBaLUhtGxByWjAKBgNVHRQEAwIBCjANBgkqhkiG9w0B AQsFAAOCAQEAg7e0bQPw19AODs01lhP14Vv3z5Q3L7VwxdY1ER/JdAHZIYqJd+01 IGlOJcaSb/KLAUKgH6Uanyx0IhtFd2H49qKed0fU6oeInRvCRHMFtCHZ0VaGZajA eBHP98hkRPmkSE58WdwQXEyLvENj7xJK9Gq6OnzN9T7ad6laTQJ6DD3IrFOMb0fb KwgTt4T2XT9CKx3G4hdMUlOTx2+HJyXzicw0/KLjkhsB3BCLrGl8K/bgbJwh5WDS 2fPR6FtS2U7jNVL4BKP8yvGEkGwJahrQ95XN7/q684HA3KLz+8X9PDizoLVBjvt0 d6jmNvpGfS8MahAg50t/TrsvpeQHZhhotg== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEKMA0GCSqGSIb3DQEBCwUAA4IBAQBH oMkgd9OWEENL65+C/ZOOIMCuNQp8yakvHr37vWj4v2rs0P4GlEKECghaf67WIpBS 3IB20IZpvFbETg79HcIUkrO02dTy2OUPdLpzEfSCvkxMl2/IofSyirGQycQcH+tg LRGlsDFQJFPFNs6/rr56t5ztYx/OaareJkHmvhwSd5w4O4Rimzxjx/UVQfnJ3Tju 1D7he3ueC0JbbWg7dA74d02akiXLLQVwqsDLgW3R1+RTyxPjn9LqrvlOfhYihD/3 NcWjMEU7+T3XN21Q3hhsBCipuBBQJdS5TWlVEFRX44IM6ykEsJFvLZbVZVJPYTej WkeaCQRskegBikdaMipH -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAxFw0yMTA1MTMxNzEwNDBaFw0yNjA1MTMxNzEwNDBaoC8wLTAfBgNVHSME GDAWgBRns71gvIKR3OhvGHDrvaIxTILvPDAKBgNVHRQEAwIBADANBgkqhkiG9w0B AQsFAAOCAQEAk/TfbEefw4OvzCrIQ3FGZs0FCQqDj26EzK/btP0CJV3vib1jLqpb zcc7u83KJA2rRaq/jjW+S0E/EqMDT9LPtxn0xBCwYXln5MSz7bY9jtMCcfbus5I2 IFjzcFNAGeXK2wvaBZoju3Xlpa1HQPG15nXC3XJmijxaKgB84lj12lhHtN9mOJjw OeEhn7mwPnOGWmYo5t/NcvMfXYzXWVQoum+mB8w9m/v0AUZCZjoUAIhAR41azIjr 2JF6cnpMEuB7SlePSIWmkz4FWxOw/FgcAapmqod10NWVfuHH/+DsURm2b2Wv24rI 4L1preXklzKJC7np+fxkfzCbWbJDTmXCQw== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAzMVoXDTI2MDUxMzE3MTAzMVqgLzAtMB8GA1UdIwQYMBaAFEOTQQAQ bB17E25bHoFIsCa8BiKmMAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQAq dibNbIfkGC8PUJr3kGYhQ74QpOQXLAEdZ1MRgBJBSwQas6Rp8s4RNZ8UrLc77Nss TQlR0h6NWZU7x/POCDd2hNEZmNoxnSPZm3qO0khqBJ1ARhzdOP2i9jEQ8Ho4Lb7B lHb76jwrAn4+whd4H3YsXcc1dpS5d/k1/3E/Xjbc0UZ9knetg8sTvphbOKjeXbiB zKSb3yUYapEiVLJM5Se89MfP/WMrSrLTnl1M8pAjseZmICB/KyRyOCpcbT6BYMwa VvK2BtTQlUuzrRi+HsC89G7fv5KTzzgikE/c1Mz0UR76uEe3ZChoF3xvQO9viKz+ cNnP6F6S2AImrT/itJ9e -----END X509 CRL----- new_crls_for_multiple_certs.pem000066400000000000000000000022521470345337400447570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAxFw0yMTA1MTMxNzEwMjlaFw0yNjA1MTMxNzEwMjlaoC8wLTAfBgNVHSME GDAWgBQl9rvh0XacxLAt5gBaLUhtGxByWjAKBgNVHRQEAwIBATANBgkqhkiG9w0B AQsFAAOCAQEAdZ8mvdidEKuUg8RupAcq9AS+K2mgiifVkuhzSwALLvTr+rgHqqiX veFPl+vKUWww59OY8A5kQh0NFlBxJ2H3kzii/iiiZQwtD62v6iQ+e8uo4rOGWKoc OFkDJG12z2E3fRCfmDIgskD4SL0+75L0gKIe9fXtIQUACntP1CXmYL+JJJjeaIPn AwoxXvJ7vrJiWvvsznwjgdWMxRCDGUwsZCcsuj7M4WWvUlMVjP6pJSWH2URC3bEh POqg2fTbY1XBs04DhtNB1NEQTSw4YVZuJSQ/bhazfK7SEZ+Dfeuv8h3dqFFGosoJ N3tWuXeSn43b48f+812Qy46CV3HINXrg8g== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAn j87vWjd9qr9BZq2rf92Ku/owQlAJTHwIPAKmmUyzMF+Aw0P2nlF7FPDiOaXXGm9x KWwstCaefp4jbru+pD5cH/UFSCyLBuUlfzqtMvF4SL7/CjGZa4W3WW4a+fqlv/HI U8Wxjqa00LBV77rqJm54z2QUlqgCPD/7r2Pqy5rrfrZTGGy58727whtSsV5sAWOw kxzRogsSm23Uh4//lmEx0BYJYTaz+HdWaEckpJU1S3DfBBrh5Rv2AG/OjsRfUvgC tB0SGdKL0EM8KG4GxbeXTvq8HuTKUp2HaWvGWpdojyxqwwiAtNaOHt76qpBkRe3f igWihATMaKzytX4xXk1C -----END X509 CRL----- new_root_crl.pem000066400000000000000000000011151470345337400416530ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAn j87vWjd9qr9BZq2rf92Ku/owQlAJTHwIPAKmmUyzMF+Aw0P2nlF7FPDiOaXXGm9x KWwstCaefp4jbru+pD5cH/UFSCyLBuUlfzqtMvF4SL7/CjGZa4W3WW4a+fqlv/HI U8Wxjqa00LBV77rqJm54z2QUlqgCPD/7r2Pqy5rrfrZTGGy58727whtSsV5sAWOw kxzRogsSm23Uh4//lmEx0BYJYTaz+HdWaEckpJU1S3DfBBrh5Rv2AG/OjsRfUvgC tB0SGdKL0EM8KG4GxbeXTvq8HuTKUp2HaWvGWpdojyxqwwiAtNaOHt76qpBkRe3f igWihATMaKzytX4xXk1C -----END X509 CRL----- old_root_crl.pem000066400000000000000000000011151470345337400416400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCQ hCaMUIuL4R25bXhpI9oNBAMvi96bCGDwtphRmk2Vm1QAwe9lTK4Ebf3tvPIMi7hz 5cSntni1855BBc7qNCJXs1UsQtCfnBW7LKpSFLLQvTkzXJN3xo+hc1y42j2Pa85Y ZDuu61vx28M/AhCe/qGyYMRk66wwwuU9ACxn8sOzvfhG7Fn3c4+xlNws+Mp6CrvD 9+b/GONkqogDSPie2FM4Rbbc7e3luFhzD0HhJ7MZKkaO5vaaeTaUvH+UQYxlumS/ Qxtjj4KdaWVBr+++b0EqLFC1oFL895j8UWYQ7Orkt3Wlm+x/b30WsuNmRJKqjLYm 4YCAH34bvjD7Tgre9fBp -----END X509 CRL----- three_cert_chain.pem000066400000000000000000000065111470345337400424520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN CERTIFICATE----- MIIDJTCCAg2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFJbnRl cm1lZGlhdGUgQ0EgMjAeFw0yMTA1MTkxODIzMjNaFw0yNjA1MjAxODIzMjNaMBwx GjAYBgNVBAMMEUludGVybWVkaWF0ZSBDQSAzMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAwRQ5Po03HUnPjguSBkFp9z2BYY65n76ddJOrUDix7DDQUJEA ReKM1AdiFLPSj6hSo5xmYgpSzepHVhYrRT711x54xXQ2jkzV5JtwEpmxJEASJgLo GLUA2W2s2aGYqdlTl/gax8mg8nq0oTbPz5IKQ/m7sp/8vxyMyx/PzM5Qh5I13DZe zBkukHlKrJKD5C8Nnsym2svRYTT0jpPXY3Q8Y3HJ/B5Bp53QwXCVh03D8urEskPL 0w2FePtpxpE/i9Ry0AnJEoOqTUBzgYukFQLI2AFN//yq0CqlR5QivHGqxPnr8Q/c Oo1A2sUbHR0OH26JsI1Z1ow4I2AGDxzIPY3oSwIDAQABo3IwcDAuBgNVHSMEJzAl oSCkHjAcMRowGAYDVQQDDBFJbnRlcm1lZGlhdGUgQ0EgM4IBAzAdBgNVHQ4EFgQU ojKdc3QTwvskQepS9arnvlGoxjgwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAI+Vy6+ujYjrQ/PYEdHDJz2FYipP9wDM /DI3gwxFiZhKPMU7WvdVpZc1YWA4wMfmgDwzFC8ZQxQ1oAsZPqtCYAdTNkJ9GIYh NXqMe+Szo8b4uBPOUAXomg6Fy/rDuxP7BNsxlKImqQismrf70vSu4auRBge1I2lA hNgzPcsOIR3Pcge9kSy3ktODSDRgRFCu++1B8N64C9Z0lmQYWi7NJJy79+Euwwz0 ivuC8YmgiqYUxLQxiMsRp7xLImWUEvkVZquxr16o2VpvfqCHAQ3Nn9T4ZRg6rbS4 aFREyKBFBFPy3fIAqtLugReFCZbae8hHznNy9uAqaOMvVkIzxUurdt8= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDGzCCAgOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 IENBMB4XDTIxMDUxOTE4MjMyMloXDTI2MDUyMDE4MjMyMlowHDEaMBgGA1UEAwwR SW50ZXJtZWRpYXRlIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQCUXf+iX5Ye6fcXPdKEHqc1TyDhnGV9kdKylvLzF7Z+mtdX8a66Vgk1egPB0HvW ZjfknbKU83ITxCUxE+aq+xKfNX/K6r45bO7XoC2xkoSYLG/CQ0YVyyzfb/DzSLDC beWbFoyApy66Ant2KQPK2V0cwmQQtsHtYgfkeO63Nu9YiomTQy2SmEYCxEATJLyW MCZ4eVX1cikF9pcavg7prWLDt2fVKztR+XwU4hlKu3C5Rv+MNRcgfUgCcLFzOwFT FWYYS/WeQKjE383HHdNWvgT+SfHHpifl2wbsxrYui4i98vijaDke6071Tj617Lsc 0G3otuRTsYWScFbyIE0NWFdNAgMBAAGjcjBwMC4GA1UdIwQnMCWhIKQeMBwxGjAY BgNVBAMMEUludGVybWVkaWF0ZSBDQSAyggECMB0GA1UdDgQWBBQVCo5LJCgawfs9 Cov+hnOA1uhcOTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkq hkiG9w0BAQsFAAOCAQEAR1Inm1dpKRf3FSTiojEphNNOTYWmZRxRxeBAQhBRqLwT x46qK+C05imRGIpirq3ft+ZzGtfzM5LZQC0tnO8K7yWUiFheQdli3NIVLPlyvr00 eKljUeyyNWuyoiKTQLfV9NBRaS+FP3Xo51lpqTLboiLibTEu5XonpdodsbMCQ6GR k2im2E8UypdVB4uQgk2AWYkvlM4Nol9cwFPBQQQw2voD+/z6s8tZwjI6Er1jw3bt VDubsPORHrli8V5pQdbavQ0kbaRlCnh9GbVkzwO8QHGLb4YuOqTjLQeuTkuTpX35 mZOkOBOwyYwl5saTpj+OekI/pdwezTFajFsVtisFwQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDBzCCAe+gAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 IENBMB4XDTIxMDUxOTE4MjMyMVoXDTI2MDUyMDE4MjMyMVowEjEQMA4GA1UEAwwH Um9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJQDnsu0xzTy ChlPUQlHt6wFqm3gptqVZKi9Htupq3SOguakK7a+2coJ88zOcmcGgJspk9IhhHDx +xrMnPEhm+CqYFs9m45chcGgq2SE6lKw12b5lq3kG782Hc1i3cKembVdDwUHU40q x1ysjSVO/45maLVUMjog0N3Y6iuuOIS2LclTB5J/Iei6ziF5SBwWA8Xdn6my/cDZ 3OyZQKFteI3YiEFxGjAdRdRn+7eqyeKzT+fXoXFEwT3OTRLHlzZuvN3FZKZmusWj gvuXeuYIqjt99Pd0BQ98/6VqzcKq40wRVU9Z4GY7yC9Jb1C3o1JTSmRIeCILWyoX i2pPExSHMCUCAwEAAaNoMGYwJAYDVR0jBB0wG6EWpBQwEjEQMA4GA1UEAwwHUm9v dCBDQYIBATAdBgNVHQ4EFgQUa3M8zKmmoRJPOe0odqodV62LeOkwDwYDVR0TAQH/ BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAB+ampdH cEjh7ovEq757pgb1RgDz/AHhzAMqh4fLUVw7xAAHDqymlToxbjatPRN0Rjug8R6Z Ef8o6ZjttMGdYgokgVS104knNzzYrIpE+Bf9F+mEf+PUZKWmp3VZulf7PC4Gi2QO rEPPSRD8ucFbgCrBVvLbi9FMQb3MtSe99EPEYLA4vdNr2jEGQi1ZRBSOWTt+ZIUS kG2Jv/ldpZDs6KimQZ9UvTJPszPJ0irIfm9dfpc8Nfl8f3MapN7MMYKq6deW0Kvs pdENK+OjrPBH7wrEm0Eo5D9BEtskjP7wmI7IoIUze+g6xxB+/7QtESOAK+7fZxpT fWcYXSYDSJP0NcA= -----END CERTIFICATE----- three_crl.pem000066400000000000000000000034071470345337400411340ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAzFw0yMTA1MjAxODIzMjNaFw0yNjA1MjAxODIzMjNaoC8wLTAfBgNVHSME GDAWgBSiMp1zdBPC+yRB6lL1que+UajGODAKBgNVHRQEAwIBADANBgkqhkiG9w0B AQsFAAOCAQEASYm9rYo0pc02DMsPZM2/X9Kyz0mljswkAaaddsXaejXfxkooMIUr ikwfXvWHxzvnjBFsbl6ua6Vjv8OrEID5QVcvLPqbodlzMyHC6pP+hDjCdxvpPTpo hPGIXhG9ZSafq1Kugn9dFi1NbWvoCqyyo7W1T9aWXcErK/9Ff7Q+bmbR4I3Vl/r5 JyoPYAwm3vMBGP4IPhJMJ+iV0syp9yj0OYL33LW3IM1R+V86sZGt2kO2Sh9hV/ak kCxqYFL7VWw5LhyjW0MFiSwkjTNxQEbs5kZNKZ6rzP08TsHpBrtKdiV80O/bBqOy Q5NVAPZ3856bbJi0xAIWeqKSTp4BZTOdrw== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAyFw0yMTA1MjAxODIzMjJaFw0yNjA1MjAxODIzMjJaoC8wLTAfBgNVHSME GDAWgBQVCo5LJCgawfs9Cov+hnOA1uhcOTAKBgNVHRQEAwIBADANBgkqhkiG9w0B AQsFAAOCAQEAcB3ZZa7OsvtRrfkiGo/4MI7oq+bUZpqfqG0Vv/FnYVEbDS+77kky PKeFuJQ2QYpODgYoUNiM9pSuCNpp1+F3rkNI8nvtUna5iLHt8oRH7ISImPqPp0zL mws3bbuSnsgK4+syprY+TYuB1dEN1HezHdb+NdsO1Ne0CqHwRVWJrOt/Nxrh2qiF mmrXP9S0r/iADCimJqYIANRDwDKGTBrocFam8biA32iIaX0YsHXRi3a4+vLMtU1g faUg1YAstd9qf1d4SQfhpQEFuRej+JHr5afY+9+dLJrKhFo++QlCjrPAECzCywcx uy8IbfoBJJDKnHju0zkziNhgC1QH8GrYsA== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIx MDUyMDE4MjMyMVoXDTI2MDUyMDE4MjMyMVqgLzAtMB8GA1UdIwQYMBaAFGtzPMyp pqESTzntKHaqHVeti3jpMAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQAw I7SGWEeyuf4wiBC9Yj/L/unOJEb6Mi4scbJyFVsbKP9bkfrQJJlAgrxTURQS4VXG Evsy3CmKmFkvn0SSvh+3JKFbGggJ+e/E0tN2ZbkXi0JM/2UfaB5L4CF5NksED07F MkDmmxXGvrJs65m3QJnGCnHrK/94gj9kdJma9YSBfkq3bkAQFPAhalfDhIB+T69h 3oIG4LmlsjN5ss5wK1mTA+nWdV6IneQiq0GQ9sfqumRjCU5fcHiODxkMabh/rGWQ ra2Nr6d/TzLeAq8ooRgB6sOsKmu/OJqyFgJE5Iorxq3EhrzXwyenqKATHAd+Quc3 VtMLDBrO+Z0kDLtHQnJF -----END X509 CRL----- three_newer_crl_chain.pem000066400000000000000000000034071470345337400434760ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAzFw0yMTA1MjAxODIzMjNaFw0yNjA1MjAxODIzMjNaoC8wLTAfBgNVHSME GDAWgBSiMp1zdBPC+yRB6lL1que+UajGODAKBgNVHRQEAwIBATANBgkqhkiG9w0B AQsFAAOCAQEAQARPaLwjX3KOnBcrAHvWm0xAUbYqI5mXMS19SaU9UDJFYKph7rR7 /tRV1B8ULKdySlReyVp9U4tCsatpepcFXmEjmD6hMB3s6QcxYylZT06uEInVC9zt s0yq5x1Euf4sYMmD8pYAygpvvgF65R6WOPfLmJlc1U9xOqfLwmLGg+2LB5UyBKqN Z24crLfh6o96efgfk7PKoZVftqZe+L5hzWkmytpphFzx6taJz0I7PWhsRJThuv4R G+bXLfpI6wF4xkJvmbD4I9D35ofMlPbQ5IKqIxZoPFEqSDIQCGFfNEOd7plTvP1X 5ihdHnVScXzYEePTiX7LqEGy0SDR09IhXg== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAyFw0yMTA1MjAxODIzMjJaFw0yNjA1MjAxODIzMjJaoC8wLTAfBgNVHSME GDAWgBQVCo5LJCgawfs9Cov+hnOA1uhcOTAKBgNVHRQEAwIBATANBgkqhkiG9w0B AQsFAAOCAQEAcIFc56QbTG80o0TFoMQ9HcsoeolN3Lj/G+FVMFA+lS+83HLgPnpz /DY+jBptVuvhIbPYJ7TJ5MlQ1QtXWVMrLHHZiL9f3BnfEdIuFSXPgWDAu+xpcCe5 6Gnr4EByKvS4jYpHnHD+vq9HlA4KOH6PELS8RJ+3VBboq/ecSYAQESLzP3XUwFWx xwbYDFx+xVAKgoJFirlhgMgQ0Lj0CZcakkW6qsP7Eawdn15Z87tuKBP9IycSpKO+ TkIfv7KOg9tFmLoDVedjG6+1Lzjl/Fl3ICOPTYkrK6oiyrJHBAQTM5PN1uH+9Uzq GQ+vDlFDjsxaMf+Lzoqdzfmz4K3JIGlNyA== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIx MDUyMDE4MjMyMVoXDTI2MDUyMDE4MjMyMVqgLzAtMB8GA1UdIwQYMBaAFGtzPMyp pqESTzntKHaqHVeti3jpMAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAK KQhJnczKWbays+GxJ7JXdF1CH511+j6SSwmiHSjbnoxN1D7Ilbt10Uy2KonVczJq 9j8oB7oPW67XlgYt/JIokcr9nzC6t3pegaOGFBZZLz3p2AFLCK5SUbFXMI2L8a+o r8n5hg6SZoguO1ruTFIH0KpL94/s3+RxdqfEK12fMhGAneaBlm+BHkc4WNBVNJUo 572RthtRyvPUssf+Em8SDbS2eP0KuLwKejjgbuR8g8yFEqstjZXOSeMxTjKDxvIV DBE0OZOwn3pUgppxLXy8uW4Msza5pCLaYQU1c9ljaaDY2bMRgIgzkST/OLoSHky+ aaoJ4IOh2DHF77Ef264f -----END X509 CRL----- unrelated_crls.pem000066400000000000000000000022521470345337400421700ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/certificate_authority_test/update_crls-----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAxFw0yMTA1MTMxNzEwNDBaFw0yNjA1MTMxNzEwNDBaoC8wLTAfBgNVHSME GDAWgBRns71gvIKR3OhvGHDrvaIxTILvPDAKBgNVHRQEAwIBADANBgkqhkiG9w0B AQsFAAOCAQEAk/TfbEefw4OvzCrIQ3FGZs0FCQqDj26EzK/btP0CJV3vib1jLqpb zcc7u83KJA2rRaq/jjW+S0E/EqMDT9LPtxn0xBCwYXln5MSz7bY9jtMCcfbus5I2 IFjzcFNAGeXK2wvaBZoju3Xlpa1HQPG15nXC3XJmijxaKgB84lj12lhHtN9mOJjw OeEhn7mwPnOGWmYo5t/NcvMfXYzXWVQoum+mB8w9m/v0AUZCZjoUAIhAR41azIjr 2JF6cnpMEuB7SlePSIWmkz4FWxOw/FgcAapmqod10NWVfuHH/+DsURm2b2Wv24rI 4L1preXklzKJC7np+fxkfzCbWbJDTmXCQw== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAzMVoXDTI2MDUxMzE3MTAzMVqgLzAtMB8GA1UdIwQYMBaAFEOTQQAQ bB17E25bHoFIsCa8BiKmMAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQAq dibNbIfkGC8PUJr3kGYhQ74QpOQXLAEdZ1MRgBJBSwQas6Rp8s4RNZ8UrLc77Nss TQlR0h6NWZU7x/POCDd2hNEZmNoxnSPZm3qO0khqBJ1ARhzdOP2i9jEQ8Ho4Lb7B lHb76jwrAn4+whd4H3YsXcc1dpS5d/k1/3E/Xjbc0UZ9knetg8sTvphbOKjeXbiB zKSb3yUYapEiVLJM5Se89MfP/WMrSrLTnl1M8pAjseZmICB/KyRyOCpcbT6BYMwa VvK2BtTQlUuzrRi+HsC89G7fv5KTzzgikE/c1Mz0UR76uEe3ZChoF3xvQO9viKz+ cNnP6F6S2AImrT/itJ9e -----END X509 CRL----- puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/error_handling_int_test/000077500000000000000000000000001470345337400335055ustar00rootroot00000000000000puppet.conf000066400000000000000000000000611470345337400356070ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/error_handling_int_test[main] cadir = $confdir/ca certname = localhost puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/ringutils_test/000077500000000000000000000000001470345337400316565ustar00rootroot00000000000000localhost-cert.pem000066400000000000000000000037311470345337400352310ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/ringutils_test-----BEGIN CERTIFICATE----- MIIFnjCCA4agAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDAyMTQxODA5MDdaFw0xOTAyMTQxODA5MDda MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBALzn4xcbGhSX65fgSIo+NB4EOYX+zJxbHamv+hbQkhAxqHxUSszDD86+ s9ZsN8cvpDIRex1/SfkNRKhgVUHGiUYbol+9RLpgpdHYLJCY0S0kOyBUgWqEcQrA tVDYpwaNC5qMneiZkcNvQ74pnuFOa0/bzbpLyOjYKEQq3BXK32yGLLHseb/PIX1o bqcuYiR6yI7S3wK9hJzSo6BRPSz0cNZNpnXbW/yLRtHbthBtzTifM2MW2jtWuFvg OW1ly9vxwTHCrJv5KxMubVDrqAx+RmmOsn327APO3r6NUr2CzV1vG8CMqLApse6m dKpCZ5UNLm4dwCUe2zWAQ0Q2Eba88O480bH8k/t8NUGXlWt25B8BUE8rklY0jwSw v8Dyjda0moeoxgMMZb+ogPjTY/Ds/h2hgFzy/DUuGrv6kyVxzH0/pOg29HeDoUaK IaqjAsN8h/oYTJ6CiOKAqWfbi8JZRmiEVTekskS5eySsPqPCegfAkfpIlz4EU4FN 0A2vORI7epW4mNiJcCLb09v5jogK+DhfeSscDsrYgIF8eAPLw6r9h1am+vXoD6vt tIwZBu15pnCWXdDcKWBNjx+zYU648iZ9V/qFG31uTJaw0z18eFPyTcJN8StTnoGZ zjKI2AyjG5F6ov/S7mnU3I/wv0B5Vq6fPjSvMrsBlbBdI3Pbr3w/AgMBAAGjge8w gewwNQYJYIZIAYb4QgENBChQdXBwZXQgUnVieS9PcGVuU1NMIEludGVybmFsIENl cnRpZmljYXRlMFQGA1UdEQRNMEuCG2Rqcm9vbWJhLnZwbi5wdXBwZXRsYWJzLm5l dIIJbG9jYWxob3N0ggZwdXBwZXSCGXB1cHBldC52cG4ucHVwcGV0bGFicy5uZXQw DgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcD AjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRZy3D0vQGiBu3mnggq8jiEZERoXzAN BgkqhkiG9w0BAQsFAAOCAgEAJwDAK7UKZvLtSJkdprO/Z0qALdUSliO0+I6lsSr/ A8SyilfMQuxOoq6uWA6j7uMU4SAHwT14QD9c6BJJiBhWLo6HoynZfYK8Smn1q2Xy vNMnUEUEjcWIgIqEDP98RTUZldgR4aWQkQVHB9XY8g6F0qWzBq64qLWjfrsIUijF Z3Ex1OMU7ZMjHhoKk2J3oBcMau47mqU49C9MoWkBH+0fLLr+lxoa40DPcFr+KzhI BHdTKuKAEJEkiE5QNVWl3+M7psFZzdTd+YFz9Vn/9L3aQr8KCb4oMietp84KM0yR 6GwodvIjh/3owsnvNvl28HeZGWQMCNIlG0aWx3JIfCOHSYlXfQ55FCtLRqMflJty M4MqRkPHKykZMZmNoiTtXRSz3vMW8JnIyZPsNtfIGltnpjHd4Y4EEVxdZhlL2wBv YycI6PN1oyhv/9ZcIbSaVY4jEpxx6mrsG8iuaT1YHlO2HOwuqvXJ48WkT1Q6go9k A775N00y4jLJXqWchiuP9Hp7AGYWzoKXFDmQbUyl0jpZsrfoTskb90xp6R7+IO7K 6opzTahhO9QeURqc7lkdvwjiYMw7uIiTT6IAKtYeK4f52siiJ/LBWucte5FLCjvq KkdWF7aQOKZq+L7Cs2nJ/qQQzlDYTQLpAbBWJbVAscoYYGPVPdKrwI4UEbKGIsWs wMA= -----END CERTIFICATE----- revoked-agent.pem000066400000000000000000000037611470345337400350440ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/ringutils_test-----BEGIN CERTIFICATE----- MIIFsTCCA5mgAwIBAgIBBDANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDA4MjUxOTI1MjlaFw0xOTA4MjUxOTI1Mjla MBgxFjAUBgNVBAMMDXJldm9rZWQtYWdlbnQwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDRTkAuRp1xvmasjoMIS14jEyikHTSQRqhN0FRTgcbl45pkZsiY plLb/JwrNt9qJrEPXqI1x2EWo0LpcQccb6akBa30zVhwARkeLWXOu/r40fCL27t9 W64excSacYu/59LAdFZvh/lhopmvCehUv90FLdNXlunLxZvY/nkymyV2CY47u02Z 3bmplB7NLYZmyAPXrXo5NWPxXsX6yNZ32QHApfR1ioe59O+yCdfNdrfRYXV76VcY Y0iFGz10pWN+hYeFNW+iQWBwJttdtB9dpw+P6UFb6ttmFR6PdYk2bXI0XDVj0iFz nxgG7Cy93vpxGLmrlgG1+Q40dkpi1ZuxTicbaJGuRMdrIWvxJdQ59YpZ4qgZ+GAI aJJTUfWD0Y9gbu+yHdVCWQqyKr/gaDd0Tzkmwd3L7BtyuvYRKwYzHmTWCntiM1ja FiWfM/nLYctyr+dxEYF3zty+y076jG/VLUkOHK2FMJYXUZ4gJtQ3e2lEI8EymBPD LOuayL3tCaY2M2rM/TYR4T+sTuuTeJqo8VxQgEV4+J9vXqTT8H69COfOOYIFFELC FnDvyv1mOGta1CMLco5iLzeQpq99SdnPajOGkQy4lwGxyoGa8cobZyxgXXArqHvJ MQtOcDudPOyPjjBfqH2hNRYocDp5jSSLDVO2EHoJSCSPT4IZwwYeDGmZaQIDAQAB o4H+MIH7MDUGCWCGSAGG+EIBDQQoUHVwcGV0IFJ1YnkvT3BlblNTTCBJbnRlcm5h bCBDZXJ0aWZpY2F0ZTAYBgsrBgEEAYKMTAEBAQQJem9vbGFuZGVyMCgGA1UdEQQh MB+CA0JBUoIEQmF6NIIDZm9vgg1yZXZva2VkLWFnZW50MA4GA1UdDwEB/wQEAwIF oDAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIw ADAdBgNVHQ4EFgQULkMvJCFY58qXuHXiVv3VdnmvH90wHwYDVR0jBBgwFoAUj4mh JiPNXG2KYzUaMaAmVAQ1J+QwDQYJKoZIhvcNAQELBQADggIBAGNMXOMlEwsspw2d WrC+wGnW2kP/ZCVWUqPu+X6MGfs51Pryt/5J2sMJOQU6DxPQhVewgIpgK40rntgp zvpFx35VaBbrLzx8uVYwtWoiK2CG+8/e/Ah57EVuYlSbzPpLRcTn8FrwYfn28RA7 P+dzaauf85t9Im0Pej/e2ZiAV+WWYyf8RlpDLWemTDlviCCWyQuH+hrnDUhbmXyx hjfpaLfvySofdw1U/x9U0oug44edTWxIvGu6ZLDqZMes8w86wTvlrwVbjMOjIoWP fSEkKgn0+McpMTVdZSN5ZU/BgoF1UihaWledZQ8SrxnuwVTivxCnjpAFQ9IRcQF0 1WBBjHZ+A2rZ2KkGaOGVKlV/lYR4Sbi3IaSdrj9b5+n1oxvJzsxLgIEMwi2TYTIH EsYPtnTse4idt2KnuD4KXGmOOVVjVH84FTVA38nNjvyDIBgRfsRSTJBBI9376GvD Pmc10cb8o16z7upI3RtfZJyP4yJFmAVgHWTfewOQ23Yzd6xb6Qh5BxkzgA3XIANc XlOscMOBFWomOJ258N4PKbDzftPHXAC3k3dBJDVmL8t2vUNKMgt20qdkn/KyHrMV fKUZR6k6erzpM51d32GPj7RUED4POMCHxO6D4TSpzKOP25vUznVeSdhHpOsoE4y8 UH7fH4utxvP85AlPOVgHWDm/S7n8 -----END CERTIFICATE----- puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/ruby/000077500000000000000000000000001470345337400275605ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/ruby/http_client_test/000077500000000000000000000000001470345337400331345ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/ruby/http_client_test/ca.pem000066400000000000000000000022701470345337400342230ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDTzCCAjegAwIBAgIQY7PT+2Ozgqiq3SfKyqSu4TANBgkqhkiG9w0BAQsFADAx MS8wLQYDVQQDDCZQdXBwZXQgQ0E6IHN3YW5zb24uaHNkMS5vci5jb21jYXN0Lm5l dDAeFw0xOTEwMTcyMzEyMTRaFw0yNDEwMTUyMzEyMTRaMDExLzAtBgNVBAMMJlB1 cHBldCBDQTogc3dhbnNvbi5oc2QxLm9yLmNvbWNhc3QubmV0MIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp7ikSm/l5A9huJ67Hapv3/m6ubJFl2g3fh1e DVeSxFHnqmZ4r6z9iuMiaa33hASnWRP3pc5j2G+329SwXmMJNP+w88N6/QVsabg/ p+5JzWE4xau3hQ71WpXdA52bnKVE7xpAF+UWziQot8kdAkkGcFn6OA6ZGKeIhZCU wwL+VgHHGYsU9wehf+nl9EAtdLWUn/rz1Pi+Eetd+7LGYQaUgK7rh1zcnn8Jgvd4 3U4bRiYvUOZzOJaDmusvFRFOZnlYk3mbPTCOAoPokchP889m0seQDhYmOlLt11Ec FstNobHxCe8j6aYlHBO8D9NAtqGiBC+n18Z1OP5W483VnwM0WQIDAQABo2MwYTAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7/pYp93p 02ARwROx5F94Ih2RtRowHwYDVR0jBBgwFoAU7/pYp93p02ARwROx5F94Ih2RtRow DQYJKoZIhvcNAQELBQADggEBAF95eHTtx4Cl+m2vOxazCTfCHGe7oprVIT8X6vQo D+AGxai3YtirgOmnOhIgNiv8qdAPx6F8idyABZaPd2ADEiru7JdAn/GQjgN3uHi8 Twm0GPLOOM32+mNJ70kehOiGnyxerQmIvDcrg0f3hPOPEKUyyKMLsNPY2nTmk9+Q TwyY3kBU0m4cUMZY9yrzs4JQO3M6J/cEFIMmMgz8nU9pY/OpgIznDehg/kOJeuaD cmPBuhMpDbhjpSFCgZHgCANAzxAeGkpV4LfkBqMZV+UZGsKVvj8M2TqyqUrRwEJt QOSyaVqhLTBEN6WAYt+VZQkr90ESePrSAz3a3qj9Jwj7pWU= -----END CERTIFICATE----- localhost_cert.pem000066400000000000000000000021171470345337400365660ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/ruby/http_client_test-----BEGIN CERTIFICATE----- MIIDADCCAeigAwIBAgIQDrGyJv+kBXgcqaWzQGo53DANBgkqhkiG9w0BAQsFADAx MS8wLQYDVQQDDCZQdXBwZXQgQ0E6IHN3YW5zb24uaHNkMS5vci5jb21jYXN0Lm5l dDAeFw0xOTEwMTcyMzEyMTRaFw0yNDEwMTUyMzEyMTRaMBQxEjAQBgNVBAMMCWxv Y2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKwAjaDsIc4G /NBT4leC9ViK9fWje5LgGVJU8DjEtj4MlL04YifNVQL6dXAB/79KwG5PAOOsSvbt CfhBaK20Kybtq1V1gY3AMsQujHjIjM4OjsWdJ5DdvIGn4rZ48Fh6eJzdGxA9hLI+ nyBqVRJwZafSDSuE5G2HxodHFLRkFSyJt19vxECnRiTrnEqruyDQaj2oq8KpnwKT dkx1Mi+HbStPN4AcnVsvGgxvW1VQNu+npyli/gM0MR7I6ZroZpg1aYtp4O+CtJUN Teyxe0E0xap1nSa9CiMfJpXylpESqT3RqIn1tEjNp7Cpdn86zt28RCmaoZTXyzb1 80yGna3mgQ0CAwEAAaMxMC8wDgYDVR0PAQH/BAQDAgWgMB0GA1UdDgQWBBRToeMp Be1dbGWtc4Xeh3H2nINEBzANBgkqhkiG9w0BAQsFAAOCAQEANte5sqSJoRLnRX8s RC7hFzw0oPhQh4O+dsP5Y5DhvnK6sO97Joz4OoP1e/98noUVOBXX/C9Wy4Xjxgc1 bPLLP9aONaNn7ytQstPr7aO02LpoIoosyhGSMli217gaYzcnpYWlNQ1UuWNy48N5 PMS47S+wyWVLdPn/hIDRWJpLuNtaKzlyopqpT+swmsdJ76WmDYqMtNTEXRx5dQ7E T5gdkBG9ai8LyBzKYqfz5C5UpsDaUZUdous1H2SWpO4IC8Qs+tbCeqL5/1mro+hc mn1tn2XLx5kTviDmct7LgW4hS2Jn+NIPGdOzn/US6dqNRDJaJdpY2e2RLoiuRTO7 Ir+oVQ== -----END CERTIFICATE----- localhost_key.pem000066400000000000000000000032131470345337400364170ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/puppetserver/ruby/http_client_test-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEArACNoOwhzgb80FPiV4L1WIr19aN7kuAZUlTwOMS2PgyUvThi J81VAvp1cAH/v0rAbk8A46xK9u0J+EForbQrJu2rVXWBjcAyxC6MeMiMzg6OxZ0n kN28gafitnjwWHp4nN0bED2Esj6fIGpVEnBlp9INK4TkbYfGh0cUtGQVLIm3X2/E QKdGJOucSqu7INBqPairwqmfApN2THUyL4dtK083gBydWy8aDG9bVVA276enKWL+ AzQxHsjpmuhmmDVpi2ng74K0lQ1N7LF7QTTFqnWdJr0KIx8mlfKWkRKpPdGoifW0 SM2nsKl2fzrO3bxEKZqhlNfLNvXzTIadreaBDQIDAQABAoIBAHm2yoIdlq5cc3pY YcrbeRJ3AyYX0dJVkpWYVYVWbj/qVzavN4ZC3u2EnqXsRDXxh8qHTXHO8h1aD7wF TTXeUMrzVFLdHBha8ZGx/uVZxYnq800TsHPq9QIq81t8qVdzEvat4ADWB5i6h5BA roKl1smy8m7hU2POuMXxns0oJXOltsc0M2i8uwGxHd64MQFMHzR6hryPchgLyrib LTz5qI4I0YijS1gMn3/sTDCN1orNAnMNy3CwocZ6L0JMBWT+Td7942g+jSHylCxi Nzopgut1Q9LIa2R0VljVudY0UOUti2zSTRYKhkf/bEf+MdER6owc2SIGBrxq1INs 7wzAtmECgYEA4WhdxSZOizQnOG7b5keb925Mx0rKNeikHww6p6+JcE0QToUOYZwW syjQKm3MNJXJrLTk/Qg0kc7sJVuoQiH+FpD2LIKvidRmgjbSoHH2KrtxfQ+yAjAR DbxyhI5zr9MzLNKLHkZonglY9pQ5AvOCq/dOCpBruAT7L062+NWzLo8CgYEAw1im L4UgZ5LbzDYhnmPXZiHuF01mat7cBvyKtGhfSZ8LSdyDi+yJdLsEYoOoLo1tYjA3 4oSUvVig5absBJJ1Zft9t05MiQh1Y+TpH88FCSGq4WGmwIO6LRdCOwOO/jjFKi7A Ve4ghT7jC7CoLzFCUYGG5bfO0HRu0KGNH8dgZKMCgYEAt7AUUlhAQ6KRn6R/4S5U BJRHT1U8aigWrxKJLiOXjgPPGR3HNXY87W2CDkGB2wyB2BNmVGl+ZaBJwrvp51LK PFuPsYAiSuDjVJQWmxejsvkjp/XFa5D+JMKAVFO+JPeoyYseQeLA2KDndbIer6// ueIEIAnHLqQoiknMRAXqSjMCgYBxvZktzBbdF65xDgevILUXW6Q03zVF/rMgQkVE 3Ay3YiqBfCr/+t7iH85iygPP7zsEU80GUGoGgadVcEa2Nsyyb6d4Zte7ZjhrzKpM gg6NjZPgnSopp8lsXcGLePv2W/m5IPWOUxOOYdpzQQ38RHM33/I6qTZ7O4AWbCou mbkvfwKBgEl1cEP0xJiiDgYdoZKgIZVZSwli2FA58TtJl3xuzUpPq252RdtMJpr+ x4vgy5zoiY56px0D+9Z+LHZecFG02AgS7yGm05T/FcYB8cOzkbHy6aWtaq0WEBIT AwH2ZR+yYwQGo078HRnaulRZL7iwK8u2B2UpvtdkFdhS1i1yCjJV -----END RSA PRIVATE KEY----- puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/000077500000000000000000000000001470345337400256565ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/000077500000000000000000000000001470345337400262415ustar00rootroot00000000000000certificate_authority_core_test/000077500000000000000000000000001470345337400346235ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/caalternate-csrdir/000077500000000000000000000000001470345337400400665ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_testhostwithaltnames.pem000066400000000000000000000032071470345337400441710ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/alternate-csrdir-----BEGIN CERTIFICATE REQUEST----- MIIEmjCCAoICAQAwGzEZMBcGA1UEAwwQaG9zdHdpdGhhbHRuYW1lczCCAiIwDQYJ KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKgUzmEZkPmZ0/NWU98HWrcav8pwaVRe jxORdl6FrhFl266IlPimVT30xSmRoc8qBiKgmil8akalVkHyWOHmsX04DwBijNC/ do5BbAsgj0FG0Qj7CzCzqqWuVMWZ0BnComGXM0+PhEfftwvBQc6LzTktjWmzJG58 HeY6T/PQk2sXqmMd+skVWatN+63CWNmxRM9OndX7CoBhdRA0DSYsr7bUmHVCx/R1 D0LxVCdC0jdQSNhrInXx2USRHyqGPLdsV0MtPhBM0nTYK0uATCVIMNb4FJfzntcv Agsj+sjN0kAfzyIk2PyBVrvnV9rfFZN1fpbXIg0Lpr+qcAo9xC9qJn0luepR6xVh /wfQvZevwwOz0K49y9jZrQBg+Y+JEIRSmnMcqV7mChuPSrld/IvkxbQPDZLAXVzB dKj4gT+NXSGdDR7u7hneXkeoSlgGuV33bBMn4BoMmNU24/VrjyvIfaKvHGZYp3XP xRlZFQ1YlYU+kfFtonhGRxTMslhTwTTOdmyQHQrvRueTNG9MZ/XIbrs+Y3PLGtWY 9iyAhFFopYe0X1r/ajWGPXJOvVhWOfiLvyPGKAaxCvnOD2EiDF6C1Wc6FdPtdUHM RCLwTqDfkX0wAFw8PiDJqFzFAWlJzRkoXcQxItS/t0i8qjkHKZPvpfwu4qD9FV2Q kifSNQY12n0PAgMBAAGgOjA4BgkqhkiG9w0BCQ4xKzApMCcGA1UdEQQgMB6CCGFs dG5hbWUxgghhbHRuYW1lMoIIYWx0bmFtZTMwDQYJKoZIhvcNAQEFBQADggIBAAnK GrD+ZRNpHJ28CBnqoPaV8obbI1IkzN2dvNHpnSsLxAlbICS1XQTuhsQtSX8ROHtQ cgRqVwmM6sr3AxvSl6BQAEdyHJ//fdQ50Wzrd7cMrgGVSW+Bl5m5nR95upCDTe4N SSbg6xl5UJ/K7M7gJFgHNgJTRqRPnHl6CCRVI8BHh22l/AjHk05KNb9ddR9Z8azc gCPw2exG16swwaZgKrHCihTvKl00oun/5QhvsBVM9RWnFVMW1iPs+mLyyFyVXB/1 uh+vRJ5tQynda00LCc6VOq/ZlWh+ue2KcVERijdRyhTyP/9ljWfWGZSNkQqW+oL6 J64AvvaDUnDcmCvrMVH+lpJyVoHHI4XGHMBPgT6uACRtH5f7UHr8ik7nMcWb/AbV AipsLqbI3UVuGgeoDR4ULoNETOjd9UBGdtIJC2lozeDT5Br4IfHFCzrat6A8TUI1 z7pFonP0W60IELPCNePlcd+lbrMIdLBr+s1IzPbJ3DvT8EJwUUs0sbOM+gnhIWfW cI0Qz+iLu9qH4IuGDq/JvoaqFwwRRjYjFFn6i/4FEkp8OIyACzGcTdt0L4EwevZX Eo6EsG8euPXTylkiA+F5F1PsGw8ZGR0LowO4dxVYMflt35IXsYjtnBQbaht6oP8S LNa26jDNcvCf/F0F1DIagsbJJoEQx8XDzG7chtZv -----END CERTIFICATE REQUEST----- meow.pem000066400000000000000000000031631470345337400415430ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/alternate-csrdir-----BEGIN CERTIFICATE REQUEST----- MIIEijCCAnICAQAwDzENMAsGA1UEAwwEbWVvdzCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAL23VOzktmj9I5xDcT77Jx6E48bYf/Asd5Z+biTugWLgurO7 2IgS1T+4E25hr0O+PgnOGxt9Tgs6kWdi/lKJjPEciTZ7P+sBo7I25sCDOvSUrdP1 7YMAvu9SFdrotSTo0rseZDhxndJvyk/9f43VwUEDIAHQSxAU/Ovfj/IXQaSCSi3L LgWAYAmdFd4F7GaUYVS4E9MmTc+R5lSjOS95wyF/n/RevGFgKv1aiWc0JPkTxAm4 OCM0zb3ikyhs+pYBamKDApEZVgYYuXn9Eq+XO3KLB+E4oyJUlpd7YSDK+3KsWIH2 oC4TlDgULp69JBgh3WyRHhCgCwqAR3gVgX51eTE7w6Q84QTTG+ejXuRbzZALdZ+q Rd2Dacd3nnmf2MOPhnodoGDd3qD0LcfGAZDYy5o1Q84+uofuTifnlqcPBukogWiQ iq/rGTGyVWXF9138AlJDmRwdOX2kS4VwMjWl47dQX8PWBEHoioWv1XKclKY4omFI +tx0J9/2eMTda6mnqnH5t6lmI4ZgSXwq2goEctPFSNW2NenDDzm5zb7wm73IA3Im jIbkZbWd8fms/KYzuFgfQYRO0+gQNeaW8hgSstJaJ02x+fWOZTDyzIgoamvNfGi+ 1ozXWoGv/HwF4bq8hqZTMW4TTTQ81Ypw3yY1M8pwx46gJ6rP7Z+olC3xr/rnAgMB AAGgNjA0BgkqhkiG9w0BCQ4xJzAlMCMGBjEJCQkJCQQZdGhpc19zaG91bGRfYmVf ZGlzYWxsb3dlZDANBgkqhkiG9w0BAQsFAAOCAgEAtABuOOHLMl5wP7pjLhaQMJ2U EDPGIXP28m/tl6PLQQXrl2o9uJnJA74wwSK7fvxbSQI85KmxXYZr0fk7mmbpeIe0 HLewF3Q6xCHPpIhrSyWzjbu1S/xkqoAaQ6FZtvhHnlNPwFrzkuYO08HgcsmwxEGk vbJ+yZ0EcB1Z3SC0MuWMjPFsMj4GTQOwQTb4sDfTlDlHfGnBCv7m4q/OniSCmuTE 8yWDnlvbb9bph660TmcPNaGo2aTWYf5JYZTf+ScrXItMWFyrNJuPqPAxZLfsX0vN 5j16ng4OUyDbkYZuOYdRY9sROn8Weg1nUKwXcGWcsw727dMbzrGa6Wv0QJ5tOi58 nIXbZTgm5GxBvXRdqrRW0ofJjy+KV2XPxAPewJHTik/SbT5ccgD4ljLgzTgJqXrf F71q2awVF0HETq7UgdeJJZ3wne2uMwwhL8m2cLAoqhlOKDz4/lPMlQSnyuezoglR +P/n2wsutYKLr6HKIvFP7UKZRA9oigkQWcMsRB5jwMk0vyZQoyoGkvacCPqdZifd kf6OMe6rzndr3+/Nwwgx3hJk8R/daW3Mic4gzTcgKJ2JGuVLekMReFlM/g3KvCrX ma24qPEAcw5/ryj7GTjRsrqmL3gqkHgdW2g1y2L99EOaldfu56f/JFZw+aOOC/BH CdXdbI2Ff7usKKxnqsc= -----END CERTIFICATE REQUEST----- autosign/000077500000000000000000000000001470345337400364545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_testautosign-whitelist.conf000066400000000000000000000003561470345337400431720ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/autosign# This is an autosign.conf whitelist (non-executable) for testing. # This file is a list of certnames and domain-name globs. # Blank lines and comment lines are allowed. # aaa bbb123 test-agent *.red *.blACk.6 #*.white # coffee#tea qux ruby-autosign-executable000077500000000000000000000011461470345337400433330ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/autosign#!/usr/bin/env ruby begin require 'rubygems' require 'puppet' require 'puppet/ssl/certificate_request' STDOUT.puts 'Ruby load path configured properly' rescue LoadError STDERR.puts 'Ruby load path not configured' end STDOUT.puts 'print to stdout' STDERR.puts 'print to stderr' subject = ARGV.pop if subject STDOUT.puts "subject: #{subject}" else STDERR.puts 'subject argument missing' end csr = Puppet::SSL::CertificateRequest.from_s(STDIN.read) if csr STDOUT.puts "CSR for: #{csr.name}" else STDERR.puts 'CSR must be provided on stdin' end if subject == csr.name exit 0 else exit 1 end ruby-autosign-executable-false000077500000000000000000000000471470345337400444220ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/autosign#!/usr/bin/env ruby STDIN.read exit 1 master/000077500000000000000000000000001470345337400361165ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_testconf/000077500000000000000000000000001470345337400370435ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/masterca/000077500000000000000000000000001470345337400374265ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/confca_crl.pem000066400000000000000000000020341470345337400413530ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca-----BEGIN X509 CRL----- MIIC3zCByAIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMjAwODIxMjAzNzE4WhcNMjUwODIxMjAzNzE5WjBEMCACAQQX DTIwMDgyMTIwMzE0MFowDDAKBgNVHRUEAwoBATAgAgEFFw0yMDA4MjEyMDM3MTla MAwwCgYDVR0VBAMKAQGgLzAtMAoGA1UdFAQDAgECMB8GA1UdIwQYMBaAFJNk3inY rw7NPEwJWq9oVNn2Jm+dMA0GCSqGSIb3DQEBCwUAA4ICAQCLRXz9tDo4TF0zLxyU r8b3Cx+tFsNsQwhzbVs04TvS2jgeOdcJ8VcaCMSoRMEol1OWf+Xy0BEq4cdna4iZ 8G/CHD1dwjh4tFVMOU+LWw0B4qaARTs+/2Z2laNL/tijmAaHhu2TWXYHRXr6prfG qo8ZV0y3UW+aa/Lh1Yte4n20nPkyU30MO5204JhE9Iq9w+eQAYDHtrGXLV3/jBYm ILgp5R6w2WLBcpEdjWQb85hdnJPz48RBg5IEwQrH4irexoTVffAsuZxCnyGI2M4H 2DDDnKPaw0dBHCSJe7RwyC4+c9R6rQaJjgNqxrCkSwfFSv0vbaHWZIzso3BY330u +My5CimHyCtmgyyJ0GtyfevRFk5DvR4pmRIBsFRuMm0VbHiq5mr1jFgja2rKqC6I RdKHGJO4xFQDcJZ0lygIGL1tPXuuHjPa3DgVXdudBqopFa19fkGAV08fvxc5Ay39 Zf2vR1AiLmCCZOr7N/85OWNnSxPGyNM2ZDr+wk6m5zti454xw4FgqlOrTsd7xXNy jQpdvvacFQwIeVtQfyDwAaQ9gK2N5buYuRWvQ2K617GkiJ7LYiQYMpNQYoOKskVS HvwipRCshevp2/ronki1Hb0UhXl2JbDLEi15i+mk6gZ763W3kp1Ff6BE0eTqYNqY jfmwm3cSsRFgKT5uKFRA5suMig== -----END X509 CRL----- ca_crt.pem000066400000000000000000000036071470345337400413720ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca-----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDA4MjAyMDI2MThaFw0yNTA4MjAyMDI2MTha MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogbG9jYWxob3N0MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAs16e1wja3owOBIZaMZACHoIe33VA6TGYU4yaFke/ DziDmBNJ7DEpub0iNMA0IM9WkuZD6jXP9ZUEZvmxH1fiMS+O9kYMDMpScZTyTtuJ ToF67GbCk5R2hzyXD79KoZf9Gw6+BVrNW+3VTifTt0v4fulas6Riy+pmwg1+88ip uOO31JMU3qTGCVbFL80dvM3qFQmwXo+48167Rc2Xo7c3X1gbOFz6zZ+U+pvsvXNs H+vCm1FHGhrYWgIKtCK0d4wRhthsrrHNqIX+G/NNmJJQ6lg0qQQ79mvS57UsY8IA lL1W6BPNe4y6/624NkYzrwzGvGhGXRCHumMQ2G3tifvc/3/1o63bkeGt9A00QyZp 7Whrr/BOE0e6JrRuOeRqU3yNPPraFUq/WEz9ssOOtok0f9kxByzYjiX6LTr3oYaF 9tKIfBBQfrpll13Sgx59ULkepsQr9MrsyANmLm+HrUgTBIsG/D9yhhur7o2jnDD9 XZJrCoL01z6tCtOeKzrhwJxm7zc53ncKjXNbDZyQ/ghPs3j8pimuWU9XKuttNKEl hHV0K12neL9tIIhYyVtiosaOq7dpZzV0CznrqCQVfEuCxAx6HEuiyneKDDgSwrkM rtUK3Y5UvEdWOH2yvpt3MzGglx1dfpED003i9rfmn1UNb5ZcchcS8yVU0Nk7MQfd T3sCAwEAAaOBqTCBpjAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRl cm5hbCBDZXJ0aWZpY2F0ZTAxBgNVHSMEKjAooSOkITAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdIIBATAdBgNVHQ4EFgQUk2TeKdivDs08TAlar2hU2fYm b50wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL BQADggIBAEVgzSjR7D4kLggPSxC1ma4ycOpfqP6xLdMplCyYGMNIFm6l/FSDfJiP hOFwsCz7RBqfoi0BSglGlI2eoHQ/NDvss9IyQfZL5nYWua3NdYGwsmU4WjAjSu+8 OkM9eXrTJYfObWQVhEefNRPZb+LQkhQMPJV89sKhXtuNM2AdGqsjzzw+BBX9bH/s nQvJbzOjxuDeQecCLEdisc0FSwg2rNU04z0xGrW96JPOouaHnb6UsFNwXtLoGoNm E+yBV8LoAbD4AjpLoVuNoTjlZtrPki63WU7MQTKLC2C5u/DPUGZ6oGd8RFYgIVQc 1hmygzSvu2OwuqxhI86bktRigKilCbHFZxDtuQBqsfCOW0l+FA7dRV0uu/VIXUre J9TBnIGUwhxj/YyGRrPoiikktYRq2TkxggMnR8t8lZeVtCFTPdSIy+/kJriTV9+r a4FRWb27cryY9G09+R7OI1N6qFhmp4ewrPePFlDJpTDTeeq0mwDYyqA+unLIKpJM AJfLJMZG2z+QjfC9yyNBuGXqxLjvh/tOMUQc5mA39xlseEy9U6pKCdekYBiV0LTS WjsWpgTaud2gCbEC8vi2kaKB+uox1TuPFxnGVQ4/ziBTAFeNYDi9tJe2ljNWCipH p1/wLPCV3+xSMZpJMxD9RRJ7eBcGmuYdxAkUoQh0IEoya9wgzNqn -----END CERTIFICATE----- ca_crt_multiple_rdns.pem000066400000000000000000000037201470345337400443270ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca-----BEGIN CERTIFICATE----- MIIFmTCCA4GgAwIBAgIJAO4Yee/Qgj1+MA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV BAYTAlVTMQ8wDQYDVQQIDAZPcmVnb24xETAPBgNVBAcMCFBvcnRsYW5kMQ8wDQYD VQQKDAZQdXBwZXQxHzAdBgNVBAMMFmV4dGVybmFsY2EuZXhhbXBsZS5vcmcwHhcN MjAwODIxMjE1MjU1WhcNMjUwODIwMjE1MjU1WjBjMQswCQYDVQQGEwJVUzEPMA0G A1UECAwGT3JlZ29uMREwDwYDVQQHDAhQb3J0bGFuZDEPMA0GA1UECgwGUHVwcGV0 MR8wHQYDVQQDDBZleHRlcm5hbGNhLmV4YW1wbGUub3JnMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAs16e1wja3owOBIZaMZACHoIe33VA6TGYU4yaFke/ DziDmBNJ7DEpub0iNMA0IM9WkuZD6jXP9ZUEZvmxH1fiMS+O9kYMDMpScZTyTtuJ ToF67GbCk5R2hzyXD79KoZf9Gw6+BVrNW+3VTifTt0v4fulas6Riy+pmwg1+88ip uOO31JMU3qTGCVbFL80dvM3qFQmwXo+48167Rc2Xo7c3X1gbOFz6zZ+U+pvsvXNs H+vCm1FHGhrYWgIKtCK0d4wRhthsrrHNqIX+G/NNmJJQ6lg0qQQ79mvS57UsY8IA lL1W6BPNe4y6/624NkYzrwzGvGhGXRCHumMQ2G3tifvc/3/1o63bkeGt9A00QyZp 7Whrr/BOE0e6JrRuOeRqU3yNPPraFUq/WEz9ssOOtok0f9kxByzYjiX6LTr3oYaF 9tKIfBBQfrpll13Sgx59ULkepsQr9MrsyANmLm+HrUgTBIsG/D9yhhur7o2jnDD9 XZJrCoL01z6tCtOeKzrhwJxm7zc53ncKjXNbDZyQ/ghPs3j8pimuWU9XKuttNKEl hHV0K12neL9tIIhYyVtiosaOq7dpZzV0CznrqCQVfEuCxAx6HEuiyneKDDgSwrkM rtUK3Y5UvEdWOH2yvpt3MzGglx1dfpED003i9rfmn1UNb5ZcchcS8yVU0Nk7MQfd T3sCAwEAAaNQME4wHQYDVR0OBBYEFJNk3inYrw7NPEwJWq9oVNn2Jm+dMB8GA1Ud IwQYMBaAFJNk3inYrw7NPEwJWq9oVNn2Jm+dMAwGA1UdEwQFMAMBAf8wDQYJKoZI hvcNAQELBQADggIBAEuNBDg2RtQ6JZrR8WrYbmsLRsPvosoJlHTlz7X9+XFzs3mr 2FDhiJm/D83Q54rlEA9WESsIx1/5wIUdpFy+NvqrBfsJMuGo7F8RAoN60VYduDbe MVGmA78/pmEe6bDYCeooKhAkU6ZMMYdVOHXjvkzF/6XOFfWdyD4osg/Gy4LsAezV sBnfx+KzGp2XVGCFfmgl9+2K0+kEuT2Nh/s63mMnMfHy+J5oytU64MFboxlcqMu2 VmnoFfOTct+pm862uftK3YdSziNJghihlDxUIj0hEQsIXGrZn/EuxjaeB1pnnorA ucnqwQTuIhPyQx9WbCZr0SWobc5/cmNOmB0r3auaQdbheTiyNh1h2vtfsFYx252y DNhZWy7qU8wqErzbl8J7RuFR9bqDsFMcm6fQkYOo9Q099Cs32OA+gK5vBmmzBtmP 8nhFtwlt62CuNYv4iRPtOIFkTMTxtf1Rk3IJvoH+RkRBCDXeJyo1NPggYu2JD5EC wLgS4O4yUQqPIfFrOJKluqlufktqHEPKEIcteS8Fsihy6MC0t01KbT8Z/C2DxYGt x+uvH3fpyjbzaMcDedAfydToh9PxdxwCa1DDpVTeDNFSzIy43+5wN2Bm9l2Na5dN ytdjvj8td5BZ6FYv8aHkocdS1LUhfxnp1NhHN+H4A4XSZyCQociWp6MsFAKD -----END CERTIFICATE----- ca_key.pem000066400000000000000000000062571470345337400413760ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca-----BEGIN RSA PRIVATE KEY----- MIIJKgIBAAKCAgEAs16e1wja3owOBIZaMZACHoIe33VA6TGYU4yaFke/DziDmBNJ 7DEpub0iNMA0IM9WkuZD6jXP9ZUEZvmxH1fiMS+O9kYMDMpScZTyTtuJToF67GbC k5R2hzyXD79KoZf9Gw6+BVrNW+3VTifTt0v4fulas6Riy+pmwg1+88ipuOO31JMU 3qTGCVbFL80dvM3qFQmwXo+48167Rc2Xo7c3X1gbOFz6zZ+U+pvsvXNsH+vCm1FH GhrYWgIKtCK0d4wRhthsrrHNqIX+G/NNmJJQ6lg0qQQ79mvS57UsY8IAlL1W6BPN e4y6/624NkYzrwzGvGhGXRCHumMQ2G3tifvc/3/1o63bkeGt9A00QyZp7Whrr/BO E0e6JrRuOeRqU3yNPPraFUq/WEz9ssOOtok0f9kxByzYjiX6LTr3oYaF9tKIfBBQ frpll13Sgx59ULkepsQr9MrsyANmLm+HrUgTBIsG/D9yhhur7o2jnDD9XZJrCoL0 1z6tCtOeKzrhwJxm7zc53ncKjXNbDZyQ/ghPs3j8pimuWU9XKuttNKElhHV0K12n eL9tIIhYyVtiosaOq7dpZzV0CznrqCQVfEuCxAx6HEuiyneKDDgSwrkMrtUK3Y5U vEdWOH2yvpt3MzGglx1dfpED003i9rfmn1UNb5ZcchcS8yVU0Nk7MQfdT3sCAwEA AQKCAgAjeHKw02900v1yp57ubiv9HH4+clGDy+rzmrpd7ZI60FI1oJrdulsl/+Dj zZ6BXn8gTajgiAO37OAR/Q6pxBdW4rDCwtdfMCNdkrbYIVHl1HUairevt4w48iJt WsbHbeb/ksrBBFPX+hBUhEu506wwbLUjET74VEI93a1dSDFH/sA7qVpXLP58mkwk R8u5qn6/6kqWaJWKixE9nIqANZsdn67CVqDCSOyNIoiObmTTayvwywHkh6qBIiY7 uSE3Atv0bpgPc9nXmafGnzaZFVYrAYZoZg31jR0H9SvyDktPHqIxArl/1TSlmxTy pq9RzpT+bSB9BufQVAbgxdxTjRsGls4U28qROXXqv5Y3o+TG5vNwTd8DTsPEzOm7 ikuBErVlsnTO9Pnocj4KT1657E4qVEHcwoS1poqeqJ+Z8pQlbGLzQ+8CwD/FCUEd 82wOEZa5KaQWusJ7EO6/ephsV6EPlXYJHhVccI5vVLUCa/CxhBS9g9T20FbMCFP1 9NKgOsXPJxdd+jPyoHYwpYd4Dpbv+OaRnsWf1a+/+aFosh20YLi4Apxsq26jsBcq ZJQnCDKRtao02X1vnUwF8sOisqojISJJK6nEMEaWIrjDIhvWHg+1MhDmroYUyreG QFBjT9i/19kmoud7V4dEQ3CrHBaBXrZ8HyVqbMJzHSLGslj/AQKCAQEA4Mc1Vb0d r5RWdleU7/pKIOu6mtI5lCqntk+A6NrSAe75ljlpRECShEFK0d2WViFwV6eT8+nE 8z60dX/IN+8N1DaDvKcdYkfyat3FiJYdn9w6B4JW6IBvSlDlEexjfidvD1FNi6Dc WKJqK3ZaOHq+q0DGVmzGuXVE6uokPtKQOMxQftcJBE/ekJdHHfo7WeUTQr6Ov2OJ HqFjkN9kbeNE77fiQxtjqz6gdwbpm/QOuHDgqtOS+kJxQMNP45t6madxemjux447 bOO83gfz0SirQPGSnWtWH3/KtK2iIWGZIF5iKmFxZq3VmAvG/OwWOEcFa/6gu7ia ieR7NghK04bsFQKCAQEAzEi/sJ/G68vIx4O6Vr5v2P6NAwIl6cf/nH1e1Ds2S2Yo DsVOSA7xKK/VCETac2OFqR5KDKglQylarr85qLODNwsujSM+Rv/Uz2/bhUVaVdim 4gK8P3nSVaZYWflVe0Z2spdeqRp2cenqFt8NfN+W6E5DsEZumS0ZXQJxAPJUJ29w 9E6Bqf/16OldBL/lAtJRhM9EME/lxjWquVdoJn2JglD4615E9pDPGucohfCPs9pH aPPN1lQv4nz7W3evtqj0zBz778uN5SSaYzq7aX3EfTpp4P0jKh0ojf3SrrvFrXb+ QsR06FGZ27cIVCpJpopqYONK7LSMFIwmPP+fn8zhTwKCAQEAr5ryEAmvJ3y8D7hc ox7mytFe95VFZnvsioGSNFi/uML6OmKf2rKXxLs9uLdku+Vj3xcMf4IiW+ahFSq/ QPOB2ki8oqXsTtvmh5a6u/qLKlji/PrW6s1sJKMOUvJayDQGj/D0pCEIBDbeuxW7 ZmR+kUwJp3tTxY/YR66kom/ePIFiYbWdVcEQH+YPqVvVAmX0pjA5VUxt04BCSOw9 iZwEP0NpgQPk2eQTeOntl+kTlwSYgNzJ9rnxwKbVwvu0zFYEUZ2o7j4wLuG8q7mK wd0D7bjM0i8JGZK8ymrcPzgAaUlTZ8i4z37/X8nTq8TFlzHlCnnjGMUf9pqJp6zS yG6gAQKCAQEArkd2OhHlm+7MCOJpy21GcIKh/KoNfEfi2zfd+gPWCzdI/2j2ouUU epifjyFmmMCUHDa6B9g/ie+y7Jg5caJMVF5WxZQGon3JqXsNdcI4Ejr2DKU2wpSE jAuRHplngvcXdr9Kw8vOttpPmlmK4TjDPsbeWnmMC2P9Wmslyx/yCX66h8KePlEf Eyhb8hxgHSse3sYQr4LKTXIlh195fDTnZmT8J5jSDuR1u8bvvG0Bu/eBqpksxygl ff0QV/Vg092KksQ7b1ViZdX3XKaTkqj4Q7nc8FQldt1PZuvfnLCXMajtvDpsXnKX Z2ncUimNkeZOYQAoQI67XyA90xZlsOgSYwKCAQEAobavoPwU9QRmri2YN9c+PhmZ 2fTQfXq/G+7L1UJ3dV1LXwj3D+Po6iKbPUzGyrETPDEMaW8h7QGOSs/6caJ0u4zy R+Gtw0ejn8TOW8AqjCyhLTCEcvUvE2DYq0BTlGrjflU4F97Ix+vBo7QVN6JXow7o LHUv4jGnfN3k4iPi/yzo8JtbFrXM3fTgw5XGRK6qwDIm3MJBKB6/ewFjdgIKqcM1 Vix7AaIK7QSDBTNGRd+e7RmTC2jt8KEyZQ64pg20su7M2NdMORVWQ2/C6rWjzMsQ c/Pm8FCL9jq5fLf6s6vq2OQcCnlvlFSePWDHoXdMfuD6l4qRtLO1TjtHfdgybQ== -----END RSA PRIVATE KEY----- ca_pub.pem000066400000000000000000000014401470345337400413610ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs16e1wja3owOBIZaMZAC HoIe33VA6TGYU4yaFke/DziDmBNJ7DEpub0iNMA0IM9WkuZD6jXP9ZUEZvmxH1fi MS+O9kYMDMpScZTyTtuJToF67GbCk5R2hzyXD79KoZf9Gw6+BVrNW+3VTifTt0v4 fulas6Riy+pmwg1+88ipuOO31JMU3qTGCVbFL80dvM3qFQmwXo+48167Rc2Xo7c3 X1gbOFz6zZ+U+pvsvXNsH+vCm1FHGhrYWgIKtCK0d4wRhthsrrHNqIX+G/NNmJJQ 6lg0qQQ79mvS57UsY8IAlL1W6BPNe4y6/624NkYzrwzGvGhGXRCHumMQ2G3tifvc /3/1o63bkeGt9A00QyZp7Whrr/BOE0e6JrRuOeRqU3yNPPraFUq/WEz9ssOOtok0 f9kxByzYjiX6LTr3oYaF9tKIfBBQfrpll13Sgx59ULkepsQr9MrsyANmLm+HrUgT BIsG/D9yhhur7o2jnDD9XZJrCoL01z6tCtOeKzrhwJxm7zc53ncKjXNbDZyQ/ghP s3j8pimuWU9XKuttNKElhHV0K12neL9tIIhYyVtiosaOq7dpZzV0CznrqCQVfEuC xAx6HEuiyneKDDgSwrkMrtUK3Y5UvEdWOH2yvpt3MzGglx1dfpED003i9rfmn1UN b5ZcchcS8yVU0Nk7MQfdT3sCAwEAAQ== -----END PUBLIC KEY----- infra_crl.pem000066400000000000000000000016761470345337400421020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca-----BEGIN X509 CRL----- MIICnDCBhQIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMTQwNDI5MjExNTI3WhcNMTkwNDI4MjExNTI4WjAiMCACAQQX DTE0MDQyOTIxMTUyOFowDDAKBgNVHRUEAwoBAaAOMAwwCgYDVR0UBAMCAQEwDQYJ KoZIhvcNAQEFBQADggIBAEHP3m5UA+lz1mjF2K+2jZ9bgZE15POftI9peXNILia3 AHE7OQtyxju/Mt/o5OpPW+0RJso9OrXhEE6T65BgOovBi1VkfxXILIui8n1oF1UK 9npunKXwgjP6Y8QbuaLv584QdwjfEFlFp/nJW5IQRKVIgsLsSGIBlZvmELiosR/W er3Ba7Cy/Y8cfMx0t/4QCU63l/Sr/8mgvp3P5RwhljN9ekp5Y3Yz4jdRycJsrq8J aQss8N4BrE/ppbvCdmf5UdkXgivd6cl04aSg1f25yYtEY12fyD8C8VySGOfZrnlh aOhJapWTuKVU/PxdCZfeL+RVufrRWBo4iJCRARKddDeqDWtI62pysjy/2PRvzMRW qudj9gJC3JnsWzvZqTGK6LNwDyH65Uc7cXjq+xxMgDpCYKZrpSmwlKUmpfnzZK/o ckJKFaQzXvF/RJF2Ai5W3HEl4CjRp5y2yqpORsl+FDVBl2hi5n7rCqJ4RibbdtTC pFFUP+na3zv0Z49uFLGQ/a/WHI2KuryMlDTkqltr9xncSpKafyT1UCciRdct3Q01 EWmuRcsawSg+nLB7VcLRgcnbbRuHJS2Pn2AZxYAg0SshGeZpl0zIiVzadb1/IY1d MlXJjO6RAj87/yUMC7/xC6IJh3sQymC1Yw8nYOGjnGiMCV68e5izd3eQTj8arTZj -----END X509 CRL----- inventory.txt000066400000000000000000000005421470345337400422250ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca0x0001 2020-08-20T20:26:18UTC 2025-08-20T20:26:18UTC /CN=Puppet CA: localhost 0x0002 2020-08-20T20:26:27UTC 2025-08-20T20:26:27UTC /CN=localhost 0x0003 2020-08-20T20:30:32UTC 2025-08-20T20:30:32UTC /CN=test_cert 0x0004 2020-08-20T20:31:04UTC 2025-08-20T20:31:04UTC /CN=revoked-agent 0x0005 2020-08-20T20:37:00UTC 2025-08-20T20:37:00UTC /CN=revoked-agent requests/000077500000000000000000000000001470345337400413015ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/catest-agent.pem000066400000000000000000000030621470345337400440600ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca/requests-----BEGIN CERTIFICATE REQUEST----- MIIEWjCCAkICAQAwFTETMBEGA1UEAwwKdGVzdC1hZ2VudDCCAiIwDQYJKoZIhvcN AQEBBQADggIPADCCAgoCggIBAMQrJEuvXjuygtK6JIaIhdmb7PP7PukT/au1+S6q +umGvZe8y7Ycob1fRLv1gn8JTizAmVnXMwc4xbyTi3AXnvSuPKzksAFEUMHt0eG2 r+V4QvEw8wqfh2KewZSMFtHl3hikCzYpemFQlASNyAcuhNWk/35UzRz2lUQaxqil OSduNNUcj0FSLzWtmjkTsPw/CMO0G0QduDg6HWeVFGfnqFlPRFRqX7boWALy0Amu SQSHDYzva7qM5LAYjP0VVtKw6r7YZng5rVc4vyjON0G6p5BgYy0KMDTm+kL8Um/A 0EJDQO7mWIos3FYij2H3THGd09MbFPKnVLIWsXjjz5BkojjJj6XsjjZle6xOJie+ mCdeekxEPTHFH3B/Zt1k9T+7p/rlxBfrwqFS9T1BmuQ8f7ximOa2sp/AbioThtEX Sq92U88wf8ORRjnx/hbJFvVn05nKyVnGWJs01Al6HSE9ZZCc4FBpjpPAJpaFATlF YG1fZtGL3BourpzHmB4cI4MqqVgM0A0io9Zv/NJcpgv/3APqWhW65F6CL+oFRwdL TYx5scf0jf+nD4GlR0Re2qo5yYmBUG0+0pfzoUHl95V3/VYQ9fvQX1Hlo6y4hMOO MUHtu+kN8BBisG8rfZD8TGyjc94DdkaT72/rxmYRYJHfWKLMufpwlcI/UzIIuQN8 PlJxAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEAXFzEZr9B8sgevG3m1BjSoN9m aI0wmGCt3EzD+Dj4D7/+N7ovEgniQ+6i11adekXtLMVLGiFYwOLdaoKxpCO9K1TX Z0neSPn/j/e+ZW8iBLPSji42ZLEbgLQP1c+vj294ZsEOFo0arXw0KSpfqgWcT1TT BuoF719CIN/r0g6Wwxp0CO6oJnnwSfcL2L1gu0zDKL9ezWF5d1JcELV9yTtihMXh hFRE7UaCOrrr9fX8FMYmTuffmgPHQe5UGx4Db8kMncqbKLUohbnhuQfKBQwBh3xJ hhUhUpfp/XYRLyqGwMhxWH/VyBHjfXWBZNu6FjKdQh5laOCbGzzhEPDFHjW03e1i PRCqqOD/8WDPZcz4lZ+33BNl8TSVJy78W6NdoD+QftHXakrKmL0y0B5CKZeoe7mW riwpQZqmB5Y/3afbyS2Oxih/98onG/Hql82Wxtbs5bj1na4/Vm18U4KUSv5AqbFj eyjSoO4ZkElqYkL1+5YsEaAVnamO/NAluHsS9ZZmKBPaRE23jgg2xKJPSpsO0Kxr 52G8L8vmGlTsZ4i5aRkH3Q7D7UjVcdxfsqnmMUCM9RY2yvoBVKGWLq9dw1TkZTty 48NXMftemB61piNPxFD/bU0bEgnVpwt8U8NoZAwSjLXxGTO9T6DW/tujUMgj1g9I mykd7/fPwJyPkTNH0+M= -----END CERTIFICATE REQUEST----- serial000066400000000000000000000000041470345337400406220ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca0006signed/000077500000000000000000000000001470345337400406775ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/calocalhost.pem000066400000000000000000000040421470345337400433720ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIF1DCCA7ygAwIBAgIBBzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDA4MjAyMjA2MjFaFw0yNTA4MjAyMjA2MjFa MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAIoNIX3CzOi9L86SSURlei/NoXJtSlzQ6wcx6uz4FdnoT9F1WNqk5X/c BZqXBPf2nPXb7lQIPjDKBQjk2eMAQwXQY68rLN44ayCCEiF61TjWXarNhZ6LgNEh Gwhvrz7IuhsB21avB3WhbrcR536v/hY36PlKELY9LriAVsioFD2ytgMkg3/ULbkp vnGPZr4yV3ycGcve5YOt4Wkr7Ka0tw9ul1T3z+n2JRtrd8MusagOhXZ2bFR9Kewz /mTYvJ4cQf3Ops/4IlAGzFIFxKRwhhKzqO8X+eQVV7i7CdU9zNrCxOjOxLNNUtN5 LGu+VOiYBQDOEzuqwb7H+LhwZGJp4SuEbjqeLaLszmJuyam6uvDyk1VVN5RoxhZJ sM0LZbf/4UmHkuFqUgu5DLvOjjBF8F+sBoBfhv/flC+/MnxawxljNf7GdE9g8ueC zQ/0HCNDkHh1PUNmTez0x8p74DfkRx8gTy8pNwX+VYPV1fTXB2vLjup54TUp1T25 TUzsXHq2kgtkyX5SKATjJsVZwvmDxRujhcrRw2zG5Ljvtf2NEvc9Rz4GXFIvzJW6 k48c8d0+792J/RVN4uU89P0kpWPLObvsnjmMEUhntc+iH2dv8c/rFFmos+oJxTn+ Oy5bRDkX7kRFng8hHKHvXM3LfoDCerefOJ4tg93FrtwjSxqQOE33AgMBAAGjggEk MIIBIDAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRlcm5hbCBDZXJ0 aWZpY2F0ZTAfBgNVHSMEGDAWgBSTZN4p2K8OzTxMCVqvaFTZ9iZvnTAdBgNVHQ4E FgQUGq405UMsiA3e5K5bqAE64LItXIMwFQYLKwYBBAGCjEwBAycEBgwEdHJ1ZTBU BgNVHREETTBLgglsb2NhbGhvc3SCG2Rqcm9vbWJhLnZwbi5wdXBwZXRsYWJzLm5l dIIZcHVwcGV0LnZwbi5wdXBwZXRsYWJzLm5ldIIGcHVwcGV0MAwGA1UdEwEB/wQC MAAwIAYDVR0lAQH/BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQE AwIFoDANBgkqhkiG9w0BAQsFAAOCAgEAaPDOiQLv2h3vct11E/LqUNojEKZqCEis eomt09FAqIlbTCHzM08SsyIkNkmUFEgqKmTJ/9AW1JzKG9BBnhzZqr5uCI+zf0RO E4eAHQbDqZZjv5zc3eknY0RTcma81aDztKSbr5+rNOEYfqdNkxnXvIQ6KqbOGi4V CyTdQ5hrNJHZPG6cBI2NyfTj8uEhKiwkl2wVb3IH78siB/Dmzw9nKDvfv5lJl2d1 hX8b+Osomsv5acZB+iS1Zq8RBi+H22FjwL/CGa+rEppBO0ig2s5D35cQtahAEN2f QoF74Ob2iM2MneDXmfTYKFcVGnu8p+We+WtEHZ+8+tOhQIiSTfEiWo0JHzHP4p0h vk1drof5Aek2Xx6w0GD9HbUYWGwII5BHO5Z0Kcx/Nyu0O+bDEgOXXgdRokPlGLnp 6nmTzTVyGPG6ZBIFr9JvLOdCG89IX2G+OXTLgxbQBOjYvrJrHzA0JLC0pBNlIs/k MXQLnqwks+GNbFkmzTQUwhd3ppvdMOkRv/XyU3mGDFm6vmyvqOsT/nn7uH2omuU5 zlqg303A7mpqBWcvI2t7H30z8h9aR5eIwDXoMtRN25SfTxujJlALNkh8oCVotAM0 wEzPJ9JsVSTuv632Oix+5nZFhMKtfdGRia/MwTyw4u6v4InS2aqT4nNAJ65OctC3 mDsvGhzlv64= -----END CERTIFICATE----- revoked-agent.pem000066400000000000000000000037101470345337400441360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIFkzCCA3ugAwIBAgIBBTANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDA4MjAyMDM3MDBaFw0yNTA4MjAyMDM3MDBa MBgxFjAUBgNVBAMMDXJldm9rZWQtYWdlbnQwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDDYMArWWfCFgApNR1VPmvy8pGbl70EqMNXZleR0umze7kMcaI2 m/58MjSU9FwNs1WB33LtaAxhO4wczxesazzH74TduaynjNlPom665JhIiaGmozXd v39dNjfKjAI4kc0joW1LKhjzGmqRIlVGxCV5v/MDxsleFwMpTsup0fHM7NKPlVJn pWFnjzIK6sDjS+3PeP+gxoWNYKcj8MwRZdKa+M0j3rxe6ANm91uBisjTl3gkDuLV +/HxlUMP4cPk5juv+j7JjChRSTSxSFshxj0FmVJI4YW5iFPvhkO62ZY6Hi9/Yrpl E0ZhRqZtchW8xhJawi1g9oFMgcUZlM0PMQ8GZp+jpO1bUjzZgkV22QMC9xgXMsnL Op55MA2dmWyHmumHOhOnWG99yL2kjPO/VKYFphgey9NrKBrUYuSaBnY62Tw/w84s TCtFRUZzUmkKL7qDWM/5Ia93e+/LFM9R8gMQIv/wIvb6XFINlWJurPtFoIPoSyES fA5clF4QlkUGRHYwFmpAwl90E4U0wmY79/oqaFH4C9Pwz/pTlZdkyVwzwESSoNwe DOEaDoJmyVl4zcDU+HvA0/pfKe70P1gsQoWHbSwOwDpDqILglAcZ39o66SrdlCXs Wfbv/XGcDjcKjvjtowfPw/2dsNkAbim/ah2PTWYXSvtfr9riOn2t7PifTwIDAQAB o4HgMIHdMDEGCWCGSAGG+EIBDQQkFiJQdXBwZXQgU2VydmVyIEludGVybmFsIENl cnRpZmljYXRlMB8GA1UdIwQYMBaAFJNk3inYrw7NPEwJWq9oVNn2Jm+dMB0GA1Ud DgQWBBQH4D/N6skE0iAoVDrNaYvyyLfRPTAoBgNVHREEITAfggNCQVKCBEJhejSC A2Zvb4INcmV2b2tlZC1hZ2VudDAMBgNVHRMBAf8EAjAAMCAGA1UdJQEB/wQWMBQG CCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwDQYJKoZIhvcNAQEL BQADggIBAIQafh/kC3NIlw2PYKo9er7NnnZp5tdB8lunhCUnO7EqCDx1Gunmo7gv zBuZjYDURGni0DLadNtx+T1E7lALdx0PZxzrdymxqy6nsi6SN2UIIuAl7Vh6zmlM 1Yri+dEVR299lmgbXFqsOrqtl3WpWwkwJKhCjfYDGx2wrIhh99XNyx/yujrDLvdl fu4OtUtx9YUSt462VdxKSyn/w7pMG8XVE+7PxJhAtyz3YVklZstw0EAMxGd67T53 SYzCDaPxEfamo7VaN4J1EbInkPnmaBwQyORpwF5FZibxxpQydqDjbYvxhcMbl9Pj MMfvhsp1lH+S0ZDGDeuGZWsRUvxhhZdLmjZ2BuAGLQrvOKsKGmKPtihM8eMS7RuA LVOpjQQ0t+WsEL6SOCI/VjbJTaIs3llCUv86dB5JadNVeDjkVKBWKdXSFSwe/IWF QVoRU5u6qRRhUC9hfKD/S5QqnemuVe25gVKLolRxKQckvWysYCyXWPKS0nmXY1G2 k/bZuh9oGgo+tSCm4+NjyyQ+oDSRwIIYYLA3Zys8r1XXIXmVznODRJTai+7vWbIU jTsBRjDh8l7SCs1xuo7AFyjSM/ZnEd/c6jvu6Sk2U54gCNwRUnViHgctVPUxsTtA Q8oprGHbjULP6NMQM1jOjtNxQ2TAxFtYPN7cnfIXnzjtatJcFrAW -----END CERTIFICATE----- test_cert.pem000066400000000000000000000036131470345337400434010ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIFZTCCA02gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDA4MjAyMDMwMzJaFw0yNTA4MjAyMDMwMzJa MBQxEjAQBgNVBAMMCXRlc3RfY2VydDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAK6dPxqG5IEaYDxTbvs7cn5KqWD6jaw3Neq7OG6XXfLZ6Vxu86iBGXmP pqeLJxR9iqRcE829ASjcWkRjkEKOgcjC/1pfkZtq6c1taURdcxZ9Yf7iv3dd/Goe gxnHawe+qzMS7OTxfQU6zkbTyezdSOpQt2VyNp+Si7GjTOr69xxF7VvPK5hEoPkW WiNyjk8WJGBLkxP3dAfMS5GptBB90gpYpAImRg3rGX9ZH8cygoxuNVslMrAzhMnC XYZNCCk3y+uG+Zzz5u6ULXB1lVogPTZGT3ME/hXJnBNy4Vr67l9HPKH7eH+2QsaA 5Dfv+NMSIBblrXNmW/aRUnCw92ls30dYrL83O3PoqHnYW/VJ+pw0GOYduo+Mc3ha 1A8+bCg1Um6izAE+lLeLYWSNpvE8/079L91bSrvgjvdt4F5bjst8WOATgWRgZYP/ yEw4Wu656wx9/wnFxbpeKib7KYYhjQX6T58EuWZZlffQgbUy/N7woZJlMBvFp+/r nID5gjy9Jl3howqEq8HMXY66mIe/k9UNoENAvda9wYcq9gatC+dxiTRM34TUB6FZ vCNW6n4CyPcDVxDMdITvw6hAbT3sAteIYShsfd56OV/nhGSBuEa+NGQef67MLePg 4gSvKzpZ8/+8BHzalE4xez3s1aT3li0+lbvFLScR/xZu3zKxN2NTAgMBAAGjgbYw gbMwMQYJYIZIAYb4QgENBCQWIlB1cHBldCBTZXJ2ZXIgSW50ZXJuYWwgQ2VydGlm aWNhdGUwHwYDVR0jBBgwFoAUk2TeKdivDs08TAlar2hU2fYmb50wHQYDVR0OBBYE FJtNdVeASKHLSqgdONDxiTA5pFxCMAwGA1UdEwEB/wQCMAAwIAYDVR0lAQH/BBYw FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDANBgkqhkiG9w0B AQsFAAOCAgEAIuCoOXZwsWTpWMfDnHQYUpl5rBDBv0fnVlJZJA/29y+u7Qyt2hNl sz0fKEqDSrN3S/IxZXUOMnWa6wxoCFM7KUOxDz6Oa6CZyuvV8/P3vIh5SnxssAu0 MRMcUObybogwRPsAmIUdFit2VicM0EqdRk/o8O/8aLCVDujaAevy5Ls2+WM0uOOA 7DIbkFxuVVOy2sFXH5ieegRK2P9uNmDjAEdb1bAQWBMFVdBiXggDZYUM5vzHry5w vk7rUSmJmgoIvDjMop/VGbVXhVCrYaimj+l9dgpDGcI5Nt+BtBJ/TIvGl1cSM6cx KIzl9Y/FPLLpMQmYw6j01PCupP8XGCFXRR+g5bhRjqDFIYuU0lodp8G4QeUpUdX0 dhOvjQqfQpFF9GeRNTD8K/LyL65oLuCfZhHhDD1k4vHxSK/XgMxXui3VUe9NtBCP t+cuM5HH3FvTHiKn1TFLoAMrj99De4JDJPSg0SXbPZEOXJwGxFZCAZOahC6l2xIB 6E/T6ngXMGhVTJSGKV8ACsO2XEW6TNpeqIKmF7ovLCGO6gcLxwMlEMtx0pskDzab HGgQ7mPoW4iYoS0tKpbAAz7q/Eq8f4XlodRFfzTckGGnF5VIrHlvX+euXbAa4oFZ V553R40ZjJZKHLCiSDZKD5MTBGPgkxYAbtlT2p4IWqU9ZfyRGubqDLo= -----END CERTIFICATE----- pems/000077500000000000000000000000001470345337400355675ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_testbad-subject-name-1.pem000066400000000000000000000010321470345337400415250ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIBUzCBvQIBADAUMRIwEAYDVQQDDAlzdXBlci9iYWQwgZ8wDQYJKoZIhvcNAQEB BQADgY0AMIGJAoGBANLmX2CG6mv5dQS3nzthRZ2NCRb8mZgUwM9otNR1Y7L2tPsu w++4C0pOAwxjX8Xt9gSoQtgf1DouPInvRV6//hi5Ccp77mY1ee3MhQd4SWLrNpM7 mJAtf/8qCuqR4XJjlQ+Os9sY6n5HC+48DU7tyOiqnyaoCPla8L6xVKKrzW8JAgMB AAGgADANBgkqhkiG9w0BAQsFAAOBgQDKR+92hZPwYr79noUK5RUIofuNQsA61ycU u7CoIhwyyDSKYzBIgd4VwAWae8dHzdWc0/pi1APg7l7FTGmzF8aggcSKmfgRjGVp 5DXFqidReWZiinhxKvk0Xa7dW8EIzEn3jrAD1HmwS6AiMsQ5qyFl7cCa7J6iUaPc 0qsAX1FwDQ== -----END CERTIFICATE REQUEST----- bad-subject-name-2.pem000066400000000000000000000010421470345337400415270ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIBWjCBxAIBADAbMRkwFwYDVQQDDBBub3QKZXZlbglraW5kDW9mMIGfMA0GCSqG SIb3DQEBAQUAA4GNADCBiQKBgQDS5l9ghupr+XUEt587YUWdjQkW/JmYFMDPaLTU dWOy9rT7LsPvuAtKTgMMY1/F7fYEqELYH9Q6LjyJ70Vev/4YuQnKe+5mNXntzIUH eEli6zaTO5iQLX//KgrqkeFyY5UPjrPbGOp+RwvuPA1O7cjoqp8mqAj5WvC+sVSi q81vCQIDAQABoAAwDQYJKoZIhvcNAQELBQADgYEAQFXWaKYI1ufzC4o4e7sm0y7o KTqW8g5aXWY6KQCJpmLMjUZbHLkEkFfWY7W9lNDjjR41DJEVsSS65YMk8TAyHHSj UrvneeCJXXv8d400Vk2tm0S3qXwmGOekCy+kjOJoyVJpkFFCDqqyaauYj/lPAB/5 7Yhf5i0LtJb/eyFGx9o= -----END CERTIFICATE REQUEST----- bad-subject-name-3.pem000066400000000000000000000010461470345337400415340ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIBXTCBxwIBADAeMRwwGgYDVQQDDBNoaWRkZW4ICAgICAhtZXNzYWdlMIGfMA0G CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDS5l9ghupr+XUEt587YUWdjQkW/JmYFMDP aLTUdWOy9rT7LsPvuAtKTgMMY1/F7fYEqELYH9Q6LjyJ70Vev/4YuQnKe+5mNXnt zIUHeEli6zaTO5iQLX//KgrqkeFyY5UPjrPbGOp+RwvuPA1O7cjoqp8mqAj5WvC+ sVSiq81vCQIDAQABoAAwDQYJKoZIhvcNAQELBQADgYEAxTq6zQWXBsGBSalA9YDM PjL1+bMRZhGbrKzNGGLd2HvLzk8V8OBUU5Mgv/FTsOrvvosFPIDwifdT2WZs2THT bo+Pt4hd8ACkXrAUB2AyDBRQrt9K8RpejI3UDr+yFWUkybmUgU1iX81EYb7K4KCw Qs/aD7/XEezYT6BiwBnktPU= -----END CERTIFICATE REQUEST----- bad-subject-name-wildcard.pem000066400000000000000000000010261470345337400431610ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIBUTCBuwIBADASMRAwDgYDVQQDDAdmb28qYmFyMIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQCcNsSxbXFNI/RzaBCoAFcZnYRtMstELzgf4rfOK9QNfamuzReN ewApICsSYn+lU2UTUR3zeg1j5QmjIn7JNioUlM7C/0VNXJlPjO23W2UqRzWK72b+ 8jkRuW2aPykzNufHO1DAGewoGZjLVFJNHa7s7DSaB4a71G4bvd3McGBFuwIDAQAB oAAwDQYJKoZIhvcNAQELBQADgYEAHymMy3A5mBd3lVbdwLU2zrddTtD/vkm5VVqh khTPoGQF/wBvk1PQjl3y5W8azOAJFX3OnzHj21DCCBChkNv3olZz5omkj9PM0MMp v7dOwtET7LA3PwBBRapv8vl76C99zVOHopNvn0AnoomAH6URC0eIY4XxzCDSOqMo ZbFKNhk= -----END CERTIFICATE REQUEST----- crl.pem000066400000000000000000000016761470345337400370640ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN X509 CRL----- MIICnDCBhQIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMTQwNDI5MjExNTI3WhcNMTkwNDI4MjExNTI4WjAiMCACAQQX DTE0MDQyOTIxMTUyOFowDDAKBgNVHRUEAwoBAaAOMAwwCgYDVR0UBAMCAQEwDQYJ KoZIhvcNAQEFBQADggIBAEHP3m5UA+lz1mjF2K+2jZ9bgZE15POftI9peXNILia3 AHE7OQtyxju/Mt/o5OpPW+0RJso9OrXhEE6T65BgOovBi1VkfxXILIui8n1oF1UK 9npunKXwgjP6Y8QbuaLv584QdwjfEFlFp/nJW5IQRKVIgsLsSGIBlZvmELiosR/W er3Ba7Cy/Y8cfMx0t/4QCU63l/Sr/8mgvp3P5RwhljN9ekp5Y3Yz4jdRycJsrq8J aQss8N4BrE/ppbvCdmf5UdkXgivd6cl04aSg1f25yYtEY12fyD8C8VySGOfZrnlh aOhJapWTuKVU/PxdCZfeL+RVufrRWBo4iJCRARKddDeqDWtI62pysjy/2PRvzMRW qudj9gJC3JnsWzvZqTGK6LNwDyH65Uc7cXjq+xxMgDpCYKZrpSmwlKUmpfnzZK/o ckJKFaQzXvF/RJF2Ai5W3HEl4CjRp5y2yqpORsl+FDVBl2hi5n7rCqJ4RibbdtTC pFFUP+na3zv0Z49uFLGQ/a/WHI2KuryMlDTkqltr9xncSpKafyT1UCciRdct3Q01 EWmuRcsawSg+nLB7VcLRgcnbbRuHJS2Pn2AZxYAg0SshGeZpl0zIiVzadb1/IY1d MlXJjO6RAj87/yUMC7/xC6IJh3sQymC1Yw8nYOGjnGiMCV68e5izd3eQTj8arTZj -----END X509 CRL----- csr-auth-extension.pem000066400000000000000000000031671470345337400420410ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIEjTCCAnUCAQIwHTEbMBkGA1UEAwwSY3NyLWF1dGgtZXh0ZW5zaW9uMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5vYnoJ85k6qcUFzWFOr9MN2ZWFlg A6nB0Adfm8Ygovg963NrauwTcoPqbfGhi53A8RWc5GT5x1OSjxQW/PAGGfGg3aHZ uQMClYWsauodCYG6YgG49WGZODCHZ+TbHMN1pNV+6S+tnZbUtfVKsN347XyHCyry mmb/OQNAxPyO/76dDR4dB7kWKP4KMMOgDAnA+WDpD1d9/UfBPVZtw/sTyjeJGEOZ qSXQW93PKumJ9/DS4azsUMR1JwJA67yWffoHb6sL7QSAQEfp17gDs9asIzITZPPy HNslmY55zaSWEslzFGqPvB7ugUbqH0rjp2TjQ/9Nw7ZKBxukFB9cBUr7v21D2Of2 SHQorzRe9lXOwO3BYEt/viypktDnH42qAeoLHDK1ay9ugByTm4ARj14CjslpkEKf lk9t9XwUR3kuUaj3w+Y5ItZXFBxns1OQpDt3bMhJFemj7MxkZXt8tvWlUMKVmCUq bnG1eDdTF4VdOovdacMDpvKg438I8MCjaHQf90qIp8MaOjdfSoKBCQi6AP7cpjB+ x9xhEuetPYcb/bNjV1OFo4h77XJ+lIH58HBpEG0zkqhtS7JqICIzp3GK7ZG3bhfK KJz0Qr4ISxI0YsYWdmsG38SyMwcomMy4WoLiuQF2QusBSHwBS+p5qQyNkJmXEy8K SQmrrIB/bkiSmgkCAwEAAaArMCkGCSqGSIb3DQEJDjEcMBowGAYLKwYBBAGCjEwB AwEECQwHQXV0aEV4dDANBgkqhkiG9w0BAQsFAAOCAgEAw+uZ2+5/9T0X1KbJ2oIQ WDn0lXOrNVKmUvXh19rhdZrOL+7KVeZ/GYy0V6ptZh2UwgDD6atdN51//U79jbKw 6DhqF5RbhlxEYaayO5X0VM5x6K/qw06w998gaQu7mp4apjOW7H5ibeCIBeMKnrkn GPMkIh3ZL2i3V4A5Vhz+w/ZZUCQnBR0OB9OE6PkgDdi8Ny9qoiazDZlp9IKzVlRl J1Lqhz2u/0993g+MksLoIs3ajllGfYF5rwatbqK4JY8VO1UPkJS+9a1GVWwrkjaQ DAEgUxhCAlyREtNMLtmUI4cm6GwjA7M41Z11rfn1xo6Mhq7dRqHhjcewzhZ60EVj oFDZXOJUS0q128+BnV1FBjTyxoqU9bdIwZwUpzS5bFiYilI1YDVEhUrm+4t5VWwY YqsezKh3z5cVbYOxW6JSBxmD6ZJNVW8ebSkn5xEv4fz1vnBS5UNRAoBYW03YSIW/ a0J6UvbT3gWRmN8zV50Ozi63ZAS7N7NZBdXVM8wAkvXV3ABgNZ0dJAqqgjixCAl2 NLa0jb+ZLWVhbu/10Q+qSHe258Co8D3B9TToTU4/xNRLUB9v5GbkubPypCps/SB3 Rz7UFX5C4xrYY+MD478ZmyEEB3GQdSCUjhRr6rI7n23r+2xX0msJQBk+IJ6CWtI3 BhdPuxnmZaMNfAs7hA8fGKM= -----END CERTIFICATE REQUEST----- foo-agent-csr.pem000066400000000000000000000017311470345337400407400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIICnjCCAYYCAQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAxMJZm9v LWFnZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApDlIep8eCrB2 sRqdpgvv240ZaXbU1+OK5rztyx/j1u0fDobpF/A9F0XMM0GU749iXIy9u1EX9u/q A0lCMPVWcTxh09NyOGSO8qWTSABaDts/Rk0Gsk+u3yGg5atnbUfmevcXqfU70nYm +3FaJjSgWsVhs/kF5bAGdVIefxJVtno7C7eE+SNGIY8s3t2/JA7KiCvwK4BOqK7h bs2hnBwFqsC9stMvLCck37LVK5uQiak+UdTAWOaPeSuF9sn/RwAhxVBxfCwuBvJv BRRq39speAYbgrMO9Ij3Uyyv/rPqQwC9UImD6QrLLv/CjQwtSFHhh1uxlkZESgFC 0h/W8Mz1qQIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAJ69nqjp/uY2Dc98xPZe ISB5eeyQ2+nYXIW6hYUdI5h1FEoiPlP3z/8rPZKHyDz4s1wqUo71SogudSDvbdCi yO2wPjksLE21GApb0h7wxwwZW3HTv4Dte2nyldD1QZ4y2vZVMT3SCkR99xgLEG6N btVcW2oxax728KtrWnJBi6ppUSl287fOsWXQuiw9h09JSW+2dE/86CpUybQfbdfx 1NMT3vuehIPYFNC0QplWEdOZwGcYoLbuTlEj7FGMJZhjgVTI53efuphV5S9DAOSd bOPBTZtFOCFAtpe2bZemgrmp6M+mtydQ07pu3XpyIAM4qVIOW4/WEwJ1hQOKZChj rgQ= -----END CERTIFICATE REQUEST----- host-with-ip-and-dns-altnames.pem000066400000000000000000000032231470345337400437520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIEoTCCAokCAQIwKDEmMCQGA1UEAwwdaG9zdC13aXRoLWlwLWFuZC1kbnMtYWx0 bmFtZXMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDm9iegnzmTqpxQ XNYU6v0w3ZlYWWADqcHQB1+bxiCi+D3rc2tq7BNyg+pt8aGLncDxFZzkZPnHU5KP FBb88AYZ8aDdodm5AwKVhaxq6h0JgbpiAbj1YZk4MIdn5Nscw3Wk1X7pL62dltS1 9Uqw3fjtfIcLKvKaZv85A0DE/I7/vp0NHh0HuRYo/goww6AMCcD5YOkPV339R8E9 Vm3D+xPKN4kYQ5mpJdBb3c8q6Yn38NLhrOxQxHUnAkDrvJZ9+gdvqwvtBIBAR+nX uAOz1qwjMhNk8/Ic2yWZjnnNpJYSyXMUao+8Hu6BRuofSuOnZOND/03DtkoHG6QU H1wFSvu/bUPY5/ZIdCivNF72Vc7A7cFgS3++LKmS0OcfjaoB6gscMrVrL26AHJOb gBGPXgKOyWmQQp+WT231fBRHeS5RqPfD5jki1lcUHGezU5CkO3dsyEkV6aPszGRl e3y29aVQwpWYJSpucbV4N1MXhV06i91pwwOm8qDjfwjwwKNodB/3Soinwxo6N19K goEJCLoA/tymMH7H3GES5609hxv9s2NXU4WjiHvtcn6UgfnwcGkQbTOSqG1Lsmog IjOncYrtkbduF8oonPRCvghLEjRixhZ2awbfxLIzByiYzLhaguK5AXZC6wFIfAFL 6nmpDI2QmZcTLwpJCausgH9uSJKaCQIDAQABoDQwMgYJKoZIhvcNAQkOMSUwIzAh BgNVHREEGjAYggZwdXBwZXSCCGhvc3RuYW1lhwTAqEVcMA0GCSqGSIb3DQEBCwUA A4ICAQC66yu2nH1Ye25sgimDtlC/XjL0RSR96wNpDxC8JqMRb0ruZPe+mPBieqlF UXSoIYZQ5Lwtrx/YvhhzN7fWaFrITENk0ZJt0NJPN3Yvp4d3HTjnRgMunDh9X5Fx kFIxvnCT+CB/9zfCTEmEHEkETapp5VHbbN4+07CmMMqae0kqvyLvGVmYQ0YeszLA k2JAO3rsARG2axbwEaZIObbts3KZ5lePm5q1olmTPj9EoaTk1DtLgOJVWreXKyOR yFy8pL+bET77h0yhLU72eNWHhRjgoLJhC4qQZLZ15lk7UvRKc/d0QA2Qa8XGS1vE WqxyTZpL1A1nzTJ6rG5b61eSFq2hCOwYPKXXZVq0Lnw1sUbRPad24WjPRvWlvjZ3 OnJAGTXRp5mI5EpnhfHUvkOHR8UCQvRF6Pdy40flRqfqRdPQmGMdAcYesaQyEqbj dYfGbcBKbKE0Jj/khZh5V07rwcGIhIhHbZiwpcJgBnaCA318cKMyg1D/vo3Ruc5q zj+RE8hp+HF80fpVrAlsbxQWxVqMDxh39Vs0gYziZQzj50+oA95Z7UE5xIQPq4dj GZNJHmt0kT98sSN9ReC4voCwYcBFx1WBP6SpbSYmjdHjq3KMjal1NmFSsO60XqlQ nfNkSuLulOX4RpXx5rUOFXywvLeRmWgziCRux9Qbbbbs92BnMA== -----END CERTIFICATE REQUEST----- hostwithaltnames.pem000066400000000000000000000032071470345337400416720ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIEmjCCAoICAQAwGzEZMBcGA1UEAwwQaG9zdHdpdGhhbHRuYW1lczCCAiIwDQYJ KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKgUzmEZkPmZ0/NWU98HWrcav8pwaVRe jxORdl6FrhFl266IlPimVT30xSmRoc8qBiKgmil8akalVkHyWOHmsX04DwBijNC/ do5BbAsgj0FG0Qj7CzCzqqWuVMWZ0BnComGXM0+PhEfftwvBQc6LzTktjWmzJG58 HeY6T/PQk2sXqmMd+skVWatN+63CWNmxRM9OndX7CoBhdRA0DSYsr7bUmHVCx/R1 D0LxVCdC0jdQSNhrInXx2USRHyqGPLdsV0MtPhBM0nTYK0uATCVIMNb4FJfzntcv Agsj+sjN0kAfzyIk2PyBVrvnV9rfFZN1fpbXIg0Lpr+qcAo9xC9qJn0luepR6xVh /wfQvZevwwOz0K49y9jZrQBg+Y+JEIRSmnMcqV7mChuPSrld/IvkxbQPDZLAXVzB dKj4gT+NXSGdDR7u7hneXkeoSlgGuV33bBMn4BoMmNU24/VrjyvIfaKvHGZYp3XP xRlZFQ1YlYU+kfFtonhGRxTMslhTwTTOdmyQHQrvRueTNG9MZ/XIbrs+Y3PLGtWY 9iyAhFFopYe0X1r/ajWGPXJOvVhWOfiLvyPGKAaxCvnOD2EiDF6C1Wc6FdPtdUHM RCLwTqDfkX0wAFw8PiDJqFzFAWlJzRkoXcQxItS/t0i8qjkHKZPvpfwu4qD9FV2Q kifSNQY12n0PAgMBAAGgOjA4BgkqhkiG9w0BCQ4xKzApMCcGA1UdEQQgMB6CCGFs dG5hbWUxgghhbHRuYW1lMoIIYWx0bmFtZTMwDQYJKoZIhvcNAQEFBQADggIBAAnK GrD+ZRNpHJ28CBnqoPaV8obbI1IkzN2dvNHpnSsLxAlbICS1XQTuhsQtSX8ROHtQ cgRqVwmM6sr3AxvSl6BQAEdyHJ//fdQ50Wzrd7cMrgGVSW+Bl5m5nR95upCDTe4N SSbg6xl5UJ/K7M7gJFgHNgJTRqRPnHl6CCRVI8BHh22l/AjHk05KNb9ddR9Z8azc gCPw2exG16swwaZgKrHCihTvKl00oun/5QhvsBVM9RWnFVMW1iPs+mLyyFyVXB/1 uh+vRJ5tQynda00LCc6VOq/ZlWh+ue2KcVERijdRyhTyP/9ljWfWGZSNkQqW+oL6 J64AvvaDUnDcmCvrMVH+lpJyVoHHI4XGHMBPgT6uACRtH5f7UHr8ik7nMcWb/AbV AipsLqbI3UVuGgeoDR4ULoNETOjd9UBGdtIJC2lozeDT5Br4IfHFCzrat6A8TUI1 z7pFonP0W60IELPCNePlcd+lbrMIdLBr+s1IzPbJ3DvT8EJwUUs0sbOM+gnhIWfW cI0Qz+iLu9qH4IuGDq/JvoaqFwwRRjYjFFn6i/4FEkp8OIyACzGcTdt0L4EwevZX Eo6EsG8euPXTylkiA+F5F1PsGw8ZGR0LowO4dxVYMflt35IXsYjtnBQbaht6oP8S LNa26jDNcvCf/F0F1DIagsbJJoEQx8XDzG7chtZv -----END CERTIFICATE REQUEST----- localhost-cert.pem000066400000000000000000000037311470345337400412210ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE----- MIIFnjCCA4agAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDAyMTQxODA5MDdaFw0xOTAyMTQxODA5MDda MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBALzn4xcbGhSX65fgSIo+NB4EOYX+zJxbHamv+hbQkhAxqHxUSszDD86+ s9ZsN8cvpDIRex1/SfkNRKhgVUHGiUYbol+9RLpgpdHYLJCY0S0kOyBUgWqEcQrA tVDYpwaNC5qMneiZkcNvQ74pnuFOa0/bzbpLyOjYKEQq3BXK32yGLLHseb/PIX1o bqcuYiR6yI7S3wK9hJzSo6BRPSz0cNZNpnXbW/yLRtHbthBtzTifM2MW2jtWuFvg OW1ly9vxwTHCrJv5KxMubVDrqAx+RmmOsn327APO3r6NUr2CzV1vG8CMqLApse6m dKpCZ5UNLm4dwCUe2zWAQ0Q2Eba88O480bH8k/t8NUGXlWt25B8BUE8rklY0jwSw v8Dyjda0moeoxgMMZb+ogPjTY/Ds/h2hgFzy/DUuGrv6kyVxzH0/pOg29HeDoUaK IaqjAsN8h/oYTJ6CiOKAqWfbi8JZRmiEVTekskS5eySsPqPCegfAkfpIlz4EU4FN 0A2vORI7epW4mNiJcCLb09v5jogK+DhfeSscDsrYgIF8eAPLw6r9h1am+vXoD6vt tIwZBu15pnCWXdDcKWBNjx+zYU648iZ9V/qFG31uTJaw0z18eFPyTcJN8StTnoGZ zjKI2AyjG5F6ov/S7mnU3I/wv0B5Vq6fPjSvMrsBlbBdI3Pbr3w/AgMBAAGjge8w gewwNQYJYIZIAYb4QgENBChQdXBwZXQgUnVieS9PcGVuU1NMIEludGVybmFsIENl cnRpZmljYXRlMFQGA1UdEQRNMEuCG2Rqcm9vbWJhLnZwbi5wdXBwZXRsYWJzLm5l dIIJbG9jYWxob3N0ggZwdXBwZXSCGXB1cHBldC52cG4ucHVwcGV0bGFicy5uZXQw DgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcD AjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRZy3D0vQGiBu3mnggq8jiEZERoXzAN BgkqhkiG9w0BAQsFAAOCAgEAJwDAK7UKZvLtSJkdprO/Z0qALdUSliO0+I6lsSr/ A8SyilfMQuxOoq6uWA6j7uMU4SAHwT14QD9c6BJJiBhWLo6HoynZfYK8Smn1q2Xy vNMnUEUEjcWIgIqEDP98RTUZldgR4aWQkQVHB9XY8g6F0qWzBq64qLWjfrsIUijF Z3Ex1OMU7ZMjHhoKk2J3oBcMau47mqU49C9MoWkBH+0fLLr+lxoa40DPcFr+KzhI BHdTKuKAEJEkiE5QNVWl3+M7psFZzdTd+YFz9Vn/9L3aQr8KCb4oMietp84KM0yR 6GwodvIjh/3owsnvNvl28HeZGWQMCNIlG0aWx3JIfCOHSYlXfQ55FCtLRqMflJty M4MqRkPHKykZMZmNoiTtXRSz3vMW8JnIyZPsNtfIGltnpjHd4Y4EEVxdZhlL2wBv YycI6PN1oyhv/9ZcIbSaVY4jEpxx6mrsG8iuaT1YHlO2HOwuqvXJ48WkT1Q6go9k A775N00y4jLJXqWchiuP9Hp7AGYWzoKXFDmQbUyl0jpZsrfoTskb90xp6R7+IO7K 6opzTahhO9QeURqc7lkdvwjiYMw7uIiTT6IAKtYeK4f52siiJ/LBWucte5FLCjvq KkdWF7aQOKZq+L7Cs2nJ/qQQzlDYTQLpAbBWJbVAscoYYGPVPdKrwI4UEbKGIsWs wMA= -----END CERTIFICATE----- luke.madstop.com-bad-public-key.pem000066400000000000000000000005531470345337400442460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIHVMIGAAgEAMBsxGTAXBgNVBAMMEGx1a2UubWFkc3RvcC5jb20wXDANBgkqhkiG 9w0BAQEFAANLADBIAkEAowXc8bSQDvflUcH6/sddPHh3xPxXWorNyuYbLsQTql44 xk4XlRtx5ghTOIDCkPoezkQy7UUbiDlCTQuCvKF3iwIDAQABoAAwDQYJKoZIhvcN AQELBQADQQCWw/BnnOnuPbfPO28qoNjgZOXV4w6cxfiMW3n5cvQ8N4w8g+IpAjxB VlB5LoyIOWk4S4PFHou5n1r92sYTQfME -----END CERTIFICATE REQUEST----- meow-bad-extension.pem000066400000000000000000000031631470345337400420020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIEijCCAnICAQAwDzENMAsGA1UEAwwEbWVvdzCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAL23VOzktmj9I5xDcT77Jx6E48bYf/Asd5Z+biTugWLgurO7 2IgS1T+4E25hr0O+PgnOGxt9Tgs6kWdi/lKJjPEciTZ7P+sBo7I25sCDOvSUrdP1 7YMAvu9SFdrotSTo0rseZDhxndJvyk/9f43VwUEDIAHQSxAU/Ovfj/IXQaSCSi3L LgWAYAmdFd4F7GaUYVS4E9MmTc+R5lSjOS95wyF/n/RevGFgKv1aiWc0JPkTxAm4 OCM0zb3ikyhs+pYBamKDApEZVgYYuXn9Eq+XO3KLB+E4oyJUlpd7YSDK+3KsWIH2 oC4TlDgULp69JBgh3WyRHhCgCwqAR3gVgX51eTE7w6Q84QTTG+ejXuRbzZALdZ+q Rd2Dacd3nnmf2MOPhnodoGDd3qD0LcfGAZDYy5o1Q84+uofuTifnlqcPBukogWiQ iq/rGTGyVWXF9138AlJDmRwdOX2kS4VwMjWl47dQX8PWBEHoioWv1XKclKY4omFI +tx0J9/2eMTda6mnqnH5t6lmI4ZgSXwq2goEctPFSNW2NenDDzm5zb7wm73IA3Im jIbkZbWd8fms/KYzuFgfQYRO0+gQNeaW8hgSstJaJ02x+fWOZTDyzIgoamvNfGi+ 1ozXWoGv/HwF4bq8hqZTMW4TTTQ81Ypw3yY1M8pwx46gJ6rP7Z+olC3xr/rnAgMB AAGgNjA0BgkqhkiG9w0BCQ4xJzAlMCMGBjEJCQkJCQQZdGhpc19zaG91bGRfYmVf ZGlzYWxsb3dlZDANBgkqhkiG9w0BAQsFAAOCAgEAtABuOOHLMl5wP7pjLhaQMJ2U EDPGIXP28m/tl6PLQQXrl2o9uJnJA74wwSK7fvxbSQI85KmxXYZr0fk7mmbpeIe0 HLewF3Q6xCHPpIhrSyWzjbu1S/xkqoAaQ6FZtvhHnlNPwFrzkuYO08HgcsmwxEGk vbJ+yZ0EcB1Z3SC0MuWMjPFsMj4GTQOwQTb4sDfTlDlHfGnBCv7m4q/OniSCmuTE 8yWDnlvbb9bph660TmcPNaGo2aTWYf5JYZTf+ScrXItMWFyrNJuPqPAxZLfsX0vN 5j16ng4OUyDbkYZuOYdRY9sROn8Weg1nUKwXcGWcsw727dMbzrGa6Wv0QJ5tOi58 nIXbZTgm5GxBvXRdqrRW0ofJjy+KV2XPxAPewJHTik/SbT5ccgD4ljLgzTgJqXrf F71q2awVF0HETq7UgdeJJZ3wne2uMwwhL8m2cLAoqhlOKDz4/lPMlQSnyuezoglR +P/n2wsutYKLr6HKIvFP7UKZRA9oigkQWcMsRB5jwMk0vyZQoyoGkvacCPqdZifd kf6OMe6rzndr3+/Nwwgx3hJk8R/daW3Mic4gzTcgKJ2JGuVLekMReFlM/g3KvCrX ma24qPEAcw5/ryj7GTjRsrqmL3gqkHgdW2g1y2L99EOaldfu56f/JFZw+aOOC/BH CdXdbI2Ff7usKKxnqsc= -----END CERTIFICATE REQUEST----- woof-bad-extensions.pem000066400000000000000000000032541470345337400421710ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/pems-----BEGIN CERTIFICATE REQUEST----- MIIEtDCCApwCAQAwDzENMAsGA1UEAwwEd29vZjCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAKtTu3FKOJ2XihVtg0mFdrZWkHwqKoZb1RrPNjILZ4FOpWOG 2U9zAJ1CivuE2RXH/THk5xHN4kMq0OXFEUtnCMeZIpFDN40XyEEN0nzNSepB9VcI mCCOcsWrs3HRF7dXxEY2SwxnMMQPd0UutLpMJ5IftHscTuB6i8veoXlLdvix7n81 7U4zNFuluSwJ4d0CvQTejrnf0HGEXO2bTeMrPcMVs68f2jbKVrGHdcrwHSn0P4DY fhOSNEFIlATzgjpT2vICNIchu14oue9PuVVvT4GijA/r3v/H8mhoBGqjg4rNIv/V RHBTxtmXHtGqRIfTtK8VFAw1fAg+XpCc9fpFf1rp3vOveRRTjGm90yrEM1v3zHx9 Q1j9ybM4QJaqo1nHlzj1hEdyhMh1VxWBHu3JTaS4u+av5gVbN12XbnUSFqMdas1Y HXmuLzDLNCv8w6Y2C43DVDiLfFKNYjTAK6upXZQ9KJ/JufWoXNdjHX3FEgFxuvZZ 9vc7j+kD9oV6coFupYW4nvc5jleUeuug4C8scHoJDTnQFHlRA9FRgVPeTT2Bc3Dy +q/VVdkiQP3KPO/obvMKX6scfYTj53CTrJTsm95GhdN506KiNBx60s0LVlWrUxzT 5MGFOr1VfHUS1LmYthpIXc1HEgtKT6xcmOILWcGNhSKTMEtaRgACbJ21VselAgMB AAGgYDBeBgkqhkiG9w0BCQ4xUTBPMCMGBjEJCQkJAAQZdGhpc19zaG91bGRfYmVf ZGlzYWxsb3dlZDAoBgYxCQkJCQEEHnRoaXNfc2hvdWxkX2Fsc29fYmVfZGlzYWxs b3dlZDANBgkqhkiG9w0BAQsFAAOCAgEAJ6auglYd8SvjTvd0K7EM01GpEGjheB19 NwWnYDoHCL2fDX3EXJdbb8WmmMn674jiwfLatf/n5rzpBIY4wyM6FvKsNwV+T78m /Fzz1e81ibA2waQeBGnPVRbUZ2kjX595KAvixfFuEfEZDnw85EalhqchMuKBOV5t JE+0/hSOuWm4soIh+kszljpNvZrCpwUxO5FfkwJCxkl2SQiJnaP6Jp9p19SEZ4Fc 0EIAxRMZBCLagQ4mOM7MoEaxIgURcg/rP+t/7E+aTk6y/kVX2AJ4+r2EFtz98+OZ u6O4zxt8JiLYTKtazplTiH4lxiVcjq1pE6TAQT4rvAzv/XNVS8U1kL199dtxcdX2 3bXaZ87D5VQvaDgRJierVQfQS1+tvSXdjvFbwzGxYqjZ1HgLSyQ5467DsjFmrJg6 gXmbalAE0E/Phkff0XaSugrOruyfu/iG6rpLhwJza4nm1pfzgKW2zCEs7X9D59B0 HNVFD9ac+sbGqlIh+iGgiU6SBlPcvOjQE5sZOEJ3IpOukVVLyhXjq25rdc68h7Mh WEDXZq048yJvRJq4v6vf0riWSt2ATHicYZs4TFBM/DT8PnNkACgEPaokk4hjlvDH ZREM+a7Ds0q7HySSy4nhBw/7I7lwr/6rZqVxuOwV8GoPMHid/o1wUp+JJ8/ENxeK fKCUoXJL5Ww= -----END CERTIFICATE REQUEST----- update_crls/000077500000000000000000000000001470345337400371305ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_testca_crl.pem000066400000000000000000000022521470345337400410570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/update_crls-----BEGIN X509 CRL----- MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 ZSBDQSAxFw0yMTA1MTMxNzEwMjlaFw0yNjA1MTMxNzEwMjlaoC8wLTAfBgNVHSME GDAWgBQl9rvh0XacxLAt5gBaLUhtGxByWjAKBgNVHRQEAwIBADANBgkqhkiG9w0B AQsFAAOCAQEALkpYMTwasy0PT6IROnlfIihY1oRwUS+yz/9E7Gh85nHe2oXkRO7g 1h4+DSBEOGuPXqp69Fr2xkSSK3vEx3hgOl3Zz1d3BkRkGeR67cTWzTZoCY0II4WN /Tk3SJ/5uxzOsIiwrG+WPufdL1HdJEJ0amq2Jn4Ri7lnuzY2UD7+FNleGDeK6qxg 1XqKYBz4o+0+wh4/HQKfc5qdnANZyzyLFmtwaxY1IXEsYcwke+6GX+sdL+x+4bBM NlLZh6ApQ9wcIDbuHXV9SsgV+FR1DzpDqLOiu8ur4qalgna9sv984VHPbhqC7Mcz 4TTTYwLvjGZQgobxv+FVtWPy3xQULooqOA== -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQCQ hCaMUIuL4R25bXhpI9oNBAMvi96bCGDwtphRmk2Vm1QAwe9lTK4Ebf3tvPIMi7hz 5cSntni1855BBc7qNCJXs1UsQtCfnBW7LKpSFLLQvTkzXJN3xo+hc1y42j2Pa85Y ZDuu61vx28M/AhCe/qGyYMRk66wwwuU9ACxn8sOzvfhG7Fn3c4+xlNws+Mp6CrvD 9+b/GONkqogDSPie2FM4Rbbc7e3luFhzD0HhJ7MZKkaO5vaaeTaUvH+UQYxlumS/ Qxtjj4KdaWVBr+++b0EqLFC1oFL895j8UWYQ7Orkt3Wlm+x/b30WsuNmRJKqjLYm 4YCAH34bvjD7Tgre9fBp -----END X509 CRL----- ca_crt.pem000066400000000000000000000043161470345337400410720ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/update_crls-----BEGIN CERTIFICATE----- MIIDGzCCAgOgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 IENBMB4XDTIxMDUxMjE3MTAyOVoXDTI2MDUxMzE3MTAyOVowHDEaMBgGA1UEAwwR SW50ZXJtZWRpYXRlIENBIDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQC/oc9oNhOuqHm4gCrPJLRbEjVdel0LUtgyd4ECCO2Qj7Li1xdN0y0GJkeJQvL1 LdFeLu/QD73wBzYQhZMyN81crtNBiTcjtyRY+C60luhRJP+8CdppeVn400fiqmVK TOEk0Q3mb6jwyBZPgS4K46bZb1YX+HBcp0I5CRHT0epEXjkAOLl+Bym8xpQ1dhw7 AxQhrSG04QJeJZvUHSpyy5bH25HsAG3jdjdT2y3LiKBAyMptH0AHkXhDIHvOZ8Ry rPQsxAnUKOq5UcNPY+JdvhsOBVDmbIVmvkkAb8vy0+aK96U+zDJFnoYMs9K+jlKK t0SnJw37WAaTwGYeOd/mdeT3AgMBAAGjcjBwMC4GA1UdIwQnMCWhIKQeMBwxGjAY BgNVBAMMEUludGVybWVkaWF0ZSBDQSAxggEBMB0GA1UdDgQWBBQl9rvh0XacxLAt 5gBaLUhtGxByWjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkq hkiG9w0BAQsFAAOCAQEAQk7Z8sC6sSrb0yJGZ7ij77iUqLujvZOUSGZMdNBUZu34 zzGJ6+70Tro3Yvw6Q7PlEhmvF8vpbOxFpZL6Rh34+O41c8FOIgwcOjABvjS61jkG hJagK38J+AdKBE7lVGJudttW6JrCHsPncHMia6iiTQz6QcHjDrE2FJ3L1Cy8zm0m U8zo8hAGqQlEuAacMff606JtBcLSVpgYTfp5BixmkpmK56rBc5vPtE2N9tdJci5U +GEmvBeQaO28JPqSKaBQ4rEaudBETl1E7mQy7TklFpeXqPxSuu38m8iMy55aunYN dZzhmfmk4DbT8TDduHO5P8xrfuhdBpkri7KWyCaU0g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v dCBDQTAeFw0yMTA1MTIxNzEwMjdaFw0yNjA1MTMxNzEwMjdaMBIxEDAOBgNVBAMM B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVnTfyQPtV f2moAdKhS7e7PI9vabK3xR39SEz0LVrHfF4kgy61iNNjkghbuDgHgDZnIPsiMBE7 HpGutRpp7AnkDX+uSpY9VOY369zGLxl/6YenNLMfZ69Q7aHCPIpWkoC+mMzU2j2n PR0FwZf633n7gB4pwlplY5Z4fhIwKGSYqlmFVC6h/f1DYQ0jfYsdVYIMct5NShfo phUvrzVSB6SPHU5Q6Z6bGGofy93ptr89cs6r2WiwXsN9tcshFJsHAzj3wpLVzT6K YZthi3K3myYPL3B8Kw9dQ+ShtHU3NiH413s1YbPfgvtCYGNc07EGfYA66nZuncJh mdtkcEzET7ibAgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv b3QgQ0GCAgKaMB0GA1UdDgQWBBSAHOzSNiXrK3J8u8ofAdn8whLXuzAPBgNVHRMB Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAc4KU gHhl2394zOrW3/rPNbQbjb3aKTvl5wK2E9rQFlCGe7X9NuMCdKAmThkBf3+i3625 ddaJavO2VJc0JPb2mxhPwEbx2O9wa9eTZ8uhhmEE56B8h1CDafklbC3KEvfl2W0h 9HskkQ6yJrJ48kJgaZu8T3H0fQq4quhI1ACzEfYBOTvhlm0Se2JHdHJF1m5YVlgI 5UbuitqL6911+khJ4veFWwkjRjKzPJQZoqoc2bKJHx2p2ufod2FXGc+trNe5AkTB f2uyNSkPEkfz2SaNYVQA+bisgTfNuNYXOVRW2Gc9K4XKqH0p6u1QgfUOa44YTtaA TVB93iVXQ7UgTbSXLg== -----END CERTIFICATE----- multiple_newest_root_crls.pem000066400000000000000000000022321470345337400451400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/update_crls-----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEKMA0GCSqGSIb3DQEBCwUAA4IBAQBH oMkgd9OWEENL65+C/ZOOIMCuNQp8yakvHr37vWj4v2rs0P4GlEKECghaf67WIpBS 3IB20IZpvFbETg79HcIUkrO02dTy2OUPdLpzEfSCvkxMl2/IofSyirGQycQcH+tg LRGlsDFQJFPFNs6/rr56t5ztYx/OaareJkHmvhwSd5w4O4Rimzxjx/UVQfnJ3Tju 1D7he3ueC0JbbWg7dA74d02akiXLLQVwqsDLgW3R1+RTyxPjn9LqrvlOfhYihD/3 NcWjMEU7+T3XN21Q3hhsBCipuBBQJdS5TWlVEFRX44IM6ykEsJFvLZbVZVJPYTej WkeaCQRskegBikdaMipH -----END X509 CRL----- -----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIx MDUxMzE3MTAzMFoXDTI2MDUxMzE3MTAzMFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEKMA0GCSqGSIb3DQEBCwUAA4IBAQA/ xc3Wlh4dlg1ICxynOsLSisEzDTQfhiT0FjnKpE7Cz3ZcR8VrKuEs+jvixSanIooZ 8e4+NnLXIX9xq1Pzz5wI0YBCmVkUpJGyNOYGjpY5R1VJzVtB1YRaJRf3lyCYz1jd fnv6Glidw5zHykoYHwHBbU0A2pWX14+LvQKC3aNQ5m0UGzg6QCSa83oiVVI2Gftf jwIhHQHHyrcKo2nTX3tBo2jYuD+cqxVndbBPO5B//XQOmF+p6nTygOR65P0yMrV7 gXzOpuPZEWx4lhHEmw+xP5w5b74EQ02Opy5HV1n0G3ZgMFnfJP5VHDG0a4fXhuNe N4L9YpQHT8XbLdm12ZcW -----END X509 CRL----- new_root_crl.pem000066400000000000000000000011151470345337400423250ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/ca/certificate_authority_core_test/update_crls-----BEGIN X509 CRL----- MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx MDUxMzE3MTAyOFoXDTI2MDUxMzE3MTAyOFqgLzAtMB8GA1UdIwQYMBaAFIAc7NI2 Jesrcny7yh8B2fzCEte7MAoGA1UdFAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAn j87vWjd9qr9BZq2rf92Ku/owQlAJTHwIPAKmmUyzMF+Aw0P2nlF7FPDiOaXXGm9x KWwstCaefp4jbru+pD5cH/UFSCyLBuUlfzqtMvF4SL7/CjGZa4W3WW4a+fqlv/HI U8Wxjqa00LBV77rqJm54z2QUlqgCPD/7r2Pqy5rrfrZTGGy58727whtSsV5sAWOw kxzRogsSm23Uh4//lmEx0BYJYTaz+HdWaEckpJU1S3DfBBrh5Rv2AG/OjsRfUvgC tB0SGdKL0EM8KG4GxbeXTvq8HuTKUp2HaWvGWpdojyxqwwiAtNaOHt76qpBkRe3f igWihATMaKzytX4xXk1C -----END X509 CRL----- puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/000077500000000000000000000000001470345337400322505ustar00rootroot00000000000000certificate_authority_int_test/000077500000000000000000000000001470345337400404745ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authorityca_true_test/000077500000000000000000000000001470345337400431555ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_testmaster/000077500000000000000000000000001470345337400444505ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_testconf/000077500000000000000000000000001470345337400453755ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/masterca/000077500000000000000000000000001470345337400457605ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/confca_crl.pem000066400000000000000000000016761470345337400477200ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ca-----BEGIN X509 CRL----- MIICnDCBhQIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMTQwNDI5MjExNTI3WhcNMTkwNDI4MjExNTI4WjAiMCACAQQX DTE0MDQyOTIxMTUyOFowDDAKBgNVHRUEAwoBAaAOMAwwCgYDVR0UBAMCAQEwDQYJ KoZIhvcNAQEFBQADggIBAEHP3m5UA+lz1mjF2K+2jZ9bgZE15POftI9peXNILia3 AHE7OQtyxju/Mt/o5OpPW+0RJso9OrXhEE6T65BgOovBi1VkfxXILIui8n1oF1UK 9npunKXwgjP6Y8QbuaLv584QdwjfEFlFp/nJW5IQRKVIgsLsSGIBlZvmELiosR/W er3Ba7Cy/Y8cfMx0t/4QCU63l/Sr/8mgvp3P5RwhljN9ekp5Y3Yz4jdRycJsrq8J aQss8N4BrE/ppbvCdmf5UdkXgivd6cl04aSg1f25yYtEY12fyD8C8VySGOfZrnlh aOhJapWTuKVU/PxdCZfeL+RVufrRWBo4iJCRARKddDeqDWtI62pysjy/2PRvzMRW qudj9gJC3JnsWzvZqTGK6LNwDyH65Uc7cXjq+xxMgDpCYKZrpSmwlKUmpfnzZK/o ckJKFaQzXvF/RJF2Ai5W3HEl4CjRp5y2yqpORsl+FDVBl2hi5n7rCqJ4RibbdtTC pFFUP+na3zv0Z49uFLGQ/a/WHI2KuryMlDTkqltr9xncSpKafyT1UCciRdct3Q01 EWmuRcsawSg+nLB7VcLRgcnbbRuHJS2Pn2AZxYAg0SshGeZpl0zIiVzadb1/IY1d MlXJjO6RAj87/yUMC7/xC6IJh3sQymC1Yw8nYOGjnGiMCV68e5izd3eQTj8arTZj -----END X509 CRL----- ca_crt.pem000066400000000000000000000035061470345337400477220ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ca-----BEGIN CERTIFICATE----- MIIFMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDAyMTQxODA5MDdaFw0xOTAyMTQxODA5MDda MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogbG9jYWxob3N0MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA5vYnoJ85k6qcUFzWFOr9MN2ZWFlgA6nB0Adfm8Yg ovg963NrauwTcoPqbfGhi53A8RWc5GT5x1OSjxQW/PAGGfGg3aHZuQMClYWsauod CYG6YgG49WGZODCHZ+TbHMN1pNV+6S+tnZbUtfVKsN347XyHCyrymmb/OQNAxPyO /76dDR4dB7kWKP4KMMOgDAnA+WDpD1d9/UfBPVZtw/sTyjeJGEOZqSXQW93PKumJ 9/DS4azsUMR1JwJA67yWffoHb6sL7QSAQEfp17gDs9asIzITZPPyHNslmY55zaSW EslzFGqPvB7ugUbqH0rjp2TjQ/9Nw7ZKBxukFB9cBUr7v21D2Of2SHQorzRe9lXO wO3BYEt/viypktDnH42qAeoLHDK1ay9ugByTm4ARj14CjslpkEKflk9t9XwUR3ku Uaj3w+Y5ItZXFBxns1OQpDt3bMhJFemj7MxkZXt8tvWlUMKVmCUqbnG1eDdTF4Vd OovdacMDpvKg438I8MCjaHQf90qIp8MaOjdfSoKBCQi6AP7cpjB+x9xhEuetPYcb /bNjV1OFo4h77XJ+lIH58HBpEG0zkqhtS7JqICIzp3GK7ZG3bhfKKJz0Qr4ISxI0 YsYWdmsG38SyMwcomMy4WoLiuQF2QusBSHwBS+p5qQyNkJmXEy8KSQmrrIB/bkiS mgkCAwEAAaN5MHcwNQYJYIZIAYb4QgENBChQdXBwZXQgUnVieS9PcGVuU1NMIElu dGVybmFsIENlcnRpZmljYXRlMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD AQH/MB0GA1UdDgQWBBRZy3D0vQGiBu3mnggq8jiEZERoXzANBgkqhkiG9w0BAQsF AAOCAgEAZHcyah146g2vmuQZsGJtljCkWjM1WWjcPoLewdd4FG1YKkAgbGGPVnSS yIS04tj4/Z3eePUlBNe3ZHs7yTQkq3SwWIhRSMJRA8xAjtL0rL7mvJ6PMV+Sujb7 +ENTML76+oq1d7XTqAh8mnSJOIc6eMUQqBBYl/5BYa4IzkvkrS4ai4vg0ihKr6pf C8XVINTjxChqK08dEr690sPD/3DwPPVGqG+qIyIv6u5buVLniLWiaq4HOG54i/yH k21W6A5UizRxb5GwVxWfjsHcLr2pvPq/ipRP/sCNBgKdziaGQm+IqeJiI6bQegx3 ZF5UX2CaIkZsEM0v2yQ7/t9rSCfpd/eEYMdcWcnSfEf/OOA/ti7jnpapENXturLo 6/TNJarHYQlkpEsaRfiiSmomAn3TNOOuqBhWtj0fdy21/fETxVVzPp/CL7EvkUnU 26SguZdBkGf22yZViKRq22eDnM/frsoSMTkIbkayDQ8Hx9JVpfPmdJWQyL86etsd uCR5OXJtd7vxRZT15m2cFvdpRW3VZbqFyIwe0NgJUs3FRrjFZdqQiBsvWwQjK8jN A3+IAAz4pk0A4xpQvNwvUzo4wyQB8/PTcmZoPBzeDaJScqSto2r3kvOSqvm1PSc6 gneGkbPvQpQRH9HVxzaEEcCrcZYFZXpCkF0ACuB+smgfMVY2Sno= -----END CERTIFICATE----- ca_key.pem000066400000000000000000000062571470345337400477300ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ca-----BEGIN RSA PRIVATE KEY----- MIIJKgIBAAKCAgEA5vYnoJ85k6qcUFzWFOr9MN2ZWFlgA6nB0Adfm8Ygovg963Nr auwTcoPqbfGhi53A8RWc5GT5x1OSjxQW/PAGGfGg3aHZuQMClYWsauodCYG6YgG4 9WGZODCHZ+TbHMN1pNV+6S+tnZbUtfVKsN347XyHCyrymmb/OQNAxPyO/76dDR4d B7kWKP4KMMOgDAnA+WDpD1d9/UfBPVZtw/sTyjeJGEOZqSXQW93PKumJ9/DS4azs UMR1JwJA67yWffoHb6sL7QSAQEfp17gDs9asIzITZPPyHNslmY55zaSWEslzFGqP vB7ugUbqH0rjp2TjQ/9Nw7ZKBxukFB9cBUr7v21D2Of2SHQorzRe9lXOwO3BYEt/ viypktDnH42qAeoLHDK1ay9ugByTm4ARj14CjslpkEKflk9t9XwUR3kuUaj3w+Y5 ItZXFBxns1OQpDt3bMhJFemj7MxkZXt8tvWlUMKVmCUqbnG1eDdTF4VdOovdacMD pvKg438I8MCjaHQf90qIp8MaOjdfSoKBCQi6AP7cpjB+x9xhEuetPYcb/bNjV1OF o4h77XJ+lIH58HBpEG0zkqhtS7JqICIzp3GK7ZG3bhfKKJz0Qr4ISxI0YsYWdmsG 38SyMwcomMy4WoLiuQF2QusBSHwBS+p5qQyNkJmXEy8KSQmrrIB/bkiSmgkCAwEA AQKCAgEAxLphcLiPo49MjEs3cyPiPJBVAONIHHaphtfxAU/XFtnabEao9a9WtVFW CwYpszHRWckuFYFJHRa7nLHhDtwoZkrh2kb1nFjLB6+P+JWn3CQrLTYIZMMYbrsv aziNxsda2uebrWaWPMhwMPlaAKNiWG+c289eTFR1CwwRTHlQGNk1DypaUey+ynXx Gi5XkklwnTqF6jJ9N5O6LtQCtU+VQMbjOM7EAUcbXlTmFMhOY+o2xlG0DOv6Whra T7IYgf/J+703cFFIKPjYX433YWT2xRfvWytLTHcCZPTuHVMXHbOIGZjXC8dRIr7T x4nTtg8CYjYB+DW6gqlxrk4z5LJFEd/zVlauBTxIIUcYTZeyM5Ssl6fUMBgyt9f5 ULfsxrahNEzeduco+1Ga5IgzIIXM3tZqQKdgZYwltauSBaMp0aagYVCdV0Y6+a5P QKNHkW7PoqyU+VwegDUDYOIxjw0S2C0m4VVzvRws3f1Xvtrq/rxNpt1wO/UcJZYY Qit1IHCJwCHaaW2R1mDBz4HenHAYdtoxBzwzDcECKoNHYyMoBRUTQx9MB8eKgQuH Y22bh2squJAqm7ubTP/Ek8KkY7BIWA6o3WKWfI8V0V0ar7siLv2GCAJzyuBFlIPO n2cmqONZdBlWlgTObTi0PzncGnWk/4HXinMkR2WjwvtQ3MF+xv0CggEBAPO3Ahbb NnLW9OsaiuUpbcpF1IhMIwoaaXo70GlqL7FpHbrKGb4CnKjBZlUnKjwvggfsl7JW hkwxL0P8vKItgEm9Uc8B5W1CRUZtysHCvuc5ROYJhBxwX2pWIcpMMu02WtD6wpp9 xb9WymnEA8ztgepSMHrDohLlXXWWC8FqCekAx8LJ9K8yVaJU1CKq2ZZw65aMca2B WPLh+nX3YL8UIAbwUfJDs9V0xE0UhQFni8yv+8Gu8jicL7+Oj0OyCM1QXC1t+96I 2hw9qnsBFeCT3Xkft5U8LNumQhWG+Ij2asUpzYaC4iDXWkX3b04NrH7VnwPsnRUj JcHTqx05WgYh1esCggEBAPKakpi3MHal/vykmzT+OLvB5HrXTQaZhoV2lORzxtnR tygwfkWtRbsMeKF3xpeuS5mZcdOIfHjJhY5qCZ3qYA1BOVN+pwMzAuFToLJO8MA4 /pF1sDODkzylSdy3kfBsCdCJFG54fwB+6HS553C48RBknAj7ctC3vKwod+YvAEIm VQDvQ16MuGvuiZma4PbbFf3QoJr9yonfBFCEmAy1c4ElviKROgHLY8NluiBJNyYJ MrQnD4HBvlmCzGAGn6uWyzvmJs0t4nSv7xeRL2qaWiFORkc1CSclqiPYuZWoQ6nY ayKO97hFpdABEPfQLHpG1fWzEC0IMfzyHDg8TmOZTtsCggEBAJ8ksvWP4cctvLLF G0u3ON0rqjPyW7MeOiA6bMZZM5mKxYIStKqR9BBycctLDtZMQ4G/KfOncnzQZUfl Apx4T9xXBtPBLjqhWrE5wnuyGozMpcP9FMqpSnUal2gNR/gEVVs/U9IkLPvbxcM4 3y5zLTGAx+1yUCQ8qEG/YB/FiYEgJFF7JQ8+NBMTh463t+v4Aq7FOPoOi7HWhIGB ryg3EQ7W4Pvs38KURBb9PjkDj5Nym1gHUF5NBxT0F3MiD4NaZUa5Gg5fmOV2ExvN Qqbqh2Wvo2aM69HmiCKchzCQkHn86Rtb3iOJ3IXxpDn4zdnozrR2TsDduasO+B7W M4XrlE8CggEBAJlV1T4s2rbDKCzqpSaTX6xcWlrB5e877ehBEM5r1s0pXchLDiRf 5ejZcw0rNRv9j87fSzBV3cZCKOXgY3+p+VenV+JL9KdzAGkGgFTyy/vSiiPJ7LpC eTcliU+1vsnknzdszLsd8beQfr/4GC4I1mR0EqMiumjtGJT/ZvjX0CP/Mk7K6xvB eXbOZ63sVC/yPS4VRM1xhygpCwMRK0EtFnoULt6OR8mGkeGYVFG/tNmXirKO1aA/ ol3U6/Pte9HqFz4es3uPesghws50dzG7qSfP3192R/i0N5s8id/rYAjjvqMzFaMk ci7L3bujmdkXGHiY2qp7uYyUQf3RMAKHjW0CggEAIUQmr1L4Z08JkFrAECdyroVL YLL+SED97h2aQ+Xs1QpU7R8TxbGYJZI5wvUTGfXNcFf5EaEyWvYc2PCtIhvkaVFZ O7rkSLbB46Ou57VufK9LnHAhAxLatYCA52ykTJGvEI+VGu4vTcXSBuQnR1Xc6jOa CrmIUQRrdg9VBCse1WFWVOj4PbCFVEI/aow264E16C5jvQCr/bZSnz/PIW2FMkIr WRlbE5B98oWsxKmVgTFpP7FOHOT+Pww4/i2p+8Wy9JFocUMAKE+sQf2NNA/6Lfk4 X9YLExKoFomNFRHVoelW5/qtr5Rx/z+XFMuMhRnH09MJhnpwe4886Sw83bITZQ== -----END RSA PRIVATE KEY----- ca_pub.pem000066400000000000000000000014401470345337400477130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ca-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5vYnoJ85k6qcUFzWFOr9 MN2ZWFlgA6nB0Adfm8Ygovg963NrauwTcoPqbfGhi53A8RWc5GT5x1OSjxQW/PAG GfGg3aHZuQMClYWsauodCYG6YgG49WGZODCHZ+TbHMN1pNV+6S+tnZbUtfVKsN34 7XyHCyrymmb/OQNAxPyO/76dDR4dB7kWKP4KMMOgDAnA+WDpD1d9/UfBPVZtw/sT yjeJGEOZqSXQW93PKumJ9/DS4azsUMR1JwJA67yWffoHb6sL7QSAQEfp17gDs9as IzITZPPyHNslmY55zaSWEslzFGqPvB7ugUbqH0rjp2TjQ/9Nw7ZKBxukFB9cBUr7 v21D2Of2SHQorzRe9lXOwO3BYEt/viypktDnH42qAeoLHDK1ay9ugByTm4ARj14C jslpkEKflk9t9XwUR3kuUaj3w+Y5ItZXFBxns1OQpDt3bMhJFemj7MxkZXt8tvWl UMKVmCUqbnG1eDdTF4VdOovdacMDpvKg438I8MCjaHQf90qIp8MaOjdfSoKBCQi6 AP7cpjB+x9xhEuetPYcb/bNjV1OFo4h77XJ+lIH58HBpEG0zkqhtS7JqICIzp3GK 7ZG3bhfKKJz0Qr4ISxI0YsYWdmsG38SyMwcomMy4WoLiuQF2QusBSHwBS+p5qQyN kJmXEy8KSQmrrIB/bkiSmgkCAwEAAQ== -----END PUBLIC KEY----- infra_crl.pem000066400000000000000000000000001470345337400504100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/cainfra_inventory.txt000066400000000000000000000000001470345337400517230ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/cainfra_serials000066400000000000000000000000001470345337400505120ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/cainventory.txt000066400000000000000000000003241470345337400505550ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ca0x0001 2014-10-07T18:03:58UTC 2019-10-07T18:03:58UTC /CN=Puppet CA: localhost 0x0002 2014-10-07T18:03:59UTC 2019-10-07T18:03:59UTC /CN=localhost 0x0005 2021-06-07T18:23:14UTC 2026-06-07T18:23:14UTC /CN=localhost serial000066400000000000000000000000041470345337400471540ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ca0006signed/000077500000000000000000000000001470345337400472315ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/calocalhost.pem000066400000000000000000000031671470345337400517330ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIEmjCCAoKgAwIBAgIBBTANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMTA2MDcxODIzMTRaFw0yNjA2MDcxODIzMTRa MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAIZ+iQ/jM9Xln2zcQL/uYuZ14yLdwt4HfyAC63bkx1lkrrBoQce0EY8n F4ymPG9jWefmt0PqYQNJNNBrJaV2kkOYCld34UY2XyOrQhgph9o3rx1E0CjjPG8N kDFFq7lFklxdLAtUMVqN2HmYnaonjlPU04nCpAy/STWB/C2F42QRODB2IvFjfRjh 7ap4HhOPUMv9TNVxrmpTn2LX0x85WSNUEu6OUlduNr0WJR1830NZF4AsAWbTIXel ofxlMkaWCGWhxUNLujxVwC3gc7AanQeQsx7RoFFTG3ffVPNMjwMkqu5BQNZWqqzm 8ppyxF3qf7Gqs0hRhl74ZpNi827ppn8CAwEAAaOB6zCB6DAxBglghkgBhvhCAQ0E JBYiUHVwcGV0IFNlcnZlciBJbnRlcm5hbCBDZXJ0aWZpY2F0ZTAfBgNVHSMEGDAW gBRZy3D0vQGiBu3mnggq8jiEZERoXzAdBgNVHQ4EFgQUxLxAxglZf9o3qOGw+sng qddHBzswFQYLKwYBBAGCjEwBAycEBgwEdHJ1ZTAcBgNVHREEFTATggZwdXBwZXSC CWxvY2FsaG9zdDAMBgNVHRMBAf8EAjAAMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMB BggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBADTh /FU6sTXZpdNeZXijqz82X3lKnvqgg9NOo/5R9u9PjBNZy6ttc+HzIyQA4jBlsGpC ckbU2+CMqnW/kEi2T0FRAkgREe2fkDZ0zH8ADByZT/h5t9pcAgKsLCfi+WpS8ZnS holEO7vpGILWLAp8ZLWNqXlcd+g86q7hYEEukWcOGxsPbrLjlGGyDaG89Nfx6Lvj fgGoKabuCOzqyJS7W4X9sh9w6M+OEswkMUWHbV4uEflqhlseUn9mjlFPVr4hDG4e 0Jlt4vXjilzjvz5xjfW0W4uYj4bHgSWrCrE0yIY54IhK1zFA3KnFSacU+7/Zx9Tx NLRi4k4wEhDcGaNqAdE2m2LpVcYLapbLDL+rZg8HWGKNq/mX32ReuAgRDK8VLUAC gTqoUbxLvwZh0vPoPaIRsqXwKNYE/nXPTPJtQF+3jLLAHaSxbnjv83NhK9J3G/WD N8hTa9OvoiZy5/ap3CkaHSnfzLsdYOkrj2lxZFDGQANBrwYCPOVYvVSb/l8Riznj ByMQZACTR60PW5t9HdWkGQqgj+wQmImbV5io0rrV+Gf9p+XeSZDCAa5pN7WvcI9x sGLBpmEwiht3wWyRTFyKJQ0NujKvBHiGuKajRivp06JMX3+gFkwFIUZvb3oSpd2L OwnHyOu64yt8PP/jaOEXe32yX18S8/EfCUpkKsVN -----END CERTIFICATE----- puppet.conf000066400000000000000000000000601470345337400475550ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf[main] certname = localhost cadir = $confdir/ca ssl/000077500000000000000000000000001470345337400461765ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/confcerts/000077500000000000000000000000001470345337400473165ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/sslca.pem000066400000000000000000000035061470345337400504100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ssl/certs-----BEGIN CERTIFICATE----- MIIFMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDAyMTQxODA5MDdaFw0xOTAyMTQxODA5MDda MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogbG9jYWxob3N0MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA5vYnoJ85k6qcUFzWFOr9MN2ZWFlgA6nB0Adfm8Yg ovg963NrauwTcoPqbfGhi53A8RWc5GT5x1OSjxQW/PAGGfGg3aHZuQMClYWsauod CYG6YgG49WGZODCHZ+TbHMN1pNV+6S+tnZbUtfVKsN347XyHCyrymmb/OQNAxPyO /76dDR4dB7kWKP4KMMOgDAnA+WDpD1d9/UfBPVZtw/sTyjeJGEOZqSXQW93PKumJ 9/DS4azsUMR1JwJA67yWffoHb6sL7QSAQEfp17gDs9asIzITZPPyHNslmY55zaSW EslzFGqPvB7ugUbqH0rjp2TjQ/9Nw7ZKBxukFB9cBUr7v21D2Of2SHQorzRe9lXO wO3BYEt/viypktDnH42qAeoLHDK1ay9ugByTm4ARj14CjslpkEKflk9t9XwUR3ku Uaj3w+Y5ItZXFBxns1OQpDt3bMhJFemj7MxkZXt8tvWlUMKVmCUqbnG1eDdTF4Vd OovdacMDpvKg438I8MCjaHQf90qIp8MaOjdfSoKBCQi6AP7cpjB+x9xhEuetPYcb /bNjV1OFo4h77XJ+lIH58HBpEG0zkqhtS7JqICIzp3GK7ZG3bhfKKJz0Qr4ISxI0 YsYWdmsG38SyMwcomMy4WoLiuQF2QusBSHwBS+p5qQyNkJmXEy8KSQmrrIB/bkiS mgkCAwEAAaN5MHcwNQYJYIZIAYb4QgENBChQdXBwZXQgUnVieS9PcGVuU1NMIElu dGVybmFsIENlcnRpZmljYXRlMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD AQH/MB0GA1UdDgQWBBRZy3D0vQGiBu3mnggq8jiEZERoXzANBgkqhkiG9w0BAQsF AAOCAgEAZHcyah146g2vmuQZsGJtljCkWjM1WWjcPoLewdd4FG1YKkAgbGGPVnSS yIS04tj4/Z3eePUlBNe3ZHs7yTQkq3SwWIhRSMJRA8xAjtL0rL7mvJ6PMV+Sujb7 +ENTML76+oq1d7XTqAh8mnSJOIc6eMUQqBBYl/5BYa4IzkvkrS4ai4vg0ihKr6pf C8XVINTjxChqK08dEr690sPD/3DwPPVGqG+qIyIv6u5buVLniLWiaq4HOG54i/yH k21W6A5UizRxb5GwVxWfjsHcLr2pvPq/ipRP/sCNBgKdziaGQm+IqeJiI6bQegx3 ZF5UX2CaIkZsEM0v2yQ7/t9rSCfpd/eEYMdcWcnSfEf/OOA/ti7jnpapENXturLo 6/TNJarHYQlkpEsaRfiiSmomAn3TNOOuqBhWtj0fdy21/fETxVVzPp/CL7EvkUnU 26SguZdBkGf22yZViKRq22eDnM/frsoSMTkIbkayDQ8Hx9JVpfPmdJWQyL86etsd uCR5OXJtd7vxRZT15m2cFvdpRW3VZbqFyIwe0NgJUs3FRrjFZdqQiBsvWwQjK8jN A3+IAAz4pk0A4xpQvNwvUzo4wyQB8/PTcmZoPBzeDaJScqSto2r3kvOSqvm1PSc6 gneGkbPvQpQRH9HVxzaEEcCrcZYFZXpCkF0ACuB+smgfMVY2Sno= -----END CERTIFICATE----- localhost.pem000066400000000000000000000031671470345337400520200ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ssl/certs-----BEGIN CERTIFICATE----- MIIEmjCCAoKgAwIBAgIBBTANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMTA2MDcxODIzMTRaFw0yNjA2MDcxODIzMTRa MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAIZ+iQ/jM9Xln2zcQL/uYuZ14yLdwt4HfyAC63bkx1lkrrBoQce0EY8n F4ymPG9jWefmt0PqYQNJNNBrJaV2kkOYCld34UY2XyOrQhgph9o3rx1E0CjjPG8N kDFFq7lFklxdLAtUMVqN2HmYnaonjlPU04nCpAy/STWB/C2F42QRODB2IvFjfRjh 7ap4HhOPUMv9TNVxrmpTn2LX0x85WSNUEu6OUlduNr0WJR1830NZF4AsAWbTIXel ofxlMkaWCGWhxUNLujxVwC3gc7AanQeQsx7RoFFTG3ffVPNMjwMkqu5BQNZWqqzm 8ppyxF3qf7Gqs0hRhl74ZpNi827ppn8CAwEAAaOB6zCB6DAxBglghkgBhvhCAQ0E JBYiUHVwcGV0IFNlcnZlciBJbnRlcm5hbCBDZXJ0aWZpY2F0ZTAfBgNVHSMEGDAW gBRZy3D0vQGiBu3mnggq8jiEZERoXzAdBgNVHQ4EFgQUxLxAxglZf9o3qOGw+sng qddHBzswFQYLKwYBBAGCjEwBAycEBgwEdHJ1ZTAcBgNVHREEFTATggZwdXBwZXSC CWxvY2FsaG9zdDAMBgNVHRMBAf8EAjAAMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMB BggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBADTh /FU6sTXZpdNeZXijqz82X3lKnvqgg9NOo/5R9u9PjBNZy6ttc+HzIyQA4jBlsGpC ckbU2+CMqnW/kEi2T0FRAkgREe2fkDZ0zH8ADByZT/h5t9pcAgKsLCfi+WpS8ZnS holEO7vpGILWLAp8ZLWNqXlcd+g86q7hYEEukWcOGxsPbrLjlGGyDaG89Nfx6Lvj fgGoKabuCOzqyJS7W4X9sh9w6M+OEswkMUWHbV4uEflqhlseUn9mjlFPVr4hDG4e 0Jlt4vXjilzjvz5xjfW0W4uYj4bHgSWrCrE0yIY54IhK1zFA3KnFSacU+7/Zx9Tx NLRi4k4wEhDcGaNqAdE2m2LpVcYLapbLDL+rZg8HWGKNq/mX32ReuAgRDK8VLUAC gTqoUbxLvwZh0vPoPaIRsqXwKNYE/nXPTPJtQF+3jLLAHaSxbnjv83NhK9J3G/WD N8hTa9OvoiZy5/ap3CkaHSnfzLsdYOkrj2lxZFDGQANBrwYCPOVYvVSb/l8Riznj ByMQZACTR60PW5t9HdWkGQqgj+wQmImbV5io0rrV+Gf9p+XeSZDCAa5pN7WvcI9x sGLBpmEwiht3wWyRTFyKJQ0NujKvBHiGuKajRivp06JMX3+gFkwFIUZvb3oSpd2L OwnHyOu64yt8PP/jaOEXe32yX18S8/EfCUpkKsVN -----END CERTIFICATE----- crl.pem000066400000000000000000000016761470345337400474730ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ssl-----BEGIN X509 CRL----- MIICnDCBhQIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMTQwNDI5MjExNTI3WhcNMTkwNDI4MjExNTI4WjAiMCACAQQX DTE0MDQyOTIxMTUyOFowDDAKBgNVHRUEAwoBAaAOMAwwCgYDVR0UBAMCAQEwDQYJ KoZIhvcNAQEFBQADggIBAEHP3m5UA+lz1mjF2K+2jZ9bgZE15POftI9peXNILia3 AHE7OQtyxju/Mt/o5OpPW+0RJso9OrXhEE6T65BgOovBi1VkfxXILIui8n1oF1UK 9npunKXwgjP6Y8QbuaLv584QdwjfEFlFp/nJW5IQRKVIgsLsSGIBlZvmELiosR/W er3Ba7Cy/Y8cfMx0t/4QCU63l/Sr/8mgvp3P5RwhljN9ekp5Y3Yz4jdRycJsrq8J aQss8N4BrE/ppbvCdmf5UdkXgivd6cl04aSg1f25yYtEY12fyD8C8VySGOfZrnlh aOhJapWTuKVU/PxdCZfeL+RVufrRWBo4iJCRARKddDeqDWtI62pysjy/2PRvzMRW qudj9gJC3JnsWzvZqTGK6LNwDyH65Uc7cXjq+xxMgDpCYKZrpSmwlKUmpfnzZK/o ckJKFaQzXvF/RJF2Ai5W3HEl4CjRp5y2yqpORsl+FDVBl2hi5n7rCqJ4RibbdtTC pFFUP+na3zv0Z49uFLGQ/a/WHI2KuryMlDTkqltr9xncSpKafyT1UCciRdct3Q01 EWmuRcsawSg+nLB7VcLRgcnbbRuHJS2Pn2AZxYAg0SshGeZpl0zIiVzadb1/IY1d MlXJjO6RAj87/yUMC7/xC6IJh3sQymC1Yw8nYOGjnGiMCV68e5izd3eQTj8arTZj -----END X509 CRL----- private_keys/000077500000000000000000000000001470345337400507035ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/sslprivate_keys/localhost.pem000066400000000000000000000032171470345337400534010ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ssl-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAhn6JD+Mz1eWfbNxAv+5i5nXjIt3C3gd/IALrduTHWWSusGhB x7QRjycXjKY8b2NZ5+a3Q+phA0k00GslpXaSQ5gKV3fhRjZfI6tCGCmH2jevHUTQ KOM8bw2QMUWruUWSXF0sC1QxWo3YeZidqieOU9TTicKkDL9JNYH8LYXjZBE4MHYi 8WN9GOHtqngeE49Qy/1M1XGualOfYtfTHzlZI1QS7o5SV242vRYlHXzfQ1kXgCwB ZtMhd6Wh/GUyRpYIZaHFQ0u6PFXALeBzsBqdB5CzHtGgUVMbd99U80yPAySq7kFA 1laqrObymnLEXep/saqzSFGGXvhmk2LzbummfwIDAQABAoIBAQCBePqVUtGpzj2l XHrwyZpn5YDdJcLcXzcgJ+9pK2BFTElnBVad21k0CBwBiF6RlIEOX+p49P6jXSv8 n8lD+ltfutPp1DwHjXwVKF6eSAzCI+zuLjp9whOBjPsMk9d2qeT2CbPGzCwe0oJc vHC7Rw0a4r0p1zh6FQNzAUk0wblfsFYi/FZNGb8b95Dbib0bso06xweQwgYanCmN KBaVBy9R8leJIVajEiffA5p/8Vh3ur++pDjMdwFcb9IMfW9XAmYRH1sRoAvyZInT KUKiLQQLqKBNanVV84obYEC2Fz6yYo6zN9Qw3ex0TuT+tg/qhPxjMfCpiLE+a/fq h86UZoXRAoGBAMRraQGqn3DcXW35FKtJi8M5SDglKXGLXcHGsI+mMRiWlo1a1pJT o01wnd/cssxKvFWbrfosSVowErducJwoxRW6O8e1l5LUuSa21W/4aMs/DIfK294y t6lGv/mVovcRv2fnH/PvCUrb90WwKcv+8vXl0QOu/bMutYC0t+c2WuWVAoGBAK9K bxXs3xZhvXk+rM0AiNH46VnEhgyZGAwKd6OzV56HjlMkWtaAOxYn5VflXr8T9uGF TIS9Dw7mcbCZ62qsSG9ANnEMO//KrrQ7FQWJpji/pLhho7NU51tw06wjD7j3SlSf eFUOgdnlIUV8cnIGw+V3je/9E4ovoasH/Bd1vC7DAoGBAJ6SjILA6dmmvnLjTRF/ 3aqtWyWgstWtCvM+4hoGtMpCAKd795DInyUMzxgEyABwMZ33gjxfdpSuDN4z9gvM SlhhMpPngcgTnqqnnqa36Hp1mzshxeGcFnQ93wyzBo7qsBlFGaHIkDr0XKvRLd04 JZPphpWvt7fp9LREsdejJT0FAoGAfSNEPoDFmjLYku/daNRS2KM742vazq+UbTQj yOfFS1U2k8BGYQ9WHzEIF0GV7A8SllkVEUXutBJrY0neuF6Zr2JF+1piku9c3Sm4 jiWAVs7phv+dX+7i43KeiirVlJRlqhfWTdJ3fNiIchSvlxuhSfWZjJQ9GM98OJ8Q pqbUWwUCgYBNT+N28jyEQp2QwWlY0WlUd+BT2F+TAN42oKVOrNExrZ3nEH/WlzmR ckjbLIHYUIIZZDjpxd6jg1EMh7ZY6XrJ8wSGoHvLvvYmphAo7IFbOwJMK+3Kljno yzqzHEfb5Zp6V9HnEyLFQuBIwbmNl1VmmrZAy7nUvi3QVfL7DNvCog== -----END RSA PRIVATE KEY----- public_keys/000077500000000000000000000000001470345337400505075ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/sslpublic_keys/localhost.pem000066400000000000000000000007031470345337400532020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/ca_true_test/master/conf/ssl-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhn6JD+Mz1eWfbNxAv+5i 5nXjIt3C3gd/IALrduTHWWSusGhBx7QRjycXjKY8b2NZ5+a3Q+phA0k00GslpXaS Q5gKV3fhRjZfI6tCGCmH2jevHUTQKOM8bw2QMUWruUWSXF0sC1QxWo3YeZidqieO U9TTicKkDL9JNYH8LYXjZBE4MHYi8WN9GOHtqngeE49Qy/1M1XGualOfYtfTHzlZ I1QS7o5SV242vRYlHXzfQ1kXgCwBZtMhd6Wh/GUyRpYIZaHFQ0u6PFXALeBzsBqd B5CzHtGgUVMbd99U80yPAySq7kFA1laqrObymnLEXep/saqzSFGGXvhmk2Lzbumm fwIDAQAB -----END PUBLIC KEY----- infracrl_test/000077500000000000000000000000001470345337400433335ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_testmaster/000077500000000000000000000000001470345337400446265ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_testconf/000077500000000000000000000000001470345337400455535ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/masterca/000077500000000000000000000000001470345337400461365ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/confca_crl.pem000066400000000000000000000036051470345337400500700ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca-----BEGIN X509 CRL----- MIICmTCBggIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMTgwOTI2MTk0MTMzWhcNMzMwOTIzMTk0MTM0WqAvMC0wHwYD VR0jBBgwFoAUwK9O427mYrXHygZOn5juGJ4/t04wCgYDVR0UBAMCAQAwDQYJKoZI hvcNAQELBQADggIBAE0DCTGA9InyroOVZUwYLihptu6/tfe8Qca4iURgzNe4LmtV 2fY5ycmHe09vd/1V/dxdZw9sdMMaCPPa9HiJItTlq7sUGl/VfXGSgYiyjKjNlRQ+ sN6Gn6MdaaztS9fj8ssy8CPTQtimrQ6ahxFOietFH1j5HekdY/kXlUtF8gveL42h eQNHbpYpAkfbjFYFq5nimdkRkuUrdtymcAbUqejQOsTB2CZVrn7e9/8aLOxC3pME CSbf/xAQPLMtrQeyCGxUApEDZdIStjIgj/OcerAaSRoWxSI3gZeBT7fy6rHnrPnj Tow3R7M7rqVcniJQVsr03fww6hWcM4s45Z2PVq7WEtYEWcbuTdsUTYch+L/bzvqK a3Xxa4JTNBclrj8kTnkgkuSOqB9IAL/sUYjIb/tzxkzLVj/2/pGRdepyn6ghbAl1 m9ON5N32hlTAJ7HNLPSJpXC2I3/bC3yAQQhYkPK7xfA7Mzwa5XVr96qyrQ93HwtK 4KtMi44gLUEDd0bMwx1kAXrB0rFVPFJ0PYtwxBmnSi+KYHG1KzYB81iMIAbfwMqZ hFg7GAgzi5JcrPOQFeQTKy9ulxta9D9wbl0hzpmphlg26yBwIFuu+7B/eL/doyI6 /AO48ln7TfNPUJdrxHuvLLz3+aLW7qMQl1yGI+ZurT5UamZK/5cfWYvo0pPN -----END X509 CRL----- -----BEGIN X509 CRL----- MIICozCBjAIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBwZXQgUm9v dCBDQTogZmM0NmI3NWUxNDE2NTYXDTE4MDkyNjE5NDEzM1oXDTMzMDkyMzE5NDEz NFqgLzAtMB8GA1UdIwQYMBaAFGKC2FP12m4ICilEGK3LEuwqB0yGMAoGA1UdFAQD AgEAMA0GCSqGSIb3DQEBCwUAA4ICAQBnxOyL5fQcVYpsKsZrUSURl/0xDBgGs7BG JD+Ak0Sa/XX1K9x0ebAHkxY5d/DFDoK6ZVOvveeASHZaUfLRSMfAFx7qzgemwK2r U/CFilr3RHbwBza5xHioil9XYFFpJd7hLfhGenHKy3r9Zar1u6MjQ0bxJojkzeIq rphZAc2NHv1lfp/bOi2+qxyqqBEKh644RxZts8aY93OkLcQnrYNQm4mWVfMnMyW4 Gfn6Cc3vYL4crGf2Cn3LOsbaidRywbMlef4wcJFZFEYtAk7iVEqDxFiZVikguVid A9YYRqNScPtbWAI5iqkDxHN6hLGAu/siZYa2lKX3kz44uVShF698/UVikj6ok1O1 317XMo2TQZ5DRoTI6OtqL7kGVFPiSHgj92Jmn9p9BB8DyfG0f6RUVn8hC4W14BaQ EslzzjKju9FLSaMWikmG/lmZ1lVY7ezaR5QXQBhVmjbTD/I2IdJUEgKZkS9A0Wmj wlJObZnHyIi7sezcIzuvRdZYlAZwf5p7XXT73vm9lX6Yj9XQl21dYjlJZ2+Fqv4x IThlbZ9qs7jaMFFO+ZkFtkYUPeA9rX6nKK7FPogA5AgTRa9hHl0UCdYg94KRnIpR 1dON5Ojfm61y9pkmCmND8EUQHzERapwAK86PHp+7zcSp//VKlIrepxs5DiidLPLA 71pTMi9UVA== -----END X509 CRL----- ca_crt.pem000066400000000000000000000074121470345337400501000ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca-----BEGIN CERTIFICATE----- MIIFWzCCA0OgAwIBAgIBAjANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBw ZXQgUm9vdCBDQTogZmM0NmI3NWUxNDE2NTYwHhcNMTgwOTI2MTk0MTMzWhcNMzMw OTIzMTk0MTM0WjAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6IGxvY2FsaG9zdDCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMym9J8hxM3zx2YXbi5glnGR773c d8pUdbbOCaCTQB8OXYX7q9wO4FlMoG5K+j/rRCGBwhAWr5hKZUFmcFmC56PC6O72 7WOSwnQjf1XepC26PkL5EEbprCGpygC+gK4gSqpGaocN0TKBS+PGbQPPzcAC/7UK Xdk0D72TtzLNOrzQy1GSUj78H4uo9OjNfHyH3EO0NDcTZyhYzlBdc40zcBgq/jYe wKoe9Dc9YdJxeQi0RD7LaMTtXE4cehG8YgySNwI82+ylO/w1w7HQZmvqgdYRd+hc 5dXzcLMAN2rGaJtidDdN+sTdktZ4GZCxggywocavpu6kHvJiRWqXnFw38S3aVpIF 1OOtuxQ1aoWlujDjJCVyp212wg4CnyYcR47Q4KCUX1qw3/uILHFJYdN2vpFKU5S3 MkwfLLpMSpf60Tgt3hjvNPrGs6dzSasS9Flg52B22zzKsoIAYNWRZZnY9BvGWvIJ 6s8tvUIUIkEQdxmTazaQgVa8KPrwZoM/b0jUuChvfeUVbnR51iAO9GKzKnSe+b1p iRQJ3WU+y/okxubuKbvynGPDl7ykcRbtMuxf+rd4csAiyxBhNRv1dsRu7nbhxVYU cwP5inu4I9Yd0O0tC/X7BIAfQZrjt3XCfGu2JaENgA7jXYNKgQT+g18bnF1u612q u5weeZgx/saAsz8vAgMBAAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAQYwHQYDVR0OBBYEFMCvTuNu5mK1x8oGTp+Y7hieP7dOMDEGCWCGSAGG +EIBDQQkFiJQdXBwZXQgU2VydmVyIEludGVybmFsIENlcnRpZmljYXRlMB8GA1Ud IwQYMBaAFGKC2FP12m4ICilEGK3LEuwqB0yGMA0GCSqGSIb3DQEBCwUAA4ICAQBU 8sBkMapmL/Fno3WFIf/YFpG/fwC0VCN7cjvllNQjF4wM66sdMxianqe7VNsBuAfi fsoR2kCv/+4iKSUXbBgvmGpmCja+1dFXXyPF6C4wvYSD2NuUa0rItBIp4tR1a72P ZG721VFJCCgd3SDcgpabeXm3M/OspVCXdCmqNMro/nOAJc8P2tYaU7dwrPDCqHfE TCEWlyNrYNTADDfZMmjuXrkT45TugqZSe8/EJfogywpnCQkHjYAWXfCJ0pjBBENJ 2T3aPXv0bD9Sixz8R92CrBWz9ZOd4UuLs1eXlt6TkVYmTr+uK9KM+famSdFO9269 xC4ZZ8JuPrn83ClNau6Kmqer1azMalgKXa+WO7ksPM1AvUuPdMNd3CGsNjpzk1PB vO9kU2uVHovR3HnKG+vmbvYeoFMQfsJ+ObKDsK06z7BeSlUv0Z4uYFMqJyozLbgw JpDHoQ2ijFsVLQQnXnYxEUFUM3DuSeiSo/ky/XQaCGGGIdSfQFy4aegwZ59bSXZf da93fUUhcAmHCOUlLNnmAW91GIMz9QBYY/U9+Pb39OMgnf0Ja9+ouJnaW1IPn42k XgegE2Hd4M8NnKTKM10muPuahMsQCOpyU4wlXiBKAZo4EBFH57jPgmyT6xx8L9OS yQcfx6OgnJPZNb3bA4wlu22EPGHvMAdZXSWwcFjmqg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFZTCCA02gAwIBAgIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBw ZXQgUm9vdCBDQTogZmM0NmI3NWUxNDE2NTYwHhcNMTgwOTI2MTk0MTMzWhcNMzMw OTIzMTk0MTM0WjApMScwJQYDVQQDDB5QdXBwZXQgUm9vdCBDQTogZmM0NmI3NWUx NDE2NTYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCXcDX4pt2H5u3H nPsf5bXm+gY46yI1u0Na4cx3hPJQ9Tw9Qa0qfy1amdJunQkfyIkpc50XyJlXRflA imfj9eQ2c9WklNbSjfumTcmPqdq0KIVBHNPh6vbKDTCzl+aVIjUzRKVweS5d4ODG 2M8QPNbN/aq8oQa8hFN0XJVB3eNqviLVaAzYdJVf4vk0uZXUnUwVkoeWu/RsM7sa 7+P5+0bCKkRKU2W0xZPYn7G2mvNZ3+M1GEYy7g75jQGY4zf/bFljN/RU1fM5JsZo C3oxKHOR4L6zhiuBdCFHfocWpBf+CUT9VYTNgsiGNs+VXBBRDpUL21VBFxTJ2Ctv XwUbRJfGepqfl/hac0o+OKEqbWmC0NUGmNG7O8UkFZ8HhsKD1gqF7Wq/gi70JB13 eJB+1NCPqPpalD1KosDCo443EqeVW6uqVCLqx3NIIGz8VlLFSJYxFIBehKkHVFGW Xj53YD3eUYU3mqWYjQmMSeK0aYg0cyqxC5fa4+Hcpn6cjjlJuGgq/UR0pw4ziDcz 80qs4NzbyATHJImsWxDa1aeJkwsMVuFWdFJ8Y6gK5PWUBmli/v798n9c3LvuNLLW ovtH+pMyIY7z1Wp5fX7fFMxeAd8p1sbqjxLvLltPVj16AXAVpZqEMcE8iRDx0D1u fBIU+qjbXDw97JmQ1wiUH/x3ecbDAQIDAQABo4GXMIGUMA8GA1UdEwEB/wQFMAMB Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRigthT9dpuCAopRBityxLsKgdM hjAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRlcm5hbCBDZXJ0aWZp Y2F0ZTAfBgNVHSMEGDAWgBRigthT9dpuCAopRBityxLsKgdMhjANBgkqhkiG9w0B AQsFAAOCAgEAjcQIGyQdwtWn3ym3dJqJL4a2vVjI49L1U6kCHC2H4EySDkuu9TX4 fF75sQfACbxV8kpYCgHk2XYm/7FUnuo0WzL8BRkscIZRaSXkFN2UyT9I1i6xPoKN TudemiCmNvZM4PmT9+Mj34pgcFz7YYfJfy5NtfL+hSmecX3gDpxtMVyIHSkoNHZn hqPsHmpsrFpBbl1Aej/0IFgzLfAgTT3dK+TA3NLI+uPKyTgMbadCipS9HyKkizFJ HkCjMp+iyKSkeD064GWaHKvIdM7w5qD35BB63X876HwQ1+e0bTONBkUUx2UxRerT rGRXavWiOPouqEq0VDaTE0h66IB73LvOapADblJENe+Uz3rKT4N+v1Rvk1H+MWVd Tst9AKiLcNOeEOaxkVX9AUE2j4IV4t87XWOVBsZp1L3AcVUWkVH2VrUIYigs2oPu RI4BjH8KYhat1WBtYkqSAZlYcsLbD5RavvJzrrX6tzz7o1S88bACrN5MW6Vz1IdX 2Q3bZRWAPv2uSwqggFvSWR+8TpPn/0toAa8RMCtUjuB+sUbtdmybkEmTXLZGthMl gFcrK2BRjg/JpnZ+6/n6A0CpEUb5oZo4ji+7zD8Wcv1RL7x/ctOzoDoskmUmNwLw wc6Lm+05t8UuN0QOm2iriELHhDG+r17IN6Cp2PIsFYmVuPgBs1oKWWI= -----END CERTIFICATE----- ca_key.pem000066400000000000000000000062531470345337400501020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca-----BEGIN RSA PRIVATE KEY----- MIIJKQIBAAKCAgEAzKb0nyHEzfPHZhduLmCWcZHvvdx3ylR1ts4JoJNAHw5dhfur 3A7gWUygbkr6P+tEIYHCEBavmEplQWZwWYLno8Lo7vbtY5LCdCN/Vd6kLbo+QvkQ RumsIanKAL6AriBKqkZqhw3RMoFL48ZtA8/NwAL/tQpd2TQPvZO3Ms06vNDLUZJS Pvwfi6j06M18fIfcQ7Q0NxNnKFjOUF1zjTNwGCr+Nh7Aqh70Nz1h0nF5CLREPsto xO1cThx6EbxiDJI3Ajzb7KU7/DXDsdBma+qB1hF36Fzl1fNwswA3asZom2J0N036 xN2S1ngZkLGCDLChxq+m7qQe8mJFapecXDfxLdpWkgXU4627FDVqhaW6MOMkJXKn bXbCDgKfJhxHjtDgoJRfWrDf+4gscUlh03a+kUpTlLcyTB8sukxKl/rROC3eGO80 +sazp3NJqxL0WWDnYHbbPMqyggBg1ZFlmdj0G8Za8gnqzy29QhQiQRB3GZNrNpCB Vrwo+vBmgz9vSNS4KG995RVudHnWIA70YrMqdJ75vWmJFAndZT7L+iTG5u4pu/Kc Y8OXvKRxFu0y7F/6t3hywCLLEGE1G/V2xG7uduHFVhRzA/mKe7gj1h3Q7S0L9fsE gB9BmuO3dcJ8a7YloQ2ADuNdg0qBBP6DXxucXW7rXaq7nB55mDH+xoCzPy8CAwEA AQKCAgB6gndty4lEwOpc8ynCGY/17KbXwWL0fBr7k9uvhHaeILtbuYzn7v/edUCU xc2I9g2TAVpqxynWwLJctDYNX4/LOKK4apkxQmmlnJpdjSo7NYKQFQjpanjgrgN+ 7ouZsTsBM6YRsvPIiB4l/GLGJV/F0gXBGrOTktbZZdQFVVYUMemEq1MQ4V0A/eOe eWRMKAhzfyzCy5q1THQ1J7xEisZPsWz8eOxc6qrHZrdogwUxcLhp3tqZCH55RBLP Czamz+CeNlBxGXkPQiAkEd0+POP8gfiF4Ra1PUX54edKw/tbCVUIxmWX9Awy1zJ2 q8xuTE6L4hrMQPNFpg5oANpZWiPFfRsFQFAqhLga8UfInSUmGZaJJoitviSqzkjl pAnPSpj/8fs4H8P+mf0E9uSdDm/FL8OofRagfBjnLx4B2vVNMOesxmMx0TmB4Gsl ueqfhu9auXKefa7eGOY0/r6P1YG/EvGMjDIP2LCmIMCELOCvhtAehXL/QKQPuJGb tmE7nN+Kq3iWGj3J5wXJ5/a2bW+gfTr6BQZXhHmnJaPE2QDLFKRNEovofY72TXUD dZqnjfaIRAt6/LO3kfK4PGXyShWhvtnroGh7BomnpbmZOW4GYaH5CQSealTmgJ/X KmxecxmgTjq39WPGvk5x33l9i5i2vFbitxHWTGWqS/a2HbzyAQKCAQEA6Iw0AM4O cPJbFha1VUlYHQ6ypK4WCofor0MZj3HGgH0eQGY7gDz9rJXFJrpkAHnsc92hE4w3 929JDmgwuLXQCcUpAGyPDJYHgiZiq0mYH4QcB3vPWK5BsFaKzXYI22/uLi7RDAni Z6VAu6ID5tMlneOu3AhR5G/CQ9hY6attEnvFihwPr+LFCG4FkWGy2gACZxpusmV4 E3WU/YS6J4wP2HZAWtH7imRE+OpSOKsxWtmDQ0b5BQ3k+7rQdZ8ljrxbL7Eatr4E dDnHYt7SApSWAe4rw4ptQDzXbwP6Cfn0kLJv/nWT3P9caGmTvKH1X5cOkcCvsN5h W5PXvwpvvPfVkwKCAQEA4UqPibCGK9p5X9TlyhYz0qJgctEeKh+Rkur0CPnHw2Nw t2XYb7jtYACLo9gqo7RwAxaTlQmyT3T208aFX2XmAy2f3flVQE5ciUZSmoJ/XbBO m/iJhzpcPg31v2xWz3auFfnPJztddehnjHN4KxIE0t6Rlko3CZt2tlxWIgAWPNal pKFNIVgVGgWk11tc7IupDRiUCj4mioxHfVgYViVOYjvS71PV/spOjtiC3GzQDbQP fiAXPtf5PsfnzHyxWux/X2s8p+lwY3UnSVv97UAZrSZiyNLE40cOEa8m4JPyjlLo jPw9vRqF4LNRN/4KERHSRrw5yX7CtSR0iUpazqyxdQKCAQEAwGmRdcEJLec5+rLb YzAGmjRZF+17C0ec/bcVZR0M06+y4jI0tUzB0JUzxXGf4M0BGnWdG6F/hVotJqCK /6pf8lWSMWmhixZwK/460eNY3WrgDkkhLQ0yCQfyXUJ23apldw0Bp2ZeUMfpIddS RyEaFOQZALJZoBvgr2ZJWz6eRxbmQfop+Kw3v1vZe4tNAxfS5SB3y2At1FwL5SB3 LtWzHrXpVbw81ytT7mljksQDWFp1Q6trzATNHIRci5Yc61dqU7HEmsPqx4gvM92O AtiSrhI1X9wfvXEaCB9QOgT5mOgrxm3e5JLeEP6aYQ/ZCTjhszOtqzi1caKIdufZ wI+HxQKCAQEA34K0cxsBkeJXRl8Wdu6eDVvxKhgTwCC/sS2OXJVKvasbOag+GWEz h2ojH7MnYnByLG4qjtMm5zOYabRrv6B9mSubjoJ+NKVJoxt0ejv7lnyDELR75QBe YWZCJ96ZJYyN29mRzk9UQtUGXk50qu5egMI1WBBbGBn3paZoAaVqaoNdpL4uomUb 0kxFJS9MOpW4avi2bo8Id64CgvVyd4zdfhHyDGR1Syl01L0y3vLJWr8IG85EoaFt cv6rFrGi1x0IpSbj74ZmbRXemyY7/zP4BVOu76RDl2R4Lc1CWc4N92uDsdPSgJke tzXP3ygW3qZ6opi9EA3FqCb5wvdUrfSgvQKCAQB0DbPQfKSRLVUH3TxVqoU9roqD dCRleddsM52e5KXqP1ez0srVgEVg7SUrsfbez/1orUqH1rx1nCejIlEMSxixAemy nMtBI+l/0/kYZPcA1zMFy7kHJkn1fuNg8fwoo7L+oE9t4luX2iaEm0IUpMgoxkhK HcFgyXl3qkQO3QGs3vme6TG6rk5phdFCB3/y+/rhn6SOKbeIY2YIfoG4KL2NxSGg iNTAgBz86uF+MV/iYK/EpY113XqJ0iLj0Spqo8a2J1vALD43xhZaKAZKCVDrRorU 8ppyCjbKoSuFgyRNRf1LUwdA2GO8SJtPJTXeC/elXA+qVeoFEfqYedcone6x -----END RSA PRIVATE KEY----- ca_pub.pem000066400000000000000000000014401470345337400500710ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzKb0nyHEzfPHZhduLmCW cZHvvdx3ylR1ts4JoJNAHw5dhfur3A7gWUygbkr6P+tEIYHCEBavmEplQWZwWYLn o8Lo7vbtY5LCdCN/Vd6kLbo+QvkQRumsIanKAL6AriBKqkZqhw3RMoFL48ZtA8/N wAL/tQpd2TQPvZO3Ms06vNDLUZJSPvwfi6j06M18fIfcQ7Q0NxNnKFjOUF1zjTNw GCr+Nh7Aqh70Nz1h0nF5CLREPstoxO1cThx6EbxiDJI3Ajzb7KU7/DXDsdBma+qB 1hF36Fzl1fNwswA3asZom2J0N036xN2S1ngZkLGCDLChxq+m7qQe8mJFapecXDfx LdpWkgXU4627FDVqhaW6MOMkJXKnbXbCDgKfJhxHjtDgoJRfWrDf+4gscUlh03a+ kUpTlLcyTB8sukxKl/rROC3eGO80+sazp3NJqxL0WWDnYHbbPMqyggBg1ZFlmdj0 G8Za8gnqzy29QhQiQRB3GZNrNpCBVrwo+vBmgz9vSNS4KG995RVudHnWIA70YrMq dJ75vWmJFAndZT7L+iTG5u4pu/KcY8OXvKRxFu0y7F/6t3hywCLLEGE1G/V2xG7u duHFVhRzA/mKe7gj1h3Q7S0L9fsEgB9BmuO3dcJ8a7YloQ2ADuNdg0qBBP6DXxuc XW7rXaq7nB55mDH+xoCzPy8CAwEAAQ== -----END PUBLIC KEY----- infra_crl.pem000066400000000000000000000036051470345337400506040ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca-----BEGIN X509 CRL----- MIICmTCBggIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMTgwOTI2MTk0MTMzWhcNMzMwOTIzMTk0MTM0WqAvMC0wHwYD VR0jBBgwFoAUwK9O427mYrXHygZOn5juGJ4/t04wCgYDVR0UBAMCAQAwDQYJKoZI hvcNAQELBQADggIBAE0DCTGA9InyroOVZUwYLihptu6/tfe8Qca4iURgzNe4LmtV 2fY5ycmHe09vd/1V/dxdZw9sdMMaCPPa9HiJItTlq7sUGl/VfXGSgYiyjKjNlRQ+ sN6Gn6MdaaztS9fj8ssy8CPTQtimrQ6ahxFOietFH1j5HekdY/kXlUtF8gveL42h eQNHbpYpAkfbjFYFq5nimdkRkuUrdtymcAbUqejQOsTB2CZVrn7e9/8aLOxC3pME CSbf/xAQPLMtrQeyCGxUApEDZdIStjIgj/OcerAaSRoWxSI3gZeBT7fy6rHnrPnj Tow3R7M7rqVcniJQVsr03fww6hWcM4s45Z2PVq7WEtYEWcbuTdsUTYch+L/bzvqK a3Xxa4JTNBclrj8kTnkgkuSOqB9IAL/sUYjIb/tzxkzLVj/2/pGRdepyn6ghbAl1 m9ON5N32hlTAJ7HNLPSJpXC2I3/bC3yAQQhYkPK7xfA7Mzwa5XVr96qyrQ93HwtK 4KtMi44gLUEDd0bMwx1kAXrB0rFVPFJ0PYtwxBmnSi+KYHG1KzYB81iMIAbfwMqZ hFg7GAgzi5JcrPOQFeQTKy9ulxta9D9wbl0hzpmphlg26yBwIFuu+7B/eL/doyI6 /AO48ln7TfNPUJdrxHuvLLz3+aLW7qMQl1yGI+ZurT5UamZK/5cfWYvo0pPN -----END X509 CRL----- -----BEGIN X509 CRL----- MIICozCBjAIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBwZXQgUm9v dCBDQTogZmM0NmI3NWUxNDE2NTYXDTE4MDkyNjE5NDEzM1oXDTMzMDkyMzE5NDEz NFqgLzAtMB8GA1UdIwQYMBaAFGKC2FP12m4ICilEGK3LEuwqB0yGMAoGA1UdFAQD AgEAMA0GCSqGSIb3DQEBCwUAA4ICAQBnxOyL5fQcVYpsKsZrUSURl/0xDBgGs7BG JD+Ak0Sa/XX1K9x0ebAHkxY5d/DFDoK6ZVOvveeASHZaUfLRSMfAFx7qzgemwK2r U/CFilr3RHbwBza5xHioil9XYFFpJd7hLfhGenHKy3r9Zar1u6MjQ0bxJojkzeIq rphZAc2NHv1lfp/bOi2+qxyqqBEKh644RxZts8aY93OkLcQnrYNQm4mWVfMnMyW4 Gfn6Cc3vYL4crGf2Cn3LOsbaidRywbMlef4wcJFZFEYtAk7iVEqDxFiZVikguVid A9YYRqNScPtbWAI5iqkDxHN6hLGAu/siZYa2lKX3kz44uVShF698/UVikj6ok1O1 317XMo2TQZ5DRoTI6OtqL7kGVFPiSHgj92Jmn9p9BB8DyfG0f6RUVn8hC4W14BaQ EslzzjKju9FLSaMWikmG/lmZ1lVY7ezaR5QXQBhVmjbTD/I2IdJUEgKZkS9A0Wmj wlJObZnHyIi7sezcIzuvRdZYlAZwf5p7XXT73vm9lX6Yj9XQl21dYjlJZ2+Fqv4x IThlbZ9qs7jaMFFO+ZkFtkYUPeA9rX6nKK7FPogA5AgTRa9hHl0UCdYg94KRnIpR 1dON5Ojfm61y9pkmCmND8EUQHzERapwAK86PHp+7zcSp//VKlIrepxs5DiidLPLA 71pTMi9UVA== -----END X509 CRL----- infra_inventory.txt000066400000000000000000000000171470345337400521110ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/cacompile-master infra_serials000066400000000000000000000000011470345337400506710ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca inventory.txt000066400000000000000000000003171470345337400507350ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca0x0001 2018-09-26T19:41:33UTC 2033-09-23T19:41:35UTC /CN=localhost 0x0002 2018-09-26T20:17:52UTC 2023-09-26T20:17:52UTC /CN=compile-master 0x0003 2018-09-26T20:17:57UTC 2023-09-26T20:17:57UTC /CN=agent-node root_key.pem000066400000000000000000000062531470345337400505020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca-----BEGIN RSA PRIVATE KEY----- MIIJKQIBAAKCAgEAl3A1+Kbdh+btx5z7H+W15voGOOsiNbtDWuHMd4TyUPU8PUGt Kn8tWpnSbp0JH8iJKXOdF8iZV0X5QIpn4/XkNnPVpJTW0o37pk3Jj6natCiFQRzT 4er2yg0ws5fmlSI1M0SlcHkuXeDgxtjPEDzWzf2qvKEGvIRTdFyVQd3jar4i1WgM 2HSVX+L5NLmV1J1MFZKHlrv0bDO7Gu/j+ftGwipESlNltMWT2J+xtprzWd/jNRhG Mu4O+Y0BmOM3/2xZYzf0VNXzOSbGaAt6MShzkeC+s4YrgXQhR36HFqQX/glE/VWE zYLIhjbPlVwQUQ6VC9tVQRcUydgrb18FG0SXxnqan5f4WnNKPjihKm1pgtDVBpjR uzvFJBWfB4bCg9YKhe1qv4Iu9CQdd3iQftTQj6j6WpQ9SqLAwqOONxKnlVurqlQi 6sdzSCBs/FZSxUiWMRSAXoSpB1RRll4+d2A93lGFN5qlmI0JjEnitGmINHMqsQuX 2uPh3KZ+nI45SbhoKv1EdKcOM4g3M/NKrODc28gExySJrFsQ2tWniZMLDFbhVnRS fGOoCuT1lAZpYv7+/fJ/XNy77jSy1qL7R/qTMiGO89VqeX1+3xTMXgHfKdbG6o8S 7y5bT1Y9egFwFaWahDHBPIkQ8dA9bnwSFPqo21w8PeyZkNcIlB/8d3nGwwECAwEA AQKCAgAXDwv4x5e1yNDt8xY93iFbgTiPVCZKXjA8V2Nl04V+FElO3oA6l1DVmdRz 6U9pWoSgHi2OYIoQwuPYEvsMt/U+4VZnkA5B00K9KN0HFgrqIb1gk74jiT54t5dx 0TBYBvRo0QwL2zfXLZWsUXj99PWUOgrUXASFkfSPJEXJ2Lp3F2qAai6CiwXvqsTd ZWDOFgFuy3f/2LC4BQx5ZoulFcDJcdwiIR68btU7R92se12Qksmq3P5bZOo8z16t 4/Mz3lCiDfQTMtytGB1f3FeHwqwOS1VeSpC3TnJ+y2JQbT4F/W1W0b29+SsFXLUw /eqyHPFO89/AYH5W2aaLd8F0THZ7k1bc8OET6PeebeKQZ1yJl+q8akt/63c2dWuO yaOD7QRlGIbWdSk1o1pG1jQuY+QzUWSdFFG/2a6hKJcouXn1hPy+XFOLFuNxhB5j C9jrNmtncd25+5FfNLOW+SXEkdPKH1tZpDOCPwL0mvwIZCbI5bq9X355Uo5qXq1D /trqBPJYXVoMmDrHL3SZzSzrajpyo+8hUvOWQdsjgh/ki+nPK4yq/NNTPU+2Wevh jqhBU5SlPfewCDLk19jIn9aIGtRlJuJS/iffxSMs1sw523z2I5bACAD/tijJC7BQ AOHnQTRUcyocpOoz8db2HyE3g1OYmqV8x+wdy0xbIVIabuno7QKCAQEAybehvxK4 /oCl9DS9SCD0/jANdsAdQQ/AL8J3nyBCfNB3nYw+n/IrRqVHPOiwo+lnl5YZ1LPm R2CAgGr8fDrqPa84VkOaeYobHmbi5TUaVntZ9FxUFeoDMI5dmIrOiQiH7c9cPzkh AOqOCw/kJSZxzhPDl+zvJBsf9RUDNwwhOdOuE2ReT7cN2UcbhXytzlSb6hwyic9w 16pY0/QAkEUwLyQrrEQFcgeRY+xgF0XIYblgC/sNoLCQxerEWCQ+u++4UqfFUyOa b2KvsilzeKw+noqq6f6qvnC2YjO0JydJS2Z6Ah38RnhmmLeJBSMIUJy74rFmpAkM pfVLmKOKxI+yjwKCAQEAwDDYCkErSxYcMTV+dsL5thvez7jZZQPKV93xLeRZzwVp SFqxuo83NrIiug05wX+p1e19MMBqTC02EwTSKPev1r0SP+ho/3kpHqfyCBBtxzit 5JFuyHLbClG2M2eGrhoEcoAjQDN6btG1NdqaSWE++dv46cGhGHfuJrystMOYgLnB SfbRZu2saVgqph9AsPLLGzOV9kNFJdShbQbeDvMIyKTpEbn1h4YPTnDH6uKmFflg xvbhNT9+GMYO8P8BncAUkiR40Nuqab9EcqSKi+WvQKCDgXH2a3CbqRGAqL/HA3pq z8E4OtOg143mvrRjYtRT2pAdW/y0vmyf8JLU7SG5bwKCAQBGHjP2VE7EAPou+ko1 kWc4GIIFnmBM5mm68FFemfsioeCCfmaieK68XuV1cbk9MPwWgFG4U1SfyRbCDO55 TI1yJb9ilRtUVkJ4/fCvFhdyqmwpehKsj2zOax5z0QRcM//0FVmOjJBBXkdD5yE6 HLQAm3QpEm5KUbd5HPXCI9BE5qUjDoeOFCaXOZWCgEV2bIjKB0U2DErAXPGFs9Ki U7qdGGip9/cgnSrX3inEzTgLaEHPyFQDYHzin2ni7a50665Z5QG9lamwQFCskKYX 81/NAozIzAKUMl/joO9lkM10jUmqBLxVzrJzMZFKnNPeGa1h7qKsMI0Z/zto8qhh DUZXAoIBAQCS4sG61KPp9zQEyAWnbsy6ygI4b+Z2tbboANBbarLY7iHREr/S/bIN M4gm+gSyRofe4GtV3zlejw9M6dpVRTg2vro77byRxGAQ9fqc/zFnmYINtrkcqeuO r3S5RN5CIdBUUmqenrlsCQqd5j0U6CXhgKV0wnAE62QwZvL4FKVxfIalqOXR7MRg num5nRksI+PnHj32wOMQTroxQZZlhomoD6Gx0pY8xdDc+oVQl3ioQrgcWIM21xfg hz7UIZFyp2MRbp6Hwds0huIhXHAnC5wtoH/hZuAWrTHKvX2/exL3LZCEx//ZtfSv ydwY1HVBC1YrLQnDTBg3kX2LuCzUL3oxAoIBAQDFxbkAE46Cn1vrnphj3R3GGGLS X1/HcTFoVM8ecIZQUQC8Zlf/gt3IFb2gAZwrWJy4Kppbsf1cz4gzuYDjTXEt2Fms zP9roRoB+gLB1mu9fwTnRN1tSoYAbnUlpRZ/Zvuz+mThziF7ujshCoXow8T50EGA 2Qc53uQta4HixI0kkAD4cYaGdEm+n8LyFwQ7UPRN+tKpdQ8K8PoTUQHEf/jhtvp6 ptLNIQlGns1kc50BIrEW/VK8gypUHpqohAWqdlsBAOQl3dieZYXC98hsCkE39BHp 0EJWRHpUzZUviBZkSMCD1KOlf49qC1iaCdXeTQdrViCou/5hPXw/O4bevjZO -----END RSA PRIVATE KEY----- serial000066400000000000000000000000041470345337400473320ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca0004signed/000077500000000000000000000000001470345337400474075ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/caagent-node.pem000066400000000000000000000036131470345337400521360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xODA5MjYyMDE3NTdaFw0yMzA5MjYyMDE3NTda MBUxEzARBgNVBAMMCmFnZW50LW5vZGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ggIKAoICAQDEGMhEdGOUVV8a3v4f1zyNllMQdgoBOA1f1Z2WsTMGqKXr+p32yBy8 Gm1y70gOy5xVElCFzXzxSWpoKXHRvVi8qU/HUdloFYjQXiX9db8hCXxvcw+hMjgo B7OFYbCJI2bTVb70ZqMt0OZlBSAetfKdqThyKio8UXEflDGHkQQ0qQ4Ge7+kcqz3 CVxIfGt3n743FQKbpY3q6Csi2mA2Dqa1cD2v3Aa6dxNotRJHyfrytS9BaptM5yUV U+aHIvUWMhNYpVP1AApnKWEKjJZWfKbdelYwP1ivko/MKKct1qNffZ9jnPI11CLZ tHgr9ldIxNIfpEbTGRe8S+CaI224xDg2fWiV2VsZIFDWlASKweHQQtYLbQFgDUix g0JBG0zlbckGQwpPSAs/lwe+lEZHEdzmhfKpV6XqMLMUUoXiB6a00+8lS1oNOXgY 8GGHEwMhw9J26gO07ly892XbyK55JdO7al0MMn+dLSxj7YxaGSDfMscQ/xeOITc6 B/vlws74ouliMGeuhZuWGc3OcAhxNqS4boMJuckK1rUsqGxNqaoF4MyrHB+J299Z HRD4G2sfIKbWyNKtKTuzQCe43rEwNzUcBlYUtho7jC53ZmSpLQ5hwaGgYfXgSVKH aWDDGFfaWcy5Er0sZquUo7yyGq3bThbaJsQx56X+rMdx3yZUUYTVswIDAQABo4G2 MIGzMDEGCWCGSAGG+EIBDQQkFiJQdXBwZXQgU2VydmVyIEludGVybmFsIENlcnRp ZmljYXRlMB8GA1UdIwQYMBaAFMCvTuNu5mK1x8oGTp+Y7hieP7dOMB0GA1UdDgQW BBQ88WqqIWcNXHFRKfDW58hyYVfoCTAMBgNVHRMBAf8EAjAAMCAGA1UdJQEB/wQW MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwDQYJKoZIhvcN AQELBQADggIBAKNpYUI8K8jnTTdhLOHfg6Eju6vmYvOKFaE1SQPpv9MF42YF0WEZ t1rBwnpMraK6dAvqTCl8N9QU6ICJSOZ/AA2RoARb50x6RjX0BHXO2N0eQ+HsW6Rr 5w3yWdspiE9R12DYvwWJvHQ3aCWiQ2WYGUhvNIfzUF+oS+YX3076N9dukOEdZ/ZR Ho9s0mHbuNNQ8SGS5Kd74i8VyNyeruz1BTfvbmlqzTEoNibEWGw0zXHKIVbJFoRe u18J65Qk4tLRoQpylNOlaP9jJsvWW4uF7GrtCx/Yyh1+SyDte7Ib4Xdr/NV+Ep6t sRwZOhYzlKQL7onFvEYYh0cZ7S8TWiYr7BNJ3DzZ1c9luCMdCXlXE86do+Y9oYFk N7zHMGCW9g236YmlxoHIZs7s8AvV9kbPrQwjzvWEnbayQDrwbZGz70aDa5x2A0xt 3C4n/UDkpWO9GLp1Dp1vKstA9RAaCdkpGMtvuW/PayinbCtHbLC+OkckBOlM72K2 MlZOpsChgbh7Qyf2ZTP0h7slqE4FG8y3Vuur27bDlMtskuWpLaQCWiR4JMveaiUt ftrCkQTi6+FsOTlArE8UUmXQvV0JreHyCnP6ROl61PYfy9O2fHHPsG5zVUAksYtj 0WFM2FUs+q3xp8JyqfhEzLiRrYTR6V6VBM88K7S1Pl2LNYl2fDXTejjM -----END CERTIFICATE----- compile-master.pem000066400000000000000000000036231470345337400530370ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIFajCCA1KgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xODA5MjYyMDE3NTJaFw0yMzA5MjYyMDE3NTJa MBkxFzAVBgNVBAMMDmNvbXBpbGUtbWFzdGVyMIICIjANBgkqhkiG9w0BAQEFAAOC Ag8AMIICCgKCAgEAugxjF7lRnvtDzCyqvfekMp8l6tdOCmKfOta1MLF52rb2gcgg ENs835pt3t65M+FTHLbdQNWVCfIleoO+uxYMQrueMNVUZGrn9UPmAT+R4rzxc99Q Pyc6KNs3gpLnX0eU3aUQyLwBbxu4ogZLVf7yjP8YdDiKsD8r7MtDLa9IWx2GNuvQ vYRPESMBOmPVqto5jiuFhVOgl+C58Mr0Qc4fBQ+I2ueCjTLWPYqgJ4g948qy0XJA LHaHLWNAUaoMR7UgdTKwgnM+sNWp8VfYLTqWVCdLJYROkfheQ8l5116Q5QLUNu2X nV1kDU4pSLrNEw67da/2LEkggIwssUHde/UzG6XjlSj9/GL6q/dqv50zWYr+0Jj+ Mr7PWsAsDuXLOJvIaVsQ4Gi5IHgY/bvd3D9LrdP6cRs4vY21ydLb/do/7z7cTPTF ph5Jp2p+F0rD3sj5hy2BdPJEItilrHkFrp0OO0UeZZCQdCvzn5O1EHhW6mqgdCnV UZdXLkaogchGF7+rE0VrBKY2RWTsH9Jgh9v3DxSfZ9cmPYcSqkPbuIo1eF92hgBt k2SyiT6MvSxXnYb734C+vlkHntU7o0DiAqHLfnyfsVFtqa1iafE922skXgg4R2tc UB86zUtforxSDLK0AB0LGHOlGDsZoWLCqqZHb/a5SIAc52SU51Epa/ttwpkCAwEA AaOBtjCBszAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRlcm5hbCBD ZXJ0aWZpY2F0ZTAfBgNVHSMEGDAWgBTAr07jbuZitcfKBk6fmO4Ynj+3TjAdBgNV HQ4EFgQUQDo1oxJP0soBZmBMHX0VjZsZJPswDAYDVR0TAQH/BAIwADAgBgNVHSUB Af8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMA0GCSqG SIb3DQEBCwUAA4ICAQAE6QcG3ztNebPLuawo7XxYil+NkYE41HXQ3DpGz+5VGUb8 IPlZzu89WQtuogVhtPrWYCLbt7xHe4nr02y/mfoxUv2fq05KfQhuheHUB5sdzNAg lSw/zhnc5/qTEKQJYeC5qlzaZtdXSXV4Q2WsI0R8TORI8A4L1lLH8AuPPlYeAjWU PFe4hcridaw7Y2fSeWh1yoVzSRx8asA5SlYyQaDb4fdKx5PbilRyXbuqTBaDeP41 VExTsrVBlr2OnH6ytJOgAyten8ctmPpRwlA/BXWjsNbJG/WOjpDb8h1YbIL3YI9M L/z94NaqRUnNRRg1v+AINVzIdVdPh4TCKixEMrpfi5Vh8E/POyOobTy6MoTYQQjT jkiUAsIYNQaKbAU4w3KiWhGSYLwqzX5WhBQRRVdCbPCPVwh4/WX/Yil3bhdfyslA muYJ97dhHxmlzgowFiZhEAvZzUALHLAbFxD1+KmvjtxoMiwYjWsuZCqfbw6K8rYi sEufO7M0LwtyA06ysgzD8InMUgDd7WdNO8p0viXQnB6yTQzp9ZWCdILFkPvHw8Bf RYAYkEJkX7prXycvLi9F+j4Cxm0hnM9oC6RjwvmF7aKHzY66cFbEIKk3JBKAE3ep yDop/Lxlh7I73fDC9XHM2cTnac8LOCZJlcjhRwFhwyEF8hgdYiIpyBcep0c9OQ== -----END CERTIFICATE----- localhost.pem000066400000000000000000000037241470345337400521100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ca/signed-----BEGIN CERTIFICATE----- MIIFmjCCA4KgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xODA5MjYxOTQxMzNaFw0zMzA5MjMxOTQxMzVa MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAJyz+EY/1s2UTN2kyJHRILQ5wxEpYkgQIDLuAuOxUykZqN+D8NlANYNR bNzn8I2/Z7xPzKYEcrC6j4fgSqV2LKcDZ5OkeronxwfZeRU7Uci8chh+NjM+zxxq ivP0HKIcGRoKw65dtiHORhVlGRUnDooYTg4zTGRSMOGWQAXOqDnM3HGQbr4PmTho GEOWyyMFiaBiFaSUy1LTey7shqndJXFhCCpBn2tpNeBEQJkNIpsTlipN7dnJpLfM GdyQmsMWapHf4LM0xEluZGMWc10uIjaeLYQyiJSvzGn4vARN3YlmCNMgL4YMyfqr gvkx1cm+OZ+vVvts2+r/nXNNcXXCcGdykB+LRXtEeOdS3eZmW+jpOPDJ7urs1RxB pQMonEjdaqtC/moDcJinSCtcbnG2fwe5QkYVmBxTcGPX5zu/pjs7quT183iAW9U/ EOC1S5TDK0NoyQb3oQrci3qGHKgfKC9ra/4LdDBz4F9QJ6kX66WpfyI2Ipbncu65 3QUN/0DAOpWJ8/eOdYE9qlTlLH5+eGD4UInNd5Hhb3iEVfc1VY3qutmoxDwQSguJ AaIzIMSxNij4hLTBSlw3qbrebGv9oRjyCQqg6KimtRe4Qisf+27m+7dvb8DlBn4G EY07fgqXEUHq1NmoY4igW57Tn5DAcSqRHrixoDV38IZoveqebP2fAgMBAAGjgesw gegwDAYDVR0TAQH/BAIwADAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJ bnRlcm5hbCBDZXJ0aWZpY2F0ZTAfBgNVHSMEGDAWgBTAr07jbuZitcfKBk6fmO4Y nj+3TjAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/ BAQDAgWgMB0GA1UdDgQWBBRo5ha7O79HIYA8joonatq2PheY9jAVBgsrBgEEAYKM TAEDJwQGDAR0cnVlMBwGA1UdEQQVMBOCBnB1cHBldIIJbG9jYWxob3N0MA0GCSqG SIb3DQEBCwUAA4ICAQCfyU4vpjMCctOPkRm4HjMA3wKUVURsAWjjfxfuCrc6uUz9 3E3XYZXm/L93enKaPmr6XePh0tA2xzmfqOaq9cWQPUtaVzP9UunU1W7LBIvWAYCK ATA/On9iU62vlPnHlqfyBrlO9H6v1gxKUVcCJ9sywTy8CCbrFn7DlNMww0UqPC1E AHwTWezG+xGTPNjo7ytuwJ/Ob64PYJ8JEw5JrfVNOKzdcWaUP3EkZX//mNm8VsE/ gnmhvHKe5KJYXb6kP/nbaKfQ+JKskvKwaJmxosOjv/4utP/8CjbZRLtIT9FnYEhM RzjDXVBE7QQdbtzmrqBE8rTaMoEb+uZHQHKaKtofYH3ItCs6jxH+fS2vPVfX8B8g 3502Vvd2S9VL7np9yMgNR7/DsctOka722ar6ZJXtlJH9TQ/VM+9Au9naqGOCsJaL 1ajOy5nuHfNjHhrpksJcVOfqq9RuqzSAw9upIcQ8TSRNmddwjEl4PZQ4BelCxBzs GF2czCSr/p0aDMWsPIpxUDlJnRJv5TZBr7lqifoVpIvhj8jssQuWDNuvp+xuXMtp 0jPnDpbT7LsYQMAsGDWeHev5NnRYXQBysyM+RjL1Fxc9hYzUVYZ6W+/hnnTXPFRr 9W3JlV2VgfvHTO2CmrK9fklifnEUD+MavSELwFez4ispBs0ucWVOOIjFKC9vBg== -----END CERTIFICATE----- ssl/000077500000000000000000000000001470345337400463545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/confcerts/000077500000000000000000000000001470345337400474745ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/sslagent-node.pem000066400000000000000000000036131470345337400522230ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl/certs-----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xODA5MjYyMDE3NTdaFw0yMzA5MjYyMDE3NTda MBUxEzARBgNVBAMMCmFnZW50LW5vZGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ggIKAoICAQDEGMhEdGOUVV8a3v4f1zyNllMQdgoBOA1f1Z2WsTMGqKXr+p32yBy8 Gm1y70gOy5xVElCFzXzxSWpoKXHRvVi8qU/HUdloFYjQXiX9db8hCXxvcw+hMjgo B7OFYbCJI2bTVb70ZqMt0OZlBSAetfKdqThyKio8UXEflDGHkQQ0qQ4Ge7+kcqz3 CVxIfGt3n743FQKbpY3q6Csi2mA2Dqa1cD2v3Aa6dxNotRJHyfrytS9BaptM5yUV U+aHIvUWMhNYpVP1AApnKWEKjJZWfKbdelYwP1ivko/MKKct1qNffZ9jnPI11CLZ tHgr9ldIxNIfpEbTGRe8S+CaI224xDg2fWiV2VsZIFDWlASKweHQQtYLbQFgDUix g0JBG0zlbckGQwpPSAs/lwe+lEZHEdzmhfKpV6XqMLMUUoXiB6a00+8lS1oNOXgY 8GGHEwMhw9J26gO07ly892XbyK55JdO7al0MMn+dLSxj7YxaGSDfMscQ/xeOITc6 B/vlws74ouliMGeuhZuWGc3OcAhxNqS4boMJuckK1rUsqGxNqaoF4MyrHB+J299Z HRD4G2sfIKbWyNKtKTuzQCe43rEwNzUcBlYUtho7jC53ZmSpLQ5hwaGgYfXgSVKH aWDDGFfaWcy5Er0sZquUo7yyGq3bThbaJsQx56X+rMdx3yZUUYTVswIDAQABo4G2 MIGzMDEGCWCGSAGG+EIBDQQkFiJQdXBwZXQgU2VydmVyIEludGVybmFsIENlcnRp ZmljYXRlMB8GA1UdIwQYMBaAFMCvTuNu5mK1x8oGTp+Y7hieP7dOMB0GA1UdDgQW BBQ88WqqIWcNXHFRKfDW58hyYVfoCTAMBgNVHRMBAf8EAjAAMCAGA1UdJQEB/wQW MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwDQYJKoZIhvcN AQELBQADggIBAKNpYUI8K8jnTTdhLOHfg6Eju6vmYvOKFaE1SQPpv9MF42YF0WEZ t1rBwnpMraK6dAvqTCl8N9QU6ICJSOZ/AA2RoARb50x6RjX0BHXO2N0eQ+HsW6Rr 5w3yWdspiE9R12DYvwWJvHQ3aCWiQ2WYGUhvNIfzUF+oS+YX3076N9dukOEdZ/ZR Ho9s0mHbuNNQ8SGS5Kd74i8VyNyeruz1BTfvbmlqzTEoNibEWGw0zXHKIVbJFoRe u18J65Qk4tLRoQpylNOlaP9jJsvWW4uF7GrtCx/Yyh1+SyDte7Ib4Xdr/NV+Ep6t sRwZOhYzlKQL7onFvEYYh0cZ7S8TWiYr7BNJ3DzZ1c9luCMdCXlXE86do+Y9oYFk N7zHMGCW9g236YmlxoHIZs7s8AvV9kbPrQwjzvWEnbayQDrwbZGz70aDa5x2A0xt 3C4n/UDkpWO9GLp1Dp1vKstA9RAaCdkpGMtvuW/PayinbCtHbLC+OkckBOlM72K2 MlZOpsChgbh7Qyf2ZTP0h7slqE4FG8y3Vuur27bDlMtskuWpLaQCWiR4JMveaiUt ftrCkQTi6+FsOTlArE8UUmXQvV0JreHyCnP6ROl61PYfy9O2fHHPsG5zVUAksYtj 0WFM2FUs+q3xp8JyqfhEzLiRrYTR6V6VBM88K7S1Pl2LNYl2fDXTejjM -----END CERTIFICATE----- ca.pem000066400000000000000000000074121470345337400505660ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl/certs-----BEGIN CERTIFICATE----- MIIFWzCCA0OgAwIBAgIBAjANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBw ZXQgUm9vdCBDQTogZmM0NmI3NWUxNDE2NTYwHhcNMTgwOTI2MTk0MTMzWhcNMzMw OTIzMTk0MTM0WjAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6IGxvY2FsaG9zdDCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMym9J8hxM3zx2YXbi5glnGR773c d8pUdbbOCaCTQB8OXYX7q9wO4FlMoG5K+j/rRCGBwhAWr5hKZUFmcFmC56PC6O72 7WOSwnQjf1XepC26PkL5EEbprCGpygC+gK4gSqpGaocN0TKBS+PGbQPPzcAC/7UK Xdk0D72TtzLNOrzQy1GSUj78H4uo9OjNfHyH3EO0NDcTZyhYzlBdc40zcBgq/jYe wKoe9Dc9YdJxeQi0RD7LaMTtXE4cehG8YgySNwI82+ylO/w1w7HQZmvqgdYRd+hc 5dXzcLMAN2rGaJtidDdN+sTdktZ4GZCxggywocavpu6kHvJiRWqXnFw38S3aVpIF 1OOtuxQ1aoWlujDjJCVyp212wg4CnyYcR47Q4KCUX1qw3/uILHFJYdN2vpFKU5S3 MkwfLLpMSpf60Tgt3hjvNPrGs6dzSasS9Flg52B22zzKsoIAYNWRZZnY9BvGWvIJ 6s8tvUIUIkEQdxmTazaQgVa8KPrwZoM/b0jUuChvfeUVbnR51iAO9GKzKnSe+b1p iRQJ3WU+y/okxubuKbvynGPDl7ykcRbtMuxf+rd4csAiyxBhNRv1dsRu7nbhxVYU cwP5inu4I9Yd0O0tC/X7BIAfQZrjt3XCfGu2JaENgA7jXYNKgQT+g18bnF1u612q u5weeZgx/saAsz8vAgMBAAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAQYwHQYDVR0OBBYEFMCvTuNu5mK1x8oGTp+Y7hieP7dOMDEGCWCGSAGG +EIBDQQkFiJQdXBwZXQgU2VydmVyIEludGVybmFsIENlcnRpZmljYXRlMB8GA1Ud IwQYMBaAFGKC2FP12m4ICilEGK3LEuwqB0yGMA0GCSqGSIb3DQEBCwUAA4ICAQBU 8sBkMapmL/Fno3WFIf/YFpG/fwC0VCN7cjvllNQjF4wM66sdMxianqe7VNsBuAfi fsoR2kCv/+4iKSUXbBgvmGpmCja+1dFXXyPF6C4wvYSD2NuUa0rItBIp4tR1a72P ZG721VFJCCgd3SDcgpabeXm3M/OspVCXdCmqNMro/nOAJc8P2tYaU7dwrPDCqHfE TCEWlyNrYNTADDfZMmjuXrkT45TugqZSe8/EJfogywpnCQkHjYAWXfCJ0pjBBENJ 2T3aPXv0bD9Sixz8R92CrBWz9ZOd4UuLs1eXlt6TkVYmTr+uK9KM+famSdFO9269 xC4ZZ8JuPrn83ClNau6Kmqer1azMalgKXa+WO7ksPM1AvUuPdMNd3CGsNjpzk1PB vO9kU2uVHovR3HnKG+vmbvYeoFMQfsJ+ObKDsK06z7BeSlUv0Z4uYFMqJyozLbgw JpDHoQ2ijFsVLQQnXnYxEUFUM3DuSeiSo/ky/XQaCGGGIdSfQFy4aegwZ59bSXZf da93fUUhcAmHCOUlLNnmAW91GIMz9QBYY/U9+Pb39OMgnf0Ja9+ouJnaW1IPn42k XgegE2Hd4M8NnKTKM10muPuahMsQCOpyU4wlXiBKAZo4EBFH57jPgmyT6xx8L9OS yQcfx6OgnJPZNb3bA4wlu22EPGHvMAdZXSWwcFjmqg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFZTCCA02gAwIBAgIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBw ZXQgUm9vdCBDQTogZmM0NmI3NWUxNDE2NTYwHhcNMTgwOTI2MTk0MTMzWhcNMzMw OTIzMTk0MTM0WjApMScwJQYDVQQDDB5QdXBwZXQgUm9vdCBDQTogZmM0NmI3NWUx NDE2NTYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCXcDX4pt2H5u3H nPsf5bXm+gY46yI1u0Na4cx3hPJQ9Tw9Qa0qfy1amdJunQkfyIkpc50XyJlXRflA imfj9eQ2c9WklNbSjfumTcmPqdq0KIVBHNPh6vbKDTCzl+aVIjUzRKVweS5d4ODG 2M8QPNbN/aq8oQa8hFN0XJVB3eNqviLVaAzYdJVf4vk0uZXUnUwVkoeWu/RsM7sa 7+P5+0bCKkRKU2W0xZPYn7G2mvNZ3+M1GEYy7g75jQGY4zf/bFljN/RU1fM5JsZo C3oxKHOR4L6zhiuBdCFHfocWpBf+CUT9VYTNgsiGNs+VXBBRDpUL21VBFxTJ2Ctv XwUbRJfGepqfl/hac0o+OKEqbWmC0NUGmNG7O8UkFZ8HhsKD1gqF7Wq/gi70JB13 eJB+1NCPqPpalD1KosDCo443EqeVW6uqVCLqx3NIIGz8VlLFSJYxFIBehKkHVFGW Xj53YD3eUYU3mqWYjQmMSeK0aYg0cyqxC5fa4+Hcpn6cjjlJuGgq/UR0pw4ziDcz 80qs4NzbyATHJImsWxDa1aeJkwsMVuFWdFJ8Y6gK5PWUBmli/v798n9c3LvuNLLW ovtH+pMyIY7z1Wp5fX7fFMxeAd8p1sbqjxLvLltPVj16AXAVpZqEMcE8iRDx0D1u fBIU+qjbXDw97JmQ1wiUH/x3ecbDAQIDAQABo4GXMIGUMA8GA1UdEwEB/wQFMAMB Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRigthT9dpuCAopRBityxLsKgdM hjAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRlcm5hbCBDZXJ0aWZp Y2F0ZTAfBgNVHSMEGDAWgBRigthT9dpuCAopRBityxLsKgdMhjANBgkqhkiG9w0B AQsFAAOCAgEAjcQIGyQdwtWn3ym3dJqJL4a2vVjI49L1U6kCHC2H4EySDkuu9TX4 fF75sQfACbxV8kpYCgHk2XYm/7FUnuo0WzL8BRkscIZRaSXkFN2UyT9I1i6xPoKN TudemiCmNvZM4PmT9+Mj34pgcFz7YYfJfy5NtfL+hSmecX3gDpxtMVyIHSkoNHZn hqPsHmpsrFpBbl1Aej/0IFgzLfAgTT3dK+TA3NLI+uPKyTgMbadCipS9HyKkizFJ HkCjMp+iyKSkeD064GWaHKvIdM7w5qD35BB63X876HwQ1+e0bTONBkUUx2UxRerT rGRXavWiOPouqEq0VDaTE0h66IB73LvOapADblJENe+Uz3rKT4N+v1Rvk1H+MWVd Tst9AKiLcNOeEOaxkVX9AUE2j4IV4t87XWOVBsZp1L3AcVUWkVH2VrUIYigs2oPu RI4BjH8KYhat1WBtYkqSAZlYcsLbD5RavvJzrrX6tzz7o1S88bACrN5MW6Vz1IdX 2Q3bZRWAPv2uSwqggFvSWR+8TpPn/0toAa8RMCtUjuB+sUbtdmybkEmTXLZGthMl gFcrK2BRjg/JpnZ+6/n6A0CpEUb5oZo4ji+7zD8Wcv1RL7x/ctOzoDoskmUmNwLw wc6Lm+05t8UuN0QOm2iriELHhDG+r17IN6Cp2PIsFYmVuPgBs1oKWWI= -----END CERTIFICATE----- compile-master.pem000066400000000000000000000036231470345337400531240ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl/certs-----BEGIN CERTIFICATE----- MIIFajCCA1KgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xODA5MjYyMDE3NTJaFw0yMzA5MjYyMDE3NTJa MBkxFzAVBgNVBAMMDmNvbXBpbGUtbWFzdGVyMIICIjANBgkqhkiG9w0BAQEFAAOC Ag8AMIICCgKCAgEAugxjF7lRnvtDzCyqvfekMp8l6tdOCmKfOta1MLF52rb2gcgg ENs835pt3t65M+FTHLbdQNWVCfIleoO+uxYMQrueMNVUZGrn9UPmAT+R4rzxc99Q Pyc6KNs3gpLnX0eU3aUQyLwBbxu4ogZLVf7yjP8YdDiKsD8r7MtDLa9IWx2GNuvQ vYRPESMBOmPVqto5jiuFhVOgl+C58Mr0Qc4fBQ+I2ueCjTLWPYqgJ4g948qy0XJA LHaHLWNAUaoMR7UgdTKwgnM+sNWp8VfYLTqWVCdLJYROkfheQ8l5116Q5QLUNu2X nV1kDU4pSLrNEw67da/2LEkggIwssUHde/UzG6XjlSj9/GL6q/dqv50zWYr+0Jj+ Mr7PWsAsDuXLOJvIaVsQ4Gi5IHgY/bvd3D9LrdP6cRs4vY21ydLb/do/7z7cTPTF ph5Jp2p+F0rD3sj5hy2BdPJEItilrHkFrp0OO0UeZZCQdCvzn5O1EHhW6mqgdCnV UZdXLkaogchGF7+rE0VrBKY2RWTsH9Jgh9v3DxSfZ9cmPYcSqkPbuIo1eF92hgBt k2SyiT6MvSxXnYb734C+vlkHntU7o0DiAqHLfnyfsVFtqa1iafE922skXgg4R2tc UB86zUtforxSDLK0AB0LGHOlGDsZoWLCqqZHb/a5SIAc52SU51Epa/ttwpkCAwEA AaOBtjCBszAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRlcm5hbCBD ZXJ0aWZpY2F0ZTAfBgNVHSMEGDAWgBTAr07jbuZitcfKBk6fmO4Ynj+3TjAdBgNV HQ4EFgQUQDo1oxJP0soBZmBMHX0VjZsZJPswDAYDVR0TAQH/BAIwADAgBgNVHSUB Af8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMA0GCSqG SIb3DQEBCwUAA4ICAQAE6QcG3ztNebPLuawo7XxYil+NkYE41HXQ3DpGz+5VGUb8 IPlZzu89WQtuogVhtPrWYCLbt7xHe4nr02y/mfoxUv2fq05KfQhuheHUB5sdzNAg lSw/zhnc5/qTEKQJYeC5qlzaZtdXSXV4Q2WsI0R8TORI8A4L1lLH8AuPPlYeAjWU PFe4hcridaw7Y2fSeWh1yoVzSRx8asA5SlYyQaDb4fdKx5PbilRyXbuqTBaDeP41 VExTsrVBlr2OnH6ytJOgAyten8ctmPpRwlA/BXWjsNbJG/WOjpDb8h1YbIL3YI9M L/z94NaqRUnNRRg1v+AINVzIdVdPh4TCKixEMrpfi5Vh8E/POyOobTy6MoTYQQjT jkiUAsIYNQaKbAU4w3KiWhGSYLwqzX5WhBQRRVdCbPCPVwh4/WX/Yil3bhdfyslA muYJ97dhHxmlzgowFiZhEAvZzUALHLAbFxD1+KmvjtxoMiwYjWsuZCqfbw6K8rYi sEufO7M0LwtyA06ysgzD8InMUgDd7WdNO8p0viXQnB6yTQzp9ZWCdILFkPvHw8Bf RYAYkEJkX7prXycvLi9F+j4Cxm0hnM9oC6RjwvmF7aKHzY66cFbEIKk3JBKAE3ep yDop/Lxlh7I73fDC9XHM2cTnac8LOCZJlcjhRwFhwyEF8hgdYiIpyBcep0c9OQ== -----END CERTIFICATE----- localhost.pem000066400000000000000000000037241470345337400521750ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl/certs-----BEGIN CERTIFICATE----- MIIFmjCCA4KgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xODA5MjYxOTQxMzNaFw0zMzA5MjMxOTQxMzVa MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAJyz+EY/1s2UTN2kyJHRILQ5wxEpYkgQIDLuAuOxUykZqN+D8NlANYNR bNzn8I2/Z7xPzKYEcrC6j4fgSqV2LKcDZ5OkeronxwfZeRU7Uci8chh+NjM+zxxq ivP0HKIcGRoKw65dtiHORhVlGRUnDooYTg4zTGRSMOGWQAXOqDnM3HGQbr4PmTho GEOWyyMFiaBiFaSUy1LTey7shqndJXFhCCpBn2tpNeBEQJkNIpsTlipN7dnJpLfM GdyQmsMWapHf4LM0xEluZGMWc10uIjaeLYQyiJSvzGn4vARN3YlmCNMgL4YMyfqr gvkx1cm+OZ+vVvts2+r/nXNNcXXCcGdykB+LRXtEeOdS3eZmW+jpOPDJ7urs1RxB pQMonEjdaqtC/moDcJinSCtcbnG2fwe5QkYVmBxTcGPX5zu/pjs7quT183iAW9U/ EOC1S5TDK0NoyQb3oQrci3qGHKgfKC9ra/4LdDBz4F9QJ6kX66WpfyI2Ipbncu65 3QUN/0DAOpWJ8/eOdYE9qlTlLH5+eGD4UInNd5Hhb3iEVfc1VY3qutmoxDwQSguJ AaIzIMSxNij4hLTBSlw3qbrebGv9oRjyCQqg6KimtRe4Qisf+27m+7dvb8DlBn4G EY07fgqXEUHq1NmoY4igW57Tn5DAcSqRHrixoDV38IZoveqebP2fAgMBAAGjgesw gegwDAYDVR0TAQH/BAIwADAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJ bnRlcm5hbCBDZXJ0aWZpY2F0ZTAfBgNVHSMEGDAWgBTAr07jbuZitcfKBk6fmO4Y nj+3TjAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/ BAQDAgWgMB0GA1UdDgQWBBRo5ha7O79HIYA8joonatq2PheY9jAVBgsrBgEEAYKM TAEDJwQGDAR0cnVlMBwGA1UdEQQVMBOCBnB1cHBldIIJbG9jYWxob3N0MA0GCSqG SIb3DQEBCwUAA4ICAQCfyU4vpjMCctOPkRm4HjMA3wKUVURsAWjjfxfuCrc6uUz9 3E3XYZXm/L93enKaPmr6XePh0tA2xzmfqOaq9cWQPUtaVzP9UunU1W7LBIvWAYCK ATA/On9iU62vlPnHlqfyBrlO9H6v1gxKUVcCJ9sywTy8CCbrFn7DlNMww0UqPC1E AHwTWezG+xGTPNjo7ytuwJ/Ob64PYJ8JEw5JrfVNOKzdcWaUP3EkZX//mNm8VsE/ gnmhvHKe5KJYXb6kP/nbaKfQ+JKskvKwaJmxosOjv/4utP/8CjbZRLtIT9FnYEhM RzjDXVBE7QQdbtzmrqBE8rTaMoEb+uZHQHKaKtofYH3ItCs6jxH+fS2vPVfX8B8g 3502Vvd2S9VL7np9yMgNR7/DsctOka722ar6ZJXtlJH9TQ/VM+9Au9naqGOCsJaL 1ajOy5nuHfNjHhrpksJcVOfqq9RuqzSAw9upIcQ8TSRNmddwjEl4PZQ4BelCxBzs GF2czCSr/p0aDMWsPIpxUDlJnRJv5TZBr7lqifoVpIvhj8jssQuWDNuvp+xuXMtp 0jPnDpbT7LsYQMAsGDWeHev5NnRYXQBysyM+RjL1Fxc9hYzUVYZ6W+/hnnTXPFRr 9W3JlV2VgfvHTO2CmrK9fklifnEUD+MavSELwFez4ispBs0ucWVOOIjFKC9vBg== -----END CERTIFICATE----- crl.pem000066400000000000000000000036051470345337400476430ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl-----BEGIN X509 CRL----- MIICmTCBggIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 IGxvY2FsaG9zdBcNMTgwOTI2MTk0MTMzWhcNMzMwOTIzMTk0MTM0WqAvMC0wHwYD VR0jBBgwFoAUwK9O427mYrXHygZOn5juGJ4/t04wCgYDVR0UBAMCAQAwDQYJKoZI hvcNAQELBQADggIBAE0DCTGA9InyroOVZUwYLihptu6/tfe8Qca4iURgzNe4LmtV 2fY5ycmHe09vd/1V/dxdZw9sdMMaCPPa9HiJItTlq7sUGl/VfXGSgYiyjKjNlRQ+ sN6Gn6MdaaztS9fj8ssy8CPTQtimrQ6ahxFOietFH1j5HekdY/kXlUtF8gveL42h eQNHbpYpAkfbjFYFq5nimdkRkuUrdtymcAbUqejQOsTB2CZVrn7e9/8aLOxC3pME CSbf/xAQPLMtrQeyCGxUApEDZdIStjIgj/OcerAaSRoWxSI3gZeBT7fy6rHnrPnj Tow3R7M7rqVcniJQVsr03fww6hWcM4s45Z2PVq7WEtYEWcbuTdsUTYch+L/bzvqK a3Xxa4JTNBclrj8kTnkgkuSOqB9IAL/sUYjIb/tzxkzLVj/2/pGRdepyn6ghbAl1 m9ON5N32hlTAJ7HNLPSJpXC2I3/bC3yAQQhYkPK7xfA7Mzwa5XVr96qyrQ93HwtK 4KtMi44gLUEDd0bMwx1kAXrB0rFVPFJ0PYtwxBmnSi+KYHG1KzYB81iMIAbfwMqZ hFg7GAgzi5JcrPOQFeQTKy9ulxta9D9wbl0hzpmphlg26yBwIFuu+7B/eL/doyI6 /AO48ln7TfNPUJdrxHuvLLz3+aLW7qMQl1yGI+ZurT5UamZK/5cfWYvo0pPN -----END X509 CRL----- -----BEGIN X509 CRL----- MIICozCBjAIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBwZXQgUm9v dCBDQTogZmM0NmI3NWUxNDE2NTYXDTE4MDkyNjE5NDEzM1oXDTMzMDkyMzE5NDEz NFqgLzAtMB8GA1UdIwQYMBaAFGKC2FP12m4ICilEGK3LEuwqB0yGMAoGA1UdFAQD AgEAMA0GCSqGSIb3DQEBCwUAA4ICAQBnxOyL5fQcVYpsKsZrUSURl/0xDBgGs7BG JD+Ak0Sa/XX1K9x0ebAHkxY5d/DFDoK6ZVOvveeASHZaUfLRSMfAFx7qzgemwK2r U/CFilr3RHbwBza5xHioil9XYFFpJd7hLfhGenHKy3r9Zar1u6MjQ0bxJojkzeIq rphZAc2NHv1lfp/bOi2+qxyqqBEKh644RxZts8aY93OkLcQnrYNQm4mWVfMnMyW4 Gfn6Cc3vYL4crGf2Cn3LOsbaidRywbMlef4wcJFZFEYtAk7iVEqDxFiZVikguVid A9YYRqNScPtbWAI5iqkDxHN6hLGAu/siZYa2lKX3kz44uVShF698/UVikj6ok1O1 317XMo2TQZ5DRoTI6OtqL7kGVFPiSHgj92Jmn9p9BB8DyfG0f6RUVn8hC4W14BaQ EslzzjKju9FLSaMWikmG/lmZ1lVY7ezaR5QXQBhVmjbTD/I2IdJUEgKZkS9A0Wmj wlJObZnHyIi7sezcIzuvRdZYlAZwf5p7XXT73vm9lX6Yj9XQl21dYjlJZ2+Fqv4x IThlbZ9qs7jaMFFO+ZkFtkYUPeA9rX6nKK7FPogA5AgTRa9hHl0UCdYg94KRnIpR 1dON5Ojfm61y9pkmCmND8EUQHzERapwAK86PHp+7zcSp//VKlIrepxs5DiidLPLA 71pTMi9UVA== -----END X509 CRL----- private_keys/000077500000000000000000000000001470345337400510615ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/sslprivate_keys/agent-node.pem000066400000000000000000000062531470345337400536130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl-----BEGIN RSA PRIVATE KEY----- MIIJKQIBAAKCAgEAxBjIRHRjlFVfGt7+H9c8jZZTEHYKATgNX9WdlrEzBqil6/qd 9sgcvBptcu9IDsucVRJQhc188UlqaClx0b1YvKlPx1HZaBWI0F4l/XW/IQl8b3MP oTI4KAezhWGwiSNm01W+9GajLdDmZQUgHrXynak4cioqPFFxH5Qxh5EENKkOBnu/ pHKs9wlcSHxrd5++NxUCm6WN6ugrItpgNg6mtXA9r9wGuncTaLUSR8n68rUvQWqb TOclFVPmhyL1FjITWKVT9QAKZylhCoyWVnym3XpWMD9Yr5KPzCinLdajX32fY5zy NdQi2bR4K/ZXSMTSH6RG0xkXvEvgmiNtuMQ4Nn1oldlbGSBQ1pQEisHh0ELWC20B YA1IsYNCQRtM5W3JBkMKT0gLP5cHvpRGRxHc5oXyqVel6jCzFFKF4gemtNPvJUta DTl4GPBhhxMDIcPSduoDtO5cvPdl28iueSXTu2pdDDJ/nS0sY+2MWhkg3zLHEP8X jiE3Ogf75cLO+KLpYjBnroWblhnNznAIcTakuG6DCbnJCta1LKhsTamqBeDMqxwf idvfWR0Q+BtrHyCm1sjSrSk7s0AnuN6xMDc1HAZWFLYaO4wud2ZkqS0OYcGhoGH1 4ElSh2lgwxhX2lnMuRK9LGarlKO8shqt204W2ibEMeel/qzHcd8mVFGE1bMCAwEA AQKCAgBGkeiYgg5IFoUYZYGsscfP6HZSKTimgaaGg5in33NOhSjZCKMKaa+1ngkf YK9c67eCAgpKbM33A4WwoKGeanbhxki4oWMNCxrmactgMJys5f4LGaxZRXpiJYtc h/CBGeVqTqRezgUReuk/F54cjzwVsw1mQHhcpq6AP9OnRu/th51NhgFMzBwk9xBn 4abHMQzCQ+RhYS32iMDlVRNkwNcL2q3IePVO64VnnCpM/Yo7CCtObnAfN9vnlf8T SOhMqY6+yxiwxef4gjKzGi8MRuXCNMGJsXJYFPV88nBflavLtKjEr3mXF5XHJSRO JeP5gyNfUb5PP+uDzwawUemtoafciiz1zyH2sP2DZaroiv5dTPH2BKT+WZrzzYmM sqytXk8bukdufpTIAGsaHPn7x21Y53V7315eEVrI9CkFalyYeLPF3EnZ/YIsKZ8s 1LC9eDK6ygtFcT+K66qlpEVIQ96aXgGjclHVadkXHhZkGjufeJeMpbilaIovAnAb lzS2xZk51Zkv0BmIRfrXE4EIQfjMSNHak83PgBWGV3Vt3FQtBcmOZda5GOG32dCc G0ZhoGrNLYGrHWjk/a8Xn0GEBdAJFAZW+XFq1XuEZt/FBD7hY8AW/Xos0n23oVsz 32wLQ2B+vgkyZUvc3XszgqLPAuydIkTPVYcW6nG11U1IKQXU6QKCAQEA91yfPuD/ Z/gY2mcSAVJ6AGAp1RRPMHJeQ9E06gPDQD0imuN/N9bHVU/gPz97URtBprRzRZYo saPbI/blWdGkNQ2sK8nIixSxKf5xu9ZJ/MlEcUX5nOqr7C/Vn1bfZ7FrG7264Gr5 s+yPoVLWDQJ3jD2PGSSek9MmFGeZsr2mPBGEKFV0anGLjT7KlAOKLFd3V6aksCLI 3wnCHbZgmu7zXKrmjVs+Zw0q51stUgW869CGBtpy2k1aTXTe3yAzSO2QY2ggNb9+ 1po/wmQhjAIG3K6Fr+o9WIF/glhKzzymW0pOssJIR42L5fqjj6c2Zwp5qXvZ0Xsi Z6Jx6ZSLi2jYPwKCAQEAyvHb1egyt9shWvCrBRARAWWI80EkznOv7Yfh9K6GCcPr SIMcG9lD3xVlC3GdxPo2nZd2hnuW0exYUBDzaoY4fw2Z0OIpUD8nx6dBMY8CCL78 biWJmXxxBs8RML7lSZIOheoT2lUSq0sV69fjwRiwFxXzB78KJ4FpSuP0+ZAy3c6X zkWCZJyl949GZJZlmhxMXwIhhv3IrpkI/nE5rlrB/7lj6sRZhyJi4VWO6lKmatgD XN+zdrvezvylohOHw+oO3W4RriUMafa2BkaKpX0iwnXLJgtOvz/q66iqtUgcafhe V7AfIZ8zAR6UVexIYgV71/iqpCNHfpcACPyWDFOFjQKCAQAQc9mnrgFu4eKNTEO3 UMwKkFrX8FTgDQtWCWkyk3N+J1LQ6IbCqQdzFi/9JPTHzT9Nnjz4iOdGAXcG6loQ 4k/As5sbAn3TOloaR/E6pCMhrCVgP1494KH0wK29vmJ3nCZanwD6AkN/gyF+gmr4 TIy1CDcnXfcqL+Ydf1KKv/B5mFSo9h4bIlg82ctRkvaywlKOwue7S2T+6MA/h6zf QTtwk3FoP4RkCE0tPDREe1s4eBMiC4+OE40JD9fvEU438I0k/3z89jKyhWnuPQi6 LjxUm0sLC1JvO5XGjqbTJ96MveGEJEX4dGK0tjoAyQdmTR0Qd8tiEoWUTQq0lYu+ hwezAoIBAQC+H+lYs2jYb7UG8lL1skCMM2gipBPsSds2R0e7J8kw2tfQneu2d0ur ceqw1ub8Q4DpEJ2cjaoUzjtJ/ydb05SYCtDgLRCROil1VM6xtA0uzmXEduw626cz vseXCC/cRbXPZSTmNS8BRJ2rzhxzqUJGzmxZBHNp4UYYQAkfyCSvQb1cJChtQ4gE rbg/wdo7j2lI1ME+KwFX+MzBOqfUHPiEL1VY+kv5WpCSE8qI4ZdAn1A/MN97S7QH 7A7sESnus5brgROVNuYzW0raBDodoWbwENSZtpw2dZYK4n/Sx1S/Pkx8D+aKZA+v a8uB15NUKVkFUtPiY562DJae1KtprtF9AoIBAQDQsu35kD+8m0uPORIFoH7Pos9B t06jIFC4dlyVYgUgr9QsEP4zG5cHVHMWxykdqrYzVqJCsV0En6KhLHn9TMdrtWW/ OcSQiis+SJRietNQWgCVcgcpZf8zNIE0E+0QwqEjMkqkXYuIujE8qSatqLe790q/ 8lATAxwzXypJgzLqsBPlgJ9IjLL8exhjGw9HHqk7JTzIfl8Eg4D/CKVhXcQp5U4f eqPb899fwLWPegF0JBJ9lYhP6heyRitC6gZb+o9h9wJLUcOggL7SvQw92zYELH56 HHUYRT1hIbRfhR/fVZFx1l2Tbxm48UqX/PoZCg06VVjkejeN0cBAIyH3TReT -----END RSA PRIVATE KEY----- private_keys/compile-master.pem000066400000000000000000000062531470345337400545130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl-----BEGIN RSA PRIVATE KEY----- MIIJKAIBAAKCAgEAugxjF7lRnvtDzCyqvfekMp8l6tdOCmKfOta1MLF52rb2gcgg ENs835pt3t65M+FTHLbdQNWVCfIleoO+uxYMQrueMNVUZGrn9UPmAT+R4rzxc99Q Pyc6KNs3gpLnX0eU3aUQyLwBbxu4ogZLVf7yjP8YdDiKsD8r7MtDLa9IWx2GNuvQ vYRPESMBOmPVqto5jiuFhVOgl+C58Mr0Qc4fBQ+I2ueCjTLWPYqgJ4g948qy0XJA LHaHLWNAUaoMR7UgdTKwgnM+sNWp8VfYLTqWVCdLJYROkfheQ8l5116Q5QLUNu2X nV1kDU4pSLrNEw67da/2LEkggIwssUHde/UzG6XjlSj9/GL6q/dqv50zWYr+0Jj+ Mr7PWsAsDuXLOJvIaVsQ4Gi5IHgY/bvd3D9LrdP6cRs4vY21ydLb/do/7z7cTPTF ph5Jp2p+F0rD3sj5hy2BdPJEItilrHkFrp0OO0UeZZCQdCvzn5O1EHhW6mqgdCnV UZdXLkaogchGF7+rE0VrBKY2RWTsH9Jgh9v3DxSfZ9cmPYcSqkPbuIo1eF92hgBt k2SyiT6MvSxXnYb734C+vlkHntU7o0DiAqHLfnyfsVFtqa1iafE922skXgg4R2tc UB86zUtforxSDLK0AB0LGHOlGDsZoWLCqqZHb/a5SIAc52SU51Epa/ttwpkCAwEA AQKCAgBBoMj7v2VpXV0HEuKP7GFBch5f/t8Kjst4Z/C2YoSHgG7oTP3ytEN+5OzI 52wRPvSgdmkJy82tGnvaAcswF5DvoVsmArqoSYXVYMQrwI7nmprZsvaNsHq1ms60 AroXRBrhLK8FADzJQtAYZ3v/s9U/o2Su6psRnNcTyofB/8jYS0vi58BUee2iL+Tp AfqHMD+JRRTueRd3O9Cbfhw3ckxC7r3p6iyFPl+QiewAxfB/ACuf8lts08rPWemA ZSm7ycrPTLgy7BA7NMOj3Mbm/Xm16b56V3eXyjMGWnXeYP9fqWXOknUfD6iRgPbT LwHULSg3VYDTEmCit8+0H3XPmikShqixe0lEdb8j5xvtA9guadBWUe0VFuFrWP41 9mOxRiI21C6Yce3AWlmLGJQJHYEXZ5jTkiyuZ8Jc6D078zIo1BVyHy7VPTDk26aL CS2BMD3nmrW/NU8VQwG2g+8H1mvt8XPqW//m8QHPiC7wIl3AZ+4WeHwFPV4IQDPO vvQxttCM7GMQYmh/WojACd/0L2L3X3jg7NmFPvUzoYdsXwcKL7h3BEdV1Ls/wdtc RaR7Za7e9WZ3b90fmKsEAiJqgsgT65CmX6PNbcqMnQElUo/XpnLZuqlCsIh1Cj4C YknC1HzlbzgZA3dEPNztdzzwXcceZjnYsvNeINj8EUXoDC1aAQKCAQEA9S1WrFm0 Y990zQ8qtEFaYKo6+ZJ/Mn3kqJiJmmp6SzeAH5VujaI0OfH9Pm6NLWhjO7obTspP ncDsjLBmQv6EiKwd7XC4equAXXqqZyLNFWqNgGA4HkeS8nVu+3UFa9bq8ZQOoEEx 8kY/P6C3tjJlEMa0jV+g1cIpYoMnsfPk+hYTkC6dN9PBbkQNYFqSquJngMStFlJU lSnnuyCOUwIZAUcPhCUeSb4RuWvzGU+hRj2LPwQnk1qwZMyX47L6oqOc6x93qRhF kQ1UNFEWl5xqCJ/F1rVPz/vtNviqcdzskgOmPBHrqv2h3RMwtsQTdgJ6t0F1EeXK zQHGkvN91v3yoQKCAQEAwkLa+sMRl3YtmFfFXuNmGxW0+vY+R2Pt+HbaAEIeFNGG rDfSgCaZlpC3g3JCAhKLJXWnHLZbdi60oJLigpzzfYhT1JTzh7BKZE1juSq7fCf4 XOAafPeBl0+xz82GKU/kpzyEKhEUuYwPlGPOuOiU9+NKHRuN4YxzzU+7McX0XzFA JWPF9iM+UjZLmbu94A2lzQkq+fDJ9KaIemPiO2pIxPD/20pzESdmbqiM79Sz9mRn ekFHezt/yzsOrGCn8/cEO5XdH4cwOWPJRLwE5slI/w8DnNBQIWkGuAleYugOrEOK 4640NT0uV8+fPuSHFF6aQIzxsm2U+2ygOD4FgbpE+QKCAQB4r6yugimtz90q44Bd 4p2eX61QFLDQJfBcnVl+zVMNm3BSG7ijt2iF7Xx/MuQDqhLO37l5e1Tdjo3iYyKz b53FuROyQX5NxAYX/b3LrvHMzPqCatq07P6EoxHSbbQRdWWJLRxV/kGbxMB1jaNg 6EWfkHBn9t6w2jaM64qqqifYgu12V7vEM1RP9ueuumbf/zp7xFR/XF+OXWZYUpo8 ehfc7SHSJoNWQV1wLJcpqmz0qm7UwjLI8idKNvu9deiyDl+7zW2VqwDzeeAtMI0y bCg1vpAgNHfpJVWLbbRZACrjZTB6+UdMkDURIdUk4jfCK05Ezs/V04uUhn887ubO 4YqBAoIBAQC1N0ivxGkUsdm206n66obFnWpG8o8GaeIEdlrHAuas5QiMf0aO5XNB UZ7fsCaDaGkFeMt7rWGEze0SHfPPhDpgUFxjYtALNBkxmD/+7C4Zk+/MNAKBsSHi 1SU6hK8yuqTCnWFtHKIItO+TrceaFt1goVbx8FJapXshe89UjyV356m/N2PkSNxK NPwxXUGzUQfqTTMaFdVPtEp8YdEZO/zGO0tydfEBf4++it1unS2EHAWrtlnIS6jb HSyDAWer3jLEovi0AJir8LpAtGSeJgdCZ+8myez2PdNWuuahvXhymk9mNYveXkRt BfG36ddY2SdsMA8IM9FW+e48iR759ZmBAoIBADwQQ6uTa9u0zbBeShnkhXr8v9m0 Nj+Jj82zqvt8k9lnctWKzz2nmA6QpTxQc0EthXVDeckgshn8+K9h3X8yfDdNVqDJ iE9iDDYkIfJk7x6eOp6SellITxHeX4q/B984UsWq5TT+CFOnq8K5mG50gWmLu/cy 4it6tHvtIts1dyfnE3KPcL4NDRvSq7CNNm9/Jxh9PmOsWUxXDqMyFVG7OYyL2pWn Ov+EujxlOpubeQY95dBSfi+PuWPWqkv4jhuwuKAD2LfjdvYgWPDZ+cqXOAoJs5e5 Q1qRBSHlTHCAApoRkcc247okttx3+fVTwj12+8tOUs2ExRpfJ3C9XjjdCiM= -----END RSA PRIVATE KEY----- private_keys/localhost.pem000066400000000000000000000062531470345337400535620ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl-----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEAnLP4Rj/WzZRM3aTIkdEgtDnDESliSBAgMu4C47FTKRmo34Pw 2UA1g1Fs3Ofwjb9nvE/MpgRysLqPh+BKpXYspwNnk6R6uifHB9l5FTtRyLxyGH42 Mz7PHGqK8/QcohwZGgrDrl22Ic5GFWUZFScOihhODjNMZFIw4ZZABc6oOczccZBu vg+ZOGgYQ5bLIwWJoGIVpJTLUtN7LuyGqd0lcWEIKkGfa2k14ERAmQ0imxOWKk3t 2cmkt8wZ3JCawxZqkd/gszTESW5kYxZzXS4iNp4thDKIlK/Mafi8BE3diWYI0yAv hgzJ+quC+THVyb45n69W+2zb6v+dc01xdcJwZ3KQH4tFe0R451Ld5mZb6Ok48Mnu 6uzVHEGlAyicSN1qq0L+agNwmKdIK1xucbZ/B7lCRhWYHFNwY9fnO7+mOzuq5PXz eIBb1T8Q4LVLlMMrQ2jJBvehCtyLeoYcqB8oL2tr/gt0MHPgX1AnqRfrpal/IjYi ludy7rndBQ3/QMA6lYnz9451gT2qVOUsfn54YPhQic13keFveIRV9zVVjeq62ajE PBBKC4kBojMgxLE2KPiEtMFKXDeput5sa/2hGPIJCqDoqKa1F7hCKx/7bub7t29v wOUGfgYRjTt+CpcRQerU2ahjiKBbntOfkMBxKpEeuLGgNXfwhmi96p5s/Z8CAwEA AQKCAgAlSeIbfVd1BgQgffTIVhZNLK2RaOKdOVEgLWj8m5apYhTAU1o9qDzTqc2Y 54xjfpeFxQtyuf48tbgv4hyBMRTBDVtZU7tsjsiawpJAjiQQ+16/G1F0ck7AeU3l bUJfBQaoHsWfuWb8tmQQ9US5ttiL3eq9EFHuUWyWUbWcbCe10VznnTHtAjM4q/SS KNDf3ZJ5Wr3BszKK3A4lBV2qEBi32RojTAhOe/O5ESS6BtkkQ83o9TBTMduDbQr+ ZF6fa7ciTT7gBf9rZdx3g8Eh/Ddh/dPg8FF16DthQDIlaA3+gww4iSEl6ecqQiPh fo1b+2sk54lwPOA8FGV4KYaFOiaa59hhnL4nxQE0Sh7NEQlneG6bSny4PyIVu9e9 8FlrgQWESuE/SRXSkLUPry5vML1mzyRTUEKPabZC3ihyKuUh3gvCJAPAZhhO7adA 4QthSXBAretptexfa2DrI12eHTNv4oXRXqH8DMrdb0WXtVtUIr+Kd3zvj80hsuy4 G+1ruiFjEeEeBT++YwQFoWJS23x5mvByaDvK/y5foWpSiMxctVNZmMl3VVTS5JJS V04uO0k3aradghm949uzedQsG+rhbIf+yNQ0/WK4NSR64DczYbU+qYuy6V2BJ2cR m62Azybgv33XTGANt8pNHJgUMqERwMu3SqKyfUqmqC+THDYl6QKCAQEAzigqZ3ar 9UEm1BCdaTx+mjeJgiK4EqK1Ml9I20l4K0tZrDWB3bj45j/xs/4zda+Tj4oLV5w/ q5fvigyKTC7R92Z4yWD7fQOJGNdVIzkeJwp2zW2JrolmL9tEQYlzQcZyl9Fav/nW GHBL+vB8d5GGLmXFMU4whuQ6M++8TenESImHQPLuejUWUfIX29eiCARI+OmHncvC FddywoCwF3cvrM8fdmZlXDjD5+hkCijuJe6nYM5X25QTN4cUiwkAi/U9rIyFtqXF OuamuIcZxV0psmhpPq6VU1VfDKN7T9oINTlHsFDJzEEWD0ZkCa15ISL7ayAx34N8 UGgR/6IjozTRTQKCAQEAwpbqNIGZZfQl435B+2QwHkhwHEeqA9Ztub1eHGpwhsTD +3PKJpXlWN2J2AI4Y9TUO+wYU1nHzbBK3U3oiTIXpVJsA4Ca5E7XfB/MA1W+vh2l QYvr1qiNx2x056JmPuGDu+vdFiNbHa8bfTg93Q5XQnAh21uD5Yc2I5+4ZeegfZU6 bBCEVlP1RlOd+tZb9xR8/twcdM9dKoj9LOElpLlLJ9+yLwh+EBtSigPOOo6W4ISL QzRp/DJ8MNBnCQPytNgCN/xoRdwpvEexbp9oR3XHpQLsxI3QoEdIGMN2ng8hBOup S0Q1g3f0VX6Ja8AT3jBZ1LrPqsOu9egXpi/VCVlUmwKCAQBJZ2XJ1yhdOCiCI7RY rzCI6rNsgb427HZGDEVdxyghij/QoHCwKNd+7E+8fguGoNCSsF1fgYPuLjgdWF+5 xoX+aB8j3QNOvP6IuMtYslK5JfGtLY5zdfrLmXARQcanKejNg76jUmrX4sw6+nvm +wri5Fu1NZjzvrm2mmra9xxrk4R0LMua+eILpX63SW0pG5V8A3LFTbK6oi77cGTC xi5Ugp86QjVfA9tFbKqKL460NOimAHKp/WxmPhOjeb4XF2gxUwudQCMc2NmOJJSZ gJWDL8ghiHok5OXmEyOqCAEaKl4LOojP0HDxWWfvRjQ2B0WsHBeF9URDQPr/oZS8 3OaVAoIBADdpDgwhk3Lq0Rc0zsktQF5/Nh13crxhBSHNAM2KqbxWr5Ac6sWODZ7+ htAR4cjbxAvEMTEa8cBqoQbftoXK09zp2YQtzO2SXd4kl82jTwuIGZTOqTuZB7Zv 9eI35nGlegO7KFuzebC8OlGwAD3AZayvjZSPPMHRfOMsCjBKgvL/2YEIOwbyJXf/ O49AFzQGi4lvWFMS8W65T47GFhgQA4y5MF4gRvWDMj/G0aTvEZuhYp6igEOmhKLJ 1W1FyIkisY8Luw2ZofDRYX8kuWcP7OfaK13VHEFnyunyTwa3PCnQiYa7R5nGQLdP rwYVzhKJJitjftsbmejATGuwVzOwUl0CggEAGOi5tRKoxiZZsGosCnX6ttNEeBJ0 VUMpL7+RttHG905RKbQJ3VGrH59v/sCzkYLV4wJActPJXFw0mKRnS/WqmfggKf2u 32c8cSp7TcBvUGKwYycg2XqyylM9Z+Kp6QV6kAc0/Sys6ULwuEdwZqWxWMVZh0Oh 7Woy7sHzzfmQfB6L1KeblrtW+KAH68qC0M2KQ1G+qIc5LNuN/d2bDHFfuRzC8soy 4rK/UzhQpX/8X1gpryjsbnlFckQZFfu6FsQoK7OE8/NMCK5A1TvObL+zrbYqas+P g7i2TVAw64gch8MsUgj1tqjrglL5LENPgydX638lduaKdTQTiXXoC9LlAg== -----END RSA PRIVATE KEY----- public_keys/000077500000000000000000000000001470345337400506655ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/sslpublic_keys/agent-node.pem000066400000000000000000000014401470345337400534100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBjIRHRjlFVfGt7+H9c8 jZZTEHYKATgNX9WdlrEzBqil6/qd9sgcvBptcu9IDsucVRJQhc188UlqaClx0b1Y vKlPx1HZaBWI0F4l/XW/IQl8b3MPoTI4KAezhWGwiSNm01W+9GajLdDmZQUgHrXy nak4cioqPFFxH5Qxh5EENKkOBnu/pHKs9wlcSHxrd5++NxUCm6WN6ugrItpgNg6m tXA9r9wGuncTaLUSR8n68rUvQWqbTOclFVPmhyL1FjITWKVT9QAKZylhCoyWVnym 3XpWMD9Yr5KPzCinLdajX32fY5zyNdQi2bR4K/ZXSMTSH6RG0xkXvEvgmiNtuMQ4 Nn1oldlbGSBQ1pQEisHh0ELWC20BYA1IsYNCQRtM5W3JBkMKT0gLP5cHvpRGRxHc 5oXyqVel6jCzFFKF4gemtNPvJUtaDTl4GPBhhxMDIcPSduoDtO5cvPdl28iueSXT u2pdDDJ/nS0sY+2MWhkg3zLHEP8XjiE3Ogf75cLO+KLpYjBnroWblhnNznAIcTak uG6DCbnJCta1LKhsTamqBeDMqxwfidvfWR0Q+BtrHyCm1sjSrSk7s0AnuN6xMDc1 HAZWFLYaO4wud2ZkqS0OYcGhoGH14ElSh2lgwxhX2lnMuRK9LGarlKO8shqt204W 2ibEMeel/qzHcd8mVFGE1bMCAwEAAQ== -----END PUBLIC KEY----- public_keys/compile-master.pem000066400000000000000000000014401470345337400543100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAugxjF7lRnvtDzCyqvfek Mp8l6tdOCmKfOta1MLF52rb2gcggENs835pt3t65M+FTHLbdQNWVCfIleoO+uxYM QrueMNVUZGrn9UPmAT+R4rzxc99QPyc6KNs3gpLnX0eU3aUQyLwBbxu4ogZLVf7y jP8YdDiKsD8r7MtDLa9IWx2GNuvQvYRPESMBOmPVqto5jiuFhVOgl+C58Mr0Qc4f BQ+I2ueCjTLWPYqgJ4g948qy0XJALHaHLWNAUaoMR7UgdTKwgnM+sNWp8VfYLTqW VCdLJYROkfheQ8l5116Q5QLUNu2XnV1kDU4pSLrNEw67da/2LEkggIwssUHde/Uz G6XjlSj9/GL6q/dqv50zWYr+0Jj+Mr7PWsAsDuXLOJvIaVsQ4Gi5IHgY/bvd3D9L rdP6cRs4vY21ydLb/do/7z7cTPTFph5Jp2p+F0rD3sj5hy2BdPJEItilrHkFrp0O O0UeZZCQdCvzn5O1EHhW6mqgdCnVUZdXLkaogchGF7+rE0VrBKY2RWTsH9Jgh9v3 DxSfZ9cmPYcSqkPbuIo1eF92hgBtk2SyiT6MvSxXnYb734C+vlkHntU7o0DiAqHL fnyfsVFtqa1iafE922skXgg4R2tcUB86zUtforxSDLK0AB0LGHOlGDsZoWLCqqZH b/a5SIAc52SU51Epa/ttwpkCAwEAAQ== -----END PUBLIC KEY----- public_keys/localhost.pem000066400000000000000000000014401470345337400533570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test/infracrl_test/master/conf/ssl-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnLP4Rj/WzZRM3aTIkdEg tDnDESliSBAgMu4C47FTKRmo34Pw2UA1g1Fs3Ofwjb9nvE/MpgRysLqPh+BKpXYs pwNnk6R6uifHB9l5FTtRyLxyGH42Mz7PHGqK8/QcohwZGgrDrl22Ic5GFWUZFScO ihhODjNMZFIw4ZZABc6oOczccZBuvg+ZOGgYQ5bLIwWJoGIVpJTLUtN7LuyGqd0l cWEIKkGfa2k14ERAmQ0imxOWKk3t2cmkt8wZ3JCawxZqkd/gszTESW5kYxZzXS4i Np4thDKIlK/Mafi8BE3diWYI0yAvhgzJ+quC+THVyb45n69W+2zb6v+dc01xdcJw Z3KQH4tFe0R451Ld5mZb6Ok48Mnu6uzVHEGlAyicSN1qq0L+agNwmKdIK1xucbZ/ B7lCRhWYHFNwY9fnO7+mOzuq5PXzeIBb1T8Q4LVLlMMrQ2jJBvehCtyLeoYcqB8o L2tr/gt0MHPgX1AnqRfrpal/IjYiludy7rndBQ3/QMA6lYnz9451gT2qVOUsfn54 YPhQic13keFveIRV9zVVjeq62ajEPBBKC4kBojMgxLE2KPiEtMFKXDeput5sa/2h GPIJCqDoqKa1F7hCKx/7bub7t29vwOUGfgYRjTt+CpcRQerU2ahjiKBbntOfkMBx KpEeuLGgNXfwhmi96p5s/Z8CAwEAAQ== -----END PUBLIC KEY----- puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/config/000077500000000000000000000000001470345337400271235ustar00rootroot00000000000000puppet_server_config_core_test/000077500000000000000000000000001470345337400353435ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/configpuppet.conf000066400000000000000000000001561470345337400375310ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/config/puppet_server_config_core_test[main] cadir = $confdir/ca autosign = true certname = localhost keylength = 2048 vardir = ./target/master-var puppet_server_config_service_test/000077500000000000000000000000001470345337400360535ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/configmaster/000077500000000000000000000000001470345337400373465ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/config/puppet_server_config_service_testconf/000077500000000000000000000000001470345337400402735ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/config/puppet_server_config_service_test/masterpuppet.conf000066400000000000000000000001151470345337400424540ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/config/puppet_server_config_service_test/master/conf[main] cadir = $confdir/ca certname = localhost vardir = ./target/master-var puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/000077500000000000000000000000001470345337400270115ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/jruby_pool_int_test/000077500000000000000000000000001470345337400331065ustar00rootroot00000000000000ca-cert.pem000066400000000000000000000036071470345337400350560ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/jruby_pool_int_test-----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDA5MjQwMDI2MjBaFw0xOTA5MjQwMDI2MjBa MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogbG9jYWxob3N0MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA5d7J0M924Hcchzs1MfZMn0qiIY5mhRLLfPsxm83Q vRl4rCmXt9Hnmq/kxU3c9+60bB/7z5gQOImHvfWJ7P23EI4DTSwNeAsRTva84nPD evasOkNwycMHIRUWXQUQIM/IHpTz/f+UccFpsJjWTckb5yhUkuSa+ukR0+YJzgTR XdKUfyh58TC95WSw93toJBZswepM5wf53s6gt0bMwhsMQKbMfDo7EOKS0py/bOIK YVT3r0ixOsQdH7AvpgybQ+IBK28LzAa5CVpq2IbdoxKluyEL0j4jHc3f6r5JiAp0 hF2OaBiw7JajWsoZPbeLADAFVWY90L9C2R/OL+kvR7O4dSYIR4a60wVJKXXnnY/C NPMS+Aqu4EV7xyh5JwO0dtqJfeIhnfMRYQO+nxwKKpw2E7lP+FthmuewDx5P7QYg vkjbLC4vXFkG8WNTPJSSKkUhgRNexl88RDPUF1E1cgHsKX9cRcNqitS2Au2LKY8o x4/fRqOwHLPcwgUIOKJWKKC7gneKB7IjS2R4pYv7iisyVKnF4G0/VKAQiOmW6c4g xCoZWSHqhIxzO9ReffesD+gnN5Kp+U0JSOdBMC7DAjsuHGlwi+gxBYy+yS1aMbyf hDPno487sjXBPG6U7pi4R/2EWFJ8GxC8iSSygD80FaQXJEvahgUILUgn1xFtIUBQ KukCAwEAAaOBqTCBpjAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRl cm5hbCBDZXJ0aWZpY2F0ZTAxBgNVHSMEKjAooSOkITAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdIIBATAdBgNVHQ4EFgQUeMyE9a6xFda+LhPQY+0eVEtI S4IwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL BQADggIBAMPM6AF3aaxBCDaMGaHvClzrWkIEMdUzGo0CBI8a+u6tmx+UD2zHxPtj rbMNyYLOwEcyBP67Wq06Z7rJW8/02cOI84DF971HClWhmz+UCswgh506HcppkykO /VU6itF9LLnLpv5OzGEUXeTV3dDRjgMQW0Z6PTbFyxQg/2urb82US2plx/xQw9X/ 3IxEzbbJM2ylG+ipTplhnO2PkTLv1kGGbJOGjs/Si5Rv+fLRoP+PpCRAoVT1tF36 i7ylmZJ70ZHLkCwjRueqJaI/LnUVeMM7k4gEYNkIE2s4Gg6G8aEHLFBfrLc5o52M +8xMArukOgifdlJq8ucdRNJ7AoHcBdayZczCJBlAe7xAUq85viSNIhjp7w7rI+cE wNkjUOYBd5wKgrDdw/0QWdm9arOV50/vfkoT0luMqgFPFD5tLiDcNNBT46ymWA7W Pqa1Z3uljcJDsk+UIabwzK+wbtPNT/7Mn4b3LBPFEGMLggOKss+lt4Rt47HZRce3 tcwf951BHNzWYfk2Ou3ZkpRbKNHj+M1UIPyDETCyfnvu534cgHjLk946V9b23tAc QKSz7YkYd5fq3pkPq6CNH04UL73jCwoHA4MZ2LZAKSOU1oSx2/tKpzlKLmr3RV1x eWxPXfiOYhyv8Im79UD5C/XNOAws+p85rfN0uAcoZdrhJp8glPqg -----END CERTIFICATE----- localhost-cert.pem000066400000000000000000000036131470345337400364600ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/jruby_pool_int_test-----BEGIN CERTIFICATE----- MIIFZTCCA02gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDA5MjQwMDI2MjdaFw0xOTA5MjQwMDI2Mjda MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAJ9SatJi8sCzU91ehCRRKvZ1hTrVrgvE6nDUVt8bBvi7BRJW4wAE49Wi MV/sfQqjxvfJ3zj6NH4ufDdApCIQ1UmAa6x+/wDzCk8r876bZBb45DVdEP4dYrIn DGsKFaFrlDwlL+YQw2bbwGkvUMiHZVWvD4yRK+dJkvHS+0139TPKP1s/R9NOrrrl OQdTSBQVBNqqHzDV9a/m9QY2LIh3L0OYjwtpJqXNyrC/I4nvcD7sxo7tI6w1LmeP f/KJBIHDSexD1Ubk/xT1uKcMQwbJ2jIqfALJERK7+ZfS9nY9tAA7sLRSbClF6V6J mmhVoE7c/ZqToOARi0rbUhMz/HpfmoEblze/vMRBHh1u/uLhF4aBK4uojccLh0xB stQm664EseNBbM195wpnv+woDO4D63hdngNBeilywnkSZ5r4okZ6F+AFQD9Om2Pe MWBjGxBbn8w3NqZNRuUkY2YUDjTeS/EjAdVrjXo/lQAe2/Imf7acbSKn2iyQrYzM 0Hl7xCTXuFskflDB/lqmd6lvCdCmiIFWsDhPqkec5byFC85291hy1EKO03SeHTD0 8dFmaSiCFWf6S/c5953ln5NXcvg+DibiagecpIdfvd5UDTgp44ABgvJeU8QQ0O+L N9DoeUwzL15Ou/faA4ubfbiJCxkMon0GiZjAZ614rRlwnLvYOKKhAgMBAAGjgbYw gbMwMQYJYIZIAYb4QgENBCQWIlB1cHBldCBTZXJ2ZXIgSW50ZXJuYWwgQ2VydGlm aWNhdGUwHwYDVR0jBBgwFoAUeMyE9a6xFda+LhPQY+0eVEtIS4IwHQYDVR0OBBYE FGqMJXJCPV2cmTD9vyjPgEBZQWiUMAwGA1UdEwEB/wQCMAAwIAYDVR0lAQH/BBYw FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDANBgkqhkiG9w0B AQsFAAOCAgEADY0gSoBFHo8Na7UrFMWNQExZLzSTuO0OV3St5VE3nDBRfO54ISim Y4i62RIyPUr+uOiQAGBHxQwThutHzKj7unFgfbP4jfGZS5OGV67rsgDL30eya5ut 7ThJuqYxoBloUIvX6XwCGgq5/59nuvk7jm5XSKxQxUsivSfg92kAj4n5h/FZSx3h UGMjjGL/Z6T6qLQ7H0v/2P0VrblwVtB6AdwHdiiTYtkyKEXTrYYU8jVu6jSG5ztL YEY5k8JAvc19KIIt0hT4AknccH8p6Bnw2tuu5o+ZUXYnezyOXVQ1bwQAogSncJxf wD3ibTEdQXabanophmLWd0UyjnQGokt/JlcP6KbLYjq7664lO5VsO8J//ejFW7hz 6rpLMmKjeTYH+Po8UZKdX/lV4rRAA2mAd2n8HBOfqnrahtbnZkYtgBUAaqa03bdR XTR4pPxoe/YkAZi4IaqUdCCtN0YF7Geu2iMxOjtEckeWx6cnnLE9z5gK9zpOl20d k5ed9u27/m7CIiWsHGbJ4jTm0EEpVuU0+s+3fMdctyfAfEBBag/8VQhKUrMxdHJI kjGGeKnGP4j9E2AuZ7f8qWcP9m12ZcTEYENfOipa0ssfk8yS/nLk7ULMk1ViapZE atmKI/0iWzZXFoPhb22UScydzclmfkDErxi7o1at+xX1rXNw1sTXVV4= -----END CERTIFICATE----- localhost-privkey.pem000066400000000000000000000062531470345337400372170ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/jruby_pool_int_test-----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEAn1Jq0mLywLNT3V6EJFEq9nWFOtWuC8TqcNRW3xsG+LsFElbj AATj1aIxX+x9CqPG98nfOPo0fi58N0CkIhDVSYBrrH7/APMKTyvzvptkFvjkNV0Q /h1isicMawoVoWuUPCUv5hDDZtvAaS9QyIdlVa8PjJEr50mS8dL7TXf1M8o/Wz9H 006uuuU5B1NIFBUE2qofMNX1r+b1BjYsiHcvQ5iPC2kmpc3KsL8jie9wPuzGju0j rDUuZ49/8okEgcNJ7EPVRuT/FPW4pwxDBsnaMip8AskRErv5l9L2dj20ADuwtFJs KUXpXomaaFWgTtz9mpOg4BGLSttSEzP8el+agRuXN7+8xEEeHW7+4uEXhoEri6iN xwuHTEGy1CbrrgSx40FszX3nCme/7CgM7gPreF2eA0F6KXLCeRJnmviiRnoX4AVA P06bY94xYGMbEFufzDc2pk1G5SRjZhQONN5L8SMB1WuNej+VAB7b8iZ/tpxtIqfa LJCtjMzQeXvEJNe4WyR+UMH+WqZ3qW8J0KaIgVawOE+qR5zlvIULznb3WHLUQo7T dJ4dMPTx0WZpKIIVZ/pL9zn3neWfk1dy+D4OJuJqB5ykh1+93lQNOCnjgAGC8l5T xBDQ74s30Oh5TDMvXk6799oDi5t9uIkLGQyifQaJmMBnrXitGXCcu9g4oqECAwEA AQKCAgBFXyWUJfF9ZpgFs7nl9lG2rsUsMQ5voXZTWqHY03PdqdEzgxGkWHy78Lt/ AQIRN+7Sxduke42Pw73icQsGqj20m25G1aVDTJAYmRKw1Aho2EbF1ZgojbMDz2zg zqtMdgM9jROmIXZzuwu0wR1zs0C0Zl1m3282bhrFoRA7Uxg5TL75hDxKDeCXEGgc gG7KD7zlWV3rbb5ksTPPWJdbdEnoLO1cEpT5bPnsq81VqiQ9wetTIH5/5UgnX5xe hrqnpdjyPzcGf39yKOwWEIi+0/VmEomczN/aQG8VZI5cPdG6qELwwVLHReGvgErz UxVSQXdLbyyFZB46ofTC18f/oNEs5g5+EcGxfX/h1Td6RW/KSO7UbsYTUloDzfIZ mwkfxAatyUfeur61GLGPa02aW2b/9w3w8rNpJRatuVWFABVnIvXe3As5+zngxKWL 7Qi2sny/qSbwV0Maw30LqelYwtLRGq9bnzGQvU/RlWPNxuN04/UUiHkSbjXHGU8Y yhHAchNPnJuU40hrwpbBmHc1OiY9/coWtH/wahYrQ163+79bpQ1TEdr1IBGE+x/g Vk6+hHM67r+yy3xTrvwy0AKjZWpzcMA2OqSJUoghy6vNo848XzyqyM8DIunwgK/c +YBF2d+6x+ZAc2PaKqGjKXVhnNKVOvVxGwsLky34r5mTQh3RYQKCAQEA151LmMa7 9dcr0JKcSGk3GYl7REkKuJpAW8eycKItZ+XHr+fypxsjxEsyi2bKNiYxYswG0d6e VaV84K25VxKC7d8ZrdpseKqBNYLfZQRZwNLRMbww58aGkNRyFBOgAkDFJO1suvA/ N+EToX0m3cBH/VlCQO3Yo69c1vTR9/q8Ap8S01Gx9fgFK9jGaks4f9tLQX/WBqYU yvjZxPoUXR3ANFyv4K9bokQpwh58PiBv2GUHqDGRrrh1vbv4VZBU5LzEXBLpRcxf /pDNqTvA5h1qAZJ3HuqY8rLdqNntRZ28l+iZMRklWdneE1YBKSV4rCk5SGeTevXa 1KSIifTnvewN2wKCAQEAvSnmHxGQBDaogyOUEBYE1JGCT4E31aQlTgCYOnYLufMP 3tXPZ4F6WC6tcHdLssX2+YwVQyS7McjGXgzcfDhbMT7b2twd2SLM/3cqM18YQOo+ N0xw9oQC8KT+anBm9jUMuT/FyYsS2XqEvJ9JNvAhHbtz6MZWA3RqPrhA3+pUM0w5 LK/fU9X4XhsU1UxJeub76eldM8jx7DSbU4loVX70tvViBzlZsThdItlm5o1KCcWg GwheaQVRiWyYrEmq9LeTg6bvThBQOXmIM0XKqfAkFtMJu1b5uSorDTWl1LCmH2zE CuUiOKRsvPFoL4UR0uhYOAtgfD0oIjCBtS+7vWugMwKCAQBVcZUKpv7HboyDbAYY v/FA4nWB2vwvqZkFhf6Vmf8qZCmc8Or9A8lJuY7/JS3PBZWelEHDm1fdkuYI129S LRjLkRTJC3ze2Jq5jPJgQrgarLCP6AbtYoPjEv1eLWTEX8yAVMI41ooG59/yp/jl +ZPNtziFKHwoaY799Cjc/3TQCR/ZtE80rSPHe3EtoD90k3+gJju3iMtGoBUUdRHq 0KZhWbWs8XD7vc1aiuArcolAFNFS+snDln+6P6oqpjauKowZ/LiKm3ITHGkTvoUz 68Ydd2BTVR5lVzJ1/l6Drv2UqW1DwrZFhAv4V6XAG4RVnUSBB+Ku4IzmpYkiOnY3 kjrvAoIBAHTgp4P4yQAheXsVh41s3W0tvtM65vHE6xvH+Ebe2x34lYy8lNrCQIKt zJIZ05bRBGlp6VVEI7l98Tr5PV4vQAEscpFGwdaAzyLlURjOn+C0Gt72BzH5nQtt FplTe/qSCpuHUMDXgj0Hm24kCQu90OhbAyIHMewOiPrZw5PWaFINvaHjxNw676vN ldC4wwoCIBKGEwVFGl00n+g8lU+GEtPcx8Xo5IdAaSN4KkE3eVCSX/tz70l6dMex Zp/FILD1oFqO0XttTvREKCht7euUKehEWtX6xm9nI5SU2jKRNwNho7uLmdpflaQk kJgT41BqKN/v/5yj+OEvEWWO6bP/BMsCggEAEUq3i1Jsq92D156U7rUd//XU1p7c akcwLlMS5k7BPBiLbaDHO8XX4zrX5N+s5TZnhzoduoFfxdgGSbFxymEv3F8xSz5X M6OdKfvvLnocZEpKX4Rb9XRWqVv/MQRxVGTUfiZ6DvOodSx2HJzFSP8nMQEABYUR vU05p3drU4pK7ox2G+IgsptxWKHQELtWRW7Cxeh7ED3s8mHKIfibSbEvJ9UK2sKm +XbOAeoOZAZQBU0zyVmX/oLsQmQVmkkG+OOrMEZioJGTvbXYIeFHCPcHe3TCjTfm KysgEhy7ilVCxLRN7+iX+RtWRgeWTp5WypMltqha2NN2C54zd7eZKSsSaw== -----END RSA PRIVATE KEY----- logback-test-restart-comes-back.xml000066400000000000000000000006611470345337400416170ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/jruby_pool_int_test ./target/test-restart-comes-back.log true %d %-5p [%t] [%c{2}] %m%n puppet.conf000066400000000000000000000000611470345337400352100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/jruby_pool_int_test[main] cadir = $confdir/ca certname = localhost puppet_environments_int_test/000077500000000000000000000000001470345337400347675ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jrubypuppet.conf000066400000000000000000000001711470345337400371520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/puppet_environments_int_test[main] cadir = $confdir/ca certname = localhost environmentpath = $confdir/environments environment_timeout = unlimited puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/request_handler_test/000077500000000000000000000000001470345337400332355ustar00rootroot00000000000000puppet.conf000066400000000000000000000000601470345337400353360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/jruby/request_handler_test[main] cadir = $confdir/ca certname = localhost puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/000077500000000000000000000000001470345337400271515ustar00rootroot00000000000000environment_classes_int_test/000077500000000000000000000000001470345337400350645ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/masterlogback-environment-classes-integration-cache-enabled-test.xml000066400000000000000000000007071470345337400511400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/environment_classes_int_test ./target/environment-classes-integration-cache-enabled.log true %d %-5p [%t] [%c{2}] %m%n puppet.conf000066400000000000000000000001611470345337400372460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/environment_classes_int_test[main] cadir = $confdir/ca certname = localhost environmentpath = $confdir/environments environment_timeout = 0 environment_modules_int_test/000077500000000000000000000000001470345337400350775ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/masterpuppet.conf000066400000000000000000000001611470345337400372610ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/environment_modules_int_test[main] cadir = $confdir/ca certname = localhost environmentpath = $confdir/environments environment_timeout = 0 environment_transports_int_test/000077500000000000000000000000001470345337400356465ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/masterpuppet.conf000066400000000000000000000001611470345337400400300ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/environment_transports_int_test[main] cadir = $confdir/ca certname = localhost environmentpath = $confdir/environments environment_timeout = 0 puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/000077500000000000000000000000001470345337400325135ustar00rootroot00000000000000bolt_projects/000077500000000000000000000000001470345337400353055ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_testembedded_e19e09/000077500000000000000000000000001470345337400400325ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projectsBoltdir/000077500000000000000000000000001470345337400414315ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/embedded_e19e09bolt-project.yaml000066400000000000000000000000171470345337400447170ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/embedded_e19e09/Boltdirname: embedded modules/000077500000000000000000000000001470345337400431015ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/embedded_e19e09/Boltdirtest/000077500000000000000000000000001470345337400440605ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/embedded_e19e09/Boltdir/modulesfiles/000077500000000000000000000000001470345337400451625ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/embedded_e19e09/Boltdir/modules/testpackages000066400000000000000000000000031470345337400466540ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/embedded_e19e09/Boltdir/modules/test/filesvimplans/000077500000000000000000000000001470345337400425465ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/embedded_e19e09/Boltdirinit.pp000066400000000000000000000002061470345337400440500ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/embedded_e19e09/Boltdir/plansplan embedded( TargetSpec $targets ) { $target_object = get_target($targets) return run_command("echo polo", $target_object) } local_23/000077500000000000000000000000001470345337400367035ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects.modules/000077500000000000000000000000001470345337400404315ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23utilities/000077500000000000000000000000001470345337400424445ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/.modulesfiles/000077500000000000000000000000001470345337400435465ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/.modules/utilitiesetc/000077500000000000000000000000001470345337400443215ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/.modules/utilities/filesgreeting000066400000000000000000000000151470345337400460440ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/.modules/utilities/files/etcGood morning tasks/000077500000000000000000000000001470345337400435715ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/.modules/utilitiesblah000066400000000000000000000000031470345337400444130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/.modules/utilities/tasksbyebolt-project.yaml000066400000000000000000000000141470345337400421660ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23name: local facts.d/000077500000000000000000000000001470345337400402255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23something000066400000000000000000000000121470345337400421360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/facts.dsomething lib/000077500000000000000000000000001470345337400374515ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23puppet/000077500000000000000000000000001470345337400407665ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/libcomment.rb000066400000000000000000000000261470345337400427530ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/lib/puppet# This is the project modules/000077500000000000000000000000001470345337400403535ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23helpers/000077500000000000000000000000001470345337400420155ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modulesfiles/000077500000000000000000000000001470345337400431175ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/helpersmarco.sh000066400000000000000000000000331470345337400445500ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/helpers/filesmarco () { echo "polo" } lib/000077500000000000000000000000001470345337400425635ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/helperspuppet/000077500000000000000000000000001470345337400441005ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/helpers/libmonkey_patch.rb000066400000000000000000000000571470345337400471100ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/helpers/lib/puppetclass NilClass def empty? true end end scripts/000077500000000000000000000000001470345337400435045ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/helpersyogurt.sh000066400000000000000000000000361470345337400453700ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/helpers/scriptsecho "Frozen, with sprinkles" unhelpers/000077500000000000000000000000001470345337400423605ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modulesfacts.d/000077500000000000000000000000001470345337400437025ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/unhelpersunhelpful000066400000000000000000000000241470345337400456230ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/unhelpers/facts.dfactually unhelpful lib/000077500000000000000000000000001470345337400431265ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/unhelperspuppet/000077500000000000000000000000001470345337400444435ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/unhelpers/libcomment.rb000066400000000000000000000000361470345337400464310ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/unhelpers/lib/puppet# This module is very helpful monkey_patch.rb000066400000000000000000000001601470345337400474460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/modules/unhelpers/lib/puppetclass Object def method_missing(m, *args, &block) self.send(self.methods.sample, *args, &block) end end plans/000077500000000000000000000000001470345337400400205ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23init.pp000066400000000000000000000002031470345337400413170ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/plansplan local( TargetSpec $targets ) { $target_object = get_target($targets) return run_command("echo polo", $target_object) } tasks/000077500000000000000000000000001470345337400400305ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23init.json000066400000000000000000000001601470345337400416630ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/tasks{ "description": "An example task that uses the ruby helper library", "files": ["helpers/files/marco.sh"] } init.sh000066400000000000000000000000571470345337400413310ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_23/tasks. $PT__installdir/helpers/files/marco.sh marco local_afafaf/000077500000000000000000000000001470345337400376635ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projectsbolt-project.yaml000066400000000000000000000000511470345337400431470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafafname: local modulepath: - "my-modules" modules/000077500000000000000000000000001470345337400413335ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafafutilities/000077500000000000000000000000001470345337400433465ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/modulesfiles/000077500000000000000000000000001470345337400444505ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/modules/utilitiesetc/000077500000000000000000000000001470345337400452235ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/modules/utilities/filesgreeting000066400000000000000000000000151470345337400467460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/modules/utilities/files/etcGood morning tasks/000077500000000000000000000000001470345337400444735ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/modules/utilitiesblah000066400000000000000000000000031470345337400453150ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/modules/utilities/tasksbyemy-modules/000077500000000000000000000000001470345337400417565ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafafhelpers/000077500000000000000000000000001470345337400434205ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/my-modulesfiles/000077500000000000000000000000001470345337400445225ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/my-modules/helpersmarco.sh000066400000000000000000000000331470345337400461530ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/my-modules/helpers/filesmarco () { echo "polo" } plans/000077500000000000000000000000001470345337400410005ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafafinit.pp000066400000000000000000000002031470345337400422770ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/plansplan local( TargetSpec $targets ) { $target_object = get_target($targets) return run_command("echo polo", $target_object) } tasks/000077500000000000000000000000001470345337400410105ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafafinit.json000066400000000000000000000001601470345337400426430ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/tasks{ "description": "An example task that uses the ruby helper library", "files": ["helpers/files/marco.sh"] } init.sh000066400000000000000000000000571470345337400423110ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/local_afafaf/tasks. $PT__installdir/helpers/files/marco.sh marco override_builtin_content/000077500000000000000000000000001470345337400424045ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projectsbolt-project.yaml000066400000000000000000000000141470345337400456670ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_contentname: local modules/000077500000000000000000000000001470345337400440545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_contentbic_module_one/000077500000000000000000000000001470345337400470175ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modulesfiles/000077500000000000000000000000001470345337400501215ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modules/bic_module_onefiles/marco.sh000066400000000000000000000000331470345337400515520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modules/bic_module_onemarco () { echo "polo" } lib/000077500000000000000000000000001470345337400475655ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modules/bic_module_onelib/puppet/000077500000000000000000000000001470345337400511025ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modules/bic_module_onelib/puppet/builtin_monkey_patch.rb000066400000000000000000000000721470345337400556350ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modules/bic_module_oneoverridden_class NilClass def empty? true end end tasks/000077500000000000000000000000001470345337400501445ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modules/bic_module_onetasks/init.json000066400000000000000000000001601470345337400517770ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modules/bic_module_one{ "description": "An example task that uses the ruby helper library", "files": ["helpers/files/marco.sh"] } tasks/init.sh000066400000000000000000000000701470345337400514400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/bolt_projects/override_builtin_content/modules/bic_module_one. $PT__installdir/helpers/files/marco.sh override_marco builtin_bolt_content/000077500000000000000000000000001470345337400366545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_testbic_module_one/000077500000000000000000000000001470345337400416175ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_contentfiles/000077500000000000000000000000001470345337400427215ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_onemarco.sh000066400000000000000000000000331470345337400443520ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_one/filesmarco () { echo "polo" } lib/000077500000000000000000000000001470345337400423655ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_onepuppet/000077500000000000000000000000001470345337400437025ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_one/libbuiltin_monkey_patch.rb000066400000000000000000000000571470345337400504400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_one/lib/puppetclass NilClass def empty? true end end tasks/000077500000000000000000000000001470345337400427445ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_oneinit.json000066400000000000000000000001601470345337400445770ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_one/tasks{ "description": "An example task that uses the ruby helper library", "files": ["helpers/files/marco.sh"] } init.sh000066400000000000000000000000571470345337400442450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_one/tasks. $PT__installdir/helpers/files/marco.sh marco bic_module_two/000077500000000000000000000000001470345337400416475ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_contentfiles/000077500000000000000000000000001470345337400427515ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_twomarco.sh000066400000000000000000000000331470345337400444020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_two/filesmarco () { echo "polo" } lib/000077500000000000000000000000001470345337400424155ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_twopuppet/000077500000000000000000000000001470345337400437325ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_two/libmonkey_patch.rb000066400000000000000000000000571470345337400467420ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_two/lib/puppetclass NilClass def empty? true end end tasks/000077500000000000000000000000001470345337400427745ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_twoinit.json000066400000000000000000000001601470345337400446270ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_two/tasks{ "description": "An example task that uses the ruby helper library", "files": ["helpers/files/marco.sh"] } init.sh000066400000000000000000000000571470345337400442750ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_core_test/builtin_bolt_content/bic_module_two/tasks. $PT__installdir/helpers/files/marco.sh marco puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/000077500000000000000000000000001470345337400332235ustar00rootroot00000000000000codedir/000077500000000000000000000000001470345337400345555ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_testenvironments/000077500000000000000000000000001470345337400373045ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedirproduction/000077500000000000000000000000001470345337400414725ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedir/environmentsmodules/000077500000000000000000000000001470345337400431425ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedir/environments/productionfoo/000077500000000000000000000000001470345337400437255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedir/environments/production/modulesmanifests/000077500000000000000000000000001470345337400457165ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedir/environments/production/modules/foobar.pp000066400000000000000000000002451470345337400470240ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedir/environments/production/modules/foo/manifestsclass foo::bar inherits foo { include foo::baz notify { "Foo::Bar": } $digest = digest("Foo::Bar") notify { "Foo Digest": message => $digest, } }baz.pp000066400000000000000000000000551470345337400470330ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedir/environments/production/modules/foo/manifestsclass foo::baz { notify { "FOO::BAZ!": } }init.pp000066400000000000000000000000711470345337400472200ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedir/environments/production/modules/foo/manifestsclass foo inherits foo::params { notify { "Foo!": } }params.pp000066400000000000000000000000541470345337400475410ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/codedir/environments/production/modules/foo/manifestsclass foo::params { $param1 = "param1!" }confdir/000077500000000000000000000000001470345337400345705ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_testauth.conf000066400000000000000000000000271470345337400363770ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/confdirpath / auth any allow *puppet.conf000066400000000000000000000005061470345337400367550ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/confdir[server] cadir = $confdir/ca certname = localhost node_terminus = exec facts_terminus = yaml external_nodes = "/bin/sh ./dev-resources/puppetlabs/services/master/master_service_test/enc.sh" reports = http # so long as the host and port are accessible, the endpoint here doesn't matter reporturl = https://localhost:8140/fake puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/master_service_test/enc.sh000066400000000000000000000000631470345337400343230ustar00rootroot00000000000000#!/usr/bin/env sh printf "classes:\n foo::bar:\n"puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/plans_int_test/000077500000000000000000000000001470345337400321775ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/plans_int_test/puppet.conf000066400000000000000000000001611470345337400343610ustar00rootroot00000000000000[main] cadir = $confdir/ca certname = localhost environmentpath = $confdir/environments environment_timeout = 0 puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/tasks_int_test/000077500000000000000000000000001470345337400322075ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/tasks_int_test/echo000077500000000000000000000000331470345337400330470ustar00rootroot00000000000000#!/usr/bin/env sh echo $@ puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/tasks_int_test/hello_world000077500000000000000000000000641470345337400344470ustar00rootroot00000000000000#!/usr/bin/env bash echo -n "echo 'Hello, world!'" puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/tasks_int_test/puppet.conf000066400000000000000000000001611470345337400343710ustar00rootroot00000000000000[main] cadir = $confdir/ca certname = localhost environmentpath = $confdir/environments environment_timeout = 0 warn_echo_and_error000077500000000000000000000000571470345337400360600ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/master/tasks_int_test#!/usr/bin/env sh echo $@ echo $@ 1>&2 exit 1 puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/puppet_admin/000077500000000000000000000000001470345337400303435ustar00rootroot00000000000000puppet_admin_int_test/000077500000000000000000000000001470345337400346625ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/puppet_adminpuppet.conf000066400000000000000000000000611470345337400370430ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/puppet_admin/puppet_admin_int_test[main] cadir = $confdir/ca certname = localhost puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/request_handler/000077500000000000000000000000001470345337400310435ustar00rootroot00000000000000request_handler_core_test/000077500000000000000000000000001470345337400362205ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/request_handlerlocalhost.pem000066400000000000000000000037311470345337400407170ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/request_handler/request_handler_core_test-----BEGIN CERTIFICATE----- MIIFnjCCA4agAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDAyMTQxODA5MDdaFw0xOTAyMTQxODA5MDda MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBALzn4xcbGhSX65fgSIo+NB4EOYX+zJxbHamv+hbQkhAxqHxUSszDD86+ s9ZsN8cvpDIRex1/SfkNRKhgVUHGiUYbol+9RLpgpdHYLJCY0S0kOyBUgWqEcQrA tVDYpwaNC5qMneiZkcNvQ74pnuFOa0/bzbpLyOjYKEQq3BXK32yGLLHseb/PIX1o bqcuYiR6yI7S3wK9hJzSo6BRPSz0cNZNpnXbW/yLRtHbthBtzTifM2MW2jtWuFvg OW1ly9vxwTHCrJv5KxMubVDrqAx+RmmOsn327APO3r6NUr2CzV1vG8CMqLApse6m dKpCZ5UNLm4dwCUe2zWAQ0Q2Eba88O480bH8k/t8NUGXlWt25B8BUE8rklY0jwSw v8Dyjda0moeoxgMMZb+ogPjTY/Ds/h2hgFzy/DUuGrv6kyVxzH0/pOg29HeDoUaK IaqjAsN8h/oYTJ6CiOKAqWfbi8JZRmiEVTekskS5eySsPqPCegfAkfpIlz4EU4FN 0A2vORI7epW4mNiJcCLb09v5jogK+DhfeSscDsrYgIF8eAPLw6r9h1am+vXoD6vt tIwZBu15pnCWXdDcKWBNjx+zYU648iZ9V/qFG31uTJaw0z18eFPyTcJN8StTnoGZ zjKI2AyjG5F6ov/S7mnU3I/wv0B5Vq6fPjSvMrsBlbBdI3Pbr3w/AgMBAAGjge8w gewwNQYJYIZIAYb4QgENBChQdXBwZXQgUnVieS9PcGVuU1NMIEludGVybmFsIENl cnRpZmljYXRlMFQGA1UdEQRNMEuCG2Rqcm9vbWJhLnZwbi5wdXBwZXRsYWJzLm5l dIIJbG9jYWxob3N0ggZwdXBwZXSCGXB1cHBldC52cG4ucHVwcGV0bGFicy5uZXQw DgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcD AjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRZy3D0vQGiBu3mnggq8jiEZERoXzAN BgkqhkiG9w0BAQsFAAOCAgEAJwDAK7UKZvLtSJkdprO/Z0qALdUSliO0+I6lsSr/ A8SyilfMQuxOoq6uWA6j7uMU4SAHwT14QD9c6BJJiBhWLo6HoynZfYK8Smn1q2Xy vNMnUEUEjcWIgIqEDP98RTUZldgR4aWQkQVHB9XY8g6F0qWzBq64qLWjfrsIUijF Z3Ex1OMU7ZMjHhoKk2J3oBcMau47mqU49C9MoWkBH+0fLLr+lxoa40DPcFr+KzhI BHdTKuKAEJEkiE5QNVWl3+M7psFZzdTd+YFz9Vn/9L3aQr8KCb4oMietp84KM0yR 6GwodvIjh/3owsnvNvl28HeZGWQMCNIlG0aWx3JIfCOHSYlXfQ55FCtLRqMflJty M4MqRkPHKykZMZmNoiTtXRSz3vMW8JnIyZPsNtfIGltnpjHd4Y4EEVxdZhlL2wBv YycI6PN1oyhv/9ZcIbSaVY4jEpxx6mrsG8iuaT1YHlO2HOwuqvXJ48WkT1Q6go9k A775N00y4jLJXqWchiuP9Hp7AGYWzoKXFDmQbUyl0jpZsrfoTskb90xp6R7+IO7K 6opzTahhO9QeURqc7lkdvwjiYMw7uIiTT6IAKtYeK4f52siiJ/LBWucte5FLCjvq KkdWF7aQOKZq+L7Cs2nJ/qQQzlDYTQLpAbBWJbVAscoYYGPVPdKrwI4UEbKGIsWs wMA= -----END CERTIFICATE----- master-with-all-cas.pem000066400000000000000000000077451470345337400425160ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/request_handler/request_handler_core_test-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MSQwIgYDVQQDExtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoTEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsTEVNl cnZlciBPcGVyYXRpb25zMB4XDTE0MDQwODAxMjUzN1oXDTM0MDQwMzAxMjUzN1ow HjEcMBoGA1UEAwwTbWFzdGVyMS5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBANtT0Se0OBG+bU3ZbZ2IxiSKNs7ZxDBoyXVeVGvOvEQW 56TkHnYdoJ3bn3zLctAoWMggv4DxO0nncmVJYbFoeZo9n7viUQdsO8+hTWVJCjov uZYNO88Q5NE4zP/Pi9IWigOzjNMl959ItGI0Sr/aPZUpsc/V6eEpyY0eREGG6Ixa eeO2z/kU4mqO9CK4VzNxfZQqAi0kJEEp2gQ8Ax0gCXee4gbBF7zvyi6467Q3hJTf 413cL0jMIPHbNiyXdLlzjtmkYDL9mjnXbL1W339twBgPzs/ZjDqR4IBK4Fzqakoz WvWbp1aTYkRqSBiNRHtiQleCXG7JU6FDeF/wzXXWkWECAwEAAaOB2TCB1jBbBgNV HSMEVDBSoU2kSzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIg T3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMB Af8EAjAAMAsGA1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH AwIwPQYDVR0RBDYwNIITbWFzdGVyMS5leGFtcGxlLm9yZ4IHbWFzdGVyMYIGcHVw cGV0ggxwdXBwZXRtYXN0ZXIwDQYJKoZIhvcNAQEFBQADggEBAFUas+1NvtqTsT8X CHiwL/njj7at7V6BsF5yw/MnJ2oEwkJpfsp7J3aB/R1s5bxjtxOJ5fVzED3L0uIf we29p16rdSeINn9D/LShF7SUFIB3GokT/L5gHgYPLGH4itmz+GKul6qBdt0bOydM 1CqfKTmMEvH0sicEDRFIxji+dfrS6lPhdDHkdKGJeEWpNuATYmw24NYOIpO+4Bv7 oVXn5hoZp5VzbokCzVha1hlsUeG+wp3GnOoN2aaAm3LZNqKLhm5dKoNeRtECFEOu +GViwgc9RG4GN4jNDGU03+z+SMozlt3cc+osIxeOKExiK2dfhJwA9Uj1uvYYnSuy /hHeAt4= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID3zCCAsegAwIBAgIBAjANBgkqhkiG9w0BAQUFADBJMRAwDgYDVQQDDAdSb290 IENBMRowGAYDVQQLDBFTZXJ2ZXIgT3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBs ZSBPcmcsIExMQzAeFw0xNDA0MDgwMTI1MzdaFw0zNDA0MDMwMTI1MzdaMH4xJDAi BgNVBAMTG0ludGVybWVkaWF0ZSBDQSAobWFzdGVyLWNhKTEfMB0GCSqGSIb3DQEJ ARYQdGVzdEBleGFtcGxlLm9yZzEZMBcGA1UEChMQRXhhbXBsZSBPcmcsIExMQzEa MBgGA1UECxMRU2VydmVyIE9wZXJhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDTgKLGBkExFRXrQJn/lHE4XHkN2nXwJpS+y8bWqHiBdq5eZ8D2 UAILOBaALeQN/1d1J4yrh6w/YK+gRtCLn+CslR+9NW4AgShALi+r26DK9ZRk4F7V Dk4yEjNpmTyVRyP8w7iZwasZdyK04xAhj+yEInz29SLxmh1jddts/rjqLMZW/s0S T+E9XSEDYNVprC5VuYutUuHKah7AYSp07FHNsqDg+y+vCRezSqbrHrGpTwMupVmD 2ObsSJntghsLzPwjSGhbo6e8C/TDwrPtm6az9TPKbsUrqjdvyZcSfc5Q6OgExNhg zWQkk5PqFOESsQSBfOOn2eqfqBXHUnH9PCNTAgMBAAGjgZwwgZkweQYDVR0jBHIw cIAUFq+AJeP66ki/kTNmAf1R7yRnTGOhTaRLMEkxEDAOBgNVBAMMB1Jvb3QgQ0Ex GjAYBgNVBAsMEVNlcnZlciBPcGVyYXRpb25zMRkwFwYDVQQKDBBFeGFtcGxlIE9y ZywgTExDggkAsbkEcvsRJ+MwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYw DQYJKoZIhvcNAQEFBQADggEBAC4keJ+jeGh7/EWwsCKollYW7H4aSjPu/Ufe38hH pEER9FyCqJ0jo+MabOx8l1F5ySNWngB0qbJuA/kiV2gJ1bQ+mE2TN88x6Sz12eol ifhFU0PazGdpNQRhpQxbwJ7tFC3Z8WrHEcVqP9iicNWqSI/QkqXsCk4Zyezpx28W sqHylf1CiBOU45FJdDXRg80mk6WOpNZR8HIUdqQLQDXz0FfXeFKmVteatmc/yrGG 5iHzMkH4Vz5laBjin9s1p+O8Z7+cWtJNWfXaULAEecZQ6CZ3V1OVOjhsrL28iF7C kx01rSrsxaFclDalJVmKmO2spHvNmQTlWD6jm5d94WaRyXU= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDZTCCAk2gAwIBAgIJALG5BHL7ESfjMA0GCSqGSIb3DQEBBQUAMEkxEDAOBgNV BAMMB1Jvb3QgQ0ExGjAYBgNVBAsMEVNlcnZlciBPcGVyYXRpb25zMRkwFwYDVQQK DBBFeGFtcGxlIE9yZywgTExDMB4XDTE0MDQwODAxMjUzNloXDTM0MDQwMzAxMjUz NlowSTEQMA4GA1UEAwwHUm9vdCBDQTEaMBgGA1UECwwRU2VydmVyIE9wZXJhdGlv bnMxGTAXBgNVBAoMEEV4YW1wbGUgT3JnLCBMTEMwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQDFDXbR+00AwXM+HuMIpw8eVWBzQWBqDCYkX3IvYRGj+w9y 7AitrN+J0MZE3pbaRvlH5wU7MShFOmT0k/B/wrylW4W5G/iAtd2ZnXicBPrA9zDU eHJftQxR7+Qjmsc1BqVf43PUlQITpn1APgXDzPJdk9XbRWEsIycuXkwTXzVND0U5 z3dGS/oh9yMim0DnF2oQ+gTFA9n17xOD5hBN80U3fn4DXtcFGbtXOj6zBHsxgLCi leif2AB1oAaZ0lqkwk6Se0rFd3zafYLDAwCPCWlZSfkQ0C/W7WYx07PDRxSYs1H6 Viz2uHwqzyD6elxvJBGcrLdvDqTLL+w0ag3yMPWbAgMBAAGjUDBOMB0GA1UdDgQW BBQWr4Al4/rqSL+RM2YB/VHvJGdMYzAfBgNVHSMEGDAWgBQWr4Al4/rqSL+RM2YB /VHvJGdMYzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQC/sFnu1TIr L6HhTft5aUaeLuO/329cDUHxlUppGRYrctkZvYK4b8TBi2BD+tcwRKS1kh4nrQhr xaBO+oUmyJeNwEPk40trzusV9N9tfqw8drBBXEVZGxrYRYovq/RqLfUQ224EF3z0 r74dAWL0R80PvVzeJfUsUw0KYgskfLzP5QSW1rrJnutfYP95EMV4yWyrNqnDko3M v7XENh0TMEolMxPZ+X3TqT6Q0j4aM8njswObyeABslt+nC6nLfgBvgDaSvEULPL6 u5aWNxp9WudGqGBvHoR6OXdZDRCzWSz52jnvXiZE4E0VnqsWxCmjDGECke4TRoMU rtMLavKgCsIe -----END CERTIFICATE----- master.pem000066400000000000000000000026241470345337400402220ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/request_handler/request_handler_core_test-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MSQwIgYDVQQDExtJbnRl cm1lZGlhdGUgQ0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhh bXBsZS5vcmcxGTAXBgNVBAoTEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsTEVNl cnZlciBPcGVyYXRpb25zMB4XDTE0MDQwODAxMjUzN1oXDTM0MDQwMzAxMjUzN1ow HjEcMBoGA1UEAwwTbWFzdGVyMS5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBANtT0Se0OBG+bU3ZbZ2IxiSKNs7ZxDBoyXVeVGvOvEQW 56TkHnYdoJ3bn3zLctAoWMggv4DxO0nncmVJYbFoeZo9n7viUQdsO8+hTWVJCjov uZYNO88Q5NE4zP/Pi9IWigOzjNMl959ItGI0Sr/aPZUpsc/V6eEpyY0eREGG6Ixa eeO2z/kU4mqO9CK4VzNxfZQqAi0kJEEp2gQ8Ax0gCXee4gbBF7zvyi6467Q3hJTf 413cL0jMIPHbNiyXdLlzjtmkYDL9mjnXbL1W339twBgPzs/ZjDqR4IBK4Fzqakoz WvWbp1aTYkRqSBiNRHtiQleCXG7JU6FDeF/wzXXWkWECAwEAAaOB2TCB1jBbBgNV HSMEVDBSoU2kSzBJMRAwDgYDVQQDDAdSb290IENBMRowGAYDVQQLDBFTZXJ2ZXIg T3BlcmF0aW9uczEZMBcGA1UECgwQRXhhbXBsZSBPcmcsIExMQ4IBAjAMBgNVHRMB Af8EAjAAMAsGA1UdDwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH AwIwPQYDVR0RBDYwNIITbWFzdGVyMS5leGFtcGxlLm9yZ4IHbWFzdGVyMYIGcHVw cGV0ggxwdXBwZXRtYXN0ZXIwDQYJKoZIhvcNAQEFBQADggEBAFUas+1NvtqTsT8X CHiwL/njj7at7V6BsF5yw/MnJ2oEwkJpfsp7J3aB/R1s5bxjtxOJ5fVzED3L0uIf we29p16rdSeINn9D/LShF7SUFIB3GokT/L5gHgYPLGH4itmz+GKul6qBdt0bOydM 1CqfKTmMEvH0sicEDRFIxji+dfrS6lPhdDHkdKGJeEWpNuATYmw24NYOIpO+4Bv7 oVXn5hoZp5VzbokCzVha1hlsUeG+wp3GnOoN2aaAm3LZNqKLhm5dKoNeRtECFEOu +GViwgc9RG4GN4jNDGU03+z+SMozlt3cc+osIxeOKExiK2dfhJwA9Uj1uvYYnSuy /hHeAt4= -----END CERTIFICATE----- puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/versioned_code_service/000077500000000000000000000000001470345337400323665ustar00rootroot00000000000000versioned_code_core_test/000077500000000000000000000000001470345337400373465ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/versioned_code_serviceecho000077500000000000000000000000331470345337400402060ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/versioned_code_service/versioned_code_core_test#!/usr/bin/env sh echo $@ invalid_code_id000077500000000000000000000000561470345337400423710ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/versioned_code_service/versioned_code_core_test#!/usr/bin/env sh echo "not a valid code id" warn000077500000000000000000000000401470345337400402350ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/versioned_code_service/versioned_code_core_test#!/usr/bin/env sh echo $@ 1>&2 warn_echo_and_error000077500000000000000000000000571470345337400432760ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/versioned_code_service/versioned_code_core_test#!/usr/bin/env sh echo $@ echo $@ 1>&2 exit 1 versioned_code_service_test/000077500000000000000000000000001470345337400400565ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/versioned_code_serviceecho000077500000000000000000000000331470345337400407160ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/dev-resources/puppetlabs/services/versioned_code_service/versioned_code_service_test#!/usr/bin/env sh echo $@ puppetlabs-puppetserver-7e1a9a8/dev-resources/regen_certs.rb000066400000000000000000000142211470345337400245010ustar00rootroot00000000000000require 'openssl' module PuppetSpec module SSL PRIVATE_KEY_LENGTH = 2048 FIVE_YEARS = 5 * 365 * 24 * 60 * 60 CA_EXTENSIONS = [ ["basicConstraints", "CA:TRUE", true], ["keyUsage", "keyCertSign, cRLSign", true], ["subjectKeyIdentifier", "hash", false], ["authorityKeyIdentifier", "keyid:always", false] ] NODE_EXTENSIONS = [ ["keyUsage", "digitalSignature,keyEncipherment", true], ["subjectKeyIdentifier", "hash", false] ] DEFAULT_SIGNING_DIGEST = OpenSSL::Digest::SHA256.new DEFAULT_REVOCATION_REASON = OpenSSL::OCSP::REVOKED_STATUS_KEYCOMPROMISE def self.create_private_key(length = PRIVATE_KEY_LENGTH) OpenSSL::PKey::RSA.new(length) end def self.self_signed_ca(key, name, serial = rand(2**128)) cert = OpenSSL::X509::Certificate.new cert.public_key = key.public_key cert.subject = OpenSSL::X509::Name.parse(name) cert.issuer = cert.subject cert.version = 2 cert.serial = serial not_before = just_now cert.not_before = not_before cert.not_after = not_before + FIVE_YEARS ext_factory = extension_factory_for(cert, cert) CA_EXTENSIONS.each do |ext| extension = ext_factory.create_extension(*ext) cert.add_extension(extension) end cert.sign(key, DEFAULT_SIGNING_DIGEST) cert end def self.create_crl(ca_cert, ca_key, revoked_cert, serial) crl = OpenSSL::X509::CRL.new crl.issuer = ca_cert.issuer crl.version = 1 last_update = just_now crl.last_update = last_update crl.next_update = last_update + FIVE_YEARS revoked = OpenSSL::X509::Revoked.new revoked.serial = revoked_cert.serial revoked.time = just_now crl.add_revoked(revoked) crlnum = OpenSSL::ASN1::Integer(serial) crl.add_extension(OpenSSL::X509::Extension.new('crlNumber', crlnum)) ef = OpenSSL::X509::ExtensionFactory.new ef.issuer_certificate = ca_cert ef.crl = crl crl.add_extension(ef.create_extension('authorityKeyIdentifier', 'keyid:always')) crl.sign(ca_key, DEFAULT_SIGNING_DIGEST) crl end def self.create_csr(name, key = PuppetSpec::SSL.create_private_key) csr = OpenSSL::X509::Request.new csr.public_key = key.public_key csr.subject = OpenSSL::X509::Name.parse(name) csr.version = 2 csr.sign(key, DEFAULT_SIGNING_DIGEST) csr end def self.sign(ca_key, ca_cert, csr, serial = rand(2**128), extensions = NODE_EXTENSIONS) cert = OpenSSL::X509::Certificate.new cert.public_key = csr.public_key cert.subject = csr.subject cert.issuer = ca_cert.subject cert.version = 2 cert.serial = serial not_before = just_now cert.not_before = not_before cert.not_after = not_before + FIVE_YEARS ext_factory = extension_factory_for(ca_cert, cert) extensions.each do |ext| extension = ext_factory.create_extension(*ext) cert.add_extension(extension) end cert.sign(ca_key, DEFAULT_SIGNING_DIGEST) cert end private def self.just_now Time.now - 1 end def self.extension_factory_for(ca, cert = nil) ef = OpenSSL::X509::ExtensionFactory.new ef.issuer_certificate = ca ef.subject_certificate = cert if cert ef end def self.bundle(*items) items.map {|i| EXPLANATORY_TEXT + i.to_pem }.join("\n") end end end puts 'Regenerating certificates for puppetlabs.puppetserver.ruby.http-client-test ...' ca_key = PuppetSpec::SSL.create_private_key ca_cert = PuppetSpec::SSL.self_signed_ca(ca_key, "/CN=Puppet CA: swanson.hsd1.or.comcast.net") host_key = PuppetSpec::SSL.create_private_key host_csr = PuppetSpec::SSL.create_csr("/CN=localhost", host_key) host_cert = PuppetSpec::SSL.sign(ca_key, ca_cert, host_csr) http_client_test_dir = "#{__dir__}/puppetlabs/puppetserver/ruby/http_client_test" File.open("#{http_client_test_dir}/ca.pem", 'w') do |f| f.puts(ca_cert) end File.open("#{http_client_test_dir}/localhost_cert.pem", 'w') do |f| f.puts(host_cert) end File.open("#{http_client_test_dir}/localhost_key.pem", 'w') do |f| f.puts(host_key) end puts 'Regenerating certificates for puppetlabs.puppetserver.certificate-authority-test ...' ca_key = PuppetSpec::SSL.create_private_key ca_cert = PuppetSpec::SSL.self_signed_ca(ca_key, "/CN=Puppet CA: localhost", 1) test_agent_csr = PuppetSpec::SSL.create_csr("/CN=test-agent") localhost_csr = PuppetSpec::SSL.create_csr("/CN=localhost") localhost_cert = PuppetSpec::SSL.sign(ca_key, ca_cert, localhost_csr, 2) test_cert_csr = PuppetSpec::SSL.create_csr("/CN=test_cert") test_cert = PuppetSpec::SSL.sign(ca_key, ca_cert, test_cert_csr, 3) revoked_agent_csr = PuppetSpec::SSL.create_csr("/CN=revoked-agent") revoked_agent_cert = PuppetSpec::SSL.sign(ca_key, ca_cert, revoked_agent_csr, 4) ca_crl = PuppetSpec::SSL.create_crl(ca_cert, ca_key, revoked_agent_cert, 1) ca_dir = "#{__dir__}/puppetlabs/puppetserver/certificate_authority_test/master/conf/ca" File.open("#{ca_dir}/ca_key.pem", 'w') do |f| f.puts(ca_key) end File.open("#{ca_dir}/ca_pub.pem", 'w') do |f| f.puts(ca_key.public_key) end File.open("#{ca_dir}/ca_crt.pem", 'w') do |f| f.puts(ca_cert) end File.open("#{ca_dir}/requests/test-agent.pem", 'w') do |f| f.puts(test_agent_csr) end File.open("#{ca_dir}/signed/localhost.pem", 'w') do |f| f.puts(localhost_cert) end File.open("#{ca_dir}/signed/test_cert.pem", 'w') do |f| f.puts(test_cert) end File.open("#{ca_dir}/signed/revoked-agent.pem", 'w') do |f| f.puts(revoked_agent_cert) end File.open("#{ca_dir}/ca_crl.pem", 'w') do |f| f.puts(ca_crl) end File.open("#{ca_dir}/serial", 'w') do |f| f.write('0005') end File.open("#{ca_dir}/infra_crl.pem", 'w') { |f| f.truncate(0) } File.open("#{ca_dir}/infra_serials", 'w') { |f| f.truncate(0) } File.open("#{ca_dir}/inventory.txt", 'w') do |f| for cert in [ ca_cert, localhost_cert, test_cert, revoked_agent_cert ] do serial_hex = "0x#{cert.serial.to_s(16).rjust(4, '0')}" not_before = cert.not_before.strftime('%Y-%m-%dT%H:%M:%SUTC') not_after = cert.not_after.strftime('%Y-%m-%dT%H:%M:%SUTC') subject = cert.subject f.puts("#{serial_hex} #{not_before} #{not_after} #{subject}") end end puts "Done." puppetlabs-puppetserver-7e1a9a8/dev-setup000077500000000000000000000035561470345337400207410ustar00rootroot00000000000000#!/usr/bin/env bash set -e # TODO: Ultimately it'd be nice to not hard-code these paths, because it is # not guaranteed to match up with the paths in puppetserver.conf or used by the # REPL. That said, it doesn't seem like a great ROI to sort it out right now # because it will probably require introducing a new setting for the vendored gem # dir into puppetserver.conf. ROOTDIR="${HOME}/.puppetlabs" CONFDIR="${ROOTDIR}/etc/puppet" CODEDIR="${ROOTDIR}/etc/code" gem_list=() while read LINE do gem_name=$(echo $LINE |awk '{print $1}') gem_version=$(echo $LINE |awk '{print $2}') gem_list+=("$gem_name:$gem_version") done < ./resources/ext/build-scripts/jruby-gem-list.txt while read LINE do gem_name=$(echo $LINE |awk '{print $1}') gem_version=$(echo $LINE |awk '{print $2}') gem_list+=("$gem_name:$gem_version") done < ./resources/ext/build-scripts/jruby-stdlib-gem-list.txt echo "Installing vendored gems" lein gem install --no-document "${gem_list[@]}" echo "Setting up puppet.conf for dev environment" # TODO: current implementation will simply overwrite puppet.conf. Might be better # to add some checks at the beginning of this script, and abort the whole script # if it already exists. if [ -z "${MASTERHOST}" ]; then echo " No value specified for environment variable 'MASTERHOST'; using 'localhost' for puppet certname." CERTNAME="localhost" else echo " Found environment variable 'MASTERHOST'; using value '${MASTERHOST}' for puppet certname." CERTNAME="${MASTERHOST}" fi mkdir -p "${CONFDIR}" cat > "${CONFDIR}/puppet.conf" < (val f) meta :doc)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utilities for interacting with running system (defn context "Get the current TK application context. Accepts an optional array argument, which is treated as a sequence of keys to retrieve a nested subset of the map (a la `get-in`)." ([] (context [])) ([keys] (get-in @(tka/app-context system) keys))) (defn print-context "Pretty-print the current TK application context. Accepts an optional array of keys (a la `get-in`) to print a nested subset of the context." ([] (print-context [])) ([keys] (pprint/pprint (context keys)))) (defn jruby-pool "Returns a reference to the current pool of JRuby interpreters." [] (jruby-core/registered-instances (context [:service-contexts :JRubyPuppetService :pool-context]))) (defn- puppet-environment-state "Given a JRuby instance, return the state information about the environments that it is aware of." [jruby-instance] {:jruby-instance-id (:id jruby-instance) :environment-states (-> jruby-instance :environment-registry puppet-env/environment-state deref)}) (defn print-puppet-environment-states "Print state information about the environments that each JRuby instance is aware of." [] (pprint/pprint (map puppet-environment-state (jruby-pool)))) (defn mark-environment-expired! "Mark the specified environment, on all JRuby instances, stale so that it will be flushed from the environment cache." [env-name] (jruby-protocol/mark-environment-expired! (tka/get-service system :JRubyPuppetService) env-name)) (defn mark-all-environments-expired! "Mark all environments, on all JRuby instances, stale so that they will be flushed from the environment cache." [] (jruby-protocol/mark-all-environments-expired! (tka/get-service system :JRubyPuppetService))) (defn flush-jruby-pool! "Flush and repopulate the JRuby pool" [] (jruby-protocol/flush-jruby-pool! (tka/get-service system :JRubyPuppetService))) (defn print-puppet-profiler-metrics "Print metrics data about function calls, resources, catalog compile and file metadata inlining." [] (let [metrics-profiler (get-in (context) [:service-contexts :PuppetProfilerService :profiler]) metrics (:experimental (puppet-profiler-core/assoc-metrics-data {} metrics-profiler))] (pprint/pprint metrics))) (defn print-http-request-stats "Print metrics data about requests we've handled, sorted in descending order of time spent." [] (let [metrics (-> (tka/get-service system :MasterService) tk-services/service-context :http-metrics) request-stats (http-metrics/request-summary metrics)] (pprint/pprint (:sorted-routes request-stats)))) (defn print-jruby-metrics [] (pprint/pprint (context [:service-contexts :JRubyMetricsService :metrics])) (pprint/pprint (let [{:keys [num-jrubies num-free-jrubies requested-count requested-jrubies-histo borrow-count borrow-timeout-count borrow-retry-count return-count free-jrubies-histo borrow-timer wait-timer requested-instances borrowed-instances lock-wait-timer lock-held-timer]} (context [:service-contexts :JRubyMetricsService :metrics])] {:num-jrubies (.getValue num-jrubies) :num-free-jrubies (.getValue num-free-jrubies) :requested-count (.getCount requested-count) :borrow-count (.getCount borrow-count) :borrow-timeout-count (.getCount borrow-timeout-count) :borrow-retry-count (.getCount borrow-retry-count) :return-count (.getCount return-count) :average-requested-jrubies (metrics/mean requested-jrubies-histo) :average-free-jrubies (metrics/mean free-jrubies-histo) :average-borrow-time (metrics/mean-millis borrow-timer) :average-wait-time (metrics/mean-millis wait-timer) :requested-instances (jruby-metrics-core/requested-instances-info (vals @requested-instances)) :borrowed-instances (jruby-metrics-core/requested-instances-info (vals @borrowed-instances)) :num-pool-locks (.getCount lock-held-timer) :average-lock-wait-time (metrics/mean-millis lock-wait-timer) :average-lock-held-time (metrics/mean-millis lock-held-timer)}))) (defn print-interesting-metrics [] (print-puppet-profiler-metrics) (print-http-request-stats) (print-jruby-metrics)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Allow user overrides ;; This code will load `user.repl` if it exists, allowing the user to override ;; functions in this namespace. For an example, see `user.clj.sample`. This ;; is usually used to provide an alternate implementation of `get-config`. (let [user-overrides (File. "./dev/user.clj")] (if (.exists user-overrides) (load-file (.getAbsolutePath user-overrides)))) puppetlabs-puppetserver-7e1a9a8/dev/logback-dev.xml000066400000000000000000000007551470345337400225530ustar00rootroot00000000000000 %d %-5p [%t] [%c{2}] %m%n puppetlabs-puppetserver-7e1a9a8/dev/puppetserver.conf000066400000000000000000000214461470345337400232660ustar00rootroot00000000000000global: { logging-config: ./dev/logback-dev.xml } product: { update-server-url: "http://some.update.server.that.does.not.exist/" name: {group-id: puppetlabs.dev artifact-id: puppetserver} } dropsonde: { enabled: false } webserver: { access-log-config: ./dev/request-logging-dev.xml client-auth: want # ssl-host controls what networks the server will accept connections from. # The default value below is '0.0.0.0', so will accept connections from # any client. For better security, you might wish to set this to 'localhost'. ssl-host: 0.0.0.0 #ssl-host: localhost ssl-port: 8140 } # configure the mount points for the web apps web-router-service: { # These two should not be modified because the Puppet 4.x agent expects # them to be mounted at these specific paths "puppetlabs.services.ca.certificate-authority-service/certificate-authority-service": "/puppet-ca" "puppetlabs.services.master.master-service/master-service": "/puppet" # This controls the mount point for the puppet admin API. "puppetlabs.services.puppet-admin.puppet-admin-service/puppet-admin-service": "/puppet-admin-api" # 3.x agent compatibility routes. The legacy routes are only mounted if the # puppetlabs.services.legacy-routes.legacy-routes-service/legacy-routes-service # service is in the bootstrap.cfg "puppetlabs.services.legacy-routes.legacy-routes-service/legacy-routes-service": "" # This controls the mount point for the status API "puppetlabs.trapperkeeper.services.status.status-service/status-service": "/status" # This controls the mount point for the metrics API "puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-webservice": "/metrics" } # configuration for the JRuby interpreters jruby-puppet: { # Where the puppet-agent dependency places puppet, facter, etc... # Puppet server expects to load Puppet from this location ruby-load-path: [./ruby/puppet/lib, ./ruby/facter/lib, ./ruby/hiera/lib, ./ruby/resource_api/lib] # This setting determines where JRuby will install gems. It is used for loading gems, # and also by the `puppetserver gem` command line tool. gem-home: ${HOME}"/.puppetlabs/opt/server/data/puppetserver/jruby-gems" # This setting defines the complete "GEM_PATH" for jruby. If set, it should include # the gem-home directory as well as any other directories that gems can be loaded # from (including the vendored gems directory for gems that ship with puppetserver) gem-path: [${jruby-puppet.gem-home}, ${HOME}"/.puppetlabs/opt/server/data/puppetserver/vendored-jruby-gems"] # (optional) path to puppet conf dir; if not specified, will use the puppet default server-conf-dir: ${HOME}"/.puppetlabs/etc/puppet" # (optional) path to puppet code dir; if not specified, will use the puppet default server-code-dir: ${HOME}"/.puppetlabs/etc/code" # (optional) path to puppet var dir; if not specified, will use the puppet default server-var-dir: ${HOME}"/.puppetlabs/opt/puppet/cache" # (optional) path to puppet run dir; if not specified, will use the puppet default server-run-dir: ${HOME}"/.puppetlabs/var/run" # (optional) path to puppet log dir; if not specified, will use the puppet default server-log-dir: ${HOME}"/.puppetlabs/var/log" # (optional) maximum number of JRuby instances to allow max-active-instances: 1 # (optional) whether to use the environment class cache. If unspecified # defaults to false environment-class-cache-enabled: true # (optional) Whether or not to track lookups during compilation; turning # this on will send that information to puppetdb # track-lookups: true # For testing running requests through a single JRuby instance. DO NOT ENABLE unless # explicitly testing this functionality. # multithreaded: true # (optional) When (re)filling a pool one instance will be initialized first, then # the remaining instances will be initialized at the specified level of concurrency. # Set to one for the previous serialized behavior. Default is three. # instance-creation-concurrency: 1 } # Settings related to HTTP client requests made by Puppet Server. # These settings only apply to client connections using the Puppet::Network::HttpPool # classes. Client connections using net/http or net/https directly will not be # configured with these settings automatically. http-client: { # A list of acceptable protocols for making HTTP requests #ssl-protocols: [TLSv1.3, TLSv1.2] # A list of acceptable cipher suites for making HTTP requests #cipher-suites: [TLS_RSA_WITH_AES_256_CBC_SHA256, # TLS_RSA_WITH_AES_256_CBC_SHA, # TLS_RSA_WITH_AES_128_CBC_SHA256, # TLS_RSA_WITH_AES_128_CBC_SHA] # The amount of time, in milliseconds, that an outbound HTTP connection # will wait for data to be available before closing the socket. If not # defined, defaults to 20 minutes. If 0, the timeout is infinite and if # negative, the value is undefined by the application and governed by the # system default behavior. #idle-timeout-milliseconds: 1200000 # The amount of time, in milliseconds, that an outbound HTTP connection will # wait to connect before giving up. Defaults to 2 minutes if not set. If 0, # the timeout is infinite and if negative, the value is undefined in the # application and governed by the system default behavior. #connect-timeout-milliseconds: 120000 } # settings related to profiling the puppet Ruby code profiler: { # enable or disable profiling for the Ruby code; defaults to 'false'. enabled: true } metrics: { # a server id that will be used as part of the namespace for metrics produced # by this server server-id: localhost registries: { puppetserver: { # specify metrics to allow in addition to those in the default list #metrics-allowed: ["compiler.compile.production"] reporters: { # enable or disable JMX metrics reporter jmx: { enabled: true } # enable or disable Graphite metrics reporter #graphite: { # enabled: true #} } } } # this section is used to configure settings for reporters that will send # the metrics to various destinations for external viewing reporters: { #graphite: { # # graphite host # host: "127.0.0.1" # # graphite metrics port # port: 2003 # # how often to send metrics to graphite # update-interval-seconds: 5 #} } } # authorization rules for web service endpoints authorization: { version: 1 rules: [ { match-request: { path: "/" type: "path" } allow-unauthenticated: true sort-order: 1 name: "allow all" } ] } certificate-authority: { # Puppet 6 onwards will have support for infrastructure CRL which would be enabled by default. # An infrastructure CRL would consist of only serial numbers of any compile masters and hence small. # While full CRL will continue to exist, agent nodes would get the infrastructure CRL if enabled. # Infra structure CRL can be disabled by setting the below option to false # enable-infra-crl: true # The infrastructure CRL feature uses the following files: # infra-crl-path: this maintains the infrastructure CRL which will reside in cadir (full crl) # infra-node-serials-path: this maintains the serial numbers of the infrastructure nodes whose revocation would # result in infrastructure crl getting updated. It will reside in the cadir. # infra-nodes-path: This file maintains the list of compile master nodes that would be used to generate the above # infra nodes serials path. In case of a PE install, this file would be managed by PE module # Note: FOSS would need to create and manage this file themselves. At any given time, # it needs to have the list of all active compile masters including the MoM. # It is expected to be at /etc/puppetlabs/puppetserver/ca/infra-nodes.txt. The file-path # is fixed and cannot be changed. allow-subject-alt-names: false allow-authorization-extensions: false # Disable auto renewal of certs by default. allow-auto-renewal: false # This value determines the lifetime of the cert if auto-renewal is enabled auto-renewal-cert-ttl: "90d" # Default cert expiration time. If the value is set here, it will take precedence over ca-ttl setting in puppet.conf #ca-ttl: "60d" } puppetlabs-puppetserver-7e1a9a8/dev/user.clj.sample000066400000000000000000000005341470345337400225760ustar00rootroot00000000000000(in-ns 'dev-tools) (clojure.core/refer 'clojure.core) ;; Override the default `get-config` function from `dev-tools`, so that we ;; can customize our dev configuration without modifying the default conf file. (defn get-config [default-config] ;; override number of jrubies (assoc-in default-config [:jruby-puppet :max-active-instances] 2)) puppetlabs-puppetserver-7e1a9a8/documentation/000077500000000000000000000000001470345337400217375ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/documentation/README.md000066400000000000000000000004301470345337400232130ustar00rootroot00000000000000## Docs have moved! Puppetserver's markdown for documentation has moved to https://github.com/puppetlabs/osp-docs. Please file a ticket in the SERVER JIRA project to request changes. Published docs can be found at https://puppet.com/docs/puppet/latest/server/about_server.html. puppetlabs-puppetserver-7e1a9a8/ext/000077500000000000000000000000001470345337400176665ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/build_defaults.yaml000066400000000000000000000001301470345337400235320ustar00rootroot00000000000000--- project: 'puppetserver' repo_name: 'puppet8' nonfinal_repo_name: 'puppet8-nightly' puppetlabs-puppetserver-7e1a9a8/ext/project_data.yaml000077700000000000000000000000001470345337400270562build_defaults.yamlustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/000077500000000000000000000000001470345337400221745ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/Gemfile000066400000000000000000000000701470345337400234640ustar00rootroot00000000000000source 'https://rubygems.org' gem 'rspec-expectations' puppetlabs-puppetserver-7e1a9a8/ext/thread_test/bootstrap.cfg000066400000000000000000000034551470345337400247010ustar00rootroot00000000000000puppetlabs.services.request-handler.request-handler-service/request-handler-service puppetlabs.services.jruby.jruby-puppet-service/jruby-puppet-pooled-service puppetlabs.services.jruby-pool-manager.jruby-pool-manager-service/jruby-pool-manager-service puppetlabs.services.puppet-profiler.puppet-profiler-service/puppet-profiler-service puppetlabs.trapperkeeper.services.webserver.jetty10-service/jetty10-service puppetlabs.trapperkeeper.services.webrouting.webrouting-service/webrouting-service puppetlabs.services.config.puppet-server-config-service/puppet-server-config-service puppetlabs.services.master.master-service/master-service puppetlabs.services.legacy-routes.legacy-routes-service/legacy-routes-service puppetlabs.services.puppet-admin.puppet-admin-service/puppet-admin-service puppetlabs.trapperkeeper.services.authorization.authorization-service/authorization-service puppetlabs.services.versioned-code-service.versioned-code-service/versioned-code-service puppetlabs.trapperkeeper.services.scheduler.scheduler-service/scheduler-service puppetlabs.trapperkeeper.services.status.status-service/status-service puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-service puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-webservice puppetlabs.services.jruby.jruby-metrics-service/jruby-metrics-service puppetlabs.services.analytics.analytics-service/analytics-service puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service # To enable the CA service, leave the following line uncommented puppetlabs.services.ca.certificate-authority-service/certificate-authority-service # To disable the CA service, comment out the above line and uncomment the line below #puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/000077500000000000000000000000001470345337400247235ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/000077500000000000000000000000001470345337400260575ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/manifests/000077500000000000000000000000001470345337400300505ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/manifests/init.pp000066400000000000000000000002121470345337400313470ustar00rootroot00000000000000notify { 'hello': } notify { threader::doit(): } notify { threader::color(): } notify { oldschool(): } include threader::params_class puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/000077500000000000000000000000001470345337400275275ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/000077500000000000000000000000001470345337400313255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/data/000077500000000000000000000000001470345337400322365ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/data/common.yaml000066400000000000000000000000571470345337400344140ustar00rootroot00000000000000--- threader::params_class::input: hiera_funky puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/hiera.yaml000066400000000000000000000012551470345337400333040ustar00rootroot00000000000000--- version: 5 defaults: # Used for any hierarchy level that omits these keys. datadir: data # This path is relative to hiera.yaml's directory. data_hash: yaml_data # Use the built-in YAML backend. hierarchy: - name: "osfamily/major release" paths: - "os/%{facts.os.family}/%{facts.os.release.major}.yaml" # Used for Solaris - "os/%{facts.os.family}/%{facts.kernelrelease}.yaml" # Used to distinguish between Debian and Ubuntu - "os/%{facts.os.name}/%{facts.os.release.major}.yaml" - name: "osfamily" paths: - "os/%{facts.os.family}.yaml" - "os/%{facts.os.name}.yaml" - name: 'common' path: 'common.yaml' puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/000077500000000000000000000000001470345337400320735ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/puppet/000077500000000000000000000000001470345337400334105ustar00rootroot00000000000000functions/000077500000000000000000000000001470345337400353415ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/puppetthreader/000077500000000000000000000000001470345337400371375ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/puppet/functionscolor.rb000066400000000000000000000002261470345337400406020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/puppet/functions/threaderPuppet::Functions.create_function(:'threader::color') do dispatch :color do end def color "The funky color is #{Puppet[:color]}" end end doit.rb000066400000000000000000000002001470345337400404130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/puppet/functions/threaderPuppet::Functions.create_function(:'threader::doit') do dispatch :doit do end def doit 'Always on the one' end end parser/000077500000000000000000000000001470345337400346255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/puppetfunctions/000077500000000000000000000000001470345337400366355ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/puppet/parseroldschool.rb000066400000000000000000000002051470345337400411450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/lib/puppet/parser/functionsmodule Puppet::Parser::Functions newfunction(:oldschool, :type => :rvalue) do |args| return 'old school v3 function' end end puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/manifests/000077500000000000000000000000001470345337400333165ustar00rootroot00000000000000params_class.pp000066400000000000000000000001251470345337400362460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/manifestsclass threader::params_class (String $input) { notify { "Param value: $input": } } puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/funky/modules/threader/metadata.json000066400000000000000000000020201470345337400337720ustar00rootroot00000000000000{ "name": "patrick-threader", "version": "0.1.0", "author": "patrick", "summary": "", "license": "Apache-2.0", "source": "", "dependencies": [ ], "operatingsystem_support": [ { "operatingsystem": "CentOS", "operatingsystemrelease": [ "7" ] }, { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ "7" ] }, { "operatingsystem": "RedHat", "operatingsystemrelease": [ "8" ] }, { "operatingsystem": "Scientific", "operatingsystemrelease": [ "7" ] }, { "operatingsystem": "Debian", "operatingsystemrelease": [ "9" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "18.04" ] } ], "requirements": [ { "name": "puppet", "version_requirement": ">= 4.10.0 < 7.0.0" } ], "pdk-version": "1.13.0", "template-url": "pdk-default#1.13.0", "template-ref": "1.13.0-0-g66e1443" } puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/000077500000000000000000000000001470345337400271115ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/manifests/000077500000000000000000000000001470345337400311025ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/manifests/init.pp000066400000000000000000000003401470345337400324030ustar00rootroot00000000000000node default { notify { 'hello': } notify { threader::doit(): } notify { threader::color(): } notify { oldschool(): } include threader::params_class } node 'testthree' { notify { threader::other_func(): } } puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/000077500000000000000000000000001470345337400305615ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/000077500000000000000000000000001470345337400323575ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/hiera.yaml000066400000000000000000000012551470345337400343360ustar00rootroot00000000000000--- version: 5 defaults: # Used for any hierarchy level that omits these keys. datadir: data # This path is relative to hiera.yaml's directory. data_hash: yaml_data # Use the built-in YAML backend. hierarchy: - name: "osfamily/major release" paths: - "os/%{facts.os.family}/%{facts.os.release.major}.yaml" # Used for Solaris - "os/%{facts.os.family}/%{facts.kernelrelease}.yaml" # Used to distinguish between Debian and Ubuntu - "os/%{facts.os.name}/%{facts.os.release.major}.yaml" - name: "osfamily" paths: - "os/%{facts.os.family}.yaml" - "os/%{facts.os.name}.yaml" - name: 'common' path: 'common.yaml' puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/000077500000000000000000000000001470345337400331255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppet/000077500000000000000000000000001470345337400344425ustar00rootroot00000000000000functions/000077500000000000000000000000001470345337400363735ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppetthreader/000077500000000000000000000000001470345337400401715ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppet/functionscolor.rb000066400000000000000000000002661470345337400416400ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppet/functions/threaderPuppet::Functions.create_function(:'threader::color') do dispatch :color do end def color Puppet[:color] = false "The production color is #{Puppet[:color]}" end end doit.rb000066400000000000000000000001641470345337400414560ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppet/functions/threaderPuppet::Functions.create_function(:'threader::doit') do dispatch :doit do end def doit 'do it' end end other_func.rb000066400000000000000000000002311470345337400426460ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppet/functions/threaderPuppet::Functions.create_function(:'threader::other_func') do dispatch :other_func do end def other_func "I'm a different function" end end parser/000077500000000000000000000000001470345337400356575ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppetfunctions/000077500000000000000000000000001470345337400376675ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppet/parseroldschool.rb000066400000000000000000000002071470345337400422010ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/lib/puppet/parser/functionsmodule Puppet::Parser::Functions newfunction(:oldschool, :type => :rvalue) do |args| return 'the old way of functions' end end puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/manifests/000077500000000000000000000000001470345337400343505ustar00rootroot00000000000000params_class.pp000066400000000000000000000001371470345337400373030ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader/manifestsclass threader::params_class (String $input = 'froyo') { notify { "Param value: $input": } } metadata.json000066400000000000000000000020201470345337400347450ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/thread_test/environments/production/modules/threader{ "name": "patrick-threader", "version": "0.1.0", "author": "patrick", "summary": "", "license": "Apache-2.0", "source": "", "dependencies": [ ], "operatingsystem_support": [ { "operatingsystem": "CentOS", "operatingsystemrelease": [ "7" ] }, { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ "7" ] }, { "operatingsystem": "RedHat", "operatingsystemrelease": [ "8" ] }, { "operatingsystem": "Scientific", "operatingsystemrelease": [ "7" ] }, { "operatingsystem": "Debian", "operatingsystemrelease": [ "9" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "18.04" ] } ], "requirements": [ { "name": "puppet", "version_requirement": ">= 4.10.0 < 7.0.0" } ], "pdk-version": "1.13.0", "template-url": "pdk-default#1.13.0", "template-ref": "1.13.0-0-g66e1443" } puppetlabs-puppetserver-7e1a9a8/ext/thread_test/parallel_test.rb000066400000000000000000000053621470345337400253620ustar00rootroot00000000000000require 'net/http' require 'json' require 'rspec/expectations' iterations = 100 processes_per_catalog = 2 include RSpec::Matchers class CatalogTester def initialize @uri = URI("http://localhost:8140/puppet/v3/catalog/#{@catalog}?environment=#{@environment}") end def run encoded_result = Net::HTTP.get(@uri) result = JSON.parse(encoded_result) verify(result) end def verify(_result) raise NotImplementedError end end class CatalogOneTester < CatalogTester def initialize @catalog = 'testone' @environment = 'production' super end def verify(result) expect(result).to include('name' => @catalog) expect(result).to include('environment' => @environment) # v4 function expect(result['resources']).to include(a_hash_including('title' => 'do it')) # v3 function expect(result['resources']).to include(a_hash_including('title' => 'the old way of functions')) # class param from hiera expect(result['resources']).to include(a_hash_including('parameters' => { 'input' => 'froyo' })) end end class CatalogTwoTester < CatalogTester def initialize @catalog = 'testtwo' @environment = 'funky' super end def verify(result) expect(result).to include('name' => @catalog) expect(result).to include('environment' => @environment) # color is turned on in color function expect(result['resources']).to include(a_hash_including('title' => 'The funky color is ansi')) # v4 function expect(result['resources']).to include(a_hash_including('title' => 'Always on the one')) # v3 function expect(result['resources']).to include(a_hash_including('title' => 'old school v3 function')) # class param from hiera expect(result['resources']).to include(a_hash_including('parameters' => { 'input' => 'hiera_funky' })) end end class CatalogThreeTester < CatalogTester def initialize @catalog = 'testthree' @environment = 'production' super end def verify(result) expect(result).to include('name' => @catalog) expect(result).to include('environment' => @environment) # function only loaded for this node expect(result['resources']).to include(a_hash_including('title' => "I'm a different function")) end end processes_per_catalog.times do Process.fork do tester = CatalogOneTester.new iterations.times do tester.run end end end processes_per_catalog.times do Process.fork do tester = CatalogTwoTester.new iterations.times do tester.run end end end processes_per_catalog.times do Process.fork do tester = CatalogThreeTester.new iterations.times do tester.run end end end exit_codes = Process.waitall if exit_codes.all? { |s| s[1].exitstatus.zero? } exit 0 else exit 1 end puppetlabs-puppetserver-7e1a9a8/ext/thread_test/puppetserver.conf000066400000000000000000000206031470345337400256100ustar00rootroot00000000000000global: { logging-config: ./dev/logback-dev.xml } product: { update-server-url: "http://some.update.server.that.does.not.exist/" name: {group-id: puppetlabs.dev artifact-id: puppetserver} } webserver: { access-log-config: ./dev/request-logging-dev.xml # client-auth: want # ssl-host controls what networks the server will accept connections from. # The default value below is '0.0.0.0', so will accept connections from # any client. For better security, you might wish to set this to 'localhost'. host: localhost port: 8140 } # configure the mount points for the web apps web-router-service: { # These two should not be modified because the Puppet 4.x agent expects # them to be mounted at these specific paths "puppetlabs.services.ca.certificate-authority-service/certificate-authority-service": "/puppet-ca" "puppetlabs.services.master.master-service/master-service": "/puppet" # This controls the mount point for the puppet admin API. "puppetlabs.services.puppet-admin.puppet-admin-service/puppet-admin-service": "/puppet-admin-api" # 3.x agent compatibility routes. The legacy routes are only mounted if the # puppetlabs.services.legacy-routes.legacy-routes-service/legacy-routes-service # service is in the bootstrap.cfg "puppetlabs.services.legacy-routes.legacy-routes-service/legacy-routes-service": "" # This controls the mount point for the status API "puppetlabs.trapperkeeper.services.status.status-service/status-service": "/status" # This controls the mount point for the metrics API "puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-webservice": "/metrics" } # configuration for the JRuby interpreters jruby-puppet: { # Where the puppet-agent dependency places puppet, facter, etc... # Puppet server expects to load Puppet from this location ruby-load-path: [./ruby/puppet/lib, ./ruby/facter/lib, ./ruby/hiera/lib, ./ruby/resource_api/lib] # This setting determines where JRuby will install gems. It is used for loading gems, # and also by the `puppetserver gem` command line tool. gem-home: ${HOME}"/.puppetlabs/opt/server/data/puppetserver/jruby-gems" # This setting defines the complete "GEM_PATH" for jruby. If set, it should include # the gem-home directory as well as any other directories that gems can be loaded # from (including the vendored gems directory for gems that ship with puppetserver) gem-path: [${jruby-puppet.gem-home}, ${HOME}"/.puppetlabs/opt/server/data/puppetserver/vendored-jruby-gems"] # (optional) path to puppet conf dir; if not specified, will use the puppet default server-conf-dir: ${HOME}"/.puppetlabs/etc/puppet" # (optional) path to puppet code dir; if not specified, will use the puppet default server-code-dir: "./ext/thread_test" # (optional) path to puppet var dir; if not specified, will use the puppet default server-var-dir: ${HOME}"/.puppetlabs/opt/puppet/cache" # (optional) path to puppet run dir; if not specified, will use the puppet default server-run-dir: ${HOME}"/.puppetlabs/var/run" # (optional) path to puppet log dir; if not specified, will use the puppet default server-log-dir: ${HOME}"/.puppetlabs/var/log" # (optional) maximum number of JRuby instances to allow max-active-instances: 2 # (optional) Authorize access to Puppet master endpoints via rules # specified in the legacy Puppet auth.conf file (if true) or via rules # specified in the Puppet Server HOCON-formatted auth.conf (if false or not # specified). #use-legacy-auth-conf: true # (optional) whether to use the environment class cache. If unspecified # defaults to false environment-class-cache-enabled: true # (optional) Whether or not to track lookups during compilation; turning # this on will send that information to puppetdb # track-lookups: true # For testing running requests through a single JRuby instance. DO NOT ENABLE unless # explicitly testing this functionality. multithreaded: true } # Settings related to HTTP client requests made by Puppet Server. # These settings only apply to client connections using the Puppet::Network::HttpPool # classes. Client connections using net/http or net/https directly will not be # configured with these settings automatically. http-client: { # A list of acceptable protocols for making HTTP requests #ssl-protocols: [TLSv1.3, TLSv1.2] # A list of acceptable cipher suites for making HTTP requests #cipher-suites: [TLS_RSA_WITH_AES_256_CBC_SHA256, # TLS_RSA_WITH_AES_256_CBC_SHA, # TLS_RSA_WITH_AES_128_CBC_SHA256, # TLS_RSA_WITH_AES_128_CBC_SHA] # The amount of time, in milliseconds, that an outbound HTTP connection # will wait for data to be available before closing the socket. If not # defined, defaults to 20 minutes. If 0, the timeout is infinite and if # negative, the value is undefined by the application and governed by the # system default behavior. #idle-timeout-milliseconds: 1200000 # The amount of time, in milliseconds, that an outbound HTTP connection will # wait to connect before giving up. Defaults to 2 minutes if not set. If 0, # the timeout is infinite and if negative, the value is undefined in the # application and governed by the system default behavior. #connect-timeout-milliseconds: 120000 } # settings related to profiling the puppet Ruby code profiler: { # enable or disable profiling for the Ruby code; defaults to 'false'. enabled: true } metrics: { # a server id that will be used as part of the namespace for metrics produced # by this server server-id: localhost registries: { puppetserver: { # specify metrics to allow in addition to those in the default list #metrics-allowed: ["compiler.compile.production"] reporters: { # enable or disable JMX metrics reporter jmx: { enabled: true } # enable or disable Graphite metrics reporter #graphite: { # enabled: true #} } } } # this section is used to configure settings for reporters that will send # the metrics to various destinations for external viewing reporters: { #graphite: { # # graphite host # host: "127.0.0.1" # # graphite metrics port # port: 2003 # # how often to send metrics to graphite # update-interval-seconds: 5 #} } } # authorization rules for web service endpoints authorization: { version: 1 rules: [ { match-request: { path: "/" type: "path" } allow-unauthenticated: true sort-order: 1 name: "allow all" } ] } certificate-authority: { # Puppet 6 onwards will have support for infrastructure CRL which would be enabled by default. # An infrastructure CRL would consist of only serial numbers of any compile masters and hence small. # While full CRL will continue to exist, agent nodes would get the infrastructure CRL if enabled. # Infra structure CRL can be disabled by setting the below option to false # enable-infra-crl: true # The infrastructure CRL feature uses the following files: # infra-crl-path: this maintains the infrastructure CRL which will reside in cadir (full crl) # infra-node-serials-path: this maintains the serial numbers of the infrastructure nodes whose revocation would # result in infrastructure crl getting updated. It will reside in the cadir. # infra-nodes-path: This file maintains the list of compile master nodes that would be used to generate the above # infra nodes serials path. In case of a PE install, this file would be managed by PE module # Note: FOSS would need to create and manage this file themselves. At any given time, # it needs to have the list of all active compile masters including the MoM. # It is expected to be at /etc/puppetlabs/puppetserver/ca/infra-nodes.txt. The file-path # is fixed and cannot be changed. allow-subject-alt-names: false allow-authorization-extensions: false } puppetlabs-puppetserver-7e1a9a8/ext/thread_test/test.rb000066400000000000000000000047661470345337400235150ustar00rootroot00000000000000require 'net/http' require 'json' require 'rspec/expectations' include RSpec::Matchers class CatalogTester def initialize @uri = URI("http://localhost:8140/puppet/v3/catalog/#{@catalog}?environment=#{@environment}") end def run encoded_result = Net::HTTP.get(@uri) result = JSON.parse(encoded_result) verify(result) end def verify(_result) raise NotImplementedError end end class CatalogOneTester < CatalogTester def initialize @catalog = 'testone' @environment = 'production' super end def verify(result) expect(result).to include('name' => @catalog) expect(result).to include('environment' => @environment) # v4 function expect(result['resources']).to include(a_hash_including('title' => 'do it')) # v3 function expect(result['resources']).to include(a_hash_including('title' => 'the old way of functions')) # class param from hiera expect(result['resources']).to include(a_hash_including('parameters' => { 'input' => 'froyo' })) end end class CatalogTwoTester < CatalogTester def initialize @catalog = 'testtwo' @environment = 'funky' super end def verify(result) expect(result).to include('name' => @catalog) expect(result).to include('environment' => @environment) # color is turned on in color function expect(result['resources']).to include(a_hash_including('title' => 'The funky color is ansi')) # v4 function expect(result['resources']).to include(a_hash_including('title' => 'Always on the one')) # v3 function expect(result['resources']).to include(a_hash_including('title' => 'old school v3 function')) # class param from hiera expect(result['resources']).to include(a_hash_including('parameters' => { 'input' => 'hiera_funky' })) end end class CatalogThreeTester < CatalogTester def initialize @catalog = 'testthree' @environment = 'production' super end def verify(result) expect(result).to include('name' => @catalog) expect(result).to include('environment' => @environment) # function only loaded for this node expect(result['resources']).to include(a_hash_including('title' => "I'm a different function")) end end # Use tester2 for funky env, and swap out for tester1 to use production instead, # or tester3 for a node in the production env with special classification. tester2 = CatalogTwoTester.new Process.fork do tester2.run end exit_codes = Process.waitall if exit_codes.all? { |s| s[1].exitstatus.zero? } exit 0 else exit 1 end puppetlabs-puppetserver-7e1a9a8/ext/travisci/000077500000000000000000000000001470345337400215125ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ext/travisci/install-java.sh000077500000000000000000000004761470345337400244450ustar00rootroot00000000000000#!/bin/bash set -e echo "Installing Java $JAVA_VERSION on arch $TRAVIS_CPU_ARCH" sudo rm -rf /usr/local/lib/jvm/ sudo rm -rf /usr/lib/jvm/openjdk-$JAVA_VERSION sudo apt-get update sudo apt-get install -y openjdk-$JAVA_VERSION-jdk-headless export JAVA_HOME=/usr/lib/jvm/java-$JAVA_VERSION-openjdk-$TRAVIS_CPU_ARCH/ puppetlabs-puppetserver-7e1a9a8/ext/travisci/test.sh000077500000000000000000000006171470345337400230340ustar00rootroot00000000000000#!/bin/bash set -e echo "Total memory available: $(grep MemTotal /proc/meminfo | awk '{print $2}')" git submodule update --recursive --init lein clean rm -rf vendor ./dev/install-test-gems.sh if [ "$MULTITHREADED" = "true" ]; then filter=":multithreaded" else filter=":singlethreaded" fi test_command="lein -U $ADDITIONAL_LEIN_ARGS test $filter" echo $test_command $test_command rake spec puppetlabs-puppetserver-7e1a9a8/ezbake/000077500000000000000000000000001470345337400203275ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ezbake/config/000077500000000000000000000000001470345337400215745ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ezbake/config/conf.d/000077500000000000000000000000001470345337400227435ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ezbake/config/conf.d/auth.conf000066400000000000000000000220531470345337400245550ustar00rootroot00000000000000authorization: { 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 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" } ] } puppetlabs-puppetserver-7e1a9a8/ezbake/config/conf.d/ca.conf000066400000000000000000000012661470345337400242020ustar00rootroot00000000000000certificate-authority: { # allow CA to sign certificate requests that have subject alternative names. # allow-subject-alt-names: false # allow CA to sign certificate requests that have authorization extensions. # allow-authorization-extensions: false # enable the separate CRL for Puppet infrastructure nodes # enable-infra-crl: false # Disable auto renewal of certs by default. allow-auto-renewal: false # This value determines the lifetime of the cert if auto-renewal is enabled auto-renewal-cert-ttl: "60d" # Default cert expiration time. If the value is set here, it will take precedence over ca-ttl setting in puppet.conf #ca-ttl: "60d" } puppetlabs-puppetserver-7e1a9a8/ezbake/config/conf.d/global.conf000066400000000000000000000003041470345337400250470ustar00rootroot00000000000000global: { # Path to logback logging configuration file; for more # info, see http://logback.qos.ch/manual/configuration.html logging-config: /etc/puppetlabs/puppetserver/logback.xml } puppetlabs-puppetserver-7e1a9a8/ezbake/config/conf.d/metrics.conf000066400000000000000000000032371470345337400252650ustar00rootroot00000000000000# settings related to metrics metrics: { # a server id that will be used as part of the namespace for metrics produced # by this server server-id: localhost registries: { puppetserver: { # specify metrics to allow in addition to those in the default list #metrics-allowed: ["compiler.compile.production"] reporters: { # enable or disable JMX metrics reporter jmx: { enabled: true } # enable or disable Graphite metrics reporter #graphite: { # enabled: true #} } } } # this section is used to configure settings for reporters that will send # the metrics to various destinations for external viewing reporters: { #graphite: { # # graphite host # host: "127.0.0.1" # # graphite metrics port # port: 2003 # # how often to send metrics to graphite # update-interval-seconds: 5 #} } metrics-webservice: { jolokia: { # Enable or disable the Jolokia-based metrics/v2 endpoint. # Default is true. # enabled: false # Configure any of the settings listed at: # https://jolokia.org/reference/html/agents.html#war-agent-installation servlet-init-params: { # Specify a custom security policy: # https://jolokia.org/reference/html/security.html # policyLocation: "file:///etc/puppetlabs/puppetserver/jolokia-access.xml" } } } } puppetlabs-puppetserver-7e1a9a8/ezbake/config/conf.d/web-routes.conf000066400000000000000000000015531470345337400257120ustar00rootroot00000000000000web-router-service: { # These two should not be modified because the Puppet 4.x agent expects them to # be mounted at these specific paths "puppetlabs.services.ca.certificate-authority-service/certificate-authority-service": "/puppet-ca" "puppetlabs.services.master.master-service/master-service": "/puppet" "puppetlabs.services.legacy-routes.legacy-routes-service/legacy-routes-service": "" # This controls the mount point for the puppet admin API. "puppetlabs.services.puppet-admin.puppet-admin-service/puppet-admin-service": "/puppet-admin-api" # This controls the mount point for the status API "puppetlabs.trapperkeeper.services.status.status-service/status-service": "/status" # This controls the mount point for the metrics API "puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-webservice": "/metrics" } puppetlabs-puppetserver-7e1a9a8/ezbake/config/conf.d/webserver.conf000066400000000000000000000002261470345337400256160ustar00rootroot00000000000000webserver: { access-log-config: /etc/puppetlabs/puppetserver/request-logging.xml client-auth: want ssl-host: 0.0.0.0 ssl-port: 8140 } puppetlabs-puppetserver-7e1a9a8/ezbake/config/logback.xml000066400000000000000000000052371470345337400237270ustar00rootroot00000000000000 %d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %-5p [%t] [%c{2}] %m%n /var/log/puppetlabs/puppetserver/puppetserver.log true /var/log/puppetlabs/puppetserver/puppetserver-%d{yyyy-MM-dd}.%i.log.gz 200MB 90 1GB %d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %-5p [%t] [%c{2}] %m%n /var/log/puppetlabs/puppetserver/puppetserver-status.log true /var/log/puppetlabs/puppetserver/puppetserver-status-%d{yyyy-MM-dd}.%i.log.gz 200MB 90 1GB %m%n puppetlabs-puppetserver-7e1a9a8/ezbake/config/services.d/000077500000000000000000000000001470345337400236415ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ezbake/config/services.d/ca.cfg000066400000000000000000000006541470345337400247120ustar00rootroot00000000000000# To enable the CA service, leave the following line uncommented puppetlabs.services.ca.certificate-authority-service/certificate-authority-service # To disable the CA service, comment out the above line and uncomment the line below #puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service puppetlabs-puppetserver-7e1a9a8/ezbake/system-config/000077500000000000000000000000001470345337400231165ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ezbake/system-config/services.d/000077500000000000000000000000001470345337400251635ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ezbake/system-config/services.d/bootstrap.cfg000066400000000000000000000024631470345337400276660ustar00rootroot00000000000000puppetlabs.services.request-handler.request-handler-service/request-handler-service puppetlabs.services.jruby.jruby-puppet-service/jruby-puppet-pooled-service puppetlabs.services.jruby-pool-manager.jruby-pool-manager-service/jruby-pool-manager-service puppetlabs.services.puppet-profiler.puppet-profiler-service/puppet-profiler-service puppetlabs.trapperkeeper.services.webserver.jetty10-service/jetty10-service puppetlabs.trapperkeeper.services.webrouting.webrouting-service/webrouting-service puppetlabs.services.config.puppet-server-config-service/puppet-server-config-service puppetlabs.services.master.master-service/master-service puppetlabs.services.puppet-admin.puppet-admin-service/puppet-admin-service puppetlabs.trapperkeeper.services.authorization.authorization-service/authorization-service puppetlabs.services.versioned-code-service.versioned-code-service/versioned-code-service puppetlabs.trapperkeeper.services.scheduler.scheduler-service/scheduler-service puppetlabs.trapperkeeper.services.status.status-service/status-service puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-service puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-webservice puppetlabs.services.jruby.jruby-metrics-service/jruby-metrics-service puppetlabs.services.analytics.analytics-service/analytics-service puppetlabs-puppetserver-7e1a9a8/jenkins/000077500000000000000000000000001470345337400205275ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/jenkins/deploy.sh000077500000000000000000000003611470345337400223620ustar00rootroot00000000000000#!/usr/bin/env bash set -e set -x git fetch --tags lein test :all echo "Tests passed!" lein release echo "Release plugin successful, pushing changes to git" git push origin --tags HEAD:$PUPPET_SERVER_BRANCH echo "git push successful." puppetlabs-puppetserver-7e1a9a8/jenkins/mergeup.sh000077500000000000000000000112071470345337400225330ustar00rootroot00000000000000#!/usr/bin/env bash # Merge driver for resolving conflicts in project.clj and acceptance/config/beaker/options.rb # Configure with: `git config merge.version-mergeup.driver "/path/to/mergeup.sh %O %A %B"` # Ensure `project.clj merge=version-mergeup` exists in your attributes file (usually .gitattributes) echo "Using puppetserver custom version driver" # Set MERGEUP_DEP_VERSIONS='TRUE' in order to take 'theirs' when resolving dependency version conflicts in project.clj # Otherwise, we will keep 'our' version of the dependency. mergeup_dep_versions=${MERGEUP_DEP_VERSIONS:-false} # $2 - ours - this is where the result should end up # $1 - common base # $3 - theirs git merge-file $2 $1 $3 # `git merge-file` exits with the number of conflicts, negative on error num_conflicts=$? if [[ "$num_conflicts" -lt 1 ]]; then exit $num_conflicts fi # sed's `-i` flag requires an argument on OSX sed_i_flag="-i" if [[ "$OSTYPE" == "darwin"* ]]; then sed_i_flag="-i .bak" fi # the smallest merge conflict will take up 4 lines, including the conflict markers, # so start by looking at "<<<<<<<" and the 3 lines following it lines=3 while [[ "$num_conflicts" -gt 0 ]]; do conflict=$(cat $2 | grep -n -A$lines "<<<<<<<" | grep -m 1 -B$lines ">>>>>>>") if [[ "$?" -ne 0 ]]; then # only increment after there are no more conflicts at that length lines=$(( $lines + 1 )) continue fi echo "FOUND CONFLICT" echo $conflict # an even diff will have an odd number of lines due to the conflict markers # but $lines doesn't include the "<<<<<<<" line we start with # so an even diff should have an even number of $lines if [[ "$(( $lines % 2))" -ne 0 ]]; then echo "ERROR: CONFLICT CONTAINS UNEVEN DIFFS, CAN'T RESOLVE" exit 1 fi # find the line number for the first line of the conflict # (obtained from using `grep -n` above) start_line=$(echo $conflict | grep -o -E "^[0-9]+") end_line=$(( $start_line + $lines )) line_pointer=$start_line for ((l=0;l<$lines;l++)); do # can skip the first line, since it should always be "<<<<<<<" line_pointer=$(( $line_pointer + 1 )) echo "READING LINE $line_pointer" line_content=$(sed "$line_pointer!d" $2) # we can stop when we read the middle of the conflict, since everything should have a match if echo $line_content | grep "=======" ; then break # TO DO: make 'ps-version' a configurable variable so other projects could use this driver elif echo $line_content | grep "ps-version" ; then echo "ps-version, keep ours" # check if it's a clj-parent bump and keep ours elif echo $line_content | grep "puppetlabs/clj-parent" ; then echo "clj-parent bump, keep ours" # check for matching lines, since identical lines sometimes still get caught in conflicts, if they're near enough real conflicts # potential for error if the line content happens to match something else that isn't just a single line?? # but that seems unlikely elif [[ "$(echo $conflict | grep -o "$line_content" | wc -l)" -eq 2 ]]; then echo "found matching line, doesn't matter, keep ours" # see if it's at least a version definition elif our_dep=$(echo $line_content | grep "(def .* \".*\")") ; then if [[ $mergeup_dep_versions == "TRUE" ]]; then echo "looks versiony, take theirs" # find their matching version definition so we can replace ours with it dep_name=$(echo $line_content | awk '{print $2}') # look for match starting after the current line, so we don't match our dep their_dep=$(tail -n +$(( $line_pointer + 1 )) $2 | grep -o -m1 "(def $dep_name \".*\")") if [[ -z $their_dep ]]; then echo "ERROR: COULDN'T FIND THEIR $dep_name, CAN'T RESOLVE" exit 1 fi set -e sed $sed_i_flag "s/$our_dep/$their_dep/" $2 set +e else echo "looks versiony, keep ours" fi # check for puppet_build_version in beaker options file, keep ours elif echo $line_content | grep "puppet_build_version" ; then echo "puppet_build_version, keep ours" else echo "ERROR: DON'T KNOW WHAT TO DO WITH THIS CONFLICT, CAN'T RESOLVE" exit 1 fi done # everything we want should be on 'our' side, so delete theirs set -e sed $sed_i_flag "$start_line,$end_line{/<<<<<<>>>>>>/d;}" $2 set +e num_conflicts=$(( $num_conflicts - 1 )) done # confirm there are no more conflict markers git --no-pager diff --check if [[ "$?" -ne 0 ]]; then echo "ERROR: CONFLICT MARKERS WERE NOT CLEANED UP APPROPRIATELY" exit 1 fi echo "Resolved all conflicts!" if [[ -e "$2.bak" ]]; then rm "$2.bak" fi exit 0 puppetlabs-puppetserver-7e1a9a8/locales/000077500000000000000000000000001470345337400205105ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/locales/eo.po000066400000000000000000000543421470345337400214630ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Puppet # This file is distributed under the same license as the puppetlabs.puppetserver package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: puppetlabs.puppetserver\n" "Report-Msgid-Bugs-To: docs@puppet.com\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2017-03-22 16:36-0600\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.12\n" "Last-Translator: \n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "Language: eo\n" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Cannot initialize {0} with partial state; need all files or none." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Found:" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Missing:" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Config setting ca_ttl must have a value below {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "The ''client-whitelist'' and ''authorization-required'' settings in the " "''certificate-authority.certificate-status'' section are deprecated and will " "be removed in a future release." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "" "Remove these settings and create an appropriate authorization rule in the /" "etc/puppetlabs/puppetserver/conf.d/auth.conf file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Because the ''client-whitelist'' is empty and ''authorization-required'' is " "set to ''false'', the ''certificate-authority.certificate-status'' settings " "will be ignored and authorization for the ''certificate_status'' endpoints " "will be done per the authorization rules in the /etc/puppetlabs/puppetserver/" "conf.d/auth.conf file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "To suppress this warning, remove the ''certificate-authority'' configuration " "settings." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Initializing SSL for the CA; settings:" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Instance name \"{0}\" does not match requested key \"{1}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Certificate names must be lower case." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Subject hostname format is invalid" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Subject contains a wildcard, which is not allowed: {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Found extensions that are not permitted: {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Only DNS names are allowed in the Subject Alternative Names extension" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Cert subjectAltName contains a wildcard, which is not allowed: {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "No CSR Attributes configuration file found at {0}, CSR Attributes will not " "be loaded" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Generating public and private keys for master cert" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Using keys found on disk to generate master cert" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Found master public key ''{0}'' but master private key ''{1}'' is missing" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Found master private key ''{0}'' but master public key ''{1}'' is missing" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Initializing SSL for the Master; settings:" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Master already initialized for SSL" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Found master cert ''{0}'' but master private key ''{1}'' is missing" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" ":localcacert ({0}) could not be found and no file at :cacert ({1}) to copy " "it from" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Invalid pattern ''{0}'' found in {1}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Executing ''{0} {1}''" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Autosign command ''{0} {1}'' exit status: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Autosign command ''{0} {1}'' output on stdout: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Autosign command ''{0} {1}'' generated output to stderr: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Autosign command ''{0}'' rejected certificate ''{1}'' because the exit code " "was {2}, not zero" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Signed certificate request for {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Saving CSR to ''{0}''" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "{0} already has a {1} certificate; new certificate will overwrite it" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "{0} already has a {1} certificate; ignoring certificate request" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "CSR contains a public key that does not correspond to the signing key" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "CSR ''{0}'' contains an authorization extension, which is disallowed." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Use {0} to sign this request." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "CSR ''{0}'' contains subject alternative names ({1}), which are disallowed." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Use `puppet cert --allow-dns-alt-names sign {0}` to sign this request." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Deleted certificate request for {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Path {0} exists but could not be deleted" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "No certificate request for {0} at expected path {1}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "The private CA key at ''{0}'' was found to have the wrong permissions set as " "''{1}''." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "This has been corrected to ''{0}''." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "CA already initialized for SSL" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Removed certificate request for {0} at ''{1}''" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Revoked {0} certificate with serial {1}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Deleted certificate for {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "No custom OID mapping configuration file found at {0}, custom OID mappings " "will not be loaded" msgstr "" #: src/clj/puppetlabs/puppetserver/cli/subcommand.clj msgid "" "Path to a configuration file or directory of configuration files. See the " "documentation for a list of supported file types." msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "The environment must be purely alphanumeric, not ''{0}''" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "" "Invalid code-id ''{0}''. Must contain only alpha-numerics and ''-'', ''_'', " "'';'', or '':''" msgstr "" #: src/clj/puppetlabs/puppetserver/jruby_request.clj msgid "Error {0} on SERVER at {1}: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/jruby_request.clj msgid "An environment parameter must be specified" msgstr "" #: src/clj/puppetlabs/puppetserver/ringutils.clj msgid "Client ''{0}'' access to {1} rejected;" msgstr "" #: src/clj/puppetlabs/puppetserver/ringutils.clj msgid "client not found in whitelist configuration." msgstr "" #: src/clj/puppetlabs/puppetserver/ringutils.clj msgid "Access to {0} rejected; no client certificate found" msgstr "" #: src/clj/puppetlabs/puppetserver/shell_utils.clj msgid "An absolute path is required, but ''{0}'' is not an absolute path" msgstr "" #: src/clj/puppetlabs/puppetserver/shell_utils.clj msgid "" "Command ''{0}'' appears to use command-line arguments, but this is not " "allowed." msgstr "" #: src/clj/puppetlabs/puppetserver/shell_utils.clj msgid "The referenced command ''{0}'' does not exist" msgstr "" #: src/clj/puppetlabs/puppetserver/shell_utils.clj msgid "The referenced command ''{0}'' is not executable" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "Not checking for updates - opt-out setting exists" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "" "Puppet Server Update Service has successfully started and will run in the " "background" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Could not find certificate {0}" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Could not find certificate_request {0}" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Cannot revoke certificate for host {0} without a signed certificate" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Cannot sign certificate for host {0} without a certificate request" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Invalid certificate subject." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "" "State {0} invalid; Must specify desired state of ''signed'' or ''revoked'' " "for host {1}." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Missing required parameter \"desired_state\"" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Request body is not JSON." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Empty request body." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Bad Request." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_disabled_service.clj msgid "CA disabled; ignoring SSL initialization for Master" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_disabled_service.clj msgid "CA disabled; ignoring retrieval of CA cert" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_disabled_service.clj msgid "CA disabled; ignoring retrieval of CA CRL" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_service.clj msgid "CA Service adding a ring handler" msgstr "" #: src/clj/puppetlabs/services/config/puppet_server_config_core.clj msgid "" "The following configuration keys conflict with the values to be read from " "puppet: {0}" msgstr "" #: src/clj/puppetlabs/services/config/puppet_server_config_core.clj msgid "Not overriding webserver settings with values from core Puppet" msgstr "" #: src/clj/puppetlabs/services/config/puppet_server_config_core.clj msgid "Initializing webserver settings from core Puppet" msgstr "" #: src/clj/puppetlabs/services/config/puppet_server_config_service.clj msgid "Initializing with the following settings from core Puppet:" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "" "JRuby instance ''{0}'' borrowed, but it appears to have already been in use!" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Not tracking jruby instance borrowed because server is shutting down" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Unable to find request event for borrowed JRuby instance: {0}" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "JRuby instance ''{0}'' returned, but no record of when it was borrowed!" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Lock request ''{0}'' acquired, but no record of when it was requested!" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Lock request ''{0}'' released, but no record of when it was acquired!" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Sampling JRuby metrics" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Unrecognized jruby event type: {0}" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_service.clj msgid "JRuby Metrics Service: stopping metrics sampler job" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_service.clj msgid "JRuby Metrics Service: stopped metrics sampler job" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj msgid "Adding facter jar to classpath from: {0}" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj msgid "Facter jar not found in ruby load path" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj msgid "The 'jruby-puppet.use-legacy-auth-conf' setting is set to ''true''." msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj msgid "" "Support for the legacy Puppet auth.conf file is deprecated and will be " "removed in a future release." msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj msgid "" "Change this setting to 'false' and migrate your authorization rule " "definitions in the /etc/puppetlabs/puppet/auth.conf file to the /etc/" "puppetlabs/puppetserver/conf.d/auth.conf file." msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_service.clj msgid "Initializing the JRuby service" msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Missing environment name!" msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Registering environment ''{0}''" msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Removing environment ''{0}'' from registry" msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Marking all registered environments as expired." msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Marking environment ''{0}'' as expired." msgstr "" #: src/clj/puppetlabs/services/legacy_routes/legacy_routes_service.clj msgid "" "The legacy routing service has successfully started and is now ready to " "handle requests" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Object cannot be coerced to a keyword: {0}" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Could not find environment ''{0}''" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Error: A /static_file_content request requires an environment, a code-id, " "and a file-path" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Request Denied: A /static_file_content request must be a file within the " "files directory of a module." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Not enough available RAM ({0}MB) to safely accommodate the configured JVM " "heap size of {1}MB." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Puppet Server requires at least {0}MB of available RAM given this heap size, " "computed as 1.1 * max heap (-Xmx)." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Either increase available memory or decrease the configured heap size by " "reducing the -Xms and -Xmx values in JAVA_ARGS in /etc/sysconfig/" "puppetserver on EL systems or /etc/default/puppetserver on Debian systems." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Route not found for service {0}" msgstr "" #: src/clj/puppetlabs/services/master/master_service.clj msgid "Master Service adding ring handlers" msgstr "" #: src/clj/puppetlabs/services/master/master_service.clj msgid "" "Puppet Server has successfully started and is now ready to handle requests" msgstr "" #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "Starting Puppet Admin web app" msgstr "" #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "" "The ''client-whitelist'' and ''authorization-required'' settings in the " "''puppet-admin'' section are deprecated and will be removed in a future " "release." msgstr "" #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "" "Because the ''client-whitelist'' is empty and ''authorization-required'' is " "set to ''false'', the ''puppet-admin'' settings will be ignored and " "authorization for the ''puppet-admin'' endpoints will be done per the " "authorization rules in the /etc/puppetlabs/puppetserver/conf.d/auth.conf " "file." msgstr "" #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "" "To suppress this warning, remove the ''puppet-admin'' configuration settings." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "CN ''{0}'' provided by HTTP header ''{1}''" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "" "Verification of client ''{0}'' provided by HTTP header ''{1}'': ''{2}''." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Authenticated: {0}." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "No DN provided by the HTTP header ''{0}''." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Treating client as unauthenticated." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "DN ''{0}'' provided by the HTTP header ''{1}'' is malformed." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Unable to URL decode the {0} header: {1}" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Unable to parse {0} into certificate: {1}" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "No certs found in PEM read from {0}" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Only 1 PEM should be supplied for {0} but {1} found" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "CN ''{0}'' provided by SSL certificate. Authenticated: {1}." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "No SSL client certificate provided. Treating client as unauthenticated." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "" "The HTTP header {0} was specified, but the master config option allow-header-" "cert-info was either not set, or was set to false." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "This header will be ignored." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Environment is required in a catalog request." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_service.clj msgid "The ''master.allow-header-cert-info'' setting is deprecated." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_service.clj msgid "" "Remove it, set ''jruby-puppet.use-legacy-auth-conf'' to ''false'', migrate " "your authorization rule definitions in the /etc/puppetlabs/puppet/auth.conf " "file to the /etc/puppetlabs/puppetserver/conf.d/auth.conf file, and set " "''authorization.allow-header-cert-info'' to the desired value." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_service.clj msgid "" "The ''master.allow-header-cert-info'' setting is deprecated and will be " "ignored in favor of the ''authorization.allow-header-cert-info'' setting " "because the ''jruby-puppet.use-legacy-auth-conf'' setting is ''false''." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_service.clj msgid "Remove the ''master.allow-header-cert-info'' setting." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "Error output generated while running ''{0}''." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "stderr: ''{0}''" msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "Non-zero exit code returned while running ''{0}''." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "exit-code: ''{0}'', stdout: ''{1}'', stderr: ''{2}''" msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "" "Running script generated an error. Command executed: ''{0}'', error " "generated: ''{1}''" msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "" "Only one of \"versioned-code.code-id-command\" and \"versioned-code.code-" "content-command\" was set." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "" "Both or neither must be set for the versioned-code-service to function " "correctly." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_service.clj msgid "No code-id-command set for versioned-code-service. Code-id will be nil." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_service.clj msgid "" "No code-content-command set for versioned-code-service. Attempting to fetch " "code content will fail." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_service.clj msgid "" "Cannot retrieve code content because the \"versioned-code.code-content-" "command\" setting is not present in configuration." msgstr "" puppetlabs-puppetserver-7e1a9a8/locales/puppetserver.pot000066400000000000000000001025231470345337400240030ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Puppet # This file is distributed under the same license as the puppetlabs.puppetserver package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: puppetlabs.puppetserver \n" "X-Git-Ref: 6efb46b8c2a4a58988e2ed260a1243495df48272\n" "Report-Msgid-Bugs-To: docs@puppet.com\n" "POT-Creation-Date: \n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Detected ca-ttl setting in CA config which will take precedence over puppet." "conf setting" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Cannot initialize {0} with partial state; need all files or none." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Found:" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Missing:" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Appending serial number {0} for {1} " msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Begin append to serial file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Inventory serial file not found. Assume empty." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Error while appending to serial file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Finish append to serial file. " msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Begin append to inventory file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Inventory file not found. Assume empty." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Error while appending to inventory file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Finish append to inventory file. " msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Append \"{1}\" to inventory file {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Looking for \"{0}\" in inventory file {1}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Extracting expired serials from inventory file {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Looking for serial numbers for \"{0}\" in inventory file {1}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Unable to find inventory file {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Config setting ca_ttl must have a value below {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "The ''client-whitelist'' and ''authorization-required'' settings in the " "''certificate-authority.certificate-status'' section are deprecated and will " "be removed in a future release." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "" "Remove these settings and create an appropriate authorization rule in the /" "etc/puppetlabs/puppetserver/conf.d/auth.conf file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Because the ''client-whitelist'' is empty and ''authorization-required'' is " "set to ''false'', the ''certificate-authority.certificate-status'' settings " "will be ignored and authorization for the ''certificate_status'' endpoints " "will be done per the authorization rules in the /etc/puppetlabs/puppetserver/" "conf.d/auth.conf file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "To suppress this warning, remove the ''certificate-authority'' configuration " "settings." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Failed to find certificate for Puppet Infrastructure Node: {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Initializing SSL for the CA; settings:" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Checking \"{0}\" for validity" msgstr "" #. see https://github.com/puppetlabs/clj-i18n/blob/main/README.md#single-quotes-in-messages for reasoning with double quote #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Rejecting subject \"{0}\" because it doesn''t match hostname \"{1}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Instance name \"{0}\" does not match requested key \"{1}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Rejecting subject \"{0}\" because all characters must be lowercase" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Certificate names must be lower case." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Subject contains a wildcard, which is not allowed: {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Rejecting subject \"{0}\" as it ends with an invalid character" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Subject hostname format is invalid" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Rejecting subject \"{0}\" as it starts with an invalid character" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Rejecting subject \"{0}\" because it contains invalid characters" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Found extensions that are not permitted: {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Only DNS and IP names are allowed in the Subject Alternative Names extension" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Cert subjectAltName contains a wildcard, which is not allowed: {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "No CSR Attributes configuration file found at {0}, CSR Attributes will not " "be loaded" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Generating public and private keys for master cert" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Using keys found on disk to generate master cert" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Found master public key ''{0}'' but master private key ''{1}'' is missing" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Found master private key ''{0}'' but master public key ''{1}'' is missing" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Initializing SSL for the Master; settings:" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Master already initialized for SSL" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Found master cert ''{0}'' but master private key ''{1}'' is missing" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" ":localcacert ({0}) could not be found and no file at :cacert ({1}) to copy " "it from" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Unable to synchronize crl file {0} to {1}: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Recent changes to the CRL may not have taken effect." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "To load the updated CRL, reload or restart the Puppet Server service." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Invalid pattern ''{0}'' found in {1}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Executing ''{0} {1}''" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Autosign command ''{0} {1}'' exit status: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Autosign command ''{0} {1}'' output on stdout: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Autosign command ''{0} {1}'' generated output to stderr: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Autosign command ''{0}'' rejected certificate ''{1}'' because the exit code " "was {2}, not zero" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Attempting to use {0} as CSR directory, but it is not a directory." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Autosign executable failed. Result: {0} " msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Entity {1} {2} 1 certificate: {3}." msgid_plural "Entity {1} {2} {0} certificates: {3}." msgstr[0] "" msgstr[1] "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Found auto-renew-attribute {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Deleted certificate request for {0} at {1}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Path {0} exists but could not be deleted" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "No certificate request for {0} at expected path {1}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Calculating validity dates for {0} from ttl of {1} " msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Saving CSR to ''{0}''" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "{0} already has a {1} certificate; new certificate will overwrite it" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "{0} already has a {1} certificate; ignoring certificate request" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "CSR contains a public key that does not correspond to the signing key" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "CSR ''{0}'' contains an authorization extension, which is disallowed." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "To allow authorization extensions, set allow-authorization-extensions to " "true in your ca.conf file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Then restart the puppetserver and try signing this certificate again." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "CSR ''{0}'' contains extra subject alternative names ({1}), which are " "disallowed." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "To allow subject alternative names, set allow-subject-alt-names to true in " "your ca.conf file." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Cannot support delta CRL." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Invalid certs and/or CRLs: {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Could not determine newest CRL." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "Received CRLs for issuer {0} but none were newer than the existing CRL; " "keeping the existing CRL." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Updating CRL for issuer {0}." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "One or more submitted CRLs do not have an authority key identifier." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Processing update to CRL at {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Successfully updated CRL at {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "The private CA key at ''{0}'' was found to have the wrong permissions set as " "''{1}''." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "This has been corrected to ''{0}''." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "CA already initialized for SSL" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Certificate with serial {0} is already revoked." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Try to read serial from \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "No revoke action needed. The certs are already in the CRL." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "No revoke action needed. The infra certs are already in the infra CRL" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Infra node certificate(s) being revoked; publishing updated infra CRL" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Deleted certificate for {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "" "No custom OID mapping configuration file found at {0}, custom OID mappings " "will not be loaded" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Renewed certificate for \"{0}\" with new expiration of \"{1}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "CA CRL expiring within 30 days, updating." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "infra crl expiring within 30 days, updating." msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Calculating validity dates from ttl of {0} " msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Signed CSR for {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "Failed in bulk signing for entry {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "File exists at {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/certificate_authority.clj msgid "File does not exist at {0}" msgstr "" #: src/clj/puppetlabs/puppetserver/cli/subcommand.clj msgid "" "Path to a configuration file or directory of configuration files. See the " "documentation for a list of supported file types." msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "The environment must be purely alphanumeric, not ''{0}''" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "" "Invalid code-id ''{0}''. Must contain only alpha-numerics and ''-'', ''_'', " "'';'', or '':''" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Attempt to acquire read lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Acquired read lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Released read lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Read Lock acquisition timed out \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Failed to acquire read lock \"{0}\" within {1} seconds" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Attempt to acquire write lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Acquired write lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Released write lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Write Lock acquisition timed out \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Failed to acquire write lock \"{0}\" within {1} seconds" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Attempt to acquire lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Acquired lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Released lock \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Lock acquisition timed out \"{0}\"" msgstr "" #: src/clj/puppetlabs/puppetserver/common.clj msgid "Failed to acquire lock \"{0}\" within {1} seconds" msgstr "" #: src/clj/puppetlabs/puppetserver/jruby_request.clj msgid "Error {0} on SERVER at {1}: {2}" msgstr "" #: src/clj/puppetlabs/puppetserver/jruby_request.clj msgid "" "The number of requests waiting for a JRuby instance has exceeded the limit " "allowed by the max-queued-requests setting." msgstr "" #: src/clj/puppetlabs/puppetserver/jruby_request.clj msgid "An environment parameter must be specified" msgstr "" #: src/clj/puppetlabs/puppetserver/ringutils.clj msgid "Client ''{0}'' access to {1} rejected;" msgstr "" #: src/clj/puppetlabs/puppetserver/ringutils.clj msgid "client not found in whitelist configuration." msgstr "" #: src/clj/puppetlabs/puppetserver/ringutils.clj msgid "Access to {0} rejected; no client certificate found" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "Running dropsonde" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "dropsonde run complete" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "Failed while running dropsonde" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "Failed to check for product updates" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "Not checking for updates - opt-out setting exists" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "" "Puppet Server Update Service has successfully started and will run in the " "background" msgstr "" #: src/clj/puppetlabs/services/analytics/analytics_service.clj msgid "Puppet Server Update Service shutting down" msgstr "" #: src/clj/puppetlabs/services/analytics/dropsonde.clj msgid "Successfully submitted module metrics via Dropsonde." msgstr "" #: src/clj/puppetlabs/services/analytics/dropsonde.clj msgid "Failed to submit module metrics via Dropsonde. Error: {0}" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Could not find certificate {0}" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Could not find certificate_request {0}" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "No valid CRLs submitted, nothing will be updated." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Error while cleaning certs" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Unable to find infra-nodes file at {0}" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "infra-nodes-path is nil, cannot validate certificate is allowed." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "" "Rejecting certificate request because the {0} was specified and the " "certificate is revoked." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "" "Rejecting certificate request because the {0} header was specified, but the " "client making the request was not in the allow list." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "" "Request is missing a certificate for an endpoint that requires a certificate." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Certificate present, processing renewal request" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Certificate present, but does not match signature" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "No valid certificate found in renewal request" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Cannot revoke certificate for host {0} without a signed certificate" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Cannot sign certificate for host {0} without a certificate request" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Invalid certificate subject." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "" "State {0} invalid; Must specify desired state of ''signed'' or ''revoked'' " "for host {1}." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "cert_ttl specified for host {0} must be an integer, not \"{1}\"" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Missing required parameter \"desired_state\"" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Request body is not JSON." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Empty request body." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_core.clj msgid "Bad Request." msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_disabled_service.clj msgid "CA disabled; ignoring SSL initialization for Master" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_disabled_service.clj msgid "CA disabled; ignoring retrieval of CA cert" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_disabled_service.clj msgid "CA disabled; ignoring retrieval of CA CRL" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_service.clj msgid "Failed to evaluate crls for expiration" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_service.clj msgid "Reporting CA event failed with: {0}nPayload: {1}" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_service.clj msgid "CA Service adding a ring handler" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_service.clj msgid "Starting CA service" msgstr "" #: src/clj/puppetlabs/services/ca/certificate_authority_service.clj msgid "Stopping CA service" msgstr "" #: src/clj/puppetlabs/services/config/puppet_server_config_core.clj msgid "" "The following configuration keys conflict with the values to be read from " "puppet: {0}" msgstr "" #: src/clj/puppetlabs/services/config/puppet_server_config_core.clj msgid "Not overriding webserver settings with values from core Puppet" msgstr "" #: src/clj/puppetlabs/services/config/puppet_server_config_core.clj msgid "Initializing webserver settings from core Puppet" msgstr "" #: src/clj/puppetlabs/services/config/puppet_server_config_service.clj msgid "Initializing with the following settings from core Puppet:" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "" "JRuby instance ''{0}'' borrowed, but it appears to have already been in use!" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Not tracking jruby instance borrowed because server is shutting down" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Unable to find request event for borrowed JRuby instance: {0}" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "JRuby instance ''{0}'' returned, but no record of when it was borrowed!" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Lock request ''{0}'' acquired, but no record of when it was requested!" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Lock request ''{0}'' released, but no record of when it was acquired!" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Sampling JRuby metrics" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Error ocurred while recording metrics for jruby event type: {0}" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj msgid "Unrecognized jruby event type: {0}" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_service.clj msgid "JRuby Metrics Service: stopping metrics sampler job" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_metrics_service.clj msgid "JRuby Metrics Service: stopped metrics sampler job" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj msgid "Disabling i18n for puppet because using multithreaded jruby" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj msgid "The jruby-puppet.compat-version setting is no longer supported." msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj msgid "jruby-puppet.compat-version setting no longer supported" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_service.clj msgid "Initializing the JRuby service" msgstr "" #: src/clj/puppetlabs/services/jruby/jruby_puppet_service.clj msgid "JRuby version info: {0}" msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Missing environment name!" msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Registering environment ''{0}''" msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Removing environment ''{0}'' from registry" msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Marking all registered environments as expired." msgstr "" #: src/clj/puppetlabs/services/jruby/puppet_environments.clj msgid "Marking environment ''{0}'' as expired." msgstr "" #: src/clj/puppetlabs/services/legacy_routes/legacy_routes_service.clj msgid "Versioned code not supported." msgstr "" #: src/clj/puppetlabs/services/legacy_routes/legacy_routes_service.clj msgid "" "The legacy routing service has successfully started and is now ready to " "handle requests" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Object cannot be coerced to a keyword: {0}" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "file did not match versioned file contents" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Static file unavailable for {0}: {1}" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Could not find environment ''{0}''" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Could not find module ''{0}''" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Could not find task ''{0}''" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Could not find plan ''{0}''" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Error: A /static_file_content request requires an environment, a code-id, " "and a file-path" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Request Denied: A /static_file_content request must be a file within the " "files, lib, scripts, or tasks directory of a module." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Failed to report action" msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "A compile request must include an `environment` or `versioned_project` " "parameter." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Not enough available RAM ({0}MB) to safely accommodate the configured JVM " "heap size of {1}MB." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Puppet Server requires at least {0}MB of available RAM given this heap size, " "computed as 1.1 * max heap (-Xmx)." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "" "Either increase available memory or decrease the configured heap size by " "reducing the -Xms and -Xmx values in JAVA_ARGS in /etc/sysconfig/" "puppetserver on EL systems or /etc/default/puppetserver on Debian systems." msgstr "" #: src/clj/puppetlabs/services/master/master_core.clj msgid "Route not found for service {0}" msgstr "" #: src/clj/puppetlabs/services/master/master_service.clj msgid "JDK {0} is neither tested nor supported. Please use JDK 11 or 17" msgstr "" #: src/clj/puppetlabs/services/master/master_service.clj msgid "JDK {0} is deprecated, please upgrade to JDK 11 or 17" msgstr "" #: src/clj/puppetlabs/services/master/master_service.clj msgid "Puppetserver doesn't support JDK {0}" msgstr "" #: src/clj/puppetlabs/services/master/master_service.clj msgid "Master Service adding ring handlers" msgstr "" #: src/clj/puppetlabs/services/master/master_service.clj msgid "" "Puppet Server has successfully started and is now ready to handle requests" msgstr "" #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "Starting Puppet Admin web app" msgstr "" #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "" "The ''client-whitelist'' and ''authorization-required'' settings in the " "''puppet-admin'' section are deprecated and will be removed in a future " "release." msgstr "" #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "" "Because the ''client-whitelist'' is empty and ''authorization-required'' is " "set to ''false'', the ''puppet-admin'' settings will be ignored and " "authorization for the ''puppet-admin'' endpoints will be done per the " "authorization rules in the /etc/puppetlabs/puppetserver/conf.d/auth.conf " "file." msgstr "" #: src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj msgid "" "To suppress this warning, remove the ''puppet-admin'' configuration settings." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "CN ''{0}'' provided by HTTP header ''{1}''" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "" "Verification of client ''{0}'' provided by HTTP header ''{1}'': ''{2}''." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Authenticated: {0}." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "No DN provided by the HTTP header ''{0}''." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Treating client as unauthenticated." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "DN ''{0}'' provided by the HTTP header ''{1}'' is malformed." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Unable to URL decode the {0} header: {1}" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Unable to parse {0} into certificate: {1}" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "No certs found in PEM read from {0}" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Only 1 PEM should be supplied for {0} but {1} found" msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "CN ''{0}'' provided by SSL certificate. Authenticated: {1}." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "No SSL client certificate provided. Treating client as unauthenticated." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "" "The HTTP header {0} was specified, but the master config option allow-header-" "cert-info was either not set, or was set to false." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "This header will be ignored." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_core.clj msgid "Environment is required in a catalog request." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_service.clj msgid "" "The ''master.allow-header-cert-info'' setting is deprecated and will be " "ignored in favor of the ''authorization.allow-header-cert-info'' setting ." msgstr "" #: src/clj/puppetlabs/services/request_handler/request_handler_service.clj msgid "Remove the ''master.allow-header-cert-info'' setting." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "Error output generated while running ''{0}''." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "stderr: ''{0}''" msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "Non-zero exit code returned while running ''{0}''." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "exit-code: ''{0}'', stdout: ''{1}'', stderr: ''{2}''" msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "" "Running script generated an error. Command executed: ''{0}'', error " "generated: ''{1}''" msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "" "Only one of \"versioned-code.code-id-command\" and \"versioned-code.code-" "content-command\" was set." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_core.clj msgid "" "Both or neither must be set for the versioned-code-service to function " "correctly." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_service.clj msgid "No code-id-command set for versioned-code-service. Code-id will be nil." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_service.clj msgid "" "No code-content-command set for versioned-code-service. Attempting to fetch " "code content will fail." msgstr "" #: src/clj/puppetlabs/services/versioned_code_service/versioned_code_service.clj msgid "" "Cannot retrieve code content because the \"versioned-code.code-content-" "command\" setting is not present in configuration." msgstr "" puppetlabs-puppetserver-7e1a9a8/project.clj000066400000000000000000000367511470345337400212420ustar00rootroot00000000000000(def ps-version "8.7.0") (defn deploy-info [url] { :url url :username :env/nexus_jenkins_username :password :env/nexus_jenkins_password :sign-releases false}) (def heap-size-from-profile-clj (let [profile-clj (io/file (System/getenv "HOME") ".lein" "profiles.clj")] (if (.exists profile-clj) (-> profile-clj slurp read-string (get-in [:user :puppetserver-heap-size]))))) (defn heap-size [default-heap-size] (or (System/getenv "PUPPETSERVER_HEAP_SIZE") heap-size-from-profile-clj default-heap-size)) (defproject puppetlabs/puppetserver ps-version :description "Puppet Server" :license {:name "Apache License, Version 2.0" :url "http://www.apache.org/licenses/LICENSE-2.0.html"} :min-lein-version "2.9.1" :parent-project {:coords [puppetlabs/clj-parent "7.3.35"] :inherit [:managed-dependencies]} :dependencies [[org.clojure/clojure] [slingshot] [org.yaml/snakeyaml] [commons-lang] [commons-io] [clj-time] [grimradical/clj-semver "0.3.0" :exclusions [org.clojure/clojure]] [prismatic/schema] [clj-commons/fs] [liberator] [org.apache.commons/commons-exec] [io.dropwizard.metrics/metrics-core] ;; We do not currently use this dependency directly, but ;; we have documentation that shows how users can use it to ;; send their logs to logstash, so we include it in the jar. [net.logstash.logback/logstash-logback-encoder] [puppetlabs/jruby-utils] [puppetlabs/clj-shell-utils] [puppetlabs/trapperkeeper] [com.puppetlabs/trapperkeeper-webserver-jetty10] [puppetlabs/trapperkeeper-authorization] [puppetlabs/trapperkeeper-comidi-metrics] [puppetlabs/trapperkeeper-metrics] [puppetlabs/trapperkeeper-scheduler] [puppetlabs/trapperkeeper-status] [puppetlabs/trapperkeeper-filesystem-watcher] [puppetlabs/kitchensink] [puppetlabs/ssl-utils] [puppetlabs/ring-middleware] [puppetlabs/dujour-version-check] [puppetlabs/http-client] [puppetlabs/comidi] [puppetlabs/i18n] [puppetlabs/rbac-client]] :main puppetlabs.trapperkeeper.main :pedantic? :abort :source-paths ["src/clj"] :java-source-paths ["src/java"] :test-paths ["test/unit" "test/integration"] :resource-paths ["resources" "src/ruby"] :repositories [["releases" "https://artifactory.delivery.puppetlabs.net/artifactory/clojure-releases__local/"] ["snapshots" "https://artifactory.delivery.puppetlabs.net/artifactory/clojure-snapshots__local/"]] :plugins [[lein-parent "0.3.7"] [jonase/eastwood "1.4.2" :exclusions [org.clojure/clojure]] ;; We have to have this, and it needs to agree with clj-parent ;; until/unless you can have managed plugin dependencies. [puppetlabs/i18n "0.9.2" :hooks false]] :uberjar-name "puppet-server-release.jar" :lein-ezbake {:vars {:user "puppet" :group "puppet" :numeric-uid-gid 52 :build-type "foss" :puppet-platform-version 8 :java-args ~(str "-Xms2g -Xmx2g " "-Djruby.logger.class=com.puppetlabs.jruby_utils.jruby.Slf4jLogger") :create-dirs ["/opt/puppetlabs/server/data/puppetserver/jars" "/opt/puppetlabs/server/data/puppetserver/yaml"] :repo-target "puppet8" :nonfinal-repo-target "puppet8-nightly" :bootstrap-source :services-d :logrotate-enabled false} :resources {:dir "tmp/ezbake-resources"} :config-dir "ezbake/config" :system-config-dir "ezbake/system-config"} :deploy-repositories [["releases" ~(deploy-info "https://artifactory.delivery.puppetlabs.net/artifactory/clojure-releases__local/")] ["snapshots" ~(deploy-info "https://artifactory.delivery.puppetlabs.net/artifactory/clojure-snapshots__local/")]] ;; By declaring a classifier here and a corresponding profile below we'll get an additional jar ;; during `lein jar` that has all the code in the test/ directory. Downstream projects can then ;; depend on this test jar using a :classifier in their :dependencies to reuse the test utility ;; code that we have. :classifiers [["test" :testutils]] :profiles {:defaults {:source-paths ["dev"] :dependencies [[org.clojure/tools.namespace] [com.puppetlabs/trapperkeeper-webserver-jetty10 :classifier "test"] [puppetlabs/trapperkeeper nil :classifier "test" :scope "test"] [puppetlabs/trapperkeeper-metrics :classifier "test" :scope "test"] [puppetlabs/kitchensink nil :classifier "test" :scope "test"] [ring-basic-authentication] [ring/ring-mock] [beckon] [lambdaisland/uri "1.4.70"] [puppetlabs/rbac-client :classifier "test" :scope "test"]]} :dev-deps {:dependencies [[org.bouncycastle/bcpkix-jdk18on]]} :dev [:defaults :dev-deps] :fips-deps {:dependencies [[org.bouncycastle/bcpkix-fips] [org.bouncycastle/bc-fips] [org.bouncycastle/bctls-fips]] :jvm-opts ~(let [version (System/getProperty "java.specification.version") [major minor _] (clojure.string/split version #"\.") unsupported-ex (ex-info "Unsupported major Java version." {:major major :minor minor})] (condp = (java.lang.Integer/parseInt major) 1 (if (= 8 (java.lang.Integer/parseInt minor)) ["-Djava.security.properties==./dev-resources/java.security.jdk8-fips"] (throw unsupported-ex)) 11 ["-Djava.security.properties==./dev-resources/java.security.jdk11on-fips"] 17 ["-Djava.security.properties==./dev-resources/java.security.jdk11on-fips"] (throw unsupported-ex)))} :fips [:defaults :fips-deps] :testutils {:source-paths ["test/unit" "test/integration"]} :test { ;; NOTE: In core.async version 0.2.382, the default size for ;; the core.async dispatch thread pool was reduced from ;; (42 + (2 * num-cpus)) to... eight. The jruby metrics tests ;; use core.async and need more than eight threads to run ;; properly; this setting overrides the default value. Without ;; it the metrics tests will hang. :jvm-opts ["-Dclojure.core.async.pool-size=50"] ;; Use humane test output so you can actually see what the problem is ;; when a test fails. :dependencies [[pjstadig/humane-test-output "0.8.3"]] :injections [(require 'pjstadig.humane-test-output) (pjstadig.humane-test-output/activate!)]} :ezbake {:dependencies ^:replace [;; we need to explicitly pull in our parent project's ;; clojure version here, because without it, lein ;; brings in its own version. ;; NOTE that these deps will completely replace the deps ;; in the list above, so any version overrides need to be ;; specified in both places. TODO: fix this. [org.clojure/clojure] [org.bouncycastle/bcpkix-jdk18on] [puppetlabs/jruby-utils] [puppetlabs/puppetserver ~ps-version] [com.puppetlabs/trapperkeeper-webserver-jetty10] [puppetlabs/trapperkeeper-metrics]] :plugins [[puppetlabs/lein-ezbake "2.6.2"]] :name "puppetserver"} :uberjar {:dependencies [[org.bouncycastle/bcpkix-jdk18on] [com.puppetlabs/trapperkeeper-webserver-jetty10]] :aot [puppetlabs.trapperkeeper.main puppetlabs.trapperkeeper.services.status.status-service puppetlabs.trapperkeeper.services.metrics.metrics-service puppetlabs.services.protocols.jruby-puppet puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service puppetlabs.trapperkeeper.services.webserver.jetty10-service puppetlabs.trapperkeeper.services.webrouting.webrouting-service puppetlabs.services.legacy-routes.legacy-routes-core puppetlabs.services.protocols.jruby-metrics puppetlabs.services.protocols.ca puppetlabs.puppetserver.common puppetlabs.trapperkeeper.services.scheduler.scheduler-service puppetlabs.services.jruby.jruby-metrics-core puppetlabs.services.jruby.jruby-metrics-service puppetlabs.services.protocols.puppet-server-config puppetlabs.puppetserver.liberator-utils puppetlabs.services.puppet-profiler.puppet-profiler-core puppetlabs.services.jruby-pool-manager.jruby-pool-manager-service puppetlabs.services.jruby.puppet-environments puppetlabs.services.jruby.jruby-puppet-schemas puppetlabs.services.jruby.jruby-puppet-core puppetlabs.services.jruby.jruby-puppet-service puppetlabs.puppetserver.jruby-request puppetlabs.puppetserver.shell-utils puppetlabs.puppetserver.ringutils puppetlabs.puppetserver.certificate-authority puppetlabs.services.ca.certificate-authority-core puppetlabs.services.puppet-admin.puppet-admin-core puppetlabs.services.puppet-admin.puppet-admin-service puppetlabs.services.versioned-code-service.versioned-code-core puppetlabs.services.ca.certificate-authority-disabled-service puppetlabs.services.protocols.request-handler puppetlabs.services.request-handler.request-handler-core puppetlabs.puppetserver.cli.subcommand puppetlabs.services.request-handler.request-handler-service puppetlabs.services.protocols.versioned-code puppetlabs.services.protocols.puppet-profiler puppetlabs.services.puppet-profiler.puppet-profiler-service puppetlabs.services.master.master-core puppetlabs.services.protocols.master puppetlabs.services.config.puppet-server-config-core puppetlabs.services.config.puppet-server-config-service puppetlabs.services.versioned-code-service.versioned-code-service puppetlabs.services.legacy-routes.legacy-routes-service puppetlabs.services.master.master-service puppetlabs.services.ca.certificate-authority-service puppetlabs.puppetserver.cli.ruby puppetlabs.puppetserver.cli.irb puppetlabs.puppetserver.cli.gem puppetlabs.services.analytics.analytics-service puppetlabs.services.protocols.legacy-routes]} :ci {:plugins [[lein-pprint "1.1.1"] [lein-exec "0.3.7"]]}} :test-selectors {:default (complement :multithreaded-only) :integration :integration :unit (complement :integration) :multithreaded (complement :single-threaded-only) :singlethreaded (complement :multithreaded-only)} :eastwood {:exclude-linters [:unused-meta-on-macro :reflection [:suspicious-test :second-arg-is-not-string]] :continue-on-exception true} :aliases {"gem" ["trampoline" "run" "-m" "puppetlabs.puppetserver.cli.gem" "--config" "./dev/puppetserver.conf" "--"] "ruby" ["trampoline" "run" "-m" "puppetlabs.puppetserver.cli.ruby" "--config" "./dev/puppetserver.conf" "--"] "irb" ["trampoline" "run" "-m" "puppetlabs.puppetserver.cli.irb" "--config" "./dev/puppetserver.conf" "--"] "thread-test" ["trampoline" "run" "-b" "ext/thread_test/bootstrap.cfg" "--config" "./ext/thread_test/puppetserver.conf"]} :jvm-opts ~(let [version (System/getProperty "java.specification.version") [major minor _] (clojure.string/split version #"\.")] (concat ["-Djruby.logger.class=com.puppetlabs.jruby_utils.jruby.Slf4jLogger" "-XX:+UseG1GC" (str "-Xms" (heap-size "1G")) (str "-Xmx" (heap-size "2G")) "-XX:+IgnoreUnrecognizedVMOptions"] (if (= 17 (java.lang.Integer/parseInt major)) ["--add-opens" "java.base/sun.nio.ch=ALL-UNNAMED" "--add-opens" "java.base/java.io=ALL-UNNAMED"] []))) :repl-options {:init-ns dev-tools} :uberjar-exclusions [#"META-INF/jruby.home/lib/ruby/stdlib/org/bouncycastle" #"META-INF/jruby.home/lib/ruby/stdlib/org/yaml/snakeyaml"] ;; This is used to merge the locales.clj of all the dependencies into a single ;; file inside the uberjar :uberjar-merge-with {"locales.clj" [(comp read-string slurp) (fn [new prev] (if (map? prev) [new prev] (conj prev new))) #(spit %1 (pr-str %2))]}) puppetlabs-puppetserver-7e1a9a8/resources/000077500000000000000000000000001470345337400211005ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/resources/ext/000077500000000000000000000000001470345337400217005ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/resources/ext/build-scripts/000077500000000000000000000000001470345337400244645ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/resources/ext/build-scripts/dropsonde-gem.txt000066400000000000000000000000341470345337400277650ustar00rootroot00000000000000dropsonde 0.0.8 scanf 1.0.0 puppetlabs-puppetserver-7e1a9a8/resources/ext/build-scripts/install-vendored-gems.sh000077500000000000000000000052671470345337400312400ustar00rootroot00000000000000#!/usr/bin/env bash set -x set -e install_gems () { gem_file=$1 additional_args=$2 gem_list=() while read LINE do gem_name=$(echo $LINE |awk '{print $1}') gem_version=$(echo $LINE |awk '{print $2}') gem_list+=("$gem_name:$gem_version") done < $gem_file java -cp puppet-server-release.jar:jruby-9k.jar clojure.main -m puppetlabs.puppetserver.cli.gem --config jruby.conf -- install ${additional_args:+"$additional_args"} --no-document "${gem_list[@]}" } SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" SOURCE="$(readlink "$SOURCE")" [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" echo "Installing JRuby vendor gems" cat "${DIR}/jruby-gem-list.txt" echo "jruby-puppet: { gem-home: ${DESTDIR}/opt/puppetlabs/server/data/puppetserver/vendored-jruby-gems }" > jruby.conf install_gems "${DIR}/jruby-gem-list.txt" echo "Installing JRuby Standard Library gems" cat "${DIR}/jruby-stdlib-gem-list.txt" echo "jruby-puppet: { gem-home: ${DESTDIR}/opt/puppetlabs/server/data/puppetserver/vendored-jruby-gems }" > jruby.conf install_gems "${DIR}/jruby-stdlib-gem-list.txt" # We need to ignore dependencies to prevent puppetserver-ca from being installed # with facter2 (from gem dependency resolution) and facter3 (from puppet-agent packages) # If puppetserver ever loses its dependency on puppet-agent or if puppet-agent ever loses # facter, this will probably explode. # # Unfortunately, even with well-crafted `GEM_HOME`, installing the puppetserver-ca gem # with `--minimal-deps` or `--conservative` does in fact update dependencies even if they're # satisfied by already-installed gems. So, `--ignore-dependencies` is our best option here. # Sorry. # - Morgan, 04-29-2019 echo "Installing MRI vendor gems (with '--ignore-dependencies')" cat "${DIR}/mri-gem-list-no-dependencies.txt" echo "jruby-puppet: { gem-home: ${DESTDIR}/opt/puppetlabs/puppet/lib/ruby/vendor_gems }" > jruby.conf install_gems "${DIR}/mri-gem-list-no-dependencies.txt" "--ignore-dependencies" # We need to install Dropsonde into an isolated directory so that its dependencies # can be installed with it without relying on the gems otherwise shipped by # puppet-agent or by puppetserver. echo "Installing Dropsonde into an isolated directory, to prevent dependency conflicts" cat "${DIR}/dropsonde-gem.txt" echo "jruby-puppet: { gem-home: ${DESTDIR}/opt/puppetlabs/server/data/puppetserver/dropsonde }" > jruby.conf install_gems "${DIR}/dropsonde-gem.txt" puppetlabs-puppetserver-7e1a9a8/resources/ext/build-scripts/jruby-gem-list.txt000066400000000000000000000002021470345337400300710ustar00rootroot00000000000000semantic_puppet 1.1.0 hocon 1.4.0 text 1.3.1 locale 2.1.4 gettext 3.4.9 fast_gettext 2.4.0 concurrent-ruby 1.2.3 deep_merge 1.2.2 puppetlabs-puppetserver-7e1a9a8/resources/ext/build-scripts/jruby-stdlib-gem-list.txt000066400000000000000000000002501470345337400313530ustar00rootroot00000000000000matrix 0.4.2 minitest 5.15.0 net-ftp 0.1.3 net-imap 0.2.3 net-pop 0.1.1 net-smtp 0.3.1 power_assert 2.0.1 prime 0.1.2 rake 13.0.6 rexml 3.2.5 rss 0.2.9 test-unit 3.5.3 puppetlabs-puppetserver-7e1a9a8/resources/ext/build-scripts/mri-gem-list-no-dependencies.txt000066400000000000000000000000261470345337400325670ustar00rootroot00000000000000puppetserver-ca 2.6.0 puppetlabs-puppetserver-7e1a9a8/resources/ext/cli/000077500000000000000000000000001470345337400224475ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/resources/ext/cli/ca.erb000066400000000000000000000001471470345337400235260ustar00rootroot00000000000000#!/opt/puppetlabs/puppet/bin/ruby require 'puppetserver/ca/cli' exit Puppetserver::Ca::Cli.run(ARGV) puppetlabs-puppetserver-7e1a9a8/resources/ext/cli/dropsonde.erb000066400000000000000000000006531470345337400251420ustar00rootroot00000000000000#!/usr/bin/env bash PUPPET_AGENT_RUBY="/opt/puppetlabs/puppet/bin/ruby" DROPSONDE_DIR="/opt/puppetlabs/server/data/puppetserver/dropsonde" DROPSONDE_BIN="${DROPSONDE_DIR}/bin/dropsonde" export GEM_HOME=${DROPSONDE_DIR} export GEM_PATH=${DROPSONDE_DIR} if [[ -f "$DROPSONDE_BIN" && -x "$DROPSONDE_BIN" ]] then $PUPPET_AGENT_RUBY $DROPSONDE_BIN "$@" else echo "Dropsonde does not appear to be installed properly." fi puppetlabs-puppetserver-7e1a9a8/resources/ext/cli/gem.erb000066400000000000000000000007071470345337400237150ustar00rootroot00000000000000#!/usr/bin/env bash umask 0022 cli_defaults=${INSTALL_DIR}/cli/cli-defaults.sh CLASSPATH=${INSTALL_DIR}/<%= EZBake::Config[:uberjar_name] %> if [ -e "$cli_defaults" ]; then . $cli_defaults if [ $? -ne 0 ]; then echo "Unable to initialize cli defaults, failing irb subcommand." 1>&2 exit 1 fi fi "${JAVA_BIN}" $JAVA_ARGS_CLI \ -cp "$CLASSPATH" \ clojure.main -m puppetlabs.puppetserver.cli.gem \ --config "${CONFIG}" -- "$@" puppetlabs-puppetserver-7e1a9a8/resources/ext/cli/irb.erb000066400000000000000000000006731470345337400237230ustar00rootroot00000000000000#!/usr/bin/env bash cli_defaults=${INSTALL_DIR}/cli/cli-defaults.sh CLASSPATH=${INSTALL_DIR}/<%= EZBake::Config[:uberjar_name] %> if [ -e "$cli_defaults" ]; then . $cli_defaults if [ $? -ne 0 ]; then echo "Unable to initialize cli defaults, failing irb subcommand." 1>&2 exit 1 fi fi "${JAVA_BIN}" $JAVA_ARGS_CLI \ -cp "$CLASSPATH" \ clojure.main -m puppetlabs.puppetserver.cli.irb \ --config "${CONFIG}" -- "$@" puppetlabs-puppetserver-7e1a9a8/resources/ext/cli/prune.erb000066400000000000000000000013061470345337400242720ustar00rootroot00000000000000#!/usr/bin/env bash usage() { echo "Prune contents of report and bucket directories." echo echo "Usage: puppetserver prune []" echo " bucketdir|reportdir work on either bucketdir or reportdir" echo " delete data older than this amount of time (default: 14d)" } prune() { DIR="$1" AGE=${2:-14d} puppet apply --no-report --log_level=warning -e "tidy { \$settings::${DIR}: age=>'${AGE}', recurse=>true, rmdirs=>true }" } case $1 in -h|--help) usage exit 0 ;; bucketdir|reportdir) prune "$1" "$2" ;; *) echo "Error: unknown argument." usage exit 1 ;; esac puppetlabs-puppetserver-7e1a9a8/resources/ext/cli/ruby.erb000066400000000000000000000006741470345337400241310ustar00rootroot00000000000000#!/usr/bin/env bash cli_defaults=${INSTALL_DIR}/cli/cli-defaults.sh CLASSPATH=${INSTALL_DIR}/<%= EZBake::Config[:uberjar_name] %> if [ -e "$cli_defaults" ]; then . $cli_defaults if [ $? -ne 0 ]; then echo "Unable to initialize cli defaults, failing irb subcommand." 1>&2 exit 1 fi fi "${JAVA_BIN}" $JAVA_ARGS_CLI \ -cp "$CLASSPATH" \ clojure.main -m puppetlabs.puppetserver.cli.ruby \ --config "${CONFIG}" -- "$@" puppetlabs-puppetserver-7e1a9a8/resources/ext/cli_defaults/000077500000000000000000000000001470345337400243365ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/resources/ext/cli_defaults/cli-defaults.sh.erb000066400000000000000000000015711470345337400300210ustar00rootroot00000000000000INSTALL_DIR="/opt/puppetlabs/server/apps/<%= EZBake::Config[:real_name] %>" if [ -n "$JRUBY_JAR" ]; then echo "Warning: the JRUBY_JAR setting is no longer needed and will be ignored." 1>&2 fi java_version=$($JAVA_BIN -version 2>&1 | head -1 | awk -F\" '{ print $2 }') java_major_version=$(echo $java_version | awk -F. '{ print $1 }') if [[ $java_major_version -eq 17 ]]; then echo $JAVA_ARGS | grep "add-opens" &>/dev/null if [[ 0 -ne $? ]]; then export JAVA_ARGS="--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED ${JAVA_ARGS}" fi echo $JAVA_ARGS_CLI | grep "add-opens" &>/dev/null if [[ 0 -ne $? ]]; then export JAVA_ARGS_CLI="--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED ${JAVA_ARGS_CLI}" fi fi CLASSPATH="${CLASSPATH}:/opt/puppetlabs/server/data/<%= EZBake::Config[:real_name] %>/jars/*" puppetlabs-puppetserver-7e1a9a8/resources/ext/config/000077500000000000000000000000001470345337400231455ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/resources/ext/config/conf.d/000077500000000000000000000000001470345337400243145ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/resources/ext/config/conf.d/puppetserver.conf000066400000000000000000000070521470345337400277330ustar00rootroot00000000000000# configuration for the JRuby interpreters jruby-puppet: { # Where the puppet-agent dependency places puppet, facter, etc... # Puppet server expects to load Puppet from this location ruby-load-path: [/opt/puppetlabs/puppet/lib/ruby/vendor_ruby] # This setting determines where JRuby will install gems. It is used for loading gems, # and also by the `puppetserver gem` command line tool. gem-home: /opt/puppetlabs/server/data/puppetserver/jruby-gems # This setting defines the complete "GEM_PATH" for jruby. If set, it should include # the gem-home directory as well as any other directories that gems can be loaded # from (including the vendored gems directory for gems that ship with puppetserver) gem-path: [${jruby-puppet.gem-home}, "/opt/puppetlabs/server/data/puppetserver/vendored-jruby-gems", "/opt/puppetlabs/puppet/lib/ruby/vendor_gems"] # PLEASE NOTE: Use caution when modifying the below settings. Modifying # these settings will change the value of the corresponding Puppet settings # for Puppet Server, but not for the Puppet CLI tools. This likely will not # be a problem with server-var-dir, server-run-dir, or server-log-dir unless # some critical setting in puppet.conf is interpolating the value of one # of the corresponding settings, but it is important that any changes made to # server-conf-dir and server-code-dir are also made to the corresponding Puppet # settings when running the Puppet CLI tools. See # https://docs.puppetlabs.com/puppetserver/latest/puppet_conf_setting_diffs.html#overriding-puppet-settings-in-puppet-server # for more information. # (optional) path to puppet conf dir; if not specified, will use # /etc/puppetlabs/puppet server-conf-dir: /etc/puppetlabs/puppet # (optional) path to puppet code dir; if not specified, will use # /etc/puppetlabs/code server-code-dir: /etc/puppetlabs/code # (optional) path to puppet var dir; if not specified, will use # /opt/puppetlabs/server/data/puppetserver server-var-dir: /opt/puppetlabs/server/data/puppetserver # (optional) path to puppet run dir; if not specified, will use # /var/run/puppetlabs/puppetserver server-run-dir: /var/run/puppetlabs/puppetserver # (optional) path to puppet log dir; if not specified, will use # /var/log/puppetlabs/puppetserver server-log-dir: /var/log/puppetlabs/puppetserver # (optional) maximum number of JRuby instances to allow #max-active-instances: 1 # (optional) Whether or not to track lookups during compilation; turning # this on will send that information to puppetdb # track-lookups: true } # settings related to HTTPS client requests made by Puppet Server http-client: { # A list of acceptable protocols for making HTTPS requests #ssl-protocols: [TLSv1.3, TLSv1.2] # A list of acceptable cipher suites for making HTTPS requests #cipher-suites: [TLS_RSA_WITH_AES_256_CBC_SHA256, # TLS_RSA_WITH_AES_256_CBC_SHA, # TLS_RSA_WITH_AES_128_CBC_SHA256, # TLS_RSA_WITH_AES_128_CBC_SHA] # Whether to enable http-client metrics; defaults to 'true'. #metrics-enabled: true } # settings related to profiling the puppet Ruby code profiler: { # enable or disable profiling for the Ruby code; defaults to 'true'. #enabled: true } # settings related to submitting module metrics via Dropsonde dropsonde: { # enabled: true # How long, in seconds, to wait between dropsonde submissions # Defaults to one week. # interval: 604800 } puppetlabs-puppetserver-7e1a9a8/resources/ext/config/request-logging.xml000066400000000000000000000017151470345337400270070ustar00rootroot00000000000000 /var/log/puppetlabs/puppetserver/puppetserver-access.log true /var/log/puppetlabs/puppetserver/puppetserver-access-%d{yyyy-MM-dd}.%i.log.gz 200MB 90 1GB %h %l %u [%t] "%r" %s %b "%i{Referer}" "%i{User-Agent}" %D %i{Content-Length} %mdc{jruby.borrow-time:--} puppetlabs-puppetserver-7e1a9a8/resources/ext/ezbake.conf000066400000000000000000000076321470345337400240200ustar00rootroot00000000000000# NOTE: I'm no longer certain whether or not it actually makes sense to keep this # file in this repo. When we have to do preinst stuff, we get into a situation # where we need to do some kind of variable interpolation into the commands # that we're expressing here... and it's starting to feel like we just have # too many levels of indirection going on. Maybe this stuff should just be # kept directly in the ezbake repo. ezbake: { pe: {} foss: { redhat: { dependencies: ["puppet-agent >= 6.16.0"], build-dependencies: ["%{open_jdk}"], # Install some gems install: [ "bash ./ext/build-scripts/install-vendored-gems.sh" ] # This is terrible, but we need write access to puppet's # var/conf dirs, so we need to add ourselves to the group. # Then we need to chmod some dirs until the Puppet packaging # is changed to allow group write; Haus said that this # has probably the way to do it for now. There might be a better # way to get rid of the hard-coded paths here, but I don't # know it. postinst-install: [ "install --owner={{user}} --group={{user}} -d /opt/puppetlabs/server/data/puppetserver/jruby-gems", "/opt/puppetlabs/puppet/bin/puppet config set --section master vardir /opt/puppetlabs/server/data/puppetserver", "/opt/puppetlabs/puppet/bin/puppet config set --section master logdir /var/log/puppetlabs/puppetserver", "/opt/puppetlabs/puppet/bin/puppet config set --section master rundir /var/run/puppetlabs/puppetserver", "/opt/puppetlabs/puppet/bin/puppet config set --section master pidfile /var/run/puppetlabs/puppetserver/puppetserver.pid", "/opt/puppetlabs/puppet/bin/puppet config set --section master codedir /etc/puppetlabs/code", "usermod --home /opt/puppetlabs/server/data/puppetserver puppet", "install --directory --owner=puppet --group=puppet --mode=775 /opt/puppetlabs/server/data", "install --directory /etc/puppetlabs/puppet/ssl", "chown -R puppet:puppet /etc/puppetlabs/puppet/ssl", "find /etc/puppetlabs/puppet/ssl -type d -print0 | xargs -0 chmod 770" ] } debian: { dependencies: ["puppet-agent (>= 6.16.0)"], build-dependencies: ["openjdk-8-jre-headless"], # Install some gems install: [ "bash ./ext/build-scripts/install-vendored-gems.sh" ] # see redhat comments on why this is terrible postinst-install: [ "install --owner={{user}} --group={{user}} -d /opt/puppetlabs/server/data/puppetserver/jruby-gems", "/opt/puppetlabs/puppet/bin/puppet config set --section master vardir /opt/puppetlabs/server/data/puppetserver", "/opt/puppetlabs/puppet/bin/puppet config set --section master logdir /var/log/puppetlabs/puppetserver", "/opt/puppetlabs/puppet/bin/puppet config set --section master rundir /var/run/puppetlabs/puppetserver", "/opt/puppetlabs/puppet/bin/puppet config set --section master pidfile /var/run/puppetlabs/puppetserver/puppetserver.pid", "/opt/puppetlabs/puppet/bin/puppet config set --section master codedir /etc/puppetlabs/code", "usermod --home /opt/puppetlabs/server/data/puppetserver puppet", "install --directory --owner=puppet --group=puppet --mode=775 /opt/puppetlabs/server/data", "install --directory /etc/puppetlabs/puppet/ssl", "chown -R puppet:puppet /etc/puppetlabs/puppet/ssl", "find /etc/puppetlabs/puppet/ssl -type d -print0 | xargs -0 chmod 770" ] } } } puppetlabs-puppetserver-7e1a9a8/ruby/000077500000000000000000000000001470345337400200475ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ruby/facter/000077500000000000000000000000001470345337400213135ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ruby/hiera/000077500000000000000000000000001470345337400211375ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ruby/puppet/000077500000000000000000000000001470345337400213645ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/ruby/resource_api/000077500000000000000000000000001470345337400225275ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/000077500000000000000000000000001470345337400200205ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/fixtures/000077500000000000000000000000001470345337400216715ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/fixtures/agent-cert-with-exts.pem000066400000000000000000000052641470345337400263660ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIHuzCCBaOgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA2MTQwMgYDVQQDDCtQdXBw ZXQgQ0E6IGZpcmVob3NlLmRlbGl2ZXJ5LnB1cHBldGxhYnMubmV0MB4XDTE1MDMx MjIxNDQyOFoXDTIwMDMxMTIxNDQyOFowGTEXMBUGA1UEAwwOZmlyZWhvc2UtYWdl bnQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDFtl/mcbaEsW9b2dtR 8XJD3o/NXJJ9rw1XhSRmoWPEWf/yUn29BDfqim6DDvLmQds7NLC6aF3sU9HrFM3K KJjPn30DxOM+sW2HoSePSfqArmC8QlISGoXxrywmiYVkrmTJpwJb4jMATMboyY/l PDtiblvybUyeXgXXEAEZ0VvuvVDXPwahDAb/+TQrmMQsJCii9krMdDT4ewm3TcuR 1457z41j6wvbai/hspFkYxFcjKMAcFIPRCNOGpnLzBvKyccgL7rGSS8I2/1u2avK 0/oIVtQbqGYLi/c6pd1YOrZKcCo0euOEMvCQ+f2E0VLdc86BXCwVGkDKDBeAPryA bG4wFgGmrvZ4XJV8LzO7S4kfHaXL0BN6bDAVssjiApvJl0H3K8K9WuCUSsBqGGCI q6nKQjjW+6+/O19oRYRkWTUi76UT6xOy8++q+4lFokMToKys2NCvHLXGW7CXwYNP 632anpwQ3jcokP7zZXRyuCLs8ZK9GfZPQ/3QBhSu6f9o8uViOK6Ra7avW7/Hsqp7 mnN2/4OMUf2UNUhckWIsxPLahRaDDJpnQlciwra0FXHvxfRsS8i6aZ6bnqAcSxIO Xas1d+iKjghpgjx6IYdFF+80wXThCZoVcNd2TDYvp3T4QX6ZBsyJcQHTd+11qMkn kuph6pkUO2M4PJA9NveCs2DBpQIDAQABo4IC7zCCAuswMQYJYIZIAYb4QgENBCQW IlB1cHBldCBTZXJ2ZXIgSW50ZXJuYWwgQ2VydGlmaWNhdGUwHwYDVR0jBBgwFoAU BG3a4q4VY5fgJTXL0kiiaMfqNGswHQYDVR0OBBYEFOoJ3huRWou/t5EP9QByypRY e8PrMDUGCysGAQQBgoxMAQEBBCYMJEVEODAzNzUwLUUzQzctNDRGNS1CQjA4LTQx QTA0NDMzRkUyRTAvBgwrBgEEAYKMTAEBAQQEHwwdSSBhbSB1bmRlZmluZWQgYnV0 IHN0aWxsIHdvcmswHQYLKwYBBAGCjEwBAQMEDgwMbXlfYW1pX2ltYWdlMDUGCysG AQQBgoxMAQEEBCYMJDM0MnRoYmprdDgyMDk0eTB1dGhob3IyODlqbnF0aHBjMjI5 MDAbBgsrBgEEAYKMTAEBAgQMDAp0aGlzaXNhbmlkMBcGCysGAQQBgoxMAQEFBAgM BmNlbnRlcjAYBgsrBgEEAYKMTAEBBgQJDAdwcm9kdWN0MBgGCysGAQQBgoxMAQEH BAkMB3Byb2plY3QwHAYLKwYBBAGCjEwBAQgEDQwLYXBwbGljYXRpb24wGAYLKwYB BAGCjEwBAQkECQwHc2VydmljZTAZBgsrBgEEAYKMTAEBCgQKDAhlbXBsb3llZTAY BgsrBgEEAYKMTAEBCwQJDAdjcmVhdGVkMBwGCysGAQQBgoxMAQEMBA0MC2Vudmly b25tZW50MBUGCysGAQQBgoxMAQENBAYMBHJvbGUwGAYLKwYBBAGCjEwBAQ4ECQwH dmVyc2lvbjAaBgsrBgEEAYKMTAEBDwQLDAlkZXBhcm1lbnQwGAYLKwYBBAGCjEwB ARAECQwHY2x1c3RlcjAcBgsrBgEEAYKMTAEBEQQNDAtwcm92aXNpb25lcjAMBgNV HRMBAf8EAjAAMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV HQ8BAf8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBAE3eeKiQ8YAzgX2b9deakGpq r8aUZZOOOiUlpMXxNr7kr9k4PRSjR9lcm4wDG9Pv2txsAGC7HRszE7RxN/tRlwxJ L01oKN+JKXwE4v3r5aHs6/MkxIr9uYslpZ3IonZaK1VGhOsir4rLApNlCFPRJJe4 zigpkjLq4kzajBRXM0qaQbfJxt7pvHhu4YEyXfYrnSWwffcR6jnlz2pYfLW4mKw+ n4RMmhw+0WGaAWbuJItegb/RbXg+/oZ8rwp6o94Z4tfYFS5wl7nopLfci+CVjysQ oBqLPh47VEOdcWPK09U03qiUIoRzgL0FzJPYjIBPGPpIrFJhvCIQggLh9bVjdpXW 6IX67MMt4bxdrfoGSDWrGKRuhCnFt/X6yhWJhWcYNWpGdA+dYlIVT7EOHl/C7urA fF4qK+fl5RTxViKn/gaBgdpO+hmB6RSw2vYsMPgqRQ75LhWBsMLGiMnGLQUhTkaN LXXJKaieaqmstgHyqO887gOE6B9IGEVa1Vp9nDVfJpHZhnuGBBrVCoXRZ5DVJHaD vWRY7BshjyVTWxyK1NdCkNA8uMHMkjbwEIuf0Ogo2rcTifyu3o+PFbWY68YtFeJs Ef1w2Lh7dFca6W4RqzDUCb3FAEcFzJdoQUWe8ntfYdVRz0iKGUMoMGel3BYZH+dh Whswob1mvDKDTKiPCnW0 -----END CERTIFICATE----- puppetlabs-puppetserver-7e1a9a8/spec/fixtures/ca-cert.pem000066400000000000000000000036071470345337400237200ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDA5MjQwMDI2MjBaFw0xOTA5MjQwMDI2MjBa MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogbG9jYWxob3N0MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA5d7J0M924Hcchzs1MfZMn0qiIY5mhRLLfPsxm83Q vRl4rCmXt9Hnmq/kxU3c9+60bB/7z5gQOImHvfWJ7P23EI4DTSwNeAsRTva84nPD evasOkNwycMHIRUWXQUQIM/IHpTz/f+UccFpsJjWTckb5yhUkuSa+ukR0+YJzgTR XdKUfyh58TC95WSw93toJBZswepM5wf53s6gt0bMwhsMQKbMfDo7EOKS0py/bOIK YVT3r0ixOsQdH7AvpgybQ+IBK28LzAa5CVpq2IbdoxKluyEL0j4jHc3f6r5JiAp0 hF2OaBiw7JajWsoZPbeLADAFVWY90L9C2R/OL+kvR7O4dSYIR4a60wVJKXXnnY/C NPMS+Aqu4EV7xyh5JwO0dtqJfeIhnfMRYQO+nxwKKpw2E7lP+FthmuewDx5P7QYg vkjbLC4vXFkG8WNTPJSSKkUhgRNexl88RDPUF1E1cgHsKX9cRcNqitS2Au2LKY8o x4/fRqOwHLPcwgUIOKJWKKC7gneKB7IjS2R4pYv7iisyVKnF4G0/VKAQiOmW6c4g xCoZWSHqhIxzO9ReffesD+gnN5Kp+U0JSOdBMC7DAjsuHGlwi+gxBYy+yS1aMbyf hDPno487sjXBPG6U7pi4R/2EWFJ8GxC8iSSygD80FaQXJEvahgUILUgn1xFtIUBQ KukCAwEAAaOBqTCBpjAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRl cm5hbCBDZXJ0aWZpY2F0ZTAxBgNVHSMEKjAooSOkITAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdIIBATAdBgNVHQ4EFgQUeMyE9a6xFda+LhPQY+0eVEtI S4IwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL BQADggIBAMPM6AF3aaxBCDaMGaHvClzrWkIEMdUzGo0CBI8a+u6tmx+UD2zHxPtj rbMNyYLOwEcyBP67Wq06Z7rJW8/02cOI84DF971HClWhmz+UCswgh506HcppkykO /VU6itF9LLnLpv5OzGEUXeTV3dDRjgMQW0Z6PTbFyxQg/2urb82US2plx/xQw9X/ 3IxEzbbJM2ylG+ipTplhnO2PkTLv1kGGbJOGjs/Si5Rv+fLRoP+PpCRAoVT1tF36 i7ylmZJ70ZHLkCwjRueqJaI/LnUVeMM7k4gEYNkIE2s4Gg6G8aEHLFBfrLc5o52M +8xMArukOgifdlJq8ucdRNJ7AoHcBdayZczCJBlAe7xAUq85viSNIhjp7w7rI+cE wNkjUOYBd5wKgrDdw/0QWdm9arOV50/vfkoT0luMqgFPFD5tLiDcNNBT46ymWA7W Pqa1Z3uljcJDsk+UIabwzK+wbtPNT/7Mn4b3LBPFEGMLggOKss+lt4Rt47HZRce3 tcwf951BHNzWYfk2Ou3ZkpRbKNHj+M1UIPyDETCyfnvu534cgHjLk946V9b23tAc QKSz7YkYd5fq3pkPq6CNH04UL73jCwoHA4MZ2LZAKSOU1oSx2/tKpzlKLmr3RV1x eWxPXfiOYhyv8Im79UD5C/XNOAws+p85rfN0uAcoZdrhJp8glPqg -----END CERTIFICATE----- puppetlabs-puppetserver-7e1a9a8/spec/fixtures/localhost-cert.pem000066400000000000000000000036131470345337400253220ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFZTCCA02gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDA5MjQwMDI2MjdaFw0xOTA5MjQwMDI2Mjda MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBAJ9SatJi8sCzU91ehCRRKvZ1hTrVrgvE6nDUVt8bBvi7BRJW4wAE49Wi MV/sfQqjxvfJ3zj6NH4ufDdApCIQ1UmAa6x+/wDzCk8r876bZBb45DVdEP4dYrIn DGsKFaFrlDwlL+YQw2bbwGkvUMiHZVWvD4yRK+dJkvHS+0139TPKP1s/R9NOrrrl OQdTSBQVBNqqHzDV9a/m9QY2LIh3L0OYjwtpJqXNyrC/I4nvcD7sxo7tI6w1LmeP f/KJBIHDSexD1Ubk/xT1uKcMQwbJ2jIqfALJERK7+ZfS9nY9tAA7sLRSbClF6V6J mmhVoE7c/ZqToOARi0rbUhMz/HpfmoEblze/vMRBHh1u/uLhF4aBK4uojccLh0xB stQm664EseNBbM195wpnv+woDO4D63hdngNBeilywnkSZ5r4okZ6F+AFQD9Om2Pe MWBjGxBbn8w3NqZNRuUkY2YUDjTeS/EjAdVrjXo/lQAe2/Imf7acbSKn2iyQrYzM 0Hl7xCTXuFskflDB/lqmd6lvCdCmiIFWsDhPqkec5byFC85291hy1EKO03SeHTD0 8dFmaSiCFWf6S/c5953ln5NXcvg+DibiagecpIdfvd5UDTgp44ABgvJeU8QQ0O+L N9DoeUwzL15Ou/faA4ubfbiJCxkMon0GiZjAZ614rRlwnLvYOKKhAgMBAAGjgbYw gbMwMQYJYIZIAYb4QgENBCQWIlB1cHBldCBTZXJ2ZXIgSW50ZXJuYWwgQ2VydGlm aWNhdGUwHwYDVR0jBBgwFoAUeMyE9a6xFda+LhPQY+0eVEtIS4IwHQYDVR0OBBYE FGqMJXJCPV2cmTD9vyjPgEBZQWiUMAwGA1UdEwEB/wQCMAAwIAYDVR0lAQH/BBYw FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDANBgkqhkiG9w0B AQsFAAOCAgEADY0gSoBFHo8Na7UrFMWNQExZLzSTuO0OV3St5VE3nDBRfO54ISim Y4i62RIyPUr+uOiQAGBHxQwThutHzKj7unFgfbP4jfGZS5OGV67rsgDL30eya5ut 7ThJuqYxoBloUIvX6XwCGgq5/59nuvk7jm5XSKxQxUsivSfg92kAj4n5h/FZSx3h UGMjjGL/Z6T6qLQ7H0v/2P0VrblwVtB6AdwHdiiTYtkyKEXTrYYU8jVu6jSG5ztL YEY5k8JAvc19KIIt0hT4AknccH8p6Bnw2tuu5o+ZUXYnezyOXVQ1bwQAogSncJxf wD3ibTEdQXabanophmLWd0UyjnQGokt/JlcP6KbLYjq7664lO5VsO8J//ejFW7hz 6rpLMmKjeTYH+Po8UZKdX/lV4rRAA2mAd2n8HBOfqnrahtbnZkYtgBUAaqa03bdR XTR4pPxoe/YkAZi4IaqUdCCtN0YF7Geu2iMxOjtEckeWx6cnnLE9z5gK9zpOl20d k5ed9u27/m7CIiWsHGbJ4jTm0EEpVuU0+s+3fMdctyfAfEBBag/8VQhKUrMxdHJI kjGGeKnGP4j9E2AuZ7f8qWcP9m12ZcTEYENfOipa0ssfk8yS/nLk7ULMk1ViapZE atmKI/0iWzZXFoPhb22UScydzclmfkDErxi7o1at+xX1rXNw1sTXVV4= -----END CERTIFICATE----- puppetlabs-puppetserver-7e1a9a8/spec/fixtures/localhost-privkey.pem000066400000000000000000000062531470345337400260610ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEAn1Jq0mLywLNT3V6EJFEq9nWFOtWuC8TqcNRW3xsG+LsFElbj AATj1aIxX+x9CqPG98nfOPo0fi58N0CkIhDVSYBrrH7/APMKTyvzvptkFvjkNV0Q /h1isicMawoVoWuUPCUv5hDDZtvAaS9QyIdlVa8PjJEr50mS8dL7TXf1M8o/Wz9H 006uuuU5B1NIFBUE2qofMNX1r+b1BjYsiHcvQ5iPC2kmpc3KsL8jie9wPuzGju0j rDUuZ49/8okEgcNJ7EPVRuT/FPW4pwxDBsnaMip8AskRErv5l9L2dj20ADuwtFJs KUXpXomaaFWgTtz9mpOg4BGLSttSEzP8el+agRuXN7+8xEEeHW7+4uEXhoEri6iN xwuHTEGy1CbrrgSx40FszX3nCme/7CgM7gPreF2eA0F6KXLCeRJnmviiRnoX4AVA P06bY94xYGMbEFufzDc2pk1G5SRjZhQONN5L8SMB1WuNej+VAB7b8iZ/tpxtIqfa LJCtjMzQeXvEJNe4WyR+UMH+WqZ3qW8J0KaIgVawOE+qR5zlvIULznb3WHLUQo7T dJ4dMPTx0WZpKIIVZ/pL9zn3neWfk1dy+D4OJuJqB5ykh1+93lQNOCnjgAGC8l5T xBDQ74s30Oh5TDMvXk6799oDi5t9uIkLGQyifQaJmMBnrXitGXCcu9g4oqECAwEA AQKCAgBFXyWUJfF9ZpgFs7nl9lG2rsUsMQ5voXZTWqHY03PdqdEzgxGkWHy78Lt/ AQIRN+7Sxduke42Pw73icQsGqj20m25G1aVDTJAYmRKw1Aho2EbF1ZgojbMDz2zg zqtMdgM9jROmIXZzuwu0wR1zs0C0Zl1m3282bhrFoRA7Uxg5TL75hDxKDeCXEGgc gG7KD7zlWV3rbb5ksTPPWJdbdEnoLO1cEpT5bPnsq81VqiQ9wetTIH5/5UgnX5xe hrqnpdjyPzcGf39yKOwWEIi+0/VmEomczN/aQG8VZI5cPdG6qELwwVLHReGvgErz UxVSQXdLbyyFZB46ofTC18f/oNEs5g5+EcGxfX/h1Td6RW/KSO7UbsYTUloDzfIZ mwkfxAatyUfeur61GLGPa02aW2b/9w3w8rNpJRatuVWFABVnIvXe3As5+zngxKWL 7Qi2sny/qSbwV0Maw30LqelYwtLRGq9bnzGQvU/RlWPNxuN04/UUiHkSbjXHGU8Y yhHAchNPnJuU40hrwpbBmHc1OiY9/coWtH/wahYrQ163+79bpQ1TEdr1IBGE+x/g Vk6+hHM67r+yy3xTrvwy0AKjZWpzcMA2OqSJUoghy6vNo848XzyqyM8DIunwgK/c +YBF2d+6x+ZAc2PaKqGjKXVhnNKVOvVxGwsLky34r5mTQh3RYQKCAQEA151LmMa7 9dcr0JKcSGk3GYl7REkKuJpAW8eycKItZ+XHr+fypxsjxEsyi2bKNiYxYswG0d6e VaV84K25VxKC7d8ZrdpseKqBNYLfZQRZwNLRMbww58aGkNRyFBOgAkDFJO1suvA/ N+EToX0m3cBH/VlCQO3Yo69c1vTR9/q8Ap8S01Gx9fgFK9jGaks4f9tLQX/WBqYU yvjZxPoUXR3ANFyv4K9bokQpwh58PiBv2GUHqDGRrrh1vbv4VZBU5LzEXBLpRcxf /pDNqTvA5h1qAZJ3HuqY8rLdqNntRZ28l+iZMRklWdneE1YBKSV4rCk5SGeTevXa 1KSIifTnvewN2wKCAQEAvSnmHxGQBDaogyOUEBYE1JGCT4E31aQlTgCYOnYLufMP 3tXPZ4F6WC6tcHdLssX2+YwVQyS7McjGXgzcfDhbMT7b2twd2SLM/3cqM18YQOo+ N0xw9oQC8KT+anBm9jUMuT/FyYsS2XqEvJ9JNvAhHbtz6MZWA3RqPrhA3+pUM0w5 LK/fU9X4XhsU1UxJeub76eldM8jx7DSbU4loVX70tvViBzlZsThdItlm5o1KCcWg GwheaQVRiWyYrEmq9LeTg6bvThBQOXmIM0XKqfAkFtMJu1b5uSorDTWl1LCmH2zE CuUiOKRsvPFoL4UR0uhYOAtgfD0oIjCBtS+7vWugMwKCAQBVcZUKpv7HboyDbAYY v/FA4nWB2vwvqZkFhf6Vmf8qZCmc8Or9A8lJuY7/JS3PBZWelEHDm1fdkuYI129S LRjLkRTJC3ze2Jq5jPJgQrgarLCP6AbtYoPjEv1eLWTEX8yAVMI41ooG59/yp/jl +ZPNtziFKHwoaY799Cjc/3TQCR/ZtE80rSPHe3EtoD90k3+gJju3iMtGoBUUdRHq 0KZhWbWs8XD7vc1aiuArcolAFNFS+snDln+6P6oqpjauKowZ/LiKm3ITHGkTvoUz 68Ydd2BTVR5lVzJ1/l6Drv2UqW1DwrZFhAv4V6XAG4RVnUSBB+Ku4IzmpYkiOnY3 kjrvAoIBAHTgp4P4yQAheXsVh41s3W0tvtM65vHE6xvH+Ebe2x34lYy8lNrCQIKt zJIZ05bRBGlp6VVEI7l98Tr5PV4vQAEscpFGwdaAzyLlURjOn+C0Gt72BzH5nQtt FplTe/qSCpuHUMDXgj0Hm24kCQu90OhbAyIHMewOiPrZw5PWaFINvaHjxNw676vN ldC4wwoCIBKGEwVFGl00n+g8lU+GEtPcx8Xo5IdAaSN4KkE3eVCSX/tz70l6dMex Zp/FILD1oFqO0XttTvREKCht7euUKehEWtX6xm9nI5SU2jKRNwNho7uLmdpflaQk kJgT41BqKN/v/5yj+OEvEWWO6bP/BMsCggEAEUq3i1Jsq92D156U7rUd//XU1p7c akcwLlMS5k7BPBiLbaDHO8XX4zrX5N+s5TZnhzoduoFfxdgGSbFxymEv3F8xSz5X M6OdKfvvLnocZEpKX4Rb9XRWqVv/MQRxVGTUfiZ6DvOodSx2HJzFSP8nMQEABYUR vU05p3drU4pK7ox2G+IgsptxWKHQELtWRW7Cxeh7ED3s8mHKIfibSbEvJ9UK2sKm +XbOAeoOZAZQBU0zyVmX/oLsQmQVmkkG+OOrMEZioJGTvbXYIeFHCPcHe3TCjTfm KysgEhy7ilVCxLRN7+iX+RtWRgeWTp5WypMltqha2NN2C54zd7eZKSsSaw== -----END RSA PRIVATE KEY----- puppetlabs-puppetserver-7e1a9a8/spec/fixtures/master-cert-with-dns-alts.pem000066400000000000000000000037411470345337400273230ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFpDCCA4ygAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDA2MDkyMjQwMThaFw0xOTA2MDkyMjQwMTha MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC AgoCggIBALvrojfJFu7MQoh3iDfxiRNkNg0O410uHPuWzcA2Cm9VIRBAfFO1jnyS 3fHlDYHpf179Ce1vkKoG4binJ2anFjjggR00tQ4hba4io+Umh5Ypxh/Vk4KBX5PI sBMr2enUNF05dpS1MgRGcVyEAOkWZFyaFQpfDN9JwizlHHFczATzWl5kywqOoq8E C+f9O4Sj2hEQaHOxQo0HQLutOYUrnbSD5vur9JXBaobvDUlFd78VwYDHsY8qQwG+ bTAtZ6Kzq67r0yAjVpZm91f18MCli76vFFXfJQnNSwNeHwUpd9xTdHDkms4rqpSf 6K5kRB5vj2Q6wiI9etb+bvWaHk61u87f3/I9Hn4sY7RiL+6eCEm5KtV7CPnyFrTl Q9AdRseMsd8sZ15xc81yBRC5tKr+v782b2oxsbI1MQn3jK/vnRQyDZmdadbxaxJX Apqz/c4unK4SWawUnHsB0XgV646UBOt1dQ0k84O4MiZc6ml9ZUIvDcRL2hj2n2O5 8Zm+EOxhVZwS0Xao6zZ2mcH6FMqchV6ffBD7MKiXMc94HH6wvh5NAoWFi6zmP+2U gwkWFtEcxtVqz3sVlDsLKijgZ6UNKIjII6/i15hMWg7gwIU5/XEPZa44g9+3tdXC 3TT7Qtyuiy7Y+BKqw86Gg/Z53sX8B/1Rp5NWTimL6nFD+muXK4m9AgMBAAGjgfUw gfIwNQYJYIZIAYb4QgENBChQdXBwZXQgUnVieS9PcGVuU1NMIEludGVybmFsIENl cnRpZmljYXRlMDkGA1UdEQQyMDCCCGJsdWVmaXNogglsb2NhbGhvc3SCB29uZWZp c2iCB3JlZGZpc2iCB3R3b2Zpc2gwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQW MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQv kk4Dd64jBY5WrHdjLF1TjaFkJDAfBgNVHSMEGDAWgBQv94nGxDKpOQ4oHTgc5X3D lr6yxDANBgkqhkiG9w0BAQsFAAOCAgEATVOv8XQ13115Sj+g9AfhCQT4bFzFKYnb B8gN8N0p3LPClzZ3bd2VU1R+tdWa81owWOXaaxmxiYw1+nZ8WULuWXOYACM7q7Yt 9puZbL/Au/TVfMFD6WBV6JOm1YOYusy5NF6npZnTFkJRWnlX0LQWh8HFNe9YnWhb m7Q/qkcB12RkFDjs5bwylc8S7CSQ8YuZqTHBvh946Hki8pIrDSQ2rdOtNPmfyLXE Z7zjQFAbybIGgoshYUsVT4GhNhICEhed6vQmBS8prb1EaxTPfE5YgbpW5ZZlJq1C 3kYGfot5KhvlEn0AnXEuPgklFMByxzCtO+Se6cSbZJPbOoI0v2L65bYIYaUDGaoN AnecSjcW/bId+IgaFEoftWWzvDtyNvump2LxBhyS7iJgUANl1m+qxkLDaLWFTO6f OP9T8PANSCfZno3crBPydXAN28ScMCZQobLFEJdqtBesU7IpxTC8onRK13KvDZAj VT5rU7WiVcTzbUNODD4c0vdbCsjqZs2I4rOu1zsqdsZ1CsDdSN4kEvLLhao3KhqW z0Dir2tFNbv9U9EbAQEhu76Tmwn1UAUyOItz7JlqMCOhr2ZtKiciqL9ww66SOIrP II70NvF6T7Al2XufX0xfmNnVknoi8HFr+VSUeJ5KBPwfkZg7Alz/lLGSwjOxW7Yp xGgmq4DQZNk= -----END CERTIFICATE----- puppetlabs-puppetserver-7e1a9a8/spec/fixtures/puppet-cacerts000066400000000000000000005045531470345337400245670ustar00rootroot000000000000009trustcor_rootcert_ca-1:2.9.0.218.155.236.113.243.3.176.25~RXX.5094000 ڛq0  *H  01 0 UPA10 U Panama10U Panama City1$0"U TrustCor Systems S. de R.L.1'0%U TrustCor Certificate Authority10U TrustCor RootCert CA-10 160204123216Z 291231172316Z01 0 UPA10 U Panama10U Panama City1$0"U TrustCor Systems S. de R.L.1'0%U TrustCor Certificate Authority10U TrustCor RootCert CA-10"0  *H 0 &k3@X YP{ &2#TI%"FɞN.,8%hZHt>ix^ 'zR-ձ괉a$۩R $~tl)QW󨍜$K*֙~B: SڷhLp?J,&ciNGMln`!sвwEZ&fvvamUŃVrdZֆp$(+jzܲyec0a0UkIZdٶ~eĎ1~vӅXwzv;l/Pgy(!g MZw\Ô$=2kK~x7M_N<3 2 B0@0U0U00UcݍUjPAeBI0 *H=g0d0ayBGSo}u䍉wFmaN0[ׅ7{'J&|hmso&!&A[%`H_quovadis_root_ca_2_g3:2.20.68.87.52.36.91.129.137.155.53.242.206.184.43.59.91.167.38.240.117.40~R;X.509d0`0HDW4$[5θ+;[&u(0  *H  0H1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 2 G30 120112185932Z 420112185932Z0H1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 2 G30"0  *H 0 %W?F#qaf!_'Qn-}PSwx:`d|Օ6ۘ43(FҴM rI}}k:%mRDnܦsa 燣 %R%˸5 ;Z]΀qmI>;׀[^`*17 :2, Ӟ]Lh{S5̀ HJՌqJA]VWC)U[#!Xj+g敲"n*AUih/S^Ҫ!0gUǛnUE#:e]*;Om4qZ\#`s%Ւ 9ڴ9W5r!;51z!n2}2JbrwvgA n٢'RV+,$B&Ən8}S-혳ch5߈`5|ia >EeXP8HY< p.<B0@0U00U0UovZ`I[ƥwrq=0  *H  ߀?C ~q볈Q=u(]ȼ{] ӟg1~jA;\`jbn*M<)XLHaa.65'f4;ars\GTIzX 3uj`^o#˄aD_bU$RQ~:/S,5"_j^S2 0X rƱ|i{6Ean^L^^3T~kCp]u Y#9ߩ&Hdz"37ZG{odI g!5c`("㱕ͅ/gRn/|Js>!?I[%T8ySN{8,r%wRHP_ 0nC=S!O"Y*G=-jl4H+;xfĎyijgeotrust_primary_certification_authority_-_g3:2.16.21.172.110.148.25.178.121.75.65.246.39.169.195.24.15.31~R[X.50900nyKA'0  *H  01 0 UUS10U  GeoTrust Inc.1907U 0(c) 2008 GeoTrust Inc. - For authorized use only1604U-GeoTrust Primary Certification Authority - G30 080402000000Z 371201235959Z01 0 UUS10U  GeoTrust Inc.1907U 0(c) 2008 GeoTrust Inc. - For authorized use only1604U-GeoTrust Primary Certification Authority - G30"0  *H 0 ^bX3W923ˇJd18.c+FD( Ip!de&ƥׄpO?Dr}1(a(Ds"ilcRژ'Lp>g]3jSѺ6`acl[~@ !(p&ll`%NU~}ᅯH޷p_@Amb8VGQ { bvU_w>IS=%v$Zۉy嶳;?L(Aj}BGB0@0U00U0UyʎNk1[>?0-0  *H  -V{zx,ߔ^ inhrGJd9%4N$4Ʀ0has^(J*'.| weD 6 j)Vrw5fWS؎@ZrǷizh}A%\| .\J@ >a$->V܍AH I?}ˍg*\1]F-tE@zh-"+ǜ_-Puca_global_g2_root:2.16.93.223.177.218.90.163.237.93.190.90.101.32.101.3.144.239~RbjX.509J0F0.]߱Z]Ze e0  *H  0=1 0 UCN10U UniTrust10U UCA Global G2 Root0 160311000000Z 401231000000Z0=1 0 UCN10U UniTrust10U UCA Global G2 Root0"0  *H 0 +o|&'$o2"aA;hL+g"+)xk ~ʓь5uEzw#.{F#[,Tz*ɍz;$h1<3FT/"T*X Qgl׶V/:;GR~$k@4g-oy><Kq` dCmq'[ƮY}(-5VXK7|K2#oHDN:T /߿WO;:!&5T ?GZKz;P\bKJ+nsPAש~mXJ+ V^)n ۽!ʉߵx6Ln>k&z/-s5ZLuq98Sx@̃ [HHGN*u*{"ɾ Wzp) ;ND֧N&hFVEX< %9;4y/G穗iwg{zeaVeB0@0U0U00UČ0 _g!t0  *H  e"+DhÀH={#/z6ڲm_X72e8=5>;мI6˼9_TtOdvEILoÔD'֩vX'?R^eքڹ5q&Ow'w;oyӔWQ' 0o+ԿED0괧[>֭x\<حk6(T,s7< )[II_'e5W0A[1j'b̵Ff86F_"h='S<eo~)DIi(i_do b΀h޾3[LL; TW6/|G:3X;DO(hK&3/P2T[^ "!b!@.d_~gEﳨ} "-p4v0#xVP/starfield_root_certificate_authority_-_g2:2.1.0~RLX.50900Š0  *H  01 0 UUS10UArizona10U Scottsdale1%0#U Starfield Technologies, Inc.1200U)Starfield Root Certificate Authority - G20 090901000000Z 371231235959Z01 0 UUS10UArizona10U Scottsdale1%0#U Starfield Technologies, Inc.1200U)Starfield Root Certificate Authority - G20"0  *H 0 o[Hٝy⢷aVG=5.Ciފ Iw2)V"r'aZn,܄[tk_ʼnRFUuTKUrWqY(tŝHld7yF^mSLb c:yat&@crj u7Yb__e0MvZv^4Vͽ21|_kI\љѢc[ vVbKt&YИB0@0U00U0U| 20}hbΫ['0  *H  Y%Oo;9v^(mb]  ԰u84j䟊&Q,-n J츊g{1g.&.CJ1 7"{Rk;yQN͐g8ush~~-ʤЗJ(Tx !q}a= "{ dE ;@}|2X}*Ysd6t^%f.9*Picomodo_aaa_services_root:2.1.1~RX.50960200  *H 0{1 0 UGB10U Greater Manchester10U Salford10U Comodo CA Limited1!0U AAA Certificate Services0 040101000000Z 281231235959Z0{1 0 UGB10U Greater Manchester10U Salford10U Comodo CA Limited1!0U AAA Certificate Services0"0  *H 0 @nvMEDFȃ*]P1 p"I-Tc̶nhF SL$rNT z3`ډU"XOhF'v5,^deHav PfxbV18'2Xok+c_s8x6Qx:B /I-߬tMG)b&{>%ݝ5h Ä ^/00U #>)00U0U00{Ut0r08642http://crl.comodoca.com/AAACertificateServices.crl06420http://crl.comodo.net/AAACertificateServices.crl0  *H V{DOX̦Ihv]`֍PO&N氥tTAOZ``J¿Ĺt-}kF/j4,}Z  /\:l7U S@lXenbHq)W0  *H 01 0 UUS10U VeriSign, Inc.10U VeriSign Trust Network1:08U 1(c) 1999 VeriSign, Inc. - For authorized use only1E0CU f/G/F +QvF ̨LYUS\b _ vίjA3zcӞb7ՅeS$t^S[,I;hW0  *H ?/ɲZd!O4v6W/ŭ7bs>_5+ۮ` __n =Z `o#". ˩tGץk/BIݧSZ(P0)F=58bJQlޯb$zhfE\i+Z7^*\TTǘ0;6ۣnG1OO x 5VڷmdEk zNOKK}Wcertum_trusted_network_ca_2:2.16.33.214.208.74.79.37.15.201.50.55.252.170.94.18.141.233~R6X.50900!JO%27^0  *H  01 0 UPL1"0 U Unizeto Technologies S.A.1'0%U Certum Certification Authority1$0"UCertum Trusted Network CA 20"20111006083956Z20461006083956Z01 0 UPL1"0 U Unizeto Technologies S.A.1'0%U Certum Certification Authority1$0"UCertum Trusted Network CA 20"0  *H 0 xՀ ddg?":u}\g\kB Kڛ{]ٛKׄ@+'0> I+@$—ǧ% Z)5pMJVA81_?I`&*gFG0.rccyD~Kc$.4?)LR*(['P,4Y Jٞ#kw*̭;Fs^bhEW䐂BBa=f]ɍE)2u1)&kbE7Z#h>N'@ MMZWugx4ܽRVu{A]i C9{lZOr})zDR*AF "[0 pRQ.N pVm۵WK,%Ȟ.xNڜ,WȒzüPiZF:&#ɶB0.Fu̹Ї[`5^gGHb9UO9cB0@0U00UT9à?:0U0  *H  q?8ՉZaL-OSkeI&&op^9\mNObD Y[w 7 N.X3φ`/L`x=!dAuq\4>A? /ޚZV5:_pM^)#(rYŒf&w,&v5(i;#݅tɐV篺G"Il緔K-3LDZ<dص16Ṥz`PʦV749%9fzYf>>{K7Dm{˨qյ6+QLP=Y|}-!g^{\" ۪DQf}vj*8v kavp+)< [BV/U.^ee_certification_centre_root_ca:2.16.84.128.249.160.115.237.63.0.76.202.137.216.227.113.230.74~R X.50900Ts?LʉqJ0  *H 0u1 0 UEE1"0 U AS Sertifitseerimiskeskus1(0&U EE Certification Centre Root CA10 *H   pki@sk.ee0"20101030101030Z20301217235959Z0u1 0 UEE1"0 U AS Sertifitseerimiskeskus1(0&U EE Certification Centre Root CA10 *H   pki@sk.ee0"0  *H 0  KxD tab#ثe2zO {clnjL.yi\bpQ}Гl0K}Rn{e82bhaS6씺62|ot{W K20X[ͨpsۗ|!=Hl'%tUu=dkO@2ӼSɉM~~V !p w5NM?cDD%vʷJfd\ŜN>,lK00U00U0UZ>V%ɩK0EU%>0<++++++ 0  *H { GMWjcŎPV8$"fSa*9?}(@!jįRwV]6^PT*䪌O5v}D?Uӂ<[VL".FC$@-;pAj O>n)M I2[K\ts]۱D:p7k3r(ɳW K (=7Stn̼Cq^av rrr6GP`$ovuŝHgts_root_r3:2.16.110.71.169.199.108.169.115.36.64.137.15.3.85.221.141.29~R'yX.5090 0nGls$@Uݍ0 *H=0G1 0 UUS1"0 U Google Trust Services LLC10U GTS Root R30 160622000000Z 360622000000Z0G1 0 UUS1"0 U Google Trust Services LLC10U GTS Root R30v0*H=+"bO33)!XAV+KL'&Qro֣EF~~/qEAUn+&KTE lD 2'B0@0U0U00U&-* g0 *H=i0f1[|#,ܾo#eR^ȝrtS }@h`T;6%15t%Q$dR$PvnS)Ӄ#ɤ{a]=hellenic_academic_and_research_institutions_rootca_2011:2.1.0~R*UX.50950100  *H 01 0 UGR1D0BU ;Hellenic Academic and Research Institutions Cert. Authority1@0>U7Hellenic Academic and Research Institutions RootCA 20110 111206134952Z 311201134952Z01 0 UGR1D0BU ;Hellenic Academic and Research Institutions Cert. Authority1@0>U7Hellenic Academic and Research Institutions RootCA 20110"0  *H 0 S.`->,*TN͹aXO=CuQ7ҊMyCxJH:)D5hU8Q$1}w{8PZy71& <0.gr0.eu0.edu0.org0.gr0.eu0.edu0.org0  *H yA{n?7BJN7f$O!%m]")l =[:Ú4N $lk Na(jbI%ȗM!T p˿_Ӳ0\{` S{~sR{JI^Zz뾌鳬%J*/w|Ź:,Y}_^Ij9^4x lK} yM-!l[})ӔI$b ' +sƝ/M6zma\ QZί `_r`^J?!›00U0U00UWgjY-.06U/0-0+)'%http://crl.globalsign.net/root-r2.crl0U#0WgjY-.0  *H ShJD 'OCx ,[AdC-9Ң߷E--tVIOnDx9~yo5]mDmyF1~ n P_M ɠAjsSPn%LRَiވIޕ x`%@j~B8@d.geotrust_global_ca:2.3.2.52.86~RX.509X0T0<4V0  *H 0B1 0 UUS10U  GeoTrust Inc.10UGeoTrust Global CA0 020521040000Z 220521040000Z0B1 0 UUS10U  GeoTrust Inc.10UGeoTrust Global CA0"0  *H 0 c0#V~[&d΃qN{U^8S\O-P#6fˎ99 8.M>o,`96S9^&+=2(Rq3=86by0_+qkS0Q0U00Uzhd }}eN0U#0zhd }}eN0  *H 5)j/]T)Px*b'g^GANKJoUR$7 dv*.,;uq=7ҵbމ=6{8wH . ²EQ""H d^Ot>NJR mƱThi? }J攥ǃ'lݠ]R+9jtM4\M3_ /f]wv 5լ$qp,V Q+^uO4f3Xamazon_root_ca_4:2.19.6.108.159.215.193.187.16.76.41.67.229.113.123.123.44.200.26.193.14~RX.50900xlL)Cq{{,0 *H=091 0 UUS10 U Amazon10UAmazon Root CA 40 150526000000Z 400526000000Z091 0 UUS10 U Amazon10UAmazon Root CA 40v0*H=+"bҫ7OS {K{FKcb-q!c'9n]=Ɂ[ E]m_bpd3$/p*ubā9n).\B0@0U00U0U:envVmW0 *H=h0e0:!~X/~+fU,(p G7Y-(N*O5M3Z1uN;:XF!rLJۖԬkkIS3$ vԥBec-acc:2.16.238.43.61.235.212.33.222.20.168.98.172.4.243.221.196.1~R X.509Z0V0>+=!b0  *H 01 0 UES1;09U 2Agencia Catalana de Certificacio (NIF Q-0801176-I)1(0&U Serveis Publics de Certificacio1503U ,Vegeu https://www.catcert.net/verarrel (c)031503U ,Jerarquia Entitats de Certificacio Catalanes10 UEC-ACC0 030107230000Z 310107225959Z01 0 UES1;09U 2Agencia Catalana de Certificacio (NIF Q-0801176-I)1(0&U Serveis Publics de Certificacio1503U ,Vegeu https://www.catcert.net/verarrel (c)031503U ,Jerarquia Entitats de Certificacio Catalanes10 UEC-ACC0"0  *H 0 "OBG@s$QÒ@p`e"ClfD >9oKzcDcf(Bn'i_frOez>O `:BDz4ՙ^H~euB}Hd]Prv]BPyД>k kN*>̂e3w]=ȗzp|q-bm8?  uBp4" KА'00U0ec_acc@catcert.net0U00U0UËD7EZx]0U x0v0t +x 0e0,+ https://www.catcert.net/verarrel05+0)'Vegeu https://www.catcert.net/verarrel 0  *H H[MH9U5zSZq;9 ^[]}O͠A4↜7V)Ğ5ߊ !C骈5BcZ^H:oܝ?zaw pzٗ,dtz n _] QP&a]- C]4 s8,& zrP2“i#A6ъ:cYi kOjciH.3YigaDr?j}Hëq+SiAS4 İEA]nE{=;&t}X2" ^;'p8n'vQ!Յ"<)ŀk0/F "00U!0Nڇ*Ч.@1L0U0U00RUK0I0GECAhttp://crl.netsolssl.com/NetworkSolutionsCertificateAuthority.crl0  *H KW-sGjW!!ceRy~Zs褂G[Ta/K0#ur|!]^gt.G)4_2%7I%]tnfDߡƾH/7xJ?^]YtCcsIB0@0U00U0U8V#9qlTL:g0  *H  B{ F`@%~h.[@v<YbZdhrC4 ,SʐKf"o&HvwŘ\&{ùd2Xm챫Utw'RkLݹe^Kujj vz$ GdSx bsCA+j.Sk_r"Q-B޻;WV;[|(KI||펡`SUP4{lJDm7XnJhv굒aQ __\~Vof^ tfNI~oP"_e خKJ1fDhW3/Ĕ{ўd:vb€ؤ|/2LhHRԙ$㳥! _;8Ƿm:D1kpRA.u[ n{^6w 9yFCY' #V@!1=eC=pDM&;Ȏ8V!jQӑFډ=S,Sbuypass_class_2_root_ca:2.1.2~R"X.509]0Y0A0  *H  0N1 0 UNO10U Buypass AS-9831633271 0U Buypass Class 2 Root CA0 101026083803Z 401026083803Z0N1 0 UNO10U Buypass AS-9831633271 0U Buypass Class 2 Root CA0"0  *H 0 ^wC!i2ۣY uRaHʌܖ`(sVKd *7I |Js0e/~`t[1Q~oSwԗU3>/uԭI˕Tl[&Y$qyDPh$_)AaA#62PNӎK\N= s Q+T}<Bgb^wUi:DJŞz'|uת%k MN{.Yj ~88 W=! ݋4*hphkRFܵWs98޴Si~ďpdfiIQgJlM3a]2K<.ZR @c7R?agkRh@CW5SxSaBdoL8 cb6s !tMrI_bcݑ3mn0h&u^{ v2MlOB0@0U00UɀwbFL޸90U0  *H  S_!:R9,l tz?r]qO㭬m.q.㭣 J{WA,YG!Q)0`F:[DAOG ʵ{w~A^Ƕ9?Ao`"q}=FjzJ+vT$,O?N){\-f[Q ~bxpj`y $r×?wC" ,kAkߙˊ^ &6H85%-zE,ĈSwٚvŎ,2zMH"jΎ`"#Zzi@WkYP٣ny'#ޒ{ MZKH0Z mһ|n!h9MXfbJ^'yt̾ &`VQ?aZMl2#CJ <]q¾y‡h \iК}T*9K*Cc]ZX/ Оׁ & V,d-trust_root_class_3_ca_2_2009:2.3.9.131.243~R X.5097030 0  *H  0M1 0 UDE10U D-Trust GmbH1'0%U D-TRUST Root Class 3 CA 2 20090 091105083558Z 291105083558Z0M1 0 UDE10U D-Trust GmbH1'0%U D-TRUST Root Class 3 CA 2 20090"0  *H 0 ӲJzGu#:/PE5:kh7PMJh5Sєc VQx*=HHP> FU'mM RC؇]N6!_9@_[~̣+@6H4F $QJP?i]EQ#rV ) UӴG5ZJs!Ъ &lk ZP+f18 .gRF>ؤZ1His|ʖގ2e4W_v/ 00U00Uğ0!B9c#I0U0U00~|zldap://directory.d-trust.net/CN=D-TRUST%20Root%20Class%203%20CA%202%202009,O=D-Trust%20GmbH,C=DE?certificaterevocationlist0CA?=http://www.d-trust.net/crl/d-trust_root_class_3_ca_2_2009.crl0  *H  0ߤ}!zpi`D0OPf~0p1ip  u~M`;^hأ@`6!дt߰okk,%$re%Z2߫Ii#\Xeԗ. %*5`u=A#lSL"M[sdTPmќUi6ÌQPY(({Sm&p>nZ^te\Issl.com_ev_root_certification_authority_ecc:2.8.44.41.156.91.22.237.5.149~RDX.50900,)[0 *H=01 0 UUS10 U Texas10U Houston10U SSL Corporation1402U +SSL.com EV Root Certification Authority ECC0 160212181523Z 410212181523Z01 0 UUS10 U Texas10U Houston10U SSL Corporation1402U +SSL.com EV Root Certification Authority ECC0v0*H=+"bG@ N0a!hCTAb\p2aQ=}\S58͟. J.ZpZ )c0a0U[^ҁͨ-dQrO0U00U#0[^ҁͨ-dQrO0U0 *H=h0e1@7k$=FXoVpk8豌OgvQ0=#(&L`&5<%<[leɇb\Jtwca_global_root_ca:2.2.12.190~R^X.509E0A0) 0  *H  0Q1 0 UTW10U  TAIWAN-CA10U Root CA10UTWCA Global Root CA0 120627062833Z 301231155959Z0Q1 0 UTW10U  TAIWAN-CA10U Root CA10UTWCA Global Root CA0"0  *H 0 n!Mq RpmLNEI@B4lt1_C3 SҜy+jf+ԳPUfG`/+295R:({bG%Mc?u_)0*6C'ILpZCmos7E6̈ulk>aq|I<֡ao0) N&㢨j‘E\嘸q|uptO-DV(j\ XKvȫ"sZ?O"tS*=S'il2,d&ca6NF?}-mڂ4!)~8)J!fyõ gF*"7`ˁȕUz=o 4@g՘;x&Z+t<߸ߩlg3Ⱦ ,)ok_*[PApqM2klᐌHM_j Bw/"&1Q}2#0!0U0U00  *H  _4vcpQLG5 (=q٪3Al!lB~i[ Bߢ|Ki '.MpGJ3E! iisr 45ע8ǥ4?( WNUإ}zo߁N!eyE_FchDdp=(9pb{ = O,vARWҝw)^Q` -uCHyƄ]Y`x(F CFYGo!(9 6Ϝ@ty+?4 i}a07#raE)HYhow.MoEpiÉazl &T9&3u-Okf!GދJU/3g~ħDGX {+p)@b-;Hi#l`O-9u}IP|~۶ӜײB0@0U00U0UмC]+ ל0  *H  4aVUMݣ51Fr_ab 7<)ɨzq(isRվ:vjV!]:>i* G p}R>Y|@arpҷ)hcе a~v̺0̣atkdIMyf1pgLaّwq`X "U'Km; cg/ fOcW?e%ϲvn'xS? ҨaFʇh"&qܠӹV-ߌ+22<"*C.Ø98{^B2&yQ # TL/IJѶn` kk$d%G[<~I ~Hq9>4j}"i3HU& -5Yȟ>Z)4=αeYVu!wz`ӭ|^SJ")H+>M[Y`XeD~'}L>qTKXYautoridad_de_certificacion_firmaprofesional_cif_a62634068:2.8.83.236.59.238.251.178.72.95~RzX.50900S;H_0  *H 0Q1 0 UES1B0@U 9Autoridad de Certificacion Firmaprofesional CIF A626340680 090520083815Z 301231083815Z0Q1 0 UES1B0@U 9Autoridad de Certificacion Firmaprofesional CIF A626340680"0  *H 0 ʖk5LR}^C*Oj](xiYW B[/b2q8 q=Q~c\鿔o)Q<7J\K6$ÄwP/-Yz NiR6 7ɒ7ׁ-Ĺ>4g>f@^b4p> Zr%lts#Y_ Gh]+< _ vva3>{?jo&oAlPjc 훛ɐ =>8#/ UNЍ~tsGd/0U 00U 00/+#http://www.firmaprofesional.com/cps0\+0PNPaseo de la Bonanova 47 Barcelona 080170  *H }K$ݥJUK+W;12[d622wD*=jn|ӭ֣d)|8+'e.qGd2%'B B*D&1H*tKՇ(y4>.DO5?%9c*k _RN,*Hf҃f% 3e ZTݯN&^ ܳՁpO$lNLIf %AHQB~dIߢL*紱eļpc;L@"0[Hvs}EuruDB}Wk}ܙ=(ꀓLep8C14G"G_f#侇] J_h{e:-k$XDGY!ep4`@<(#'3C@<;rJK^HȌŝr644kvS$"K|UƝennO~ <ahongkong_post_root_ca_3:2.20.8.22.95.138.76.165.236.0.201.147.64.223.196.198.174.35.184.28.90.164~R-2X.50900_Lɓ@Ʈ#Z0  *H  0o1 0 UHK10U Hong Kong10U Hong Kong10U  Hongkong Post1 0UHongkong Post Root CA 30 170603022946Z 420603022946Z0o1 0 UHK10U Hong Kong10U Hong Kong10U  Hongkong Post1 0UHongkong Post Root CA 30"0  *H 0  NmYW)h>hhX`KC Nu鵧5K_30 3S٦>IP-PXpV\,+i;r%6[kUJ a=P:cAS0Y<wczP`׼j|[*9:T9q!{n$%,,ĉ/ LOۢ7G-_44Lg7HW{ yRB7z=Pc?E77~HuEr(@c0a0U00U0U#09+p\Ԡa0U9+p\Ԡa0  *H  V{n"Bf#\ǒ锭K|tHYH0[Ws.Y$Xh..bjp - P 22IzGnˣr:-i]E9BLw]jXD끞f8~ULE;Szx¾Fv?"HR~!%=^-7\!NG+UܫЂuP/va*!1ЪG":PW[CgebICϱcEZ,-ŦG'L8 .I;R舃+T(5R2bid t'baltimore_cybertrust_root:2.4.2.0.0.185~RMX.509{0w0_0  *H 0Z1 0 UIE10U  Baltimore10U  CyberTrust1"0 UBaltimore CyberTrust Root0 000512184600Z 250512235900Z0Z1 0 UIE10U  Baltimore10U  CyberTrust1"0 UBaltimore CyberTrust Root0"0  *H 0 "=W&ry)蕀[+)dߡ] m(.bb8!A+R{wǺj s@b- PҨP(%g? R/pp˚3zwhDBH¤^`YYcc }]z^>_i96ruwRMɐ,=#S?$!\):n:ktc3h1xv]*M'9E0C0UY0GX̬T6{:M0U00U0  *H  ]oQhBݻO'%d-0))y?v# Xapaj ż0| %@Ọ~87Oh1Lҳtu^Hp\yeR79թ1z*E<^Ȟ|.ȤNKmpmkcd.Ps2~5>0z3=ebGD,]2G8.2j<$Bc9Ydigicert_assured_id_root_ca:2.16.12.231.224.229.23.216.70.254.143.229.96.252.27.240.48.57~RX.50900 F`090  *H 0e1 0 UUS10U  DigiCert Inc10U www.digicert.com1$0"UDigiCert Assured ID Root CA0 061110000000Z 311110000000Z0e1 0 UUS10U  DigiCert Inc10U www.digicert.com1$0"UDigiCert Assured ID Root CA0"0  *H 0 C\`q& 9(X` ک2a<(ܟ zyS\1*26vÌ3/(nDa5YvmK + rڞ`Ў5xU m I|13l"2Z9:r1u}"?F(yȱW~VŨ?_wOc0a0U0U00UE뢯˂1-Q!m0U#0E뢯˂1-Q!m0  *H rszdrf2BubV( `\LX=IEX5iGVyg <&, =(_"◄egI] *&x}?+&5m_I[=%̶odh-BbPglk 67|[mzF`'KΗg*h߀ 3f nc%mlaң&qÙQ+.P E/Kssl.com_root_certification_authority_ecc:2.8.117.230.223.203.193.104.91.168~RFX.50900uh[0 *H=0|1 0 UUS10 U Texas10U Houston10U SSL Corporation110/U (SSL.com Root Certification Authority ECC0 160212181403Z 410212181403Z0|1 0 UUS10 U Texas10U Houston10U SSL Corporation110/U (SSL.com Root Certification Authority ECC0v0*H=+"bEnPĦ#6_(˖"d?zq$IGX-5'뉌SXb[k1RcA;춍4ܻE# Gӣc0a0Uхs05ӎ!0U00U#0хs05ӎ!0U0 *H=g0d0oY`a{/PkFF!b ]r>Ī0 0$|mU > 3fՋ ,]~hm|in_je8cybertrust_global_root:2.11.4.0.0.0.0.1.15.133.170.45.72~R>X.50900 -H0  *H 0;10U Cybertrust, Inc10UCybertrust Global Root0 061215080000Z 211215080000Z0;10U Cybertrust, Inc10UCybertrust Global Root0"0  *H 0 ȼPfy#ǎsۜetZw>Q}V#_X7MInjҌ'6eN*dՐ;(NHm1\-:m`FKI~Ft 珸kfDf%+0?Mk{ 8G]9*tZ;PE5PecݿwMbcs)IH𳪷lŧ09@]]&S#ab@8pwq0]%'00U0U00U{ z̬ LV2^ϫn-pW0?U8060420.http://www2.public-trust.com/crl/ct/ctroot.crl0U#0{ z̬ LV2^ϫn-pW0  *H V #TNEԣ%Xi0-́Zs#Z|";6Ls".#NJ n$"`g{r 1\yG= =Gi Dc%ɸv#}E~߳銶ͨg+Rշe9LcyRT݃яSs0|D_q "n>N a7^ EUР`[)`-La_HXV1N!e۴8Usonera_class_2_root_ca:2.1.29~RCX.509$0 00  *H 091 0 UFI10 U Sonera10USonera Class2 CA0 010406072940Z 210406072940Z091 0 UFI10 U Sonera10USonera Class2 CA0"0  *H 0 J5 D7H-5;ogMo2GAh5 C\͑_N]|&uyW):({6i^v-ӐN#(}cT;&v[BN9NI@TZf=< p#T|ȮrTa#Ѷq:i?BLj?qqXWPz\ktFÎnv2n's贓uDk` qW󾠐#=$!3010U00U JX^<0 U0  *H Z·rWKٛ&0g-48Ϋ/|5ˬL+k_6v۳aqD(:C蟿1q4G2e$J|s9orKz{(N g?gI$ja9k!u! pBq<6[ jl{BNN E^BPc]ı;.Zuc5ڝf T&43: 2nO%2ǖZpL>emsign_root_ca_-_c1:2.11.0.174.207.0.186.196.207.50.248.67.178~RdX.509w0s0[ 2C0  *H  0V1 0 UUS10U  emSign PKI10U  eMudhra Inc10UemSign Root CA - C10 180218183000Z 430218183000Z0V1 0 UUS10U  emSign PKI10U  eMudhra Inc10UemSign Root CA - C10"0  *H 0 멹(!Js4QVO,'yt_y9[pR%TZ?^Ƕ>ΚVB*9%pֿ{6s+7k&G;)Vjj:=8X䴸]x_ EhHFs4;vц2UΦO~#? 4 Eyҩ#*_Rbqd>6M/q(aH4AKLiP Ys|ICXVc==5VY +K)j0f0U0 0U ʜl:kT[5.^0U#0ր ʜl:kT[5.^01 0 UEU1C0AU:Madrid (see current address at www.camerfirma.com/address)10U A8274328710U AC Camerfirma S.A.1'0%UGlobal Chambersign Root - 2008 }#0U0=U 60402U 0*0(+http://policy.camerfirma.com0  *H pޒ(FW/ k|I$y'Fo)YRp=STo` Y|5g寺E DwEz3__,hG=Ղ5Ѿ68Vr1[G-cQ uˡdg#*9]!=BtphlP]I],Gׁ:Yskc 1E9p~@pZ?kBt=(/mur Hc#W^5 ,b|ݦ1~&jc07f/}K5:)P3JZnW?[ckԸrxk9]˛ONj<1(}觰dyHD?x{q><?(3BE |my/ł} |Tvn1֓%js[:.4'oB7P-XX:qh(#e?ꮙ0 OɄH-0#wFKym:`x雮Tt B`comodo_rsa_certification_authority:2.16.76.170.249.202.219.99.111.224.31.247.78.216.91.3.134.157~RaX.50900LcoN[0  *H  01 0 UGB10UGreater Manchester10USalford10U COMODO CA Limited1+0)U"COMODO RSA Certification Authority0 100119000000Z 380118235959Z01 0 UGB10UGreater Manchester10USalford10U COMODO CA Limited1+0)U"COMODO RSA Certification Authority0"0  *H 0 T V $Dgt+7}#pqS*KVpraK=a> >\4zk眳zvq l߰~Ħ/OgCr ։k,폘~nب$CkbUllixH0Eխ |3WA/a*z+=s XFn'ӕ7rsG8]Iy) $iWx9:|.b'9< h< WOȽ#ICy\ hL S, u e{#(+b{ ghjc!unƅ-$GyX*ٝה}J>VI= OI=@Y:.iYɐEC~y*=7fVhKh>07:"aN}կ{5~(G1yd[`<8)j/ UoX-Lfq )[AHqb-|۫Z1L"sy KNmų"5\?u'_ ͠@ \U)^?VW86EL(͞AVL@ȸ+ipj2ñ2D,oFfAOX aޥ]}e<UNDT|U")mN,g ba՗C-])*?e_+xlIS[eFJ]:r%!) eWWH́^digicert_high_assurance_ev_root_ca:2.16.2.172.92.38.106.11.64.155.143.11.121.242.174.70.37.119~RfX.50900\&j @ yF%w0  *H 0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0 061110000000Z 311110000000Z0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0"0  *H 0 sԻ--2?%Iq*Ք4g _i@ķИAY:ܔiGԘ&cd+0U#0>iGԘ&cd+0  *H ל#0WHEg7*}^䏗gKdW8Ui46=HOf^63ԴwPE]#~5P{0 hg]<S)b^rǖ-iP M=a:^ӍMӕ67_cc3-&kS|2n=!9ɡhP.:+6/oaQ 9>SgSvY6C =2`"Q3/x{F6y5Ǖ,;5s\Ye{z*7;p[+QS)ZO/b?iC| XuXK޺Gj_jG~*hx5M?0=0U00 U0UY8 {0  *H \bN$  hI"?D'omރfΨ wA{*!]Wu_&NOFzO@,"5kg,@75\\Bx P vQSzVI.z 'TM `rb֥͑șkL8o1nI?v&&)6 Sp4chkM0/]F GCY\Ht_1TA! {CŊXe xW# Ku*\sm{%EKӱYP:;)CF^+TSoJqB|(HāLs& &$ϻ[u}3,yw ipv"Bνs &*Л=p$l͇v Iў`Dr!19H$uTid9p@'VScekXM [v$P?*ٷqHYԐYaT L:̿uumVhgeotrust_primary_certification_authority_-_g2:2.16.60.178.244.72.10.0.226.254.235.36.59.94.96.62.195.107~RjX.509005k0 *H=01 0 UUS10U  GeoTrust Inc.1907U 0(c) 2007 GeoTrust Inc. - For authorized use only1604U-GeoTrust Primary Certification Authority - G20 071105000000Z 380118235959Z01 0 UUS10U  GeoTrust Inc.1907U 0(c) 2007 GeoTrust Inc. - For authorized use only1604U-GeoTrust Primary Certification Authority - G20v0*H=+"bC7b҃6R}EW J{T;:n_P%/}HPc*!|6 &X10(%]]l,C˺В 7swisssign_gold_ca_-_g2:2.9.0.187.64.28.67.245.94.79.176~RNX.50900 @C^O0  *H 0E1 0 UCH10U  SwissSign AG10USwissSign Gold CA - G20 061025083035Z 361025083035Z0E1 0 UCH10U  SwissSign AG10USwissSign Gold CA - G20"0  *H 0 ~$nP-D;\ʸ]B*eW@>W$P%*o$J#(XG#++ŰWbe=Vsڮ~m~B 5CMR,'w k/rx.>7Z*rb<+Z `ݵdSo&wb4Ւ3Q޾z`)u~bX%4A= PZsxbrix&(B b g9F8zf JV\ވhn}QP0V؃"d-%Tꭒ$JjG. VTΚjA'wjBl 8uP2+0"HA8%]]ƔuE0C džs`Ji-ޥxjK>w: "пhc`k5M m=#Ur%NFdʠj`/IB85nOV躣#o;0vmAf&:tI$[ɰW>z^oiste_wisekey_global_root_ga_ca:2.16.65.61.114.199.244.107.31.129.67.125.241.210.40.84.223.154~R5X.50900٠A=rkC}(Tߚ0  *H 01 0 UCH10U WISeKey10U Copyright (c) 20051"0 U OISTE Foundation Endorsed1(0&UOISTE WISeKey Global Root GA CA0 051211160344Z 371211160951Z01 0 UCH10U WISeKey10U Copyright (c) 20051"0 U OISTE Foundation Endorsed1(0&UOISTE WISeKey Global Root GA CA0"0  *H 0 O=6IjkI+2)CL#!EQU[7+k*ݨQ+fa\`r{;NeͤjsͼaM=qdpk~w$s{ 6ᙋ E1 rЎǶas vfc0',UO(VDn*9 1@I.zAdYqK,![}.hp `&Q0O0 U0U00U~6yܔ&!i0 +70  *H K nCH(. AIO=Mo&0tElQ6~L2:AO[G -tG;j6LRvnZ6S>ui)XSo\/ yverisign_class_3_public_primary_certification_authority_-_g4:2.16.47.128.254.35.140.14.34.15.72.103.18.40.145.135.172.179~RfnX.50900 /#"Hg(0 *H=01 0 UUS10U VeriSign, Inc.10U VeriSign Trust Network1:08U 1(c) 2007 VeriSign, Inc. - For authorized use only1E0CUE{UbR@GtZc( Vw@&y%>aQKQE̅ h>P8z$b 7mjM XN硭6k$9PҁF_bW,ldnT_-gcω7 zP "YRCVRMF'q$چ ~k ej腋:Uu~f!s5D =[^o*у#fmp2/R",`]/ïEÄ,ROݣԆ Sthawte_primary_root_ca:2.16.52.78.213.87.32.213.237.236.73.244.47.206.55.219.43.109~RSX.509$0 04NW I/7+m0  *H 01 0 UUS10U  thawte, Inc.1(0&U Certification Services Division1806U /(c) 2006 thawte, Inc. - For authorized use only10Uthawte Primary Root CA0 061117000000Z 360716235959Z01 0 UUS10U  thawte, Inc.1(0&U Certification Services Division1806U /(c) 2006 thawte, Inc. - For authorized use only10Uthawte Primary Root CA0"0  *H 0 YԜǤϝYs E ,nhl[HhIY7 3w-4M Ҹɗ6$_DboZ(\z tf/j8TDoN )>~qe Q{"` [ߺQ[ .b+NLdχXJOhJ/|qrg2ɒ\څS}+ 􌝑jR 6w{PD>n)i9I& {@-'a~|՝B0@0U00U0U{[Eϯz1jFWHP0  *H yKg nEU?%W:vLPvdr և2Awٳ`nDDUbw\HI|;Ws7/x\hG``=" rs|/>j'ZMd a9{"@yo=yv7!6c 3ADc B?,vcYݏ.A.Gϼ3 a~~+G'0]7\9+{Vh7gdca_trustauth_r5_root:2.8.125.9.151.254.240.71.234.122~RX.50900p} Gz0  *H  0b1 0 UCN1200U )GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.10U GDCA TrustAUTH R5 ROOT0 141126051315Z 401231155959Z0b1 0 UCN1200U )GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.10U GDCA TrustAUTH R5 ROOT0"0  *H 0 ٣ttw3 ;~U`vB}Vf>rc4,QQYTkLF]8Ƣ.WmJ pcNyķ[]A+:y _:<4&{V5_)N=n'=rzYN때"9y-̼A#íED,)P\˂6}戚M4 ,Zf*vJf1A?~F6dc;9#guuW7j&P6&pdmvfna../p;}Ǜ5a:Au+w*!ٕv gh  jsq/}S0F^KTgɥ ; ed *pga޸/+v9UL 0/ R T\e}灊W9tB[_tGҫ;xfN6}Icmqg/GJ*spF0Z/y c77epj\[ rc<27从'~p%b2'&2:MOp"+)p/Z߷F vz|bނfN:0?˭' ^бVwquP@C(R[cB>3zF. FT~jO1~Bt8es'|ץ:טUK@nWb|Wm͝*;qXEZSoE un]7f jHNtB)o.j}f1"̆~f B4O~rM pHXD i)%J+݊fxWqG17z$n AlݽX.50940000  *H 0G1 0 UHK10U  Hongkong Post1 0UHongkong Post Root CA 10 030515051314Z 230515045229Z0G1 0 UHK10U  Hongkong Post1 0UHongkong Post Root CA 10"0  *H 0 8fI㢴@yy$"څri? ݑЍZUP)&٠i( E"-V;TV"Y( =m6#n'?9S jte\|x͞.O *wĚRfH^"e]#f;2QȆv¦lA8 ;LmPă'Y=ut^:zB6rjMW_&x ywv ]o᫕_m<\M[ &0$0U00U0  *H F<^AL'jEOpZnmFn*.3봟7.g'ԦIevB/"lOZ9q+Qm*{A#t8U.g 7ڜ !y4oH 34Dp^C)laPoElO:F[-APgA=!N|ֵ'/n,D)SsSC]cqtkZIgts_root_r1:2.16.110.71.169.197.75.71.12.13.236.51.208.137.185.28.244.225~R%X.509^0Z0BnGKG 3Љ0  *H  0G1 0 UUS1"0 U Google Trust Services LLC10U GTS Root R10 160622000000Z 360622000000Z0G1 0 UUS1"0 U Google Trust Services LLC10U GTS Root R10"0  *H 0 w;ܿ>@<}2qۼj.K+΄ŗ^R#'ˤcי~ ^hZG M3NlK ߝd)%#=.` HMzY֯1.ml~&E=y(&ߑ"2cQr])h3:f&Wex'^I! lH<@~ ZV<їK9K?Un$qA=:Ȯz7B0@0U0U00U+&q+H'/Rf,q>0  *H  8 =_ 3+Ҏ At|7R2 a(D)5uw|ٽth1 )`sG|SJ'Kן6Κh o_\q}{/~6֗p \Vj3I8 }Y^jݡdDQ!f>G(%f5\ ,bZ)J|Zr9зwyi:7n8eF~`y_8[ȆmvInm_'v@X\,BB{4E>acPI4jnGAB)` 1c#ZH͊ϙٞ6hKqI6(:=Κ%qa+{%1_~jvr 6//pĒ@l%~{ ܲDhutZ| K b1QltI|< CNՓ46 d9Lȩb=@435,s'ru;"ޘhf[cGUQuH%geotrust_universal_ca:2.1.1~RHX.509l0h0P0  *H 0E1 0 UUS10U  GeoTrust Inc.10UGeoTrust Universal CA0 040304050000Z 290304050000Z0E1 0 UUS10U  GeoTrust Inc.10UGeoTrust Universal CA0"0  *H 0 U!P+[rXLaE=:m$q|_UʃY00H"7Jrf>+1הTB34EvO7zǜ.=X=h 5݀NS׵ D dLS hժrMmۜϴ\]Tzi u9<$|b}We %i(FЗ;7d= ( Vq#)AKR{q;ZXQLAAgr(`{SsrYzv\ U4[jTWm^/EX#n(cY0Pcp7$GZNirl~s,Oe@.<.(>i&3{c0a0U00Uڻ. &Qt\m؏z0U#0ڻ. &Qt\m؏z0U0  *H 1xǵ߸@qĨ5F…(X 9DUd\iК8<5Dyhğ=40FT+?51j#^Zvw/`DFjs1WE09O<m"p ])ˠ|~P՝XA8u<ٛJYS36-vH8 ƽ#AwoԅPQ>v'_nY +|k_HLGLE+ H @&Sas]M)7a9-g.v}KfE`i R^>+GDO?T 7M Y0,Ƚ߮J'ffhS\ie &4]Q{ש6Չ- ^ l|=|?ϵ]v߈EFjLHή~lOjzd>v.ŧH\?2o)Hs,3tubitak_kamu_sm_ssl_kok_sertifikasi_-_surum_1:2.1.1~R]X.509g0c0K0  *H  01 0 UTR10UGebze - Kocaeli1B0@U 9Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK1-0+U $Kamu Sertifikasyon Merkezi - Kamu SM1604U-TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 10 131125082555Z 431025082555Z01 0 UTR10UGebze - Kocaeli1B0@U 9Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK1-0+U $Kamu Sertifikasyon Merkezi - Kamu SM1604U-TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 10"0  *H 0 u03kә,7ٍ{nP>VB|&:d8$.7@%yu;lVDlLhU4ԃk7|WμS7*MO N!Wzg,aU-'8tNM"TP;QVÎV"3/ 6,m;Y#, @DЀ4FxFOB0@0Ue?NJ<TN12Vd굝fBrӱ1Cm#fn&- P϶ZDŸ"^Qcertigna_root_ca:2.17.0.202.233.27.137.241.85.3.13.163.230.65.109.196.227.166.225~RX.509_0[0CU Am0  *H  0Z1 0 UFR10U Dhimyotis10U 0002 4814630810003610U Certigna Root CA0 131001083227Z 331001083227Z0Z1 0 UFR10U Dhimyotis10U 0002 4814630810003610U Certigna Root CA0"0  *H 0 9eYd$|9& WجB[-EٳRr(ێN Mv")\ҳ>09tVoL m#z,,ܳ(LNIT@-lh##pmQiz"1‚UvP|%zɄ\ BN+炢$ː#fLbSZd{|Hj.Et*z]ѾD&2)l~! o?S},|X=77f(@Q-S$Xd0Ū @x|iѧhW:aDmYIY60A{v3"’npz1Huxp<<œ U:vY w2,:/l}m&UyR $-d%k!ijtMkzAH6-EA:Eh6LW# *(MtČY$Yt10mj_00U00U0UVnw$5\=(SUϡ_fF 3( $pdW]ČOLdF\YBћ~ݏ0;ju74(( O5`&j=Pӏ_3y|'4h1q83bqfyeՏ`-?B̪k2#,Aas"C_ĶWl X"6L:|φDtqs BYkBo_k[JrKt;}&ZG=Uװ&R(1@f$*!I\zU5~k'˒@]Zt>l Sʽr \8iּl[h%H1(alg9E$9B0@0U00U0Ul`> t+cY0  *H  @ؕe 9fS]x$DQ4 jDQ+z? ,R+C%?p3%mE(;'Ϫ)B;L34[Ak+e(êf{VgɜI`PFwy8/( ?w&t%1)A"pkqXl̛9Va \L`{w&zR,bpc9oyv),d^6n1@b46?5c5trustcor_rootcert_ca-2:2.8.37.161.223.202.51.203.89.2~RYX.50930/0%3Y0  *H  01 0 UPA10 U Panama10U Panama City1$0"U TrustCor Systems S. de R.L.1'0%U TrustCor Certificate Authority10U TrustCor RootCert CA-20 160204123223Z 341231172639Z01 0 UPA10 U Panama10U Panama City1$0"U TrustCor Systems S. de R.L.1'0%U TrustCor Certificate Authority10U TrustCor RootCert CA-20"0  *H 0  n*b$v8~ҫe ퟓLJȰ'+B = >AZuݍh2ih V>,%/dFT:T-1+*q1z$B ԒeVLlaZG#i:t< uNv*;ΰ~j('ȱ)Wndm.F^Qc:;qoY ]ILWBWvh w5%,D VDw]^k>2/W賎LK1 .>Z <48]+VjɶTS.x2g=t`pێ Xoq`RA rg1xc0a0U#0-( Ŀ/0U00U0U-( Ŀ/0  *H  %ƺkނ9=Dksޝ+O xϗy.Hz?S/jy#(7W5vO46gA PKR`Nk%*A6t99 ;'\`R((SfJ4f| goA kq/f3)vT'? 0"]ӿ%MK ʫ]9ׯQ;HjC%"mCĩKgaH``(w+77dY*FWK7|6g SkI wH%p0 %uZHN{an;Ĥt>]%&>U:b({07Ѻ8I07&!HܐU8͙7!O]"oj`Uef088%x^P`Rcme}t~d)r} IJ( tk=ݰH =.e+~}f|>͘0xogо_h,Yx+`c^P>4 h(\>G2?[ktrt㋠Jf/5 ӈa"դT%$WUn&@\QD xJUٷVv yiFh6)6 `b3ֺn֒4؁]\M;900U00RU K0I0GU 0?0=+1http://www.pkioverheid.nl/policies/root-policy-G20U0Uh26(4 |b0  *H  AJg*Pnس9; PQ-${; #`yNQy3HAC~G@zʪuf<'[nP>B)ƴVV #QEA$_{!9:Fl{(ǩUb4b5K:U%TWJx&-] yp59R]uUGueRJ %~Yl8~9a?r:ePW |Kqs*EQ̎GtѯNi&ªxW[Mʲ_I4&lHhsZ[m}׍! E?Qy4[7[kJ,W@Z6uD7Bp ^!hPEGxNe7BcW7E-{eU39(*!z$?Ț UbmPx efāw:X Rom1q ܹ}2`믊Sdigicert_trusted_root_g4:2.16.5.155.27.87.158.142.33.50.226.57.7.189.167.119.117.92~RQX.50900xW!29wu\0  *H  0b1 0 UUS10U  DigiCert Inc10U www.digicert.com1!0UDigiCert Trusted Root G40 130801120000Z 380115120000Z0b1 0 UUS10U  DigiCert Inc10U www.digicert.com1!0UDigiCert Trusted Root G40"0  *H 0 sh޻]J<0"0i3§%.!=Y)=Xvͮ{ 08VƗmy_pUA2s*n|!LԼu]xf:1D3@ZI橠gݤ'O9X$\Fdivv=Y]BvizHftKc:=E%D+~am3K}Ï!Ռp,A`cDvb~d3щίCw !T)%lRQGt&Auz_?ɼA[P1r" |Lu?c!_ QkoOE_ ~ &i/-٩B0@0U00U0Uq]dL.g?纘O0  *H  a}lđádhVwpJx\ _)V 6I]Dcଡ଼f# =ymkTY9"SD]Pz}b! sfѠ`_襴m5|Z֢8xM Gr 20Y.qVjoPmhz6z$ Pz#aB)͢ Aќd&LPAq=?Mp# J܁2  Ok t094!U2qI(PMMuACDO,6E#SlogUFL?n(Zy&ҤbJGJ gf~[A;;cTQ*xίI󒙶a҅POBl C:qM&5]b2Ҡ+TWJ'S趉m[h#QV𦀠Su)wތ!G=uf~+accvraiz1:2.8.94.195.183.166.67.127.164.224~RX.50900^÷C0  *H 0B10U ACCVRAIZ110U PKIACCV1 0 U ACCV1 0 UES0 110505093737Z 301231093737Z0B10U ACCVRAIZ110U PKIACCV1 0 U ACCV1 0 UES0"0  *H 0 aJ/ft_ٖfG3DߚT|i5o j؏H6\cZ\$7ף qr}MoڶEh=Dl>JH" 7L #VM@sW<: WCiWmyx嵴;ؼL(N%*"k 0(T f@-n"o{BP-#ТS qE&^ scZtp%ǗƊ3`7>>n)֡ш,oBACm;#6;%HɉteKh1@8X|uR.~ZRKPNb$B-)*Zqzdj'`c I2sCZau yfvOq% ZzK@O೬;p`JCn )q e00}+q0o0L+0@http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1.crt0+0http://ocsp.accv.es0U҇7'UV6̌?0U00U#0҇7'UV6̌?0sU j0f0bU 0X0"+0Autoridad de Certificacin Raz de la ACCV (Agencia de Tecnologa y Certificacin Electrnica, CIF Q4601156E). CPS en http://www.accv.es00+$http://www.accv.es/legislacion_c.htm0UUN0L0JHFDhttp://www.accv.es/fileadmin/Archivos/certificados/raizaccv1_der.crl0U0U0 accv@accv.es0  *H 1CgHD)L(fЏ5MaJMې.yiGپ۵)ڛٮ<0D|3b7' -' dD.ulM`@ICTc̺fODz[j+@'X,H|?)s6ކ>հ=* =f< Ք\5?ZC_̙M '[\3Um M/&['u bw)_Y~T0"qd8 #} 'A#+%UDM6~xVI3%քPBl *վpp`Da#$ZIѧ1,U |U%\@̕?U5Ǹ]zr_&G*m[Ew'2]*Řf/ 'װ}П XQ/8-֍VC,V4a7XYKU4F*;addtrust_external_root:2.1.1~RX.509:0600  *H 0o1 0 USE10U  AddTrust AB1&0$U AddTrust External TTP Network1"0 UAddTrust External CA Root0 000530104838Z 200530104838Z0o1 0 USE10U  AddTrust AB1&0$U AddTrust External TTP Network1"0 UAddTrust External CA Root0"0  *H 0 3-9N[l͵#ޛ3)L}JmPZ֗)ZIz.ʿ78->ApVO?2tȐT_x@<a^jPךNqqP` 8i&LO#:OΟioBkDǭmA_rZq7yeY7/ ’r8rE]*}D+C%aijX#3VuY)F +eBo{]S4Z'00Uz4&&T$T0 U0U00U#0z4&&T$Tsq0o1 0 USE10U  AddTrust AB1&0$U AddTrust External TTP Network1"0 UAddTrust External CA Root0  *H %#Aلy[#6ewAlG`Q2=&ǀZxy!L 5QҖ~Np9 Q-Fu$Bpg5J+zQBzc满+6 c~y{ @jݏBQEb!h C<|$ةs?V18q.ጘ1DLsIv`k.LZy .՞c&U؂Z{мǏNNidentrust_commercial_root_ca_1:2.16.10.1.66.128.0.0.1.69.35.200.68.181.0.0.0.2~R.(X.509d0`0H BE#D0  *H  0J1 0 UUS10U  IdenTrust1'0%UIdenTrust Commercial Root CA 10 140116181223Z 340116181223Z0J1 0 UUS10U  IdenTrust1'0%UIdenTrust Commercial Root CA 10"0  *H 0 P?=3FoQaOg]S (Cr]|B1Ptс |͛!C⬭^n Z2\ үqSNO20K^WSb+$bø)KIx<`"6¢,Tg5nsX尢&z6?@mZ4$t#]3]%0]GII؟[$bOOtrjzI̴FyژYu!eݐV`ĝR+# #v;3iKN~9Dp~Z屬5IIV=};MO7jb.5Qy,%8K\ 9Jt|Y?N \R=R꣬I4(A:_P`1sᅠ3 t glzUFN> 3d+c2^{xoxzrtUtxnpOh{1s==* AMeky3B0@0U0U00UD{B&TȎ6v0  *H   2K|Dva'(^T%)׮hX..~SR\ꈺPׂa 7x_s8͍>ϱ--쪚`-;Ä=Wu0`ӎTMf]t@~w]R%m:4Y{P5M1`H7uYf1G)v邮Q#ib rݣځ{n&wX AzsnmzxA~.fclT˒LS97# DMMd Z"&졈Dit 'P&zV,l$8KGYkSJ˩oDAᆧjL3Z5b\N,qX,{ !wO (ҹڥGi{p(,$LwH;u@ZyKϪL>Աb~O r~w[FG00U0info@izenpe.com01G0EU >IZENPE S.A. - CIF A01337260-RMerc.Vitoria-Gasteiz T1055 F62 S81C0AU :Avda del Mediterraneo Etorbidea 14 - 01010 Vitoria-Gasteiz0U00U0Ue%{䱱Utl0  *H  x JL:}H_ b6k}q?x'!GBJ|H:E| Qx}LBر`mzk )hIg0$z19[~.l 1N*?@:YYK<($۴u .sXB^0"7!lm&B GYp,5֯64;2xE,ڜ~@a>,K){.W+ޅi7˞xj1xz{<޾yΟpY5.*1EzA.4f{IdFyrPc[Hm9p5Ѫ|[R5:5#H5Fh1 X.PuZP-a?BsCՎl&Mdst_root_ca_x3:2.16.68.175.176.128.214.163.39.186.137.48.57.134.46.248.64.107~R/X.509N0J02D֣'09.@k0  *H 0?1$0"U Digital Signature Trust Co.10UDST Root CA X30 000930211219Z 210930140115Z0?1$0"U Digital Signature Trust Co.10UDST Root CA X30"0  *H 0 ߯PWbe,k0[}@3vI*?!IN>He!e*2w{s.z 2~0*8y 1Pe߷QcaKaRkK(H >. [*.p %tr{j40h{T ֮Z=d߿Apr&8U9C\@՚%:n>.\<փi*)W=]B0@0U00U0Uħ{,qKu`0  *H ,\(f7:?K ]YD> >Ktt~K D}jNݷ:pI˔:^HX_Z 񱭩Ynf3Y[sG+̙7HVK r2DSrmC&HRgXgvqx V9$1Z0GP dc`}=2e|WvŶ(9ewj w ؑ ) 558affirmtrust_premium_ecc:2.8.116.151.37.138.199.63.122.84~RX.50900t%?zT0 *H=0E1 0 UUS10U AffirmTrust1 0U AffirmTrust Premium ECC0 100129142024Z 401231142024Z0E1 0 UUS10U AffirmTrust1 0U AffirmTrust Premium ECC0v0*H=+"b 0^Сy5:U7Hellenic Academic and Research Institutions RootCA 20150 150707101121Z 400630101121Z01 0 UGR10 UAthens1D0BU ;Hellenic Academic and Research Institutions Cert. Authority1@0>U7Hellenic Academic and Research Institutions RootCA 20150"0  *H 0 ?<<]=6:y߬硈k13Ej4$( ^v* :[SM7%B"؎^:2>et/|'4)} eet s\@ԶLPhY'N5wՇ/n}$'&gcE :Ye9Xzr=^!,pROx<+h ~L\_57fJ΃W:Á˒6]ѣu'zHAE'NpGݵS屌H]1CzcK)0NNb^<Η%=~QQ}-&iYaj*6zP2/rGGf ?ůzzd ٮ:i(- hQwƤ71#G nxׂ IFEUek.r솈-_/&3B4 B0@0U00U0Uqgɽu]r8jq$T 0  *H  umTKXF4b6]^lȇ.F1|BUܡ a~XXsdrEܩ&?yS3VQ\؛ OKVSO `MBU|!!:whZ-E8*7y l'xgFtT iJMtwgūj#ԔD(bK)kp~$a{O2% E$+FjJ go4scF*r+~RT/>Uf_سY4YOlu˒͔8aKF\;J+yiIPMV]j6h*G%n(&V_o:x /O=@FLת{ m'õ+!S8;w70Oo@AzJ5A|UMJs :$َq{ڲ> ԫvߪ [ad@ SZjeboj,B2!;entrust.net_premium_2048_secure_server_ca:2.4.56.99.222.248~R1X.509.0*08c0  *H 010U  Entrust.net1@0>U 7www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)1%0#U (c) 1999 Entrust.net Limited1301U*Entrust.net Certification Authority (2048)0 991224175051Z 290724141512Z010U  Entrust.net1@0>U 7www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)1%0#U (c) 1999 Entrust.net Limited1301U*Entrust.net Certification Authority (2048)0"0  *H 0 MK d*+Kѿ JMvgx@sBhS+^v5|:[$}kK ܫ@$t) wU~jd[2Po=Ⱥf IvIg/Ɵq`-,ɐvf{xeS]<֜)/PH2UdLu߹U`0){Hi5?]zz"T&IhGӝBMo&!bfCpB0@0U0U00UU؉1$ p0  *H ;V0S|zyM3|Fcf$@!'rsO1 LhSƀ]=n ?/W,ɻDO}W/ Zn:֞ly^yL;e<=õý^[#h'\-o0ZѪ'yy3WBlVm ~ט!,s WddZ%"4,hmӊď#z jBg%E!|b>-e00 +7CA0 U0U00UO=c b\06U/0-0+)'%http://crl.xrampsecurity.com/XGCA.crl0 +70  *H 9gJ `[Mb$S'ׂdN.I+xg5H ?ɶUHY.[;}G7_Mv6סF ,m~?)ɒsd+,ҹ}o1 y\#M!My' dA1l$\q~j!ۦ@=i(<|@C}:4 ;L'|Bt| ɴ%Tdigicert_global_root_ca:2.16.8.59.224.86.144.66.70.177.161.117.106.201.89.145.199.74~RX.50900;VBFujYJ0  *H 0a1 0 UUS10U  DigiCert Inc10U www.digicert.com1 0UDigiCert Global Root CA0 061110000000Z 311110000000Z0a1 0 UUS10U  DigiCert Inc10U www.digicert.com1 0UDigiCert Global Root CA0"0  *H 0 ;rިӣWP wɢΖ[ N0SCiW"݇@ ;qFfv'{}H֯z 9eJ](tzxYhn\#2KNZmpw٨DX2uѢG'j3I`_:JL}>O_lv^K7"mjͳd[)2 BԫA2 ջX?I(p1L NJ=^ï'c0a0U0U00UP5VLf×=U0U#0P5VLf×=U0  *H ˜7H DOR߮yy$K+-X˸mzt)pLpc`ӣ[ ՎSc?۴fbfnA-wJX+Y@#-(E>yT&H7y`ެnD8/IE>*6S:P.WIla!x<,:k؉8lldw%W0$G|$0- EPȈƘ4_ <Օm4affirmtrust_premium:2.8.109.140.20.70.177.166.10.238~RX.509J0F0.mF 0  *H  0A1 0 UUS10U AffirmTrust10U AffirmTrust Premium0 100129141036Z 401231141036Z0A1 0 UUS10U AffirmTrust10U AffirmTrust Premium0"0  *H 0 ߩ_AQ" 8Hl}WօxwCHؾ#m6lX\TvጽZF-ղU!L'3CGF`;~8 ɚBlŔ~aĊ YY2w`iV9{,d6ٽH~"*BSxN-oD;tB.krꪨygB0@0Ug "&EeR'Ec0U00U0  *H  WMbN:2#ȳIZQv(yWFRDD UaAܵ$

޺4@آx?/ե٢^ArD3B-XVb?B \~.e&\SOx~ -İ`0b5z8^/po}~H^gQ%%kR)9sWޙ[J A5!}8T5mj:Ųл:zxF7/劄١h/$ Օ$|s-u9$N_C9UpHW1J0`#`#Gb4o{Hgr-f=)ම hCBnetlock_arany_=class_gold=_főtanúsítvány:2.6.73.65.44.228.0.16~R3X.50900IA,0  *H  01 0 UHU10U Budapest10U NetLock Kft.1705U .Tanúsítványkiadók (Certification Services)1503U ,NetLock Arany (Class Gold) Főtanúsítvány0 081211150821Z 281206150821Z01 0 UHU10U Budapest10U NetLock Kft.1705U .Tanúsítványkiadók (Certification Services)1503U ,NetLock Arany (Class Gold) Főtanúsítvány0"0  *H 0 $^sKmá㗐n0Ec%?>D &%Jc,S~\Fb"i:X00U00UA9$YREZ90dU#]0[A9$YREZ986041 0 UFR10U Dhimyotis10U Certigna H0U0 `HB0  *H qBaڕ־h6=~nL!m^Rc*o7;>"ka.r=0L@לу0{Y}ƹ )L3g:eӖvEp+#In<Ɵ5PjpDbˮhAWS u,lra T c.D&&U0;6*\,@#H!(-N+0[!4A{uX/F׻.@e-tugra_certification_authority:2.8.106.104.62.156.81.155.203.83~RX.509O0K03jh>QS0  *H  01 0 UTR10 U Ankara1@0>U 7E-Tuğra EBG Bilişim Teknolojileri ve Hizmetleri A.Ş.1&0$U E-Tugra Sertifikasyon Merkezi1(0&U E-Tugra Certification Authority0 130305120948Z 230303120948Z01 0 UTR10 U Ankara1@0>U 7E-Tuğra EBG Bilişim Teknolojileri ve Hizmetleri A.Ş.1&0$U E-Tugra Sertifikasyon Merkezi1(0&U E-Tugra Certification Authority0"0  *H 0 ?QbT^z ~|ԊkcC9Kd=.TR99KK݅v̿/L}=Gptm@љ unȩk1C+4菗kJ[tCӀ[^wDȡThޏ+[@ df yё(_R0sûJ%̤F"C,$,\]dÓ^(?'*PU9STb&}|ƞfBUGXf|.6P?C$ſGyyZl?YB>2IFK1Z˭tG鑷("]yOlᳮuIgםFN1v;$eZ\ZG\UU"q[[ ܠadh c ?Ӫ~QQ+US˷ffLuLpEc0a0U.۲IМTy\'*NNT0U00U#0.۲IМTy\'*NNT0U0  *H  7:MEEu$wReY>)]Ы| HxN(`0c|5avKizwE$И.NL\FJ3(8>YaOTa>iG5CZ=\BG;U c: o~SjDf#Q{[R78@aJ7fx.Q5SkhN<&p9?vg&S`;|CU(9LCґrYV?pvZCP0rMIƩgm:%XoSAH8Gh3Ǐt!zΖ)]#`O2ɿC. Ő;-&,LҊx mzz J*7__:8YKq pO2㰧WC˄4(m*kv~S-eJ;15nȋeL4zY2@'{η+@n mowo5P>B0@0U[MO:c W0U0U00  *H 8f.V!"8&NOyF!wů2 |f)}%RICL.+nzplBEU;. 4\lXJP_"ezP: {TP BUe䜿ąATo%x Ic{Zi!RY}5Rk%rS 2QvYl_uCÅL- wN(A'I@#D9ܡ"ֺ6affirmtrust_commercial:2.8.119.119.6.39.38.169.177.124~RZX.509P0L04ww'&|0  *H  0D1 0 UUS10U AffirmTrust10U AffirmTrust Commercial0 100129140606Z 301231140606Z0D1 0 UUS10U AffirmTrust10U AffirmTrust Commercial0"0  *H 0 Og+"sEDI,I%÷,OA2W[-_ ¯5y2-b7[J=q_B"Hd+m ϚP;G#[zz3? (ϔE@t 1+&jLW >Ezi}N c5v:7Gvs򗤵zyB+\&Of5DT02e<^PNz:n7$*W"( Iu(uy1B0@0US^ʯ?噕$0U00U0  *H  X Ժ_){hXIҴ7M'}F]CƆ.>s&}O*!ތӫk$ؤ\QcaBp}%}'o$KU;5;]0+gĎC\kbN3o P;.Df83VHm3 ?`7m~4~ rvrR5AE/sI!IGEGj4MYZNe):d#! ;|Issl.com_root_certification_authority_rsa:2.8.123.44.155.211.22.128.50.153~RGX.50900Š{,20  *H  0|1 0 UUS10 U Texas10U Houston10U SSL Corporation110/U (SSL.com Root Certification Authority RSA0 160212173939Z 410212173939Z0|1 0 UUS10 U Texas10U Houston10U SSL Corporation110/U (SSL.com Root Certification Authority RSA0"0  *H 0 ݣ+}*g.wJ]WGkwkv= fVVb" TeNAOFȸnb^i_*~lA?aHKNe6^g Uaz8oPbut<%nz"ݑ1+J7酤3+U4|JhDzӷʡ"$t=j)[_%4X#T8~=l@|\O(ˮq:3%5`=|ղuxr":,.,QF`h6k$܀*Am>ɁA^,B@o8'KN=G|εu\Q.+r(t䟭S557]!sޒ cjj>eU &%%im|Y_.ȼY<+ȓk'c&q4gNx 3pfvs " V N,lNϜ 3c0a0U z}RS8% Y0U00U#0 z}RS8% Y0U0  *H   )&parq$hX2p%+t=xj;@[U\f㱔 29ypD8C?G=F"h{,> !-3Ł1tuqž#Ekc %SPEDxd(݇peta2޻cL@Tn quz4r#'w\%@3˟ -…teRGI"k~c3#AZݎŹE?xۺ@qM?^~U !ޓ I60wu-e ڐR25|=+&l4pY2yy RH=lآD.NrXӉD׋n,[j_7 &nW NcaUh7tj۟"e'춟B`gµA Ӌa+D^)SHZ(X!ͰU'?SpW'@emsign_ecc_root_ca_-_g3:2.10.60.246.7.169.104.112.14.218.139.132~R ~X.509R0N0Ӡ <hpڋ0 *H=0k1 0 UIN10U  emSign PKI1%0#U eMudhra Technologies Limited1 0UemSign ECC Root CA - G30 180218183000Z 430218183000Z0k1 0 UIN10U  emSign PKI1%0#U eMudhra Technologies Limited1 0UemSign ECC Root CA - G30v0*H=+"b# -(9_IM%4Ytr/ATJ|[jܳu΋І#FՎ?~c_.O+2 d}ѣB0@0U|]̊.)HcB0U0U00 *H=i0f1adn/L zՁ G;|\G1UJvB{`ٍQU;{e GUw$~,3staat_der_nederlanden_root_ca_-_g3:2.4.0.152.162.57~RJX.509x0t0\90  *H  0Z1 0 UNL10U Staat der Nederlanden1+0)U "Staat der Nederlanden Root CA - G30 131114112842Z 281113230000Z0Z1 0 UNL10U Staat der Nederlanden1+0)U "Staat der Nederlanden Root CA - G30"0  *H 0 2Tp,\YlĤQ*J4_=Sho=ž̂g'hq:u"F[*ޜ:ƕg/I \4xPk2מ-u#[o >x/ 3H烚{CMU8JQYtӟKm$o`[VADj,X3X7c?@QO:z~BqnK0ߪWHj9iyx {!g'0YSdigicert_global_root_g3:2.16.5.85.86.188.242.94.164.53.53.195.164.15.213.171.69.114~RX.509C0?0ŠUV^55äիEr0 *H=0a1 0 UUS10U  DigiCert Inc10U www.digicert.com1 0UDigiCert Global Root G30 130801120000Z 380115120000Z0a1 0 UUS10U  DigiCert Inc10U www.digicert.com1 0UDigiCert Global Root G30v0*H=+"bݧٻ !s3]4ƛЕ a[QF~-c pτ.@?Am;ӤY6xClrޮkCg#>B0@0U00U0UHخ6Acib)K0 *H=h0e1l?J-9 s6'戍Pc2f̱ lk09f[dPܨIIȆN+T[|'fusertrust_ecc_certification_authority:2.16.92.139.153.197.90.148.197.210.113.86.222.205.137.128.204.38~RcpX.50900\ZqV͉&0 *H=01 0 UUS10U New Jersey10U Jersey City10U The USERTRUST Network1.0,U%USERTrust ECC Certification Authority0 100201000000Z 380118235959Z01 0 UUS10U New Jersey10U Jersey City10U The USERTRUST Network1.0,U%USERTrust ECC Certification Authority0v0*H=+"bTZh#z$oSZKնsqݜ a۠W]?!Ԋyࣃ~-a%c0pǡ3.\S_}24yyB0@0U: –vtIv5cc0U0U00 *H=h0e06gANc;Bd9y\{dB M1*aGRJKNpDnmX$VHĢFj:FѩMa]Wj$security_communication_root_ca:2.1.0~RAX.509^0Z0B0  *H 0P1 0 UJP10U SECOM Trust.net1'0%U Security Communication RootCA10 030930042049Z 230930042049Z0P1 0 UJP10U SECOM Trust.net1'0%U Security Communication RootCA10"0  *H 0 m|W mv/KdL)|*[d"o,:&iQ&jqƚ}|lƌggJ>q' K U;"Kq8yi~!ha6m'VWV2Ϥَ#׍%p8:;&CIYrL#0XNhVfA]ȳM*UF@=}7 d"daR}RK!ƱÕ`pM~ٽTyv$(s?0=0UsIh܅[e(/W3H0 U0U00  *H h@O]y`ƒ]jmmY ڄXcHO J?GkcGR?xMOϚ*A9Rٛ.hB$Bl:>HPI1_7;Ye2ɳ>:bXIbq2/ƉvC@g=T%:IVA5aɈ6"YJVsnM"Oz-E'0^%BQGl!tBS3W/Ϧp"l buypass_class_3_root_ca:2.1.2~RX.509]0Y0A0  *H  0N1 0 UNO10U Buypass AS-9831633271 0U Buypass Class 3 Root CA0 101026082858Z 401026082858Z0N1 0 UNO10U Buypass AS-9831633271 0U Buypass Class 3 Root CA0"0  *H 0  P^v12zvR6$GdyؐbL"/8=,xhQr3] \W*07w(MRq-p>Ċ( vU:>'7"O*`=9G]OCWG&[]7WE6{oc2j]l n9k1.9'8frdRǩ70\p3zKUKi(6\QsMk 49({k.O*k.-nR-=~Bk $̌4l#/!Uo y @ pzhH9X*X;UGgb~cF? T2^ bz'KZ7Z%wo P=ߌE0Vdf^|k:yI=≟0K$y}kEh+iIbmcb`XfvdL9R0KB0@0U00UGo/N%ST]e}sTZ)C'…{;`)iWZzC0b@dJבS n_D`4o}H_봐- բh /J1 J6)&ua~vcJz@e֏S,`a>C{9`Tj&hH34>C Q=WAnˠcm6h]pD 5 ]Q~/ELqټəRWF/PϽ5i=,>ûex҆yI; xMLނ)Z'^EНQhDЋj;MdQ檫Z1sb ǹZdigicert_assured_id_root_g3:2.16.11.161.90.250.29.223.160.181.73.68.175.205.36.160.108.236~RX.509J0F0͠ ZߠID$l0 *H=0e1 0 UUS10U  DigiCert Inc10U www.digicert.com1$0"UDigiCert Assured ID Root G30 130801120000Z 380115120000Z0e1 0 UUS10U  DigiCert Inc10U www.digicert.com1$0"UDigiCert Assured ID Root G30v0*H=+"b缬De͸?XWD- tbR_f~Ey S ]٩YZ*8JIƼ8_U~ n^E Yv֠$-6l)9B0@0U00U0UнQM7y΍*0 *H=g0d0%EkKutO#pur|ϑra^YV8X&6}490|6S0bc:ⶣ;4q^ݤn2!f/cjeEEchambers_of_commerce_root_-_2008:2.9.0.163.218.66.126.164.177.174.218~RX.509S0O07 B~0  *H 01 0 UEU1C0AU:Madrid (see current address at www.camerfirma.com/address)10U A8274328710U AC Camerfirma S.A.1)0'U Chambers of Commerce Root - 20080 080801122950Z 380731122950Z01 0 UEU1C0AU:Madrid (see current address at www.camerfirma.com/address)10U A8274328710U AC Camerfirma S.A.1)0'U Chambers of Commerce Root - 20080"0  *H 0 p7+ZJ:lx}5ս Dr>&Rc;(Xomd U""^bƶ)l}2jT2Y=`$ow> 5!kp.dS㇍ӽ♡ښ aPRv ϙ0=EXwQHMhu鼞Nq2Km` ̝uܿ&͏x9ys^%\wdAGrP vd49v vEĩ=j}e/X\|~ЛNZIߩf M7C "Q)<_23[0lj/G2ف䜽,أȥ!)4S[j2R"ܲ!B@) \кH7  y=iK4 }4Kd>#g - Ql^5[I > Oܕ725":N'2a GM`BGZPX銋]ݙJ6gH䃶7H:gj1q{gdJB{e.0j ͂١JKEmx.m61d *5 xUAG0a(z_88s;H*!̨5Ä>i:xV~[9, 2`* ~IJF/&<GsQpd/G0lD)7hf8{9.P^`'ArtJgTHdߌnqLإGtQ¢#@ sKsYF/qFm8yEH]9" XCqH.00U0U00UA:[;E˜X0U#0A:[;E˜X0FU ?0=0; `tY0.0,+ http://repository.swisssign.com/0  *H sƁ'-0AP,__baji tI]ARoXPV jƽ(iXܑ5:`Ei~xr*Ώpa 9)V2N=*rQ"Aqcb^Wu]yP1{p_حo`@K"=:zGy32inKqgr\"DŽ#?%eaZA"Z],[m x`VZ hiy~$Q^KS#Z6eA0Feձ[xuzmY*{ÇIsx=Q5t*~i*;%Z=raf Mt j UWJˮ[#1S8-j?j^Atn~)`?8W 0/ǥAڮelL ӹ0kNgbV>f6}>ԀNzjbr O#|l%c*gؚj *L `9b.nWthawte_primary_root_ca_-_g2:2.16.53.252.38.92.217.132.79.201.61.38.61.87.155.174.215.86~RTX.50900 5&\لO=&=WV0 *H=01 0 UUS10U  thawte, Inc.1806U /(c) 2007 thawte, Inc. - For authorized use only1$0"Uthawte Primary Root CA - G20 071105000000Z 380118235959Z01 0 UUS10U  thawte, Inc.1806U /(c) 2007 thawte, Inc. - For authorized use only1$0"Uthawte Primary Root CA - G20v0*H=+"b՜{RxߣO Q R-"B9Mz| sznpg5ԣ1Ƒ)B0@0U00U0U0kΊ 0 *H=i0f1WG[ ý5 1čSܝx3#SRZ1]ʮ)D '[hX?.rW.Zszafir_root_ca2:2.20.62.138.93.7.236.85.210.50.213.183.227.182.95.1.235.45.220.228.214.228~RPX.509v0r0Z>]U2շ_-0  *H  0Q1 0 UPL1(0&U Krajowa Izba Rozliczeniowa S.A.10U SZAFIR ROOT CA20 151019074330Z 351019074330Z0Q1 0 UPL1(0&U Krajowa Izba Rozliczeniowa S.A.10U SZAFIR ROOT CA20"0  *H 0 >PK@aʴ "{vw }&Q = X*Ѯ&SJ <Ҏ :ܱ8ú-_Jg=4G 6 [˩ 9`/u痜>~MoM/ j=n Mpr;'IrI; 糦+ @p _O&/#NuѴ`Lͮ ]{PaןQTɅ% 7 4(Ţʍ*0*zM#34. ?]τ_ s5ca_disig_root_r2:2.9.0.146.184.136.219.176.138.193.99~RX.509m0i0Q ۰c0  *H  0R1 0 USK10U Bratislava10U  Disig a.s.10UCA Disig Root R20 120719091530Z 420719091530Z0R1 0 USK10U Bratislava10U  Disig a.s.10UCA Disig Root R20"0  *H 0  օ]-ms5qU~FP|IxyX<|ؗx>kAA,E/dԫ]G=dh?4.Uo_LM!4VL <_l1fAecƀji0 'ߟs%lA84a-A~wNQT^Zh+W|%N$.V xM+en|bk*S s FB:@nƔn}o Ims{.o7vȴZvv,֜4ؖaD3ڹeԮ6 8 回fݙ։A))mk:u}qݝ`f`憹f@EgYπOe@x\GPț{D[Z:DfK2T|l=4~Iz(@7s eC |U3} BW|6{^yB0@0U00U0U NV.nB0  *H  &^pe3Ȃnٜ:zfx;i^/N(Ø*aL$}m漞'Lȩz6mrnƢmscnySػ5UũV;"^~R,g6LѳI;)a;+xl#oӲ^u1{FҼgbT cR.``V\B܃[d˵O|!bcq ɟDۨ'un>p\4nzZB`"Nv}%Gsåo ePSUaFaD!=t~$5="1/@()gOf$S)m-gluFJ $certsign_root_ca:2.6.32.6.5.22.112.2~RVX.509<080  p0  *H 0;1 0 URO10U certSIGN10U certSIGN ROOT CA0 060704172004Z 310704172004Z0;1 0 URO10U certSIGN10U certSIGN ROOT CA0"0  *H 0 3~%J۴(W"dӓԬa@j`WhTMjTߛ*]J(+yǭS$fɨZ龺F[s{,^b,e+~3W ]E85МJ\_ıۈ!0C搂U(I[ש8L[FAtЈ3|t܄Cu9%@(x,.9n/&e ^][кzK7[(Ҝs>2Q/ެ3OB0@0U00U0U%I|ֲB k0  *H >.5uerL,2NyG;[PI$kr ӡ@2tǠ ̣Hd璵ϯrCpÄ<~WSp‘1g]8^_sNgޞvb UiC9MZNIDTX_BXamazon_root_ca_3:2.19.6.108.159.213.116.151.54.102.63.59.11.154.217.232.158.118.3.242.74~R#X.50900[lt6f?; vJ0 *H=091 0 UUS10 U Amazon10UAmazon Root CA 30 150526000000Z 400526000000Z091 0 UUS10 U Amazon10UAmazon Root CA 30Y0*H=*H=B)A VR-.تms;;k9|3NhbEW}DX7gfޣB0@0U00U0U70pǜx0 *H=I0F!+harx`CŸ!񔜳*,:׌c$H0}h;=microsec_e-szigno_root_ca_2009:2.9.0.194.126.67.4.78.71.63.25~R2X.5090 0 ~CNG?0  *H  01 0 UHU10U Budapest10U Microsec Ltd.1'0%U Microsec e-Szigno Root CA 200910 *H  info@e-szigno.hu0 090616113018Z 291230113018Z01 0 UHU10U Budapest10U Microsec Ltd.1'0%U Microsec e-Szigno Root CA 200910 *H  info@e-szigno.hu0"0  *H 0 cچاBϑަ&cp3@}mnDBRut,,\q~/uط;ϙJFЃ}mJǥM3.9@u~|PAgaTlNɺ3U(,US{H7$YPc_Pn q~|Sn"_+|]LW#y$jQwv3CI 0~0U00U0UBC=˵H#z*4h0U#0BC=˵H#z*4h0U0info@e-szigno.hu0  *H  ^.̳|>= (ȿyC!]B0l? sj>.@~Tay.7#󌟾u۠T)15@vWY%b\~~!Vp4<a_:+E=Wkbp =6B2za=ȩɛXDo8xӣu6|muF5\=!Vɂ"-zTp}"ep8starfield_services_root_certificate_authority_-_g2:2.1.0~RMX.50900נ0  *H  01 0 UUS10UArizona10U Scottsdale1%0#U Starfield Technologies, Inc.1;09U2Starfield Services Root Certificate Authority - G20 090901000000Z 371231235959Z01 0 UUS10UArizona10U Scottsdale1%0#U Starfield Technologies, Inc.1;09U2Starfield Services Root Certificate Authority - G20"0  *H 0  :*N_S?ϟ m):}s u mE7ЏGݏAw'b37qw@}F#UNGF>{)&ab7(-*dpҭ)pyX.50900V"ԊM0  *H 0J1 0 UUS1 0U SecureTrust Corporation10USecure Global CA0 061107194228Z 291231195206Z0J1 0 UUS1 0U SecureTrust Corporation10USecure Global CA0"0  *H 0 5.جlUiqh$O!G`8^FS \ZE*1a)3L| 7~28Qhn|$ѮBȖPc.u_I.93d_g8zj Ű3ZXOƜ@Mʾi0|+Hиv> ҰجEFg`w~j<Rz=< v jr4|WNV>y);lmM5߮$yEވ]%|dg ٿZ X23wdv5l*s 2Sٳ,.v.~j s@? %|ѯ{ w~b9mecTŀK}G&]ш2DJ hT8S̤3dQY z^*b*Yb%J* GCp)zHMpMgQ zNAj^PTÉX-06r9~I)LyW۔SFaWV[aXo6P ج+64ebfՀ_ _- x h,o+JokgNiJR7ęт+;5uQQXB0@0Ut:0= ~Z40U00U0  *H  6Bd)7&,i,k_LYȹ̺.z-;pj%O)p Z|I*KrȢ1]@NʳT iZqx} ToLtdqA͑<29s*ix&1}0xwKg{pSʰ8M,9 ]kՈ,(tn}Ї&l=;.gXB,huϵ}$<]ܥD{>2ǷBve8+85Q!o.4@+g mJA0#Z2U#n&Frki" bv<--b7Rr'17cY v~26Rv_vIIe +vvVZdigicert_assured_id_root_g2:2.16.11.147.28.58.214.57.103.234.103.35.191.195.175.154.244.75~RX.50900~ :9gg#ïK0  *H  0e1 0 UUS10U  DigiCert Inc10U www.digicert.com1$0"UDigiCert Assured ID Root G20 130801120000Z 380115120000Z0e1 0 UUS10U  DigiCert Inc10U www.digicert.com1$0"UDigiCert Assured ID Root G20"0  *H 0 (/R?6rI4j1TTAGߖԯ- u}$" + 3MA Mn"U1eblP? ϷmLR|l8+wp6y܂p tpUihݶyp)Ua@oѾӈ*rZVq;? (ٙӏ`򒡱0æ.b3wDZ ^V(@q7G*h"bG+Kɭ>LېP? 0 =*Y#,EnCym \H#G\^nhEц[)%qRKQ1NM۬jռ9Tqzz}فY&e47)pM8.W(!_"00U0U00+U$0"20061127202342Z20261127205342Z0U#0hgSdžfKCm0UhgSdžfKCm0 *H}A0V7.1:4.00  *H 0 *c  _{rNԱЖTZ, m;R*Ԅc&Pl_t0:P`"DqG雚`p~_MIR{Tڿk؞CD:BsR)d MѼ*}0%4[xV6&gIzJP\J.__'D(?{*ȯS/f9MZs%fwYJ%T&0pF*)ן4_C6f<:>;efz=qQ<0._=ws]l#V+&? y6=5i̝d3n^J]n5#^ߛ_=v>x BgkoD00U_[U0U#0_[Ulj0h1 0 UUS1%0#U Starfield Technologies, Inc.1200U )Starfield Class 2 Certification Authority0 U00  *H ?UiYڛOWy */^j؃I5>wAXbX g?!fTr=L@؁wz4@,*Mb].% h(YMȲe-zSmW A htV]zy-qC̍ )U"X#C)[G݌Aje!A!}4֭=9ͽ>upY"^*ץ m@Fyb/"t-telesec_globalroot_class_3:2.1.1~R\X.509000  *H  01 0 UDE1+0)U "T-Systems Enterprise Services GmbH10U T-Systems Trust Center1%0#U T-TeleSec GlobalRoot Class 30 081001102956Z 331001235959Z01 0 UDE1+0)U "T-Systems Enterprise Services GmbH10U T-Systems Trust Center1%0#U T-TeleSec GlobalRoot Class 30"0  *H 0 ub"o$zv}$ոBxV^TM pRؓFqAJ+*,UH98\K&0n?AG5T>=Ij=o"G1" >Zk Tz}CN{ע=&4-j0]N_ ~w=F;K:@cZ3tCliR6)oU\GIG N" Ia.rnYW:u2N_(bMś`ۧ~TT- ,TJTQgn~o?-Y)fː9t'B0@0U00U0U L0XH3RKfR0  *H  xz;Z,rscqxY0 Zmj怟 hGkj߶w2r ,]Ҍuve y1#cx h&yKak/S`XQ[bYcޚ&']U7tPY.D,%L2wK] CԻ&Ep^ 7SF{'FB(&n٥:A`PmWx*e?l:'6c庴|Nɱt_8Q,ԩ-'ENq XFiS˳kAA~}L|ryzY^Jsy|̹ t\og:b=)gXS0 !џe\\w)hk@ҨK8(Tu>d$NG5e Vdl"%IX~]_! ' `lFtaiwan_grca:2.16.31.157.89.90.215.47.194.6.68.165.128.8.105.227.94.246~RQX.509v0r0ZYZ/Di^0  *H 0?1 0 UTW100.U 'Government Root Certification Authority0 021205132333Z 321205132333Z0?1 0 UTW100.U 'Government Root Certification Authority0"0  *H 0 %̢u{[YцTF|LG6W!$?H+.,ѿSΧ !vwsOFI7YI]jVp"MA2Ü?pS݁cxSnj$rTҲyֵpb.NO嚿̇m&W?SlL~S lg­̀vjפxGΆ114(pLIǯ,mfd~ j;@gKeS_D /'F} uTI;z]*uB{ޥ(8h5&z;EѻCxnoBTj R^jrj`qgMB@gF8/G?q!a-m|-Q%cWk#m?= k'컑 N A;@:]fR\3¦UnLK8M^f`RZz<#y|J!j0h0U)`;<2b%;0 U009g*10/0-0 +0g*"(6ܞ21:Qe0  *H @J&^0OtvX3xztNR tbhxL,#.j$hӊ؜ 8~W8O^ ;uˤgH} jix!§#vV *fdI=BROGAv5v6E2F]$HWGUzAD$kړ`^J HfyT,/K][`Rc*;@e?K~z5).z`"}'N-t<3ӿE#na$] >g0m'KhnK*\4vg&?2JŁ1V- wҿXbKu~mSN^U$8c;X߄_/ U[8.?rH˻)8U0#N]H  TtQ,j F`ۜYPu#isGq'E \2%,|&certum_trusted_network_ca:2.3.4.68.192~R1X.50900D0  *H 0~1 0 UPL1"0 U Unizeto Technologies S.A.1'0%U Certum Certification Authority1"0 UCertum Trusted Network CA0 081022120737Z 291231120737Z0~1 0 UPL1"0 U Unizeto Technologies S.A.1'0%U Certum Certification Authority1"0 UCertum Trusted Network CA0"0  *H 0 }rkNn@m'][-ZQ_2an0iW9]jdyY<1J8|K( _;MsOVZh#Y' 'nr0rtu*{TC9U(8I3v9EҤQ|-_-Ѻ̑BwL%ɐ8oY>`N(IyKH/r94r@1-]P^i3(PTTPEIB0@0U00Uv$7Fu0U0  *H "=bH^rxD #H*ĹU' c 7yA["A\pw#lV/i ٪!P7Ъ-EB t/ؙ'G Fw1Ĝ(t43& t>v'fA[ʘVsp1A/-ZvoNN?["fXJĴ**-9THv'-9ҫ۟ '5)@UFַ4~98QO,:entrust_root_certification_authority_-_g2:2.4.74.83.140.40~RX.509B0>0&JS(0  *H  01 0 UUS10U  Entrust, Inc.1(0&U See www.entrust.net/legal-terms1907U 0(c) 2009 Entrust, Inc. - for authorized use only1200U)Entrust Root Certification Authority - G20 090707172554Z 301207175554Z01 0 UUS10U  Entrust, Inc.1(0&U See www.entrust.net/legal-terms1907U 0(c) 2009 Entrust, Inc. - for authorized use only1200U)Entrust Root Certification Authority - G20"0  *H 0 r۞ k0v2AaNXrysa 'س_ENrN2rjE皿W'h/ jk^ewԅp!2狢Ն9GI;T}Wny: UP2\/xV”Z'$Л%EŌzk* nH;oBS_>,iN2Lbw4Q~S3"mp<g􍥯bLMXd4c$qB0@0U0U00Ujr&z};iQlf0  *H  yƶy?"Ӈ`jk.YsC9+Op/ T3 ! 0x܇CcǍ;X=z,N !C7y2,LC)0Ӭ!3vT"*M .phS\ӝD DfFm%]1QTFMۙ\xy]>LUop0BF“}c{?q|蘮x4% k;AHzswiǶ\X(+l^m{%7hB]Pu6i{ni HY{`zdiCLlS-^r>TȽgLEӹ0#LٙZW̻S,Ğ4L$x_|Jt%>K,V8\yt-a ~~OY_-CRF fGywT[$7EZNDHذ IIeqnE>l gZɤOssl.com_ev_root_certification_authority_rsa_r2:2.8.86.182.41.205.52.188.120.246~REX.50900ӠV)4x0  *H  01 0 UUS10 U Texas10U Houston10U SSL Corporation1705U .SSL.com EV Root Certification Authority RSA R20 170531181437Z 420530181437Z01 0 UUS10 U Texas10U Houston10U SSL Corporation1705U .SSL.com EV Root Certification Authority RSA R20"0  *H 0 6e@M״Fk3GL}}-=xᆥٺ WhW>A(A$r^p#˟9Nƒm&{' 7qqcgӅUIZo2;A˫m{ Lr+&iꅷ K@P."7Mk!"FDia5oa꺸`MfWX͇iGfvw}4$ת!,xdxU˄2xaS wL=b8fYvZS+hD{y3Jv[{^b ֆcI(4ؤUnޙU;#")f& PwJ `pA^ԮP9"&˲;stUGy90D%BSě<Jg0,Wf\Vwc0a0U00U#0`4%sFi0U`4%sFi0U0  *H  V IđfQuP,zӊ>)cشT /Jm^WUG6juG%ch-U򍰤ϼ<^x祠 pŷr" 3%Fd&>.cڛ= }QP چ뷯h9&hzg=bg%rK+<@8ThƏQ<盝 rĩxCe9(Âe_et< 5.{]m:V;/"FF<LD^.\f &)Ras lj?@Y_Lam;̢ "ggD.ҊAf Z}#ޛ.?ߒ;eǠlbÐ%4owv֯tbHwiaޕtTпCuSz . 6"KP% ɃN5Mf,D˕' 0qn -;qT`KfO WEcvquovadis_root_ca_2:2.2.5.9~R9X.50900 0  *H 0E1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 20 061124182700Z 311124182333Z0E1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 20"0  *H 0 K -)ȮL)D/2F&~:\`*:t30}aTҢ~ko -> ƳF]IZ3$?[+z5gfPm(`+`Ǔ6ĜwvjzEV7Hqc"eKߏZ _^k Ds\sk~\+L9Ვ-BճCl?uÑՊАmމeq [y|%+Q:S HɴvRrc6+ tVfu%ga`>Ѩѱ#TDvmA"S5ܡw*1- c3,ꗳҢla7s3ח#}LѺg_'{EJLҫ QPj1 d\: ?ng=:}[^a܋3wD25 b؞'G;![00U00 U0UbHL3%Fєk0nU#g0ebHL3%FєkIG0E1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 2 0  *H > M[q]//gE6& Gd]rF'Ux}v4 _M.gDwP| rSvAG &U"`e|_&2P7qU!xy-&fV0w7x3RX?aj~JYcʍVէ/V9 ,}MzclD8;@nV oX.E?,:"܄"o9<úUzm$l[owh 5d#UMBuYVIy|j4ж&b8 .Ӑ*~\8?^5bnWPț探fya<Ṃ\]Hnh>H7]^'b\!ݺBqS1}brᣓ̊&Z 8 x:LF,T"PiCmߑT* %&ReՂ1.Zoiste_wisekey_global_root_gc_ca:2.16.33.42.86.12.174.218.12.171.64.69.191.43.162.45.58.234~R7X.509m0i0!*V @E+-:0 *H=0m1 0 UCH10U WISeKey1"0 U OISTE Foundation Endorsed1(0&UOISTE WISeKey Global Root GC CA0 170509094834Z 420509095833Z0m1 0 UCH10U WISeKey1"0 U OISTE Foundation Endorsed1(0&UOISTE WISeKey Global Root GC CA0v0*H=+"bLPr񺳉yJkT$Q $ "j' 1tn%ٌuКK!~c9Աx_P57jM7[1T0R0U0U00UHÞ`:ʉӭPf0 +70 *H=h0e0&i[ ycRNMJs%LZmI)`x~Hd14 2I]lq?6:vS¢{OXKS97globalsign_root_ca_-_r3:2.11.4.0.0.0.0.1.33.88.83.8.162~R!X.509c0_0G !XS0  *H  0L1 0U GlobalSign Root CA - R310U  GlobalSign10U GlobalSign0 090318100000Z 290318100000Z0L1 0U GlobalSign Root CA - R310U  GlobalSign10U GlobalSign0"0  *H 0 %vyx"(vŭrFCDz_$.K`FR Gpld,= +׶y;wIjb/^h߉'8>&Y sް&[`I(i;(坊aW7tt:r/.л=3+S:sA :O.2`W˹hh8&`uw I@H1a^wdz_b lTin郓qviB0@0U0U00UK.E$MPc0  *H  K@P TEI A(3kt- sgJD{xnlo)39EÎWlS-$lcShgV>5!hS̐]FzX(/7ADmS(~g׊L'Lssvz- ,V/RVX0EW;+oGE7\v%PTDv#2ë}b[)5Cd`]2;M@j#k8 01lRe"XB0@0U0U00Uj8[&ދZOzT50  *H XK/g!0uh*ML  Kd(uEer!"A8Tm|X""t-telesec_globalroot_class_2:2.1.1~R[X.509000  *H  01 0 UDE1+0)U "T-Systems Enterprise Services GmbH10U T-Systems Trust Center1%0#U T-TeleSec GlobalRoot Class 20 081001104014Z 331001235959Z01 0 UDE1+0)U "T-Systems Enterprise Services GmbH10U T-Systems Trust Center1%0#U T-TeleSec GlobalRoot Class 20"0  *H 0 __s\GhU`Y4 Hi !\e_|{|-ֺfT#͹I?On7H(8žhp9MǘPD#}9GRb^1BvzlqOx`˾~3n4!r?0[Mj[CDWŘ( ŷS&QC Xv|rpo_5Ʋo4|HOZ9؝x>^DB0@0U00U0UY 6y"kaҸ,˂J0  *H  1a tr6mM"Vͻ꫑8|M󶣍D!>ba#30zk6b{#Xe+%S7bS_b)'q:"~op J4z[u|z)G~@1w@;QGz.GޝfЋTfU|)o/>xbn_xctXH 9yZ zW"-<%&=C|ȫd0.<3vͭO'nTdigicert_global_root_g2:2.16.3.58.241.230.167.17.169.160.187.40.100.177.29.9.250.229~RX.50900v:(d 0  *H  0a1 0 UUS10U  DigiCert Inc10U www.digicert.com1 0UDigiCert Global Root G20 130801120000Z 380115120000Z0a1 0 UUS10U  DigiCert Inc10U www.digicert.com1 0UDigiCert Global Root G20"0  *H 0 74{kɲhJuF! T:1⍄ږ>5_pPpGAWNĕ/%u򱎙oAq*O UEDꇕ2SF,"K EޤX}RYC&o 7}w_v<]V[fn572quovadis_root_ca_3:2.2.5.198~R<X.509000  *H 0E1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 30 061124191123Z 311124190644Z0E1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 30"0  *H 0 WBTMǟC9Je4 Ytϒ@K1h {N]⊷?aep gYq)vVyE+zT)5hO.7rXWT[,]n<>\3o6NJ 4L!PU뱻EdUvˡ?Bi/hCV*7aNe7KȜ {=*e:x܀ә:kZkΜ¾K/h;o})%C/_&M^nn3i;SUQx@ɢ{RBRZYV? )Oޕߋ3﵁"S|xRnw`*v X0scjINJģ"0 h"s U!X:*sl d &p, mhQ?2\k_@"ȴdOֺ}H>i ׻qs?;%K@00U00U 00 +X00+0Any use of this Certificate constitutes acceptance of the QuoVadis Root CA 3 Certificate Policy / Certification Practice Statement.0-+!http://www.quovadisglobal.com/cps0 U0UC>/g25\۸0nU#g0eC>/g25\۸СIG0E1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 30  *H O,LofU#4)[!`;]`S'"*翠r$j1z'ۄ'wZ8׿]wkm$/Kzlㄟ[fv8 Bi+n<'D ZUY RHŮ/2P5.#Q8fVvQR MIQ6=K Lrڨ]Ms#tb" YjyzJ$RtNn D#7_|+.~ݙ'o-]{ K&npBn31{i=kN"mXMA+O^ElӠUw0ub9lWLґ u(Cw;ai(B^p*!؏#[-t@c sibGt+}AFš"_N(*(`\#Z'^ 7;i6멞a2ڎ t>{ $wG;4%a3Yn7W zverisign_class_3_public_primary_certification_authority_-_g5:2.16.24.218.209.158.38.125.232.187.74.33.88.205.204.107.59.74~RghX.50900ў&}J!Xk;J0  *H 01 0 UUS10U VeriSign, Inc.10U VeriSign Trust Network1:08U 1(c) 2006 VeriSign, Inc. - For authorized use only1E0CUmn< n@A d8ɔ) o %ۤDAziJXO`~j %9e*^-*m( &oB2ΝQ^([}E@rk35Hq'e_ vDz\]23T?h\BJ8T_,֨cjKisrg_root_x1:2.17.0.130.16.207.176.210.64.227.89.68.99.224.187.99.130.139.0~R0X.509o0k0Sϰ@YDcc0  *H  0O1 0 UUS1)0'U  Internet Security Research Group10U ISRG Root X10 150604110438Z 350604110438Z0O1 0 UUS1)0'U  Internet Security Research Group10U ISRG Root X10"0  *H 0 $s7+W(ܷ8nY>&$ZL@F:Qn;}rxY>Qx />{JKsP|Ctt0[q600\H;}`)̺A¶|;FH*vvj=8d+ (B"']ypNً:'Qnd3COB0@0U0U00UyY{sXn0  *H  UXP i ')au\ni/VKsY!~Lq`9 !VPYY鑐bEf|o;֮'Ȯ}~"+"4[XT&̊3L-tbdj"<{QgFQˆT?3~lQ5frg!fԛxP:ܼL5WZ=,T:ML\ ="4~;hfDNFS3`S7sC2S۪tNik` 2̓;Qxg=V i%&k3mnGsC~f)|2cU T0}7]:l5\AکI ؀ bf%̈́?9L|k^̸g[L[s#;-5Ut IIX6Q&}MC&пA_@DDWPWT>tc/Pe XB.CL%GY&FJP޾xgWcb_U.\(%9+L? R/B0@0USyZ+JT؛f0U0U00  *H  \| }Ae sRϙCUWR<'(:7vSPkN!OUbiؼĪ KU* mUx)_0\K$U$n^*+ M8C `^jYm?Eds(.$NXE"/Eaovr6 qolqbЃr g Lr4߼qߪql<]eڽWCkMfQϙqI5q'a&og%!] .h;gԘQtx\yJ`.@L7*,b]6[%%w?=?̅o-߹5gJ(#\'kO.YRAGdAU|Yb¹Z(t 6t2( LiGF/cDpč-3{p>@(Ȑ]"RX1CƎx k/j+ň~ĻE'o7X&-r6N?e*n] :-؎_=\e8E``tArbbo_BQe#jxMZ@^s wyg ݠXD{ >b(_ASX~8tit00UİґLqa=ݨj0U#0İґLqa=ݨjge0c1 0 UUS1!0U The Go Daddy Group, Inc.110/U (Go Daddy Class 2 Certification Authority0 U00  *H 2K>ơw3\= ni04cr8(1zT1Xb۔EsE$Ղ#yiML3#An 剞;p~& T%ns! l l a+r9 ͗nN&s+L&qatJWuH.Qia@LĬC Օb ψ2 +E (*ZW7۽4affirmtrust_networking:2.8.124.79.4.57.28.212.153.45~R8X.509P0L04|O9ԙ-0  *H 0D1 0 UUS10U AffirmTrust10U AffirmTrust Networking0 100129140824Z 301231140824Z0D1 0 UUS10U AffirmTrust10U AffirmTrust Networking0"0  *H 0 3.klkaRyL唀UdDegd\7I/-`0N̄,63w5D5=6zGji:yZq#kt _-S+ܻv>L#j".me˾$fU$K@D…?=#Sܿeo@q}ξ^'#&)A+!]C) +*><: řxA3v/]夘P 8hвz1~X'C3ӧ\uA>%ۏ.{ _c7uiL(&%pEUs^7!l5Z#xB(XfFmpKT]JEZ Q/G9ϺB@H! kѾFI "N8<0p,uŌQ;=d&a}e!Ъr^SrA[!E7 9]#m B8sڇ[<Ӟ>;}tyfA\`W. ĺϧ@ûZ UK;8vQcVB0@0U00U0U$'0n;0  *H  w,nVNG vdžӶxi I3Ŭˆ}5`ɿө%Zn}}l~X)sHn)d_QƛMU%OSuǦAAҿE3 j%_9Xw;,L^>aP$)cLpGC\]F oYݟr[+ߌ[ Fl LTBtndة_U\jvsgM\is68II釸?OzZyԓhRlpUr24+I b:zgcmvV.f[ɤ'/&*@6>^PYF) D\ᕶiohGLm@xoPDP?fCVJ -zKͥN^&%Y#~~!W'WLF LMO:yCy֭oz'$?ٽ_PI..go_daddy_root_certificate_authority_-_g2:2.1.0~R$X.509000  *H  01 0 UUS10UArizona10U Scottsdale10U GoDaddy.com, Inc.110/U(Go Daddy Root Certificate Authority - G20 090901000000Z 371231235959Z01 0 UUS10UArizona10U Scottsdale10U GoDaddy.com, Inc.110/U(Go Daddy Root Certificate Authority - G20"0  *H 0 qbY4IX" C;I'Np2>NO/Y0"Vku9Q{5tN?j öè;F|2 f"ȍim6Ӳ`8F >]||+SbiQ%aD,C#߬:)]0 9K]2bC%4V';p*?n蜈}Sm`,X_F< I1\iFGB0@0U00U0U:g(An 0  *H  ]yYga~;1u- Oe/Zts8B{u׮S~Fї.+'Z7l=$Oy5_뀃-ؐs@r%잫hWƏ: D728d,~h"8-zTi_3z={ _9uv3,/LOěJT}~^C MkezD\Jsecuretrust_ca:2.16.12.240.142.92.8.22.165.173.66.127.240.235.39.24.89.208~R@X.50900 \B'Y0  *H 0H1 0 UUS1 0U SecureTrust Corporation10USecureTrust CA0 061107193118Z 291231194055Z0H1 0 UUS1 0U SecureTrust Corporation10USecureTrust CA0"0  *H 0 OxXA @$93fჯb\$[aAnާHƟA>)Ԏm gWf%H ]OF\^m̆o1BlR>h4߻V&oޠ‘dKDcfvq6hzw/zrkY?rD$sW/B&tRKS|G 6f4WfpTǓ.(Y00 +7CA0 U0U00UB2]KzL@ZC04U-0+0)'%#http://crl.securetrust.com/STCA.crl0 +70  *H 0OJX:Rr[eQ;wӟ\Ee{ [pPIǍAs~ #!`Zrzo]iBqȷ&.jqܸߙ|!T+XW)&.iϙ 㧟+64{$xL&dR6_`gٜt g#鮋07~2-D00l4@KfFT2 c&0k܋GbТgx)coL7(K,¸h1Mgts_root_r4:2.16.110.71.169.200.139.148.182.232.187.59.42.216.162.178.193.153~R(hX.5090 0nGȋ;*آ0 *H=0G1 0 UUS1"0 U Google Trust Services LLC10U GTS Root R40 160622000000Z 360622000000Z0G1 0 UUS1"0 U Google Trust Services LLC10U GTS Root R40v0*H=+"btsh`C5Ł0{KIaFka5@s0Z<|@v;ƸG*璑jsr9)_^Xee܋sȌj/īB0@0U0U00ULtI6>j0 *H=g0d0jPRtpܞPt!z!On"5a-7m۲}4`,4o 0q` jhd|^y-#]qMȔu4globalsign_root_ca:2.11.4.0.0.0.0.1.21.75.90.195.148~RX.509y0u0] KZÔ0  *H 0W1 0 UBE10U GlobalSign nv-sa10U Root CA10UGlobalSign Root CA0 980901120000Z 280128120000Z0W1 0 UBE10U GlobalSign nv-sa10U Root CA10UGlobalSign Root CA0"0  *H 0 晍ΣO~%kH*cgfH+)e-˫Lp= 0OԌPP.R}m50^CsAj㲉:V98oàcU9C8/&;PV 8 pQ_A]ud U0솏 ,cF߼i.Hd) i,i$xqbȗ]Gn*V1g+l]F QpV=aj\=AcRSS+_Aہo fUH)&i>actalis_authentication_root_ca:2.8.87.10.17.151.66.196.227.204~RX.50900W B0  *H  0k1 0 UIT10 U Milan1#0!U Actalis S.p.A./033585209671'0%U Actalis Authentication Root CA0 110922112202Z 300922112202Z0k1 0 UIT10 U Milan1#0!U Actalis S.p.A./033585209671'0%U Actalis Authentication Root CA0"0  *H 0 ĥ),ŰPoQ; ZH8 @?h-Vm_lᬼ ±QiMZo/D~XEG'!A-/L("VeTC)9Fx0#}W]҃kHLīZ[:ɧ"?'3[ ]7lzG"D5.*}f _aQ"UF=5bۯ[̉0&G9ӿOP:v$O!G hzSTyۜ.>m%BaJ英e9<ZY{NOYE ^(_?EϯowZoJJD!1EaPN5|Lȵ ztU hbdmÔW ߋ~Sŀ4P(XPq0xc+9^ {V;] L+ٲKc0a0UR؈:ȟxf{8p60U00U#0R؈:ȟxf{8p60U0  *H   {r`ILXdHX O551ȁ>j;2=.c.#fgo9`4%uRާRqj<)e?Z!qM8?0Mφeї+rBhNZk^H)\>6bbpxH[ڼ8gU>^W@LOc B €sO.@{Hz(&Xts"m9}*,_N,vM8OH`y&КpIz -}Ǖqڣ|t"S@Lv25v?nn&,+hȺ+lts%L~ P%6f7ѻTd,'K~e-NA!Aw9fov~kT/+'%7xLQjX]jH\PF=OYTG>4{xmV.sf(x/..|l Gac_raiz_fnmt-rcm:2.15.93.147.141.48.103.54.200.6.29.26.199.84.132.105.7~R7X.50900k]0g6Ti0  *H  0;1 0 UES10U FNMT-RCM10U AC RAIZ FNMT-RCM0 081029155956Z 300101000000Z0;1 0 UES10U FNMT-RCM10U AC RAIZ FNMT-RCM0"0  *H 0 qzLnm}, #@Vj{%]Y6.Q$X7J9W,"XwG>tC4M8vgo03Xq\knP~lJI )e !gB_O0>Eh@@wz e[<ٚR۵F=vLM;߾#5E\%^"9*.ljJ/4&]f!NoLQPw9 ,I2yZYeG5^5 ƛJ9h"U+NBqMχjq}Ӵq{NGv(nSm_H6.IŒX-p◒0U'K퐭c%Y-5ʗ3ǝ^J&c5-ve,W}ׁ]IzWSFuyBhq`9iV@ǭR oG('] lVF00U00U0U}wd̿`m0>U 70503U 0+0)+http://www.cert.fnmt.es/dpcs/0  *H  J#NÜQe" s)kM cg_bbnLuE|e 7Ϭύopʸv7v[nb2" :jf -StWeղ#;f#'g wCeQQX9Gv;_3eᣤӼ9z4A2*+ i8͊. p&+ ֗n:! @f~ E9]ט}gsÚ*:4R@~EiWP|OnC;#MF;jʺ#)ZXZ-m&n42 e;7"r3] v<#(Yd_r~ ͉gMbz?N9z(AHQyfj1B@j:rj7UiaCt $FES[yGLbFɶ%@uJ`/0wT⸄XQ:OH[comodo_ecc_certification_authority:2.16.31.71.175.170.98.0.112.80.84.76.1.158.155.99.153.42~RvX.50900GbpPTLc*0 *H=01 0 UGB10UGreater Manchester10USalford10U COMODO CA Limited1+0)U"COMODO ECC Certification Authority0 080306000000Z 380118235959Z01 0 UGB10UGreater Manchester10USalford10U COMODO CA Limited1+0)U"COMODO ECC Certification Authority0v0*H=+"bG{/uɂuԫb>R A $<=ҍ uw*`K6# qJ(Pn?l// Y[[ 3=j,B0@0UuqHAGߔHwy0U0U00 *H=h0e1[zx rF }s&` Ι\0105F=0  *H 01 0 UGB10UGreater Manchester10USalford10U COMODO CA Limited1'0%UCOMODO Certification Authority0 061201000000Z 291231235959Z01 0 UGB10UGreater Manchester10USalford10U COMODO CA Limited1'0%UCOMODO Certification Authority0"0  *H 0 @rQTө]; /?)P;WtQqBMAjwDYfP^,pD7Bi<0qR!Mغ9|$|C[4b&F?Wz r0jfFphHw޵gmA92b=n7/Ӣ&ƸUC#>$9jGԡ% ?Q ڬ8UP$eF4O-!ҎaqsGMNH&00U XL7@0!G6ZV0U0U00IUB0@0><:8http://crl.comodoca.com/COMODOCertificationAuthority.crl0  *H >9xrIӇC?ɪU|!Re l>s.Nqo8a / /AHE޺vk3-1FLψ3V$&88*k?GL ?ܱSY)E(Kt{WJ&^nt O5[2 zw5ZWtVD0\N+&tz voMA-_B{Xa4*."DL[J|s'.N$wj][EáoV&I.A"O`cy<m+KNv;_;F@R:jw5ڍ^j1<(kTƪ[ע,̢Y7kmV6X> &8O]"ЗU+(:{!QR8fyVЃ GQ[PjH]>el;2V9z[/`NXL?+sٔm'fp@ BO a Q$ؒ a5TDC<kHJ @ J̙/X}Ά_r\14_-=d".Y١7T5s2O3F\UPh6 c0a0U00UvU6\bq,5c |/Q.Z>̤).0xvTs(Y8 bB}!=:w +_6*0$c {XB|h,~*= 4tjǴ[ ҤL*/l='pjR!@gPZ#xNOU:S|X)"ད.vW)Dz`c]315rχ+/c#]?W(&iԏDH()o& <:l7D,(toJW5)'!d6]Dz'@U8(QngSlq\&MuZ~`VM җTw=ܯ~VA.)}1q,'HN*RQ) 43bOLX [Z:d3wN ٔko`h6{f1q4NꯋVA"7^7- /iQf:*:[jF ;p}sp)&>Rb|SWaM'nQk$0 0U00UӔLb*.̯r}6ךg0U0U00ldap://directory.d-trust.net/CN=D-TRUST%20Root%20Class%203%20CA%202%20EV%202009,O=D-Trust%20GmbH,C=DE?certificaterevocationlist0FDB@http://www.d-trust.net/crl/d-trust_root_class_3_ca_2_ev_2009.crl0  *H  4{Z<u/<Q&)$ U0Q-K (%IѦ6w4dRsz9­q!Zk}qCtxIa>sMqĶSx֢/9)<!0(^F;xBtU PgMfѧfCͧ+W{cFj.Rm)xH#쵫Kzn@qheM|SepFҿTX}RoV&bۉ1o"b5LiT_wˎ=CiX$;@~5NqZamazon_root_ca_1:2.19.6.108.159.207.153.191.140.10.57.226.240.120.138.67.230.150.54.91.202~RuX.509E0A0)lϙ 9xC6[0  *H  091 0 UUS10 U Amazon10UAmazon Root CA 10 150526000000Z 380117000000Z091 0 UUS10 U Amazon10UAmazon Root CA 10"0  *H 0 xqxqGPt}n׈vhX!`t/-ӠCzN6H6L#>7Ih׹v8a6JVEtڜ59/ PlzЀGP8ܢ9XթHg0x^oQ0fEfTÑH0-}-tp5׈$Yns2F(Cʴ$-Kq\^i8P8o-bTwg#?@  ĀL>;$&lȪ B0@0U00U0U̅4 .YDzN 0  *H  7ZAvQ( 6#(H0$KȡzpS(%#!| Nu: jxvDGelA;P,7KanŲ[\wR;ދ\[ZR[`K@m1TBF#HpuxqrC4unWY\&`)#C#CC)rb]^ԐUēCwfaAחx`nJr}lY3Đeluxtrust_global_root_2:2.20.10.126.166.223.75.68.158.218.106.36.133.158.230.184.21.211.22.127.187.177~R2X.50900 ~KDj$0  *H  0F1 0 ULU10U LuxTrust S.A.10U LuxTrust Global Root 20 150305132157Z 350305132157Z0F1 0 ULU10U LuxTrust S.A.10U LuxTrust Global Root 20"0  *H 0 ׅbLf`ogGZ; gFƮ8օk3$p"K) Fk*fB5Fl{PU1-퀭h$iq0g@~C/e/d_1xZYeY2HL)Kvw%mB8M_-yB1ci" 40.mNp8d%M9ɇXq00U00BU ;0907++ 0,0*+https://repository.luxtrust.lu0U0U#0(vH,++SK|0U(vH,++SK|0  *H  jny, p~x NıΓpT2͙0d36@rjYh .r jd1 }IZ7EɅU 詴Ό[\ϊ ֬w2$rToV7,eXW5{1]=Y\zp4Xԕ`r.egӞ\%O~- u3θum>[1 VC0kVUg̓.-pQCxM_đXFwZt@0$@zjO @ߡDKFEBEfJ$ι?o>{eY(gאuc~֊uŲӢޛ䘾}遭o4 wX6߬pq5B0@0U00U0U,PA6a[Jkٙ30  *H Zp,ݷ4OQ&Kq aǠ4zw5'l$F>JN+ RgE1OySjc:әUq5:ꮭBo!M5c3I֛NN bw"^x8rxKs-AZ1qHrsZYScR39pBf)Q0T"_٫+xFָ +>B^mKEZ|"ZY5碷b⫤8L95oi:Thm/CU j<,xP:V5@>,9BAtߣ†`Hhi Tvi! yN4^̱|pDžB0@0U ݩ!>w+0U0U00  *H  Y}q=[Ӝk6a,t=u׺B=}>ϒlH"?i;Ŷ/5h*W95 {V͋t޾Ъ?4pΝ F`~IQ}p`yrz=_*9G~#c@l 1( ϳ#5Al7{/@B8SiZE ῝Wlbc "BAo>?@zyҝ=-2v zxoǺ%t*A!j jGve:Ϗb{ (҃!,ahgxMg#f❐u46+̊%\Z/my$RhÄ5fc%My7"T1j0h0U g& EU9.w?BJ0 U009g*10/0-0 +0g*E V|[x S0  *H  SY>Iv #'`tj4^lSٟ$Dj*ƥxGX*^y *g%?iVsÊfH)Wtʜ(8g&+յ?e6]@ '=9%{hPtU Y}Z=A%RG,1տUƻ_qlv =-(;VQ.wR4֛a5{9i b`@ 66-J\sn3_h'j5c߫ٺJPa-05]GQK.M݅ R Pc7!LDěQsT.(^D9V-7D K,Ò4aJCR4:})v0q6Ht"A\qAD~X[lGbꔞYíM1 'ɾld[7Bݤo|Tnzh.: <;xNc!gI[> J=+* M$security_communication_rootca2:2.1.0~RBX.509{0w0_0  *H  0]1 0 UJP1%0#U SECOM Trust Systems CO.,LTD.1'0%U Security Communication RootCA20 090529050039Z 290529050039Z0]1 0 UJP1%0#U SECOM Trust Systems CO.,LTD.1'0%U Security Communication RootCA20"0  *H 0 9RRY]R:CeK6֦d^ ߗ=K]!A͹~v>64;1Et=WjԵAB¿8LT6E{e M~ ;:VZoviRzj]R- k5 j:7G~WO?gžSU}x.aJՎ9ߔp(?@^c<*kYj;oJN:' S$kP-<D4'uB0@0U we|@,8 <0U0U00  *H  L:DEǓ~ BdYl_jJzErq:o#$̍q)l]3_de;ovxܢH?NU>|^ƧOh:. CW\bh|b+ 4j)V<7#lNtFl4욑D1rI|ٖUG5Zˊ[q)z W#!?J9I 7]3^(|}'7"quovadis_root_ca:2.4.58.182.80.139~R:X.50900:P0  *H 01 0 UBM10U QuoVadis Limited1%0#U Root Certification Authority1.0,U%QuoVadis Root Certification Authority0 010319183333Z 210317183333Z01 0 UBM10U QuoVadis Limited1%0#U Root Certification Authority1.0,U%QuoVadis Root Certification Authority0"0  *H 0 aSWg :dѼz).$T@$8XLˤ'BП[Qpt:׭;fhWv=|ޔj;KՏe8:=U6NyW1*YeIX ~_~Mtl)J*Tec7{ ADˠqef1v}XI& vf]&_g'TűzqJ)jE^o6â\8RDC搻R0N0=+10/0-+0!https://ocsp.quovadisoffshore.com0U00U 0 0  +X00+0Reliance on the QuoVadis Root Certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certification practices, and the QuoVadis Certificate Policy.0"+http://www.quovadis.bm0UKm)99j0U#0Km)99jߡ01 0 UBM10U QuoVadis Limited1%0#U Root Certification Authority1.0,U%QuoVadis Root Certification Authority:P0U0  *H Ԥ~rh|R$go9zĪ^=XMpaiGPN$'/Ss{=tn.ĿV'P+bKM>G>Gz$5 mrb'kT>Pπԕ赂ŶU%W۱P`dYzio >otr0*sbIa*j  ^jŝd lY'+atqlC5U7",G}b)f(ʷpHPo r0?(uOSt$.vśUtx!- ՖT"z}0{0U, `їp;l!0U00U#0, `їp;l!0U 00  +-0U0  *H  &w4۔H*A,>`Č T{9>{=N#k\@ߡ yx$14'Ocku!&GXrq~MG;ɯm8d%Ϧ\ZE ķµƽZV" }7AB` {/trustcor_eca-1:2.9.0.132.130.44.95.28.98.208.64~RWX.509$0 0 ,_b@0  *H  01 0 UPA10 U Panama10U Panama City1$0"U TrustCor Systems S. de R.L.1'0%U TrustCor Certificate Authority10U TrustCor ECA-10 160204123233Z 291231172807Z01 0 UPA10 U Panama10U Panama City1$0"U TrustCor Systems S. de R.L.1'0%U TrustCor Certificate Authority10U TrustCor ECA-10"0  *H 0 ϏvvTsc)Gƣk_3CQ31tԧ沒>jt@?@Q&k+Ƭ՗ U'|v)@98EuК4RG~ sWZ~CU:mDL^R% }}1DAۯ,Ś!=B;P&qab!TN> *ؗbȃ3}ZW;%|/Mơ:z]5HJ6EfԺXc0a0UDHmHԠKY$/0U#0DHmHԠKY$/0U00U0  *H  >5\psaor+C]Ĕg]gluv 6ƭGc~.28s,Y! +'$:D>wsd,|?]E%<n*Lc$ab~l*U*G<.^t"}SE'}"h6OD2ި dMkHXiMQߟ=`NbE <[\q'%SU]quovadis_root_ca_1_g3:2.20.120.88.95.46.173.44.25.75.227.55.7.53.52.19.40.181.150.212.101.147~R8X.509d0`0HxX_.,K754(e0  *H  0H1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 1 G30 120112172744Z 420112172744Z0H1 0 UBM10U QuoVadis Limited10UQuoVadis Root CA 1 G30"0  *H 0 Pl@1-<UX0$ތ,=߂OGl[IJջ쇬=R5Sf<Ԭ$;FsXv LÆ0 ~5߻8g>ǫϓ#'I<]*!9S}~ S]ϡJv w[6>R^cŦRR9r b`n%f@No僠'^0=i8biQ4 !YJ\a*xQ=:Y\"Eqݑlz==|^h^ #Z"v-ɡD#*X/0T#w]aˉ_J!Ia(1tű2M_ :z_w_@]2jF#[LB16HǍ[3FftO ac~.w*#hkWvp3O#we?Ǽ.-F/if>ʔv % {;_ :=dῧ-NM)"Ŭr?::"1cu`(-[hf#QS1{鷝K]8I0w1MgTl/oe=!^`eTqd363qx_N!4IYvZ6 a*lJ(o.y͐3óvlrG5 STa%8ޅ2-^sR]B=KբPAAýZcf:;G&LQ# &daJ\޳gm]ihi^:|i;NOÕzXll)c^,-=Ze[@Hm*<$zKdcJ.$3`̹a&z GpMWpuppetlabs-puppetserver-7e1a9a8/spec/fixtures/puppet-server-lib/000077500000000000000000000000001470345337400252565ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/fixtures/puppet-server-lib/puppet/000077500000000000000000000000001470345337400265735ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/fixtures/puppet-server-lib/puppet/jvm/000077500000000000000000000000001470345337400273675ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/fixtures/puppet-server-lib/puppet/jvm/execution_spec/000077500000000000000000000000001470345337400324045ustar00rootroot00000000000000echo_cwd.sh000077500000000000000000000000361470345337400344360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/fixtures/puppet-server-lib/puppet/jvm/execution_spec#!/bin/sh echo "cwd is $PWD" echo_stdout_and_stderr.sh000077500000000000000000000000711470345337400374070ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/fixtures/puppet-server-lib/puppet/jvm/execution_spec#!/bin/sh echo "hello stdout" echo "hello stderr" 1>&2 puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/000077500000000000000000000000001470345337400234055ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/000077500000000000000000000000001470345337400247225ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/000077500000000000000000000000001470345337400255165ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/ast_compiler_spec.rb000066400000000000000000000155531470345337400315470ustar00rootroot00000000000000require 'spec_helper' require 'puppet_pal' require 'puppet/server/ast_compiler' def generate_ast(code) Puppet::Pal.in_tmp_environment("ast") do |pal| pal.with_catalog_compiler do |compiler| ast = compiler.parse_string(code) Puppet::Pops::Serialization::ToDataConverter.convert(ast, rich_data: true, symbol_to_string: true) end end end def environment_request(code) {"certname" => "localhost", "facts" => {"values" => {"my_fact" => "fact_value"}}, "trusted_facts" => {"values" => {"my_trusted" => "trusted_value"}}, "options" => {"capture_logs" => false}, "environment" => "production", "code_ast" => generate_ast(code).to_json, "variables" => {"values" => {"foo" => "bar"}}} end def project_request(code) {"certname" => "localhost", "facts" => {"values" => {"my_fact" => "fact_value"}}, "trusted_facts" => {"values" => {"my_trusted" => "trusted_value"}}, "options" => {"capture_logs" => false, "compile_for_plan" => true}, "versioned_project" => "fakeproject_GITSHA", "project_root" => "/etc/puppetlabs/puppetserver/projects", "modulepath" => ['/etc/puppetlabs/puppetserver/projects/fakeproject_GITSHA', '/etc/puppetlabs/puppetserver/projects/fakeproject_GITSHA/.modules'], "hiera_config" => ['/etc/puppetlabs/puppetserver/projects/fakeproject_GITSHA/hiera.yaml'], "project_name" => 'fakeproject', "code_ast" => generate_ast(code).to_json, "variables" => {"values" => {"foo" => "bar"}}} end def find_notify(catalog, title: nil) catalog['resources'].find do |item| next item['type'] == 'Notify' unless title item['type'] == 'Notify' && item['title'] == title end end describe Puppet::Server::ASTCompiler do context 'when compiling AST' do let(:boltlib_path) { nil } it 'handles basic resources' do response = Puppet::Server::ASTCompiler.compile(environment_request("notify { 'my_notify': }"), boltlib_path) notify = find_notify(response[:catalog]) expect(notify).not_to be_nil expect(notify['title']).to eq("my_notify") end it 'correctly interpolates supplied variables' do response = Puppet::Server::ASTCompiler.compile(environment_request('notify { "$foo": }'), boltlib_path) notify = find_notify(response[:catalog]) expect(notify).not_to be_nil expect(notify['title']).to eq("bar") end it 'correctly interpolates supplied facts' do response = Puppet::Server::ASTCompiler.compile(environment_request('notify { "$my_fact": }'), boltlib_path) notify = find_notify(response[:catalog]) expect(notify).not_to be_nil expect(notify['title']).to eq("fact_value") end it 'correctly interpolates supplied trusted facts' do response = Puppet::Server::ASTCompiler.compile(environment_request('notify { "${trusted[\'my_trusted\']}": }'), boltlib_path) notify = find_notify(response[:catalog]) expect(notify).not_to be_nil expect(notify['title']).to eq("trusted_value") end it 'fails gracefully when boltlib is not found when request requires bolt types' do bolt_request = environment_request('notify { "${trusted[\'my_trusted\']}": }') bolt_request.merge!({'options' => { 'compile_for_plan' => true } }) expect { Puppet::Server::ASTCompiler.compile(bolt_request, boltlib_path) }.to raise_error(Puppet::Error, /the path to boltlib modules must be provided/) end context 'when compiling for an environment plan with fact and plan/target variable collisions' do let(:boltlib_path) { [] } it 'properly shadows the relevant variables' do # TODO: This is a temporary stub of the Bolt requires to get this # test to pass. We should figure out how to properly load Bolt code # later for the tests. allow(Puppet::Server::ASTCompiler).to receive(:load_bolt) mock_apply_inventory_class = double('Bolt::ApplyInventory') allow(mock_apply_inventory_class).to receive(:new).with(anything).and_return(double('mock')) stub_const("Bolt::ApplyInventory", mock_apply_inventory_class) facts = { "values" => { "plan_var_fact" => "fact_value", "target_var_fact" => "fact_value", } } variables = { "values" => [ # should be shadowed by plan_var_fact fact {"plan_var_fact" => "plan_value"}, {"plan_var_plain" => "plan_value"}, ] } target_variables = { "values" => { # should be shadowed by target_var_fact fact "target_var_fact" => "target_value", # should be shadowed by plan_var_plain plan variable "plan_var_plain" => "target_value" } } code = < $plan_var_fact } notify { "target_var_fact": message => $target_var_fact } notify { "plan_var_plain": message => $plan_var_plain } CODE bolt_request = environment_request(code) bolt_request.merge!( 'facts' => facts, 'variables' => variables, 'target_variables' => target_variables, 'options' => { 'compile_for_plan' => true }, ) response = Puppet::Server::ASTCompiler.compile(bolt_request, boltlib_path) catalog = response[:catalog] # assert the shadowed values expected_collisions = { 'plan_var_fact' => 'fact_value', 'target_var_fact' => 'fact_value', 'plan_var_plain' => 'plan_value', } expected_collisions.each do |var, expected_value| notify = find_notify(catalog, title: var) expect(notify).not_to be_nil expect(notify['parameters']['message']).to eql(expected_value) end end end context 'when running a project plan' do let(:boltlib_path) { [] } it 'returns puppet settings back to normal' do # TODO: This is a temporary stub of the Bolt requires to get this # test to pass. We should figure out how to properly load Bolt code # later for the tests. allow(Puppet::Server::ASTCompiler).to receive(:load_bolt) mock_apply_inventory_class = double('Bolt::ApplyInventory') allow(mock_apply_inventory_class).to receive(:new).with(anything).and_return(double('mock')) stub_const("Bolt::ApplyInventory", mock_apply_inventory_class) # Use a simple resource, since we aren't testing the compilation itself # but rather ensuring the compilation does not interfere with global state response = Puppet::Server::ASTCompiler.compile(project_request("notify { 'my_notify': }"), boltlib_path) notify = find_notify(response[:catalog]) expect(notify).not_to be_nil expect(notify['title']).to eq("my_notify") end end end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/certificate_spec.rb000066400000000000000000000056101470345337400313410ustar00rootroot00000000000000require 'spec_helper' require 'puppet/ssl' require 'puppet/ssl/base' require 'puppet/server/certificate' require 'puppet/server/puppet_config' require 'rspec' java_import com.puppetlabs.ssl_utils.SSLUtils java_import java.io.FileReader describe Puppet::Server::Certificate do java_master_cert = SSLUtils.pem_to_cert( FileReader.new("spec/fixtures/master-cert-with-dns-alts.pem")) master_certificate = Puppet::Server::Certificate.new(java_master_cert) java_agent_cert = SSLUtils.pem_to_cert( FileReader.new("spec/fixtures/agent-cert-with-exts.pem")) agent_certificate = Puppet::Server::Certificate.new(java_agent_cert) it 'should return DNS alt names' do expect(Set.new(master_certificate.subject_alt_names)).to eq( Set.new(['localhost', 'onefish', 'twofish', 'redfish', 'bluefish']) ) end it 'should return Puppet white-listed extensions' do Puppet::Server::PuppetConfig.initialize_puppet(puppet_config: {}) exts = agent_certificate.custom_extensions expect(exts.find { |ext| ext['oid'] == 'pp_uuid' }['value']).to eq("ED803750-E3C7-44F5-BB08-41A04433FE2E") expect(exts.find { |ext| ext['oid'] == 'pp_instance_id' }['value']).to eq("thisisanid") expect(exts.find { |ext| ext['oid'] == 'pp_image_name' }['value']).to eq("my_ami_image") expect(exts.find { |ext| ext['oid'] == 'pp_preshared_key' }['value']).to eq("342thbjkt82094y0uthhor289jnqthpc2290") expect(exts.find { |ext| ext['oid'] == 'pp_cost_center' }['value']).to eq("center") expect(exts.find { |ext| ext['oid'] == 'pp_product' }['value']).to eq("product") expect(exts.find { |ext| ext['oid'] == 'pp_project' }['value']).to eq("project") expect(exts.find { |ext| ext['oid'] == 'pp_application' }['value']).to eq("application") expect(exts.find { |ext| ext['oid'] == 'pp_service' }['value']).to eq("service") expect(exts.find { |ext| ext['oid'] == 'pp_employee' }['value']).to eq("employee") expect(exts.find { |ext| ext['oid'] == 'pp_created_by' }['value']).to eq("created") expect(exts.find { |ext| ext['oid'] == 'pp_environment' }['value']).to eq("environment") expect(exts.find { |ext| ext['oid'] == 'pp_role' }['value']).to eq("role") expect(exts.find { |ext| ext['oid'] == 'pp_software_version' }['value']).to eq("version") expect(exts.find { |ext| ext['oid'] == 'pp_department' }['value']).to eq("deparment") expect(exts.find { |ext| ext['oid'] == 'pp_cluster' }['value']).to eq("cluster") expect(exts.find { |ext| ext['oid'] == 'pp_provisioner' }['value']).to eq("provisioner") end it 'should return the proper subject name' do expect(agent_certificate.unmunged_name).to eq('firehose-agent') end it 'should return the expiration date' do expect(agent_certificate.expiration.to_s).to eq('2020-03-11 21:44:28 UTC') end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/compiler_spec.rb000066400000000000000000000130051470345337400306660ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/compiler' def set_facts(fact_hash) fact_hash.each do |key, value| allow(Facter).to receive(:value).with(key).and_return(value) end end describe Puppet::Server::Compiler do let(:compiler) { Puppet::Server::Compiler.new } context 'when creating a node' do let(:certname) { 'mynode.best.website' } let(:environment) { 'production' } let(:persistence) { { 'facts' => false, 'catalog' => false } } let(:facts) { { 'values' => { 'hello' => 'hi' } } } let(:trusted_facts) { { 'values' => { 'secret' => 'm3ss4g3' } } } let(:transaction_uuid) { '3542fd19-86df-424a-a2b1-31c6600a4ad9' } let(:job_id) { '1234' } let(:options) { {} } let(:request_data) do { 'certname' => certname, 'environment' => environment, 'persistence' => persistence, 'facts' => facts, 'trusted_facts' => trusted_facts, 'transaction_uuid' => transaction_uuid, 'job_id' => job_id, 'options' => options } end let(:node) { compiler.create_node(request_data) } let(:pe_version_file) { '/opt/puppetlabs/server/pe_version' } before(:each) do Puppet::Node.indirection.terminus_class = :plain end it 'the node has facts set' do expect(node.facts.values).to eq(facts['values']) end it 'the node has trusted data set' do expect(node.trusted_data).to eq(trusted_facts['values']) end it 'the node has server facts set' do expect(node.parameters).to include('serverversion' => Puppet.version.to_s) expect(node.server_facts).to include('serverversion' => Puppet.version.to_s) end it 'the node has no pe_serverversion fact set when FOSS' do expect(node.parameters).not_to include('pe_serverversion') expect(node.server_facts).not_to include('pe_serverversion') end it 'the node has pe_serverversion fact set when PE' do set_facts({ 'networking.fqdn' => "my.server.com", 'networking.ip' => "my.ip.address", 'networking.ip6' => nil }) allow(File).to receive(:readable?).with(pe_version_file).and_return(true) allow(File).to receive(:zero?).with(pe_version_file).and_return(false) allow(File).to receive(:read).with(pe_version_file).and_return('2019.3.0') expect(node.parameters).to include('pe_serverversion' => '2019.3.0') expect(node.server_facts).to include('pe_serverversion' => '2019.3.0') end context 'the classified node has a different environment' do let(:environment) { 'fancy' } before(:each) do FileUtils.mkdir_p(File.join(Puppet[:environmentpath], environment)) end it 'by default uses the classified environment' do expect(Puppet::Node.indirection).to receive(:find).and_return( Puppet::Node.new(certname, environment: 'production') ) expect(node.environment.name).to eq(:production) end context 'and facts are not submitted' do let(:facts) { nil } it 'requests facts from pdb after classifying and attempts to classify again' do allow(Puppet::Node::Facts.indirection.terminus).to receive(:name).and_return(:puppetdb) expect(compiler).to receive(:get_facts_from_terminus) .with(certname, 'fancy') .ordered .and_return(Puppet::Node::Facts.new(certname)) expect(compiler).to receive(:get_facts_from_terminus) .with(certname, 'production') .ordered .and_return(Puppet::Node::Facts.new(certname)) expect(Puppet::Node.indirection).to receive(:find).and_return( Puppet::Node.new(certname, environment: 'production') ).twice expect(node.environment.name).to eq(:production) end it 'makes a limited number of attempts to retrieve a node' do %w[foo bar baz qux].each do |env| FileUtils.mkdir_p(File.join(Puppet[:environmentpath], env)) end allow(Puppet::Node::Facts.indirection.terminus).to receive(:name).and_return(:puppetdb) allow(compiler).to receive(:get_facts_from_terminus).and_return(Puppet::Node::Facts.new(certname)) expect(Puppet::Node.indirection).to receive(:find).and_return( Puppet::Node.new(certname, environment: 'production') ).ordered expect(Puppet::Node.indirection).to receive(:find).and_return( Puppet::Node.new(certname, environment: 'foo') ).ordered expect(Puppet::Node.indirection).to receive(:find).and_return( Puppet::Node.new(certname, environment: 'bar') ).ordered expect(Puppet::Node.indirection).to receive(:find).and_return( Puppet::Node.new(certname, environment: 'baz') ).ordered expect(Puppet::Node.indirection).to receive(:find).and_return( Puppet::Node.new(certname, environment: 'qux') ).ordered expect { compiler.create_node(request_data) } .to raise_error(Puppet::Error, /environment didn't stabilize/) end end context 'and prefer_requested_environment is set' do let(:options) { { 'prefer_requested_environment' => true } } it 'uses the environment in the request' do expect(Puppet::Node.indirection).to receive(:find).and_return( Puppet::Node.new(certname, environment: 'production') ) expect(node.environment.name).to eq(:fancy) end end end end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/config_spec.rb000066400000000000000000000040501470345337400303210ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/config' describe Puppet::Server::Config do context "SSL context" do before :each do Puppet[:hostcert] = "spec/fixtures/localhost-cert.pem" Puppet[:hostprivkey] = "spec/fixtures/localhost-privkey.pem" Puppet[:localcacert] = "spec/fixtures/ca-cert.pem" # The class will memoize loaded contexts in these variables Puppet::Server::Config.instance_variable_set(:@puppet_and_system_ssl_context, nil) Puppet::Server::Config.instance_variable_set(:@puppet_only_ssl_context, nil) end it "is configured with :localcacert and not :cacert" do Puppet[:cacert] = "SHOULD/NOT/BE/USED" begin Puppet::Server::Config.ssl_context rescue Java::JavaIO::FileNotFoundException fail 'SSL context configured with :cacert' end end it "ssl_context and puppet_only_ssl_context are the same SSLContext" do ssl_context = Puppet::Server::Config.ssl_context puppet_only_ssl_context = Puppet::Server::Config.puppet_only_ssl_context expect(ssl_context).to be_a_kind_of(Java::JavaxNetSsl::SSLContext) expect(ssl_context).to eq(puppet_only_ssl_context) end it "loads the puppet certs and any existing configured system certs w/o error" do Puppet[:ssl_trust_store] = "spec/fixtures/puppet-cacerts" begin ssl_context = Puppet::Server::Config.puppet_and_system_ssl_context expect(ssl_context).to be_a_kind_of(Java::JavaxNetSsl::SSLContext) rescue => e fail "Could not initialize puppet_and_system_ssl_context because of #{e.inspect}" end end it "warns if :ssl_trust_store is set but not readable" do Puppet[:ssl_trust_store] = "spec/fixtures/foo.pem" allow(File).to receive(:exist?).and_return(false) expect(Puppet).to receive(:warning).with(/Could not find Puppet-vendored keystore/) expect(Puppet).to receive(:warning).with(/The 'ssl_trust_store' setting does not refer to a file/) Puppet::Server::Config.puppet_and_system_ssl_context end end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/execution_spec.rb000066400000000000000000000066051470345337400310670ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/execution' def test_execute(command, options = {}) # NOTE: the `execute` function is not part of the public API, # but is still the best level of abstraction to use for this sort # of test, so we're abusing Ruby's `send` for these tests. Puppet::Server::Execution.send(:execute, command, options) end describe Puppet::Server::Execution do context "execution stub" do it "should return an instance of ProcessOutput" do result = test_execute("echo hi") expect(result).to be_a Puppet::Util::Execution::ProcessOutput end it "should return the STDOUT of the process" do result = test_execute("echo hi") expect(result).to eq "hi\n" end it "should combine STDOUT/STDERR of the process when :combine is set" do result = test_execute("./spec/fixtures/puppet-server-lib/puppet/jvm/execution_spec/echo_stdout_and_stderr.sh", {:combine => true}) expect(result).to match(/hello stdout/) expect(result).to match(/hello stderr/) end it "should set the current working directory" do tmpdir = Dir.tmpdir result = test_execute(File.join(__dir__, "../../../../spec/fixtures/puppet-server-lib/puppet/jvm/execution_spec/echo_cwd.sh"), {:cwd => tmpdir}) expect(result).to match(/cwd is #{Regexp.escape(tmpdir)}/) end it "should return an instance of ProcessOutput for a command with args" do result = test_execute(["echo", "hi"]) expect(result).to be_a Puppet::Util::Execution::ProcessOutput end it "should return the STDOUT of the process for a command with args" do result = test_execute(["echo", "hi"]) expect(result).to eq "hi\n" end it "returns an instance of ProcessOutput for a command with an empty array of args" do result = test_execute("echo hi") expect(result).to be_a Puppet::Util::Execution::ProcessOutput expect(result).to eq "hi\n" end it "should return the exit code of the process" do result = test_execute("echo hi") expect(result.exitstatus).to eq 0 result = test_execute(["echo", "hi"]) expect(result.exitstatus).to eq 0 result = test_execute("false") expect(result.exitstatus).not_to eq 0 end context "it should support other shellisms" do it "should support pipes" do result = test_execute("echo foo | wc -c") expect(result).to be_a Puppet::Util::Execution::ProcessOutput expect(result.strip).to eq "4" expect(result.exitstatus).to eq 0 end it "should support environment variables" do result = test_execute(%(FOO=bar sh -c 'echo $FOO')) expect(result).to be_a Puppet::Util::Execution::ProcessOutput expect(result).to eq "bar\n" expect(result.exitstatus).to eq 0 end it "should support environment newlines" do result = test_execute(%(echo "foo\nbar")) expect(result).to be_a Puppet::Util::Execution::ProcessOutput expect(result.lines.count).to eq 2 expect(result.exitstatus).to eq 0 end end it "should raise an error if `failonfail` is true and the process returns non-zero" do expect { test_execute("false", {:failonfail => true}) }.to raise_error(Puppet::ExecutionFailure, /^Execution of 'false' returned 1/) end end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/handler_spec.rb000066400000000000000000000031641470345337400304760ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/network/http/handler' class TestHandler include Puppet::Server::Network::HTTP::Handler end describe Puppet::Server::Network::HTTP::Handler do context "body" do it "should return a string body untouched" do body_string = "12345" handler = TestHandler.new() result = handler.body({"body" => body_string}) expect(result).to be_a String expect(result).to eq body_string end it "should return an InputStream body back as a string" do bytes = Java::byte[3].new bytes[0] = -128 bytes[1] = -127 bytes[2] = -126 bytes_as_stream = Java::Java::io::ByteArrayInputStream.new(bytes) handler = TestHandler.new() result = handler.body({"body" => bytes_as_stream}) expect(result).to be_a String result_as_bytes = result.bytes.to_a expect(result_as_bytes[0]).to eq 128 expect(result_as_bytes[1]).to eq 129 expect(result_as_bytes[2]).to eq 130 end it "should return a nil body back as nil" do handler = TestHandler.new() result = handler.body({"body" => nil}) expect(result).to be_nil end it "should convert param values from a Java list to a Ruby array" do somestuff = java.util.ArrayList.new somestuff.add "one fish" somestuff.add "two fish" request = {"params" => {"something" => somestuff}} parsed_params = TestHandler.new().params(request) something = parsed_params[:something] expect(something.class).to eq Array expect(something[0]).to eq "one fish" expect(something[1]).to eq "two fish" end end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/http_client_spec.rb000066400000000000000000000103711470345337400313740ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/http_client' require 'java' describe 'Puppet::Server::HttpClient' do let :client do Puppet::Server::HttpClient.new end let(:url) { URI('http://localhost:0/') } context "when settings are initialized with specific values" do before :all do Puppet[:hostcert] = "spec/fixtures/localhost-cert.pem" Puppet[:hostprivkey] = "spec/fixtures/localhost-privkey.pem" Puppet[:localcacert] = "spec/fixtures/ca-cert.pem" @settings = Puppet::Server::HttpClient.settings Puppet::Server::HttpClient.initialize_settings( {"http_connect_timeout_milliseconds" => 42, "http_idle_timeout_milliseconds" => 24}) end after :all do Puppet::Server::HttpClient.initialize_settings(@settings) end subject do Puppet::Server::HttpClient.create_client_options(include_system_store: false) end it 'then get_socket_timeout_milliseconds is 24' do expect(subject.get_socket_timeout_milliseconds).to eq(24) end it 'then get_connect_timeout_milliseconds is 42' do expect(subject.get_connect_timeout_milliseconds).to eq(42) end end context 'when making a request with basic auth' do let(:headers) { {} } let(:params) { {} } let(:options) { {} } describe '#create_common_request_options' do subject { client.create_common_request_options(url, headers, params, options) } it 'includes Puppet user-agent header' do expect(subject.headers['User-Agent']).to match(/Puppet/) end context 'with query params' do let(:params) { {foo: 1, bar: 2} } it 'includes the query params in the url' do expect(subject.uri.get_query).to eq("foo=1&bar=2") end end context 'with auth provided via options' do let(:options) { {basic_auth: {user: 'username', password: 'secret'}} } it 'has the Authorization header set' do expect(subject.headers['Authorization']).to eq('Basic dXNlcm5hbWU6c2VjcmV0') end end context 'with auth provided via headers' do let(:headers) { {'Authorization' => 'Basic dXNlcm5hbWU6c2VjcmV0'} } it 'has the Authorization header set' do expect(subject.headers['Authorization']).to eq('Basic dXNlcm5hbWU6c2VjcmV0') end context 'with match auth via options' do let(:options) { {basic_auth: {user: 'username', password: 'secret'}} } it 'has the Authorization header set' do expect(subject.headers['Authorization']).to eq('Basic dXNlcm5hbWU6c2VjcmV0') end end context 'with non-match auth via options' do let(:options) { {basic_auth: {user: 'username', password: 'mismatch'}} } it 'raises an exception' do expect { subject }.to raise_error(StandardError, /Existing 'Authorization' header conflicts/) end end end end end context "when making a request that triggers a Java exception" do let :requests do body = nil { get: lambda { client.get(url) }, post: lambda { client.post(url, body) } } end [:get, :post].each do |request| describe "#{request} request" do subject { requests[request].call } it 'raises a Puppet::HTTP::HTTPError' do expect { subject }.to raise_error Puppet::HTTP::HTTPError end it 'raises a Puppet::Server::HttpClientError' do expect { subject }.to raise_error Puppet::Server::HttpClientError end it 'raises an Error with a specific message' do expect { subject }.to raise_error "Error executing http request" end end end end context "when passing the `include_system_store` option" do it "GET uses the client with the system store" do expect(Puppet::Server::HttpClient). to receive(:client_with_system_certs). and_return(double.as_null_object) client.get(url, options: {include_system_store: true }) end it "POST uses the client with the system store" do expect(Puppet::Server::HttpClient). to receive(:client_with_system_certs). and_return(double.as_null_object) client.post(url, nil, options: {include_system_store: true }) end end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/jvm_profiler_spec.rb000066400000000000000000000033061470345337400315550ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/jvm_profiler' class TestWrappedProfiler attr_reader :context, :description, :metric_id, :is_shutdown def initialize @is_shutdown = false end def start(description, metric_id) @description = description @metric_id = metric_id "foo" end def finish(context, description, metric_id) @context = context @description = description @metric_id = metric_id end def shutdown @is_shutdown = true end end describe Puppet::Server::JvmProfiler do let(:wrapped) { TestWrappedProfiler.new } let(:profiler) { Puppet::Server::JvmProfiler.new(wrapped) } it "converts metric ids to java" do converted = profiler.javify_metric_id(["foo", "bar"]) expect(converted).to be_a java.lang.String[] expect(converted[0]).to eq("foo") expect(converted[1]).to eq("bar") end it "calls wrapped profiler with java args" do context = profiler.start("desc", ["my", "metric"]) expect(wrapped.description).to be_a java.lang.String expect(wrapped.description).to eq("desc") expect(wrapped.metric_id).to be_a java.lang.String[] expect(wrapped.metric_id[0]).to eq("my") expect(wrapped.metric_id[1]).to eq("metric") expect(context).to eq("foo") profiler.finish(context, "desc", ["my", "metric"]) expect(wrapped.context).to eq("foo") expect(wrapped.description).to be_a java.lang.String expect(wrapped.description).to eq("desc") expect(wrapped.metric_id).to be_a java.lang.String[] expect(wrapped.metric_id[0]).to eq("my") expect(wrapped.metric_id[1]).to eq("metric") expect(wrapped.is_shutdown).to eq(false) profiler.shutdown expect(wrapped.is_shutdown).to eq(true) end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/logging_spec.rb000066400000000000000000000021471470345337400305070ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/puppet_config' require 'puppet/server/logging' describe Puppet::Server::Logging do context 'when setting the log level' do it 'flush logging queue' do # The logger will queue any old log messages, creating a logging destination # will force the pending queue to be flushed to this logger. We don't care # about these messages so we discard the logger, but we do not want them to # interfere with the next tests. _, _ = Puppet::Server::Logging.capture_logs('debug') do; end end it 'correctly filters messages' do _, logs = Puppet::Server::Logging.capture_logs('err') do Puppet.debug "Debug" Puppet.warning "Warning" Puppet.err "Error" end expect(logs.length).to eq(1) expect(logs[0]['level']).to eq("err") end it 'returns more verbose logging when requested' do _, logs = Puppet::Server::Logging.capture_logs('debug') do Puppet.debug "Debug" Puppet.warning "Warning" Puppet.err "Error" end expect(logs.length).to eq(3) end end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/master_spec.rb000066400000000000000000000057301470345337400303550ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/master' require 'puppet/server/jvm_profiler' describe 'Puppet::Server::Master' do let :master do Puppet::Server::Master.new({}, {}) end context "run mode" do subject do master.run_mode end it "is set to 'server'" do expect(subject).to eq('server') end end class MasterTestProfiler def start(description, metric_id) metric_id end def finish(context, description, metric_id) end def shutdown() end end context "profiler" do it "does not register a profiler if profiler is set to nil" do master = Puppet::Server::Master.new({}, {}) expect(Puppet::Util::Profiler.current.length).to eq(0) end it "registers a profiler if the profiler is not nil" do master = Puppet::Server::Master.new({}, {"profiler" => MasterTestProfiler.new}) expect(Puppet::Util::Profiler.current.length).to eq(1) end end context "multithreaded" do before do @old_settings = Puppet.settings end after do Puppet.replace_settings_object(@old_settings) end it 'creates a new Puppet::Server::Settings class for settings' do Puppet::Server::Master.new({}, {'multithreaded' => true}) expect(Puppet.settings).to be_a_kind_of(Puppet::Server::Settings) end end context "#check_ca_dir_for_deprecation_warning" do before do @master = Puppet::Server::Master.new({}, {}) @ssldir = Puppet[:ssldir] @cadir = File.join(@ssldir, 'ca') end it "warns when there is a directory in puppet's ssl dir" do expect(File).to receive(:exist?).with(@cadir).and_return(true) expect(File).to receive(:symlink?).with(@cadir).and_return(false) expect(@master).to receive(:log_ca_migration_warning) @master.check_cadir_for_deprecation_warning end it "warns when the symlink target is in puppet's ssl dir" do expect(File).to receive(:exist?).with(@cadir).and_return(true) expect(File).to receive(:symlink?).with(@cadir).and_return(true) expect(File).to receive(:readlink).with(@cadir).and_return(File.join(@ssldir, 'someotherdirinssldir')) expect(@master).to receive(:log_ca_migration_warning) @master.check_cadir_for_deprecation_warning end it "does not warn when there is no ca directory in puppet's ssl dir" do expect(File).to receive(:exist?).with(@cadir).and_return(false) expect(@master).to_not receive(:log_ca_migration_warning) @master.check_cadir_for_deprecation_warning end it "does not warn when there is a symlink pointing outside puppet's ssl dir" do expect(File).to receive(:exist?).with(@cadir).and_return(true) expect(File).to receive(:symlink?).with(@cadir).and_return(true) expect(File).to receive(:readlink).with(@cadir).and_return('/I/am/a/dir/outside/of/puppets/ssl/dir') expect(@master).to_not receive(:log_ca_migration_warning) @master.check_cadir_for_deprecation_warning end end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/puppet_config_spec.rb000066400000000000000000000037501470345337400317240ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/puppet_config' describe 'Puppet::Server::PuppetConfig' do context "initializing Puppet Server" do context "setting the Puppet log level from logback" do let(:logger) do double("Logger", isDebugEnabled: false, isInfoEnabled: true, isWarnEnabled: false, isErrorEnabled: false) end before :each do expect(Puppet::Server::Logger).to receive(:get_logger).and_return(logger) Puppet::Server::PuppetConfig.initialize_puppet(puppet_config: {}) end it "the puppet log level (Puppet[:log_level]) is set from logback" do expect(Puppet[:log_level]).to eq('info') end it "the puppet log level (Puppet::Util::Log.level) is set from logback" do expect(Puppet::Util::Log.level).to eq(:info) end end end context "When puppet has had settings initialized" do before :each do Puppet::Server::PuppetConfig.initialize_puppet(puppet_config: {}) end describe '(PUP-5482) Puppet[:always_retry_plugins]' do subject { Puppet[:always_retry_plugins] } it 'is false for increased performance in puppetserver' do expect(subject).to eq(false) end end describe '(PUP-6060) Puppet::Node indirection caching' do subject { Puppet[:node_cache_terminus] } it 'is nil to avoid superfluous caching' do expect(subject).to be_nil end subject { Puppet::Node.indirection.cache_class } it 'is nil to avoid superfluous caching'do expect(subject).to be_nil end end end # Even though we don't set the node_cache_terminus setting value, so it # defaults to nil, we want to honor it if users have specified it directly. # PUP-6060 / SERVER-1819 subject { Puppet::Node.indirection.cache_class } it 'honors the Puppet[:node_cache_terminus] setting' do Puppet::Server::PuppetConfig.initialize_puppet(puppet_config: { :node_cache_terminus => "plain" }) expect(subject).to eq(:plain) end end puppetlabs-puppetserver-7e1a9a8/spec/puppet-server-lib/puppet/jvm/settings_spec.rb000066400000000000000000000021601470345337400307140ustar00rootroot00000000000000require 'spec_helper' require 'puppet/server/settings' describe 'Puppet::Server::Settings' do before :each do @old_settings = Puppet.settings Puppet.replace_settings_object(Puppet::Settings.new) Puppet.initialize_default_settings!(Puppet.settings) @new_max_errors = Puppet[:max_errors] + 10 puppet_config = {max_errors: @new_max_errors.to_s} Puppet::Server::PuppetConfig.initialize_puppet(puppet_config: puppet_config) Puppet.replace_settings_object(Puppet::Server::Settings.new(global_settings: Puppet.settings, puppet_config: puppet_config)) end after :each do Puppet.replace_settings_object(@old_settings) end it 'settings configured prior to replacement are kept in new threads' do thread = Thread.new do expect(Puppet[:max_errors]).to be(@new_max_errors) end thread.join end it 'does not write settings to the global config when set in threads' do thread = Thread.new do Puppet[:max_errors] = 0 end thread.join expect(Puppet[:max_errors]).to be(@new_max_errors) end end puppetlabs-puppetserver-7e1a9a8/spec/rspec_via_jruby_spec.rb000066400000000000000000000004471470345337400245520ustar00rootroot00000000000000require 'puppet/server/http_client' describe "rspec via jruby" do it "can access our ruby source" do some_ruby_class = Puppet::Server::HttpClient.new expect(some_ruby_class).not_to be_nil end it "is actually running in JRuby" do expect(RUBY_PLATFORM).to eq('java') end end puppetlabs-puppetserver-7e1a9a8/spec/run_specs.rb000066400000000000000000000001641470345337400223470ustar00rootroot00000000000000require "bundler/setup" require "rspec" require "spec_helper" exit RSpec::Core::Runner.run(ARGV, $stderr, $stdout) puppetlabs-puppetserver-7e1a9a8/spec/spec_helper.rb000066400000000000000000000007131470345337400226370ustar00rootroot00000000000000require 'puppet' require 'puppet/test/test_helper' RSpec.configure do |config| config.mock_with :rspec Puppet::Test::TestHelper.initialize config.before(:all) do Puppet::Test::TestHelper.before_all_tests end config.after(:all) do Puppet::Test::TestHelper.after_all_tests end config.before(:each) do Puppet::Test::TestHelper.before_each_test end config.after(:each) do Puppet::Test::TestHelper.after_each_test end end puppetlabs-puppetserver-7e1a9a8/src/000077500000000000000000000000001470345337400176555ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/000077500000000000000000000000001470345337400204255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/000077500000000000000000000000001470345337400226045ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/000077500000000000000000000000001470345337400253505ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/certificate_authority.clj000066400000000000000000003470111470345337400324420ustar00rootroot00000000000000(ns puppetlabs.puppetserver.certificate-authority (:require [clj-time.coerce :as time-coerce] [clj-time.core :as time] [clj-time.format :as time-format] [clojure.java.io :as io] [clojure.set :as set] [clojure.string :as str] [clojure.tools.logging :as log] [me.raynes.fs :as fs] [puppetlabs.i18n.core :as i18n] [puppetlabs.kitchensink.core :as ks] [puppetlabs.kitchensink.file :as ks-file] [puppetlabs.puppetserver.common :as common] [puppetlabs.puppetserver.ringutils :as ringutils] [puppetlabs.puppetserver.shell-utils :as shell-utils] [puppetlabs.ssl-utils.core :as utils] [schema.core :as schema] [slingshot.slingshot :as sling]) (:import (java.io BufferedReader BufferedWriter ByteArrayInputStream ByteArrayOutputStream File FileNotFoundException IOException InputStream Reader StringReader) (java.nio CharBuffer) (java.nio.file Files Path Paths) (java.nio.file.attribute FileAttribute PosixFilePermissions) (java.security PrivateKey PublicKey) (java.security.cert CRLException CertPathValidatorException X509CRL X509Certificate) (java.text SimpleDateFormat) (java.time LocalDateTime ZoneId) (java.util Date) (java.util.concurrent.locks ReentrantReadWriteLock) (org.apache.commons.io IOUtils) (org.bouncycastle.pkcs PKCS10CertificationRequest) (org.joda.time DateTime))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public utilities ;; Pattern is one or more digit followed by time unit (def digits-with-unit-pattern #"(\d+)(y|d|h|m|s)") (def repeated-digits-with-unit-pattern #"((\d+)(y|d|h|m|s))+") (defn duration-string? "Returns true if string is formatted with duration string pairs only, otherwise returns nil. Ignores whitespace." [maybe-duration-string] (when (string? maybe-duration-string) (let [no-whitespace-string (clojure.string/replace maybe-duration-string #" " "")] (some? (re-matches repeated-digits-with-unit-pattern no-whitespace-string))))) (defn duration-str->sec "Converts a string containing any combination of duration string pairs in the format 'y' 'd' 'm' 'h' 's' to a total number of seconds. nil is returned if the input is not a string or not a string containing any valid duration string pairs." [string-input] (when (duration-string? string-input) (let [pattern-matcher (re-matcher digits-with-unit-pattern string-input) first-match (re-find pattern-matcher)] (loop [[_match-str digits unit] first-match running-total 0] (let [unit-in-seconds (case unit "y" 31536000 ;; 365 day year, not a real year "d" 86400 "h" 3600 "m" 60 "s" 1) total-seconds (+ running-total (* (Integer/parseInt digits) unit-in-seconds)) next-match (re-find pattern-matcher)] (if (some? next-match) (recur next-match total-seconds) total-seconds)))))) (defn get-ca-ttl "Returns ca-ttl value as an integer. If a value is set in certificate-authority that value is returned. Otherwise puppet config setting is returned" [puppetserver certificate-authority] (let [ca-config-value (duration-str->sec (:ca-ttl certificate-authority)) puppet-config-value (:ca-ttl puppetserver)] (when (and ca-config-value puppet-config-value) (log/warn (i18n/trs "Detected ca-ttl setting in CA config which will take precedence over puppet.conf setting"))) (or ca-config-value puppet-config-value))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Schemas (def AutoSignInput (schema/cond-pre schema/Bool schema/Str)) (def CertificateOrCSR (schema/cond-pre X509Certificate PKCS10CertificationRequest)) (def TTLDuration (schema/cond-pre schema/Int schema/Str)) (def MasterSettings "Settings from Puppet that are necessary for SSL initialization on the master. Most of these are files and directories within the SSL directory, excluding the CA directory and its contents; see `CaSettings` for more information. All of these are Puppet configuration settings." {:certdir schema/Str :dns-alt-names schema/Str :hostcert schema/Str :hostcrl schema/Str :hostprivkey schema/Str :hostpubkey schema/Str :keylength schema/Int :localcacert schema/Str :privatekeydir schema/Str :requestdir schema/Str :csr-attributes schema/Str}) (def AccessControl "Defines which clients are allowed access to the various CA endpoints. Each endpoint has a sub-section containing the client whitelist. Currently we only control access to the certificate_status(es) endpoints." {(schema/optional-key :certificate-status) ringutils/WhitelistSettings}) (defn positive-integer? [i] (and (integer? i) (pos? i))) (def PosInt "Any integer z in Z where z > 0." (schema/pred positive-integer? 'positive-integer?)) (def CaSettings "Settings from Puppet that are necessary for CA initialization and request handling during normal Puppet operation. Most of these are Puppet configuration settings." {:access-control (schema/maybe AccessControl) :allow-authorization-extensions schema/Bool :allow-duplicate-certs schema/Bool :allow-subject-alt-names schema/Bool :allow-auto-renewal schema/Bool :auto-renewal-cert-ttl TTLDuration :allow-header-cert-info schema/Bool :autosign AutoSignInput :cacert schema/Str :cadir schema/Str :cacrl schema/Str :cakey schema/Str :capub schema/Str :ca-name schema/Str :ca-ttl schema/Int :cert-inventory schema/Str :csrdir schema/Str :keylength schema/Int :manage-internal-file-permissions schema/Bool :ruby-load-path [schema/Str] :gem-path schema/Str :signeddir schema/Str :serial schema/Str ;; Path to file containing list of infra node certificates including MoM ;; provisioned by PE or user in case of FOSS :infra-nodes-path schema/Str ;; Path to file containing serial numbers of infra node certificates ;; This would be re-generated anytime the infra-nodes list is updated. :infra-node-serials-path schema/Str ;; Path to Infrastructure CRL file containing infra certificates :infra-crl-path schema/Str ;; Option to continue using full CRL instead of infra CRL if desired ;; Infra CRL would be enabled by default. :enable-infra-crl schema/Bool :serial-lock ReentrantReadWriteLock :serial-lock-timeout-seconds PosInt :crl-lock ReentrantReadWriteLock :crl-lock-timeout-seconds PosInt :inventory-lock ReentrantReadWriteLock :inventory-lock-timeout-seconds PosInt}) (def DesiredCertificateState "The pair of states that may be submitted to the certificate status endpoint for signing and revoking certificates." (schema/enum :signed :revoked)) (def CertificateState "The list of states a certificate may be in." (schema/enum "requested" "signed" "revoked")) (def CertificateDetails "CA and client certificate details; notAfter, notBefore and serial values." {:not_after schema/Str :not_before schema/Str :serial_number schema/Int}) (def CertificateStatusResult "Various information about the state of a certificate or certificate request that is provided by the certificate status endpoint." (let [base {:name schema/Str :state CertificateState :dns_alt_names [schema/Str] :subject_alt_names [schema/Str] :authorization_extensions {schema/Str schema/Str} :fingerprint schema/Str :fingerprints {schema/Keyword schema/Str}}] ;; The map should either have all of the CertificateDetails keys or none of ;; them (schema/conditional :serial_number (merge base CertificateDetails) :else base))) (def Certificate (schema/pred utils/certificate?)) (def CertificateRequest (schema/pred utils/certificate-request?)) (def Extension (schema/pred utils/extension?)) (def KeyIdExtension {:key-identifier [Byte] schema/Keyword schema/Any}) (def CertificateRevocationList (schema/pred utils/certificate-revocation-list?)) (def OutcomeInfo "Generic map of outcome & message for API consumers" {:outcome (schema/enum :success :not-found :error) :message schema/Str}) (def OIDMappings {schema/Str schema/Keyword}) (def default-allow-subj-alt-names false) (def default-allow-auth-extensions false) (def default-serial-lock-timeout-seconds 5) (def default-crl-lock-timeout-seconds ;; for large crls, and a slow disk a longer timeout is needed 60) (def default-inventory-lock-timeout-seconds 60) (def default-auto-ttl-renewal "90d") ; 90 days by default (def default-auto-ttl-renewal-seconds (duration-str->sec default-auto-ttl-renewal)) ; 90 days by default ;; if the crl is going to expire in less than this number of days, it should be regenerated. (def crl-expiration-window-days 30) (schema/defn ^:always-validate initialize-ca-config "Adds in default ca config keys/values, which may be overwritten if a value for any of those keys already exists in the ca-data" [ca-data] (let [cadir (:cadir ca-data) defaults {:infra-nodes-path (str cadir "/infra_inventory.txt") :infra-node-serials-path (str cadir "/infra_serials") :infra-crl-path (str cadir "/infra_crl.pem") :enable-infra-crl false :allow-subject-alt-names default-allow-subj-alt-names :allow-authorization-extensions default-allow-auth-extensions :serial-lock-timeout-seconds default-serial-lock-timeout-seconds :crl-lock-timeout-seconds default-crl-lock-timeout-seconds :inventory-lock-timeout-seconds default-inventory-lock-timeout-seconds :allow-auto-renewal false :auto-renewal-cert-ttl default-auto-ttl-renewal :allow-header-cert-info false}] (merge defaults ca-data))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Definitions (def ssl-server-cert "OID which indicates that a certificate can be used as an SSL server certificate." "1.3.6.1.5.5.7.3.1") (def ssl-client-cert "OID which indicates that a certificate can be used as an SSL client certificate." "1.3.6.1.5.5.7.3.2") ;; Note: When updating the following OIDs make sure to also update the OIDs here: ;; https://github.com/puppetlabs/puppet/blob/master/lib/puppet/ssl/oids.rb#L29-L67 (def puppet-oid-arc "The parent OID for all Puppet Labs specific X.509 certificate extensions." "1.3.6.1.4.1.34380.1") (def ppRegCertExt "The OID for the extension with shortname 'ppRegCertExt'." "1.3.6.1.4.1.34380.1.1") (def ppPrivCertExt "The OID for the extension with shortname 'ppPrivCertExt'." "1.3.6.1.4.1.34380.1.2") (def ppAuthCertExt "The OID for the extension with shortname 'ppAuthCertExt'." "1.3.6.1.4.1.34380.1.3") (def subject-alt-names-oid "2.5.29.17") ;; Extension that is checked when allowing access to the certificate_status(es) ;; endpoint. Should only be present on the puppet master cert. (def cli-auth-oid "1.3.6.1.4.1.34380.1.3.39") (def puppet-short-names "A mapping of Puppet extension short names to their OIDs. These appear in csr_attributes.yaml." {:pp_uuid "1.3.6.1.4.1.34380.1.1.1" :pp_instance_id "1.3.6.1.4.1.34380.1.1.2" :pp_image_name "1.3.6.1.4.1.34380.1.1.3" :pp_preshared_key "1.3.6.1.4.1.34380.1.1.4" :pp_cost_center "1.3.6.1.4.1.34380.1.1.5" :pp_product "1.3.6.1.4.1.34380.1.1.6" :pp_project "1.3.6.1.4.1.34380.1.1.7" :pp_application "1.3.6.1.4.1.34380.1.1.8" :pp_service "1.3.6.1.4.1.34380.1.1.9" :pp_employee "1.3.6.1.4.1.34380.1.1.10" :pp_created_by "1.3.6.1.4.1.34380.1.1.11" :pp_environment "1.3.6.1.4.1.34380.1.1.12" :pp_role "1.3.6.1.4.1.34380.1.1.13" :pp_software_version "1.3.6.1.4.1.34380.1.1.14" :pp_department "1.3.6.1.4.1.34380.1.1.15" :pp_cluster "1.3.6.1.4.1.34380.1.1.16" :pp_provisioner "1.3.6.1.4.1.34380.1.1.17" :pp_region "1.3.6.1.4.1.34380.1.1.18" :pp_datacenter "1.3.6.1.4.1.34380.1.1.19" :pp_zone "1.3.6.1.4.1.34380.1.1.20" :pp_network "1.3.6.1.4.1.34380.1.1.21" :pp_securitypolicy "1.3.6.1.4.1.34380.1.1.22" :pp_cloudplatform "1.3.6.1.4.1.34380.1.1.23" :pp_apptier "1.3.6.1.4.1.34380.1.1.24" :pp_hostname "1.3.6.1.4.1.34380.1.1.25" :pp_owner "1.3.6.1.4.1.34380.1.1.26" :pp_authorization "1.3.6.1.4.1.34380.1.3.1" :pp_auth_role "1.3.6.1.4.1.34380.1.3.13" :pp_cli_auth cli-auth-oid}) ;; OID for the attribute that indicates if the agent supports auto-renewal or not (def pp_auth_auto_renew-attribute "1.3.6.1.4.1.34380.1.3.2",) (def netscape-comment-value "Standard value applied to the Netscape Comment extension for certificates" "Puppet Server Internal Certificate") (defn required-ca-files "The set of SSL related files that are required on the CA." [enable-infra-crl] (set/union #{:cacert :cacrl :cakey :cert-inventory :serial} (if enable-infra-crl #{:infra-nodes-path :infra-crl-path} #{}))) (def max-ca-ttl "The longest valid duration for CA certs, in seconds. 50 standard years." 1576800000) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Internal (def private-key-perms "Posix permissions for all private keys on disk." "rw-r-----") (def public-key-perms "Posix permissions for all public keys on disk." "rw-r--r--") (def private-key-dir-perms "Posix permissions for the private key directory on disk." "rwxr-x---") (schema/defn create-file-with-perms :- File "Create a new empty file which has the provided posix file permissions. The permissions string is in the form of the standard 9 character posix format. " [path :- schema/Str permissions :- schema/Str] (let [perms-set (PosixFilePermissions/fromString permissions)] (-> (ks-file/str->path path) (Files/createFile (into-array FileAttribute [(PosixFilePermissions/asFileAttribute perms-set)])) (Files/setPosixFilePermissions perms-set) (.toFile)))) (schema/defn cert-validity-dates :- {:not-before Date :not-after Date} "Calculate the not-before & not-after dates that define a certificate's period of validity. The value of `ca-ttl` is expected to be in seconds, and the dates will be based on the current time. Returns a map in the form {:not-before Date :not-after Date}." [ca-ttl :- schema/Int] (let [now (time/now) not-before (time/minus now (time/days 1)) not-after (time/plus now (time/seconds ca-ttl))] {:not-before (.toDate not-before) :not-after (.toDate not-after)})) (schema/defn settings->cadir-paths "Trim down the CA settings to include only paths to files and directories. These paths are necessary during CA initialization for determining what needs to be created and where they should be placed." [ca-settings :- CaSettings] (let [settings' (dissoc ca-settings :access-control :allow-authorization-extensions :allow-duplicate-certs :allow-subject-alt-names :autosign :ca-name :ca-ttl :allow-header-cert-info :keylength :manage-internal-file-permissions :ruby-load-path :gem-path :enable-infra-crl :serial-lock-timeout-seconds :serial-lock :crl-lock-timeout-seconds :crl-lock :inventory-lock :inventory-lock-timeout-seconds :allow-auto-renewal :auto-renewal-cert-ttl)] (if (:enable-infra-crl ca-settings) settings' (dissoc settings' :infra-crl-path :infra-node-serials-path)))) (schema/defn settings->ssldir-paths "Remove all keys from the master settings map which are not file or directory paths. These paths are necessary during initialization for determining what needs to be created and where." [master-settings :- MasterSettings] (dissoc master-settings :dns-alt-names :csr-attributes :keylength)) (defn path-to-cert "Return a path to the `subject`s certificate file under the `signeddir`." [signeddir subject] (str signeddir "/" subject ".pem")) (defn path-to-cert-request "Return a path to the `subject`s certificate request file under the `csrdir`." [csrdir subject] (str csrdir "/" subject ".pem")) (defn create-parent-directories! "Create all intermediate directories present in each of the file paths. Throws an exception if the directory cannot be created." [paths] {:pre [(sequential? paths)]} (doseq [path paths] (ks/mkdirs! (fs/parent path)))) (defn input-stream->byte-array [input-stream] (with-open [os (ByteArrayOutputStream.)] (IOUtils/copy input-stream os) (.toByteArray os))) (schema/defn partial-state-error :- Exception "Construct an exception appropriate for the end-user to signify that there are missing SSL files and the master or CA cannot start until action is taken." [master-or-ca :- schema/Str found-files :- [schema/Str] missing-files :- [schema/Str]] (IllegalStateException. (format "%s\n%s\n%s\n%s\n%s\n" (i18n/trs "Cannot initialize {0} with partial state; need all files or none." master-or-ca) (i18n/trs "Found:") (str/join "\n" found-files) (i18n/trs "Missing:") (str/join "\n" missing-files)))) ; TODO - PE-5529 - this should be moved to jvm-c-a. (schema/defn get-csr-subject :- schema/Str [csr :- CertificateRequest] (-> csr (.getSubject) (.toString) (utils/x500-name->CN))) (defn contains-uppercase? "Does the given string contain any uppercase letters?" [s] (not= s (.toLowerCase s))) (schema/defn dns-alt-names :- [schema/Str] "Get the list of DNS alt names on the provided certificate or CSR. Each name will be prepended with 'DNS:'." [cert-or-csr :- CertificateOrCSR] (mapv (partial str "DNS:") (utils/get-subject-dns-alt-names cert-or-csr))) (schema/defn subject-alt-names :- [schema/Str] "Get the list of both DNS and IP alt names on the provided certificate or CSR. Each name will be prepended with 'DNS:' or 'IP:'." [cert-or-csr :- CertificateOrCSR] (into (mapv (partial str "IP:") (utils/get-subject-ip-alt-names cert-or-csr)) (mapv (partial str "DNS:") (utils/get-subject-dns-alt-names cert-or-csr)))) (schema/defn get-csr-attributes :- utils/SSLMultiValueAttributeList [csr :- PKCS10CertificationRequest] (utils/get-attributes csr)) (schema/defn authorization-extensions :- {schema/Str schema/Str} "Get the authorization extensions for the certificate or CSR. These are extensions that fall under the ppAuthCert OID arc. Returns a map of OIDS to values." [cert-or-csr :- CertificateOrCSR] (let [extensions (utils/get-extensions cert-or-csr) auth-exts (filter (fn [{:keys [oid]}] (utils/subtree-of? ppAuthCertExt oid)) extensions)] (reduce (fn [exts ext] ;; Get the short name from the OID if available (let [short-name (get (set/map-invert puppet-short-names) (:oid ext)) short-name-string (when short-name (name short-name)) oid (or short-name-string (:oid ext)) value (:value ext)] (assoc exts oid value))) {} auth-exts))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Writing various SSL objects safely ;; These versions all encode writing atomically and knowledge of file permissions (schema/defn write-public-key "Encode a key to PEM format and write it to a file atomically and with appropriate permissions for a public key." [key :- PublicKey path :- schema/Str] (ks-file/atomic-write path (partial utils/key->pem! key) public-key-perms)) (schema/defn write-private-key "Encode a key to PEM format and write it to a file atomically and with appropriate permissions for a private key." [key :- PrivateKey path :- schema/Str] (ks-file/atomic-write path (partial utils/key->pem! key) private-key-perms)) (schema/defn write-cert "Encode a certificate to PEM format and write it to a file atomically and with appropriate permissions." [cert :- Certificate path :- schema/Str] (ks-file/atomic-write path (partial utils/cert->pem! cert) public-key-perms)) (schema/defn write-crl "Encode a CRL to PEM format and write it to a file atomically and with appropriate permissions." [crl :- CertificateRevocationList path :- schema/Str] (ks-file/atomic-write path (partial utils/crl->pem! crl) public-key-perms)) (schema/defn write-crls "Encode a list of CRLS to PEM format and write it to a file atomically and with appropriate permissions. Note, assumes proper locking is done." [crls :- [CertificateRevocationList] path :- schema/Str] ;; use an atomic write for crash safety. (ks-file/atomic-write path (partial utils/objs->pem! crls) public-key-perms)) (schema/defn write-csr "Encode a CSR to PEM format and write it to a file atomically and with appropriate permissions." [csr :- CertificateRequest path :- schema/Str] (ks-file/atomic-write path (partial utils/obj->pem! csr) public-key-perms)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Serial number functions (def serial-lock-descriptor "Text used in exceptions to help identify locking issues" "serial-file") (def crl-lock-descriptor "Text used in exceptions to help identify locking issues" "crl-file") (def inventory-lock-descriptor "Text used in exceptions to help identify locking issues" "inventory-file") (schema/defn parse-serial-number :- schema/Int "Parses a serial number from its format on disk. See `format-serial-number` for the awful, gory details." [serial-number :- schema/Str] (Integer/parseInt serial-number 16)) (schema/defn get-serial-number! :- schema/Int "Reads the serial number file from disk and returns the serial number." [{:keys [serial serial-lock serial-lock-timeout-seconds]} :- CaSettings] (common/with-safe-read-lock serial-lock serial-lock-descriptor serial-lock-timeout-seconds (-> serial (slurp) (.trim) (parse-serial-number)))) (schema/defn format-serial-number :- schema/Str "Converts a serial number to the format it needs to be written in on disk. This function has to write serial numbers in the same format that the puppet ruby code does, to maintain compatibility with things like 'puppet cert'; for whatever arcane reason, that format is 0-padding up to 4 digits." [serial-number :- schema/Int] (format "%04X" serial-number)) (def serial-file-permissions "rw-r--r--") (schema/defn next-serial-number! :- schema/Int "Returns the next serial number to be used when signing a certificate request. Reads the serial number as a hex value from the given file and replaces the contents of `serial-file` with the next serial number for a subsequent call. Puppet's $serial setting defines the location of the serial number file." [{:keys [serial serial-lock serial-lock-timeout-seconds] :as ca-settings} :- CaSettings] (common/with-safe-write-lock serial-lock serial-lock-descriptor serial-lock-timeout-seconds (let [serial-number (get-serial-number! ca-settings)] (ks-file/atomic-write-string serial (format-serial-number (inc serial-number)) serial-file-permissions) serial-number))) (schema/defn initialize-serial-file! "Initializes the serial number file on disk. Serial numbers start at 1." [{:keys [serial serial-lock serial-lock-timeout-seconds]} :- CaSettings] (common/with-safe-write-lock serial-lock serial-lock-descriptor serial-lock-timeout-seconds (ks-file/atomic-write-string serial (format-serial-number 1) serial-file-permissions))) (schema/defn write-local-cacrl! :- (schema/maybe Exception) "Spits the contents of 'cacrl-contents' string to the 'localcacrl' file location if the 'cacrl' string contains valid CRL pem data. On success, return nil. On failure, return the Exception captured from the failed attempt to parse the CRL pem data." [localcacrl-path :- schema/Str cacrl-contents :- schema/Str] (let [crl-reader (StringReader. cacrl-contents)] (try (when (zero? (count (utils/pem->crls crl-reader))) (throw (CRLException. "No CRL data found"))) (ks-file/atomic-write-string localcacrl-path cacrl-contents public-key-perms) nil (catch IOException e e) (catch CRLException e e)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Inventory File (def inventory-date-formatter (time-format/formatter "YYY-MM-dd'T'HH:mm:ssz")) (schema/defn format-date-time :- schema/Str "Formats a date-time into the format expected by the ruby puppet code." [date-time :- Date] (time-format/unparse inventory-date-formatter (time-coerce/from-date date-time))) (schema/defn parse-date-time :- DateTime "parses a date-time string into a DateTime instance" [date-time :- schema/Str] (time-format/parse inventory-date-formatter date-time)) (def buffer-copy-size (* 64 1024)) (schema/defn read-infra-nodes "Returns a list of infra nodes or infra node serials from the specified file organized as one item per line." [infra-file-reader :- Reader] (line-seq infra-file-reader)) (schema/defn maybe-write-to-infra-serial! "Determine if the host in question is an infra host, and if it is, add the provided serial number to the infra-serials file" [serial :- BigInteger certname :- schema/Str {:keys [infra-nodes-path infra-node-serials-path]} :- CaSettings] (when (fs/exists? infra-nodes-path) (with-open [infra-nodes-reader (io/reader infra-nodes-path)] (let [infra-nodes (read-infra-nodes infra-nodes-reader)] (when (seq (filter #(= certname %) infra-nodes)) (log/debug (i18n/trs "Appending serial number {0} for {1} " serial certname)) (let [stream-content-fn (fn [^BufferedWriter writer] (log/trace (i18n/trs "Begin append to serial file.")) (let [copy-buffer (CharBuffer/allocate buffer-copy-size)] (try (with-open [^BufferedReader reader (io/reader infra-node-serials-path)] ;; copy all the existing content (loop [read-length (.read reader copy-buffer)] ;; theoretically read can return 0, which means try again (when (<= 0 read-length) (when (pos? read-length) (.write writer (.array copy-buffer) 0 read-length)) (.clear copy-buffer) (recur (.read reader copy-buffer))))) (catch FileNotFoundException _e (log/trace (i18n/trs "Inventory serial file not found. Assume empty."))) (catch Throwable e (log/error e (i18n/trs "Error while appending to serial file.")) (throw e)))) (.write writer (str serial)) (.newLine writer) (.flush writer) (log/trace (i18n/trs "Finish append to serial file. ")))] (ks-file/atomic-write infra-node-serials-path stream-content-fn))))))) (defn stream-content-to-file [^String cert-inventory ^String entry ^BufferedWriter writer] (log/trace (i18n/trs "Begin append to inventory file.")) (let [copy-buffer (CharBuffer/allocate buffer-copy-size)] (try (with-open [^BufferedReader reader (io/reader cert-inventory)] ;; copy all the existing content (loop [read-length (.read reader copy-buffer)] ;; theoretically read can return 0, which means try again (when (<= 0 read-length) (when (pos? read-length) (.write writer (.array copy-buffer) 0 read-length)) (.clear copy-buffer) (recur (.read reader copy-buffer))))) (catch FileNotFoundException _e (log/trace (i18n/trs "Inventory file not found. Assume empty."))) (catch Throwable e (log/error e (i18n/trs "Error while appending to inventory file.")) (throw e)))) (.write writer entry) (.flush writer) (log/trace (i18n/trs "Finish append to inventory file. "))) (schema/defn ^:always-validate write-cert-to-inventory-unlocked! "Writes an entry into Puppet's inventory file for a given certificate. The location of this file is defined by Puppet's 'cert_inventory' setting. The inventory is a text file where each line represents a certificate in the following format: $SN $NB $NA /$S where: * $SN = The serial number of the cert. The serial number is formatted as a hexadecimal number, with a leading 0x, and zero-padded up to four digits, eg. 0x002f. * $NB = The 'not before' field of the cert, as a date/timestamp in UTC. * $NA = The 'not after' field of the cert, as a date/timestamp in UTC. * $S = The distinguished name of the cert's subject." [cert :- Certificate {:keys [cert-inventory] :as settings} :- CaSettings] (let [serial-number (.getSerialNumber cert) formatted-serial-number (->> serial-number (format-serial-number) (str "0x")) not-before (-> cert (.getNotBefore) (format-date-time)) not-after (-> cert (.getNotAfter) (format-date-time)) subject (utils/get-subject-from-x509-certificate cert) cert-name (utils/x500-name->CN subject) entry (str formatted-serial-number " " not-before " " not-after " /" subject "\n")] (log/debug (i18n/trs "Append \"{1}\" to inventory file {0}" cert-inventory entry)) (ks-file/atomic-write cert-inventory (partial stream-content-to-file cert-inventory entry)) (maybe-write-to-infra-serial! serial-number cert-name settings))) (schema/defn ^:always-validate write-cert-to-inventory! "Same behavior as `write-cert-to-inventory-unlocked! but acquires the inventory lock prior to doing the work. Writes an entry into Puppet's inventory file for a given certificate. The location of this file is defined by Puppet's 'cert_inventory' setting. The inventory is a text file where each line represents a certificate in the following format: $SN $NB $NA /$S where: * $SN = The serial number of the cert. The serial number is formatted as a hexadecimal number, with a leading 0x, and zero-padded up to four digits, eg. 0x002f. * $NB = The 'not before' field of the cert, as a date/timestamp in UTC. * $NA = The 'not after' field of the cert, as a date/timestamp in UTC. * $S = The distinguished name of the cert's subject." [cert :- Certificate {:keys [inventory-lock inventory-lock-timeout-seconds] :as settings} :- CaSettings] (common/with-safe-write-lock inventory-lock inventory-lock-descriptor inventory-lock-timeout-seconds (write-cert-to-inventory-unlocked! cert settings))) (schema/defn is-subject-in-inventory-row? :- schema/Bool [cn-subject :- utils/ValidX500Name [_serial _not-before _not-after row-subject] :- [schema/Str]] ;; row subject always starts with a slash, so drop it. (if (some? row-subject) (= (subs row-subject 1) cn-subject) false)) (schema/defn is-not-expired? :- schema/Bool [now :- DateTime [_serial _not-before not-after _row-subject] :- [schema/Str]] (if-let [not-after-date (parse-date-time not-after)] (time/before? now not-after-date) ;; lack of an end date means we can't tell if it is expired or not, so assume it isn't. false)) (schema/defn is-expired? :- schema/Bool [now :- DateTime [_serial _not-before not-after _row-subject] :- [schema/Str]] (if-let [not-after-date (parse-date-time not-after)] (time/after? now not-after-date) ;; lack of an end date means we can't tell if it is expired or not, so assume it isn't. false)) (defn extract-inventory-row-contents [row] (str/split row #" ")) (schema/defn in-cert-inventory-file? :- schema/Bool [{:keys [cert-inventory inventory-lock inventory-lock-timeout-seconds]} :- CaSettings certname :- schema/Str] (common/with-safe-read-lock inventory-lock inventory-lock-descriptor inventory-lock-timeout-seconds (log/trace (i18n/trs "Looking for \"{0}\" in inventory file {1}" certname cert-inventory)) (if (fs/exists? cert-inventory) (with-open [inventory-reader (io/reader cert-inventory)] (let [inventory-rows (map extract-inventory-row-contents (line-seq inventory-reader)) cn-subject (utils/cn certname)] (some? (some (partial is-subject-in-inventory-row? cn-subject) inventory-rows)))) (do (log/debug "Unable to find inventory file {0}" cert-inventory) false)))) (schema/defn base-16-str->biginteger :- BigInteger "Given a base-16 string with a leading 0x, return the result as a BigInteger" [serial :- schema/Str] (BigInteger. ^String (subs serial 2) 16)) (schema/defn expired-inventory-serials :- [BigInteger] [{:keys [cert-inventory inventory-lock inventory-lock-timeout-seconds]} :- CaSettings] (common/with-safe-read-lock inventory-lock inventory-lock-descriptor inventory-lock-timeout-seconds (log/trace (i18n/trs "Extracting expired serials from inventory file {0}" cert-inventory)) (if (fs/exists? cert-inventory) (with-open [inventory-reader (io/reader cert-inventory)] (let [now (time/now)] (doall (->> (line-seq inventory-reader) (map extract-inventory-row-contents) (filter (partial is-expired? now)) (map first) ;; assume serials are base 16 strings (map base-16-str->biginteger))))) (do (log/debug "Unable to find inventory file {0}" cert-inventory) [])))) (schema/defn find-matching-valid-serial-numbers :- [BigInteger] [{:keys [cert-inventory inventory-lock inventory-lock-timeout-seconds]} :- CaSettings certname :- schema/Str] (common/with-safe-read-lock inventory-lock inventory-lock-descriptor inventory-lock-timeout-seconds (log/trace (i18n/trs "Looking for serial numbers for \"{0}\" in inventory file {1}" certname cert-inventory)) (if (fs/exists? cert-inventory) (with-open [inventory-reader (io/reader cert-inventory)] (let [inventory-rows (map extract-inventory-row-contents (line-seq inventory-reader)) cn-subject (utils/cn certname) now (time/now)] (doall (->> inventory-rows (filter (partial is-subject-in-inventory-row? cn-subject)) (filter (partial is-not-expired? now)) ;; serial number is first entry in the array (map first) ;; assume serials are base 16 strings, drop the `0x` as BigInteger won't deal with them. (map base-16-str->biginteger))))) (do (log/debug (i18n/trs "Unable to find inventory file {0}" cert-inventory)) [])))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Initialization (schema/defn validate-settings! "Ensure config values are valid for basic CA behaviors." [settings :- CaSettings] (let [ca-ttl (:ca-ttl settings) certificate-status-access-control (get-in settings [:access-control :certificate-status]) certificate-status-whitelist (:client-whitelist certificate-status-access-control)] (when (> ca-ttl max-ca-ttl) (throw (IllegalStateException. (i18n/trs "Config setting ca_ttl must have a value below {0}" max-ca-ttl)))) (cond (or (false? (:authorization-required certificate-status-access-control)) (not-empty certificate-status-whitelist)) (log/warn (format "%s %s" (i18n/trs "The ''client-whitelist'' and ''authorization-required'' settings in the ''certificate-authority.certificate-status'' section are deprecated and will be removed in a future release.") (i18n/trs "Remove these settings and create an appropriate authorization rule in the /etc/puppetlabs/puppetserver/conf.d/auth.conf file."))) (not (nil? certificate-status-whitelist)) (log/warn (format "%s %s %s" (i18n/trs "The ''client-whitelist'' and ''authorization-required'' settings in the ''certificate-authority.certificate-status'' section are deprecated and will be removed in a future release.") (i18n/trs "Because the ''client-whitelist'' is empty and ''authorization-required'' is set to ''false'', the ''certificate-authority.certificate-status'' settings will be ignored and authorization for the ''certificate_status'' endpoints will be done per the authorization rules in the /etc/puppetlabs/puppetserver/conf.d/auth.conf file.") (i18n/trs "To suppress this warning, remove the ''certificate-authority'' configuration settings.")))))) (schema/defn ensure-cn-as-san :- utils/SSLExtension "Given the SSLExtension for subject alt names and a common name, ensure that the CN is listed in the SAN dns name list." [extension :- utils/SSLExtension cn :- schema/Str] (if (some #(= cn %) (get-in extension [:value :dns-name])) extension (update-in extension [:value :dns-name] conj cn))) (schema/defn is-san? [extension] (= utils/subject-alt-name-oid (:oid extension))) (schema/defn ensure-ext-list-has-cn-san "Given a list of extensions to be signed onto a certificate, ensure that a CN is provided as a subject alternative name; if no subject alternative name extension is found, generate a new extension and add it to the list with the CN supplied" [cn :- schema/Str extensions :- (schema/pred utils/extension-list?)] (let [[san] (filter is-san? extensions) sans-san (filter (complement is-san?) extensions) new-san (if san (ensure-cn-as-san san cn) (utils/subject-dns-alt-names [cn] false))] (conj sans-san new-san))) (schema/defn create-ca-extensions :- (schema/pred utils/extension-list?) "Create a list of extensions to be added to the CA certificate." [issuer-public-key :- (schema/pred utils/public-key?) ca-public-key :- (schema/pred utils/public-key?)] (vec (cons (utils/netscape-comment netscape-comment-value) (utils/create-ca-extensions issuer-public-key ca-public-key)))) (schema/defn extract-active-infra-serials :- [BigInteger] "Read the infra nodes file to determine which nodes are infrastructure nodes. For each node, check the inventory file for any serial numbers for that node, Also check the filesystem for a signed cert for that node. Return a sorted unique set of serial numbers for nodes in the infra file" [{:keys [infra-nodes-path signeddir] :as settings} :- CaSettings] (if (fs/exists? infra-nodes-path) (with-open [infra-nodes-reader (io/reader infra-nodes-path)] (let [infra-nodes (read-infra-nodes infra-nodes-reader)] (loop [local-infra-nodes infra-nodes result []] (if-let [infra-node (first local-infra-nodes)] (let [augmented-results (concat result (find-matching-valid-serial-numbers settings infra-node)) cert-path (path-to-cert signeddir infra-node)] (if (fs/exists? cert-path) (let [serial (-> cert-path utils/pem->cert utils/get-serial)] (recur (rest local-infra-nodes) (conj augmented-results serial))) (do (log/warn (i18n/trs "Failed to find certificate for Puppet Infrastructure Node: {0}" infra-node)) (recur (rest local-infra-nodes) augmented-results)))) ;; ensure they are unique and ordered so the end result is stable (sort (set result)))))) [])) (schema/defn write-infra-serials-to-writer [writer :- BufferedWriter settings :- CaSettings] (let [infra-serials (extract-active-infra-serials settings)] (doseq [infra-serial infra-serials] (.write writer (str infra-serial)) (.newLine writer)))) (schema/defn generate-infra-serials! "Given a list of infra nodes it will create a file containing serial numbers of their certificates (listed on separate lines). It is expected have at least one entry (MoM)" [{:keys [infra-node-serials-path] :as settings} :- CaSettings] (ks-file/atomic-write infra-node-serials-path #(write-infra-serials-to-writer % settings) public-key-perms)) (defn symlink-cadir "Symlinks the new cadir that ends in 'puppetserver/ca' to the old cadir of 'puppet/ssl/ca' for backwards compatibility. Will delete the old cadir if it exists. Does nothing if set to a custom value." [cadir] (let [[_ base] (re-matches #"(.*)puppetserver/ca" cadir) old-cadir (str base "puppet/ssl/ca")] (when base (when (fs/exists? old-cadir) (fs/delete-dir old-cadir)) (fs/sym-link old-cadir cadir) ;; Ensure the symlink has the same ownership as the actual cadir. ;; Symlink permissions are ignored in favor of the target's permissions, ;; so we don't have to change those. (let [old-cadir-path (ks-file/str->path old-cadir) cadir-path (ks-file/str->path cadir) owner (Files/getOwner cadir-path ks-file/nofollow-links) group (Files/getAttribute cadir-path "posix:group" ks-file/nofollow-links)] (Files/setOwner old-cadir-path owner) (Files/setAttribute old-cadir-path "posix:group" group ks-file/nofollow-links))))) (schema/defn generate-ssl-files! "Given the CA settings, generate and write to disk all of the necessary SSL files for the CA. Any existing files will be replaced." [ca-settings :- CaSettings] (log/debug (str (i18n/trs "Initializing SSL for the CA; settings:") "\n" (ks/pprint-to-string ca-settings))) (create-parent-directories! (vals (settings->cadir-paths ca-settings))) (-> ca-settings :csrdir fs/file ks/mkdirs!) (-> ca-settings :signeddir fs/file ks/mkdirs!) (initialize-serial-file! ca-settings) (-> ca-settings :infra-nodes-path fs/file fs/create) (generate-infra-serials! ca-settings) (let [keypair (utils/generate-key-pair (:keylength ca-settings)) public-key (utils/get-public-key keypair) private-key (utils/get-private-key keypair) x500-name (utils/cn (:ca-name ca-settings)) validity (cert-validity-dates (:ca-ttl ca-settings)) serial (next-serial-number! ca-settings) ;; Since this is a self-signed cert, the issuer key and the ;; key for this cert are the same ca-exts (create-ca-extensions public-key public-key) cacert (utils/sign-certificate x500-name private-key serial (:not-before validity) (:not-after validity) x500-name public-key ca-exts) cacrl (utils/generate-crl (.getIssuerX500Principal cacert) private-key public-key) infra-crl (utils/generate-crl (.getIssuerX500Principal cacert) private-key public-key)] (write-cert-to-inventory! cacert ca-settings) (write-public-key public-key (:capub ca-settings)) (write-private-key private-key (:cakey ca-settings)) (write-cert cacert (:cacert ca-settings)) (write-crl cacrl (:cacrl ca-settings)) (write-crl infra-crl (:infra-crl-path ca-settings)) (symlink-cadir (:cadir ca-settings)))) (schema/defn split-hostnames :- (schema/maybe [schema/Str]) "Given a comma-separated list of hostnames, return a list of the individual dns alt names with all surrounding whitespace removed. If hostnames is empty or nil, then nil is returned." [hostnames :- (schema/maybe schema/Str)] (let [hostnames (str/trim (or hostnames ""))] (when-not (empty? hostnames) (map str/trim (str/split hostnames #","))))) (schema/defn create-subject-alt-names-ext :- Extension "Given a hostname and a comma-separated list of DNS (and possibly IP) alt names, create a Subject Alternative Names extension. If there are no alt names provided then defaults will be used." [host-name :- schema/Str alt-names :- schema/Str] (let [split-alt-names (split-hostnames alt-names) default-alt-names ["puppet"] alt-names-list (reduce (fn [acc alt-name] (if (str/starts-with? alt-name "IP:") (update acc :ip conj (str/replace alt-name #"^IP:" "")) (update acc :dns-name conj (str/replace alt-name #"^DNS:" "")))) {:ip [] :dns-name []} split-alt-names)] (if (and (empty? (get alt-names-list :dns-name)) (empty? (get alt-names-list :ip))) (utils/subject-alt-names {:dns-name (conj default-alt-names host-name)} false) (utils/subject-alt-names (update alt-names-list :dns-name conj host-name) false)))) (def pattern-match-dot #"\.") (def pattern-starts-with-alphanumeric-or-underscore #"^[\p{Alnum}_].*") (def pattern-matches-alphanumeric-with-symbols-string #"^[\p{Alnum}\-_]*[\p{Alnum}_]$") (schema/defn validate-subject! "Validate the CSR or certificate's subject name. The subject name must: * match the hostname specified in the HTTP request (the `subject` parameter) * not contain any non-printable characters or slashes * not contain any capital letters * not contain the wildcard character (*)" [hostname :- schema/Str subject :- schema/Str] (log/debug (i18n/trs "Checking \"{0}\" for validity" subject)) (when-not (= hostname subject) ;; see https://github.com/puppetlabs/clj-i18n/blob/main/README.md#single-quotes-in-messages for reasoning with double quote (log/info (i18n/tru "Rejecting subject \"{0}\" because it doesn''t match hostname \"{1}\"" subject hostname)) (sling/throw+ {:kind :hostname-mismatch :msg (i18n/tru "Instance name \"{0}\" does not match requested key \"{1}\"" subject hostname)})) (when (contains-uppercase? hostname) (log/info (i18n/tru "Rejecting subject \"{0}\" because all characters must be lowercase" subject)) (sling/throw+ {:kind :invalid-subject-name :msg (i18n/tru "Certificate names must be lower case.")})) (when (.contains subject "*") (sling/throw+ {:kind :invalid-subject-name :msg (i18n/tru "Subject contains a wildcard, which is not allowed: {0}" subject)})) (when (str/ends-with? subject "-") (log/info (i18n/tru "Rejecting subject \"{0}\" as it ends with an invalid character" subject)) (sling/throw+ {:kind :invalid-subject-name :msg (i18n/tru "Subject hostname format is invalid")})) (let [segments (str/split subject pattern-match-dot)] (when-not (re-matches pattern-starts-with-alphanumeric-or-underscore (first segments)) (log/info (i18n/tru "Rejecting subject \"{0}\" as it starts with an invalid character" subject)) (sling/throw+ {:kind :invalid-subject-name :msg (i18n/tru "Subject hostname format is invalid")})) (when-not (every? #(re-matches pattern-matches-alphanumeric-with-symbols-string %) segments) (log/info (i18n/tru "Rejecting subject \"{0}\" because it contains invalid characters" subject)) (sling/throw+ {:kind :invalid-subject-name :msg (i18n/tru "Subject hostname format is invalid")})))) (schema/defn allowed-extension? "A predicate that answers if an extension is allowed or not. This logic is copied out of the ruby CA." [extension :- Extension] (let [oid (:oid extension)] (or (= subject-alt-names-oid oid) (and (utils/subtree-of? ppAuthCertExt oid) (not (= cli-auth-oid oid))) (utils/subtree-of? ppRegCertExt oid) (utils/subtree-of? ppPrivCertExt oid)))) (schema/defn validate-extensions! "Throws an error if the extensions list contains any invalid extensions, according to `allowed-extension?`" [extensions :- (schema/pred utils/extension-list?)] (let [bad-extensions (remove allowed-extension? extensions)] (when-not (empty? bad-extensions) (let [bad-extension-oids (map :oid bad-extensions)] (sling/throw+ {:kind :disallowed-extension :msg (i18n/tru "Found extensions that are not permitted: {0}" (str/join ", " bad-extension-oids))}))))) (schema/defn validate-subject-alt-names! "Validate that the provided Subject Alternative Names extension is valid for a cert signed by this CA. This entails: * Only DNS and IP alternative names are allowed, no other types * Each DNS name does not contain a wildcard character (*)" [{value :value} :- Extension] (let [name-types (keys value) dns-names (:dns-name value)] (when-not (every? #{:dns-name :ip} name-types) (sling/throw+ {:kind :invalid-alt-name :msg (i18n/tru "Only DNS and IP names are allowed in the Subject Alternative Names extension")})) (doseq [dns-name dns-names] (when (.contains dns-name "*") (sling/throw+ {:kind :invalid-alt-name :msg (i18n/tru "Cert subjectAltName contains a wildcard, which is not allowed: {0}" dns-name)}))))) (schema/defn create-csr-attrs-exts :- (schema/maybe (schema/pred utils/extension-list?)) "Parse the CSR attributes yaml file at the given path and create a list of certificate extensions from the `extensions_requests` section." [csr-attributes-file :- schema/Str] (if (fs/file? csr-attributes-file) (let [csr-attrs (common/parse-yaml (slurp csr-attributes-file)) ext-req (:extension_requests csr-attrs)] (map (fn [[oid value]] {:oid (or (get puppet-short-names oid) (name oid)) :critical false :value (str value)}) ext-req)) (log/debug (i18n/trs "No CSR Attributes configuration file found at {0}, CSR Attributes will not be loaded" csr-attributes-file)))) (schema/defn create-master-extensions :- (schema/pred utils/extension-list?) "Create a list of extensions to be added to the master certificate." [master-certname :- schema/Str master-public-key :- (schema/pred utils/public-key?) ca-cert :- Certificate {:keys [dns-alt-names csr-attributes]} :- MasterSettings] (let [alt-names-ext (create-subject-alt-names-ext master-certname dns-alt-names) csr-attr-exts (create-csr-attrs-exts csr-attributes) base-ext-list [(utils/netscape-comment netscape-comment-value) (utils/authority-key-identifier-options ca-cert) (utils/basic-constraints-for-non-ca true) (utils/ext-key-usages [ssl-server-cert ssl-client-cert] true) (utils/key-usage #{:key-encipherment :digital-signature} true) (utils/subject-key-identifier master-public-key false) {:oid cli-auth-oid :critical false :value "true"}]] (validate-subject-alt-names! alt-names-ext) (when csr-attr-exts (validate-extensions! csr-attr-exts)) (remove nil? (concat base-ext-list [alt-names-ext] csr-attr-exts)))) (schema/defn generate-master-ssl-keys!* :- (schema/pred utils/public-key?) "Generate and store ssl public and private keys for the master to disk. Returns the public key." [{:keys [hostprivkey hostpubkey keylength]} :- MasterSettings] (log/debug (i18n/trs "Generating public and private keys for master cert")) (let [keypair (utils/generate-key-pair keylength) public-key (utils/get-public-key keypair) private-key (utils/get-private-key keypair)] (write-public-key public-key hostpubkey) (write-private-key private-key hostprivkey) public-key)) (schema/defn generate-master-ssl-keys! :- (schema/pred utils/public-key?) "Generate and store ssl public and private keys for the master to disk. If the files are both already present, new ones will not be generated to replace them. Returns the public key." [{:keys [hostprivkey hostpubkey] :as settings} :- MasterSettings] (cond (and (fs/exists? hostprivkey) (fs/exists? hostpubkey)) (do (log/debug (i18n/trs "Using keys found on disk to generate master cert")) (utils/pem->public-key hostpubkey)) (and (not (fs/exists? hostprivkey)) (not (fs/exists? hostpubkey))) (generate-master-ssl-keys!* settings) (fs/exists? hostpubkey) (throw (IllegalStateException. ^String (i18n/trs "Found master public key ''{0}'' but master private key ''{1}'' is missing" hostpubkey hostprivkey))) :else (throw (IllegalStateException. ^String (i18n/trs "Found master private key ''{0}'' but master public key ''{1}'' is missing" hostprivkey hostpubkey))))) (schema/defn generate-master-ssl-files! "Given master configuration settings, certname, and CA settings, generate and write to disk all of the necessary SSL files for the master. Any existing files will be replaced." [settings :- MasterSettings certname :- schema/Str ca-settings :- CaSettings] (log/debug (format "%s\n%s" (i18n/trs "Initializing SSL for the Master; settings:") (ks/pprint-to-string settings))) (create-parent-directories! (vals (settings->ssldir-paths settings))) (ks-file/set-perms (:privatekeydir settings) private-key-dir-perms) (-> settings :certdir fs/file ks/mkdirs!) (-> settings :requestdir fs/file ks/mkdirs!) (let [ca-cert (utils/pem->ca-cert (:cacert ca-settings) (:cakey ca-settings)) ca-private-key (utils/pem->private-key (:cakey ca-settings)) next-serial (next-serial-number! ca-settings) public-key (generate-master-ssl-keys! settings) extensions (create-master-extensions certname public-key ca-cert settings) x500-name (utils/cn certname) validity (cert-validity-dates (:ca-ttl ca-settings)) hostcert (utils/sign-certificate (utils/get-subject-from-x509-certificate ca-cert) ca-private-key next-serial (:not-before validity) (:not-after validity) x500-name public-key extensions)] (write-cert-to-inventory! hostcert ca-settings) (write-cert hostcert (:hostcert settings)) (write-cert hostcert (path-to-cert (:signeddir ca-settings) certname)))) (schema/defn ^:always-validate initialize-master-ssl! "Given configuration settings, certname, and CA settings, ensure all necessary SSL files exist on disk by regenerating all of them if any are found to be missing." [{:keys [hostprivkey hostcert] :as settings} :- MasterSettings certname :- schema/Str ca-settings :- CaSettings] (cond (and (fs/exists? hostcert) (fs/exists? hostprivkey)) (log/info (i18n/trs "Master already initialized for SSL")) (fs/exists? hostcert) (throw (IllegalStateException. ^String (i18n/trs "Found master cert ''{0}'' but master private key ''{1}'' is missing" hostcert hostprivkey))) :else (generate-master-ssl-files! settings certname ca-settings))) (schema/defn ^:always-validate retrieve-ca-cert! "Ensure a local copy of the CA cert is available on disk. cacert is the base CA cert file to copy from and localcacert is where the CA cert file should be copied to." [cacert :- schema/Str localcacert :- schema/Str] (if (and (fs/exists? cacert) (not (fs/exists? localcacert))) (do (ks/mkdirs! (fs/parent localcacert)) (fs/copy cacert localcacert)) (when-not (fs/exists? localcacert) (throw (IllegalStateException. ^String (i18n/trs ":localcacert ({0}) could not be found and no file at :cacert ({1}) to copy it from" localcacert cacert)))))) (schema/defn ^:always-validate retrieve-ca-crl! "Ensure a local copy of the CA CRL, if one exists, is available on disk. cacrl is the base CRL file to copy from and localcacrl is where the CRL file should be copied to." [cacrl :- schema/Str localcacrl :- schema/Str] (when (not= cacrl localcacrl) (let [max-attempts 25] (when (fs/exists? cacrl) (ks/mkdirs! (fs/parent localcacrl)) ;; Make up to 'max-attempts' tries to copy the cacrl file to the ;; localcacrl file. The content of the cacrl file is read into memory ;; and parsed for valid CRL pem content during each attempt. The content ;; in memory is written to the localcacrl file only if it is valid. This ;; validation is done to protect against a partially written (which could ;; happen if an asynchronous revocation is in progress) or currupt cacrl ;; file being copied. (loop [attempts-left max-attempts] (let [cacrl-as-string (slurp cacrl)] (when-let [write-exception (write-local-cacrl! localcacrl cacrl-as-string)] (if (zero? attempts-left) (log/error (format "%s\n%s\n%s" (i18n/trs "Unable to synchronize crl file {0} to {1}: {2}" cacrl localcacrl (.getMessage write-exception)) (i18n/trs "Recent changes to the CRL may not have taken effect.") (i18n/trs "To load the updated CRL, reload or restart the Puppet Server service."))) (do (Thread/sleep 100) (recur (dec attempts-left))))))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Autosign (schema/defn glob-matches? :- schema/Bool "Test if a subject matches the domain-name glob from the autosign whitelist. The glob is expected to start with a '*' and be in a form like `*.foo.bar`. The subject is expected to contain only lowercase characters and be in a form like `agent.foo.bar`. Capitalization in the glob will be ignored. Examples: (glob-matches? *.foo.bar agent.foo.bar) => true (glob-matches? *.baz baz) => true (glob-matches? *.QUX 0.1.qux) => true" [glob :- schema/Str subject :- schema/Str] (letfn [(munge [name] (-> name str/lower-case (str/split #"\.") reverse)) (seq-starts-with? [a b] (= b (take (count b) a)))] (seq-starts-with? (munge subject) (butlast (munge glob))))) (schema/defn line-matches? :- schema/Bool "Test if the subject matches the line from the autosign whitelist. The line is expected to be an exact certname or a domain-name glob. A single line with the character '*' will match all subjects. If the line contains invalid characters it will be logged and false will be returned." [whitelist :- schema/Str subject :- schema/Str line :- schema/Str] (if (or (.contains line "#") (.contains line " ")) (do (log/error (i18n/trs "Invalid pattern ''{0}'' found in {1}" line whitelist)) false) (if (= line "*") true (if (.startsWith line "*") (glob-matches? line subject) (= line subject))))) (schema/defn whitelist-matches? :- schema/Bool "Test if the whitelist file contains an entry that matches the subject. Each line of the file is expected to contain a single entry, either as an exact certname or a domain-name glob, and will be evaluated verbatim. All blank lines and comment lines (starting with '#') will be ignored. If an invalid pattern is encountered, it will be logged and ignored." [whitelist :- schema/Str subject :- schema/Str] (with-open [r (io/reader whitelist)] (not (nil? (some (partial line-matches? whitelist subject) (remove #(or (.startsWith % "#") (str/blank? %)) (line-seq r))))))) (schema/defn execute-autosign-command! :- shell-utils/ExecutionResult "Execute the autosign script and return a map containing the standard-out, standard-err, and exit code. The subject will be passed in as input, and the CSR stream will be provided on standard-in. The ruby-load-path will be prepended to the RUBYLIB found in the environment, and is intended to make the Puppet and Facter Ruby libraries available to the autosign script. All output (stdout & stderr) will be logged at the debug level. Warnings are issued for nonzero exit code or if stderr is generated by the autosign script." [executable :- schema/Str subject :- schema/Str csr-stream :- InputStream ruby-load-path :- [schema/Str] gem-path :- schema/Str] (log/debug (i18n/trs "Executing ''{0} {1}''" executable subject)) (let [env (into {} (System/getenv)) rubylib (->> (if-let [lib (get env "RUBYLIB")] (cons lib ruby-load-path) ruby-load-path) (map ks/absolute-path) (str/join (System/getProperty "path.separator"))) gempath (if-let [gems (get env "GEM_PATH")] (str gems (System/getProperty "path.separator") gem-path) gem-path) results (shell-utils/execute-command executable {:args [subject] :in csr-stream :env (merge env {"RUBYLIB" rubylib "GEM_PATH" gempath})})] (log/debug (i18n/trs "Autosign command ''{0} {1}'' exit status: {2}" executable subject (:exit-code results))) (log/debug (i18n/trs "Autosign command ''{0} {1}'' output on stdout: {2}" executable subject (:stdout results))) (when-not (empty? (:stderr results)) (log/warn (i18n/trs "Autosign command ''{0} {1}'' generated output to stderr: {2}" executable subject (:stderr results)))) (when-not (zero? (:exit-code results)) (log/warn (i18n/trs "Autosign command ''{0}'' rejected certificate ''{1}'' because the exit code was {2}, not zero" executable subject (:exit-code results)))) results)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (schema/defn ^:always-validate config->ca-settings :- CaSettings "Given the configuration map from the Puppet Server config service return a map with of all the CA settings." [{:keys [puppetserver jruby-puppet certificate-authority authorization]}] (let [merged (-> (select-keys puppetserver (keys CaSettings)) (merge (select-keys certificate-authority (keys CaSettings))) (initialize-ca-config))] (assoc merged :ruby-load-path (:ruby-load-path jruby-puppet) :allow-auto-renewal (:allow-auto-renewal merged) :auto-renewal-cert-ttl (duration-str->sec (:auto-renewal-cert-ttl merged)) :ca-ttl (get-ca-ttl puppetserver certificate-authority) :allow-header-cert-info (get authorization :allow-header-cert-info false) :gem-path (str/join (System/getProperty "path.separator") (:gem-path jruby-puppet)) :access-control (select-keys certificate-authority [:certificate-status]) :serial-lock (new ReentrantReadWriteLock) :crl-lock (new ReentrantReadWriteLock) :inventory-lock (new ReentrantReadWriteLock)))) (schema/defn ^:always-validate config->master-settings :- MasterSettings "Given the configuration map from the Puppet Server config service return a map with of all the master settings." [{:keys [puppetserver]}] (select-keys puppetserver (keys MasterSettings))) (schema/defn ^:always-validate get-certificate-path :- (schema/maybe schema/Str) "Given a subject name and paths to the CA certificate and path to the certificate directory return the path to the subject's certificate as a string, or nil if not found. If the subject is 'ca', then use the `cacert` path instead." [subject :- schema/Str cacert :- schema/Str signeddir :- schema/Str] (let [cert-path (if (= "ca" subject) cacert (path-to-cert signeddir subject))] (when (fs/exists? cert-path) cert-path))) (schema/defn ^:always-validate get-certificate :- (schema/maybe schema/Str) "Given a subject name and path to the certificate directory and the CA certificate, return the subject's certificate as a string, or nil if not found. If the subject is 'ca', then use the `cacert` path instead." [subject :- schema/Str cacert :- schema/Str signeddir :- schema/Str] (when-let [cert-path (get-certificate-path subject cacert signeddir)] (slurp cert-path))) (schema/defn ^:always-validate get-certificate-request :- (schema/maybe schema/Str) "Given a subject name, return their certificate request as a string, or nil if not found. Looks for certificate requests in `csrdir`." [subject :- schema/Str csrdir :- schema/Str] (let [cert-request-path (path-to-cert-request csrdir subject)] (when (fs/exists? cert-request-path) (slurp cert-request-path)))) (schema/defn ^:always-validate get-paths-to-all-certificate-requests :- [Path] "Given a csr directory, return Path entries to all the files that could be CSRs" [csrdir :- schema/Str] (let [csr-dir-as-path (Paths/get csrdir (into-array String []))] (if (Files/isDirectory csr-dir-as-path ks-file/nofollow-links) (with-open [dir-stream (Files/newDirectoryStream csr-dir-as-path "*.pem")] (doall (iterator-seq (.iterator dir-stream)))) (do (log/error (i18n/trs "Attempting to use {0} as CSR directory, but it is not a directory." csrdir)) [])))) (schema/defn ^:always-validate autosign-csr? :- schema/Bool "Return true if the CSR should be automatically signed given Puppet's autosign setting, and false otherwise." ([autosign :- AutoSignInput subject :- schema/Str csr-stream :- InputStream] (autosign-csr? autosign subject csr-stream [] "")) ([autosign :- AutoSignInput subject :- schema/Str csr-stream :- InputStream ruby-load-path :- [schema/Str] gem-path :- schema/Str] (if (ks/boolean? autosign) autosign (if (fs/exists? autosign) (if (fs/executable? autosign) (let [command-result (execute-autosign-command! autosign subject csr-stream ruby-load-path gem-path) succeed? (zero? (:exit-code command-result))] (when-not succeed? (log/debug (i18n/trs "Autosign executable failed. Result: {0} " (pr-str command-result)))) succeed?) (whitelist-matches? autosign subject)) false)))) (schema/defn create-agent-extensions :- (schema/pred utils/extension-list?) "Given a certificate signing request, generate a list of extensions that should be signed onto the certificate. This includes a base set of standard extensions in addition to any valid extensions found on the signing request." [csr :- CertificateRequest cacert :- Certificate] (let [subj-pub-key (utils/get-public-key csr) csr-ext-list (utils/get-extensions csr) base-ext-list [(utils/netscape-comment netscape-comment-value) (utils/authority-key-identifier-options cacert) (utils/basic-constraints-for-non-ca true) (utils/ext-key-usages [ssl-server-cert ssl-client-cert] true) (utils/key-usage #{:key-encipherment :digital-signature} true) (utils/subject-key-identifier subj-pub-key false)] subject (get-csr-subject csr) combined-list (vec (concat base-ext-list csr-ext-list))] (ensure-ext-list-has-cn-san subject combined-list))) (defn report-cert-event "Log message and report to the activity service if available about cert activties, ie signing and revoking." [report-activity message subject certnames ip-address activity-type] (let [commit {:service {:id "puppet-ca"} :subject {:id subject :name subject :type "users"} :objects (mapv (fn [cert] {:type "node" :id cert :name cert}) certnames) :events [{:type (str activity-type "-certificate") :what "node" :description (str "certificate_successfully_" activity-type) :message message}] :ip_address ip-address}] (log/info message) (report-activity {:commit commit}))) (defn generate-cert-message-from-request "Extract params from request and create successful cert signing message. Returns message, subject, certname and ip address" [request subjects activity-type] (let [auth-name (get-in request [:authorization :name]) rbac-user (get-in request [:rbac-subject :login]) ip-address (:remote-addr request) signee (first (remove clojure.string/blank? [rbac-user auth-name "CA"]))] [(i18n/trsn "Entity {1} {2} 1 certificate: {3}." "Entity {1} {2} {0} certificates: {3}." (count subjects) signee activity-type (str/join ", " subjects)) signee subjects ip-address])) (defn create-report-activity-fn [report-activity request] (fn [subjects activity-type] (let [[msg signee certnames ip] (generate-cert-message-from-request request subjects activity-type)] (report-cert-event report-activity msg signee certnames ip activity-type)))) (schema/defn supports-auto-renewal? :- schema/Bool "Given a csr, determine if the requester is capable of supporting auto-renewal by looking for a specific attribute" [csr] (if-let [auto-renew-attribute (first (filter #(= pp_auth_auto_renew-attribute (:oid %)) (get-csr-attributes csr)))] (do (log/debug (i18n/trs "Found auto-renew-attribute {0}" (first (:values auto-renew-attribute)))) ;; the values is a sequence of results, assume the first one is correct. (= "true" (first (:values auto-renew-attribute)))) false)) (schema/defn ^:always-validate delete-certificate-request! :- OutcomeInfo "Delete pending certificate requests for subject" [{:keys [csrdir]} :- CaSettings subject :- schema/Str] (let [csr-path (path-to-cert-request csrdir subject)] (if (fs/exists? csr-path) (if (fs/delete csr-path) (let [msg (i18n/trs "Deleted certificate request for {0} at {1}" subject csr-path)] (log/debug msg) {:outcome :success :message msg}) (let [msg (i18n/trs "Path {0} exists but could not be deleted" csr-path)] (log/error msg) {:outcome :error :message msg})) (let [msg (i18n/trs "No certificate request for {0} at expected path {1}" subject csr-path)] (log/warn msg) {:outcome :not-found :message msg})))) (schema/defn ^:always-validate autosign-certificate-request! "Given a subject name, their certificate request, and the CA settings from Puppet, auto-sign the request and write the certificate to disk." [subject :- schema/Str csr :- CertificateRequest {:keys [cacert cakey signeddir ca-ttl allow-auto-renewal auto-renewal-cert-ttl] :as ca-settings} :- CaSettings report-activity] (let [renewal-ttl (if (and allow-auto-renewal (supports-auto-renewal? csr)) auto-renewal-cert-ttl ca-ttl) _ (log/debug (i18n/trs "Calculating validity dates for {0} from ttl of {1} " subject renewal-ttl)) validity (cert-validity-dates renewal-ttl) ;; if part of a CA bundle, the intermediate CA will be first in the chain cacert (utils/pem->ca-cert cacert cakey) signed-cert (utils/sign-certificate (utils/get-subject-from-x509-certificate cacert) (utils/pem->private-key cakey) (next-serial-number! ca-settings) (:not-before validity) (:not-after validity) (utils/cn subject) (utils/get-public-key csr) (create-agent-extensions csr cacert))] (common/record-action {:type :add :targets [subject] :meta {:type :certificate}}) (write-cert-to-inventory! signed-cert ca-settings) (write-cert signed-cert (path-to-cert signeddir subject)) (delete-certificate-request! ca-settings subject) (report-activity [subject] "signed"))) (schema/defn ^:always-validate save-certificate-request! "Write the subject's certificate request to disk under the CSR directory." [subject :- schema/Str csr :- CertificateRequest csrdir :- schema/Str] (let [csr-path (path-to-cert-request csrdir subject)] (log/debug (i18n/trs "Saving CSR to ''{0}''" csr-path)) (write-csr csr csr-path))) (schema/defn is-revoked? :- schema/Bool [cert :- X509Certificate {:keys [cacert cacrl crl-lock crl-lock-timeout-seconds cakey]} :- CaSettings] (utils/revoked? (common/with-safe-read-lock crl-lock crl-lock-descriptor crl-lock-timeout-seconds (utils/pem->ca-crl cacrl (utils/pem->ca-cert cacert cakey))) cert)) (schema/defn validate-duplicate-cert-policy! "Throw a slingshot exception if allow-duplicate-certs is false, and we already have a certificate or CSR for the subject. The exception map will look like: {:kind :duplicate-cert :msg }" [csr :- CertificateRequest {:keys [allow-duplicate-certs csrdir signeddir] :as settings} :- CaSettings] (let [subject (get-csr-subject csr) cert (path-to-cert signeddir subject) existing-cert? (fs/exists? cert) existing-csr? (fs/exists? (path-to-cert-request csrdir subject))] (when (or existing-cert? existing-csr?) (let [status (if existing-cert? (if (is-revoked? (utils/pem->cert cert) settings) "revoked" "signed") "requested")] (if allow-duplicate-certs (log/info (i18n/trs "{0} already has a {1} certificate; new certificate will overwrite it" subject status)) (sling/throw+ {:kind :duplicate-cert :msg (i18n/tru "{0} already has a {1} certificate; ignoring certificate request" subject status)})))))) (schema/defn validate-csr-signature! "Throws an exception when the CSR's signature is invalid. See `signature-valid?` for more detail." [certificate-request :- CertificateRequest] (when-not (utils/signature-valid? certificate-request) (sling/throw+ {:kind :invalid-signature :msg (i18n/tru "CSR contains a public key that does not correspond to the signing key")}))) (schema/defn ensure-no-authorization-extensions! "Throws an exception if the CSR contains authorization exceptions AND the user has chosen to disallow authorization-extensions. This ensures that certificates with authentication extensions can only be signed intentionally." [csr :- CertificateRequest allow-authorization-extensions :- schema/Bool] (let [extensions (utils/get-extensions csr)] (doseq [extension extensions] (when (utils/subtree-of? ppAuthCertExt (:oid extension)) (when (false? allow-authorization-extensions) (sling/throw+ {:kind :disallowed-extension :msg (format "%s %s %s" (i18n/trs "CSR ''{0}'' contains an authorization extension, which is disallowed." (get-csr-subject csr)) (i18n/trs "To allow authorization extensions, set allow-authorization-extensions to true in your ca.conf file.") (i18n/trs "Then restart the puppetserver and try signing this certificate again."))})))))) (schema/defn ensure-subject-alt-names-allowed! "Throws an exception if the CSR contains subject-alt-names AND the user has chosen to disallow subject-alt-names. Subject alt names can be allowed by setting allow-subject-alt-names to true in the ca.conf file. Always allows a single subject alt name that matches the CSR subject, which may be present to comply with RFC 2818 (see SERVER-2338)." [csr :- CertificateRequest allow-subject-alt-names :- schema/Bool] (when-let [subject-alt-names (not-empty (subject-alt-names csr))] (when (false? allow-subject-alt-names) (let [subject (get-csr-subject csr) cn-alt-name (str "DNS:" subject)] (if (and (= 1 (count subject-alt-names)) (= (first subject-alt-names) cn-alt-name)) (log/debug "Allowing subject alt name that matches CSR subject.") (let [disallowed-alt-names (filter #(not (= cn-alt-name %)) subject-alt-names)] (sling/throw+ {:kind :disallowed-extension :msg (format "%s %s %s" (i18n/tru "CSR ''{0}'' contains extra subject alternative names ({1}), which are disallowed." subject (str/join ", " disallowed-alt-names)) (i18n/tru "To allow subject alternative names, set allow-subject-alt-names to true in your ca.conf file.") (i18n/tru "Then restart the puppetserver and try signing this certificate again."))}))))))) (schema/defn ^:always-validate process-csr-submission! "Given a CSR for a subject (typically from the HTTP endpoint), perform policy checks and sign or save the CSR (based on autosign). Throws a slingshot exception if the CSR is invalid." [subject :- schema/Str certificate-request :- InputStream {:keys [autosign csrdir ruby-load-path gem-path allow-subject-alt-names allow-authorization-extensions] :as settings} :- CaSettings report-activity] (with-open [byte-stream (-> certificate-request input-stream->byte-array ByteArrayInputStream.)] (let [csr (utils/pem->csr byte-stream) csr-stream (doto byte-stream .reset)] (validate-duplicate-cert-policy! csr settings) (validate-subject! subject (get-csr-subject csr)) (save-certificate-request! subject csr csrdir) (common/record-action {:type :info :targets [subject] :meta {:what :csr :action :submit}}) (when (autosign-csr? autosign subject csr-stream ruby-load-path gem-path) (ensure-subject-alt-names-allowed! csr allow-subject-alt-names) (ensure-no-authorization-extensions! csr allow-authorization-extensions) (validate-extensions! (utils/get-extensions csr)) (validate-csr-signature! csr) (autosign-certificate-request! subject csr settings report-activity))))) (schema/defn ^:always-validate get-certificate-revocation-list :- schema/Str "Given the value of the 'cacrl' setting from Puppet, return the CRL from the .pem file on disk." [cacrl :- schema/Str lock :- ReentrantReadWriteLock lock-descriptor :- schema/Str lock-timeout :- PosInt] (common/with-safe-read-lock lock lock-descriptor lock-timeout (slurp cacrl))) (schema/defn ^:always-validate get-file-last-modified :- DateTime "Given a path to a file, return a Joda DateTime instance of when the file was last modified. an optional lock, description, and timeout may be passed to serialize access to files." ([path :- schema/Str] (let [last-modified-milliseconds (.lastModified (io/file path))] (time-coerce/from-long last-modified-milliseconds))) ([path :- schema/Str lock :- ReentrantReadWriteLock lock-descriptor :- schema/Str lock-timeout :- PosInt] (common/with-safe-read-lock lock lock-descriptor lock-timeout (let [last-modified-milliseconds (.lastModified (io/file path))] (time-coerce/from-long last-modified-milliseconds))))) (schema/defn ^:always-validate reject-delta-crl [crl :- CertificateRevocationList] (when (utils/delta-crl? crl) (throw (IllegalArgumentException. ^String (i18n/trs "Cannot support delta CRL."))))) (schema/defn ^:always-validate validate-certs-and-crls "Given a list of certificates and a list of CRLs, validate the certificate chain, i.e. ensure that none of the certs have been revoked by checking the appropriate CRL, which must be present and currently valid. Delta CRLs are not supported. Returns nil if successful." [cert-chain :- [Certificate] crl-chain :- [CertificateRevocationList]] (doseq [crl crl-chain] (reject-delta-crl crl)) (try (utils/validate-cert-chain cert-chain crl-chain) ;; currently not distinguishing between invalid CRLs ;; and a revoked cert in the CA chain (catch CertPathValidatorException e (throw (IllegalArgumentException. ^String (i18n/trs "Invalid certs and/or CRLs: {0}" (.getMessage e))))))) (schema/defn ^:always-validate get-newest-crl :- CertificateRevocationList "Determine the newest CRL by looking for the highest CRL Number. This assumes all given CRLs have the same issuer. Fails if more than one CRL has the highest CRL Number." [crls :- [CertificateRevocationList]] (let [newest-crl (->> crls (group-by utils/get-crl-number) (into (sorted-map)) last last)] (if (= 1 (count newest-crl)) (first newest-crl) (throw (IllegalArgumentException. ^String (i18n/trs "Could not determine newest CRL.")))))) (schema/defn ^:always-validate maybe-replace-crl :- CertificateRevocationList "Given a CRL and a map of key identifiers to CRLs, determine the newest CRL with the key-id of the given CRL. Warn if the newest CRL is the given CRL. Never replaces the CRL corresponding to the Puppet CA signing cert." [crl :- CertificateRevocationList key-crl-map :- {KeyIdExtension [CertificateRevocationList]}] (let [key-id-ext (utils/get-extension-value crl utils/authority-key-identifier-oid) maybe-new-crls (get key-crl-map key-id-ext)] (if maybe-new-crls (let [new-crl (get-newest-crl (conj maybe-new-crls crl)) issuer (.getIssuerX500Principal crl)] (if (.equals crl new-crl) (log/warn (i18n/trs "Received CRLs for issuer {0} but none were newer than the existing CRL; keeping the existing CRL." issuer)) (log/info (i18n/trs "Updating CRL for issuer {0}." issuer))) new-crl) ;; no new CRLs found for this issuer, keep it crl))) (schema/defn get-auth-key-id [crl :- X509CRL] (if-let [key-id (utils/get-extension-value crl utils/authority-key-identifier-oid)] key-id (throw (IllegalArgumentException. ^String (i18n/trs "One or more submitted CRLs do not have an authority key identifier."))))) (schema/defn ^:always-validate update-crls "Given a collection of CRLs, update the CRL chain and confirm that all CRLs are currently valid. NOTE: assumes appropriate locking is in place" [incoming-crls :- [X509CRL] crl-path :- schema/Str cert-chain-path :- schema/Str] (log/info (i18n/trs "Processing update to CRL at {0}" crl-path)) (let [current-crls (utils/pem->crls crl-path) cert-chain (utils/pem->certs cert-chain-path) ca-cert-key (utils/get-extension-value (first cert-chain) utils/subject-key-identifier-oid) external-crl-chain (remove #(= ca-cert-key (:key-identifier (utils/get-extension-value % utils/authority-key-identifier-oid))) current-crls) ca-crl (first (filter #(= ca-cert-key (:key-identifier (utils/get-extension-value % utils/authority-key-identifier-oid))) current-crls)) incoming-crls-by-key-id (->> incoming-crls ;; just in case we're given multiple copies ;; of the same CRL, deduplicate so we can ;; identify the newest CRL set (group-by get-auth-key-id)) new-ext-crl-chain (cons ca-crl (map #(maybe-replace-crl % incoming-crls-by-key-id) external-crl-chain))] (validate-certs-and-crls cert-chain new-ext-crl-chain) (write-crls new-ext-crl-chain crl-path) (log/info (i18n/trs "Successfully updated CRL at {0}" crl-path)))) (schema/defn update-crls! "Apply write locking to the crls, and update the crls as appropriate." [incoming-crls :- [X509CRL] crl-path :- schema/Str cacert :- schema/Str {:keys [crl-lock crl-lock-timeout-seconds enable-infra-crl infra-crl-path]} :- CaSettings] (common/with-safe-write-lock crl-lock crl-lock-descriptor crl-lock-timeout-seconds (update-crls incoming-crls crl-path cacert) (when enable-infra-crl (update-crls incoming-crls infra-crl-path cacert)))) (schema/defn ensure-directories-exist! "Create any directories used by the CA if they don't already exist." [settings :- CaSettings] (doseq [dir [:csrdir :signeddir]] (let [path (get settings dir)] (when-not (fs/exists? path) (ks/mkdirs! path))))) (schema/defn ensure-ca-file-perms! "Ensure that the CA's private key file has the correct permissions set. If it does not, then correct them." [settings :- CaSettings] (let [ca-p-key (:cakey settings) cur-perms (ks-file/get-perms ca-p-key)] (when-not (= private-key-perms cur-perms) (ks-file/set-perms ca-p-key private-key-perms) (log/warn (format "%s %s" (i18n/trs "The private CA key at ''{0}'' was found to have the wrong permissions set as ''{1}''." ca-p-key cur-perms) (i18n/trs "This has been corrected to ''{0}''." private-key-perms)))))) (schema/defn ^:always-validate initialize! "Given the CA configuration settings, ensure that all required SSL files exist. If all files exist, new ones will not be generated. If only some are found (but others are missing), an exception is thrown." [settings :- CaSettings] (ensure-directories-exist! settings) (let [required-files (-> (settings->cadir-paths settings) (select-keys (required-ca-files (:enable-infra-crl settings))) (vals))] (if (every? fs/exists? required-files) (do (log/info (i18n/trs "CA already initialized for SSL")) (when (:enable-infra-crl settings) (generate-infra-serials! settings)) (when (:manage-internal-file-permissions settings) (ensure-ca-file-perms! settings))) (let [{found true missing false} (group-by fs/exists? required-files)] (if (= required-files missing) (generate-ssl-files! settings) (throw (partial-state-error "CA" found missing))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; certificate_status endpoint (schema/defn certificate-state :- CertificateState "Determine the state a certificate is in." [cert-or-csr :- CertificateOrCSR crl :- CertificateRevocationList] (if (utils/certificate-request? cert-or-csr) "requested" (if (utils/revoked? crl cert-or-csr) "revoked" "signed"))) (schema/defn fingerprint :- schema/Str "Calculate the hash of the certificate or CSR using the given algorithm, which must be one of SHA-1, SHA-256, or SHA-512." [cert-or-csr :- CertificateOrCSR algorithm :- schema/Str] (->> (utils/fingerprint cert-or-csr algorithm) (partition 2) (map (partial apply str)) (str/join ":") (str/upper-case))) (schema/defn get-certificate-details :- CertificateDetails "Return details from a X509 certificate." [cert] {:not_after (-> cert (.getNotAfter) (format-date-time)) :not_before (-> cert (.getNotBefore) (format-date-time)) :serial_number (-> cert (.getSerialNumber))}) (schema/defn get-cert-or-csr-status* [crl :- CertificateRevocationList is-cert? :- schema/Bool subject :- schema/Str cert-or-csr :- CertificateOrCSR] (let [default-fingerprint (fingerprint cert-or-csr "SHA-256")] (merge {:name subject :state (certificate-state cert-or-csr crl) :dns_alt_names (dns-alt-names cert-or-csr) :subject_alt_names (subject-alt-names cert-or-csr) :authorization_extensions (authorization-extensions cert-or-csr) :fingerprint default-fingerprint :fingerprints {:SHA1 (fingerprint cert-or-csr "SHA-1") :SHA256 default-fingerprint :SHA512 (fingerprint cert-or-csr "SHA-512") :default default-fingerprint}} ;; Only certificates have expiry dates (when is-cert? (get-certificate-details cert-or-csr))))) (schema/defn ^:always-validate get-cert-or-csr-status :- CertificateStatusResult "Get the status of the subject's certificate or certificate request. The status includes the state of the certificate (signed, revoked, requested), DNS alt names, and several different fingerprint hashes of the certificate." [{:keys [csrdir signeddir cacert cacrl cakey]} :- CaSettings subject :- schema/Str] (let [crl (utils/pem->ca-crl cacrl (utils/pem->ca-cert cacert cakey)) cert-path (path-to-cert signeddir subject) is-cert? (fs/exists? cert-path) cert-or-csr (if is-cert? (utils/pem->cert cert-path) (utils/pem->csr (path-to-cert-request csrdir subject)))] (get-cert-or-csr-status* crl is-cert? subject cert-or-csr))) (schema/defn ^:always-validate get-cert-or-csr-statuses :- [CertificateStatusResult] "Get the statuses of either all the CSR or all the certificate." [dir :- schema/Str crl :- CertificateRevocationList fetch-cert? :- schema/Bool] (let [pem-pattern #"^.+\.pem$" all-subjects (map #(fs/base-name % ".pem") (fs/find-files dir pem-pattern)) all-certs-or-csr (if fetch-cert? (map #(utils/pem->cert (path-to-cert dir %)) all-subjects) (map #(utils/pem->csr (path-to-cert-request dir %)) all-subjects))] (map (partial get-cert-or-csr-status* crl fetch-cert?) all-subjects all-certs-or-csr))) (schema/defn ^:always-validate get-cert-and-csr-statuses :- [CertificateStatusResult] "Get the status of all certificates and certificate requests." [{:keys [csrdir signeddir cacert cacrl cakey]} :- CaSettings] (let [crl (utils/pem->ca-crl cacrl (utils/pem->ca-cert cacert cakey)) all-csr (get-cert-or-csr-statuses csrdir crl false) all-certs (get-cert-or-csr-statuses signeddir crl true)] (concat all-csr all-certs))) (schema/defn ^:always-validate filter-by-certificate-state :- [CertificateStatusResult] "Get the status of all certificates in the given state." [{:keys [csrdir signeddir cacert cacrl cakey]} :- CaSettings state :- schema/Str] (let [crl (utils/pem->ca-crl cacrl (utils/pem->ca-cert cacert cakey))] (if (= "requested" state) (get-cert-or-csr-statuses csrdir crl false) (->> (get-cert-or-csr-statuses signeddir crl true) (filter (fn [cert-status] (= state (:state cert-status)))))))) (schema/defn sign-existing-csr! "Sign the subject's certificate request." [{:keys [csrdir] :as settings} :- CaSettings subject :- schema/Str report-activity] (let [csr-path (path-to-cert-request csrdir subject)] (autosign-certificate-request! subject (utils/pem->csr csr-path) settings report-activity))) (schema/defn filter-already-revoked-serials :- [BigInteger] "Given a list of serials and Puppet's CA CRL, returns vector of serials with any already-revoked serials removed." [serials :- [BigInteger] crl :- X509CRL] (let [crl-revoked-list (.getRevokedCertificates crl) existed-serials (set (map #(.getSerialNumber %) crl-revoked-list)) duplicate-serials (set/intersection (set serials) existed-serials)] (when (> (count duplicate-serials) 0) (doseq [serial duplicate-serials] (log/debug (i18n/trs "Certificate with serial {0} is already revoked." serial)))) (vec (set/difference (set serials) existed-serials)))) (schema/defn get-cert-serial :- BigInteger ;; will throw if the file doesn't exist [path-to-cert] (log/trace (i18n/trs "Try to read serial from \"{0}\"" path-to-cert)) (-> path-to-cert (utils/pem->cert) (utils/get-serial))) (schema/defn safe-get-cert-serial :- [BigInteger] ;; Check to see if the file exists and attempt to read the serial from the file if it does [path-to-cert] (if (fs/exists? path-to-cert) [(get-cert-serial path-to-cert)] [])) (schema/defn look-for-serial-numbers :- [BigInteger] [settings :- CaSettings certname :- schema/Str] ;; first look in the inventory (it is cheaper than reading certs). If it isn't there, read the cert (let [inventory-certs (find-matching-valid-serial-numbers settings certname) path-to-cert (path-to-cert (:signeddir settings) certname)] (if-not (empty? inventory-certs) ;; cover the corner case of the serial number in the cert in the file, but not in the inventory file (concat inventory-certs (safe-get-cert-serial path-to-cert)) ;; this will throw if the file isn't found, indicating it isn't present [(get-cert-serial path-to-cert)]))) (schema/defn revoke-existing-certs! "Revoke the subjects' certificates. Note this does not destroy the certificates. The certificates will remain in the signed directory despite being revoked." [{:keys [cacert cacrl cakey infra-crl-path crl-lock crl-lock-timeout-seconds infra-node-serials-path enable-infra-crl] :as settings} :- CaSettings subjects :- [schema/Str] report-activity] ;; because we need the crl to be consistent for the serials, maintain a write lock on the crl ;; as reentrant read-write locks do not allow upgrading from a read lock to a write lock (common/with-safe-write-lock crl-lock crl-lock-descriptor crl-lock-timeout-seconds (let [[our-full-crl & rest-of-full-chain] (utils/pem->crls cacrl) serials (filter-already-revoked-serials (->> subjects ; `look-for-serial-numbers` also looks in the inventory and for the file on disk (map (partial look-for-serial-numbers settings)) flatten) our-full-crl) serial-count (count serials)] (if (zero? serial-count) (log/info (i18n/trs "No revoke action needed. The certs are already in the CRL.")) (let [ca-private-key (utils/pem->private-key cakey) ca-public-key (.getPublicKey (utils/pem->ca-cert cacert cakey)) new-full-crl (utils/revoke-multiple our-full-crl ca-private-key ca-public-key serials) new-full-chain (cons new-full-crl (vec rest-of-full-chain))] (write-crls new-full-chain cacrl) ;; Publish infra-crl if an infra node is getting revoked. (when (and enable-infra-crl (fs/exists? infra-node-serials-path)) (with-open [infra-nodes-serial-path-reader (io/reader infra-node-serials-path)] (let [infra-nodes (set (map biginteger (read-infra-nodes infra-nodes-serial-path-reader))) infra-revocations (vec (set/intersection infra-nodes (set serials)))] (when (seq infra-revocations) (let [[our-infra-crl & rest-of-infra-chain] (utils/pem->crls infra-crl-path) new-infra-revocations (filter-already-revoked-serials infra-revocations our-infra-crl)] (if (empty? new-infra-revocations) (log/info (i18n/trs "No revoke action needed. The infra certs are already in the infra CRL")) (let [new-infra-crl (utils/revoke-multiple our-infra-crl ca-private-key ca-public-key new-infra-revocations) full-infra-chain (cons new-infra-crl (vec rest-of-infra-chain))] (write-crls full-infra-chain infra-crl-path) (log/info (i18n/trs "Infra node certificate(s) being revoked; publishing updated infra CRL"))))))))))))) (report-activity subjects "revoked") (common/record-action {:type :remove :targets subjects :meta {:type :certificate}})) (schema/defn ^:always-validate set-certificate-status! "Sign or revoke the certificate for the given subject." [settings :- CaSettings subject :- schema/Str desired-state :- DesiredCertificateState report-activity] (if (= :signed desired-state) (sign-existing-csr! settings subject report-activity) (revoke-existing-certs! settings [subject] report-activity))) (schema/defn ^:always-validate certificate-exists? :- schema/Bool "Do we have a certificate for the given subject?" [{:keys [signeddir]} :- CaSettings subject :- schema/Str] (fs/exists? (path-to-cert signeddir subject))) (schema/defn ^:always-validate csr-exists? :- schema/Bool "Do we have a CSR for the given subject?" [{:keys [csrdir]} :- CaSettings subject :- schema/Str] (fs/exists? (path-to-cert-request csrdir subject))) (defn csr-validation-failure? "Does the given object represent a CSR validation failure? (thrown from one of the CSR validate-* function, using slingshot)" [x] (when (map? x) (let [kind (:kind x) expected-types #{:disallowed-extension :duplicate-cert :hostname-mismatch :invalid-signature :invalid-subject-name}] (contains? expected-types kind)))) (schema/defn validate-csr "Validates the CSR (on disk) for the specified subject. Assumes existence of the CSR on disk; duplicate CSR or certificate policy will not be checked. If the CSR is invalid, returns a user-facing message. Otherwise, returns nil." [{:keys [csrdir allow-subject-alt-names allow-authorization-extensions] :as _settings} :- CaSettings subject :- schema/Str] (let [csr (utils/pem->csr (path-to-cert-request csrdir subject)) csr-subject (get-csr-subject csr) extensions (utils/get-extensions csr)] (sling/try+ ;; Matching the order of validations here with ;; 'process-csr-submission!' when autosigning (validate-subject! subject csr-subject) (ensure-subject-alt-names-allowed! csr allow-subject-alt-names) (ensure-no-authorization-extensions! csr allow-authorization-extensions) (validate-extensions! extensions) (validate-csr-signature! csr) (catch csr-validation-failure? {:keys [msg]} msg)))) (schema/defn ^:always-validate delete-certificate! "Delete the certificate for the given subject. Note this does not revoke the certificate." [{signeddir :signeddir} :- CaSettings subject :- schema/Str] (let [cert (path-to-cert signeddir subject)] (when (fs/exists? cert) (fs/delete cert) (log/debug (i18n/trs "Deleted certificate for {0}" subject))))) (schema/defn ^:always-validate delete-certificates! "Delete each of the given certificates. Note that this does not revoke the certs." [ca-settings :- CaSettings subjects :- [schema/Str]] (doseq [subj subjects] (delete-certificate! ca-settings subj))) (schema/defn ^:always-validate get-custom-oid-mappings :- (schema/maybe OIDMappings) "Given a path to a custom OID mappings file, return a map of all oids to shortnames" [custom-oid-mapping-file :- schema/Str] (if (fs/file? custom-oid-mapping-file) (let [oid-mappings (:oid_mapping (common/parse-yaml (slurp custom-oid-mapping-file)))] (into {} (for [[oid names] oid-mappings] [(name oid) (keyword (:shortname names))]))) (log/debug (i18n/trs "No custom OID mapping configuration file found at {0}, custom OID mappings will not be loaded" custom-oid-mapping-file)))) (schema/defn ^:always-validate get-oid-mappings :- OIDMappings [custom-oid-mapping-file :- (schema/maybe schema/Str)] (merge (get-custom-oid-mappings custom-oid-mapping-file) (clojure.set/map-invert puppet-short-names))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; CA status info (schema/defn ca-expiration-dates "Returns of a map of subject names of certs in the CA bundle to their expiration dates." [ca-cert-file :- schema/Str] (let [ca-cert-bundle (utils/pem->certs ca-cert-file)] (reduce (fn [cert-expirations cert] (assoc cert-expirations (-> cert (.getSubjectDN) (.getName) (utils/x500-name->CN)) (-> cert (.getNotAfter) (format-date-time)))) {} ca-cert-bundle))) (schema/defn crl-expiration-dates [crl-chain-file :- schema/Str] (let [crl-chain (utils/pem->crls crl-chain-file)] (reduce (fn [crl-expirations crl] (assoc crl-expirations (-> crl (.getIssuerDN) (.getName) (utils/x500-name->CN)) (-> crl (.getNextUpdate) (format-date-time)))) {} crl-chain))) (schema/defn cert-authority-id-match-ca-subject-id? :- schema/Bool "Given a certificate, and the ca-cert, validate that the certificate was signed by the CA provided" [incoming-cert :- X509Certificate ca-cert :- X509Certificate] (let [incoming-key-id (utils/get-extension-value incoming-cert utils/authority-key-identifier-oid) ca-key-id (utils/get-extension-value ca-cert utils/subject-key-identifier-oid)] (if incoming-key-id ;; incoming are byte-arrays, convert to seq for simple comparisons (= (seq (:key-identifier incoming-key-id)) (seq ca-key-id)) false))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public utilities (schema/defn replace-authority-identifier :- utils/SSLExtensionList [extensions :- utils/SSLExtensionList ca-cert :- X509Certificate] (conj (filter #(not= utils/authority-key-identifier-oid (:oid %)) extensions) (utils/authority-key-identifier-options ca-cert))) (schema/defn replace-subject-identifier :- utils/SSLExtensionList [extensions :- utils/SSLExtensionList subject-public-key :- PublicKey] (conj (filter #(not= utils/subject-key-identifier-oid (:oid %)) extensions) (utils/subject-key-identifier subject-public-key false))) (schema/defn update-extensions-for-new-signing :- utils/SSLExtensionList [extensions :- utils/SSLExtensionList ca-cert :- X509Certificate subject-public-key :- PublicKey] (replace-subject-identifier (replace-authority-identifier extensions ca-cert) subject-public-key)) (schema/defn renew-certificate! :- X509Certificate "Given a certificate and CaSettings create a new signed certificate using the public key from the certificate. It recreates all the extensions in the original certificate." [certificate :- X509Certificate {:keys [cacert cakey auto-renewal-cert-ttl signeddir] :as ca-settings} :- CaSettings report-activity] (let [validity (cert-validity-dates (or auto-renewal-cert-ttl default-auto-ttl-renewal-seconds)) cacert (utils/pem->ca-cert cacert cakey) cert-subject (utils/get-subject-from-x509-certificate certificate) cert-name (utils/x500-name->CN cert-subject) signed-cert (utils/sign-certificate (utils/get-subject-from-x509-certificate cacert) (utils/pem->private-key cakey) (next-serial-number! ca-settings) (:not-before validity) (:not-after validity) cert-subject (.getPublicKey certificate) (update-extensions-for-new-signing (utils/get-extensions certificate) cacert (.getPublicKey certificate)))] (write-cert-to-inventory! signed-cert ca-settings) (write-cert signed-cert (path-to-cert signeddir cert-name)) (log/info (i18n/trs "Renewed certificate for \"{0}\" with new expiration of \"{1}\"" cert-name (.format (new SimpleDateFormat "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") (.getNotAfter signed-cert)))) (report-activity [cert-subject] "renewed") signed-cert)) (schema/defn crl-expires-in-n-days? [crl-path {:keys [crl-lock crl-lock-timeout-seconds]} :- CaSettings days :- schema/Int] (common/with-safe-write-lock crl-lock crl-lock-descriptor crl-lock-timeout-seconds (let [crl-object (first (utils/pem->crls crl-path)) next-update (-> crl-object .getNextUpdate .toInstant (.atZone (ZoneId/systemDefault)) .toLocalDateTime)] (.isBefore next-update (.plusDays (LocalDateTime/now) days))))) (schema/defn overwrite-existing-crl! [crl :- X509CRL rest-of-full-chain capub :- schema/Str cakey :- schema/Str cacert :- X509Certificate valid-serials :- [BigInteger] crl-path :- schema/Str] (let [^BigInteger crl-number (utils/get-crl-number crl) public-key (utils/pem->public-key capub) private-key (utils/pem->private-key cakey) ;; because we are purging existing serials, we need a whole new CRL ;; the "next update" and "crl-number" will get updated by the process that ;; adds the serial numbers to the crl new-full-crl (utils/generate-crl ;; ensure the issuer is identical (.getIssuerX500Principal crl) private-key public-key (.getThisUpdate crl) (.getNextUpdate crl) crl-number ;; original crl is generated with no extensions, continue the precedence nil) ;; create a new CRL with incremented "next update" and crl-number, and all the serials new-crl-with-revoked (utils/revoke-multiple new-full-crl (utils/pem->private-key cakey) (.getPublicKey cacert) valid-serials) new-full-chain (cons new-crl-with-revoked (vec rest-of-full-chain))] (write-crls new-full-chain crl-path))) (schema/defn update-and-sign-crl! "Given a path to a CRL, and the ca-settings, update the CRl with all known valid serials that have been revoked" [path-to-crl {:keys [crl-lock crl-lock-timeout-seconds cacert cakey capub] :as settings} :- CaSettings] ;; read in the existing crl, and extract the serial numbers that have expired so we can remove them from the CRL set. (let [expired-serials (set (expired-inventory-serials settings))] (common/with-safe-write-lock crl-lock crl-lock-descriptor crl-lock-timeout-seconds (let [[our-full-crl & rest-of-full-chain] (utils/pem->crls path-to-crl) crl-serials (set (map #(.getSerialNumber %) (.getRevokedCertificates our-full-crl))) valid-crl-serials (set/difference crl-serials expired-serials) cacert (utils/pem->ca-cert cacert cakey)] (overwrite-existing-crl! our-full-crl rest-of-full-chain capub cakey cacert (vec valid-crl-serials) path-to-crl))))) (schema/defn maybe-update-crls-for-expiration [{:keys [cacrl enable-infra-crl infra-crl-path] :as settings} :- CaSettings] ;; check the age of the main crl (when (crl-expires-in-n-days? cacrl settings crl-expiration-window-days) (log/info (i18n/trs "CA CRL expiring within 30 days, updating.")) (update-and-sign-crl! cacrl settings)) (when (and enable-infra-crl (fs/exists? infra-crl-path)) (when (crl-expires-in-n-days? infra-crl-path settings crl-expiration-window-days) (log/info (i18n/trs "infra crl expiring within 30 days, updating.")) (update-and-sign-crl! infra-crl-path settings)))) (schema/defn maybe-sign-one :- (schema/enum :signed :signing-errors) [subject :- schema/Str csr-path :- schema/Str cacert :- Certificate casubject :- schema/Str ca-private-key :- PrivateKey {:keys [signeddir ca-ttl allow-auto-renewal allow-subject-alt-names allow-authorization-extensions auto-renewal-cert-ttl] :as ca-settings} :- CaSettings] (try (let [csr (utils/pem->csr csr-path) renewal-ttl (if (and allow-auto-renewal (supports-auto-renewal? csr)) auto-renewal-cert-ttl ca-ttl) _ (log/debug (i18n/trs "Calculating validity dates from ttl of {0} " renewal-ttl)) validity (cert-validity-dates renewal-ttl)] ;; these ensure/validate functions throw exceptions if the criteria isn't met (ensure-subject-alt-names-allowed! csr allow-subject-alt-names) (ensure-no-authorization-extensions! csr allow-authorization-extensions) (validate-extensions! (utils/get-extensions csr)) (validate-csr-signature! csr) (let [signed-cert (utils/sign-certificate casubject ca-private-key (next-serial-number! ca-settings) (:not-before validity) (:not-after validity) (utils/cn subject) (utils/get-public-key csr) (create-agent-extensions csr cacert))] (write-cert-to-inventory-unlocked! signed-cert ca-settings) (write-cert signed-cert (path-to-cert signeddir subject)) (delete-certificate-request! ca-settings subject) (log/info (i18n/trs "Signed CSR for {0}" subject)) ;; success case, add the host to the set of signed results :signed)) (catch Throwable e (log/error e (i18n/trs "Failed in bulk signing for entry {0}" subject)) ;; failure case, add the host to the set of not signed results :signing-errors))) (schema/defn ^:always-validate sign-multiple-certificate-signing-requests! :- {:signed [schema/Str] :no-csr [schema/Str] :signing-errors [schema/Str]} [subjects :- [schema/Str] {:keys [cacert cakey csrdir inventory-lock inventory-lock-timeout-seconds serial-lock serial-lock-timeout-seconds] :as ca-settings} :- CaSettings report-activity] (let [;; if part of a CA bundle, the intermediate CA will be first in the chain cacert (utils/pem->ca-cert cacert cakey) casubject (utils/get-subject-from-x509-certificate cacert) ca-private-key (utils/pem->private-key cakey)] ;; since we are going to be manipulating the serial file and the inventory file for multiple entries, ;; acquire the locks to prevent lock thrashing (common/with-safe-write-lock serial-lock serial-lock-descriptor serial-lock-timeout-seconds (common/with-safe-write-lock inventory-lock inventory-lock-descriptor inventory-lock-timeout-seconds (let [results ;; loop through the subjects, one at a time, and collect the results for success or failure. (loop [s subjects result {:signed [] :no-csr [] :signing-errors []}] (if-not (empty? s) (let [subject (first s) csr-path (path-to-cert-request csrdir subject)] (if (fs/exists? csr-path) (let [_ (log/trace (i18n/trs "File exists at {0}" csr-path)) one-result (maybe-sign-one subject csr-path cacert casubject ca-private-key ca-settings)] ;; one-result is either :signed or :signing-errors (recur (rest s) (update result one-result conj subject))) (do (log/trace (i18n/trs "File does not exist at {0}" csr-path)) (recur (rest s) (update result :no-csr conj subject))))) result))] ;; submit the signing activity as one entry for all the hosts. (when-not (empty? (:signed results)) (common/record-action {:type :add :targets (:signed results) :meta {:type :certificate}}) (report-activity (:signed results) "signed")) results)))))puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/cli/000077500000000000000000000000001470345337400261175ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/cli/gem.clj000066400000000000000000000007431470345337400273650ustar00rootroot00000000000000(ns puppetlabs.puppetserver.cli.gem (:require [puppetlabs.puppetserver.cli.subcommand :as cli] [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core])) (defn gem-run! [config args] (let [jruby-config (jruby-puppet-core/initialize-and-create-jruby-config config)] (jruby-core/cli-run! jruby-config "gem" args))) (defn -main [& args] (cli/jruby-run gem-run! args)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/cli/irb.clj000066400000000000000000000007431470345337400273710ustar00rootroot00000000000000(ns puppetlabs.puppetserver.cli.irb (:require [puppetlabs.puppetserver.cli.subcommand :as cli] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core])) (defn irb-run! [config args] (let [jruby-config (jruby-puppet-core/initialize-and-create-jruby-config config)] (jruby-core/cli-run! jruby-config "irb" args))) (defn -main [& args] (cli/jruby-run irb-run! args)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/cli/ruby.clj000066400000000000000000000007411470345337400275740ustar00rootroot00000000000000(ns puppetlabs.puppetserver.cli.ruby (:require [puppetlabs.puppetserver.cli.subcommand :as cli] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core])) (defn ruby-run! [config args] (let [jruby-config (jruby-puppet-core/initialize-and-create-jruby-config config)] (jruby-core/cli-ruby! jruby-config args))) (defn -main [& args] (cli/jruby-run ruby-run! args)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/cli/subcommand.clj000066400000000000000000000042001470345337400307350ustar00rootroot00000000000000(ns puppetlabs.puppetserver.cli.subcommand (:require [puppetlabs.kitchensink.core :as ks] [slingshot.slingshot :refer [try+ throw+]] [puppetlabs.trapperkeeper.config :as tk-config] [puppetlabs.i18n.core :as i18n])) (defn parse-cli-args! "Parses the command-line arguments using `puppetlabs.kitchensink.core/cli!`. Required arguments: --config " [cli-args] (let [specs [["-c" "--config CONFIG-PATH" (i18n/trs "Path to a configuration file or directory of configuration files. See the documentation for a list of supported file types.")]] required [:config]] (ks/cli! cli-args specs required))) (defn load-tk-config [cli-data] (let [debug? (or (:debug cli-data) false)] (if-not (contains? cli-data :config) {:debug debug?} (-> (:config cli-data) (tk-config/load-config) (assoc :debug debug?))))) (defn print-message-and-exit [error-map exit-code] (if-let [msg (:msg error-map)] (println msg) (println error-map)) (System/exit exit-code)) (defn run "The main entry for subcommands, this parses the `args` provided on the command line and prints out a message if there's any missing or incorrect. The given `run-fn` is then called with the configuration map and the command line arguments specific to the subcommand. The `run-fn` must accept a configuration map and argument sequence." [run-fn args] (try+ (let [[config extra-args] (-> (or args '()) (parse-cli-args!))] (run-fn (load-tk-config config) extra-args)) (catch map? m (let [kind (:kind m)] (when (keyword? kind) (case (ks/without-ns kind) :cli-error (print-message-and-exit m 1) :cli-help (print-message-and-exit m 0) nil))) (throw+)) (finally (shutdown-agents)))) (defn jruby-run "Executes a function that invokes the JRuby interpeter with the `run` function and use the return value from JRuby as the process exit code." [run-fn args] (-> (run run-fn args) .getStatus System/exit)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/common.clj000066400000000000000000000133471470345337400273420ustar00rootroot00000000000000(ns puppetlabs.puppetserver.common (:require [clojure.string :as str] [clojure.tools.logging :as log] [puppetlabs.i18n.core :as i18n] [schema.core :as schema] [slingshot.slingshot :as sling]) (:import (java.util List Map Set) (java.util.concurrent TimeUnit) (org.yaml.snakeyaml Yaml))) (def Environment "Schema for environment names. Alphanumeric and _ only." (schema/pred (comp not nil? (partial re-matches #"\w+")) "environment")) (def CodeId "Validates that code-id contains only alpha-numerics and '-', '_', ';', or ':'." (schema/pred (comp not (partial re-find #"[^_\-:;a-zA-Z0-9]")) "code-id")) (schema/defn environment-validation-error-msg [environment :- schema/Str] (i18n/tru "The environment must be purely alphanumeric, not ''{0}''" environment)) (schema/defn code-id-validation-error-msg [code-id :- schema/Str] (i18n/tru "Invalid code-id ''{0}''. Must contain only alpha-numerics and ''-'', ''_'', '';'', or '':''" code-id)) (defmacro with-safe-read-lock "Given a ReentrantReadWriteLock, acquire the read lock, and hold it for the length of the execution of the body. If the lock can't be acquired, throw an exception to indicate a timeout. Log behaviors at trace level to aid with supportability" [read-write-lock descriptor timeout-in-seconds & body] `(let [l# (.readLock ~read-write-lock) descriptor# ~descriptor timeout# ~timeout-in-seconds] (log/trace (i18n/trs "Attempt to acquire read lock \"{0}\"" descriptor#)) (if (.tryLock l# timeout# TimeUnit/SECONDS) (try (log/trace (i18n/trs "Acquired read lock \"{0}\"" descriptor#)) (do ~@body) (finally (.unlock l#) (log/trace (i18n/trs "Released read lock \"{0}\"" descriptor#)))) (do (log/info (i18n/trs "Read Lock acquisition timed out \"{0}\"" descriptor#)) (sling/throw+ {:kind :lock-acquisition-timeout :msg (i18n/tru "Failed to acquire read lock \"{0}\" within {1} seconds" descriptor# timeout#)}))))) (defmacro with-safe-write-lock "Given a ReentrantReadWriteLock, acquire the write lock, and hold it for the length of the execution of the body. If the lock can't be acquired, throw an exception to indicate a timeout. Log behaviors at trace level to aid with supportability" [read-write-lock descriptor timeout-in-seconds & body] `(let [l# (.writeLock ~read-write-lock) descriptor# ~descriptor timeout# ~timeout-in-seconds] (log/trace (i18n/trs "Attempt to acquire write lock \"{0}\"" descriptor#)) (if (.tryLock l# timeout# TimeUnit/SECONDS) (try (log/trace (i18n/trs "Acquired write lock \"{0}\"" descriptor#)) (do ~@body) (finally (.unlock l#) (log/trace (i18n/trs "Released write lock \"{0}\"" descriptor#)))) (do (log/info (i18n/trs "Write Lock acquisition timed out \"{0}\"" descriptor#)) (sling/throw+ {:kind :lock-acquisition-timeout :msg (i18n/tru "Failed to acquire write lock \"{0}\" within {1} seconds" descriptor# timeout#)}))))) (defmacro with-safe-lock "Given a ReentrantLock, acquire the lock, and hold it for the length of the execution of the body. If the lock can't be acquired, throw an exception to indicate a timeout. Log behaviors at trace level to aid with supportability" [reentrant-lock descriptor timeout-in-seconds & body] `(let [l# ~reentrant-lock descriptor# ~descriptor timeout# ~timeout-in-seconds] (log/trace (i18n/trs "Attempt to acquire lock \"{0}\"" descriptor#)) (if (.tryLock l# timeout# TimeUnit/SECONDS) (try (log/trace (i18n/trs "Acquired lock \"{0}\"" descriptor#)) (do ~@body) (finally (.unlock l#) (log/trace (i18n/trs "Released lock \"{0}\"" descriptor#)))) (do (log/info (i18n/trs "Lock acquisition timed out \"{0}\"" descriptor#)) (sling/throw+ {:kind :lock-acquisition-timeout :msg (i18n/tru "Failed to acquire lock \"{0}\" within {1} seconds" descriptor# timeout#)}))))) (defprotocol JavaMap->ClojureMap (java->clj [o])) (extend-protocol JavaMap->ClojureMap Map (java->clj [o] (let [entries (.entrySet o)] (reduce (fn [m [^String k v]] (assoc m (keyword k) (java->clj v))) {} entries))) List (java->clj [o] (vec (map java->clj o))) Set (java->clj [o] (set (map java->clj o))) Object (java->clj [o] o) nil (java->clj [_] nil)) (defn parse-yaml [yaml-string] ;; default in snakeyaml 2.0 is to not allow ;; global tags, which is the source of exploits. (let [yaml (new Yaml) data (.load yaml ^String yaml-string)] (java->clj data))) (defn extract-file-names-from-paths "Given a sequence of java.nio.file.Path objects, return a lazy sequence of the file names of the file represented by those paths. Example ['/foo/bar/baz.tmp'] will result in ['baz.tmp']" [paths-to-files] (map #(.toString (.getFileName %)) paths-to-files)) (defn remove-suffix-from-file-names "Given a suffix, and a sequence of file-names, remove the suffix from the filenames" [files suffix] (let [suffix-size (count suffix)] (map (fn [s] (if (str/ends-with? s suffix) (subs s 0 (- (count s) suffix-size)) s)) files))) (def action-registration-function (atom (constantly nil))) (schema/def action-shape {:type (schema/enum :add :remove :info :action) :targets [schema/Str] :meta schema/Any}) (schema/defn record-action [action :- action-shape] (@action-registration-function action)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/jruby_request.clj000066400000000000000000000125241470345337400307510ustar00rootroot00000000000000(ns puppetlabs.puppetserver.jruby-request (:import [clojure.lang IFn]) (:require [clojure.tools.logging :as log] [clj-semver.core :as semver] [slingshot.slingshot :as sling] [puppetlabs.ring-middleware.utils :as ringutils] [puppetlabs.services.protocols.jruby-metrics :as jruby-metrics] [puppetlabs.services.jruby.jruby-puppet-service :as jruby] [schema.core :as schema] [puppetlabs.puppetserver.common :as ps-common] [puppetlabs.i18n.core :as i18n])) (defn jruby-timeout? "Determine if the supplied slingshot message is for a JRuby borrow timeout." [x] (when (map? x) (= (:kind x) :puppetlabs.services.jruby-pool-manager.jruby-core/jruby-timeout))) (defn schema-error? "Determine if the supplied slingshot message is for a JRuby borrow timeout." [x] (when (map? x) (= (:type x) :schema.core/error))) (defn output-error [{:keys [uri]} {:keys [msg]} http-status] (log/error (i18n/trs "Error {0} on SERVER at {1}: {2}" http-status uri msg)) (ringutils/plain-response http-status msg)) (defn output-map-error [{:keys [uri]} error http-status] (log/error (i18n/trs "Error {0} on SERVER at {1}: {2}" http-status uri error)) (ringutils/json-response http-status error)) (defn wrap-with-error-handling "Middleware that wraps a JRuby request with some error handling to return the appropriate http status codes, etc." [handler] (fn [request] (sling/try+ (handler request) (catch ringutils/bad-request? e (output-error request e 400)) (catch jruby-timeout? e (output-error request e 503)) (catch ringutils/service-unavailable? e (output-error request e 503)) (catch schema-error? e (output-map-error request e 500))))) (defn wrap-with-jruby-instance "Middleware fn that borrows a jruby instance from the `jruby-service` and makes it available in the request as `:jruby-instance`" [handler jruby-service] (fn [request] (jruby/with-jruby-puppet jruby-puppet jruby-service {:request (dissoc request :ssl-client-cert)} (handler (assoc request :jruby-instance jruby-puppet))))) (schema/defn ^:always-validate wrap-with-request-queue-limit :- IFn "Middleware fn that short-circuits incoming requests with a 503 'Service Unavailable' response if the queue of outstanding requests for JRuby instances exceeds the limit given by the max-queued-requests argument. The response will include a Retry-After header set to a random fraction of the value given by the max-retry-delay argument if set to a positive non-zero number." [handler :- IFn metrics-service :- (schema/protocol jruby-metrics/JRubyMetricsService) max-queued-requests :- schema/Int max-retry-delay :- schema/Int] (let [metrics-map (jruby-metrics/get-metrics metrics-service) {:keys [requested-instances queue-limit-hit-meter]} metrics-map minimum-version (semver/version "5.3.1") err-msg (i18n/trs "The number of requests waiting for a JRuby instance has exceeded the limit allowed by the max-queued-requests setting.")] (fn [{{:strs [x-puppet-version]} :headers :as request}] (if (and (>= (count @requested-instances) max-queued-requests) (some? x-puppet-version) (semver/valid-format? x-puppet-version) (>= (semver/cmp x-puppet-version minimum-version) 0)) (let [response (output-error request {:msg err-msg} 503)] ;; Record an occurance of the rate limit being hit to metrics. (.mark queue-limit-hit-meter) (if (pos? max-retry-delay) (-> response (assoc-in [:headers "Retry-After"] (-> (rand) (* max-retry-delay) int str)) (assoc-in [:headers "Connection"] "close")) response)) (handler request))))) (defn get-environment-from-request "Gets the environment from the URL or query string of a request." [req] ;; If environment is derived from the path, favor that over a query/form ;; param named environment, since it doesn't make sense to ask about ;; environment production in environment development. (or (get-in req [:route-params :environment]) (get-in req [:params "environment"]))) (defn wrap-with-environment-validation "Middleware function which validates the presence and syntactical content of an environment in a ring request. If validation fails, a :bad-request slingshot exception is thrown. If the optional-environment-param is provided as true, it allows for the endpoint to have its query param environment to be optional. However if the param is provided, it will still validate that param for the given request." ([handler] (wrap-with-environment-validation handler false)) ([handler optional-environment-param] (fn [request] (let [environment (get-environment-from-request request)] (cond (and (true? optional-environment-param) (nil? environment)) (handler request) (nil? environment) (ringutils/throw-bad-request! (i18n/tru "An environment parameter must be specified")) (not (nil? (schema/check ps-common/Environment environment))) (ringutils/throw-bad-request! (ps-common/environment-validation-error-msg environment)) :else (handler request)))))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/liberator_utils.clj000066400000000000000000000004011470345337400312400ustar00rootroot00000000000000(ns puppetlabs.puppetserver.liberator-utils) (defn exception-handler "Handles exceptions which occur inside a liberator resource by simply re-throwing them so they can be handled elsewhere, like middleware." [context] (throw (:exception context))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/puppetserver/ringutils.clj000066400000000000000000000124401470345337400300630ustar00rootroot00000000000000(ns puppetlabs.puppetserver.ringutils (:import (clojure.lang IFn) (java.security.cert X509Certificate)) (:require [clojure.tools.logging :as log] [puppetlabs.ssl-utils.core :as ssl-utils] [ring.util.response :as ring] [schema.core :as schema] [puppetlabs.i18n.core :as i18n])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Schema (def WhitelistSettings {(schema/optional-key :authorization-required) schema/Bool (schema/optional-key :client-whitelist) [schema/Str]}) (def RingRequest {:uri schema/Str (schema/optional-key :ssl-client-cert) (schema/maybe X509Certificate) schema/Keyword schema/Any}) (def RingResponse {:status schema/Int :headers {schema/Str schema/Any} :body schema/Any schema/Keyword schema/Any}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Private (defn log-access-denied "Log a message to info stating that the client is not in the access control whitelist." [uri certificate] (let [subject (ssl-utils/get-cn-from-x509-certificate certificate)] (log/info (format "%s\n%s" (i18n/trs "Client ''{0}'' access to {1} rejected;" subject uri) (i18n/trs "client not found in whitelist configuration."))))) (defn client-on-whitelist? "Test if the certificate subject is on the client whitelist." [settings certificate] (let [whitelist (-> settings :client-whitelist (set)) client (ssl-utils/get-cn-from-x509-certificate certificate)] (contains? whitelist client))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (schema/defn client-allowed-access? :- schema/Bool "Determines if the client in the request is allowed to access the endpoint based on the client whitelist and whether authorization is required." [settings :- WhitelistSettings req :- RingRequest] (if (get settings :authorization-required true) (if-let [client-cert (:ssl-client-cert req)] (if (client-on-whitelist? settings client-cert) true (do (log-access-denied (:uri req) client-cert) false)) (do (log/info (i18n/trs "Access to {0} rejected; no client certificate found" (:uri req))) false)) true)) (schema/defn ^:always-validate wrap-with-cert-whitelist-check :- IFn "A ring middleware that checks to make sure the client cert is in the whitelist before granting access." [handler :- IFn settings :- WhitelistSettings] (fn [req] (if (client-allowed-access? settings req) (handler req) {:status 403 :body "Forbidden."}))) (defn wrap-with-certname-as-compiler "Function that returns middleware that add X-Puppet-Compiler-Name to the response, only for the posts to the v3 catalog endpoint. Otherwise, do nothing." [handler name] (fn [request] (ring/header (handler request) "X-Puppet-Compiler-Name" name))) (defn wrap-with-puppet-version-header "Function that returns a middleware that adds an X-Puppet-Version header to the response." [handler version] (fn [request] (let [response (handler request)] ; Our compojure app returns nil responses sometimes. ; In that case, don't add the header. (when response (ring/header response "X-Puppet-Version" version))))) ;; This function exists to support backward-compatible usage of a ;; client-whitelist to protect access to some Clojure endpoints. When support ;; for client-whitelist authorization is dropped, this function should deleted. ;; Callers would presumably be using a trapperkeeper-authorization handler ;; for all endpoint authorization. (schema/defn ^:always-validate wrap-with-trapperkeeper-or-client-whitelist-authorization "Middleware function that routes a request through either an authorization handler derived from the supplied 'authorization-fn' or to a client-whitelist handler. The 'authorization-fn' is expected to return a handler when called and this function and accept a single argument, an downstream handler that the authorization-fn should route a handled request to. The authorization-fn is called with 'base-handler' as its parameter. Requests are only routed to the client-whitelist handler if the request 'uri' starts with the value provided to this function for 'whitelist-path' and if the 'whitelist-settings' are non-empty. In all other cases, requests are routed to the handler constructed from the 'authorization-fn'" [base-handler :- IFn authorization-fn :- IFn whitelist-path :- schema/Str whitelist-settings :- (schema/maybe WhitelistSettings)] (let [handler-with-trapperkeeper-authorization (authorization-fn base-handler)] (if-let [handler-with-client-whitelist-authorization (when (or (false? (:authorization-required whitelist-settings)) (not-empty (:client-whitelist whitelist-settings))) (wrap-with-cert-whitelist-check base-handler whitelist-settings))] (fn [request] (if (and (.startsWith (:uri request) whitelist-path) whitelist-settings) (handler-with-client-whitelist-authorization request) (handler-with-trapperkeeper-authorization request))) (fn [request] (handler-with-trapperkeeper-authorization request))))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/000077500000000000000000000000001470345337400244275ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/analytics/000077500000000000000000000000001470345337400264165ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/analytics/analytics_service.clj000066400000000000000000000056631470345337400326310ustar00rootroot00000000000000(ns puppetlabs.services.analytics.analytics-service (:require [clojure.tools.logging :as log] [puppetlabs.trapperkeeper.core :refer [defservice]] [puppetlabs.i18n.core :as i18n] [puppetlabs.dujour.version-check :as version-check] [puppetlabs.services.analytics.dropsonde :refer [run-dropsonde]])) (defprotocol AnalyticsService "Protocol placeholder for the analytics service.") (def analytics-service-job-group-id :analytics-service-job-group) (defn safe-run-dropsonde "Prevent exceptions from escaping as this is run in a scheduled task" [config] (try (log/debug (i18n/trs "Running dropsonde")) (run-dropsonde config) (log/debug (i18n/trs "dropsonde run complete")) (catch Exception _ (log/info (i18n/trs "Failed while running dropsonde"))))) (defservice analytics-service AnalyticsService [[:PuppetServerConfigService get-config] [:SchedulerService interspaced stop-jobs]] (start [this context] (let [config (get-config)] ;; Configure analytics (let [product-name (or (get-in config [:product :name]) {:group-id "puppetlabs" :artifact-id "puppetserver"}) checkin-interval-millis (* 1000 60 60 24) ; once per day update-server-url (get-in config [:product :update-server-url]) check-for-updates (get-in config [:product :check-for-updates] true)] (if check-for-updates (interspaced checkin-interval-millis (fn [] (try (version-check/check-for-update {:product-name product-name} update-server-url) (catch Exception _ (log/error (i18n/trs "Failed to check for product updates"))))) analytics-service-job-group-id) (log/info (i18n/trs "Not checking for updates - opt-out setting exists")))) (log/info (i18n/trs "Puppet Server Update Service has successfully started and will run in the background")) ;; Configure dropsonde, enabled by default if not specified (let [dropsonde-enabled (get-in config [:dropsonde :enabled] true) ;; once a week, config value is documented as seconds dropsonde-interval-millis (* 1000 (get-in config [:dropsonde :interval] (* 60 60 24 7)))] (if dropsonde-enabled (interspaced dropsonde-interval-millis #(safe-run-dropsonde config) analytics-service-job-group-id) (log/info (i18n/trs (str "Not submitting module metrics via Dropsonde -- submission is disabled. " "Enable this feature by setting `dropsonde.enabled` to true in Puppet Server''s config.")))))) context) (stop [this context] (log/info (i18n/trs "Puppet Server Update Service shutting down")) (stop-jobs analytics-service-job-group-id) context)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/analytics/dropsonde.clj000066400000000000000000000035201470345337400311050ustar00rootroot00000000000000(ns puppetlabs.services.analytics.dropsonde (:require [clojure.tools.logging :as log] [puppetlabs.i18n.core :as i18n] [puppetlabs.puppetserver.shell-utils :as shell-utils] [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet])) (def puppet-agent-ruby "/opt/puppetlabs/puppet/bin/ruby") (def dropsonde-dir "/opt/puppetlabs/server/data/puppetserver/dropsonde") (def dropsonde-bin (str dropsonde-dir "/bin/dropsonde")) (defn run-dropsonde [config] ;; process config to ensure default resolution of these settings (let [puppet-config (jruby-puppet/initialize-puppet-config {} (jruby-puppet/extract-puppet-config (:jruby-puppet config)) false) confdir (:server-conf-dir puppet-config) codedir (:server-code-dir puppet-config) vardir (:server-var-dir puppet-config) logdir (:server-log-dir puppet-config) result (shell-utils/execute-command puppet-agent-ruby {:args [dropsonde-bin "submit"] :env {"GEM_HOME" dropsonde-dir "GEM_PATH" dropsonde-dir "HOME" dropsonde-dir "PUPPET_CONFDIR" confdir "PUPPET_CODEDIR" codedir "PUPPET_VARDIR" vardir "PUPPET_LOGDIR" logdir}})] (if (= 0 (:exit-code result)) (log/info (i18n/trs "Successfully submitted module metrics via Dropsonde.")) (log/warn (i18n/trs "Failed to submit module metrics via Dropsonde. Error: {0}" (:stderr result)))))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/ca/000077500000000000000000000000001470345337400250125ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/ca/certificate_authority_core.clj000066400000000000000000000664171470345337400331240ustar00rootroot00000000000000(ns puppetlabs.services.ca.certificate-authority-core (:require [bidi.schema :as bidi-schema] [cheshire.core :as cheshire] [clj-time.core :as time] [clj-time.format :as time-format] [clojure.java.io :as io] [clojure.string :as string] [clojure.tools.logging :as log] [liberator.core :refer [defresource]] [liberator.representation :as representation] [puppetlabs.comidi :as comidi :refer [ANY DELETE GET POST PUT]] [puppetlabs.i18n.core :as i18n] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.puppetserver.common :as common] [puppetlabs.puppetserver.liberator-utils :as liberator-utils] [puppetlabs.puppetserver.ringutils :as ringutils] [puppetlabs.ring-middleware.core :as middleware] [puppetlabs.ring-middleware.utils :as middleware-utils] [puppetlabs.ssl-utils.core :as utils] [puppetlabs.trapperkeeper.authorization.ring :as ring] [puppetlabs.trapperkeeper.authorization.ring-middleware :as auth-middleware] [puppetlabs.trapperkeeper.services.status.status-core :as status-core] [ring.util.request :as request] [ring.util.response :as rr] [schema.core :as schema] [slingshot.slingshot :refer [try+]]) (:import (clojure.lang IFn) (java.io ByteArrayInputStream InputStream StringWriter) (java.security.cert X509Certificate) (org.joda.time DateTime))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Constants (def puppet-ca-API-version "v1") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 'handler' functions for HTTP endpoints (schema/defn format-http-date :- (schema/maybe DateTime) "Formats an http-date into joda time. Returns nil for malformed or nil http-dates" [http-date :- (schema/maybe schema/Str)] (when http-date (try (time-format/parse (time-format/formatters :rfc822) (string/replace http-date #"GMT" "+0000")) (catch IllegalArgumentException _ nil)))) (defn handle-get-certificate [subject {:keys [cacert signeddir]} request] (-> (if-let [certificate-path (ca/get-certificate-path subject cacert signeddir)] (let [last-modified-val (rr/get-header request "If-Modified-Since") last-modified-date-time (format-http-date last-modified-val) cert-last-modified-date-time (ca/get-file-last-modified certificate-path)] (if (or (nil? last-modified-date-time) (time/after? cert-last-modified-date-time last-modified-date-time)) (rr/response (slurp certificate-path)) (-> (rr/response nil) (rr/status 304)))) (rr/not-found (i18n/tru "Could not find certificate {0}" subject))) (rr/content-type "text/plain"))) (defn handle-get-certificate-request [subject {:keys [csrdir]}] (-> (if-let [certificate-request (ca/get-certificate-request subject csrdir)] (rr/response certificate-request) (rr/not-found (i18n/tru "Could not find certificate_request {0}" subject))) (rr/content-type "text/plain"))) (schema/defn handle-put-certificate-request! [ca-settings :- ca/CaSettings report-activity {:keys [body] {:keys [subject]} :route-params :as request}] (try+ (let [report-activity-fn (ca/create-report-activity-fn report-activity request)] (ca/process-csr-submission! subject body ca-settings report-activity-fn) (rr/content-type (rr/response nil) "text/plain")) (catch ca/csr-validation-failure? {:keys [msg]} (log/error msg) ;; Respond to all CSR validation failures with a 400 (middleware-utils/plain-response 400 msg)))) (schema/defn resolve-crl-information "Create a map that has the appropriate path, lock, timeout and descriptor for the crl being used" [{:keys [enable-infra-crl cacrl infra-crl-path crl-lock crl-lock-timeout-seconds]} :- ca/CaSettings] {:path (if (true? enable-infra-crl) infra-crl-path cacrl) :lock crl-lock :descriptor ca/crl-lock-descriptor :timeout crl-lock-timeout-seconds}) (defn handle-get-certificate-revocation-list "Always return the crl if no 'If-Modified-Since' header is provided or if that header is not in correct http-date format. If the header is present and has correct format, only return the crl if the server cacrl is newer than the agent crl." [request ca-settings] (let [agent-crl-last-modified-val (rr/get-header request "If-Modified-Since") agent-crl-last-modified-date-time (format-http-date agent-crl-last-modified-val) {:keys [path lock descriptor timeout]} (resolve-crl-information ca-settings)] ;; Since the locks are reentrant, obtain the read lock to prevent modification during the ;; window of time between when the last-modified is read and when the crl content is potentially read. (common/with-safe-read-lock lock descriptor timeout (if (or (nil? agent-crl-last-modified-date-time) (time/after? (ca/get-file-last-modified path lock descriptor timeout) agent-crl-last-modified-date-time)) (-> (ca/get-certificate-revocation-list path lock descriptor timeout) (rr/response) (rr/content-type "text/plain")) (-> (rr/response nil) (rr/status 304) (rr/content-type "text/plain")))))) (schema/defn handle-put-certificate-revocation-list! [incoming-crl-pem :- InputStream {:keys [cacrl cacert] :as ca-settings} :- ca/CaSettings] (try (let [byte-stream (-> incoming-crl-pem ca/input-stream->byte-array ByteArrayInputStream.) incoming-crls (utils/pem->crls byte-stream)] (if (empty? incoming-crls) (do (log/info (i18n/trs "No valid CRLs submitted, nothing will be updated.")) (middleware-utils/plain-response 400 "No valid CRLs submitted.")) (do (ca/update-crls! incoming-crls cacrl cacert ca-settings) (middleware-utils/plain-response 200 "Successfully updated CRLs.")))) (catch IllegalArgumentException e (let [error-msg (.getMessage e)] (log/error error-msg) (middleware-utils/plain-response 400 error-msg))))) (schema/defn handle-delete-certificate-request! [subject :- String ca-settings :- ca/CaSettings] (let [response (ca/delete-certificate-request! ca-settings subject) outcomes->codes {:success 204 :not-found 404 :error 500}] (if (not= (response :outcome) :success) (-> (rr/response (:message response)) (rr/status ((response :outcome) outcomes->codes)) (rr/content-type "text/plain")) (-> (rr/response (:message response)) (rr/status ((response :outcome) outcomes->codes)))))) (schema/defn handle-get-ca-expirations [ca-settings :- ca/CaSettings] (let [response {:ca-certs (ca/ca-expiration-dates (:cacert ca-settings)) :crls (ca/crl-expiration-dates (:cacrl ca-settings))}] (-> (rr/response (cheshire/generate-string response)) (rr/status 200) (rr/content-type "application/json")))) (defn try-to-parse [body] (try (cheshire/parse-stream (io/reader body) true) (catch Exception e (log/debug e)))) (schema/defn certificate-issued? :- schema/Bool [settings :- ca/CaSettings subject :- schema/Str] (or (ca/certificate-exists? settings subject) (ca/in-cert-inventory-file? settings subject))) (schema/defn handle-cert-clean [request ca-settings :- ca/CaSettings report-activity] (if-let [json-body (try-to-parse (:body request))] ;; TODO support async mode (if (true? (:async json-body)) (-> (rr/response "Async mode is not currently supported.") (rr/status 400) (rr/content-type "text/plain")) (if-let [certnames (:certnames json-body)] (let [{existing-certs true missing-certs false} (group-by #(certificate-issued? ca-settings %) ;; ensure we process a unique set of certnames (distinct certnames)) message (when (seq missing-certs) (format "The following certs do not exist and cannot be revoked: %s" (vec missing-certs))) report-activity-fn (ca/create-report-activity-fn report-activity request)] (try (ca/revoke-existing-certs! ca-settings existing-certs report-activity-fn) (ca/delete-certificates! ca-settings existing-certs) (-> (rr/response (or message "Successfully cleaned all certs.")) (rr/status 200) (rr/content-type "text/plain")) (catch Exception e (log/info e (i18n/trs "Error while cleaning certs")) (-> (rr/response (str "Error while cleaning certs: " (.getMessage e))) (rr/status 500) (rr/content-type "text/plain"))))) (-> (rr/response "Missing required key: 'certnames'. Please supply the list of certs you want to clean.") (rr/status 400) (rr/content-type "text/plain")))) (-> (rr/response "Request body is not JSON.") (rr/status 400) (rr/content-type "text/plain")))) (schema/defn validate-cert-in-infra-list :- schema/Bool [request-cert :- X509Certificate infra-nodes-path :- schema/Str] (if infra-nodes-path (let [subject-name (utils/get-cn-from-x509-certificate request-cert)] (if (.exists (io/file infra-nodes-path)) (with-open [infra-nodes-reader (io/reader infra-nodes-path)] (let [infra-nodes (ca/read-infra-nodes infra-nodes-reader)] (boolean (some #(= subject-name %) infra-nodes)))) (do (log/info (i18n/trs "Unable to find infra-nodes file at {0}" infra-nodes-path)) false))) (do (log/info (i18n/trs "infra-nodes-path is nil, cannot validate certificate is allowed.")) false))) (schema/defn validate-header-cert-not-revoked :- (schema/maybe X509Certificate) "Given a certificate, validate that the certificate is not in the CRL. The messaging is specific to the header method of certificate delivery. If the certificate is valid, it is returned, otherwise return nil" [cert :- X509Certificate ca-settings :- ca/CaSettings] (if-not (ca/is-revoked? cert ca-settings) cert (log/warn (i18n/trs "Rejecting certificate request because the {0} was specified and the certificate is revoked." auth-middleware/header-cert-name)))) (schema/defn request->cert :- (schema/maybe X509Certificate) "Pull the client certificate from the request. Response includes the certificate as a java.security.cert.X509Certificate object or, if none can be found, nil. allow-header-cert-info determines whether to try to pull the certificate from an HTTP header (true) or from the certificate provided during SSL session negotiation (false). If allow-header-cert-info is false, and the cert is present in both the header and the request, validate that the cert in the request is in the infra list. If it isn't in the infra list, log the issue and return nil. If the header isn't set, return the cert from the request. " [request :- ring/Request {:keys [allow-header-cert-info infra-nodes-path] :as ca-settings} :- ca/CaSettings] (let [header-cert-val (get-in request [:headers auth-middleware/header-cert-name])] (if allow-header-cert-info (validate-header-cert-not-revoked (auth-middleware/header->cert header-cert-val) ca-settings) (if-let [request-cert (:ssl-client-cert request)] (if header-cert-val (if (validate-cert-in-infra-list request-cert infra-nodes-path) (validate-header-cert-not-revoked (auth-middleware/header->cert header-cert-val) ca-settings) (log/warn (i18n/trs "Rejecting certificate request because the {0} header was specified, but the client making the request was not in the allow list." auth-middleware/header-cert-name))) request-cert) (log/warn (i18n/trs "Request is missing a certificate for an endpoint that requires a certificate.")))))) (schema/def Certnames [schema/Str]) (schema/defn handle-bulk-cert-signing [request ca-settings :- ca/CaSettings report-activity] (let [json-body (try-to-parse (:body request)) certnames (:certnames json-body)] (if-let [schema-error (schema/check Certnames certnames)] (-> (rr/response (cheshire/generate-string {:kind :schema-violation :submitted certnames :error (str schema-error)})) (rr/status 422) (rr/content-type "application/json")) (-> (rr/response (cheshire/generate-string (ca/sign-multiple-certificate-signing-requests! certnames ca-settings report-activity))) (rr/status 200) (rr/content-type "application/json"))))) (schema/defn handle-bulk-cert-signing-all [ca-settings :- ca/CaSettings report-activity] (let [csr-files (-> (ca/get-paths-to-all-certificate-requests (:csrdir ca-settings)) (common/extract-file-names-from-paths) (common/remove-suffix-from-file-names ".pem")) results (ca/sign-multiple-certificate-signing-requests! csr-files ca-settings report-activity)] (-> (rr/response (cheshire/generate-string results)) (rr/status 200) (rr/content-type "application/json")))) (schema/defn ^:always-validate handle-cert-renewal "Given a request and the CA settings, if there is a cert present in the request (either in the ssl-client-cert property of the request, or as an x-client-cert field in the header when allow-header-cert-info is set to true) and the cert in the request is valid and signed by the this CA. then generate a renewed cert and return it in the response body" [request {:keys [cacert cakey allow-auto-renewal] :as ca-settings} :- ca/CaSettings report-activity] (if allow-auto-renewal (if-let [request-cert (request->cert request ca-settings)] (let [signing-cert (utils/pem->ca-cert cacert cakey)] (if (ca/cert-authority-id-match-ca-subject-id? request-cert signing-cert) (do (log/info (i18n/trs "Certificate present, processing renewal request")) (let [cert-signing-result (ca/renew-certificate! request-cert ca-settings report-activity) cert-writer (StringWriter.)] ;; has side effect of writing to the writer (utils/cert->pem! cert-signing-result cert-writer) (-> (rr/response (.toString cert-writer)) (rr/content-type "text/plain")))) (do (log/info (i18n/trs "Certificate present, but does not match signature")) (-> (rr/response (i18n/tru "Certificate present, but does not match signature")) (rr/status 403) (rr/content-type "text/plain"))))) (do (log/info (i18n/trs "No valid certificate found in renewal request")) (-> (rr/bad-request (i18n/tru "No valid certificate found in renewal request")) (rr/content-type "text/plain")))) (-> (rr/response "Not Found") (rr/status 404) (rr/content-type "text/plain")))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Web app (defn malformed "Returns a value indicating to liberator that the request is malformed, with the given error message assoc'ed into the context." [message] [true {::malformed message}]) (defn conflict "Returns a value indicating to liberator that the request is conflict with the server, with the given error message assoc'ed into the context." [message] [true {::conflict message}]) (defn get-desired-state [context] (keyword (get-in context [::json-body :desired_state]))) (defn merge-request-settings [settings context] (if-let [cert-ttl (get-in context [::json-body :cert_ttl])] (assoc settings :ca-ttl cert-ttl) settings)) (defn invalid-state-requested? [context] (when (= :put (get-in context [:request :request-method])) (when-let [desired-state (get-desired-state context)] (not (contains? #{:signed :revoked} desired-state))))) (def media-types #{"application/json" "text/pson" "pson"}) (defn content-type-valid? [context] (let [content-type (request/content-type (:request context))] (or (nil? content-type) (media-types content-type)))) (defn as-json-or-pson "This is a stupid hack because of PSON. We shouldn't have to do this, but liberator does not know how to serialize a map as PSON (as it does with JSON), so we have to tell it how." [x context] (let [representation-media-type (get-in context [:representation :media-type]) accept-header (-> context (get-in [:request :headers]) ((partial some #(when (= (string/lower-case (key %)) "accept") (val %))))) context-with-media-type (cond (not-empty representation-media-type) context (not-empty accept-header) (assoc-in context [:representation :media-type] accept-header) :else (assoc-in context [:representation :media-type] "application/json"))] (-> (cheshire/generate-string x) (representation/as-response context-with-media-type) (assoc :status 200) (representation/ring-response)))) (defn as-plain-text-response "Create a ring response based on the response info in the supplied context and a specific message. The message is assumed to be plain text and so is marked with a 'text/plain; charset=UTF-8' Content-Type header. This is needed for cases where liberator would not mark the Content-Type in the response as 'text/plain' on its own, which could otherwise result in the underlying webserver dumbly constructing the Content-Type as ';charset=UTF-8'. A Content-Type with a charset and no MIME value would be problematic for some clients to interpret." [context message] (-> message (representation/as-response context) (assoc :status (:status context)) (assoc-in [:headers "Content-Type"] "text/plain; charset=UTF-8") (representation/ring-response))) (defresource certificate-status [subject settings report-activity] :allowed-methods [:get :put :delete] :available-media-types media-types :can-put-to-missing? false :conflict? (fn [context] (let [desired-state (get-desired-state context)] (case desired-state :revoked ;; A signed cert must exist if we are to revoke it. (when-not (certificate-issued? settings subject) (conflict (i18n/tru "Cannot revoke certificate for host {0} without a signed certificate" subject))) :signed (or ;; A CSR must exist if we are to sign it. (when-not (ca/csr-exists? settings subject) (conflict (i18n/tru "Cannot sign certificate for host {0} without a certificate request" subject))) ;; And the CSR must be valid. (when-let [error-message (ca/validate-csr settings subject)] (conflict error-message)))))) :delete! (fn [_context] (ca/delete-certificate! settings subject) (ca/delete-certificate-request! settings subject)) :exists? (fn [context] ;; if we actually want to get the certificate state, we only care if the files ;; really exist, not if they are in the inventory file (if (= :get (get-in context [:request :request-method])) (or (ca/certificate-exists? settings subject) (ca/csr-exists? settings subject)) (or (certificate-issued? settings subject) (ca/csr-exists? settings subject)))) :handle-conflict (fn [context] (as-plain-text-response context (::conflict context))) :handle-exception (fn [context] (as-plain-text-response context (liberator-utils/exception-handler context))) :handle-not-implemented (fn [context] (when (= :put (get-in context [:request :request-method])) ; We've landed here because :exists? returned false, and we have set ; `:can-put-to-missing? false` above. This happens when ; a PUT request comes in with an invalid hostname/subject specified in ; in the URL; liberator is pushing us towards a 501 here, but instead ; we want to return a 404. There seems to be some disagreement as to ; which makes the most sense in general - see ; https://github.com/clojure-liberator/liberator/pull/120 ; ... but in our case, a 404 definitely makes more sense. (-> (assoc context :status 404) (as-plain-text-response (i18n/tru "Invalid certificate subject."))))) :handle-ok (fn [context] (-> (ca/get-cert-or-csr-status settings subject) (as-json-or-pson context))) :malformed? (fn [context] (when (= :put (get-in context [:request :request-method])) (if-let [body (get-in context [:request :body])] (if-let [json-body (try-to-parse body)] (if-let [desired-state (keyword (:desired_state json-body))] (if (schema/check ca/DesiredCertificateState desired-state) (malformed (i18n/tru "State {0} invalid; Must specify desired state of ''signed'' or ''revoked'' for host {1}." (name desired-state) subject)) (let [cert-ttl (:cert_ttl json-body)] (if (and cert-ttl (schema/check schema/Int cert-ttl)) (malformed (i18n/tru "cert_ttl specified for host {0} must be an integer, not \"{1}\"" subject cert-ttl)) ; this is the happy path. we have a body, it's parsable json, ; and the desired_state field is one of (signed revoked), and ; it potentially has a valid cert_ttl field [false {::json-body json-body}]))) (malformed (i18n/tru "Missing required parameter \"desired_state\""))) (malformed (i18n/tru "Request body is not JSON."))) (malformed (i18n/tru "Empty request body."))))) :handle-malformed (fn [context] (if-let [message (::malformed context)] message (i18n/tru "Bad Request."))) :known-content-type? (fn [context] (if (= :put (get-in context [:request :request-method])) (content-type-valid? context) true)) ;; Never return a 201, we're not creating a new cert or anything like that. :new? false :put! (fn [context] (let [desired-state (get-desired-state context) request (:request context) report-activity-fn (ca/create-report-activity-fn report-activity request)] (ca/set-certificate-status! (merge-request-settings settings context) subject desired-state report-activity-fn) (-> context (assoc-in [:representation :media-type] "text/plain"))))) (defresource certificate-statuses [request settings] :allowed-methods [:get] :available-media-types media-types :handle-exception (fn [context] (as-plain-text-response context (liberator-utils/exception-handler context))) :handle-ok (fn [context] (let [queried-state (get-in request [:params "state"])] (-> (if (some #(= queried-state %) ["requested" "signed" "revoked"]) (ca/filter-by-certificate-state settings queried-state) (ca/get-cert-and-csr-statuses settings)) (as-json-or-pson context))))) (schema/defn ^:always-validate web-routes :- bidi-schema/RoutePair [ca-settings :- ca/CaSettings report-activity] (comidi/routes (comidi/context ["/v1"] (ANY ["/certificate_status/" :subject] [subject] (certificate-status subject ca-settings report-activity)) (comidi/context ["/certificate_statuses/"] (ANY [[#"[^/]+" :ignored-but-required]] request (certificate-statuses request ca-settings)) (ANY [""] [] (middleware-utils/plain-response 400 "Missing URL Segment"))) (GET ["/certificate/" :subject] request (handle-get-certificate (get-in request [:params :subject]) ca-settings request)) (comidi/context ["/certificate_request/" :subject] (GET [""] [subject] (handle-get-certificate-request subject ca-settings)) (PUT [""] request (handle-put-certificate-request! ca-settings report-activity request)) (DELETE [""] [subject] (handle-delete-certificate-request! subject ca-settings))) (GET ["/certificate_revocation_list/" :ignored-node-name] request (handle-get-certificate-revocation-list request ca-settings)) (PUT ["/certificate_revocation_list"] request (handle-put-certificate-revocation-list! (:body request) ca-settings)) (GET ["/expirations"] _request (handle-get-ca-expirations ca-settings)) (PUT ["/clean"] request (handle-cert-clean request ca-settings report-activity)) (POST ["/certificate_renewal"] request (handle-cert-renewal request ca-settings report-activity)) (POST ["/sign"] request (handle-bulk-cert-signing request ca-settings report-activity)) (POST ["/sign/all"] _request (handle-bulk-cert-signing-all ca-settings report-activity))) (comidi/not-found "Not Found"))) (schema/defn ^:always-validate wrap-middleware :- IFn [handler :- IFn puppet-version :- schema/Str] (-> handler ;(liberator-dev/wrap-trace :header) ; very useful for debugging! (middleware/wrap-uncaught-errors :plain) (ringutils/wrap-with-puppet-version-header puppet-version) (middleware/wrap-response-logging))) (schema/defn ^:always-validate get-wrapped-handler :- IFn [route-handler :- IFn ca-settings :- ca/CaSettings path :- schema/Str authorization-fn :- IFn puppet-version :- schema/Str] ;; For backward compatibility, requests to the .../certificate_status* endpoint ;; will be authorized by a client-whitelist, if one is configured for ;; 'certificate_status'. When we are able to drop support for ;; client-whitelist authorization later on, we should be able to get rid of ;; the 'wrap-with-trapperkeeper-or-client-whitelist-authorization' function ;; and replace with a line chaining the handler into a call to ;; 'authorization-fn'. (let [whitelist-path (str path (when (not= \/ (last path)) "/") puppet-ca-API-version "/certificate_status")] (-> route-handler (ringutils/wrap-with-trapperkeeper-or-client-whitelist-authorization authorization-fn whitelist-path (get-in ca-settings [:access-control :certificate-status])) i18n/locale-negotiator (wrap-middleware puppet-version)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (schema/defn ^:always-validate v1-status :- status-core/StatusCallbackResponse [_level :- status-core/ServiceStatusDetailLevel] {:state :running :status {}}) certificate_authority_disabled_service.clj000066400000000000000000000017701470345337400353730ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/ca(ns puppetlabs.services.ca.certificate-authority-disabled-service (:require [puppetlabs.services.protocols.ca :refer [CaService]] [puppetlabs.trapperkeeper.core :as tk] [clojure.tools.logging :as log] [puppetlabs.i18n.core :as i18n])) (tk/defservice certificate-authority-disabled-service "Contains a NOOP version of the certificate authority service. This is required to maintain service loading order on installations which are not running a CA service." CaService [[:AuthorizationService wrap-with-authorization-check]] (initialize-master-ssl! [this master-settings certname] (log/info (i18n/trs "CA disabled; ignoring SSL initialization for Master"))) (retrieve-ca-cert! [this localcacert] (log/info (i18n/trs "CA disabled; ignoring retrieval of CA cert"))) (retrieve-ca-crl! [this localcacrl] (log/info (i18n/trs "CA disabled; ignoring retrieval of CA CRL"))) (get-auth-handler [this] wrap-with-authorization-check)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/ca/certificate_authority_service.clj000066400000000000000000000131751470345337400336250ustar00rootroot00000000000000(ns puppetlabs.services.ca.certificate-authority-service (:require [clojure.tools.logging :as log] [me.raynes.fs :as fs] [puppetlabs.trapperkeeper.core :as tk] [puppetlabs.trapperkeeper.services :refer [maybe-get-service] :as tk-services] [puppetlabs.trapperkeeper.services.protocols.filesystem-watch-service :as watch-protocol] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.services.ca.certificate-authority-core :as core] [puppetlabs.services.protocols.ca :refer [CaService]] [puppetlabs.comidi :as comidi] [puppetlabs.i18n.core :as i18n] [puppetlabs.trapperkeeper.services.status.status-core :as status-core] [puppetlabs.rbac-client.protocols.activity :refer [ActivityReportingService] :as activity-proto])) (def one-day-ms (* 24 60 60 1000)) (def ca-scheduled-job-group-id :ca-scheduled-job-group-id) (defn evaluate-crls-for-expiration [ca-settings] (try ;; don't allow exceptions to escape (ca/maybe-update-crls-for-expiration ca-settings) (catch Exception e (log/error e (i18n/trs "Failed to evaluate crls for expiration"))))) (tk/defservice certificate-authority-service CaService {:required [[:PuppetServerConfigService get-config get-in-config] [:WebroutingService add-ring-handler get-route] [:AuthorizationService wrap-with-authorization-check] [:FilesystemWatchService create-watcher] [:StatusService register-status] [:SchedulerService interspaced stop-jobs]] :optional [ActivityReportingService]} (init [this context] (let [path (get-route this) settings (ca/config->ca-settings (get-config)) puppet-version (get-in-config [:puppetserver :puppet-version]) custom-oid-file (get-in-config [:puppetserver :trusted-oid-mapping-file]) oid-mappings (ca/get-oid-mappings custom-oid-file) auth-handler (fn [request] (wrap-with-authorization-check request {:oid-map oid-mappings})) ca-crl-file (.getCanonicalPath (fs/file (get-in-config [:puppetserver :cacrl]))) host-crl-file (.getCanonicalPath (fs/file (get-in-config [:puppetserver :hostcrl]))) infra-nodes-file (.getCanonicalPath (fs/file (str (fs/parent ca-crl-file) "/infra_inventory.txt"))) watcher (create-watcher {:recursive false}) report-activity (if-let [activity-reporting-service (maybe-get-service this :ActivityReportingService)] (fn [& payload] (try (activity-proto/report-activity! activity-reporting-service (first payload)) (catch Exception e (log/error (i18n/trs "Reporting CA event failed with: {0}\nPayload: {1}" (.getMessage e) (first payload)))))) (constantly nil))] (ca/validate-settings! settings) (ca/initialize! settings) (log/info (i18n/trs "CA Service adding a ring handler")) (add-ring-handler this (core/get-wrapped-handler (-> (core/web-routes settings report-activity) ((partial comidi/context path)) comidi/routes->handler) settings path auth-handler puppet-version) {:normalize-request-uri true}) (when (not= ca-crl-file host-crl-file) (watch-protocol/add-watch-dir! watcher (fs/parent ca-crl-file)) (watch-protocol/add-callback! watcher (fn [events] (when (some #(and (:changed-path %) (= (.getCanonicalPath (:changed-path %)) ca-crl-file)) events) (ca/retrieve-ca-crl! ca-crl-file host-crl-file))))) (watch-protocol/add-watch-dir! watcher (fs/parent infra-nodes-file)) (watch-protocol/add-callback! watcher (fn [events] (when (some #(and (:changed-path %) (= (.getCanonicalPath (:changed-path %)) infra-nodes-file)) events) (ca/generate-infra-serials! settings)))) (register-status "ca" (status-core/get-artifact-version "puppetlabs" "puppetserver") 1 core/v1-status) (assoc context :auth-handler auth-handler :watcher watcher :ca-settings settings))) (start [this context] (log/info (i18n/trs "Starting CA service")) (interspaced one-day-ms #(evaluate-crls-for-expiration (:ca-settings context)) ca-scheduled-job-group-id) context) (stop [this context] (log/info (i18n/trs "Stopping CA service")) (stop-jobs ca-scheduled-job-group-id) (dissoc context :ca-settings)) (initialize-master-ssl! [this master-settings certname] (let [settings (ca/config->ca-settings (get-config))] (ca/initialize-master-ssl! master-settings certname settings))) (retrieve-ca-cert! [this localcacert] (ca/retrieve-ca-cert! (get-in-config [:puppetserver :cacert]) localcacert)) (retrieve-ca-crl! [this localcacrl] (ca/retrieve-ca-crl! (get-in-config [:puppetserver :cacrl]) localcacrl)) (get-auth-handler [this] (:auth-handler (tk-services/service-context this)))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/config/000077500000000000000000000000001470345337400256745ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/config/puppet_server_config_core.clj000066400000000000000000000103541470345337400336310ustar00rootroot00000000000000(ns ^{:doc "Core logic for the implementation of the PuppetServerConfigService in puppetlabs.services.config.puppet-server-config-service."} puppetlabs.services.config.puppet-server-config-core (:require [clojure.set :as set] [clojure.tools.logging :as log] [puppetlabs.kitchensink.core :refer [keyset]] [puppetlabs.services.jruby.jruby-puppet-service :as jruby] [schema.core :as schema] [clojure.string :as str] [puppetlabs.i18n.core :as i18n]) (:import (com.puppetlabs.puppetserver JRubyPuppet))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; config (def puppet-config-keys "The configuration values which, instead of being configured through Trapperkeeper's normal configuration service, are read from JRubyPuppet." #{:allow-duplicate-certs :autosign :cacert :cadir :cacrl :cakey :ca-name :capub :ca-ttl :certdir :certname :cert-inventory :codedir ; This is not actually needed in Puppet Server, but it's needed in PE (file sync) :csrdir :csr-attributes :dns-alt-names :hostcert :hostcrl :hostprivkey :hostpubkey :keylength :localcacert :manage-internal-file-permissions :privatekeydir :requestdir :serial :signeddir :ssl-client-header :ssl-client-verify-header :trusted-oid-mapping-file}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; internal helpers (defn keyword->setting [k] (-> (name k) (.replace "-" "_"))) (defn get-puppet-config-value "For a given keyword `k`, returns the configuration value (setting) from JRubyPuppet. Returns `nil` if Puppet does not have a setting for the given key. The keyword will be converted into the appropriate format before it is passed to Puppet - for example, if you want the value of Puppet's 'autoflush' setting, pass in `:autoflush`." [jruby-puppet k] {:pre [(keyword? k)]} (->> (keyword->setting k) (.getSetting jruby-puppet))) (schema/defn get-puppet-config* [jruby-puppet :- JRubyPuppet] (into {} (for [k puppet-config-keys] {k (get-puppet-config-value jruby-puppet k)}))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Schemas (def Config "Represents valid configuration data from Puppet. Ensures that * all config keys are present in the map, and there is a non-nil value for each key. * :puppet-version is present." (assoc (zipmap puppet-config-keys (repeat Object)) :puppet-version String)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; public API (defn validate-tk-config! "Ensure that Trapperkeeper's configuration data contains no conflicts with the keys we're going to load from JRuby (`puppet-config-keys`)." [tk-config] (let [key-conflicts (set/intersection (keyset tk-config) puppet-config-keys)] (when-not (empty? key-conflicts) (throw (Exception. (i18n/trs "The following configuration keys conflict with the values to be read from puppet: {0}" (str/join ", " (sort key-conflicts)))))))) (schema/defn ^:always-validate get-puppet-config :- Config "Returns all of the configuration values for puppetserver from JRubyPuppet." [jruby-service] {:post [(map? %)]} (jruby/with-jruby-puppet jruby-puppet jruby-service :get-puppet-config (let [config (get-puppet-config* jruby-puppet)] (assoc config :puppet-version (.puppetVersion jruby-puppet))))) (defn init-webserver! "Initialize Jetty with paths to puppetserver's SSL certs." [override-webserver-settings! webserver-settings puppet-config] (let [{:keys [hostcert localcacert hostcrl hostprivkey]} puppet-config overrides {:ssl-cert hostcert :ssl-key hostprivkey :ssl-ca-cert localcacert :ssl-crl-path hostcrl}] (if (some #((key %) webserver-settings) overrides) (log/info (i18n/trs "Not overriding webserver settings with values from core Puppet")) (do (log/info (i18n/trs "Initializing webserver settings from core Puppet")) (override-webserver-settings! overrides))))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/config/puppet_server_config_service.clj000066400000000000000000000042031470345337400343350ustar00rootroot00000000000000(ns ^{:doc "Implementation of the PuppetServerConfigService."} puppetlabs.services.config.puppet-server-config-service (:require [clojure.tools.logging :as log] [puppetlabs.kitchensink.core :as ks] [puppetlabs.trapperkeeper.core :as tk] [puppetlabs.services.protocols.puppet-server-config :refer [PuppetServerConfigService]] [puppetlabs.services.config.puppet-server-config-core :as core] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.i18n.core :as i18n])) (tk/defservice puppet-server-config-service PuppetServerConfigService [[:ConfigService get-config get-in-config] [:WebserverService override-webserver-settings!] [:JRubyPuppetService]] (init [this context] (let [tk-config (get-config)] (core/validate-tk-config! tk-config) (let [jruby-service (tk-services/get-service this :JRubyPuppetService) puppet-config (core/get-puppet-config jruby-service)] (log/debug (format "%s\n%s" (i18n/trs "Initializing with the following settings from core Puppet:") (ks/pprint-to-string puppet-config))) (core/init-webserver! override-webserver-settings! (get-in tk-config [:webserver :puppet-server] (get-in tk-config [:webserver])) puppet-config) (assoc context :puppet-config {:puppetserver puppet-config})))) (get-config [this] (let [context (tk-services/service-context this) puppet-config (:puppet-config context)] (merge puppet-config (get-config)))) (get-in-config [this ks] (let [context (tk-services/service-context this) puppet-config (:puppet-config context)] (or (get-in puppet-config ks) (get-in-config ks)))) (get-in-config [this ks default] (let [context (tk-services/service-context this) puppet-config (:puppet-config context)] (or (get-in puppet-config ks) (get-in-config ks default))))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/jruby/000077500000000000000000000000001470345337400255625ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/jruby/jruby_metrics_core.clj000066400000000000000000000530071470345337400321520ustar00rootroot00000000000000(ns puppetlabs.services.jruby.jruby-metrics-core (:require [schema.core :as schema] [puppetlabs.metrics :as metrics] [puppetlabs.services.jruby-pool-manager.jruby-schemas :as jruby-schemas] [clojure.string :as str] [clojure.tools.logging :as log] [puppetlabs.trapperkeeper.services.status.status-core :as status-core] [puppetlabs.comidi :as comidi] [puppetlabs.i18n.core :refer [trs]] [clj-time.core :as time] [clj-time.format :as time-format] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol]) (:import (com.codahale.metrics MetricRegistry Gauge Counter Histogram Meter Timer) (clojure.lang Atom IFn) (java.util.concurrent TimeUnit) (org.joda.time DateTime) (org.joda.time.format DateTimeFormatter) (org.slf4j MDC))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Schemas ;; creating some constants for lock state enumeration; using Strings ;; rather than keywords since these need to be serialized over the wire (def jruby-pool-lock-not-in-use (str :not-in-use)) (def jruby-pool-lock-requested (str :requested)) (def jruby-pool-lock-acquired (str :acquired)) (def JRubyPoolLockState (schema/enum jruby-pool-lock-not-in-use jruby-pool-lock-requested jruby-pool-lock-acquired)) (def JRubyLockEventType (schema/enum :lock-requested :lock-acquired :lock-released)) (def JRubyPoolLockStatus {:current-state JRubyPoolLockState :last-change-time schema/Str}) (def JRubyPoolLockRequestReason {:type (schema/eq :master-code-sync) :lock-request-id schema/Str}) (def JRubyMetrics {:num-jrubies Gauge :requested-count Counter :requested-jrubies-histo Histogram :borrow-count Counter :borrow-timeout-count Counter :borrow-retry-count Counter :return-count Counter :num-free-jrubies Gauge :free-jrubies-histo Histogram :borrow-timer Timer :wait-timer Timer :requested-instances Atom :borrowed-instances Atom :lock-wait-timer Timer :lock-held-timer Timer :lock-requests Atom :lock-status Atom :hostname schema/Str :metric-registry MetricRegistry :sampler-job-id schema/Any :queue-limit-hit-meter Meter}) (def TimestampedReason {:time Long :reason jruby-schemas/JRubyEventReason}) (def HttpRequestReasonInfo {:request {:request-method comidi/RequestMethod :route-id schema/Str :uri schema/Str} schema/Any schema/Any}) (def RequestReasonInfo (schema/conditional #(and (map? %) (contains? % :request)) HttpRequestReasonInfo :else jruby-schemas/JRubyEventReason)) (def TimestampedReasonWithRequestInfo (assoc TimestampedReason :reason RequestReasonInfo)) (def InstanceRequestInfo {:duration-millis schema/Num :reason RequestReasonInfo :time schema/Num}) (def TimerSummary {:count schema/Int :mean schema/Num :max schema/Num :rate schema/Num}) (def JRubyMetricsStatusV1 {(schema/optional-key :experimental) {:jruby-pool-lock-status JRubyPoolLockStatus :metrics {:num-jrubies schema/Int :num-free-jrubies schema/Int :requested-count schema/Int :borrow-count schema/Int :borrow-timeout-count schema/Int :borrow-retry-count schema/Int :return-count schema/Int :average-requested-jrubies schema/Num :average-free-jrubies schema/Num :average-borrow-time schema/Num :average-wait-time schema/Num :borrow-timers {schema/Keyword TimerSummary} :requested-instances [InstanceRequestInfo] :borrowed-instances [InstanceRequestInfo] :num-pool-locks schema/Int :average-lock-wait-time schema/Num :average-lock-held-time schema/Num :queue-limit-hit-count schema/Int :queue-limit-hit-rate schema/Num}}}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Private (schema/def ^:always-validate datetime-formatter :- DateTimeFormatter "The date/time formatter used to produce timestamps using clj-time. This matches the format used by PuppetDB." (time-format/formatters :date-time)) (schema/defn ^:always-validate format-date-time :- schema/Str "Given a DateTime object, return a human-readable, formatted string." [date-time :- DateTime] (time-format/unparse datetime-formatter date-time)) (schema/defn ^:always-validate timestamp :- schema/Str "Returns a nicely-formatted string of the current date/time." [] (format-date-time (time/now))) (schema/defn timestamped-reason :- TimestampedReason [reason :- jruby-schemas/JRubyEventReason] {:time (System/currentTimeMillis) :reason reason}) (schema/defn add-duration-to-instance :- InstanceRequestInfo [{:keys [time] :as instance} :- TimestampedReasonWithRequestInfo] (assoc instance :duration-millis (- (System/currentTimeMillis) time))) (schema/defn instance-request-info :- TimestampedReasonWithRequestInfo [instance :- TimestampedReason] (if-let [request (get-in instance [:reason :request])] (assoc-in instance [:reason :request] {:uri (:uri request) :request-method (:request-method request) :route-id (get-in request [:route-info :route-id] "unknown-http-request")}) instance)) (schema/defn ^:always-validate requested-instances-info :- [InstanceRequestInfo] [instances :- [TimestampedReason]] (map (comp add-duration-to-instance instance-request-info) instances)) (schema/defn timer-for-borrow-reason :- Timer "Create or return a named timer for a JRuby borrow reason. If the JRuby instance was borrowed to service a HTTP request, then the timer name is generated from the sanitized Comidi :route-id. If a Clojure Keyword was used as the JRuby borrow reason, then the timer is generated from the Keyword's name and namespace. Returns a timer named 'other' if the borrow reason does not match one of the above cases." [{:keys [hostname metric-registry]} :- JRubyMetrics request :- TimestampedReason] (let [request-info (instance-request-info request) reason (:reason request-info) timer-name (cond (nil? (schema/check HttpRequestReasonInfo reason)) (-> (get-in reason [:request :route-id]) ;; Remove ":" characters created by stringifying ;; Clojure keywords. (str/replace ":" "") ;; Remove segments created from regexes by Comidi. ;; Regexes contain characters that create escaping ;; problems in downstream services that use regexes ;; to search for or select metrics by name. (str/replace #"-\/.*\/" "")) (keyword? reason) (if-let [name-space (namespace reason)] (str name-space "." (name reason)) (name reason)) :else "other")] (->> timer-name (str "jruby.borrow-timer.") (metrics/host-metric-name hostname) (.timer metric-registry)))) (schema/defn borrow-timers :- java.util.Map "Returns a map of borrow timers from JRuby Metrics" [{:keys [metric-registry hostname]} :- JRubyMetrics] (let [metric-namespace (metrics/host-metric-name hostname "jruby.borrow-timer") ;; TODO: v4.0 of Dropwizard Metrics has a MetricFilter/startsWith ;; static method that returns a filter which can be passed ;; directly to .getTimers. metric-filter (partial filter (fn [[k _]] (str/starts-with? k metric-namespace)))] (->> (.getTimers metric-registry) metric-filter (into {})))) (schema/defn summarize-borrow-timers "Generates a summary for each JRuby borrow timer This function iterates through the list of registered JRuby borrow timers and summarizes each one." [{:keys [hostname] :as metrics} :- JRubyMetrics] (let [timer-namespace (metrics/host-metric-name hostname "jruby.borrow-timer") get-name (fn [timer-name] (if (= timer-namespace timer-name) "total" (str/replace-first timer-name (str timer-namespace ".") ""))) timer-summary (fn [timer] (let [snapshot (.getSnapshot timer)] {:count (.getCount timer) :mean (->> snapshot .getMean (.toMillis TimeUnit/NANOSECONDS)) :max (->> snapshot ;; Using 99.9th percentile instead of the ;; max as it is properly weighted for the ;; past 5 minutes. (.get999thPercentile) (.toMillis TimeUnit/NANOSECONDS)) :rate (.getFiveMinuteRate timer)}))] (->> (borrow-timers metrics) (map (fn [[k v]] (vector (keyword (get-name k)) (timer-summary v)))) (into {})))) (schema/defn track-successful-borrow-instance! [{:keys [borrow-count borrowed-instances]} :- JRubyMetrics reason :- jruby-schemas/JRubyEventReason id :- jruby-schemas/JRubyWorkerId] (.inc borrow-count) (when (get @borrowed-instances id) (log/warn (trs "JRuby instance ''{0}'' borrowed, but it appears to have already been in use!" id))) (swap! borrowed-instances assoc id (timestamped-reason reason))) (schema/defn track-request-instance! [{:keys [requested-count requested-instances]} :- JRubyMetrics {:keys [reason] :as event} :- jruby-schemas/JRubyRequestedEvent] (.inc requested-count) (swap! requested-instances assoc event (timestamped-reason reason))) (schema/defn track-borrow-instance! [{:keys [borrow-timeout-count requested-instances wait-timer] :as metrics} :- JRubyMetrics {jruby-instance :instance requested-event :requested-event reason :reason worker-id :worker-id :as event} :- jruby-schemas/JRubyBorrowedEvent] (condp (fn [pred instance] (pred instance)) jruby-instance nil? (.inc borrow-timeout-count) jruby-schemas/shutdown-poison-pill? (log/warn (trs "Not tracking jruby instance borrowed because server is shutting down")) jruby-schemas/jruby-instance? (track-successful-borrow-instance! metrics reason worker-id)) (if-let [ta (get @requested-instances requested-event)] (do (.update wait-timer (- (System/currentTimeMillis) (:time ta)) TimeUnit/MILLISECONDS) (swap! requested-instances dissoc requested-event)) (log/warn (trs "Unable to find request event for borrowed JRuby instance: {0}" event)))) (schema/defn track-return-instance! [{:keys [return-count borrowed-instances borrow-timer] :as metrics} :- JRubyMetrics {:keys [instance worker-id]} :- jruby-schemas/JRubyReturnedEvent] (.inc return-count) (when (jruby-schemas/jruby-instance? instance) (if-let [ta (get @borrowed-instances worker-id)] (let [elapsed-time (- (System/currentTimeMillis) (:time ta)) per-reason-timer (timer-for-borrow-reason metrics ta)] (.update borrow-timer elapsed-time TimeUnit/MILLISECONDS) (.update per-reason-timer elapsed-time TimeUnit/MILLISECONDS) (MDC/put "jruby.borrow-time" (Long/toString elapsed-time)) (swap! borrowed-instances dissoc worker-id)) (log/warn (trs "JRuby instance ''{0}'' returned, but no record of when it was borrowed!" worker-id))))) (schema/defn ^:always-validate update-pool-lock-status! :- JRubyPoolLockStatus [jruby-pool-lock-status :- Atom jruby-lock-event-type :- JRubyLockEventType] (swap! jruby-pool-lock-status assoc :current-state (case jruby-lock-event-type :lock-requested jruby-pool-lock-requested :lock-acquired jruby-pool-lock-acquired :lock-released jruby-pool-lock-not-in-use) :last-change-time (timestamp))) (schema/defn ^:always-validate track-lock-requested! [{:keys [lock-requests lock-status]} :- JRubyMetrics {:keys [lock-request-id]} :- JRubyPoolLockRequestReason] (swap! lock-requests assoc lock-request-id {:state :requested :time (System/currentTimeMillis)}) (update-pool-lock-status! lock-status :lock-requested)) (schema/defn ^:always-validate track-lock-acquired! [{:keys [lock-requests lock-status lock-wait-timer]} :- JRubyMetrics {:keys [lock-request-id]} :- JRubyPoolLockRequestReason] (if-let [lock-request (get @lock-requests lock-request-id)] (do (.update lock-wait-timer (- (System/currentTimeMillis) (:time lock-request)) TimeUnit/MILLISECONDS) (swap! lock-requests assoc lock-request-id {:state :acquired :time (System/currentTimeMillis)})) (log/warn (trs "Lock request ''{0}'' acquired, but no record of when it was requested!" lock-request-id))) (update-pool-lock-status! lock-status :lock-acquired)) (schema/defn ^:always-validate track-lock-released! [{:keys [lock-requests lock-status lock-held-timer]} :- JRubyMetrics {:keys [lock-request-id]} :- JRubyPoolLockRequestReason] (if-let [lock-request (get @lock-requests lock-request-id)] (do (.update lock-held-timer (- (System/currentTimeMillis) (:time lock-request)) TimeUnit/MILLISECONDS) (swap! lock-requests dissoc lock-request-id)) (log/warn (trs "Lock request ''{0}'' released, but no record of when it was acquired!" lock-request-id))) (update-pool-lock-status! lock-status :lock-released)) (schema/defn track-free-instance-count! [metrics :- JRubyMetrics free-instance-count :- schema/Int] (.update (:free-jrubies-histo metrics) free-instance-count)) (schema/defn track-requested-instance-count! [{:keys [requested-jrubies-histo requested-instances]} :- JRubyMetrics] (.update requested-jrubies-histo (count @requested-instances))) (schema/defn sample-jruby-metrics! [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) metrics :- JRubyMetrics] (log/trace (trs "Sampling JRuby metrics")) (track-free-instance-count! metrics (jruby-protocol/free-instance-count jruby-service)) (track-requested-instance-count! metrics)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (schema/defn ^:always-validate init-metrics :- JRubyMetrics [hostname :- schema/Str max-active-instances :- schema/Int free-instances-fn :- IFn registry :- MetricRegistry] {:num-jrubies (metrics/register registry (metrics/host-metric-name hostname "jruby.num-jrubies") (metrics/gauge max-active-instances)) :requested-count (.counter registry (metrics/host-metric-name hostname "jruby.request-count")) ;; See the comments on `jruby-metrics-service/schedule-metrics-sampler!` for ;; an explanation of how we're using these histograms. :requested-jrubies-histo (.histogram registry (metrics/host-metric-name hostname "jruby.requested-jrubies-histo")) :borrow-count (.counter registry (metrics/host-metric-name hostname "jruby.borrow-count")) :borrow-timeout-count (.counter registry (metrics/host-metric-name hostname "jruby.borrow-timeout-count")) :borrow-retry-count (.counter registry (metrics/host-metric-name hostname "jruby.borrow-retry-count")) :return-count (.counter registry (metrics/host-metric-name hostname "jruby.return-count")) :num-free-jrubies (metrics/register registry (metrics/host-metric-name hostname "jruby.num-free-jrubies") (proxy [Gauge] [] (getValue [] (free-instances-fn)))) ;; See the comments on `jruby-metrics-service/schedule-metrics-sampler!` for ;; an explanation of how we're using these histograms. :free-jrubies-histo (.histogram registry (metrics/host-metric-name hostname "jruby.free-jrubies-histo")) :borrow-timer (.timer registry (metrics/host-metric-name hostname "jruby.borrow-timer")) :wait-timer (.timer registry (metrics/host-metric-name hostname "jruby.wait-timer")) :requested-instances (atom {}) :borrowed-instances (atom {}) :lock-wait-timer (.timer registry (metrics/host-metric-name hostname "jruby.lock-wait-timer")) :lock-held-timer (.timer registry (metrics/host-metric-name hostname "jruby.lock-held-timer")) :lock-requests (atom {}) :lock-status (atom {:current-state jruby-pool-lock-not-in-use :last-change-time (timestamp)}) :metric-registry registry :hostname hostname :sampler-job-id nil :queue-limit-hit-meter (.meter registry (metrics/host-metric-name hostname "jruby.queue-limit-hit-meter"))}) (schema/defn jruby-event-callback [metrics :- JRubyMetrics event :- jruby-schemas/JRubyEvent] (if-let [[func & args] (case (:type event) :instance-requested [track-request-instance! metrics event] :instance-borrowed [track-borrow-instance! metrics event] :instance-returned [track-return-instance! metrics event] :lock-requested [track-lock-requested! metrics (:reason event)] :lock-acquired [track-lock-acquired! metrics (:reason event)] :lock-released [track-lock-released! metrics (:reason event)] nil)] (try (apply func args) (catch Exception e (log/error e (trs "Error ocurred while recording metrics for jruby event type: {0}" (:type event))) (throw e))) (throw (IllegalStateException. (trs "Unrecognized jruby event type: {0}" (:type event)))))) (schema/defn ^:always-validate v1-status :- status-core/StatusCallbackResponse [metrics :- JRubyMetrics level :- status-core/ServiceStatusDetailLevel] (let [{:keys [num-jrubies requested-count requested-jrubies-histo borrow-count borrow-timeout-count borrow-retry-count return-count free-jrubies-histo num-free-jrubies borrow-timer wait-timer requested-instances borrowed-instances lock-status lock-wait-timer lock-held-timer queue-limit-hit-meter]} metrics level>= (partial status-core/compare-levels >= level)] {:state :running :status (cond-> ;; no status info at ':critical' level {} ;; no extra status at ':info' level yet (level>= :info) identity (level>= :debug) (assoc :experimental {:jruby-pool-lock-status @lock-status :metrics {:num-jrubies (.getValue num-jrubies) :num-free-jrubies (.getValue num-free-jrubies) :requested-count (.getCount requested-count) :borrow-count (.getCount borrow-count) :borrow-timeout-count (.getCount borrow-timeout-count) :borrow-retry-count (.getCount borrow-retry-count) :return-count (.getCount return-count) :average-requested-jrubies (metrics/mean requested-jrubies-histo) :average-free-jrubies (metrics/mean free-jrubies-histo) :average-borrow-time (metrics/mean-millis borrow-timer) :average-wait-time (metrics/mean-millis wait-timer) :borrow-timers (summarize-borrow-timers metrics) :requested-instances (requested-instances-info (vals @requested-instances)) :borrowed-instances (requested-instances-info (vals @borrowed-instances)) :num-pool-locks (.getCount lock-held-timer) :average-lock-wait-time (metrics/mean-millis lock-wait-timer) :average-lock-held-time (metrics/mean-millis lock-held-timer) :queue-limit-hit-count (.getCount queue-limit-hit-meter) :queue-limit-hit-rate (.getFiveMinuteRate queue-limit-hit-meter) }}))})) ;; This function schedules some metrics sampling to happen on a background thread. ;; The reason it is necessary to do this is because the metrics histograms are ;; sample-based, as opposed to time-based, and we are interested in keeping a ;; time-based average for certain metrics. e.g. if we only updated the ;; "free-instance-count" average when an instance was borrowed or returned, then, ;; if there was a period where there was no load on the server, the histogram ;; would not be getting any updates at all and the average would appear to ;; remain flat, when actually it should be changing (increasing, presumably, ;; because there should be plenty of free jruby instances available in the pool). (schema/defn ^:always-validate schedule-metrics-sampler! [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) metrics :- JRubyMetrics interspaced :- IFn] (interspaced 5000 (partial sample-jruby-metrics! jruby-service metrics))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/jruby/jruby_metrics_service.clj000066400000000000000000000067141470345337400326650ustar00rootroot00000000000000(ns puppetlabs.services.jruby.jruby-metrics-service (:require [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [puppetlabs.trapperkeeper.core :as tk] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.services.jruby.jruby-metrics-core :as jruby-metrics-core] [clojure.tools.logging :as log] [puppetlabs.trapperkeeper.services.status.status-core :as status-core] [puppetlabs.services.protocols.jruby-metrics :as jruby-metrics-protocol] [puppetlabs.i18n.core :refer [trs]])) (def jruby-metrics-service-status-version 1) ;; Default list of allowed histograms/timers (def default-metrics-allowed-hists ["jruby.borrow-timer" "jruby.free-jrubies-histo" "jruby.lock-held-timer" "jruby.lock-wait-timer" "jruby.requested-jrubies-histo" "jruby.wait-timer"]) ;; Default list of allowed values/counts (def default-metrics-allowed-vals ["jruby.borrow-count" "jruby.borrow-retry-count" "jruby.borrow-timeout-count" "jruby.num-free-jrubies" "jruby.num-jrubies" "jruby.request-count" "jruby.return-count"]) (def default-metrics-allowed (concat default-metrics-allowed-hists default-metrics-allowed-vals)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (tk/defservice jruby-metrics-service jruby-metrics-protocol/JRubyMetricsService [[:ConfigService get-in-config] [:JRubyPuppetService register-event-handler] [:MetricsService get-metrics-registry get-server-id update-registry-settings] [:SchedulerService interspaced stop-job] [:StatusService register-status]] (init [this context] (let [jruby-service (tk-services/get-service this :JRubyPuppetService) metrics-server-id (get-server-id) max-active-instances (-> (tk-services/get-service this :JRubyPuppetService) tk-services/service-context (get-in [:pool-context :config :max-active-instances])) metrics (jruby-metrics-core/init-metrics metrics-server-id max-active-instances (fn [] (jruby-protocol/free-instance-count jruby-service)) (get-metrics-registry :puppetserver))] (update-registry-settings :puppetserver {:default-metrics-allowed default-metrics-allowed}) (register-status "jruby-metrics" (status-core/get-artifact-version "puppetlabs" "puppetserver") jruby-metrics-service-status-version (partial jruby-metrics-core/v1-status metrics)) (assoc context :metrics metrics))) (start [this context] (let [jruby-service (tk-services/get-service this :JRubyPuppetService) {:keys [metrics]} (tk-services/service-context this) sampler-job-id (jruby-metrics-core/schedule-metrics-sampler! jruby-service metrics interspaced)] (register-event-handler (partial jruby-metrics-core/jruby-event-callback metrics)) (assoc-in context [:metrics :sampler-job-id] sampler-job-id))) (get-metrics [this] (:metrics (tk-services/service-context this))) (stop [this context] (log/info (trs "JRuby Metrics Service: stopping metrics sampler job")) (stop-job (get-in context [:metrics :sampler-job-id])) (log/info (trs "JRuby Metrics Service: stopped metrics sampler job")) context)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj000066400000000000000000000474601470345337400320270ustar00rootroot00000000000000(ns puppetlabs.services.jruby.jruby-puppet-core (:require [clojure.tools.logging :as log] [schema.core :as schema] [puppetlabs.kitchensink.core :as ks] [puppetlabs.services.jruby.jruby-puppet-schemas :as jruby-puppet-schemas] [puppetlabs.services.jruby-pool-manager.jruby-schemas :as jruby-schemas] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.jruby.puppet-environments :as puppet-env] [puppetlabs.trapperkeeper.services.protocols.metrics :as metrics] [puppetlabs.i18n.core :as i18n] [clojure.string :as str]) (:import (com.puppetlabs.puppetserver PuppetProfiler JRubyPuppet) (clojure.lang IFn) (java.util HashMap) (com.codahale.metrics MetricRegistry))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Constants (def ruby-code-dir "The name of the directory containing the ruby code in this project. This directory is relative to `src/ruby` and works from source because the `src/ruby` directory is defined as a resource in `project.clj` which places the directory on the classpath which in turn makes the directory available on the JRuby load path. Similarly, this works from the uberjar because this directory is placed into the root of the jar structure which is on the classpath. See also: https://www.javadoc.io/doc/org.jruby/jruby-core/latest/org/jruby/runtime/load/LoadService.html" "uri:classloader:/puppetserver-lib") (def default-http-connect-timeout "The default number of milliseconds that the client will wait for a connection to be established. Currently set to 2 minutes." (* 2 60 1000)) (def default-http-socket-timeout "The default number of milliseconds that the client will allow for no data to be available on the socket. Currently set to 20 minutes." (* 20 60 1000)) (def default-http-metrics-enabled "The default for whether or not to enable http client metrics. Currently set to true." true) (def default-server-conf-dir "/etc/puppetlabs/puppet") (def default-server-code-dir "/etc/puppetlabs/code") (def default-server-log-dir "/var/log/puppetlabs/puppetserver") (def default-server-run-dir "/var/run/puppetlabs/puppetserver") (def default-server-var-dir "/opt/puppetlabs/server/data/puppetserver") (def default-vendored-gems-dir "/opt/puppetlabs/server/data/puppetserver/vendored-jruby-gems") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Private (schema/defn ^:always-validate managed-load-path :- [schema/Str] "Return a list of ruby LOAD_PATH directories built from the user-configurable ruby-load-path setting of the jruby-puppet configuration." [ruby-load-path :- [schema/Str]] (cons ruby-code-dir ruby-load-path)) (schema/defn ^:always-validate config->puppet-config :- HashMap "Given the raw jruby-puppet configuration section, return a HashMap with the configuration necessary for ruby Puppet." [config :- jruby-puppet-schemas/JRubyPuppetConfig] (let [puppet-config (new HashMap)] (doseq [[setting-name dir] [[:server-conf-dir "confdir"] [:server-code-dir "codedir"] [:server-var-dir "vardir"] [:server-run-dir "rundir"] [:server-log-dir "logdir"]]] (when-let [value (get config setting-name)] (.put puppet-config dir (ks/absolute-path value)))) (when (:disable-i18n config) ; The value for disable-i18n is stripped in Puppet::Server::PuppetConfig ; so that only the key is outputted, so that '--disable_18n' is used, not ; '--disable_i18n true' (.put puppet-config "disable_i18n" true)) puppet-config)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (def MetricsInfo {:metric-registry MetricRegistry :server-id schema/Str}) (schema/defn get-initialize-pool-instance-fn :- IFn [config :- jruby-puppet-schemas/JRubyPuppetConfig profiler :- (schema/maybe PuppetProfiler) metrics-service multithreaded :- schema/Bool] (fn [jruby-instance] (let [{:keys [http-client-ssl-protocols http-client-cipher-suites http-client-connect-timeout-milliseconds http-client-idle-timeout-milliseconds http-client-metrics-enabled track-lookups]} config scripting-container (:scripting-container jruby-instance)] (.runScriptlet scripting-container "require 'puppet/server/master'") (let [ruby-puppet-class (.runScriptlet scripting-container "Puppet::Server::Master") puppet-config (config->puppet-config config) puppetserver-config (HashMap.) env-registry (puppet-env/environment-registry)] (when http-client-ssl-protocols (.put puppetserver-config "ssl_protocols" (into-array String http-client-ssl-protocols))) (when http-client-cipher-suites (.put puppetserver-config "cipher_suites" (into-array String http-client-cipher-suites))) (when http-client-metrics-enabled (doto puppetserver-config (.put "metric_registry" (metrics/get-metrics-registry metrics-service :puppetserver)) (.put "server_id" (metrics/get-server-id metrics-service)))) (doto puppetserver-config (.put "multithreaded" multithreaded) (.put "track_lookups" track-lookups) (.put "profiler" profiler) (.put "environment_registry" env-registry) (.put "http_connect_timeout_milliseconds" http-client-connect-timeout-milliseconds) (.put "http_idle_timeout_milliseconds" http-client-idle-timeout-milliseconds)) (let [jruby-puppet (.callMethodWithArgArray scripting-container ruby-puppet-class "new" (into-array Object [puppet-config puppetserver-config]) JRubyPuppet)] (-> jruby-instance (assoc :jruby-puppet jruby-puppet) (assoc :environment-registry env-registry))))))) (schema/defn cleanup-fn [instance] (.terminate (:jruby-puppet instance))) (schema/defn extract-jruby-config [config :- {schema/Keyword schema/Any}] (select-keys config (keys jruby-schemas/JRubyConfig))) (schema/defn multithreaded? [config :- {schema/Keyword schema/Any}] (get config :multithreaded false)) (schema/defn extract-puppet-config [config :- {schema/Keyword schema/Any}] (select-keys config (map schema/explicit-schema-key (keys jruby-puppet-schemas/JRubyPuppetConfig)))) (schema/defn extract-http-config "The config is allowed to be nil because the http-client section isn't required in puppetserver's tk config" [config :- (schema/maybe {schema/Keyword schema/Any})] (select-keys config [:ssl-protocols :cipher-suites :connect-timeout-milliseconds :idle-timeout-milliseconds :metrics-enabled])) (schema/defn ^:always-validate initialize-gem-path [{:keys [gem-home gem-path] :as jruby-config} :- {schema/Keyword schema/Any}] (if gem-path (assoc jruby-config :gem-path (str/join ":" gem-path)) (assoc jruby-config :gem-path (str gem-home ":" default-vendored-gems-dir)))) (schema/defn ^:always-validate initialize-puppet-config :- jruby-puppet-schemas/JRubyPuppetConfig [http-config :- {schema/Keyword schema/Any} jruby-puppet-config :- {schema/Keyword schema/Any} multithreaded :- schema/Bool] (when multithreaded (log/info (i18n/trs "Disabling i18n for puppet because using multithreaded jruby"))) (let [config (-> jruby-puppet-config (assoc :http-client-ssl-protocols (:ssl-protocols http-config)) (assoc :http-client-cipher-suites (:cipher-suites http-config)) (assoc :http-client-connect-timeout-milliseconds (get http-config :connect-timeout-milliseconds default-http-connect-timeout)) (assoc :http-client-idle-timeout-milliseconds (get http-config :idle-timeout-milliseconds default-http-socket-timeout)) (assoc :http-client-metrics-enabled (get http-config :metrics-enabled default-http-metrics-enabled)) (update-in [:server-conf-dir] #(or % (:master-conf-dir jruby-puppet-config) default-server-conf-dir)) (update-in [:server-var-dir] #(or % (:master-var-dir jruby-puppet-config) default-server-var-dir)) (update-in [:server-code-dir] #(or % (:master-code-dir jruby-puppet-config) default-server-code-dir)) (update-in [:server-run-dir] #(or % (:master-run-dir jruby-puppet-config) default-server-run-dir)) (update-in [:server-log-dir] #(or % (:master-log-dir jruby-puppet-config) default-server-log-dir)) (update-in [:max-requests-per-instance] #(or % 0)) (assoc :disable-i18n multithreaded) (dissoc :environment-class-cache-enabled))] (assoc config :master-conf-dir (:server-conf-dir config) :master-var-dir (:server-var-dir config) :master-code-dir (:server-code-dir config) :master-run-dir (:server-run-dir config) :master-log-dir (:server-log-dir config)))) (schema/defn create-jruby-config :- jruby-schemas/JRubyConfig "Handles creating a valid JRubyConfig map for use in the jruby-puppet-service. This method: * Creates the appropriate lifecycle functions * overrides the default ruby-load-path to include the ruby code directory from this project" [jruby-puppet-config :- jruby-puppet-schemas/JRubyPuppetConfig jruby-config :- {schema/Keyword schema/Any} agent-shutdown-fn :- IFn profiler :- (schema/maybe PuppetProfiler) metrics-service] (let [initialize-pool-instance-fn (get-initialize-pool-instance-fn jruby-puppet-config profiler metrics-service (multithreaded? jruby-config)) lifecycle-fns {:shutdown-on-error agent-shutdown-fn :initialize-pool-instance initialize-pool-instance-fn :cleanup cleanup-fn} modified-jruby-config (-> jruby-config (assoc :ruby-load-path (managed-load-path (:ruby-load-path jruby-config))) initialize-gem-path)] (jruby-core/initialize-config (assoc modified-jruby-config :lifecycle lifecycle-fns)))) (schema/defn initialize-and-create-jruby-config :- jruby-schemas/JRubyConfig "Handles the initialization of the jruby-puppet config (from the puppetserver.conf file), for the purpose of converting it to the structure required by the jruby-utils library (puppetlabs.services.jruby-pool-manager.jruby-schemas/JRubyConfig). This function will use data from the :jruby-puppet and :http-client sections of puppetserver.conf, from raw-config. If values are not provided, everything in :http-client :jruby-puppet will be given default values, except for :ruby-load-path and :gem-home, which are required. The 1-arity function takes only a config and supplies a default of nil for the profiler and an empty fn for the agent-shutdown-fn. This arity is intended for uses where a jruby-config is required but will not be used to create a pool, such as the cli ruby subcommands. The 5-arity function takes a profiler object and the metrics service. The profiler is placed into the puppetserver config through the :initialize-pool-instance lifecycle function. If the `http-client -> metrics-enabled` setting is set to true, then the metrics service is used to get a metrics registry for the `:puppetserver` domain, and the server id - these are also placed into the puppetserver config. The agent-shutdown-fn is run when a jruby-instance is terminated." ([raw-config :- {:jruby-puppet {schema/Keyword schema/Any} (schema/optional-key :http-client) {schema/Keyword schema/Any} schema/Keyword schema/Any}] (initialize-and-create-jruby-config raw-config nil (fn []) nil)) ([raw-config :- {schema/Keyword schema/Any} profiler :- (schema/maybe PuppetProfiler) agent-shutdown-fn :- IFn metrics-service] (when (get-in raw-config [:jruby-puppet :compat-version]) (log/errorf "%s" (i18n/trs "The jruby-puppet.compat-version setting is no longer supported.")) (throw (IllegalArgumentException. (i18n/trs "jruby-puppet.compat-version setting no longer supported")))) (let [jruby-puppet (:jruby-puppet raw-config) jruby-puppet-config (initialize-puppet-config (extract-http-config (:http-client raw-config)) (extract-puppet-config jruby-puppet) (multithreaded? jruby-puppet)) uninitialized-jruby-config (-> (extract-jruby-config (:jruby-puppet raw-config)) (assoc :max-borrows-per-instance (:max-requests-per-instance jruby-puppet-config)))] (create-jruby-config jruby-puppet-config uninitialized-jruby-config agent-shutdown-fn profiler metrics-service)))) (def EnvironmentCacheEntry "Represents an environment with each cacheable info service as a key. The value for each info service is a map that contains a: `:tag` Representing the latest value computed for that info service (this is the sanitized Etag used in subsequent HTTP cache checks). `:version` Representing the version of the environment's content at a given tag. This is incremented whenever the environment cache is invalidated or new information is retrieved from the environment. New tag values are only accepted if they have a content-version parameter that matches the **currently** stored version, signifying that the cache was not invalidated while the tag was being computed." {:classes {:tag (schema/maybe schema/Str) :version schema/Int} :transports {:tag (schema/maybe schema/Str) :version schema/Int}}) (def EnvironmentCache "Maps each environment to its cache entry" {schema/Str EnvironmentCacheEntry}) (schema/defn ^:always-validate environment-cache-entry :- EnvironmentCacheEntry "Creates an initial EnvironmentCacheEntry" [] {:classes {:tag nil :version 1} :transports {:tag nil :version 1}}) (schema/defn ^:always-validate invalidate-environment-cache-entry :- EnvironmentCacheEntry "Sets all info service tags to nil and increments their content versions" [maybe-environment-cache-entry :- (schema/maybe EnvironmentCacheEntry)] (-> (or maybe-environment-cache-entry (environment-cache-entry)) (update-in [:classes :version] inc) (update-in [:transports :version] inc) (assoc-in [:classes :tag] nil) (assoc-in [:transports :tag] nil))) (schema/defn ^:always-validate invalidate-environment :- EnvironmentCache "Return the EnvironmentCache with named environment invalidated." [environment-cache :- EnvironmentCache env-name :- schema/Str] (->> env-name (get environment-cache) invalidate-environment-cache-entry (assoc environment-cache env-name))) (schema/defn ^:always-validate environment-class-info-cache-updated-with-tag :- EnvironmentCache "DEPRECATED: see `maybe-update-environment-info-service-cache` Updates the class info service tag in the given EnvironmentCache for the named environment, **if** the prior-content-version and the version currently in the cache are the same. If the two content versions are not the same, eg the cache has been invalidated, or otherwise moved since the action that computed the tag started, then the update will silently fail. Returns the given EnvironmentCache regardless of update status." [environment-cache :- EnvironmentCache env-name :- schema/Str tag :- (schema/maybe schema/Str) prior-content-version :- schema/Int] (if (= (get-in environment-cache [env-name :classes :version]) prior-content-version) (-> environment-cache (assoc-in [env-name :classes :tag] tag) (update-in [env-name :classes :version] inc)) environment-cache)) (schema/defn ^:always-validate maybe-update-environment-info-service-cache :- EnvironmentCache "Updates the requested info service tag in the given EnvironmentCache for the named environment, **if** the prior-content-version and the version currently in the cache are the same. If the two content versions are not the same, eg the cache has been invalidated, or otherwise moved since the action that computed the tag started, then the update will silently fail. Returns the given EnvironmentCache regardless of update status." [environment-cache :- EnvironmentCache env-name :- schema/Str svc-id :- schema/Keyword tag :- (schema/maybe schema/Str) prior-content-version :- schema/Int] (if (= (get-in environment-cache [env-name svc-id :version]) prior-content-version) (-> environment-cache (assoc-in [env-name svc-id :tag] tag) (update-in [env-name svc-id :version] inc)) environment-cache)) (schema/defn ^:always-validate ensure-environment :- EnvironmentCache "Ensure the given environment exists within the EnvironmentCache." [environment-cache :- (schema/atom EnvironmentCache) env-name :- schema/Str] (swap! environment-cache #(if (contains? % env-name) % (assoc % env-name (environment-cache-entry))))) (schema/defn ^:always-validate get-environment-class-info-cache-generation-id! :- schema/Int "DEPRECATED: see `get-info-service-version` for replacement. Get the current cache generation id for a specific environment's info cache. If no entry for the environment had existed at the point this function was called this function would, as a side effect, populate a new entry for that environment into the cache." [environment-cache :- (schema/atom EnvironmentCache) env-name :- schema/Str] (-> (ensure-environment environment-cache env-name) (get-in [env-name :classes :version]))) (schema/defn ^:always-validate get-cached-content-version :- schema/Int "Get the current version for a specific service's content within an environment, initializes environment if it did not already exist." [environment-cache :- (schema/atom EnvironmentCache) env-name :- schema/Str info-service :- schema/Keyword] (-> (ensure-environment environment-cache env-name) (get-in [env-name info-service :version]))) (schema/defn ^:always-validate mark-environment-expired! "Mark the specified environment expired in the clojure managed cache and, using the Environment Expiration Service, in each JRuby instance." [context :- jruby-schemas/PoolContext env-name :- schema/Str environment-cache :- (schema/atom EnvironmentCache)] (swap! environment-cache invalidate-environment env-name) (doseq [jruby-instance (jruby-core/registered-instances context)] (-> jruby-instance :environment-registry (puppet-env/mark-environment-expired! env-name)))) (schema/defn ^:always-validate mark-all-environments-expired! "Mark all cached environments expired, in all JRuby instances." [context :- jruby-schemas/PoolContext environment-cache :- (schema/atom EnvironmentCache)] (swap! environment-cache (partial ks/mapvals invalidate-environment-cache-entry)) (doseq [jruby-instance (jruby-core/registered-instances context)] (-> jruby-instance :environment-registry puppet-env/mark-all-environments-expired!))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/jruby/jruby_puppet_schemas.clj000066400000000000000000000071451470345337400325160ustar00rootroot00000000000000(ns puppetlabs.services.jruby.jruby-puppet-schemas (:require [schema.core :as schema])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Schemas (def JRubyPuppetConfig "Schema defining the config map for the JRubyPuppet pooling functions. The keys should have the following values: * :server-conf-dir - file path to Puppet Server's conf dir; if not specified, will use the puppet default. * :server-code-dir - file path to Puppet Server's code dir; if not specified, will use the puppet default. * :server-var-dir - path to the Puppet Server's var dir; if not specified, will use the puppet default. * :server-run-dir - path to the Puppet Server's run dir; if not specified, will use the puppet default. * :server-log-dir - path to the Puppet Server's log dir; if not specified, will use the puppet default. * :track-lookups - a boolean to turn on tracking hiera lookups during compilation; if not specified, no tracking is enabled. * :disable-i18n - a boolean to pass to Puppet to control whether or not to translate; if not specified or false, the flag is not passed to Puppet's initialization. * :http-client-ssl-protocols - A list of legal SSL protocols that may be used when https client requests are made. * :http-client-cipher-suites - A list of legal SSL cipher suites that may be used when https client requests are made. * :http-client-connect-timeout-milliseconds - The amount of time, in milliseconds, that an outbound HTTP connection will wait to connect before giving up. If 0, the timeout is infinite and if negative, the value is undefined in the application and governed by the system default behavior. * :http-client-idle-timeout-milliseconds - The amount of time, in milliseconds, that an outbound HTTP connection will wait for data to be available after a request is sent before closing the socket. If 0, the timeout is infinite and if negative, the value is undefined by the application and is governed by the default system behavior. * :http-client-metrics-enabled - Whether to use http client metrics. * :boltlib-path - Optional array containing path(s) to bolt modules. This path will be prepended to AST compilation modulepath. This is required for compiling AST that contains bolt types." {(schema/optional-key :server-conf-dir) (schema/maybe schema/Str) (schema/optional-key :server-code-dir) (schema/maybe schema/Str) (schema/optional-key :server-var-dir) (schema/maybe schema/Str) (schema/optional-key :server-run-dir) (schema/maybe schema/Str) (schema/optional-key :server-log-dir) (schema/maybe schema/Str) (schema/optional-key :track-lookups) schema/Bool (schema/optional-key :disable-i18n) schema/Bool :http-client-ssl-protocols [schema/Str] :http-client-cipher-suites [schema/Str] :http-client-connect-timeout-milliseconds schema/Int :http-client-idle-timeout-milliseconds schema/Int :http-client-metrics-enabled schema/Bool :max-requests-per-instance schema/Int (schema/optional-key :boltlib-path) [schema/Str] ;; Deprecated in favor of their `server-*` counterparts. ;; to be removed in Puppet 8. (schema/optional-key :master-conf-dir) (schema/maybe schema/Str) (schema/optional-key :master-code-dir) (schema/maybe schema/Str) (schema/optional-key :master-var-dir) (schema/maybe schema/Str) (schema/optional-key :master-run-dir) (schema/maybe schema/Str) (schema/optional-key :master-log-dir) (schema/maybe schema/Str)}) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/jruby/jruby_puppet_service.clj000066400000000000000000000171341470345337400325320ustar00rootroot00000000000000(ns puppetlabs.services.jruby.jruby-puppet-service (:require [clojure.tools.logging :as log] [puppetlabs.services.jruby.jruby-puppet-core :as core] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.trapperkeeper.core :as trapperkeeper] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.services.protocols.jruby-puppet :as jruby] [puppetlabs.i18n.core :as i18n])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public ;; This service uses TK's normal config service instead of the ;; PuppetServerConfigService. This is because that service depends on this one. (trapperkeeper/defservice jruby-puppet-pooled-service jruby/JRubyPuppetService [[:ConfigService get-config] [:ShutdownService shutdown-on-error] [:PuppetProfilerService get-profiler] [:PoolManagerService create-pool] MetricsService] (init [this context] (log/info (i18n/trs "Initializing the JRuby service")) (let [config (get-config) metrics-service (tk-services/get-service this :MetricsService) jruby-config (core/initialize-and-create-jruby-config config (get-profiler) (partial shutdown-on-error (tk-services/service-id this)) metrics-service) pool-context (create-pool jruby-config)] (log/info (i18n/trs "JRuby version info: {0}" jruby-core/jruby-version-info)) (-> context (assoc :pool-context pool-context) (assoc :environment-class-info-tags (atom {}))))) (stop [this context] (let [{:keys [pool-context]} (tk-services/service-context this)] ;; Only flush the pool if there is a pool-context available. No pool-context ;; would be available if an exception were to be thrown during service ;; initialization before the pool-context were created - e.g., during the ;; the initialization of an upstream service. (when pool-context (jruby-core/flush-pool-for-shutdown! pool-context))) context) (free-instance-count [this] (let [pool-context (:pool-context (tk-services/service-context this)) pool (jruby-core/get-pool pool-context)] (jruby-core/free-instance-count pool))) (mark-environment-expired! [this env-name] (let [{:keys [environment-class-info-tags pool-context]} (tk-services/service-context this)] (core/mark-environment-expired! pool-context env-name environment-class-info-tags))) (mark-all-environments-expired! [this] (let [{:keys [environment-class-info-tags pool-context]} (tk-services/service-context this)] (core/mark-all-environments-expired! pool-context environment-class-info-tags))) (get-environment-class-info [this jruby-instance env-name] (.getClassInfoForEnvironment jruby-instance env-name)) (get-environment-transport-info [this jruby-instance env-name] (.getTransportInfoForEnvironment jruby-instance env-name)) (compile-catalog [this jruby-instance request-options] (.compileCatalog jruby-instance request-options)) (compile-ast [this jruby-instance compile-options boltlib-path] (.compileAST jruby-instance compile-options boltlib-path)) (get-environment-module-info [this jruby-instance env-name] (.getModuleInfoForEnvironment jruby-instance env-name)) (get-all-environment-module-info [this jruby-instance] (.getModuleInfoForAllEnvironments jruby-instance)) (get-environment-class-info-tag [this env-name] (let [environment-class-info (:environment-class-info-tags (tk-services/service-context this))] (get-in @environment-class-info [env-name :classes :tag]))) (get-cached-info-tag [this env-name info-service] (let [environment-class-info (:environment-class-info-tags (tk-services/service-context this))] (get-in @environment-class-info [env-name info-service :tag]))) (get-environment-class-info-cache-generation-id! [this env-name] (let [environment-class-info (:environment-class-info-tags (tk-services/service-context this))] (core/get-environment-class-info-cache-generation-id! environment-class-info env-name))) (get-cached-content-version [this env-name info-service] (let [environment-class-info (:environment-class-info-tags (tk-services/service-context this))] (core/get-cached-content-version environment-class-info env-name info-service))) (set-environment-class-info-tag! [this env-name tag cache-generation-id-before-tag-computed] (let [environment-class-info (:environment-class-info-tags (tk-services/service-context this))] (swap! environment-class-info core/environment-class-info-cache-updated-with-tag env-name tag cache-generation-id-before-tag-computed))) (set-cache-info-tag! [this env-name info-service-id tag initial-content-version] (let [environment-class-info (:environment-class-info-tags (tk-services/service-context this))] (swap! environment-class-info core/maybe-update-environment-info-service-cache env-name info-service-id tag initial-content-version))) (get-task-data [this jruby-instance env-name module-name task-name] (.getTaskData jruby-instance env-name module-name task-name)) (get-tasks [this jruby-instance env-name] (.getTasks jruby-instance env-name)) (get-plan-data [this jruby-instance env-name module-name plan-name] (.getPlanData jruby-instance env-name module-name plan-name)) (get-plans [this jruby-instance env-name] (.getPlans jruby-instance env-name)) (flush-jruby-pool! [this] (let [service-context (tk-services/service-context this) {:keys [pool-context]} service-context] (jruby-core/flush-pool! pool-context))) (get-jruby-thread-dump [this] (let [service-context (tk-services/service-context this) {:keys [pool-context]} service-context] (jruby-core/get-jruby-thread-dump pool-context))) (get-pool-context [this] (:pool-context (tk-services/service-context this))) (register-event-handler [this callback-fn] (let [pool-context (:pool-context (tk-services/service-context this))] (jruby-core/register-event-handler pool-context callback-fn)))) (defmacro with-jruby-puppet "A convenience macro that wraps jruby/with-jruby-instance. jruby-puppet is bound to the jruby-puppet object found in the borrowed jruby-instance" [jruby-puppet jruby-service reason & body] `(let [pool-context# (jruby/get-pool-context ~jruby-service)] (jruby-core/with-jruby-instance jruby-instance# pool-context# ~reason (let [~jruby-puppet (:jruby-puppet jruby-instance#)] ~@body)))) (defmacro with-lock "A convenience macro that wraps jruby/with-lock. Does the work of extracting the pool-context from the service and passes it to with-lock" [jruby-service reason & body] `(let [pool-context# (jruby/get-pool-context ~jruby-service)] (jruby-core/with-lock pool-context# ~reason ~@body))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/jruby/puppet_environments.clj000066400000000000000000000036071470345337400324060ustar00rootroot00000000000000(ns puppetlabs.services.jruby.puppet-environments (:import (com.puppetlabs.puppetserver EnvironmentRegistry)) (:require [clojure.tools.logging :as log] [puppetlabs.i18n.core :as i18n])) (defprotocol EnvironmentStateContainer (environment-state [this]) (mark-all-environments-expired! [this]) (mark-environment-expired! [this env-name])) (defn environment-registry [] (let [state (atom {}) mark-expired! (fn [acc env-name] (assoc-in acc [env-name :expired] true)) mark-all-expired! (fn [m] (reduce mark-expired! m (keys m)))] (reify EnvironmentRegistry (registerEnvironment [_this env-name] (when-not env-name (throw (IllegalArgumentException. (i18n/trs "Missing environment name!")))) (log/debug (i18n/trs "Registering environment ''{0}''" env-name)) (swap! state assoc-in [(keyword env-name) :expired] false) nil) (isExpired [_this env-name] (when-not env-name (throw (IllegalArgumentException. (i18n/trs "Missing environment name!")))) (get-in @state [(keyword env-name) :expired] true)) (removeEnvironment [_this env-name] (when-not env-name (throw (IllegalArgumentException. (i18n/trs "Missing environment name!")))) (log/debug (i18n/trs "Removing environment ''{0}'' from registry" env-name)) (swap! state dissoc (keyword env-name)) nil) EnvironmentStateContainer (environment-state [_this] state) (mark-all-environments-expired! [_this] (log/info (i18n/trs "Marking all registered environments as expired.")) (swap! state mark-all-expired!)) (mark-environment-expired! [_this env-name] (log/info (i18n/trs "Marking environment ''{0}'' as expired." env-name)) (swap! state mark-expired! (keyword env-name)))))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/legacy_routes/000077500000000000000000000000001470345337400272745ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/legacy_routes/legacy_routes_core.clj000066400000000000000000000176271470345337400336600ustar00rootroot00000000000000(ns puppetlabs.services.legacy-routes.legacy-routes-core (:require [clojure.string :as str] [puppetlabs.comidi :as comidi] [ring.util.codec :as ring-codec] [ring.util.response :as ring-response] [schema.core :as schema]) (:import (clojure.lang IFn))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Schemas (def LegacyHandlerInfo "A map of the three pieces of data needed to implement a legacy re-routing ring handler." {:mount schema/Str :handler IFn :api-version schema/Str}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; v3 => v4 header translation support functions ; TODO: Improve the naive parsing here with a real library like ; https://github.com/ToBeReplaced/http-accept-headers (defn- map-accept-header "Convert Accept: raw, s media types to Accept: binary. NOTE: This method does not conform to RFC-2616 Accept: header specification. The split on `,` is naive, the method should take into account `;` parameters and such to be RFC compliant, but puppet agent does not use this format so implementing the full spec is unnecessary." [request] (if-let [accept (get-in request [:headers "accept"])] (let [vals (map str/lower-case (str/split accept #"\s*,\s*"))] (assoc-in request [:headers "accept"] (->> vals (replace {"raw" "binary", "s" "binary"}) (distinct) (str/join ", ")))) request)) (defn- respond-with-content-type-text-plain "Return a new ring handler with a ring middleware wrapped around `handler` that unconditionally adds the Content-Type: text/plain header to the response." [handler] (fn [request] (ring-response/content-type (handler request) "text/plain"))) (defn- decode-query-string "Parses the given query string into a map. If `query-str` is nil then an empty map is returned." [query-str] {:pre [(or (nil? query-str) (string? query-str))] :post [(map? %)]} (if (str/blank? query-str) {} (ring-codec/form-decode query-str))) (defn- add-query-param "Given a query string or map of query parameters, add the given key and value to it. If the given query string is empty or nil then the resulting string will be the single KEY=VALUE expression. If the key already exists in the query string its value will be replaced." [query-params key value] {:pre [(or (map? query-params) (string? query-params) (nil? query-params)) (or (string? key) (keyword? key)) (string? value)] :post [(string? %)]} (let [param-pairs (if (not (map? query-params)) (decode-query-string query-params) query-params)] (ring-codec/form-encode (assoc param-pairs key value)))) (defn- add-source-permissions-param "Add the source_permissions header to the request. This is needed since this was considered a default in Puppet 3.x and is now turned off by default in Puppet 4.x. See SERVER-684." [handler] (fn [request] (let [{:keys [query-string]} request query-keys (decode-query-string query-string) source-perms-val (or (get query-keys "source_permissions") "use") updated-request (assoc request :query-string (add-query-param query-keys "source_permissions" source-perms-val))] (handler updated-request)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Handler wrapper (schema/defn ^:always-validate request-compatibility-wrapper :- IFn "Given a Puppet 3.x request, convert it to a Puppet 4.x request." [{:keys [handler mount api-version]} :- LegacyHandlerInfo request] (let [{{environment :environment} :params uri :uri query-string :query-string} request path-info (str "/" (-> (str/split uri #"/" 3) (nth 2))) compat-request (-> request (map-accept-header) (assoc :path-info (str "/" api-version path-info) :context mount :uri (str mount "/" api-version path-info) :query-string (if environment (add-query-param query-string "environment" environment) query-string)) (dissoc :params :route-params))] (handler compat-request))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Routing (defn v2_0-routes "Creates the compojure routes to handle the 3.X master's '/v2.0' routes." [request-handler] (comidi/routes (comidi/GET "/environments" request (request-handler request)))) (defn legacy-master-routes [master-request-handler] (comidi/routes (comidi/GET ["/node/" [#".*" :rest]] request (master-request-handler request)) (comidi/GET ["/file_content/" [#".*" :rest]] request (master-request-handler request)) (comidi/GET ["/file_metadatas/" [#".*" :rest]] request ((add-source-permissions-param master-request-handler) request)) (comidi/GET ["/file_metadata/" [#".*" :rest]] request ((add-source-permissions-param master-request-handler) request)) (comidi/GET ["/file_bucket_file/" [#".*" :rest]] request ((respond-with-content-type-text-plain master-request-handler) request)) ;; Coercing Content-Type to "application/octet-stream" for Puppet 4 ;; compatibility. (comidi/PUT ["/file_bucket_file/" [#".*" :rest]] request (master-request-handler (-> request (assoc :content-type "application/octet-stream") ; deprecated in ring >= 1.2 (assoc-in [:headers "content-type"] "application/octet-stream")))) ; ring >= 1.2 spec (comidi/HEAD ["/file_bucket_file/" [#".*" :rest]] request (master-request-handler request)) (comidi/GET ["/catalog/" [#".*" :rest]] request (master-request-handler request)) (comidi/POST ["/catalog/" [#".*" :rest]] request (master-request-handler request)) (comidi/PUT ["/report/" [#".*" :rest]] request (master-request-handler request)) (comidi/GET ["/status/" [#".*" :rest]] request (master-request-handler request)))) (defn legacy-ca-routes [ca-request-handler] (comidi/routes (comidi/ANY ["/certificate_status/" [#".*" :rest]] request (ca-request-handler request)) (comidi/ANY ["/certificate_statuses/" [#".*" :rest]] request (ca-request-handler request)) (comidi/GET ["/certificate/" [#".*" :rest]] request (ca-request-handler request)) (comidi/GET ["/certificate_revocation_list/" [#".*" :rest]] request (ca-request-handler request)) (comidi/GET ["/certificate_request/" [#".*" :rest]] request (ca-request-handler request)) (comidi/PUT ["/certificate_request/" [#".*" :rest]] request (ca-request-handler request)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (schema/defn add-root-path-to-route-id :- (schema/pred fn?) [handler :- (schema/pred fn?) path :- schema/Str] (fn [request] (handler (update-in request [:route-info :route-id] #(str (subs path 1) "-" %))))) (schema/defn ^:always-validate build-ring-handler :- IFn [master-handler-info :- LegacyHandlerInfo ca-handler-info :- (schema/maybe LegacyHandlerInfo)] (let [master-handler #(request-compatibility-wrapper master-handler-info %) master-routes (legacy-master-routes master-handler) ca-routes (when ca-handler-info (legacy-ca-routes #(request-compatibility-wrapper ca-handler-info %))) root-routes (vec (filter (complement nil?) [master-routes ca-routes]))] (comidi/routes->handler (comidi/routes (comidi/context "/v2.0" (v2_0-routes master-handler)) [["/" :environment] root-routes])))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/legacy_routes/legacy_routes_service.clj000066400000000000000000000121531470345337400343550ustar00rootroot00000000000000(ns puppetlabs.services.legacy-routes.legacy-routes-service (:require [puppetlabs.trapperkeeper.core :as tk] [clojure.tools.logging :as log] [puppetlabs.comidi :as comidi] [puppetlabs.services.legacy-routes.legacy-routes-core :as legacy-routes-core] [puppetlabs.services.ca.certificate-authority-core :as ca-core] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.services.master.master-core :as master-core] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.i18n.core :as i18n] [puppetlabs.metrics.http :as http-metrics])) (tk/defservice legacy-routes-service [[:WebroutingService add-ring-handler get-route] [:RequestHandlerService handle-request] [:PuppetServerConfigService get-config] [:JRubyPuppetService] [:AuthorizationService wrap-with-authorization-check] [:CaService get-auth-handler] [:MasterService]] (init [this context] (let [ca-service (tk-services/get-service this :CaService) path (get-route this) config (get-config) puppet-version (get-in config [:puppetserver :puppet-version]) master-service (tk-services/get-service this :MasterService) master-ns (keyword (tk-services/service-symbol master-service)) master-metrics (-> master-service tk-services/service-context :http-metrics) master-route-config (master-core/get-master-route-config master-ns config) jruby-service (tk-services/get-service this :JRubyPuppetService) master-routes (comidi/context path (master-core/root-routes handle-request identity jruby-service identity (fn [_ _ _] (throw (IllegalStateException. (i18n/trs "Versioned code not supported.")))) (constantly nil) false nil (get-in config [:puppetserver :certname]))) master-route-handler (comidi/routes->handler master-routes) master-mount (master-core/get-master-mount master-ns master-route-config) master-handler-info {:mount master-mount :handler (-> (master-core/wrap-middleware master-route-handler (get-auth-handler) puppet-version) (http-metrics/wrap-with-request-metrics master-metrics) (legacy-routes-core/add-root-path-to-route-id master-mount) (comidi/wrap-with-route-metadata master-routes)) :api-version master-core/puppet-API-version} real-ca-service? (= (namespace (tk-services/service-symbol ca-service)) "puppetlabs.services.ca.certificate-authority-service") ca-settings (ca/config->ca-settings (get-config)) ca-route-handler (-> (ca-core/web-routes ca-settings nil) ((partial comidi/context path)) comidi/routes->handler) ca-handler-info (when real-ca-service? (let [ca-mount (get-route ca-service)] {:mount ca-mount :handler (ca-core/get-wrapped-handler ca-route-handler ca-settings ca-mount (get-auth-handler) puppet-version) :api-version ca-core/puppet-ca-API-version})) ring-handler (legacy-routes-core/build-ring-handler master-handler-info ca-handler-info)] (add-ring-handler this ring-handler {:normalize-request-uri true})) context) (start [this context] (log/info (i18n/trs "The legacy routing service has successfully started and is now ready to handle requests")) context)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/master/000077500000000000000000000000001470345337400257225ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/master/master_core.clj000066400000000000000000001677241470345337400307400ustar00rootroot00000000000000(ns puppetlabs.services.master.master-core (:require [bidi.bidi :as bidi] [bidi.schema :as bidi-schema] [cheshire.core :as json] [clojure.java.io :as io] [clojure.string :as str] [clojure.tools.logging :as log] [me.raynes.fs :as fs] [puppetlabs.comidi :as comidi] [puppetlabs.http.client.common :as http-client-common] [puppetlabs.http.client.metrics :as http-client-metrics] [puppetlabs.i18n.core :as i18n] [puppetlabs.kitchensink.core :as ks] [puppetlabs.metrics :as metrics] [puppetlabs.metrics.http :as http-metrics] [puppetlabs.puppetserver.common :as ps-common] [puppetlabs.puppetserver.jruby-request :as jruby-request] [puppetlabs.puppetserver.ringutils :as ringutils] [puppetlabs.ring-middleware.core :as middleware] [puppetlabs.ring-middleware.utils :as middleware-utils] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [puppetlabs.trapperkeeper.services.status.status-core :as status-core] [ring.middleware.params :as ring] [ring.util.response :as rr] [schema.core :as schema] [slingshot.slingshot :refer [throw+ try+]]) (:import (clojure.lang IFn) (com.codahale.metrics Gauge MetricRegistry) (com.fasterxml.jackson.core JsonParseException) (java.io FileInputStream) (java.lang.management ManagementFactory) (java.util List Map Map$Entry) (org.jruby.exceptions RaiseException) (org.jruby RubySymbol))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Constants (def puppet-API-version "v3") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Private (def EnvironmentClassesFileClassParameter "Schema for an individual parameter found in a class defined within an environment_classes file. Includes the name of the parameter. Optionally, if available in the parameter definition, includes the type, source text for the parameter's default value, and a literal (primitive data type) representation of the parameter's default value. For example, if a class parameter were defined like this in a Puppet manifest ... Integer $someint = 3 ... then the map representation of that parameter would be: {:name \"someint\", :type \"Integer\", :default_source \"3\", :default_literal 3 } For a parameter default value which contains an expression - something that cannot be coerced into a primitive data type - the map representation omits the default_literal. For example, this parameter definition in a Puppet manifest ... String $osfam = \"$::osfamily\" ... would produce a map representation which looks like this ... {:name \"osfam\", :type \"String\", :default_source \"\"$::osfamily\"\", } The data types that could be used in the value for a :default_literal may vary over time, as the Puppet language continues to evolve. For this reason, the more permissive schema/Any is used here. General data types that we could see based on current types that the Puppet language allows today are in the table below: Puppet | :default_literal value ================================================ String | java.lang.String Boolean | java.lang.Boolean Float/Numeric | java.lang.Double Integer/Numeric | java.lang.Long Array | clojure.lang.LazySeq Hash | clojure.lang.PersistentTreeMap For the Regexp, Undef, Default, any Hash objects (top-level or nested within another Array or Hash) whose keys are not of type String, and any Array or Hash objects (top-level or nested within another Array or Hash) which contain a Regexp, Undef, or Default typed value, the :default_literal value will not be populated. These are not populated because they cannot be represented in JSON transfer without some loss of fidelity as compared to what the original data type from the manifest was." {:name schema/Str (schema/optional-key :type) schema/Str (schema/optional-key :default_source) schema/Str (schema/optional-key :default_literal) schema/Any}) (def EnvironmentClassesFileClass "Schema for an individual class found within an environment_classes file entry. Includes the name of the class and a vector of information about each parameter found in the class definition." {:name schema/Str :params [EnvironmentClassesFileClassParameter]}) (def EnvironmentClassesFileWithError "Schema for an environment_classes file that could not be parsed. Includes the path to the file and an error string containing details about the problem encountered during parsing." {:path schema/Str :error schema/Str}) (def EnvironmentClassesFileWithClasses "Schema for an environment_classes file that was successfully parsed. Includes the path to the file and a vector of information about each class found in the file." {:path schema/Str :classes [EnvironmentClassesFileClass]}) (def EnvironmentClassesFileEntry "Schema for an individual file entry which is part of the return payload for an environment_classes request." (schema/conditional #(contains? % :error) EnvironmentClassesFileWithError #(contains? % :classes) EnvironmentClassesFileWithClasses)) (def EnvironmentClassesInfo "Schema for the return payload an environment_classes request." {:name schema/Str :files [EnvironmentClassesFileEntry]}) (def EnvironmentModuleInfo "Schema for a given module that can be returned within the :modules key in EnvironmentModulesInfo." {:name schema/Str :version (schema/maybe schema/Str)}) (def EnvironmentModulesInfo "Schema for the return payload for an environment_classes request." {:name schema/Str :modules [EnvironmentModuleInfo]}) (def TaskData "Response from puppet's TaskInformationService for data on a single task, *after* it has been converted to a Clojure map." {:metadata (schema/maybe {schema/Keyword schema/Any}) :files [{:name schema/Str :path schema/Str}] (schema/optional-key :error) {:msg schema/Str :kind schema/Str :details {schema/Keyword schema/Any}}}) (def TaskDetails "A filled-in map of information about a task." {:metadata {schema/Keyword schema/Any} :name schema/Str :files [{:filename schema/Str :sha256 schema/Str :size_bytes schema/Int :uri {:path schema/Str :params {:environment schema/Str (schema/optional-key :code_id) schema/Str}}}]}) (def PlanData "Response from puppet's PlanInformationService for data on a single plan, *after* it has been converted to a Clojure map." {:metadata (schema/maybe {schema/Keyword schema/Any}) :files [{:name schema/Str :path schema/Str}] (schema/optional-key :error) {:msg schema/Str :kind schema/Str :details {schema/Keyword schema/Any}}}) (def PlanDetails "A filled-in map of information about a plan." {:metadata {schema/Keyword schema/Any} :name schema/Str}) (defn obj-or-ruby-symbol-as-string "If the supplied object is of type RubySymbol, returns a string representation of the RubySymbol. Otherwise, just returns the original object." [obj] (if (instance? RubySymbol obj) (.asJavaString obj) obj)) (defn obj->keyword "Attempt to convert the supplied object to a Clojure keyword. On failure to do so, throws an IllegalArgumentException." [obj] (if-let [obj-as-keyword (-> obj obj-or-ruby-symbol-as-string keyword)] obj-as-keyword (throw (IllegalArgumentException. (i18n/trs "Object cannot be coerced to a keyword: {0}" obj))))) (defn sort-nested-info-maps "For a data structure, recursively sort any nested maps and sets descending into map values, lists, vectors and set members as well. The result should be that all maps in the data structure become explicitly sorted with natural ordering. This can be used before serialization to ensure predictable serialization. The returned data structure is not a transient so it is still able to be modified, therefore caution should be taken to avoid modification else the data will lose its sorted status. This function was copypasta'd from clj-kitchensink's core/sort-nested-maps. sort-nested-maps can only deep sort a structure that contains native Clojure types, whereas this function includes a couple of changes which handle the sorting of the data structure returned from JRuby: 1) This function sorts keys within any `java.util.Map`, as opposed to just an object for which `map?` returns true. 2) This function attempts to coerces any keys found within a map to a Clojure keyword before using `sorted-map` to sort the keys. `sorted-map` would otherwise throw an error upon encountering a non-keyword type key." [data] (cond (instance? Map data) (into (sorted-map) (for [[k v] data] [(obj->keyword k) (sort-nested-info-maps v)])) (instance? Iterable data) (map sort-nested-info-maps data) :else data)) (schema/defn ^:always-validate if-none-match-from-request :- (schema/maybe String) "Retrieve the value of an 'If-None-Match' HTTP header from the supplied Ring request. If the header is not found, returns nil." [request :- {schema/Keyword schema/Any}] ;; SERVER-1153 - For a non-nil value, the characters '--gzip' will be ;; stripped from the end of the value which is returned. The '--gzip' ;; characters are added by the Jetty web server to an HTTP Etag response ;; header for cases in which the corresponding response payload has been ;; gzipped. Newer versions of Jetty, 9.3.x series, have logic in the ;; GzipHandler to strip these characters back off of the If-None-Match header ;; value before the Ring request would see it. The version of Jetty being ;; used at the time this code was written (9.2.10), however, did not have this ;; logic to strip the "--gzip" characters from the incoming header. This ;; function compensates for that by stripping the characters here - before ;; other Puppet Server code would use it. When/if Puppet Server is upgraded to ;; a version of trapperkeeper-webserver-jetty9 which is based on Jetty 9.3.x ;; or newer, it may be safe to take out the line that removes the '--gzip' ;; characters. (some-> (rr/get-header request "If-None-Match") (str/replace #"--gzip$" ""))) (schema/defn ^:always-validate add-path-to-file-entry :- Map "Convert the value for a manifest file entry into an appropriate map for use in serializing an environment_classes response to JSON." [file-detail :- Map file-name :- schema/Str] (.put file-detail "path" file-name) file-detail) (schema/defn ^:always-validate manifest-info-from-jruby->manifest-info-for-json :- EnvironmentClassesFileEntry "Convert the per-manifest file information received from the jruby service into an appropriate map for use in serializing an environment_classes response to JSON." [file-info :- Map$Entry] (-> file-info val (add-path-to-file-entry (key file-info)) sort-nested-info-maps)) (schema/defn ^:always-validate class-info-from-jruby->class-info-for-json :- EnvironmentClassesInfo "Convert a class info map received from the jruby service into an appropriate map for use in serializing an environment_classes response to JSON. The map that this function returns should be 'sorted' by key - both at the top-level and within any nested map - so that it will consistently serialize to the exact same content. For this reason, this function and the functions that this function calls use the `sorted-map` and `sort-nested-java-maps` helper functions when constructing / translating maps." [info-from-jruby :- Map environment :- schema/Str] (->> info-from-jruby (map manifest-info-from-jruby->manifest-info-for-json) (sort-by :path) (vec) (sorted-map :name environment :files))) (schema/defn ^:always-validate response-with-etag :- ringutils/RingResponse "Create a Ring response, including the supplied 'body' and an HTTP 'Etag' header set to the supplied 'etag' parameter." [body :- schema/Str etag :- schema/Str] (-> body (rr/response) (rr/header "Etag" etag))) (schema/defn ^:always-validate not-modified-response :- ringutils/RingResponse "Create an HTTP 304 (Not Modified) response, including an HTTP 'Etag' header set to the supplied 'etag' parameter." [etag] (-> "" (response-with-etag etag) (rr/status 304))) (schema/defn ^:always-validate all-tasks-response! :- ringutils/RingResponse "Process the info, returning a Ring response to be propagated back up to the caller of the endpoint. Returns environment as a list of objects for an eventual future in which tasks for all environments can be requested, and a given task will list all the environments it is found in." [info-from-jruby :- [{schema/Any schema/Any}] environment :- schema/Str] (let [format-task (fn [task-object] {:name (:name task-object) :private (get-in task-object [:metadata :private] false) :description (get-in task-object [:metadata :description] "") :environment [{:name environment :code_id nil}]})] (->> (map format-task info-from-jruby) (middleware-utils/json-response 200)))) (defn task-file-uri-components "The 'id' portion for a task implementation is a single component like 'foo.sh' and can never be nested in subdirectories. In that case we know the 'file' must be structured ///tasks/. Other task files are the path relative to the module root, in the form // where may have subdirectories. For those, we just slice that off the end of the file path and take the last component that remains as the module root." [file-id file] (if (str/includes? file-id "/") (let [[module mount subpath] (str/split file-id #"/" 3) module-root (fs/base-name (subs file 0 (str/last-index-of file file-id)))] [module-root module mount subpath]) (take-last 4 (str/split file #"/")))) (defn describe-task-file [get-code-content env-name code-id file-data] (let [file (:path file-data) file-id (:name file-data) size (fs/size file) sha256 (ks/file->sha256 (io/file file)) ;; we trust the file path from Puppet, so extract the relative path info from the file [module-root module-name mount relative-path] (task-file-uri-components file-id file) static-path (str/join "/" [module-root module-name mount relative-path]) uri (try ;; if code content can be retrieved, then use static_file_content (when (not= sha256 (ks/stream->sha256 (get-code-content env-name code-id static-path))) (throw (Exception. (i18n/trs "file did not match versioned file contents")))) {:path (str "/puppet/v3/static_file_content/" static-path) :params {:environment env-name :code_id code-id}} (catch Exception e (log/debug (i18n/trs "Static file unavailable for {0}: {1}" file e)) {:path (case mount "files" (format "/puppet/v3/file_content/modules/%s/%s" module-name relative-path) "lib" (format "/puppet/v3/file_content/plugins/%s" relative-path) "scripts" (format "/puppet/v3/file_content/scripts/%s/%s" module-name relative-path) "tasks" (format "/puppet/v3/file_content/tasks/%s/%s" module-name relative-path)) :params {:environment env-name}}))] {:filename file-id :sha256 sha256 :size_bytes size :uri uri})) (defn full-task-name "Construct a full task name from the two components. If the task's short name is 'init', then the second component is omitted so the task name is just the module's name." [module-name task-shortname] (if (= task-shortname "init") module-name (str module-name "::" task-shortname))) (schema/defn ^:always-validate task-data->task-details :- TaskDetails "Fills in a bare TaskData map by examining the files it refers to, returning TaskDetails." [task-data :- TaskData get-code-content :- IFn env-name :- schema/Str code-id :- (schema/maybe schema/Str) module-name :- schema/Str task-name :- schema/Str] (if (:error task-data) (throw+ (:error task-data)) {:metadata (or (:metadata task-data) {}) :name (full-task-name module-name task-name) :files (mapv (partial describe-task-file get-code-content env-name code-id) (:files task-data))})) (schema/defn environment-not-found :- ringutils/RingResponse "Ring handler to provide a standard error when an environment is not found." [environment :- schema/Str] (rr/not-found (i18n/tru "Could not find environment ''{0}''" environment))) (schema/defn module-not-found :- ringutils/RingResponse "Ring handler to provide a standard error when a module is not found." [module :- schema/Str] (rr/not-found (i18n/tru "Could not find module ''{0}''" module))) (schema/defn task-not-found :- ringutils/RingResponse "Ring handler to provide a standard error when a task is not found." [task :- schema/Str] (rr/not-found (i18n/tru "Could not find task ''{0}''" task))) (schema/defn plan-not-found :- ringutils/RingResponse "Ring handler to provide a standard error when a plan is not found." [plan :- schema/Str] (rr/not-found (i18n/tru "Could not find plan ''{0}''" plan))) (schema/defn ^:always-validate module-info-from-jruby->module-info-for-json :- EnvironmentModulesInfo "Creates a new map with a top level key `name` that corresponds to the requested environment and a top level key `modules` which contains the module information obtained from JRuby." [info-from-jruby :- List environment :- schema/Str] (->> info-from-jruby sort-nested-info-maps vec (sorted-map :name environment :modules))) (schema/defn ^:always-validate environment-module-response! :- ringutils/RingResponse "Process the environment module information, returning a ring response to be propagated back up to the caller of the environment_modules endpoint." ([info-from-jruby :- Map] (let [all-info-as-json (map #(module-info-from-jruby->module-info-for-json (val %) (name (key %))) (sort-nested-info-maps info-from-jruby))] (middleware-utils/json-response 200 all-info-as-json))) ([info-from-jruby :- List environment :- schema/Str] (let [info-as-json (module-info-from-jruby->module-info-for-json info-from-jruby environment)] (middleware-utils/json-response 200 info-as-json)))) (schema/defn ^:always-validate environment-module-info-fn :- IFn "Middleware function for constructing a Ring response from an incoming request for environment_modules information." [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (fn [request] (if-let [environment (jruby-request/get-environment-from-request request)] (if-let [module-info (jruby-protocol/get-environment-module-info jruby-service (:jruby-instance request) environment)] (environment-module-response! module-info environment) (rr/not-found (i18n/tru "Could not find environment ''{0}''" environment))) (let [module-info (jruby-protocol/get-all-environment-module-info jruby-service (:jruby-instance request))] (environment-module-response! module-info))))) (schema/defn ^:always-validate all-tasks-fn :- IFn "Middleware function for constructing a Ring response from an incoming request for tasks information." [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (fn [request] (let [environment (jruby-request/get-environment-from-request request)] (if-let [task-info-for-env (sort-nested-info-maps (jruby-protocol/get-tasks jruby-service (:jruby-instance request) environment))] (all-tasks-response! task-info-for-env environment) (environment-not-found environment))))) (schema/defn ^:always-validate task-details :- TaskDetails "Returns a TaskDetails map for the task matching the given environment, module, and name. Will throw a JRuby RaiseException with (EnvironmentNotFound), (MissingModule), or (TaskNotFound) if any of those conditions occur." [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) jruby-instance code-content-fn :- IFn environment-name :- schema/Str code-id :- (schema/maybe schema/Str) module-name :- schema/Str task-name :- schema/Str] (-> (jruby-protocol/get-task-data jruby-service jruby-instance environment-name module-name task-name) sort-nested-info-maps (task-data->task-details code-content-fn environment-name code-id module-name task-name))) (schema/defn exception-matches? :- schema/Bool [^Exception e :- Exception pattern :- schema/Regex] (->> e .getMessage (re-find pattern) boolean)) (defn handle-task-details-jruby-exception "Given a JRuby RaiseException arising from a call to task-details, constructs a 4xx error response if appropriate, otherwise re-throws." [jruby-exception environment module task] (cond (exception-matches? jruby-exception #"^\(EnvironmentNotFound\)") (environment-not-found environment) (exception-matches? jruby-exception #"^\(MissingModule\)") (module-not-found module) (exception-matches? jruby-exception #"^\(TaskNotFound\)") (task-not-found task) :else (throw jruby-exception))) (defn is-task-error? [err] (and (map? err) (:kind err) (str/starts-with? (:kind err) "puppet.task"))) (defn handle-plan-details-jruby-exception "Given a JRuby RaiseException arising from a call to plan-details, constructs a 4xx error response if appropriate, otherwise re-throws." [jruby-exception environment module plan] (cond (exception-matches? jruby-exception #"^\(EnvironmentNotFound\)") (environment-not-found environment) (exception-matches? jruby-exception #"^\(MissingModule\)") (module-not-found module) (exception-matches? jruby-exception #"^\(PlanNotFound\)") (plan-not-found plan) :else (throw jruby-exception))) (defn is-plan-error? [err] (and (map? err) (:kind err) (str/starts-with? (:kind err) "puppet.plan"))) (schema/defn ^:always-validate task-details-fn :- IFn "Middleware function for constructing a Ring response from an incoming request for detailed task information." [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) get-code-content-fn :- IFn current-code-id-fn :- IFn] (fn [request] (let [environment (jruby-request/get-environment-from-request request) module (get-in request [:route-params :module-name]) task (get-in request [:route-params :task-name])] (try+ (->> (task-details jruby-service (:jruby-instance request) get-code-content-fn environment (current-code-id-fn environment) module task) (middleware-utils/json-response 200)) (catch is-task-error? {:keys [kind msg details]} (middleware-utils/json-response 500 {:kind kind :msg msg :details details})) (catch RaiseException e (handle-task-details-jruby-exception e environment module task)))))) (schema/defn ^:always-validate all-plans-response! :- ringutils/RingResponse "Process the info, returning a Ring response to be propagated back up to the caller of the endpoint. Returns environment as a list of objects for an eventual future in which tasks for all environments can be requested, and a given task will list all the environments it is found in." [info-from-jruby :- [{schema/Any schema/Any}] environment :- schema/Str] (let [format-plan (fn [plan-object] {:name (:name plan-object) :environment [{:name environment :code_id nil}]})] (->> (map format-plan info-from-jruby) (middleware-utils/json-response 200)))) (schema/defn ^:always-validate all-plans-fn :- IFn "Middleware function for constructing a Ring response from an incoming request for plans information." [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (fn [request] (let [environment (jruby-request/get-environment-from-request request)] (if-let [plan-info-for-env (sort-nested-info-maps (jruby-protocol/get-plans jruby-service (:jruby-instance request) environment))] (all-plans-response! plan-info-for-env environment) (environment-not-found environment))))) (schema/defn ^:always-validate plan-data->plan-details :- PlanDetails "Fills in a bare PlanData map by examining the files it refers to, returning PlanDetails." [plan-data :- PlanData module-name :- schema/Str plan-name :- schema/Str] (if (:error plan-data) (throw+ (:error plan-data)) {:metadata (or (:metadata plan-data) {}) :name (full-task-name module-name plan-name)})) (schema/defn ^:always-validate plan-details :- PlanDetails "Returns a PlanDetails map for the plan matching the given environment, module, and name. Will throw a JRuby RaiseException with (EnvironmentNotFound), (MissingModule), or (PlanNotFound) if any of those conditions occur." [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) jruby-instance environment-name :- schema/Str module-name :- schema/Str plan-name :- schema/Str] (-> (jruby-protocol/get-plan-data jruby-service jruby-instance environment-name module-name plan-name) sort-nested-info-maps (plan-data->plan-details module-name plan-name))) (schema/defn ^:always-validate plan-details-fn :- IFn "Middleware function for constructing a Ring response from an incoming request for detailed plan information." [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (fn [request] (let [environment (jruby-request/get-environment-from-request request) module (get-in request [:route-params :module-name]) plan (get-in request [:route-params :plan-name])] (try+ (->> (plan-details jruby-service (:jruby-instance request) environment module plan) (middleware-utils/json-response 200)) (catch is-plan-error? {:keys [kind msg details]} (middleware-utils/json-response 500 {:kind kind :msg msg :details details})) (catch RaiseException e (handle-plan-details-jruby-exception e environment module plan)))))) (defn info-service [request] (let [path-components (-> request :route-info :path) ;; path-components will be something like ;; ["/puppet" "/v3" "/environment_classes" ["*" :rest]] ;; and we want to map "/environment_classes" to a ;; cacheable info service resource-component (-> path-components butlast last)] (when resource-component (get {"environment_classes" :classes "environment_transports" :transports} (str/replace resource-component "/" ""))))) (schema/defn ^:always-validate wrap-with-cache-check :- IFn "Middleware function which validates whether or not the If-None-Match header on an incoming cacheable request matches the last Etag computed for the environment whose info is being requested. If the two match, the middleware function returns an HTTP 304 (Not Modified) Ring response. If the two do not match, the request is threaded through to the supplied handler function." [handler :- IFn jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (fn [request] (let [environment (jruby-request/get-environment-from-request request) svc-key (info-service request) request-tag (if-none-match-from-request request)] (if (and request-tag (= request-tag (jruby-protocol/get-cached-info-tag jruby-service environment svc-key))) (not-modified-response request-tag) (handler request))))) (schema/defn ^:always-validate raw-transports->response-map [data :- List env :- schema/Str] (sort-nested-info-maps {:name env :transports data})) (schema/defn ^:always-validate maybe-update-cache! :- ringutils/RingResponse "Updates cached etag for a given info service if the etag is different than the etag requested. Note, the content version at the time of etag computation must be supplied, the jruby service will only update the cache if the current content version of the cache has not changed while the etag was being computed." [info :- {schema/Any schema/Any} env :- schema/Str jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) svc-key :- (schema/maybe schema/Keyword) request-tag :- (schema/maybe String) content-version :- (schema/maybe schema/Int)] (let [body (json/encode info) tag (ks/utf8-string->sha256 body)] (jruby-protocol/set-cache-info-tag! jruby-service env svc-key tag content-version) (if (= tag request-tag) (not-modified-response tag) (-> (response-with-etag body tag) (rr/content-type "application/json"))))) (schema/defn ^:always-validate make-cacheable-handler :- IFn "Given a function to retrieve information from the jruby protocol (referred to as an info service), builds a handler that honors the environment cache." [info-fn :- IFn jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) cache-enabled? :- schema/Bool] (fn [request] (let [env (jruby-request/get-environment-from-request request) service-id (info-service request) content-version (jruby-protocol/get-cached-content-version jruby-service env service-id)] (if-let [info (info-fn (:jruby-instance request) env)] (let [known-tag (if-none-match-from-request request)] (if cache-enabled? (maybe-update-cache! info env jruby-service service-id known-tag content-version) (middleware-utils/json-response 200 info))) (environment-not-found env))))) (schema/defn ^:always-validate create-cacheable-info-handler-with-middleware :- IFn "Creates a cacheable info handler and wraps it in appropriate middleware." [info-fn :- IFn jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) cache-enabled :- schema/Bool] (-> (make-cacheable-handler info-fn jruby-service cache-enabled) (jruby-request/wrap-with-jruby-instance jruby-service) (wrap-with-cache-check jruby-service) jruby-request/wrap-with-environment-validation jruby-request/wrap-with-error-handling)) (schema/defn ^:always-validate environment-module-handler :- IFn "Handler for processing an incoming environment_modules Ring request" [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (-> (environment-module-info-fn jruby-service) (jruby-request/wrap-with-jruby-instance jruby-service) (jruby-request/wrap-with-environment-validation true) jruby-request/wrap-with-error-handling)) (schema/defn ^:always-validate all-tasks-handler :- IFn "Handler for processing an incoming all_tasks Ring request" [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (-> (all-tasks-fn jruby-service) (jruby-request/wrap-with-jruby-instance jruby-service) jruby-request/wrap-with-environment-validation jruby-request/wrap-with-error-handling)) (schema/defn ^:always-validate task-details-handler :- IFn "Handler for processing an incoming /tasks/:module/:task-name Ring request" [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) get-code-content-fn :- IFn current-code-id-fn :- IFn] (-> (task-details-fn jruby-service get-code-content-fn current-code-id-fn) (jruby-request/wrap-with-jruby-instance jruby-service) jruby-request/wrap-with-environment-validation jruby-request/wrap-with-error-handling)) (schema/defn ^:always-validate all-plans-handler :- IFn "Handler for processing an incoming all_plans Ring request" [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (-> (all-plans-fn jruby-service) (jruby-request/wrap-with-jruby-instance jruby-service) jruby-request/wrap-with-environment-validation jruby-request/wrap-with-error-handling)) (schema/defn ^:always-validate plan-details-handler :- IFn "Handler for processing an incoming /plans/:module/:plan-name Ring request" [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService)] (-> (plan-details-fn jruby-service) (jruby-request/wrap-with-jruby-instance jruby-service) jruby-request/wrap-with-environment-validation jruby-request/wrap-with-error-handling)) (schema/defn ^:always-validate valid-static-file-path? "Helper function to decide if a static_file_content path is valid. The access here is designed to mimic Puppet's file_content endpoint." [path :- schema/Str] ;; Here, keywords represent a single element in the path. Anything between two '/' counts. ;; The second vector takes anything else that might be on the end of the path. ;; Below, this corresponds to '*/*/files/**' or '*/*/tasks/**' or '*/*/scripts/**' in a filesystem glob. (bidi/match-route [[#"[^/]+/" :module-name #"/(files|tasks|scripts|lib)/" [#".+" :rest]] :_] path)) (defn static-file-content-request-handler "Returns a function which is the main request handler for the /static_file_content endpoint, utilizing the provided implementation of `get-code-content`" [get-code-content] (fn [req] (let [environment (get-in req [:params "environment"]) code-id (get-in req [:params "code_id"]) file-path (get-in req [:params :rest])] (cond (some empty? [environment code-id file-path]) {:status 400 :headers {"Content-Type" "text/plain"} :body (i18n/tru "Error: A /static_file_content request requires an environment, a code-id, and a file-path")} (not (nil? (schema/check ps-common/Environment environment))) {:status 400 :headers {"Content-Type" "text/plain"} :body (ps-common/environment-validation-error-msg environment)} (not (nil? (schema/check ps-common/CodeId code-id))) {:status 400 :headers {"Content-Type" "text/plain"} :body (ps-common/code-id-validation-error-msg code-id)} (not (valid-static-file-path? file-path)) {:status 403 :headers {"Content-Type" "text/plain"} :body (i18n/tru "Request Denied: A /static_file_content request must be a file within the files, lib, scripts, or tasks directory of a module.")} :else {:status 200 :headers {"Content-Type" "application/octet-stream"} :body (get-code-content environment code-id file-path)})))) (defn valid-env-name? [string] (re-matches #"\w+" string)) (def CatalogRequestV4 {(schema/required-key "certname") schema/Str (schema/required-key "persistence") {(schema/required-key "facts") schema/Bool (schema/required-key "catalog") schema/Bool} (schema/required-key "environment") (schema/constrained schema/Str valid-env-name?) (schema/optional-key "trusted_facts") {(schema/required-key "values") {schema/Str schema/Any}} (schema/optional-key "facts") {(schema/required-key "values") {schema/Str schema/Any}} (schema/optional-key "job_id") schema/Str (schema/optional-key "transaction_uuid") schema/Str (schema/optional-key "options") {(schema/optional-key "capture_logs") schema/Bool (schema/optional-key "log_level") (schema/enum "debug" "info" "warning" "err") (schema/optional-key "prefer_requested_environment") schema/Bool}}) (def CompileRequest {(schema/required-key "certname") schema/Str (schema/required-key "code_ast") schema/Str (schema/required-key "trusted_facts") {(schema/required-key "values") {schema/Str schema/Any}} (schema/required-key "facts") {(schema/required-key "values") {schema/Str schema/Any}} (schema/required-key "variables") {(schema/required-key "values") (schema/cond-pre [{schema/Str schema/Any}] {schema/Str schema/Any})} ;; Both environment and versioned project are technically listed in the schema as ;; "optional" but we will check later that exactly one of them is set. (schema/optional-key "environment") schema/Str (schema/optional-key "versioned_project") schema/Str (schema/optional-key "target_variables") {(schema/required-key "values") {schema/Str schema/Any}} (schema/optional-key "job_id") schema/Str (schema/optional-key "transaction_uuid") schema/Str (schema/optional-key "options") {(schema/optional-key "capture_logs") schema/Bool (schema/optional-key "log_level") (schema/enum "debug" "info" "warning" "error") (schema/optional-key "compile_for_plan") schema/Bool}}) (defn validated-body [body schema] (let [parameters (try+ (json/decode body false) (catch JsonParseException e (throw+ {:kind :bad-request :msg (format "Error parsing JSON: %s" e)})))] (try+ (schema/validate schema parameters) (catch [:type :schema.core/error] {:keys [error]} (throw+ {:kind :bad-request :msg (format "Invalid input: %s" error)}))) parameters)) (schema/defn ^:always-validate v4-catalog-fn :- IFn [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) current-code-id-fn :- IFn] (fn [request] (let [request-options (-> request :body slurp (validated-body CatalogRequestV4))] (try {:status 200 :headers {"Content-Type" "application/json"} :body (json/encode (jruby-protocol/compile-catalog jruby-service (:jruby-instance request) (assoc request-options "code_id" (current-code-id-fn (get request-options "environment")))))} (finally ;; don't let any exceptions escape (try (ps-common/record-action {:type :action :targets [(get request-options "certname")] :meta {:type :certificate :what :compile-catalog :where :v4}}) (catch Throwable e (log/info e (i18n/trs "Failed to report action"))))))))) (schema/defn ^:always-validate compile-fn :- IFn [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) current-code-id-fn :- IFn boltlib-path :- (schema/maybe [schema/Str])] (fn [request] (let [request-options (-> request :body slurp (validated-body CompileRequest)) environment (get request-options "environment")] ;; Check to ensure environment is set. (if (nil? environment) {:status 400 :headers {"Content-Type" "text/plain"} :body (i18n/tru "A compile request must include an `environment` or `versioned_project` parameter.")} (let [compile-options (assoc request-options "code_id" (current-code-id-fn environment))] {:status 200 :headers {"Content-Type" "application/json"} :body (json/encode (jruby-protocol/compile-ast jruby-service (:jruby-instance request) compile-options boltlib-path))}))))) (schema/defn ^:always-validate v4-catalog-handler :- IFn [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) wrap-with-jruby-queue-limit :- IFn current-code-id-fn :- IFn] (-> (v4-catalog-fn jruby-service current-code-id-fn) (jruby-request/wrap-with-jruby-instance jruby-service) wrap-with-jruby-queue-limit jruby-request/wrap-with-error-handling)) (schema/defn ^:always-validate compile-handler :- IFn [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) wrap-with-jruby-queue-limit :- IFn current-code-id-fn :- IFn boltlib-path :- (schema/maybe [schema/Str])] (-> (compile-fn jruby-service current-code-id-fn boltlib-path) (jruby-request/wrap-with-jruby-instance jruby-service) wrap-with-jruby-queue-limit jruby-request/wrap-with-error-handling)) (def MetricIdsForStatus (schema/atom [[schema/Str]])) (schema/defn http-client-metrics-summary :- {:metrics-data [http-client-common/MetricIdMetricData] :sorted-metrics-data [http-client-common/MetricIdMetricData]} [metric-registry :- MetricRegistry metric-ids-to-select :- MetricIdsForStatus] (let [metrics-data (map #(http-client-metrics/get-client-metrics-data-by-metric-id metric-registry %) @metric-ids-to-select) flattened-data (flatten metrics-data)] {:metrics-data flattened-data :sorted-metrics-data (sort-by :aggregate > flattened-data)})) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Routing (schema/defn ^:always-validate v3-ruby-routes :- bidi-schema/RoutePair "v3 route tree for the ruby side of the master service." [request-handler :- IFn certname :- schema/Str] (comidi/routes (comidi/GET ["/node/" [#".*" :rest]] request (request-handler request)) (comidi/GET ["/file_content/" [#".*" :rest]] request (request-handler request)) (comidi/GET ["/file_metadatas/" [#".*" :rest]] request (request-handler request)) (comidi/GET ["/file_metadata/" [#".*" :rest]] request (request-handler request)) (comidi/GET ["/file_bucket_file/" [#".*" :rest]] request (request-handler request)) (comidi/PUT ["/file_bucket_file/" [#".*" :rest]] request (request-handler request)) (comidi/HEAD ["/file_bucket_file/" [#".*" :rest]] request (request-handler request)) (comidi/GET ["/catalog/" [#".*" :rest]] request (request-handler (assoc request :include-code-id? true))) (comidi/POST ["/catalog/" [#".*" :rest]] request (let [request-handler (ringutils/wrap-with-certname-as-compiler request-handler certname)] (request-handler (assoc request :include-code-id? true)))) (comidi/PUT ["/facts/" [#".*" :rest]] request (request-handler request)) (comidi/PUT ["/report/" [#".*" :rest]] request (request-handler request)) (comidi/GET "/environments" request (request-handler request)))) (schema/defn ^:always-validate v3-clojure-routes :- bidi-schema/RoutePair "v3 route tree for the clojure side of the master service." [jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) get-code-content-fn :- IFn current-code-id-fn :- IFn cache-enabled :- schema/Bool wrap-with-jruby-queue-limit :- IFn boltlib-path :- (schema/maybe [schema/Str])] (let [class-handler (create-cacheable-info-handler-with-middleware (fn [jruby env] (some-> jruby-service (jruby-protocol/get-environment-class-info jruby env) (class-info-from-jruby->class-info-for-json env))) jruby-service cache-enabled) module-handler (environment-module-handler jruby-service) tasks-handler (all-tasks-handler jruby-service) plans-handler (all-plans-handler jruby-service) transport-handler (create-cacheable-info-handler-with-middleware (fn [jruby env] (some-> jruby-service (jruby-protocol/get-environment-transport-info jruby env) (raw-transports->response-map env))) jruby-service cache-enabled) task-handler (task-details-handler jruby-service get-code-content-fn current-code-id-fn) plan-handler (plan-details-handler jruby-service) static-content-handler (static-file-content-request-handler get-code-content-fn) compile-handler' (compile-handler jruby-service wrap-with-jruby-queue-limit current-code-id-fn boltlib-path)] (comidi/routes (comidi/POST "/compile" request (compile-handler' request)) (comidi/GET ["/environment_classes" [#".*" :rest]] request (class-handler request)) (comidi/GET ["/environment_modules" [#".*" :rest]] request (module-handler request)) (comidi/GET ["/environment_transports" [#".*" :rest]] request (transport-handler request)) (comidi/GET ["/tasks/" :module-name "/" :task-name] request (task-handler request)) (comidi/GET ["/tasks"] request (tasks-handler request)) (comidi/GET ["/plans/" :module-name "/" :plan-name] request (plan-handler request)) (comidi/GET ["/plans"] request (plans-handler request)) (comidi/GET ["/static_file_content/" [#".*" :rest]] request (static-content-handler request))))) (schema/defn ^:always-validate v4-routes :- bidi-schema/RoutePair [clojure-request-wrapper :- IFn jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) wrap-with-jruby-queue-limit :- IFn current-code-id-fn :- IFn] (let [v4-catalog-handler' (v4-catalog-handler jruby-service wrap-with-jruby-queue-limit current-code-id-fn)] (comidi/context "/v4" (comidi/wrap-routes (comidi/routes (comidi/POST "/catalog" request (v4-catalog-handler' request))) clojure-request-wrapper)))) (schema/defn ^:always-validate v3-routes :- bidi-schema/RoutePair "Creates the routes to handle the master's '/v3' routes, which includes '/environments' and the non-CA indirected routes. The CA-related endpoints are handled separately by the CA service." [ruby-request-handler :- IFn clojure-request-wrapper :- IFn jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) get-code-content-fn :- IFn current-code-id-fn :- IFn environment-class-cache-enabled :- schema/Bool wrap-with-jruby-queue-limit :- IFn boltlib-path :- (schema/maybe [schema/Str]) certname :- schema/Str] (comidi/context "/v3" (v3-ruby-routes ruby-request-handler certname) (comidi/wrap-routes (v3-clojure-routes jruby-service get-code-content-fn current-code-id-fn environment-class-cache-enabled wrap-with-jruby-queue-limit boltlib-path) clojure-request-wrapper))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Lifecycle Helper Functions (defn meminfo-content "Read and return the contents of /proc/meminfo, if it exists. Otherwise return nil." [] (when (fs/exists? "/proc/meminfo") ; Due to OpenJDK Issue JDK-7132461 ; (https://bugs.openjdk.java.net/browse/JDK-7132461), ; we have to open and slurp a FileInputStream object rather than ; slurping the file directly, since directly slurping the file ; causes a call to be made to FileInputStream.available(). (with-open [mem-info-file (FileInputStream. "/proc/meminfo")] (slurp mem-info-file)))) ; the current max java heap size (-Xmx) in kB defined for with-redefs in tests (def max-heap-size (/ (.maxMemory (Runtime/getRuntime)) 1024)) (defn validate-memory-requirements! "On Linux Distributions, parses the /proc/meminfo file to determine the total amount of System RAM, and throws an exception if that is less than 1.1 times the maximum heap size of the JVM. This is done so that the JVM doesn't fail later due to an Out of Memory error." [] (when-let [meminfo-file-content (meminfo-content)] (let [heap-size max-heap-size mem-size (BigInteger. (second (re-find #"MemTotal:\s+(\d+)\s+\S+" meminfo-file-content))) required-mem-size (* heap-size 1.1)] (when (< mem-size required-mem-size) (throw (Error. (format "%s %s %s" (i18n/trs "Not enough available RAM ({0}MB) to safely accommodate the configured JVM heap size of {1}MB." (int (/ mem-size 1024.0)) (int (/ heap-size 1024.0))) (i18n/trs "Puppet Server requires at least {0}MB of available RAM given this heap size, computed as 1.1 * max heap (-Xmx)." (int (/ required-mem-size 1024.0))) (i18n/trs "Either increase available memory or decrease the configured heap size by reducing the -Xms and -Xmx values in JAVA_ARGS in /etc/sysconfig/puppetserver on EL systems or /etc/default/puppetserver on Debian systems.")))))))) (defn register-gauge! [registry hostname metric-name metric-fn] (.register registry (metrics/host-metric-name hostname metric-name) (proxy [Gauge] [] (getValue [] (metric-fn))))) (schema/defn register-jvm-metrics! [registry :- MetricRegistry hostname :- schema/Str] (register-gauge! registry hostname "uptime" (fn [] (.getUptime (ManagementFactory/getRuntimeMXBean)))) (let [memory-mbean (ManagementFactory/getMemoryMXBean) get-heap-memory (fn [] (.getHeapMemoryUsage memory-mbean)) get-non-heap-memory (fn [] (.getNonHeapMemoryUsage memory-mbean))] (register-gauge! registry hostname "memory.heap.committed" (fn [] (.getCommitted (get-heap-memory)))) (register-gauge! registry hostname "memory.heap.init" (fn [] (.getInit (get-heap-memory)))) (register-gauge! registry hostname "memory.heap.max" (fn [] (.getMax (get-heap-memory)))) (register-gauge! registry hostname "memory.heap.used" (fn [] (.getUsed (get-heap-memory)))) (register-gauge! registry hostname "memory.non-heap.committed" (fn [] (.getCommitted (get-non-heap-memory)))) (register-gauge! registry hostname "memory.non-heap.init" (fn [] (.getInit (get-non-heap-memory)))) (register-gauge! registry hostname "memory.non-heap.max" (fn [] (.getMax (get-non-heap-memory)))) (register-gauge! registry hostname "memory.non-heap.used" (fn [] (.getUsed (get-non-heap-memory)))) ;; Unfortunately there isn't an mbean for "total" memory. Dropwizard metrics' ;; MetricUsageGaugeSet has "total" metrics that are computed by adding together Heap Memory and ;; Non Heap Memory. (register-gauge! registry hostname "memory.total.committed" (fn [] (+ (.getCommitted (get-heap-memory)) (.getCommitted (get-non-heap-memory))))) (register-gauge! registry hostname "memory.total.init" (fn [] (+ (.getInit (get-heap-memory)) (.getInit (get-non-heap-memory))))) (register-gauge! registry hostname "memory.total.max" (fn [] (+ (.getMax (get-heap-memory)) (.getMax (get-non-heap-memory))))) (register-gauge! registry hostname "memory.total.used" (fn [] (+ (.getUsed (get-heap-memory)) (.getUsed (get-non-heap-memory))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (schema/defn ^:always-validate root-routes :- bidi-schema/RoutePair "Creates all of the web routes for the master." [ruby-request-handler :- IFn clojure-request-wrapper :- IFn jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) wrap-with-jruby-queue-limit :- IFn get-code-content-fn :- IFn current-code-id-fn :- IFn environment-class-cache-enabled :- schema/Bool boltlib-path :- (schema/maybe [schema/Str]) certname :- schema/Str] (comidi/routes (v3-routes ruby-request-handler clojure-request-wrapper jruby-service get-code-content-fn current-code-id-fn environment-class-cache-enabled wrap-with-jruby-queue-limit boltlib-path certname) (v4-routes clojure-request-wrapper jruby-service wrap-with-jruby-queue-limit current-code-id-fn))) (schema/defn ^:always-validate wrap-middleware :- IFn [handler :- IFn authorization-fn :- IFn puppet-version :- schema/Str] (-> handler authorization-fn (middleware/wrap-uncaught-errors :plain) middleware/wrap-request-logging i18n/locale-negotiator middleware/wrap-response-logging (ringutils/wrap-with-puppet-version-header puppet-version))) (schema/defn ^:always-validate get-master-route-config "Get the webserver route configuration for the master service" [master-ns :- schema/Keyword config :- {schema/Keyword schema/Any}] (get-in config [:web-router-service master-ns])) (schema/defn ^:always-validate get-master-mount :- schema/Str "Get the webserver mount point that the master service is rooted under" [master-ns :- schema/Keyword config-route] (cond ;; if the route config is a map, we need to determine whether it's the ;; new-style multi-server config (where there will be a `:route` key and a ;; `:server`, key), or the old style where there is a single key that is ;; assumed to be our hard-coded route id (`:master-routes`). ;; It should be possible to delete this hack (perhaps this entire function) ;; when we remove support for legacy routes. (and (map? config-route) (or (contains? config-route :route) (contains? config-route :master-routes))) (or (:route config-route) (:master-routes config-route)) (string? config-route) config-route :else (throw (IllegalArgumentException. (i18n/trs "Route not found for service {0}" master-ns))))) (schema/defn ^:always-validate construct-root-routes :- bidi-schema/RoutePair "Creates a wrapped ruby request handler and a clojure request handler, then uses those to create all of the web routes for the master." [puppet-version :- schema/Str jruby-service :- (schema/protocol jruby-protocol/JRubyPuppetService) get-code-content :- IFn current-code-id :- IFn handle-request :- IFn wrap-with-authorization-check :- IFn wrap-with-jruby-queue-limit :- IFn environment-class-cache-enabled :- schema/Bool boltlib-path :- (schema/maybe [schema/Str]) certname :- schema/Str] (let [ruby-request-handler (wrap-middleware handle-request wrap-with-authorization-check puppet-version) clojure-request-wrapper (fn [handler] (wrap-middleware (ring/wrap-params handler) wrap-with-authorization-check puppet-version))] (root-routes ruby-request-handler clojure-request-wrapper jruby-service wrap-with-jruby-queue-limit get-code-content current-code-id environment-class-cache-enabled boltlib-path certname))) (def MasterStatusV1 {(schema/optional-key :experimental) {:http-metrics [http-metrics/RouteSummary] :http-client-metrics [http-client-common/MetricIdMetricData]}}) (def puppet-server-http-client-metrics-for-status [["puppet" "report" "http"] ["puppetdb" "command" "replace_catalog"] ["puppetdb" "command" "replace_facts"] ["puppetdb" "command" "store_report"] ["puppetdb" "facts" "find"] ["puppetdb" "facts" "search"] ["puppetdb" "query"] ["puppetdb" "resource" "search"]]) (schema/defn ^:always-validate add-metric-ids-to-http-client-metrics-list! [metric-id-atom :- MetricIdsForStatus metric-ids-to-add :- [[schema/Str]]] (swap! metric-id-atom concat metric-ids-to-add)) (schema/defn ^:always-validate v1-status :- status-core/StatusCallbackResponse [http-metrics :- http-metrics/HttpMetrics http-client-metric-ids-for-status :- MetricIdsForStatus metric-registry :- MetricRegistry level :- status-core/ServiceStatusDetailLevel] (let [level>= (partial status-core/compare-levels >= level)] {:state :running :status (cond-> ;; no status info at ':critical' level {} ;; no extra status at ':info' level yet (level>= :info) identity (level>= :debug) (-> (assoc-in [:experimental :http-metrics] (:sorted-routes (http-metrics/request-summary http-metrics))) (assoc-in [:experimental :http-client-metrics] (:sorted-metrics-data (http-client-metrics-summary metric-registry http-client-metric-ids-for-status)))))})) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/master/master_service.clj000066400000000000000000000236111470345337400314320ustar00rootroot00000000000000(ns puppetlabs.services.master.master-service (:require [clojure.tools.logging :as log] [puppetlabs.trapperkeeper.core :refer [defservice]] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.puppetserver.jruby-request :as jruby-request] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.comidi :as comidi] [puppetlabs.metrics.http :as http-metrics] [puppetlabs.services.protocols.master :as master] [puppetlabs.i18n.core :as i18n] [puppetlabs.trapperkeeper.services.status.status-core :as status-core] [puppetlabs.services.master.master-core :as master-core] [clojure.string :as str])) (def master-service-status-version 1) ;; Default list of allowed histograms/timers (def default-metrics-allowed-hists ["http.active-histo" "http.puppet-v3-catalog-/*/-requests" "http.puppet-v3-environment-/*/-requests" "http.puppet-v3-environment_classes-/*/-requests" "http.puppet-v3-environments-requests" "http.puppet-v3-file_bucket_file-/*/-requests" "http.puppet-v3-file_content-/*/-requests" "http.puppet-v3-file_metadata-/*/-requests" "http.puppet-v3-file_metadatas-/*/-requests" "http.puppet-v3-node-/*/-requests" "http.puppet-v3-report-/*/-requests" "http.puppet-v3-static_file_content-/*/-requests"]) ;; Default list of allowed values/counts (def default-metrics-allowed-vals ["http.active-requests" "http.puppet-v3-catalog-/*/-percentage" "http.puppet-v3-environment-/*/-percentage" "http.puppet-v3-environment_classes-/*/-percentage" "http.puppet-v3-environments-percentage" "http.puppet-v3-file_bucket_file-/*/-percentage" "http.puppet-v3-file_content-/*/-percentage" "http.puppet-v3-file_metadata-/*/-percentage" "http.puppet-v3-file_metadatas-/*/-percentage" "http.puppet-v3-node-/*/-percentage" "http.puppet-v3-report-/*/-percentage" "http.puppet-v3-static_file_content-/*/-percentage" "http.puppet-v3-status-/*/-percentage" "http.total-requests" ; num-cpus is registered in trapperkeeper-comidi-metrics, see ; https://github.com/puppetlabs/trapperkeeper-comidi-metrics/blob/0.1.1/src/puppetlabs/metrics/http.clj#L117-L120 "num-cpus"]) ;; List of allowed jvm gauges/values (def default-jvm-metrics-allowed ["uptime" "memory.heap.committed" "memory.heap.init" "memory.heap.max" "memory.heap.used" "memory.non-heap.committed" "memory.non-heap.init" "memory.non-heap.max" "memory.non-heap.used" "memory.total.committed" "memory.total.init" "memory.total.max" "memory.total.used"]) (def http-client-metrics-allowed-hists (map #(format "http-client.experimental.with-metric-id.%s.full-response" (str/join "." %)) master-core/puppet-server-http-client-metrics-for-status)) (def default-metrics-allowed (concat default-metrics-allowed-hists default-metrics-allowed-vals default-jvm-metrics-allowed http-client-metrics-allowed-hists)) (defn jdk-support-status "Returns :official, :deprecated, :unknown, or :unsupported." [version] (cond (re-matches #"1\.[1234567]($|(\..*))" version) :unsupported (re-matches #"1\.[89]($|(\..*))" version) :deprecated (re-matches #"10($|(\..*))" version) :deprecated (re-matches (re-pattern (str 11 "($|(\\..*))")) version) :official (re-matches #"17($|(\..*))" version) :official :else :unknown)) (defn log-java-deprecation-message [version] (let [status (jdk-support-status version)] (case status (:unknown) (log/warn (i18n/trs "JDK {0} is neither tested nor supported. Please use JDK 11 or 17" version)) (:deprecated) (log/warn (i18n/trs "JDK {0} is deprecated, please upgrade to JDK 11 or 17" version)) (:official) nil (:unsupported) (log/warn (i18n/trs "Puppetserver doesn't support JDK {0}" version))))) (defservice master-service master/MasterService [[:WebroutingService add-ring-handler get-route] [:PuppetServerConfigService get-config] [:RequestHandlerService handle-request] [:MetricsService get-metrics-registry get-server-id update-registry-settings] [:CaService initialize-master-ssl! retrieve-ca-cert! retrieve-ca-crl! get-auth-handler] [:JRubyPuppetService] [:AuthorizationService wrap-with-authorization-check] [:StatusService register-status] [:VersionedCodeService get-code-content current-code-id]] (init [this context] (master-core/validate-memory-requirements!) (let [config (get-config) route-config (master-core/get-master-route-config ::master-service config) path (master-core/get-master-mount ::master-service route-config) certname (get-in config [:puppetserver :certname]) localcacert (get-in config [:puppetserver :localcacert]) puppet-version (get-in config [:puppetserver :puppet-version]) max-queued-requests (get-in config [:jruby-puppet :max-queued-requests] 0) max-retry-delay (get-in config [:jruby-puppet :max-retry-delay] 1800) settings (ca/config->master-settings config) metrics-service (tk-services/get-service this :JRubyMetricsService) metrics-server-id (get-server-id) jruby-service (tk-services/get-service this :JRubyPuppetService) environment-class-cache-enabled (get-in config [:jruby-puppet :environment-class-cache-enabled] false) wrap-with-jruby-queue-limit (if (pos? max-queued-requests) (fn [handler] (jruby-request/wrap-with-request-queue-limit handler metrics-service max-queued-requests max-retry-delay)) identity) boltlib-path (get-in config [:jruby-puppet :boltlib-path]) ring-app (comidi/routes (master-core/construct-root-routes puppet-version jruby-service get-code-content current-code-id handle-request (get-auth-handler) wrap-with-jruby-queue-limit environment-class-cache-enabled boltlib-path certname)) routes (comidi/context path ring-app) route-metadata (comidi/route-metadata routes) comidi-handler (comidi/routes->handler routes) registry (get-metrics-registry :puppetserver) http-metrics (http-metrics/initialize-http-metrics! registry metrics-server-id route-metadata) http-client-metric-ids-for-status (atom master-core/puppet-server-http-client-metrics-for-status) ring-handler (-> comidi-handler (http-metrics/wrap-with-request-metrics http-metrics) (comidi/wrap-with-route-metadata routes)) hostcrl (get-in config [:puppetserver :hostcrl])] (log-java-deprecation-message (System/getProperty "java.version")) (retrieve-ca-cert! localcacert) (retrieve-ca-crl! hostcrl) (initialize-master-ssl! settings certname) (master-core/register-jvm-metrics! registry metrics-server-id) (update-registry-settings :puppetserver {:default-metrics-allowed default-metrics-allowed}) (log/info (i18n/trs "Master Service adding ring handlers")) ;; if the webrouting config uses the old-style config where ;; there is a single key with a route-id, we need to deal with that ;; for backward compat. We have a hard-coded assumption that this route-id ;; must be `master-routes`. In Puppet Server 2.0, we also supported a ;; key called `invalid-in-puppet-4` in the same route config, even though ;; that key is no longer used for Puppet Server 2.1 and later. We ;; should be able to remove this hack as soon as we are able to get rid ;; of the legacy routes. (if (and (map? route-config) (contains? route-config :master-routes)) (add-ring-handler this ring-handler {:route-id :master-routes :normalize-request-uri true}) (add-ring-handler this ring-handler {:normalize-request-uri true})) (register-status "master" (status-core/get-artifact-version "puppetlabs" "puppetserver") master-service-status-version (partial master-core/v1-status http-metrics http-client-metric-ids-for-status registry)) (register-status "server" (status-core/get-artifact-version "puppetlabs" "puppetserver") master-service-status-version (partial master-core/v1-status http-metrics http-client-metric-ids-for-status registry)) (-> context (assoc :http-metrics http-metrics) (assoc :http-client-metric-ids-for-status http-client-metric-ids-for-status)))) (start [this context] (log/info (i18n/trs "Puppet Server has successfully started and is now ready to handle requests")) context) (add-metric-ids-to-http-client-metrics-list! [this metric-ids-to-add] (let [metric-ids-from-context (:http-client-metric-ids-for-status (tk-services/service-context this))] (master-core/add-metric-ids-to-http-client-metrics-list! metric-ids-from-context metric-ids-to-add)))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/000077500000000000000000000000001470345337400264535ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/ca.clj000066400000000000000000000004311470345337400275260ustar00rootroot00000000000000(ns puppetlabs.services.protocols.ca) (defprotocol CaService "Describes the functionality of the CA service." (initialize-master-ssl! [this master-settings certname]) (retrieve-ca-cert! [this localcacert]) (retrieve-ca-crl! [this localcacrl]) (get-auth-handler [this])) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/jruby_metrics.clj000066400000000000000000000002361470345337400320270ustar00rootroot00000000000000(ns puppetlabs.services.protocols.jruby-metrics) (defprotocol JRubyMetricsService (get-metrics [this] "Get the current map of JRuby-related metrics")) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/jruby_puppet.clj000066400000000000000000000122141470345337400316750ustar00rootroot00000000000000(ns puppetlabs.services.protocols.jruby-puppet) (defprotocol JRubyPuppetService "Describes the JRubyPuppet provider service which pools JRubyPuppet instances." (free-instance-count [this] "The number of free JRubyPuppet instances left in the pool.") (mark-environment-expired! [this env-name] "Mark the specified environment expired, in all JRuby instances. Resets the cached class info for the environment's 'tag' to nil and increments the 'cache-generation-id' value.") (mark-all-environments-expired! [this] "Mark all cached environments expired, in all JRuby instances. Resets the cached class info for all previously stored environment 'tags' to nil and increments the 'cache-generation-id' value.") (get-environment-class-info [this jruby-instance env-name] "Get class information for a specific environment") (get-environment-transport-info [this jruby-instance env-name] "Get transport information for a specific environment") (get-environment-class-info-tag [this env-name] "DEPRECATED: see get-cached-info-tag Get a tag for the latest class information parsed for a specific environment") (get-cached-info-tag [this env-name info-service] "Get a tag for the latest information parsed for a specific environment and info service") (get-environment-class-info-cache-generation-id! [this env-name] "DEPRECATED: see `get-cache-content-version` Get the current cache generation id for a specific environment's class info. If no entry for the environment had existed at the point this function was called this function would, as a side effect, populate a new entry for that environment into the cache.") (get-cached-content-version [this env-name info-service] "Get the cached content version for a specific service's cache within an environment. If no entry for the environment had existed at the point this function was called this function would, as a side effect, populate a new entry for that environment into the cache.") (set-environment-class-info-tag! [this env-name tag cache-generation-id-before-tag-computed] "DEPRECATED: see `set-cache-info-tag!` Set the tag computed for the latest class information parsed for a specific environment. cache-generation-id-before-tag-computed should represent what the client received for a 'get-environment-class-info-cache-generation-id!' call for the environment made before it started doing the work to parse environment class info / compute the new tag. If cache-generation-id-before-tag-computed equals the 'cache-generation-id' value stored in the cache for the environment, the new 'tag' will be stored for the environment and the corresponding 'cache-generation-id' value will be incremented. If cache-generation-id-before-tag-computed is different than the 'cache-generation-id' value stored in the cache for the environment, the cache will remain unchanged as a result of this call.") (set-cache-info-tag! [this env-name info-service-id tag initial-content-version] "Set the tag computed for the latest info service parsed for a specific environment. initial-content-version should represent what the client received for a `get-cached-content-version` call for the environment made before it started doing the work to parse environment info & compute the new tag. If initial-content-version equals the value stored in the cache for the environment, the new 'tag' will be stored for the environment and the corresponding content version will be incremented.") (compile-catalog [this jruby-instance request-options] "Compile the catalog for a given certname") (compile-ast [this jruby-instance compile-options boltlib-path] "Compiles arbitrary Puppet ASTs into mini catalogs") (get-environment-module-info [this jruby-instance env-name] "Get module information for a specific environment") (get-all-environment-module-info [this jruby-instance] "Get all module information for all environments") (get-task-data [this jruby-instance env-name module-name task-name] "Get information (:metadata_file and :files) for a specific task. Returns a JRuby hash.") (get-tasks [this jruby-instance env-name] "Get list of task names and environment information.") (get-plan-data [this jruby-instance env-name module-name plan-name] "Get information (:metadata_file and :files) for a specific plan. Returns a JRuby hash.") (get-plans [this jruby-instance env-name] "Get list of plan names and environment information.") (flush-jruby-pool! [this] "Flush all the current JRuby instances and repopulate the pool.") (get-jruby-thread-dump [this] "Return a thread dump for each JRuby instance registered to the pool.") (get-pool-context [this] "Get the pool context out of the service context.") (register-event-handler [this callback] "Register a callback function to receive notifications when JRuby service events occur. The callback fn should accept a single arg, which will conform to the JRubyEvent schema.")) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/legacy_routes.clj000066400000000000000000000002071470345337400320110ustar00rootroot00000000000000(ns puppetlabs.services.protocols.legacy-routes) (defprotocol LegacyRoutesService "Marker protocol for the legacy routes service.") puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/master.clj000066400000000000000000000006121470345337400304370ustar00rootroot00000000000000(ns puppetlabs.services.protocols.master) (defprotocol MasterService "Protocol for the master service." (add-metric-ids-to-http-client-metrics-list! [this metric-ids-to-add] "Append a list of metric-ids to the built in list (defined in `master-core/puppet-server-http-client-metrics-for-status`) that gets included in the `http-client-metrics` key in the status endpoint.")) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/puppet_profiler.clj000066400000000000000000000006111470345337400323620ustar00rootroot00000000000000(ns puppetlabs.services.protocols.puppet-profiler) (defprotocol PuppetProfilerService "This protocol describes a service that provides a profiler that can be used to profile the internals of the Puppet ruby code." (get-profiler [this] "Returns an instance of `com.puppetlabs.master.PuppetProfiler` that can be used by the ruby Puppet profiling system."))puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/puppet_server_config.clj000066400000000000000000000016501470345337400333770ustar00rootroot00000000000000(ns puppetlabs.services.protocols.puppet-server-config) (defprotocol PuppetServerConfigService "The configuration service for puppetserver. This is built on top of Trapperkeeper's normal configuration service. It adds a few features - most importantly, it merges in settings from the Puppet's 'settings' in ruby. It also adds a set of required configuration values and validates them during service initialization. Note that this is an exact copy of the API from Trapperkeeper's built-in configuration service's." (get-config [this] "Returns a map containing all of the configuration values") (get-in-config [this ks] [this ks default] "Returns the individual configuration value from the nested configuration structure, where ks is a sequence of keys. Returns nil if the key is not present, or the default value if supplied.")) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/request_handler.clj000066400000000000000000000002451470345337400323330ustar00rootroot00000000000000(ns puppetlabs.services.protocols.request-handler) (defprotocol RequestHandlerService (handle-request [this request] "Handles a request from an agent.")) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/protocols/versioned_code.clj000066400000000000000000000006771470345337400321470ustar00rootroot00000000000000(ns puppetlabs.services.protocols.versioned-code) (defprotocol VersionedCodeService "A TK service for interacting with versioned puppet code." (current-code-id [this environment] "Returns the current code id (representing the freshest code) for the given environment.") (get-code-content [this environment code-id file-path] "Returns the content of file-path in the given environment at the revision represented by code-id.")) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/puppet_admin/000077500000000000000000000000001470345337400271145ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/puppet_admin/puppet_admin_core.clj000066400000000000000000000124321470345337400333050ustar00rootroot00000000000000(ns puppetlabs.services.puppet-admin.puppet-admin-core (:import (clojure.lang IFn)) (:require [puppetlabs.puppetserver.ringutils :as ringutils] [puppetlabs.services.protocols.jruby-puppet :as jruby-puppet] [puppetlabs.ring-middleware.utils :as middleware-utils] [puppetlabs.puppetserver.liberator-utils :as liberator-utils] [schema.core :as schema] [liberator.core :refer [defresource]] ;[liberator.dev :as liberator-dev] [puppetlabs.comidi :as comidi] [puppetlabs.ring-middleware.params :as pl-ring-params] [puppetlabs.i18n.core :as i18n] [slingshot.slingshot :as sling] [ring.util.response :as rr] [clojure.tools.logging :as log])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Schemas (def PuppetAdminSettings ringutils/WhitelistSettings) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Liberator resources (defresource environment-cache-resource [jruby-service env-name] :allowed-methods [:delete] ;; If you need to define :available-media-types, see comment below. ;:available-media-types ... :handle-exception liberator-utils/exception-handler ;; This next line of code tells liberator to ignore any media-types ;; the client has asked for. This is necessary for this endpoint to work ;; when the client sends an 'Accept: */*' header, due to the somewhat strange ;; fact that this endpoint defines no 'available-media-types', since it always ;; returns a '204 No Content' on success. ;; ;; If this resource is ever updated to define ':available-media-types' and ;; return a response body, this line of code should be deleted. :media-type-available? true ;; Never return a '201 Created', we're not creating anything :new? false :delete! (fn [_context] (if env-name (jruby-puppet/mark-environment-expired! jruby-service env-name) (jruby-puppet/mark-all-environments-expired! jruby-service)))) (defn handle-jruby-pool-flush [jruby-service] (sling/try+ (jruby-puppet/flush-jruby-pool! jruby-service) ; 204 No Content on success {:status 204} ; If a lock timeout occurs return a 503 Service Unavailable (catch [:kind :puppetlabs.services.jruby-pool-manager.impl.jruby-internal/jruby-lock-timeout] e (log/error (:msg e)) (-> (rr/response (:msg e)) (rr/status 503) (rr/content-type "text/plain"))))) (defn handle-jruby-pool-thread-dump [jruby-service] (let [result (jruby-puppet/get-jruby-thread-dump jruby-service)] (if (some :error (vals result)) (middleware-utils/json-response 500 result) (middleware-utils/json-response 200 result)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Routing (defn v1-routes "Routes for v1 of the Puppet Admin HTTP API." [jruby-service] (comidi/routes (comidi/ANY "/environment-cache" request (environment-cache-resource jruby-service (get-in request [:query-params "environment"]))) (comidi/DELETE "/jruby-pool" [] (handle-jruby-pool-flush jruby-service)) (comidi/context "/jruby-pool" (comidi/routes (comidi/GET "/thread-dump" [] (handle-jruby-pool-thread-dump jruby-service)))))) (defn versioned-routes [jruby-service] (comidi/routes (comidi/context "/v1" (v1-routes jruby-service)) (comidi/not-found "Not Found"))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (schema/defn ^:always-validate config->puppet-admin-settings :- (schema/maybe PuppetAdminSettings) "Given the full Puppet Server config map, extract and return the Puppet Admin web service settings." [config] (:puppet-admin config)) (schema/defn ^:always-validate puppet-admin-settings->whitelist-settings :- ringutils/WhitelistSettings "Given the full Puppet Admin web service settings, extract and return the embedded client whitelist settings." [admin-settings :- (schema/maybe PuppetAdminSettings)] (select-keys admin-settings [:client-whitelist :authorization-required])) (schema/defn ^:always-validate build-ring-handler :- IFn "Returns the ring handler for the Puppet Admin API." [path :- schema/Str settings :- ringutils/WhitelistSettings jruby-service :- (schema/protocol jruby-puppet/JRubyPuppetService) authorization-fn :- IFn] (-> (versioned-routes jruby-service) ((partial comidi/context path)) (comidi/routes->handler) ;(liberator-dev/wrap-trace :header) ; very useful for debugging! ;; For backward compatibility, requests to the puppet-admin endpoint ;; will be authorized by a client-whitelist, if one is configured for ;; 'certificate_status'. When we are able to drop support for ;; client-whitelist authorization later on, we should be able to get rid ;; of the 'wrap-with-trapperkeeper-or-client-whitelist-authorization' ;; function and replace with a line chaining the handler into a call to ;; 'authorization-fn'. (ringutils/wrap-with-trapperkeeper-or-client-whitelist-authorization authorization-fn path settings) i18n/locale-negotiator pl-ring-params/wrap-params)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/puppet_admin/puppet_admin_service.clj000066400000000000000000000047511470345337400340220ustar00rootroot00000000000000(ns puppetlabs.services.puppet-admin.puppet-admin-service (:require [puppetlabs.trapperkeeper.core :refer [defservice]] [puppetlabs.trapperkeeper.services :as services] [puppetlabs.services.puppet-admin.puppet-admin-core :as core] [clojure.tools.logging :as log] [puppetlabs.i18n.core :as i18n])) (defservice puppet-admin-service [[:ConfigService get-config] [:WebroutingService add-ring-handler get-route] [:JRubyPuppetService] [:AuthorizationService wrap-with-authorization-check] [:CaService get-auth-handler]] (init [this context] (log/info (i18n/trs "Starting Puppet Admin web app")) (let [route (get-route this) settings (core/config->puppet-admin-settings (get-config)) jruby-service (services/get-service this :JRubyPuppetService) whitelist-settings (core/puppet-admin-settings->whitelist-settings settings) client-whitelist (:client-whitelist whitelist-settings)] (cond (or (false? (:authorization-required whitelist-settings)) (not-empty client-whitelist)) (log/warn (format "%s %s" (i18n/trs "The ''client-whitelist'' and ''authorization-required'' settings in the ''puppet-admin'' section are deprecated and will be removed in a future release.") (i18n/trs "Remove these settings and create an appropriate authorization rule in the /etc/puppetlabs/puppetserver/conf.d/auth.conf file."))) (not (nil? client-whitelist)) (log/warn (format "%s %s %s" (i18n/trs "The ''client-whitelist'' and ''authorization-required'' settings in the ''puppet-admin'' section are deprecated and will be removed in a future release.") (i18n/trs "Because the ''client-whitelist'' is empty and ''authorization-required'' is set to ''false'', the ''puppet-admin'' settings will be ignored and authorization for the ''puppet-admin'' endpoints will be done per the authorization rules in the /etc/puppetlabs/puppetserver/conf.d/auth.conf file.") (i18n/trs "To suppress this warning, remove the ''puppet-admin'' configuration settings.")))) (add-ring-handler this (core/build-ring-handler route whitelist-settings jruby-service (get-auth-handler)) {:normalize-request-uri true})) context)) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/puppet_profiler/000077500000000000000000000000001470345337400276465ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/puppet_profiler/puppet_profiler_core.clj000066400000000000000000000127731470345337400346010ustar00rootroot00000000000000(ns puppetlabs.services.puppet-profiler.puppet-profiler-core (:import (com.codahale.metrics MetricRegistry) (com.puppetlabs.puppetserver MetricsPuppetProfiler PuppetProfiler)) (:require [clojure.string :as str] [schema.core :as schema] [puppetlabs.kitchensink.core :as ks] [puppetlabs.trapperkeeper.services.status.status-core :as status-core] [puppetlabs.metrics :as metrics])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Schemas (def MetricsProfilerServiceContext {:profiler (schema/maybe PuppetProfiler)}) (def MetricsProfilerServiceConfig {(schema/optional-key :enabled) (schema/conditional string? schema/Str :else schema/Bool)}) (def PuppetProfilerStatusV1 {(schema/optional-key :experimental) {:function-metrics [{:function schema/Str :count schema/Int :mean schema/Num :aggregate schema/Num}] :resource-metrics [{:resource schema/Str :count schema/Int :mean schema/Num :aggregate schema/Num}] :catalog-metrics [{:metric schema/Str :count schema/Int :mean schema/Num :aggregate schema/Num}] :puppetdb-metrics [{:metric schema/Str :count schema/Int :mean schema/Num :aggregate schema/Num}] :inline-metrics [{:metric schema/Str :count schema/Int}]}}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Private (schema/defn metrics-profiler :- PuppetProfiler [hostname :- String registry :- MetricRegistry] (MetricsPuppetProfiler. hostname registry)) (defn function-metric [[function-name timer]] (let [count (.getCount timer) mean (metrics/mean-millis timer)] {:function function-name :count count :mean mean :aggregate (* count mean)})) (defn resource-metric [[resource-name timer]] (let [count (.getCount timer) mean (metrics/mean-millis timer)] {:resource resource-name :count count :mean mean :aggregate (* count mean)})) (defn catalog-metric [[metric-name timer]] (let [count (.getCount timer) mean (metrics/mean-millis timer)] {:metric metric-name :count count :mean mean :aggregate (* count mean)})) (defn puppetdb-metric [[metric-name timer]] (let [count (.getCount timer) mean (metrics/mean-millis timer) ;; Metric databases like Graphite and InfluxDB treat ;; spaces and periods as delimiters. ;; ;; TODO: Should probably be abstracted into ;; trapperkeeper-metrics as a general utility function. munged-name (str/replace metric-name #"\.| " "_")] {:metric munged-name :count count :mean mean :aggregate (* count mean)})) (defn inline-metric [[metric-name timer]] (let [count (.getCount timer)] {:metric metric-name :count count})) (schema/defn assoc-metrics-data [status :- {schema/Any schema/Any} metrics-profiler :- (schema/maybe MetricsPuppetProfiler)] (if metrics-profiler (let [function-metrics (->> (map function-metric (.getFunctionTimers metrics-profiler)) (sort-by :aggregate) reverse) resource-metrics (->> (map resource-metric (.getResourceTimers metrics-profiler)) (sort-by :aggregate) reverse) catalog-metrics (->> (map catalog-metric (.getCatalogTimers metrics-profiler)) (sort-by :aggregate) reverse) puppetdb-metrics (->> (map puppetdb-metric (.getPuppetDBTimers metrics-profiler)) (sort-by :aggregate) reverse) inline-metrics (->> (map inline-metric (.getInliningTimers metrics-profiler)) (sort-by :count) reverse)] (-> status (assoc-in [:experimental :function-metrics] (take 50 function-metrics)) (assoc-in [:experimental :resource-metrics] (take 50 resource-metrics)) (assoc-in [:experimental :catalog-metrics] catalog-metrics) (assoc-in [:experimental :puppetdb-metrics] puppetdb-metrics) (assoc-in [:experimental :inline-metrics] inline-metrics))) status)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (schema/defn ^:always-validate v1-status :- status-core/StatusCallbackResponse [metrics-profiler :- (schema/maybe MetricsPuppetProfiler) level :- status-core/ServiceStatusDetailLevel] (let [level>= (partial status-core/compare-levels >= level)] {:state :running :status (cond-> ;; no status info at ':critical' level {} ;; no extra status at ':info' level yet (level>= :info) identity (level>= :debug) (assoc-metrics-data metrics-profiler))})) (schema/defn ^:always-validate initialize :- MetricsProfilerServiceContext [config :- MetricsProfilerServiceConfig hostname :- schema/Str registry :- (schema/maybe MetricRegistry)] (let [enabled (if (some? (:enabled config)) (ks/to-bool (:enabled config)) true)] (if enabled {:profiler (metrics-profiler hostname registry)} {:profiler nil}))) puppet_profiler_service.clj000066400000000000000000000035301470345337400352210ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/puppet_profiler(ns puppetlabs.services.puppet-profiler.puppet-profiler-service (:require [puppetlabs.trapperkeeper.core :as trapperkeeper] [puppetlabs.services.puppet-profiler.puppet-profiler-core :as puppet-profiler-core] [puppetlabs.services.protocols.puppet-profiler :as profiler] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.trapperkeeper.services.status.status-core :as status-core])) ;; Default list of allowed histograms/timers (def default-metrics-allowed ["compiler" "compiler.compile" "compiler.find_facts" "compiler.find_node" "compiler.static_compile" "compiler.static_compile_inlining" "compiler.static_compile_postprocessing" "functions" "puppetdb.catalog.save" "puppetdb.command.submit" "puppetdb.facts.find" "puppetdb.facts.search" "puppetdb.report.process" "puppetdb.resource.search"]) (trapperkeeper/defservice puppet-profiler-service profiler/PuppetProfilerService [[:MetricsService get-metrics-registry get-server-id update-registry-settings] [:ConfigService get-in-config] [:StatusService register-status]] (init [this context] (let [context (puppet-profiler-core/initialize (get-in-config [:profiler] {}) (get-server-id) (get-metrics-registry :puppetserver))] (update-registry-settings :puppetserver {:default-metrics-allowed default-metrics-allowed}) (register-status "puppet-profiler" (status-core/get-artifact-version "puppetlabs" "puppetserver") 1 (partial puppet-profiler-core/v1-status (:profiler context))) context)) (get-profiler [this] (:profiler (tk-services/service-context this)))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/request_handler/000077500000000000000000000000001470345337400276145ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/request_handler/request_handler_core.clj000066400000000000000000000277261470345337400345210ustar00rootroot00000000000000(ns puppetlabs.services.request-handler.request-handler-core (:require [clojure.string :as string] [clojure.tools.logging :as log] [clojure.walk :as walk] [puppetlabs.i18n.core :as i18n] [puppetlabs.puppetserver.common :as ps-common] [puppetlabs.puppetserver.jruby-request :as jruby-request] [puppetlabs.ring-middleware.params :as pl-ring-params] [puppetlabs.ring-middleware.utils :as ringutils] [puppetlabs.ssl-utils.core :as ssl-utils] [puppetlabs.trapperkeeper.authorization.ring :as ring-auth] [ring.util.codec :as ring-codec] [schema.core :as schema]) (:import (com.puppetlabs.puppetserver JRubyPuppetResponse) (java.io StringReader) (java.util HashMap Map))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Internal (def header-client-cert-name "Name of the HTTP header through which a client certificate can be passed for a request" "x-client-cert") (defn unmunge-http-header-name "Given the value of a Puppet setting which contains a munged HTTP header name, convert it to the actual header name in all lower-case." [setting] (->> (string/split setting #"_") rest (string/join "-") string/lower-case)) (defn config->request-handler-settings "Given an entire Puppet Server configuration map, return only those keys which are required by the request handler service." [{:keys [puppetserver master]}] {:allow-header-cert-info (true? (:allow-header-cert-info master)) :ssl-client-verify-header (unmunge-http-header-name (:ssl-client-verify-header puppetserver)) :ssl-client-header (unmunge-http-header-name (:ssl-client-header puppetserver))}) (defn response->map "Converts a JRubyPuppetResponse instance to a map." [response] { :pre [(instance? JRubyPuppetResponse response)] :post [(map? %)]} { :status (.getStatus response) :body (.getBody response) :headers {"Content-Type" (.getContentType response) "X-Puppet-Version" (.getPuppetVersion response)}}) (defn update-body-for-jruby "Converts the body from a request into a String if it is a form encoding. Otherwise, just returns back the same body InputStream." [request] (let [content-type (when-let [raw-type (:content-type request)] (string/lower-case raw-type))] (if (= content-type "application/x-www-form-urlencoded") (update request :body slurp :encoding (or (:character-encoding request) "UTF-8")) request))) (defn wrap-params-for-jruby "Pull parameters from the URL query string and/or urlencoded form POST body into the ring request map. Includes some special processing for a request destined for JRubyPuppet." [request] (-> request update-body-for-jruby pl-ring-params/params-request)) (def unauthenticated-client-info "Return a map with default info for an unauthenticated client" {:client-cert-cn nil :authenticated false}) (defn header-auth-info "Return a map with authentication info based on header content" [header-dn-name header-dn-val header-auth-name header-auth-val] (if (ssl-utils/valid-x500-name? header-dn-val) (let [cn (ssl-utils/x500-name->CN header-dn-val) authenticated (= "SUCCESS" header-auth-val)] (log/debug (i18n/trs "CN ''{0}'' provided by HTTP header ''{1}''" cn header-dn-val)) (log/debug (format "%s %s" (i18n/trs "Verification of client ''{0}'' provided by HTTP header ''{1}'': ''{2}''." cn header-auth-name header-auth-val) (i18n/trs "Authenticated: {0}." authenticated))) {:client-cert-cn cn :authenticated authenticated}) (do (if (nil? header-dn-val) (log/debug (format "%s %s" (i18n/trs "No DN provided by the HTTP header ''{0}''." header-dn-name) (i18n/trs "Treating client as unauthenticated."))) (log/error (format "%s %s" (i18n/trs "DN ''{0}'' provided by the HTTP header ''{1}'' is malformed." header-dn-val header-dn-name) (i18n/trs "Treating client as unauthenticated.")))) unauthenticated-client-info))) (defn header-cert->pem "Convert the header cert value into a PEM string" [header-cert] (try (ring-codec/url-decode header-cert) (catch Exception e (ringutils/throw-bad-request! (i18n/tru "Unable to URL decode the {0} header: {1}" header-client-cert-name (.getMessage e)))))) (defn pem->certs "Convert a pem string into certificate objects" [pem] (with-open [reader (StringReader. pem)] (try (ssl-utils/pem->certs reader) (catch Exception e (ringutils/throw-bad-request! (i18n/tru "Unable to parse {0} into certificate: {1}" header-client-cert-name (.getMessage e))))))) (defn header-cert "Return an X509Certificate or nil from a string encoded for transmission in an HTTP header." [header-cert-val] (when header-cert-val (let [pem (header-cert->pem header-cert-val) certs (pem->certs pem) cert-count (count certs)] (condp = cert-count 0 (ringutils/throw-bad-request! (i18n/tru "No certs found in PEM read from {0}" header-client-cert-name)) 1 (first certs) (ringutils/throw-bad-request! (i18n/tru "Only 1 PEM should be supplied for {0} but {1} found" header-client-cert-name cert-count)))))) (defn ssl-auth-info "Get map of client authentication info from the supplied `java.security.cert.X509Certificate` object. If the supplied object is nil, the information returned would represent an 'unauthenticated' client." [ssl-client-cert] (if ssl-client-cert (let [cn (ssl-utils/get-cn-from-x509-certificate ssl-client-cert) authenticated (if (seq cn) true false)] (log/debug (i18n/trs "CN ''{0}'' provided by SSL certificate. Authenticated: {1}." cn authenticated)) {:client-cert-cn cn :authenticated authenticated}) (do (log/debug (i18n/trs "No SSL client certificate provided. Treating client as unauthenticated.")) unauthenticated-client-info))) (defn client-auth-info "Get map of client authentication info for the client. Map has the following keys: * :client-cert - A `java.security.cert.X509Certificate` object or nil * :client-cert-cn - The CN (Common Name) of the client, typically associated with the CN attribute from the Distinguished Name in an X.509 certificate's Subject. * :authenticated - A boolean representing whether or not the client is considered to have been successfully authenticated. Parameters: * config - Map of configuration data * request - Ring request containing client data" [config request] (if (:authorization request) {:client-cert (ring-auth/authorized-certificate request) :client-cert-cn (ring-auth/authorized-name request) :authenticated (true? (ring-auth/authorized-authenticated request))} (let [headers (:headers request) header-dn-name (:ssl-client-header config) header-dn-val (get headers header-dn-name) header-auth-name (:ssl-client-verify-header config) header-auth-val (get headers header-auth-name) header-cert-val (get headers header-client-cert-name)] (if (:allow-header-cert-info config) (-> (header-auth-info header-dn-name header-dn-val header-auth-name header-auth-val) (assoc :client-cert (header-cert header-cert-val))) (do (doseq [[header-name header-val] {header-dn-name header-dn-val header-auth-name header-auth-val header-client-cert-name header-cert-val} :when header-val] (log/warn (format "%s %s" (i18n/trs "The HTTP header {0} was specified, but the master config option allow-header-cert-info was either not set, or was set to false." header-name) (i18n/trs "This header will be ignored.")))) (let [ssl-cert (:ssl-client-cert request)] (-> (ssl-auth-info ssl-cert) (assoc :client-cert ssl-cert)))))))) (defn as-jruby-request "Given a ring HTTP request, return a new map that contains all of the data needed by the ruby HTTP layer to process it. This function does a couple things that are a bit weird: * It reads the entire request body into memory. This is not ideal for performance and memory usage, but we have to ship this thing over to JRuby, so I don't think there's any way around this. * It also extracts the client DN and certificate and includes that in the map it returns, because it's needed by the ruby layer. It is possible that the HTTPS termination has happened external to Puppet Server. If so, then the DN, authentication status, and, optionally, the certificate will be provided by HTTP headers." [config request] (merge {:uri (:uri request) :params (:params request) :remote-addr (:remote-addr request) :headers (:headers request) :body (:body request) :request-method (-> (:request-method request) name string/upper-case)} (client-auth-info config request))) (defn make-request-mutable "Make the request mutable. This is required by the ruby layer." [request] (HashMap. ^Map request)) (defn with-code-id "Wraps the given request with the current-code-id, if it contains a :include-code-id? key with a truthy value. current-code-id is passed the environment from the request from it is invoked." [current-code-id request] (if (:include-code-id? request) (let [env (jruby-request/get-environment-from-request request)] (when-not (nil? (schema/check ps-common/Environment env)) (ringutils/throw-bad-request! (ps-common/environment-validation-error-msg env))) (when-not env (ringutils/throw-bad-request! (i18n/tru "Environment is required in a catalog request."))) (assoc-in request [:params "code_id"] (current-code-id env))) request)) (defn jruby-request-handler "Build a request handler fn that processes a request using a JRubyPuppet instance" [config current-code-id] (fn [request] (try (->> request wrap-params-for-jruby (with-code-id current-code-id) (as-jruby-request config) walk/stringify-keys make-request-mutable (.handleRequest (:jruby-instance request)) response->map) (finally ;; don't let any exceptions escape (try (let [[_ certname] (re-matches #"^/puppet/v3/catalog/(.*)" (ring-codec/url-decode (:uri request)))] (when certname (ps-common/record-action {:type :action :targets [certname] :meta {:type :certificate :what :compile-catalog :where :v3}}))) (catch Throwable e (log/info e (i18n/trs "Failed to report action")))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (defn build-request-handler "Build the main request handler fn for JRuby requests." [jruby-service config current-code-id] (-> (jruby-request-handler config current-code-id) (jruby-request/wrap-with-jruby-instance jruby-service) jruby-request/wrap-with-error-handling)) request_handler_service.clj000066400000000000000000000045031470345337400351360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/request_handler(ns puppetlabs.services.request-handler.request-handler-service (:require [puppetlabs.trapperkeeper.core :as tk] [puppetlabs.services.protocols.request-handler :as handler] [puppetlabs.services.request-handler.request-handler-core :as request-handler-core] [puppetlabs.puppetserver.jruby-request :as jruby-request] [puppetlabs.trapperkeeper.services :as tk-services] [clojure.tools.logging :as log] [puppetlabs.i18n.core :as i18n])) (tk/defservice request-handler-service handler/RequestHandlerService [[:PuppetServerConfigService get-config] [:ConfigService get-in-config] [:VersionedCodeService current-code-id] [:JRubyPuppetService] [:JRubyMetricsService]] (init [this context] (let [config (get-config) max-queued-requests (get-in-config [:jruby-puppet :max-queued-requests] 0) max-retry-delay (get-in-config [:jruby-puppet :max-retry-delay] 1800) jruby-service (tk-services/get-service this :JRubyPuppetService) metrics-service (tk-services/get-service this :JRubyMetricsService) request-handler (request-handler-core/build-request-handler jruby-service (request-handler-core/config->request-handler-settings config) current-code-id)] (when (contains? (:master config) :allow-header-cert-info) (log/warn (format "%s %s" (i18n/trs "The ''master.allow-header-cert-info'' setting is deprecated and will be ignored in favor of the ''authorization.allow-header-cert-info'' setting .") (i18n/trs "Remove the ''master.allow-header-cert-info'' setting.")))) (assoc context :request-handler (if (pos? max-queued-requests) (jruby-request/wrap-with-request-queue-limit request-handler metrics-service max-queued-requests max-retry-delay) request-handler)))) (handle-request [this request] (let [handler (:request-handler (tk-services/service-context this))] (handler request)))) puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/versioned_code_service/000077500000000000000000000000001470345337400311375ustar00rootroot00000000000000versioned_code_core.clj000066400000000000000000000123601470345337400355540ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/versioned_code_service(ns puppetlabs.services.versioned-code-service.versioned-code-core (:require [schema.core :as schema] [clojure.tools.logging :as log] [puppetlabs.puppetserver.common :as ps-common] [puppetlabs.puppetserver.shell-utils :as shell-utils] [clojure.string :as string] [puppetlabs.i18n.core :as i18n]) (:import (java.io IOException InputStream) (org.apache.commons.io IOUtils))) (def VersionedCodeServiceConfig "Schema describing the versioned-code-service config settings" {(schema/optional-key :code-id-command) schema/Str (schema/optional-key :code-content-command) schema/Str}) (schema/defn ^:always-validate success-with-stderr-msg :- schema/Str [cmd :- schema/Str stderr :- schema/Str] (format "%s %s" (i18n/trs "Error output generated while running ''{0}''." cmd) (i18n/trs "stderr: ''{0}''" stderr))) (schema/defn ^:always-validate nonzero-msg :- schema/Str [cmd :- schema/Str exit-code :- schema/Int stdout :- schema/Str stderr :- schema/Str] (format "%s %s" (i18n/trs "Non-zero exit code returned while running ''{0}''." cmd) (i18n/trs "exit-code: ''{0}'', stdout: ''{1}'', stderr: ''{2}''" exit-code stdout stderr))) (schema/defn ^:always-validate execution-error-msg :- schema/Str [cmd :- schema/Str e :- Exception] (i18n/trs "Running script generated an error. Command executed: ''{0}'', error generated: ''{1}''" cmd (.getMessage e))) (schema/defn ^:always-validate execute-code-id-script! :- schema/Str "Executes code-id-script to determine the code-id for environment. Non-zero return from code-id-script generates an IllegalStateException." [code-id-script :- schema/Str environment :- ps-common/Environment] (let [{:keys [exit-code stderr stdout]} (shell-utils/execute-command code-id-script {:args [environment]})] ; TODO Decide what to do about normalizing/sanitizing output with respect to ; control characters and encodings ;; There are three cases we care about here: ;; - exit code is 0 and no stderr generated: groovy. return stdout ;; - exit code is 0 and stderr was generated: that's fine. log an error ;; about the stderr and return stdout. ;; - exit code is non-zero: oh no! throw an error with all the details (if (zero? exit-code) (do (when-not (string/blank? stderr) (log/error (success-with-stderr-msg code-id-script stderr))) (string/trim-newline stdout)) (throw (IllegalStateException. (nonzero-msg code-id-script exit-code stdout stderr)))))) (schema/defn get-current-code-id! :- (schema/maybe String) "Execute the code-id-script and validate its output before returning" [code-id-script :- schema/Str environment :- schema/Str] (let [code-id (execute-code-id-script! code-id-script environment)] (when-not (nil? (schema/check (schema/maybe ps-common/CodeId) code-id)) (throw (IllegalStateException. (ps-common/code-id-validation-error-msg code-id)))) code-id)) (schema/defn ^:always-validate execute-code-content-script! :- InputStream "Given a string path to an executable script and the environment, code-id, and file-path of a desired revision of a file, returns that file as a stream. Does no exception catching: Being unable to compute code content is considered a fatal error and should be handled by calling code appropriately." [code-content-script :- schema/Str environment :- ps-common/Environment code-id :- ps-common/CodeId file-path :- schema/Str] (let [throw-execution-error! (fn [e] (throw (IllegalStateException. (execution-error-msg code-content-script e))))] (try (let [{:keys [stdout stderr exit-code]} (shell-utils/execute-command-streamed code-content-script {:args [environment code-id file-path]})] (if (zero? exit-code) (do (when-not (string/blank? stderr) (log/error (success-with-stderr-msg code-content-script stderr))) stdout) (throw (IllegalStateException. (nonzero-msg code-content-script exit-code (IOUtils/toString stdout "UTF-8") stderr))))) (catch IllegalArgumentException e (throw-execution-error! e)) (catch IOException e (throw-execution-error! e)) (catch InterruptedException e (throw-execution-error! e))))) (schema/defn ^:always-validate validate-config! "Validates the versioned-code-service config. The config is considered valid if it is either empty or fully populated." [{:keys [code-id-command code-content-command]} :- (schema/maybe VersionedCodeServiceConfig)] (when (or (and code-id-command (not code-content-command)) (and (not code-id-command) code-content-command)) (throw (IllegalStateException. (format "%s %s" (i18n/trs "Only one of \"versioned-code.code-id-command\" and \"versioned-code.code-content-command\" was set.") (i18n/trs "Both or neither must be set for the versioned-code-service to function correctly.")))))) versioned_code_service.clj000066400000000000000000000032741470345337400362700ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/clj/puppetlabs/services/versioned_code_service(ns puppetlabs.services.versioned-code-service.versioned-code-service (:require [puppetlabs.trapperkeeper.core :as trapperkeeper] [puppetlabs.services.protocols.versioned-code :as vc] [puppetlabs.services.versioned-code-service.versioned-code-core :as vc-core] [clojure.tools.logging :as log] [puppetlabs.i18n.core :as i18n])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public (trapperkeeper/defservice versioned-code-service vc/VersionedCodeService [[:ConfigService get-in-config]] (init [this context] (when (nil? (get-in-config [:versioned-code :code-id-command])) (log/info (i18n/trs "No code-id-command set for versioned-code-service. Code-id will be nil."))) (when (nil? (get-in-config [:versioned-code :code-content-command])) (log/info (i18n/trs "No code-content-command set for versioned-code-service. Attempting to fetch code content will fail."))) (vc-core/validate-config! (get-in-config [:versioned-code])) context) (current-code-id [this environment] (if-let [code-id-script (get-in-config [:versioned-code :code-id-command])] (vc-core/get-current-code-id! code-id-script environment) nil)) (get-code-content [this environment code-id file-path] (if-let [code-content-script (get-in-config [:versioned-code :code-content-command])] (vc-core/execute-code-content-script! code-content-script environment code-id file-path) (throw (IllegalStateException. (i18n/trs "Cannot retrieve code content because the \"versioned-code.code-content-command\" setting is not present in configuration.")))))) puppetlabs-puppetserver-7e1a9a8/src/java/000077500000000000000000000000001470345337400205765ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/java/com/000077500000000000000000000000001470345337400213545ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/java/com/puppetlabs/000077500000000000000000000000001470345337400235335ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/java/com/puppetlabs/puppetserver/000077500000000000000000000000001470345337400262775ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/java/com/puppetlabs/puppetserver/EnvironmentRegistry.java000066400000000000000000000003341470345337400331770ustar00rootroot00000000000000package com.puppetlabs.puppetserver; public interface EnvironmentRegistry { public void registerEnvironment(String name); public boolean isExpired(String name); public void removeEnvironment(String name); } puppetlabs-puppetserver-7e1a9a8/src/java/com/puppetlabs/puppetserver/JRubyPuppet.java000066400000000000000000000024351470345337400313770ustar00rootroot00000000000000package com.puppetlabs.puppetserver; import java.util.Map; import java.util.List; /** * * This interface is a bridge between the clojure/Java code and the ruby class * `JRubyPuppet`. (defined in `src/ruby/puppetserver-lib/puppet/server/master.rb`.) * The ruby class uses some JRuby magic that causes it to "implement" the Java * interface. * * So, from the outside (in the clojure/Java code), we can interact with an instance * of the ruby class simply as if it were an instance of this interface; thus, consuming * code need not be aware of any of the JRuby implementation details. * */ public interface JRubyPuppet { Map getTaskData(String environment, String module, String task); List getTasks(String environment); Map getPlanData(String environment, String module, String plan); List getPlans(String environment); Map getClassInfoForEnvironment(String environment); List getTransportInfoForEnvironment(String environment); List getModuleInfoForEnvironment(String environment); Map compileCatalog(Map requestBody); Map compileAST(Map compileOptions, List boltlibPath); Map getModuleInfoForAllEnvironments(); JRubyPuppetResponse handleRequest(Map request); Object getSetting(String setting); String puppetVersion(); void terminate(); } puppetlabs-puppetserver-7e1a9a8/src/java/com/puppetlabs/puppetserver/JRubyPuppetResponse.java000066400000000000000000000023151470345337400331130ustar00rootroot00000000000000package com.puppetlabs.puppetserver; /** * This class is a simple data structure that contains the response to an * agent -> master HTTP request, including all information * produced by the master during the processing of the request that needs to be * included in the response back to the client. * * Instances of this class act as carriers for information from the old ruby * code, running in JRuby, back to the `RequestHandlerService` implementation * in clojure. */ public class JRubyPuppetResponse { private final Integer status; private final Object body; private final String contentType; private final String puppetVersion; public JRubyPuppetResponse( Integer status, Object body, String contentType, String puppetVersion) { this.status = status; this.body = body; this.contentType = contentType; this.puppetVersion = puppetVersion; } public Object getBody() { return body; } public Integer getStatus() { return status; } public String getContentType() { return contentType; } public String getPuppetVersion() { return puppetVersion; } } puppetlabs-puppetserver-7e1a9a8/src/java/com/puppetlabs/puppetserver/MetricsPuppetProfiler.java000066400000000000000000000171511470345337400334560ustar00rootroot00000000000000package com.puppetlabs.puppetserver; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Collections; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MetricsPuppetProfiler implements PuppetProfiler { private final String hostname; private final MetricRegistry registry; private final Set metric_ids; private final Map function_timers; private final Map resource_timers; private final Map catalog_timers; private final Map inlining_timers; private final Map puppetdb_timers; public MetricsPuppetProfiler(String hostname, MetricRegistry registry) { this.hostname = hostname; this.registry = registry; this.metric_ids = Collections.newSetFromMap(new ConcurrentHashMap()); this.function_timers = new ConcurrentHashMap(); this.resource_timers = new ConcurrentHashMap(); this.catalog_timers = new ConcurrentHashMap(); this.inlining_timers = new ConcurrentHashMap(); this.puppetdb_timers = new ConcurrentHashMap(); } @Override public Object start(String message, String[] metric_id) { return System.currentTimeMillis(); } @Override public void finish(Object context, String message, String[] metric_id) { if (shouldTime(metric_id)) { Long elapsed = System.currentTimeMillis() - (Long)context; Map metricsByID = getOrCreateTimersByIDs(metric_id); for (Timer t : metricsByID.values()) { t.update(elapsed, TimeUnit.MILLISECONDS); } updateMetricsTrackers(metric_id, metricsByID); } } public Set getAllMetricIds() { return this.metric_ids; } public Map getFunctionTimers() { return this.function_timers; } public Map getResourceTimers() { return this.resource_timers; } public Map getCatalogTimers() { return this.catalog_timers; } public Map getInliningTimers() { return this.inlining_timers; } public Map getPuppetDBTimers() { return this.puppetdb_timers; } @Override public void shutdown() { } private List sliceOfArrayToList(String[] idSegments, int lengthOfID) { // Callers expect a mutable List returned, but Arrays.asList() returns a // fix length array, which is why we have to create a List and then add to it. List idList = new ArrayList(); idList.addAll(Arrays.asList(Arrays.copyOf(idSegments, lengthOfID))); return idList; } private String safeGet(String[] collection, int i) { try { return collection[i]; } catch (IndexOutOfBoundsException _ex) { return ""; } } private void updateMetricsTrackers(String[] metricId, Map metricsByID) { String firstElement = safeGet(metricId, 0); String secondElement = safeGet(metricId, 1); if ("functions".equals(firstElement)) { Timer metric = metricsByID.get(getMetricName(sliceOfArrayToList(metricId, 2))); this.function_timers.put(secondElement, metric); } else if ("compiler".equals(firstElement)) { String thirdElemet = safeGet(metricId, 2); if ("evaluate_resource".equals(secondElement)) { Timer metric = metricsByID.get(getMetricName(sliceOfArrayToList(metricId, 3))); this.resource_timers.put(thirdElemet, metric); } else if ("static_compile_inlining".equals(secondElement)) { Timer metric = metricsByID.get(getMetricName(sliceOfArrayToList(metricId, 3))); this.inlining_timers.put(thirdElemet, metric); } else { Timer metric = metricsByID.get(getMetricName(sliceOfArrayToList(metricId, 2))); this.catalog_timers.put(secondElement, metric); } } else if ("puppetdb".equals(firstElement)) { if ("query".equals(secondElement)) { Timer metric = metricsByID.get(getMetricName(sliceOfArrayToList(metricId, 2))); this.puppetdb_timers.put(secondElement, metric); } else { String thirdElemet = safeGet(metricId, 2); if ( ("resource".equals(secondElement) && "search".equals(thirdElemet)) || ("payload".equals(secondElement) && "format".equals(thirdElemet)) || // Set.of would be preferrable but 7.x still support Java 8, which does not have Set.of ("facts".equals(secondElement) && Arrays.asList("save", "find", "search", "encode").contains(thirdElemet)) || ("catalog".equals(secondElement) && Arrays.asList("save", "munge").contains(thirdElemet)) || ("report".equals(secondElement) && Arrays.asList("convert_to_wire_format_hash", "process").contains(thirdElemet)) ) { String key = String.join(".", secondElement, thirdElemet); Timer metric = metricsByID.get(getMetricName(sliceOfArrayToList(metricId, 3))); this.puppetdb_timers.put(key, metric); } else if ("command".equals(secondElement) && "submit".equals(thirdElemet)) { String fourthElement = safeGet(metricId, 3); if ( "store report".equals(fourthElement) || "replace facts".equals(fourthElement) || "replace catalog".equals(fourthElement) ) { String key = String.join(".", secondElement, thirdElemet, fourthElement); Timer metric = metricsByID.get(getMetricName(sliceOfArrayToList(metricId, 4))); this.puppetdb_timers.put(key, metric); } } } } } private boolean shouldTime(String[] metric_id) { if (metric_id == null) { return false; } if ((metric_id.length > 0) && (metric_id[0].equals("http"))) { // Puppet contains some metrics that are intended to time http requests. We have // more comprehensive metrics for this in our ring middleware, so we skip the // ones from Puppet. return false; } return true; } private Map getOrCreateTimersByIDs(String[] metric_id) { Map timers = new HashMap(); // If this is turns out to be a performance hit, we could cache these in a // map or something. for (int i = 0; i < metric_id.length; i++) { List current_id = new ArrayList(); for (int j = 0; j <= i; j++) { current_id.add(metric_id[j]); } String metric_name = getMetricName(current_id); registerMetricName(metric_name); timers.put(metric_name, registry.timer(metric_name)); } return timers; } private String getMetricName(List metric_id) { metric_id.add(0, hostname); return MetricRegistry.name("puppetlabs", metric_id.toArray(new String[metric_id.size()])); } private void registerMetricName(String metric_name) { this.metric_ids.add(metric_name); } } puppetlabs-puppetserver-7e1a9a8/src/java/com/puppetlabs/puppetserver/PuppetProfiler.java000066400000000000000000000006771470345337400321340ustar00rootroot00000000000000package com.puppetlabs.puppetserver; /** * This interface specifies Java method signatures that map to the API of the * Ruby Puppet Profiler. JVM implementations of this interface can be wired in * to the Puppet Server and used to provide profiling support. */ public interface PuppetProfiler { Object start(String message, String[] metric_id); void finish(Object context, String message, String[] metric_id); void shutdown(); } puppetlabs-puppetserver-7e1a9a8/src/ruby/000077500000000000000000000000001470345337400206365ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/000077500000000000000000000000001470345337400241465ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/000077500000000000000000000000001470345337400254635ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server.rb000066400000000000000000000000531470345337400273140ustar00rootroot00000000000000require 'puppet' module Puppet::Server endpuppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/000077500000000000000000000000001470345337400267715ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/ast_compiler.rb000066400000000000000000000252711470345337400320060ustar00rootroot00000000000000require 'puppet_pal' require 'puppet/server/log_collector' require 'puppet/server/logging' module Puppet module Server class ASTCompiler def self.compile(compile_options, boltlib_path) options = compile_options['options'] || {} log_level = options['log_level'] code = JSON.parse(compile_options['code_ast']) if options['capture_logs'] catalog, logs = Logging.capture_logs(log_level) do compile_ast(code, compile_options, boltlib_path) end { catalog: catalog, logs: logs } else catalog = compile_ast(code, compile_options, boltlib_path) { catalog: catalog } end end def self.compile_ast(code, compile_options, boltlib_path) # Save the original node_name_value, to be put back later original_node_name_value = Puppet[:node_name_value] # Set node_name_value directly. All types of compilation # including project/environment and plan/non-plan compiles # will need to have this set. Puppet[:node_name_value] = compile_options['certname'] # If the request requires that bolt be loaded we assume we are in a properly # configured PE environment if compile_options.dig('options', 'compile_for_plan') unless boltlib_path msg = "When compile_for_plan is set, the path to boltlib modules " \ "must be provided by setting boltlib-path as a jruby-puppet setting in pe-puppet-server.conf" raise(Puppet::Error, msg) end load_bolt() if compile_options.has_key?('versioned_project') compile_for_project_plan(code, compile_options, boltlib_path) else compile_for_environment_plan(code, compile_options, boltlib_path) end else compile_for_environment(code, compile_options, boltlib_path) end ensure Puppet[:node_name_value] = original_node_name_value end private_class_method :compile_ast def self.compile_for_project_plan(code, compile_options, boltlib_path) # Save the original hiera_config value, to be put back later original_hiera_config = Puppet[:hiera_config] # hiera_config is set directly here rather than passing it to # Puppet.override below. For some reason passing it to .override # does not correctly force it to update and compilation does not # correctly use the updated setting. We decided not to continue # pursuing debugging that behavior, and instead just set it # directly here and return hiera_config to it's original value # below. # - Sean P. McDonald 8/3/2021 # Puppet[:hiera_config] = compile_options['hiera_config'] # Modulepath needs to be combined "manually" here because there is no # equivalent to pre_modulepath for in_tmp_environment env_conf = { modulepath: Array(boltlib_path) + Array(compile_options['modulepath']), facts: compile_options['facts']['values'], } plan_variables = ordered_plan_vars(compile_options) target_variables = compile_options.dig('target_variables', 'values') || {} variables = { variables: plan_variables, target_variables: target_variables, } # TODO: Given we hide this from plan authors this current iteration has only # the "required" data for now. Once we can get https://github.com/puppetlabs/bolt/pull/1770 # merged and promoted we can just use an empty hash. fake_config = { 'transport' => 'redacted', 'transports' => { 'redacted' => 'redacted' } } bolt_inv = Bolt::ApplyInventory.new(fake_config) bolt_project = Struct.new(:name, :path, :load_as_module?).new(compile_options['project_name'], compile_options['project_root'], true) puppet_overrides = { bolt_inventory: bolt_inv, bolt_project: bolt_project, } Puppet::Pal.in_tmp_environment('bolt_catalog', **env_conf) do |pal| Puppet.override(puppet_overrides) do Puppet.lookup(:pal_current_node).trusted_data = compile_options['trusted_facts']['values'] pal.with_catalog_compiler(**variables) do |compiler| Puppet[:strict] = :warning Puppet[:strict_variables] = false ast = build_program(code) compiler.evaluate(ast) compiler.evaluate_ast_node compiler.compile_additions compiler.catalog_data_hash end end end ensure # Return hiera_config to it's original state Puppet[:hiera_config] = original_hiera_config end private_class_method :compile_for_project_plan def self.compile_for_environment_plan(code, compile_options, boltlib_path) plan_variables = ordered_plan_vars(compile_options) target_variables = compile_options.dig('target_variables', 'values') || {} variables = { variables: plan_variables, target_variables: target_variables, } env_conf = { pre_modulepath: boltlib_path, envpath: Puppet[:environmentpath], facts: compile_options['facts']['values'], } # Use the existing environment with the requested name Puppet::Pal.in_environment(compile_options['environment'], **env_conf) do |pal| # TODO: Given we hide this from plan authors this current iteration has only # the "required" data for now. Once we can get https://github.com/puppetlabs/bolt/pull/1770 # merged and promoted we can just use an empty hash. fake_config = { 'transport' => 'redacted', 'transports' => { 'redacted' => 'redacted' } } bolt_inv = Bolt::ApplyInventory.new(fake_config) Puppet.override(bolt_inventory: bolt_inv) do Puppet.lookup(:pal_current_node).trusted_data = compile_options['trusted_facts']['values'] # This compiler has been configured with a node containing # the requested environment, facts, and variables, and is used # to compile a catalog in that context from the supplied AST. pal.with_catalog_compiler(**variables) do |compiler| # TODO: PUP-10476 Explore setting these as default in PAL. They are the defaults in Puppet Puppet[:strict] = :warning Puppet[:strict_variables] = false ast = build_program(code) compiler.evaluate(ast) compiler.evaluate_ast_node compiler.compile_additions compiler.catalog_data_hash end end end end private_class_method :compile_for_environment_plan # When we do not need to load bolt we assume there are no Bolt types to resolve in # AST compilation. def self.compile_for_environment(code, compile_options, boltlib_path) # Use the existing environment with the requested name Puppet::Pal.in_environment(compile_options['environment'], envpath: Puppet[:environmentpath], facts: compile_options['facts']['values'], variables: compile_options['variables']['values']) do |pal| Puppet.lookup(:pal_current_node).trusted_data = compile_options['trusted_facts']['values'] # This compiler has been configured with a node containing # the requested environment, facts, and variables, and is used # to compile a catalog in that context from the supplied AST. pal.with_catalog_compiler do |compiler| # We have to parse the AST inside the compiler block, because it # initializes the necessary type loaders for us. ast = Puppet::Pops::Serialization::FromDataConverter.convert(code) compiler.evaluate(ast) compiler.compile_additions compiler.catalog_data_hash end end end private_class_method :compile_for_environment # Prior to PE-29443 variables were in a hash. Serialization between ruby/clojure/json did # not preserve hash order necessary for deserialization. The data strucutre is now stored # in a list for moving data and the list is used to construct an ordered ruby hash. def self.ordered_plan_vars(compile_options) if compile_options['variables']['values'].is_a?(Array) compile_options['variables']['values'].each_with_object({}) do |param_hash, acc| acc[param_hash.keys.first] = param_hash.values.first end else compile_options['variables']['values'] end end private_class_method :ordered_plan_vars def self.load_bolt() # TODO: PE-28677 Develop entrypoint for loading bits of bolt we need here. require 'bolt/apply_inventory' require 'bolt/apply_target' require 'bolt/pal/issues' end private_class_method :load_bolt def self.build_program(code) ast = Puppet::Pops::Serialization::FromDataConverter.convert(code) # Node definitions must be at the top level of the apply block. # That means the apply body either a) consists of just a # NodeDefinition, b) consists of a BlockExpression which may # contain NodeDefinitions, or c) doesn't contain NodeDefinitions. # See https://github.com/puppetlabs/bolt/pull/1512 for more details definitions = if ast.is_a?(Puppet::Pops::Model::BlockExpression) ast.statements.select { |st| st.is_a?(Puppet::Pops::Model::NodeDefinition) } elsif ast.is_a?(Puppet::Pops::Model::NodeDefinition) [ast] else [] end # During ordinary compilation, definitions are stored on the parser at # parse time and then added to the Program node at the root of the AST # before evaluation. Because the AST for an apply block has already been # parsed and is not a complete tree with a Program at the root level, we # need to rediscover the definitions and construct our own Program object. # https://github.com/puppetlabs/bolt/commit/3a7597dda25cdb25854c7d08d37c5c58ab6a016b Puppet::Pops::Model::Factory.PROGRAM(ast, definitions, ast.locator).model end private_class_method :build_program end end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/auth_config.rb000066400000000000000000000007571470345337400316150ustar00rootroot00000000000000## This is a "dummy" AuthConfig that Puppet Server registers with core ## Puppet for cases where Puppet Server decides that it should be in charge of ## authorizing requests at the Clojure / Ring handler level - depending upon ## the configuration of the 'use_legacy_auth_conf' setting - and not core ## Puppet. class Puppet::Server::AuthConfig def initialize Puppet.debug 'Using PuppetServer AuthConfig for server routes' end def check_authorization(method, path, params) end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/auth_config_loader.rb000066400000000000000000000007451470345337400331400ustar00rootroot00000000000000## This is a "dummy" AuthConfigLoader that Puppet Server registers with core ## Puppet for cases where Puppet Server decides that it should be in charge of ## authorizing requests at the Clojure / Ring handler level - depending upon ## the configuration of the 'use_legacy_auth_conf' setting - and not core ## Puppet. require 'puppet/server/auth_config' class Puppet::Server::AuthConfigLoader def self.authconfig @cached_authconfig ||= Puppet::Server::AuthConfig.new end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/auth_provider.rb000066400000000000000000000006701470345337400321740ustar00rootroot00000000000000## This is a "dummy" AuthProvider that Puppet Server registers with core ## Puppet for cases where Puppet Server decides that it should be in charge of ## authorizing requests at the Clojure / Ring handler level - depending upon ## the configuration of the 'use_legacy_auth_conf' setting - and not core ## Puppet. class Puppet::Server::AuthProvider def initialize(rights) end def check_authorization(method, path, params) end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/certificate.rb000066400000000000000000000037671470345337400316150ustar00rootroot00000000000000require 'puppet/ssl/base' require 'puppet/ssl/certificate' require 'puppet/ssl/oids' require 'puppet/server' require 'java' java_import com.puppetlabs.ssl_utils.SSLUtils java_import com.puppetlabs.ssl_utils.ExtensionsUtils java_import java.security.cert.X509Certificate class Puppet::Server::Certificate < Puppet::SSL::Certificate def initialize(java_cert) unless java_cert.is_a? Java::JavaSecurityCert::X509Certificate raise(ArgumentError, "java_cert must be a Java X509Certificate.") end @java_cert = java_cert end def to_s @java_cert.to_s end def subject_alt_names alt_names_list = @java_cert.getSubjectAlternativeNames if alt_names_list alt_names_list.map { |name_arr| name_arr[1] } end end def expiration Time.at(@java_cert.getNotAfter.getTime / 1000).utc end def unmunged_name SSLUtils.get_cn_from_x500_principal(@java_cert.getSubjectX500Principal) end def custom_extensions exts = ExtensionsUtils.get_extension_list(@java_cert) if exts.nil? [] else valid_oids = exts.select do |ext| subtree_of?(get_name_from_oid('ppRegCertExt'), ext['oid']) or subtree_of?(get_name_from_oid('ppPrivCertExt'), ext['oid']) or subtree_of?(get_name_from_oid('ppAuthCertExt'), ext['oid']) end valid_oids.collect do |ext| {'oid' => get_oid_name(ext['oid']), 'value' => ext['value']} end end end private def get_oid_name(oid) found_oid_desc = Puppet::Server::PuppetConfig.oid_defns.select { |oid_desc| oid_desc[0] == oid }[0] if found_oid_desc.nil? oid else found_oid_desc[1] end end def get_name_from_oid(short_name) found_oid_desc = Puppet::Server::PuppetConfig.oid_defns.select { |oid_desc| oid_desc[1] == short_name }[0] unless found_oid_desc.nil? found_oid_desc[0] end end def subtree_of?(first, second) if first == second false else second.start_with? first end end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/compiler.rb000066400000000000000000000243411470345337400311340ustar00rootroot00000000000000require 'puppet/server' require 'puppet/server/logging' require 'puppet/util/profiler' module Puppet module Server class Compiler def initialize set_server_facts end # Compiles a catalog according to the spec provided from the # request. # @param [Hash] request_data details about the catalog to be compiled # @return [Hash] containing either just the catalog or catalog and logs, # if capturing logs was enabled def compile(request_data) options = request_data['options'] || {} if options['capture_logs'] catalog, logs = Logging.capture_logs(options['log_level']) do compile_catalog(request_data) end { catalog: catalog, logs: logs } else catalog = compile_catalog(request_data) { catalog: catalog } end end # Make the node object to be used in compilation. This requests it from # the node indirection and merges local facts and other data. # @api private def create_node(request_data) facts, trusted_facts = process_facts(request_data) certname = request_data['certname'] requested_environment = request_data['environment'] transaction_uuid = request_data['transaction_uuid'] prefer_requested_environment = request_data.dig('options', 'prefer_requested_environment') node = Puppet.override(trusted_information: trusted_facts) do Puppet::Node.indirection.find(certname, environment: requested_environment, facts: facts, transaction_uuid: transaction_uuid) end if request_data['facts'].nil? && !prefer_requested_environment tries = 0 environment = requested_environment while node.environment != environment if tries > 3 raise Puppet::Error, _("Node environment didn't stabilize after %{tries} fetches, aborting run") % { tries: tries } end environment = node.environment facts = get_facts_from_terminus(certname, environment.to_s) node = Puppet.override(trusted_information: trusted_facts) do Puppet::Node.indirection.find(certname, environment: environment, configured_environment: requested_environment, facts: facts, transaction_uuid: transaction_uuid) end tries += 1 end end if prefer_requested_environment node.environment = requested_environment end node.trusted_data = trusted_facts node.add_server_facts(@server_facts) node end private def compile_catalog(request_data) persist = request_data['persistence'] save_options = request_data.slice('environment', 'transaction_id', 'certname', 'job_id') node = nil Puppet::Util::Profiler.profile(_("Found node information using the v4 catalog endpoint"), [:compiler, :v4, :find_node]) do node = create_node(request_data) end if persist['facts'] save_facts(node.facts, node.trusted_data, save_options) end # Note: if we change this to use the indirection we may no longer # need to call `save_catalog` below. See its documentation for # further info. catalog = nil info_string = _("Compiled catalog for %{node} in environment %{environment} using the v4 catalog endpoint") % { node: node.name, environment: node.environment } Puppet::Util::Profiler.profile(info_string, [:compiler, :v4, :compile, node.environment, node.name]) do catalog = Puppet::Parser::Compiler.compile(node, request_data['code_id']) Puppet.info(info_string) end if persist['catalog'] save_catalog(catalog, save_options) end catalog.to_data_hash end # Typically in our use case (~early 2019, with PuppetDB configured as # the primary terminus and yaml as the cache) Indirection.save will # save to both the primary terminus and cache. # # @param [Puppet::Node::Facts] facts # @param [Hash] trusted_facts # @param [Hash] options # @option options [String] environment Required # @option options [String] certname Required def save_facts(facts, trusted_facts, options) # trusted_facts are pulled from the context in at least the PDB terminus. Puppet.override({trusted_information: trusted_facts}) do Puppet::Node::Facts.indirection.save(facts, options.delete('certname'), options) end end # The current Compiler terminus (which is the primary terminus for the # Catalog indirection) does not implement save and so we # cannot call Indirection#save directly. Typically, the catalog is # "saved" to PDB because PDB becomes the cache terminus and # Indirection#find will attempt to cache on successful lookup. # # Should we begin retrieving the catalog via Indirection#find this # method may become unnecessary # # @param [Puppet::Resource::Catalog] catalog # @param [Hash] options # @option options [String] environment Required # @option options [String] certname Required # @option options [String] transaction_id Optional # @option options [String] job_id Optional def save_catalog(catalog, options) if Puppet::Resource::Catalog.indirection.cache? terminus = Puppet::Resource::Catalog.indirection.cache request = Puppet::Indirector::Request.new(terminus.class.name, :save, options.delete('certname'), catalog, options) terminus.save(request) end end # @return Puppet::Node::Facts facts, Hash trusted_facts def process_facts(request_data) facts = nil trusted_facts = nil Puppet::Util::Profiler.profile(_("Found facts using the v4 catalog endpoint"), [:compiler, :v4, :find_facts]) do facts = extract_facts(request_data) trusted_facts = extract_trusted_facts(request_data, facts) end return facts, trusted_facts end def extract_facts(request_data) if request_data['facts'].nil? Puppet.debug _("No facts submitted with request, retrieving from %{terminus_name}.") % { terminus_name: Puppet::Node::Facts.indirection.terminus.name.to_s } facts = get_facts_from_terminus(request_data['certname'], request_data['environment']) else facts_from_request = request_data['facts'] # Ensure request data has the proper keys, mirroring the structure # of Facts#to_data_hash facts_from_request['values'] ||= {} facts_from_request['name'] ||= request_data['certname'] facts = Puppet::Node::Facts.from_data_hash(facts_from_request) end facts.sanitize facts end def extract_trusted_facts(request_data, facts) # Pull the trusted facts from the request, or attempt to extract them from # the facts hash trusted_facts = if request_data['trusted_facts'] request_data['trusted_facts']['values'] else fact_values = facts.to_data_hash['values'] fact_values['trusted'] end # If no trusted facts could be found, ensure a hash is returned trusted_facts ||= {} end def get_facts_from_terminus(nodename, environment) # Ignore the cache terminus, which is not guaranteed to store trusted facts facts = Puppet::Node::Facts.indirection.find(nodename, {environment: environment, ignore_cache: true}) # If no facts have been stored for the node, the terminus will return nil if facts.nil? # Create an empty facts object facts = Puppet::Node::Facts.new(nodename) end facts end # Initialize our server fact hash; we add these to each catalog, and they # won't change while we're running, so it's safe to cache the values. # # See also set_server_facts in Puppet::Indirector::Catalog::Compiler in puppet. def set_server_facts @server_facts = {} # Add our server Puppet Enterprise version, if available. pe_version_file = '/opt/puppetlabs/server/pe_version' if File.readable?(pe_version_file) and !File.zero?(pe_version_file) @server_facts['pe_serverversion'] = File.read(pe_version_file).chomp end # Add our server version to the fact list @server_facts['serverversion'] = Puppet.version.to_s # And then add the server name and IP { 'servername' => 'networking.fqdn', 'serverip' => 'networking.ip', 'serverip6' => 'networking.ip6' }.each do |var, fact| value = Facter.value(fact) if value @server_facts[var] = value end end if @server_facts['servername'].nil? host = Facter.value('networking.hostname') if host.nil? Puppet.warning _("Could not retrieve fact servername") elsif domain = Facter.value('networking.domain') @server_facts['servername'] = [host, domain].join('.') else @server_facts['servername'] = host end end if @server_facts['serverip'].nil? && @server_facts['serverip6'].nil? Puppet.warning _("Could not retrieve either serverip or serverip6 fact") end end end end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/config.rb000066400000000000000000000112621470345337400305650ustar00rootroot00000000000000require 'puppet/server' require 'puppet/network/http_pool' require 'puppet/environments' require 'puppet/server/logger' require 'puppet/server/jvm_profiler' require 'puppet/server/http_client' require 'puppet/server/auth_config_loader' require 'puppet/server/auth_provider' require 'puppet/server/execution' require 'puppet/server/environments/cached' require 'java' java_import com.puppetlabs.ssl_utils.SSLUtils java_import java.io.FileReader java_import java.io.FileInputStream java_import java.security.KeyStore class Puppet::Server::Config PUPPET_KEYSTORE_LOCATION = '/opt/puppetlabs/puppet/ssl/puppet-cacerts' CERT_REGEX = /.*-----BEGIN CERTIFICATE-----.*/ def self.initialize_puppet_server(puppet_server_config) Puppet::Server::Logger.init_logging if puppet_server_config["profiler"] @profiler = Puppet::Server::JvmProfiler.new(puppet_server_config["profiler"]) Puppet::Util::Profiler.add_profiler(@profiler) end Puppet::Server::HttpClient.initialize_settings(puppet_server_config) if !puppet_server_config["use_legacy_auth_conf"] Puppet::Network::Authorization.authconfigloader_class = Puppet::Server::AuthConfigLoader Puppet::Network::AuthConfig.authprovider_class = Puppet::Server::AuthProvider end Puppet::Server::Execution.initialize_execution_stub if puppet_server_config["environment_registry"] Puppet::Environments::Cached.cache_expiration_service = Puppet::Server::Environments::Cached::CacheExpirationService.new(puppet_server_config["environment_registry"]) end end def self.puppet_only_ssl_context # Initialize an SSLContext for use during HTTPS client requests. # Do this lazily due to startup-ordering issues - to give the CA # service time to create these files before they are referenced here. unless @puppet_only_ssl_context @puppet_only_ssl_context = SSLUtils.pems_to_ssl_context( FileReader.new(Puppet[:hostcert]), FileReader.new(Puppet[:hostprivkey]), FileReader.new(Puppet[:localcacert])) end @puppet_only_ssl_context end def self.ssl_context self.puppet_only_ssl_context end # The logging when loading these stores strives to match the equivalent # agent logging in 'puppet/ssl/ssl_provider' def self.puppet_and_system_ssl_context unless @puppet_and_system_ssl_context @puppet_and_system_ssl_context = load_puppet_and_system_ssl_context end @puppet_and_system_ssl_context end def self.load_puppet_and_system_ssl_context stores = SSLUtils.pemsToKeyAndTrustStores( FileReader.new(Puppet[:hostcert]), FileReader.new(Puppet[:hostprivkey]), FileReader.new(Puppet[:localcacert])) truststore = stores['truststore'] if File.exist?(PUPPET_KEYSTORE_LOCATION) associate_entries(truststore, PUPPET_KEYSTORE_LOCATION) else Puppet.warning("Could not find Puppet-vendored keystore at '#{PUPPET_KEYSTORE_LOCATION}'") end if additional_store_location = Puppet[:ssl_trust_store] if File.exist?(additional_store_location) load_additional_store(truststore, additional_store_location) else Puppet.warning("The 'ssl_trust_store' setting does not refer to a file and will be ignored: '#{additional_store_location}'") end end SSLUtils.managerFactoriesToSSLContext( SSLUtils.getKeyManagerFactory(stores['keystore'], stores['keystore-pw']), SSLUtils.getTrustManagerFactory(stores['truststore'])) end def self.load_additional_store(truststore, location) begin if File.read(location) =~ CERT_REGEX # The truststore looks like a cert chain the agent reads # Attempt to load it as SSLUtils would our own CA chain SSLUtils.associateCertsFromReader( truststore, 'puppet_setting_ssl_trust_store', FileReader.new(location)) else # Attempt to treat the file as a java keystore associate_entries(truststore, location) end rescue => detail Puppet.err("Failed to add '#{location}' as a trusted CA file: #{detail}") end end # to_store should be an already initialized Java KeyStore to act as a TrustStore # from_file should be a string path to a file that contains Java KeyStore formatted certs. def self.associate_entries(to_store, from_file) # We defer the creation of KeyStores to SSLUtils because it is FIPS specific. temp_truststore = SSLUtils.createKeyStore temp_truststore.load(FileInputStream.new(from_file), nil) temp_truststore.aliases.each do |a| to_store.setEntry(a, temp_truststore.getEntry(a, nil), nil) end end def self.terminate_puppet_server Puppet::Server::HttpClient.terminate end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/environments.rb000066400000000000000000000001001470345337400320340ustar00rootroot00000000000000require 'puppet/server' module Puppet::Server::Environments endpuppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/environments/000077500000000000000000000000001470345337400315205ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/environments/cached.rb000066400000000000000000000012131470345337400332510ustar00rootroot00000000000000require 'puppet/server/environments' require 'puppet/environments' module Puppet::Server::Environments::Cached class CacheExpirationService def initialize(environment_registry) @environment_registry = environment_registry end def created(env) # `env` should be of type Puppet::Node::Environment, so we # can access properties like `modulepath` if we ever need to @environment_registry.register_environment(env.name) end def expired?(env_name) @environment_registry.is_expired?(env_name) end def evicted(env_name) @environment_registry.remove_environment(env_name) end end endpuppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/execution.rb000066400000000000000000000034501470345337400313230ustar00rootroot00000000000000require 'puppet/server' require 'java' java_import com.puppetlabs.puppetserver.ShellUtils class Puppet::Server::Execution def self.initialize_execution_stub Puppet::Util::ExecutionStub.set do |command, options, stdin, stdout, stderr| # We're going to handle STDIN/STDOUT/STDERR in java, so we don't need # them here. However, Puppet::Util::Execution.execute doesn't close them # for us, so we have to do that now. [stdin, stdout, stderr].each { |io| io.close rescue nil } execute(command, options) end end private SHELL_CHARACTERS = "*?{}[]<>()~&|\\$;'`\"\n#=".chars def self.execute(command, options) if command.is_a?(Array) orig_command_str = command.join(" ") binary = command.first args = command[1..-1] else orig_command_str = command binary = command args = nil end exe_options = ShellUtils::ExecutionOptions.new if options[:combine] exe_options.combine_stdout_stderr = true end if options[:cwd] exe_options.working_directory = options[:cwd] end if args && !args.empty? result = ShellUtils.executeCommand(binary, args.to_java(:string), exe_options) else if binary.index(Regexp.union(SHELL_CHARACTERS)) result = ShellUtils.executeCommand("/bin/sh", ["-c", binary].to_java(:string), exe_options) else result = ShellUtils.executeCommand(binary, exe_options) end end # TODO - not all options from Puppet::Util::Execution are supported yet, see SERVER-74 if options[:failonfail] and result.exit_code != 0 raise Puppet::ExecutionFailure, "Execution of '#{orig_command_str}' returned #{result.exit_code}: #{result.output.strip}" end Puppet::Util::Execution::ProcessOutput.new(result.output, result.exit_code) end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/http_client.rb000066400000000000000000000170721470345337400316420ustar00rootroot00000000000000require 'puppet' require 'puppet/server' require 'puppet/server/config' require 'puppet/server/http_response' require 'puppet/http/client' require 'puppet/http/errors' require 'base64' require 'java' java_import com.puppetlabs.http.client.RequestOptions java_import com.puppetlabs.http.client.ClientOptions java_import com.puppetlabs.http.client.CompressType java_import com.puppetlabs.http.client.ResponseBodyType SyncHttpClient = com.puppetlabs.http.client.Sync class Puppet::Server::HttpClientError < Puppet::HTTP::HTTPError attr_reader :cause def initialize(message, cause = nil) super(message) @cause = cause end end class Puppet::Server::HttpClient < Puppet::HTTP::Client # Store a java HashMap of settings related to the http client def self.initialize_settings(settings) @settings = settings.select { |k,v| ["server_id", "metric_registry", "ssl_protocols", "cipher_suites", "http_connect_timeout_milliseconds", "http_idle_timeout_milliseconds"].include? k } end def self.settings @settings ||= {} end def initialize(options = {}) # NOTE: Unlike Puppet's HTTP client implementation, the Java HttpAsyncClient # does not support retries in the version we are using, so the `retry_limit` # option will be ignored if passed. # # Similarly, `redirect_limit` is not easily configurable, so we just use the default # of 100. The param will be ignored if passed. end def get(url, headers: {}, params: {}, options: {}, &block) include_system_store = options.delete(:include_system_store) request_options = create_common_request_options(url, headers, params, options) java_response = self.class.client_get(request_options, include_system_store: include_system_store) ruby_response = Puppet::Server::HttpResponse.new(java_response, URI(request_options.uri.to_s)) if block_given? yield ruby_response end ruby_response end def post(url, body, headers: {}, params: {}, options: {}, &block) include_system_store = options.delete(:include_system_store) request_options = create_common_request_options(url, headers, params, options) request_options.set_body(body) compress = options[:compress] if compress compress_as_sym = compress.to_sym if compress_as_sym == :gzip request_options.set_compress_request_body(CompressType::GZIP) else raise ArgumentError, "Unsupported compression specified for request: #{compress}" end end java_response = self.class.client_post(request_options, include_system_store: include_system_store) ruby_response = Puppet::Server::HttpResponse.new(java_response, URI(request_options.uri.to_s)) if block_given? yield ruby_response end ruby_response end def create_common_request_options(url, headers, params, options) if !url.is_a?(URI) raise ArgumentError, "URL must be provided as a URI object." end # If credentials were supplied for HTTP basic auth, add them into the headers. # This is based on the code in lib/puppet/reports/http.rb. credentials = options[:basic_auth] if credentials # http://en.wikipedia.org/wiki/Basic_access_authentication#Client_side encoded = Base64.strict_encode64("#{credentials[:user]}:#{credentials[:password]}") authorization = "Basic #{encoded}" if headers["Authorization"] && headers["Authorization"] != authorization raise "Existing 'Authorization' header conflicts with supplied HTTP basic auth credentials." end headers["Authorization"] = authorization end # Ensure multiple requests are not made on the same connection headers["Connection"] = "close" # TODO: this is using the same value as the agent would use. # It would be better to have it include puppetserver's version # instead of the puppet version, and include that we're running # in JRuby more explicitly. # TODO: Add a X-Puppetserver-Version header to match the one # the agent sends, but with our version instead. headers["User-Agent"] ||= Puppet[:http_user_agent] url = encode_query(url, params) # Java will reparse the string into its own URI object request_options = RequestOptions.new(url.to_s) if options[:metric_id] request_options.set_metric_id(options[:metric_id]) end request_options.set_headers(headers) request_options.set_as(ResponseBodyType::TEXT) end def self.terminate unless @client.nil? @client.close @client = nil end end private def self.configure_timeouts(client_options) settings = self.settings if settings.has_key?("http_connect_timeout_milliseconds") client_options.set_connect_timeout_milliseconds(settings["http_connect_timeout_milliseconds"]) end if settings.has_key?("http_idle_timeout_milliseconds") client_options.set_socket_timeout_milliseconds(settings["http_idle_timeout_milliseconds"]) end end def self.configure_ssl(client_options, include_system_store:) if include_system_store client_options.set_ssl_context(Puppet::Server::Config.puppet_and_system_ssl_context) else client_options.set_ssl_context(Puppet::Server::Config.puppet_only_ssl_context) end settings = self.settings if settings.has_key?("ssl_protocols") client_options.set_ssl_protocols(settings["ssl_protocols"]) end if settings.has_key?("cipher_suites") client_options.set_ssl_cipher_suites(settings["cipher_suites"]) end end def self.configure_metrics(client_options) settings = self.settings if settings.has_key?("metric_registry") client_options.set_metric_registry(settings["metric_registry"]) end if settings.has_key?("server_id") client_options.set_server_id(settings["server_id"]) end end def self.create_client_options(include_system_store:) client_options = ClientOptions.new self.configure_timeouts(client_options) self.configure_ssl(client_options, include_system_store: include_system_store) self.configure_metrics(client_options) client_options.set_enable_url_metrics(false) client_options end def self.create_client(include_system_store:) client_options = create_client_options(include_system_store: include_system_store) SyncHttpClient.createClient(client_options) end def self.client @client ||= create_client(include_system_store: false) end def self.client_with_system_certs @client_with_system_certs ||= create_client(include_system_store: true) end def self.choose_client(include_system_store:) include_system_store ? self.client_with_system_certs : self.client end def self.client_post(request_options, include_system_store: false) self.choose_client(include_system_store: include_system_store).post(request_options) rescue Java::ComPuppetlabsHttpClient::HttpClientException => e raise Puppet::Server::HttpClientError.new(e.message, e) end def self.client_get(request_options, include_system_store: false) self.choose_client(include_system_store: include_system_store).get(request_options) rescue Java::ComPuppetlabsHttpClient::HttpClientException => e raise Puppet::Server::HttpClientError.new(e.message, e) end def create_session raise NotImplementedError end def connect(uri, options: {}, &block) raise NotImplementedError end def head(url, headers: {}, params: {}, options: {}) raise NotImplementedError end def put(url, headers: {}, params: {}, options: {}) raise NotImplementedError end def delete(url, headers: {}, params: {}, options: {}) raise NotImplementedError end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/http_response.rb000066400000000000000000000020201470345337400322050ustar00rootroot00000000000000require 'puppet/http/response' class Puppet::Server::HttpResponse < Puppet::HTTP::Response attr_reader :url # @param [com.puppetlabs.http.client.Response] java_response the response # object from the Clojure HTTP client # @param [URI] url the URL requested for this response def initialize(java_response, url) @java_response = java_response @url = url end def code @java_response.get_status end def reason @java_response.get_reason_phrase end def body @java_response.get_body end def read_body raise ArgumentError, "A block is required" unless block_given? yield body end # The HTTP standard counts all codes 200-299 as successes def success? code > 199 && code < 300 end def [](name) @java_response.get_headers[name] end # Yield each header name and value. Returns an enumerator if no block is given. def each_header(&block) @java_response.get_headers.each(&block) end # Drain the response body def drain body true end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/jvm_profiler.rb000066400000000000000000000013501470345337400320130ustar00rootroot00000000000000require 'java' # A wrapper class that implements Puppet's profiler API by passing calls # through to a Java/JVM-based implementation. module Puppet module Server class JvmProfiler def initialize(profiler) @profiler = profiler end def start(description, metric_id) @profiler.start(description.to_java, javify_metric_id(metric_id)) end def finish(context, description, metric_id) @profiler.finish(context, description.to_java, javify_metric_id(metric_id)) end def shutdown() @profiler.shutdown() end def javify_metric_id(metric_id) if metric_id metric_id.map { |s| s.to_s }.to_java(:string) end end end end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/key_recorder.rb000066400000000000000000000012461470345337400317760ustar00rootroot00000000000000require 'puppet/server' # Puppet::Pops::Lookup::KeyRecorder was added in Puppet 6.8 with # this "null" behavior. If running with agent code < 6.8 define our # own null recorder. begin require 'puppet/pops/lookup/key_recorder' rescue LoadError module Puppet module Pops module Lookup class KeyRecorder def self.singleton @recorder ||= new end def record(key) end end end end end end class Puppet::Server::KeyRecorder < Puppet::Pops::Lookup::KeyRecorder attr_accessor :lookups def initialize @lookups = Hash.new(0) end def record(key) @lookups[key] += 1 end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/log_collector.rb000066400000000000000000000007551470345337400321540ustar00rootroot00000000000000require 'puppet/util/log' module Puppet module Server # Log to an array, just for testing. class LogCollector def initialize(logs) @logs = logs end def <<(value) @logs << value.to_data_hash end end Puppet::Util::Log.newdesttype :collector do match "Puppet::Server::LogCollector" def initialize(messages) @messages = messages end def handle(msg) @messages << msg end end end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/logger.rb000066400000000000000000000023711470345337400306000ustar00rootroot00000000000000require 'puppet' require 'puppet/util' require 'puppet/server' require 'java' java_import org.slf4j.LoggerFactory Puppet::Util::Log.newdesttype :logback do def handle(msg) output = msg.to_s if msg.source.size > 0 output = "#{msg.source} #{output}" end logger = LoggerFactory.getLogger("puppetserver") case msg.level when :debug logger.debug(output) when :info, :notice logger.info(output) when :warning logger.warn(output) when :err, :alert, :emerg, :crit logger.error(output) end end end class Puppet::Server::Logger def self.init_logging Puppet::Util::Log.newdestination(:logback) end # @note This must be called after Puppet settings are configured; otherwise # the default log level will overwrite this setting. def self.set_log_level_from_logback Puppet[:log_level] = level_from_logback(get_logger) end def self.level_from_logback(logger) case when logger.isDebugEnabled() 'debug' when logger.isInfoEnabled() 'info' when logger.isWarnEnabled() 'warning' when logger.isErrorEnabled() 'err' else 'notice' end end def self.get_logger LoggerFactory.getLogger("puppetserver") end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/logging.rb000066400000000000000000000017301470345337400307450ustar00rootroot00000000000000require 'puppet' require 'puppet/util/log' require 'puppet/server/log_collector' module Puppet module Server module Logging # @param level [String] one of "err", "warning", "info", or "debug", # overriding the log level of the underlying # server process. If nil, the process's log level # will be used. # @return the result of the block, along with the list of log entries # that occurred while processing the block def self.capture_logs(level, &block) old_log_level = Puppet.settings[:log_level] Puppet.settings[:log_level] = level if level logs = [] result = nil log_dest = Puppet::Server::LogCollector.new(logs) Puppet::Util::Log.with_destination(log_dest) do result = yield end Puppet.settings[:log_level] = old_log_level return result, logs end end end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/master.rb000066400000000000000000000253511470345337400306170ustar00rootroot00000000000000require 'puppet/server' require 'puppet/info_service' require 'puppet/network/http' # TODO: In Puppet 8, require the "server" vesion of this path require 'puppet/network/http/api/master/v3' require 'puppet/node/facts' require 'puppet/server/config' require 'puppet/server/puppet_config' require 'puppet/server/network/http/handler' require 'puppet/server/compiler' require 'puppet/server/ast_compiler' require 'puppet/server/key_recorder' require 'puppet/server/settings' require 'java' require 'timeout' ## ## This class is a bridge between the puppet ruby code and the java interface ## `com.puppetlabs.puppetserver.JRubyPuppet`. The first `include` line in the class ## is some JRuby magic that causes this class to "implement" the Java interface. ## So, in this class we can make calls into the puppet ruby code, but from ## outside (in the clojure/Java code), we can interact with an instance of this ## class simply as if it were an instance of the Java interface; thus, consuming ## code need not be aware of any of the JRuby implementation details. ## class Puppet::Server::Master include Java::com.puppetlabs.puppetserver.JRubyPuppet include Puppet::Server::Network::HTTP::Handler def initialize(puppet_config, puppet_server_config) # There is a setting that is routed from the puppetserver.conf to # configure whether or not to track hiera lookups. @track_lookups = puppet_server_config.delete('track_lookups') multithreaded = puppet_server_config.delete('multithreaded') Puppet::Server::Config.initialize_puppet_server(puppet_server_config) Puppet::Server::PuppetConfig.initialize_puppet(puppet_config: puppet_config) # Tell Puppet's network layer which routes we are willing to handle - which is # the server routes, not the CA routes. # There are SERVER variants of this constant in Puppet > 7.4, but we should # continue to use this one until Puppet 8 for backwards compatibility. server_prefix = Regexp.new("^#{Puppet::Network::HTTP::MASTER_URL_PREFIX}/") server_routes = Puppet::Network::HTTP::Route.path(server_prefix). any. chain(Puppet::Network::HTTP::API::Master::V3.routes) register([server_routes]) @env_loader = Puppet.lookup(:environments) @transports_loader = Puppet::Util::Autoload.new(self, "puppet/transport/schema") @catalog_compiler = Puppet::Server::Compiler.new if multithreaded if Puppet.respond_to?(:replace_settings_object) Puppet.replace_settings_object(Puppet::Server::Settings.new(global_settings: Puppet.settings, puppet_config: puppet_config)) else Puppet.warning( "Attempting to run in multithreaded mode without a version of Puppet that " + "supports threadsafe settings. Please upgrade to Puppet 6.13.0 or greater.") end end check_cadir_for_deprecation_warning end def handleRequest(request) response = {} Puppet.override(lookup_key_recorder: create_recorder) do process(request, response) # 'process' returns only the status - # `response` now contains all of the response data end body = response[:body] body_to_return = if body.is_a? String if body.encoding == Encoding::ASCII_8BIT body.to_java_bytes else body end elsif body.is_a? IO body.to_inputstream elsif body.nil? body else raise "Don't know how to handle response body from puppet, which is a #{body.class}" end com.puppetlabs.puppetserver.JRubyPuppetResponse.new( response[:status], body_to_return, response[:content_type], response["X-Puppet-Version"]) ensure Puppet.settings.clear_local_settings if Puppet.settings.is_a?(Puppet::Server::Settings) end def compileCatalog(request_data) Puppet.override( lookup_key_recorder: create_recorder, # rich_data was moved to the context because determining if it should be true, in # some code paths, needs to inspect the global settings, per-environment settings, # and the request's content-type. For the `handleRequest` endpoint this logic is # handled by the indirector. We need to provide some value, as the default in # Puppet's context is, as of Puppet 8.9.0, hardcoded to be false, which will cause # any rich_data in a catalog to fail via this endpoint (but likely not via the # indirected endpoint). So here we set it to the global setting value, as the # per-environment settings logic is fairly complicated to implement and have never # gotten user facing documentation anyways. rich_data: Puppet[:rich_data] ) do @catalog_compiler.compile(convert_java_args_to_ruby(request_data)) end end def compileAST(compile_options, boltlib_path) ruby_compile_options = convert_java_args_to_ruby(compile_options) ruby_boltlib_path = boltlib_path.kind_of?(Java::JavaUtil::List) ? boltlib_path.to_a : nil Puppet::Server::ASTCompiler.compile(ruby_compile_options, ruby_boltlib_path) end def create_recorder @track_lookups ? Puppet::Server::KeyRecorder.new : Puppet::Pops::Lookup::KeyRecorder.singleton end def getClassInfoForEnvironment(env) environment = @env_loader.get(env) unless environment.nil? environments = Hash[env, self.class.getManifests(environment)] classes_per_env = Puppet::InfoService::ClassInformationService.new.classes_per_environment(environments) classes_per_env[env] end end def getTransportInfoForEnvironment(env) require 'puppet/resource_api/transport' Puppet::ResourceApi::Transport.list_all_transports(env).values.map do |transport| definition = transport.definition order_info = definition[:connection_info_order] definition[:connection_info_order] = order_info.map(&:to_s) definition end end def getModuleInfoForEnvironment(env) environment = @env_loader.get(env) unless environment.nil? self.class.getModules(environment) end end def getModuleInfoForAllEnvironments() all_envs = @env_loader.list all_mod_data = {} all_envs.each { |env| all_mod_data[env.name] = self.class.getModules(env) } all_mod_data end def getSetting(setting) Puppet[setting] end def puppetVersion() Puppet.version end def run_mode() Puppet.run_mode.name.to_s end def terminate Puppet::Server::Config.terminate_puppet_server end # @return [Array, nil] an array of hashes describing tasks def getTasks(env) environment = @env_loader.get(env) unless environment.nil? # Pass the original env string. environment.name is a symbol # while the environment cache is primarily used with strings. # Pass as a string to ensure we re-use a cached environment # if available. Puppet::InfoService.tasks_per_environment(env) end end def getTaskData(environment_name, module_name, task_name) # the 'init' task is special-cased to be just the name of the module, # otherwise we have to request 'module::taskname' qualified_task_name = task_name == 'init' ? module_name : "#{module_name}::#{task_name}" Puppet::InfoService.task_data(environment_name, module_name, qualified_task_name) end def getPlans(env) environment = @env_loader.get(env) unless environment.nil? # Pass the original env string. environment.name is a symbol # while the environment cache is primarily used with strings. # Pass as a string to ensure we re-use a cached environment # if available. Puppet::InfoService.plans_per_environment(env) end end def getPlanData(environment_name, module_name, plan_name) # the 'init' plan is special-cased to be just the name of the module, # otherwise we have to request 'module::planname' qualified_plan_name = plan_name == 'init' ? module_name : "#{module_name}::#{plan_name}" Puppet::InfoService.plan_data(environment_name, module_name, qualified_plan_name) end def log_ca_migration_warning urge_to_migrate = <<-UTM The cadir is currently configured to be inside the #{Puppet[:ssldir]} directory. This config setting and the directory location will not be used in a future version of puppet. Please run the puppetserver ca tool to migrate out from the puppet confdir to the /etc/puppetlabs/puppetserver/ca directory. Use `puppetserver ca migrate --help` for more info. UTM Puppet.warn_once('deprecations', 'CA migration message', urge_to_migrate, :default, :default) end def check_cadir_for_deprecation_warning old_ca_dir = "#{Puppet[:ssldir]}/ca" if File.exist?(old_ca_dir) if File.symlink?(old_ca_dir) target = File.readlink(old_ca_dir) if target.start_with?(Puppet[:ssldir]) log_ca_migration_warning end else log_ca_migration_warning end end end private # This helper is used to resolve all java objects in an array. # Each array element is examined, if it is expected to be a map # we call back to the convert_java_args_to_ruby method, if it # is expected to be an array, we recurse otherwise we do not modify # the value. def resolve_java_objects_from_list(list) list.map do |value| if value.kind_of?(Java::ClojureLang::IPersistentMap) convert_java_args_to_ruby(value) elsif value.kind_of?(Java::JavaUtil::List) resolve_java_objects_from_list(value) else value end end end def convert_java_args_to_ruby(hash) Hash[hash.collect do |key, value| # Stolen and heavily modified from params_to_ruby in handler.rb if value.kind_of?(Java::ClojureLang::IPersistentMap) [key, convert_java_args_to_ruby(value)] elsif value.kind_of?(Java::JavaUtil::List) [key, resolve_java_objects_from_list(value)] else [key, value] end end] end def self.getModules(env) env.modules.collect do |mod| # NOTE: If in the future we want to collect more # Module settings, this should be more programatic # rather than getting these settings one by one {:name => mod.forge_name ||= mod.name, :version => mod.version} end end def self.getManifests(env) manifests = case when env.manifest == Puppet::Node::Environment::NO_MANIFEST [] when File.directory?(env.manifest) Dir.glob(File.join(env.manifest, '**/*.pp')) when File.exist?(env.manifest) [env.manifest] else [] end module_manifests = env.modules.collect {|mod| mod.all_manifests} manifests.concat(module_manifests).flatten.uniq end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/network.rb000066400000000000000000000000731470345337400310070ustar00rootroot00000000000000require 'puppet/server' module Puppet::Server::Network endpuppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/network/000077500000000000000000000000001470345337400304625ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/network/http.rb000066400000000000000000000001111470345337400317570ustar00rootroot00000000000000require 'puppet/server/network' module Puppet::Server::Network::HTTP endpuppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/network/http/000077500000000000000000000000001470345337400314415ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/network/http/handler.rb000066400000000000000000000060641470345337400334110ustar00rootroot00000000000000require 'puppet/server/network/http' require 'puppet/network/http/handler' require 'puppet/server/certificate' java_import java.io.InputStream module Puppet::Server::Network::HTTP::Handler include Puppet::Network::HTTP::Handler # Set the response up, with the body and status. def set_response(response, body, status = 200) response[:body] = body response[:status] = status end # Set the specified format as the content type of the response. def set_content_type(response, format) response[:content_type] = format_to_mime(format) end # Retrieve all headers from the http request, as a hash with the header names # (lower-cased) as the keys def headers(request) request["headers"] end def http_method(request) request["request-method"] end def path(request) request["uri"] end def body(request) body = request["body"] if body.kind_of?(InputStream) io = body.to_io content_type = '' has_headers = request.key?('headers') if has_headers && request['headers'].key?('content-type') content_type = request['headers']['content-type'] end case content_type when nil, "", "application/octet-stream", "application/x-msgpack" io.binmode else encoding = 'UTF-8' if has_headers encoding = request['headers'].fetch('content-encoding', 'UTF-8') end io.set_encoding(encoding) end io.read else body end end def params(request) params = request["params"] || {} params = params_to_ruby(params) params = decode_params(params) params.merge(client_information(request)) end def client_cert(request) if request['client-cert'] Puppet::Server::Certificate.new(request['client-cert']) end end # Retrieve node/cert/ip information from the request object. def client_information(request) result = {} if ip = request["remote-addr"] result[:ip] = ip end # If a CN was provided then use that instead of IP info result[:authenticated] = false if cn = request["client-cert-cn"] result[:node] = cn result[:authenticated] = request["authenticated"] else result[:node] = resolve_node(result) end result end def params_to_ruby(params) Hash[params.collect do |key, value| # Values for query string and/or form parameters which are specified # with array-like syntax will be parsed by Ring into a Clojure # PersistentVector, which derives from a Java List. Need to # translate the Java List into a Ruby Array so that the request # handling logic in Ruby can make use of it. # For example, a query string of 'arr=one&arr=two" will be translated # at the Clojure Ring layer into an element with a key of "arr" and # value of '["one", "two"]' as a Clojure PersistentVector. This # PersistentVector needs to be converted into a Ruby Array before # proceeding with the request processing. [key, value.kind_of?(Java::JavaUtil::List) ? value.to_a : value] end] end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/puppet_config.rb000066400000000000000000000125611470345337400321650ustar00rootroot00000000000000require 'puppet/server' require 'puppet/server/logger' require 'puppet/server/http_client' require 'puppet/indirector/indirection' require 'puppet/file_serving/content' require 'puppet/file_serving/metadata' require 'puppet/file_bucket/file' require 'puppet/node' require 'puppet/application_support' require 'puppet/ssl/oids' class Puppet::Server::PuppetConfig # Configure the Puppet.settings object # @param puppet_config [Hash] Hash of puppet settings # @param require_config [Boolean] controls loading of Puppet configuration files # @param push_global_settings [Boolean] controls push to global context after settings object initialization # @return [void] def self.initialize_puppet_settings(puppet_config:, require_config:, push_settings_globally:) # It's critical that we initialize the run mode before allowing any of the # other settings to be loaded / accessed. Puppet.settings.preferred_run_mode = :server # Puppet.initialize_settings is the method that you call if you want to use # the puppet code as a library. (It is called implicitly by all of the puppet # cli tools.) Here we can basically pass through any settings that we wish # to modify/override in the same syntax as you would pass in cli args to # set them. # # `config` is a map whose keys are the names of the settings that we wish # to override, and whose values are the desired values for the settings. # Values that are not strings are omitted, allowing for keys in the # HashMap from puppetserver to have true values. cli_flags = puppet_config.reduce([]) do |acc, entry| acc << "--#{entry[0]}" acc << entry[1] if entry[1].kind_of?(String) acc end # We check parameter length because Method#arity returns -1 for varargs if Puppet.method(:initialize_settings).parameters.length >= 3 Puppet.initialize_settings(cli_flags, require_config, push_settings_globally, { :http => Puppet::Server::HttpClient.new }) else Puppet.initialize_settings(cli_flags) end Puppet[:trace] = true Puppet::Server::Logger.set_log_level_from_logback # (SERVER-410) Cache features in puppetserver for performance. Avoiding # the cache is intended for agents to reload features mid-catalog-run. # As of (PUP-5482) setting always_retry_plugins to false implies that # features will always be cached. if Puppet.settings.setting('always_retry_plugins') Puppet[:always_retry_plugins] = false end app_defaults = Puppet::Settings.app_defaults_for_run_mode(Puppet::Util::RunMode[:server]). merge({:name => "server", :facts_terminus => 'json'}) Puppet.settings.initialize_app_defaults(app_defaults) if push_settings_globally Puppet.info("Puppet settings initialized; run mode: #{Puppet.run_mode.name}") else Puppet.info("Puppet local settings initialized; run mode: #{Puppet.run_mode.name}") end end # This `initialize_puppet` method should only run during the initialization # of the Puppet::Server::Master class. Beyond the Puppet.settings configuration, # it configures additional state for Puppet to begin compilations. def self.initialize_puppet(puppet_config:) initialize_puppet_settings(puppet_config: puppet_config, require_config: true, push_settings_globally: true) Puppet::ApplicationSupport.push_application_context(Puppet::Util::RunMode[:server]) # Puppet's https machinery expects to find an object at # `Puppet.lookup(:ssl_context)` which it will then use as an input # to the Verifier, which is passed to the client. We ignore these # values when passed to our https client and manage our SSLContext # in a completely different way. # # See `Puppet::Network::HttpPool.connection` dummy_ssl_context = {ssl_context: :unused} if Puppet.respond_to?(:push_context_global) Puppet.push_context_global(dummy_ssl_context) else Puppet.push_context(dummy_ssl_context) end # We have now added support for setting "settings_catalog" to false in the puppet.conf. # We should default to not applying the settings catalog and remove this line in Puppet 9. Puppet.settings.use :main, :server, :ssl, :metrics if Puppet::Indirector::Indirection.method_defined?(:set_global_setting) Puppet::FileServing::Content.indirection.set_global_setting(:terminus_class, :file_server) Puppet::FileServing::Metadata.indirection.set_global_setting(:terminus_class, :file_server) Puppet::FileBucket::File.indirection.set_global_setting(:terminus_class, :file) Puppet::Node.indirection.set_global_setting(:cache_class, Puppet[:node_cache_terminus]) else Puppet::FileServing::Content.indirection.terminus_class = :file_server Puppet::FileServing::Metadata.indirection.terminus_class = :file_server Puppet::FileBucket::File.indirection.terminus_class = :file Puppet::Node.indirection.cache_class = Puppet[:node_cache_terminus] end Puppet::ApplicationSupport.configure_indirector_routes("server") oid_defns = Puppet::SSL::Oids.parse_custom_oid_file(Puppet[:trusted_oid_mapping_file]) if oid_defns @@oid_defns = Puppet::SSL::Oids::PUPPET_OIDS + oid_defns else @@oid_defns = Puppet::SSL::Oids::PUPPET_OIDS end end def self.oid_defns @@oid_defns end end puppetlabs-puppetserver-7e1a9a8/src/ruby/puppetserver-lib/puppet/server/settings.rb000066400000000000000000000031221470345337400311540ustar00rootroot00000000000000require 'puppet/server/puppet_config' class Puppet::Server::Settings # @param global_settings[Puppet::Settings] read-only puppet settings shared globally # @param puppet_config[Hash] the setting options to use for new thread-local settings def initialize(global_settings:, puppet_config:) @global_settings = global_settings @local_settings = Puppet::ThreadLocal.new @puppet_config = puppet_config end def method_missing(method, *args, &block) current_settings.send(method, *args, &block) end def clear_local_settings @local_settings.value = nil end # This method populates the local_settings value, so that any reading of # settings will read from @local_settings.value instead of the @global_settings. # This should never happen on the parent thread, but on threads spawned # from the parent during compilation. def generate_new_local_settings @local_settings.value = Puppet::Settings.new Puppet.initialize_default_settings!(@local_settings.value) Puppet::Server::PuppetConfig.initialize_puppet_settings(puppet_config: @puppet_config, require_config: true, push_settings_globally: false) end def local_settings? !@local_settings.value.nil? end def current_settings local_settings? ? @local_settings.value : @global_settings end def [](key) current_settings[key] end def []=(key, value) if !local_settings? generate_new_local_settings end @local_settings.value[key] = value end end puppetlabs-puppetserver-7e1a9a8/test/000077500000000000000000000000001470345337400200455ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/000077500000000000000000000000001470345337400223705ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/000077500000000000000000000000001470345337400245475ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/general_puppet/000077500000000000000000000000001470345337400275615ustar00rootroot00000000000000general_puppet_int_test.clj000066400000000000000000000407121470345337400351230ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/general_puppet(ns puppetlabs.general-puppet.general-puppet-int-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [me.raynes.fs :as fs] [puppetlabs.http.client.sync :as http-client] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.trapperkeeper.testutils.logging :as logging] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.common :as ps-common])) (def test-resources-dir (ks/absolute-path "./dev-resources/puppetlabs/general_puppet/general_puppet_int_test")) (def environment-dir (ks/absolute-path (str testutils/conf-dir "/environments/production"))) (defn script-path [script-name] (str test-resources-dir "/" script-name)) (def gem-path [(ks/absolute-path jruby-testutils/gem-path)]) (use-fixtures :once (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (use-fixtures :each #(logging/with-test-logging (%))) (def num-jrubies 1) (deftest ^:integration test-simple-external-command-execution (testing "puppet functions can call external commands successfully that are just one argument" ; The generate puppet function runs a fully qualified command with arguments. ; This function calls into Puppet::Util::Execution.execute(), which calls into ; our shell-utils code via Puppet::Util::ExecutionStub which we call in ; Puppet::Server::Execution. (testutils/write-site-pp-file (format "$a = generate('%s'); notify {$a:}" (script-path "echo_foo"))) (bootstrap/with-puppetserver-running app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path}} (testing "calling generate successfully executes shell command" (let [catalog (testutils/get-catalog)] (is (testutils/catalog-contains? catalog "Notify" "foo\n"))))))) (deftest ^:integration test-external-command-execution (testing "puppet functions can call external commands successfully" ; The generate puppet function runs a fully qualified command with arguments. ; This function calls into Puppet::Util::Execution.execute(), which calls into ; our shell-utils code via Puppet::Util::ExecutionStub which we call in ; Puppet::Server::Execution. (testutils/write-site-pp-file (format "$a = generate('%s', 'this command echoes a thing'); notify {$a:}" (script-path "echo"))) (bootstrap/with-puppetserver-running app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path}} (testing "calling generate successfully executes shell command" (let [catalog (testutils/get-catalog)] (is (testutils/catalog-contains? catalog "Notify" "this command echoes a thing\n"))))))) (deftest ^:integration test-complicated-external-command-execution (testing "puppet functions can call more complicated external commands successfully" ; The generate puppet function runs a fully qualified command with arguments. ; This function calls into Puppet::Util::Execution.execute(), which calls into ; our shell-utils code via Puppet::Util::ExecutionStub which we call in ; Puppet::Server::Execution. (testutils/write-site-pp-file (format "$a = generate('%s', '-c', \"echo foo\"); notify {$a: }" "/bin/sh")) (bootstrap/with-puppetserver-running app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path}} (testing "calling generate successfully executes shell command" (let [catalog (testutils/get-catalog)] (is (testutils/catalog-contains? catalog "Notify" "foo\n"))))))) (deftest ^:integration code-id-request-test-get-catalog (testing "when making catalog requests with get" (bootstrap/with-puppetserver-running app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path} :versioned-code {:code-id-command (script-path "echo") :code-content-command (script-path "echo")}} (testing "and environment is valid code id is injected" (let [catalog (testutils/get-catalog)] ;; As we have set code-id-command to echo, the code id will ;; be the result of running `echo $environment`, which will ;; be production here. (is (= "production" (get catalog "code_id"))))) (testing "and environment is invalid 400 is returned" (logging/with-test-logging (let [response (http-client/get "https://localhost:8140/puppet/v3/catalog/localhost?environment=production;cat" testutils/catalog-request-options)] (is (= 400 (:status response))) (is (= (ps-common/environment-validation-error-msg "production;cat") (:body response))))))))) (deftest ^:integration code-id-request-test-post-catalog (testing "when making catalog requests with post" (bootstrap/with-puppetserver-running app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path} :versioned-code {:code-id-command (script-path "echo") :code-content-command (script-path "echo")}} (testing "and environment is valid code id is injected" (let [catalog (testutils/post-catalog)] ;; As we have set code-id-command to echo, the code id will ;; be the result of running `echo $environment`, which will ;; be production here. (is (= "production" (get catalog "code_id"))))) (testing "and environment is invalid the request fails" (logging/with-test-logging (let [response (http-client/post "https://localhost:8140/puppet/v3/catalog/localhost" (assoc-in (assoc testutils/catalog-request-options :body "environment=production;cat") [:headers "Content-Type"] "application/x-www-form-urlencoded"))] (is (= 400 (:status response))) (is (= (ps-common/environment-validation-error-msg "production;cat") (:body response))))))))) (deftest ^:integration code-id-request-test-non-zero-exit (testing "catalog request fails if code-id-command returns a non-zero exit code" ; As we have set code-id-command to warn, the code id will ; be the result of running `warn_echo_and_error $environment`, which will ; exit non-zero and fail the catalog request. (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here, because the catalog request will never make it all the way through to the ruby layer due to the code-id-command failure in the Clojure layer." app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path} :versioned-code {:code-id-command (script-path "warn_echo_and_error") :code-content-command (script-path "echo")}} (logging/with-test-logging (let [catalog-response (http-client/get "https://localhost:8140/puppet/v3/catalog/localhost?environment=production" testutils/catalog-request-options)] (is (= 500 (:status catalog-response))) (is (re-find #"Non-zero exit code returned while running" (:body catalog-response))) (is (logged? #"Executed an external process which logged to STDERR: production" :warn))))))) (deftest ^:integration code-id-request-test-no-environment (testing "code id is not added and 400 is returned if environment is not included in request" (logging/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jrubies "Mocking is safe here because the Clojure code will raise an error about the missing environment information before the request makes it through to the Ruby layer." app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path} :versioned-code {:code-content-command (script-path "echo") :code-id-command (script-path "echo")}} (let [response (testutils/http-get "puppet/v3/catalog/localhost")] (is (= 400 (:status response))) (is (logged? #"Error 400 on SERVER"))))))) (deftest ^:integration static-file-content-endpoint-test (logging/with-test-logging (testing "the /static_file_content endpoint behaves as expected when :code-content-command is set" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because the static file content endpoint is implemented in Clojure." app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path} :versioned-code {:code-content-command (script-path "echo") :code-id-command (script-path "echo")}} (testing "the /static_file_content endpoint successfully streams file content" (let [response (testutils/get-static-file-content "modules/foo/files/bar.txt?code_id=foobar&environment=test")] (is (= 200 (:status response))) (is (= "application/octet-stream" (get-in response [:headers "content-type"]))) (is (= "test foobar modules/foo/files/bar.txt\n" (:body response))))) (testing "the /static_file_content endpoint successfully streams task content" (let [response (testutils/get-static-file-content "modules/foo/tasks/bar.txt?code_id=foobar&environment=test")] (is (= 200 (:status response))) (is (= "application/octet-stream" (get-in response [:headers "content-type"]))) (is (= "test foobar modules/foo/tasks/bar.txt\n" (:body response))))) (testing "the /static_file_content endpoint successfully streams lib content" (let [response (testutils/get-static-file-content "plugins/foo/lib/bar.txt?code_id=foobar&environment=test")] (is (= 200 (:status response))) (is (= "application/octet-stream" (get-in response [:headers "content-type"]))) (is (= "test foobar plugins/foo/lib/bar.txt\n" (:body response))))) (testing (str "the /static_file_content endpoint successfully streams file content " "from directories other than /modules") (let [response (testutils/get-static-file-content "site/foo/files/bar.txt?code_id=foobar&environment=test")] (is (= 200 (:status response))) (is (= "application/octet-stream" (get-in response [:headers "content-type"]))) (is (= "test foobar site/foo/files/bar.txt\n" (:body response)))) (let [response (testutils/get-static-file-content "dist/foo/files/bar.txt?code_id=foobar&environment=test")] (is (= 200 (:status response))) (is (= "test foobar dist/foo/files/bar.txt\n" (:body response))))) (testing "the /static_file_content endpoint validates environment" (doseq [[env-encoded env-decoded] [["hi%23cat" "hi#cat"] ["hi%20cat" "hi cat"] ["%20hicat" " hicat"] ["hi%3Bcat" "hi;cat"] ["hicat%20" "hicat "]]] (let [response (testutils/get-static-file-content (format "modules/foo/files/bar.txt?code_id=foobar&environment=%s" env-encoded))] (is (= 400 (:status response))) (is (= (ps-common/environment-validation-error-msg env-decoded) (:body response)))))) (testing "the /static_file_content endpoint validates code-id" (doseq [[code-id-encoded code-id-decoded] [["hi%23cat" "hi#cat"] ["hi%20cat" "hi cat"] ["%20hicat" " hicat"] ["hicat%20" "hicat "] ["hi%3B%2Fusr%2Fbin%2Fcat" "hi;/usr/bin/cat"]]] (let [response (testutils/get-static-file-content (format "modules/foo/files/bar.txt?code_id=%s&environment=test" code-id-encoded))] (is (= 400 (:status response))) (is (= (ps-common/code-id-validation-error-msg code-id-decoded) (:body response)))))) (let [error-message "Error: A /static_file_content request requires an environment, a code-id, and a file-path"] (testing "the /static_file_content endpoint returns an error if code_id is not provided" (let [response (testutils/get-static-file-content "modules/foo/files/bar.txt?environment=test")] (is (= 400 (:status response))) (is (= error-message (:body response))))) (testing "the /static_file_content endpoint returns an error if environment is not provided" (let [response (testutils/get-static-file-content "modules/foo/files/bar.txt?code_id=foobar")] (is (= 400 (:status response))) (is (= error-message (:body response))))) (testing "the /static_file_content endpoint returns an error if file-path is not provided" (let [response (testutils/get-static-file-content "?code_id=foobar&environment=test")] (is (= 400 (:status response))) (is (= error-message (:body response)))))) (testing "the /static_file_content endpoint returns an error (403) for invalid file-paths" (let [response (testutils/get-static-file-content (str "modules/foo/secretstuff/bar?" "environment=test&code_id=foobar"))] (is (= 403 (:status response))) (is (= (str "Request Denied: A /static_file_content request must be " "a file within the files, lib, scripts, or tasks directory of a module.") (:body response))))) (testing "the /static_file_content endpoint returns an error (400) for attempted traversals" (let [response (testutils/get-static-file-content "modules/foo/files/bar/../../../..?environment=test&code_id=foobar")] (is (= 400 (:status response))) (is (re-find #"Invalid relative path" (:body response))))) (testing "the /static_file_content decodes and rejects alternate encodings of .." (let [response (testutils/get-static-file-content "modules/foo/files/bar/%2E%2E/%2E%2E/%2E%2E/%2E%2E?environment=test&code_id=foobar")] (is (= 400 (:status response))) (is (re-find #"Invalid relative path" (:body response))))))))) (deftest ^:integration static-file-content-endpoint-test-no-code-content-command (logging/with-test-logging (testing "the /static_file_content endpoint errors if :code-content-command is not set" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because the static file content endpoint is implemented in Clojure." app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path} :versioned-code {}} (let [response (testutils/get-static-file-content "modules/foo/files/bar/?code_id=foobar&environment=test")] (is (= 500 (:status response))) (is (re-matches #".*Cannot retrieve code content because the \"versioned-code\.code-content-command\" setting is not present in configuration.*" (:body response)))))))) (deftest ^:integration test-config-version-execution (testing "config_version is executed correctly" (testutils/create-env-conf environment-dir (format "config_version = \"%s $environment\"" (script-path "echo"))) (bootstrap/with-puppetserver-running app {:jruby-puppet {:max-active-instances num-jrubies :gem-path gem-path}} (let [catalog (testutils/get-catalog)] (is (= "production" (get catalog "version"))))))) (deftest ^:integration custom-trusted-oid-mapping-test (testing "custom_trusted_oid_mapping works properly" (testutils/write-site-pp-file "notify { 'trusted_hash':\n\tmessage => \"${trusted['extensions']}\",\n}") (fs/delete-dir (fs/file testutils/conf-dir "ssl")) (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path}} (let [catalog (testutils/get-catalog)] (is (= "{pp_cli_auth => true, sf => Burning Finger, short => 22}" (get-in (first (filter #(= (get % "title") "trusted_hash") (get catalog "resources"))) ["parameters" "message"]))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/puppetserver/000077500000000000000000000000001470345337400273135ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/puppetserver/auth_conf_test.clj000066400000000000000000000341241470345337400330160ustar00rootroot00000000000000(ns puppetlabs.puppetserver.auth-conf-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [clojure.string :as str] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [puppetlabs.ssl-utils.simple :as ssl-simple] [puppetlabs.ssl-utils.core :as ssl-utils] [schema.test :as schema-test] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.puppetserver.testutils :as testutils :refer [http-get]] [me.raynes.fs :as fs] [ring.util.codec :as ring-codec] [cheshire.core :as cheshire]) (:import (java.io StringWriter))) (def test-resources-dir (ks/absolute-path "./dev-resources/puppetlabs/puppetserver/auth_conf_test")) (def gem-path [(ks/absolute-path jruby-testutils/gem-path)]) (defn script-path [script-name] (str test-resources-dir "/" script-name)) (use-fixtures :once schema-test/validate-schemas (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (deftest ^:integration request-with-ssl-cert-handled-via-tk-auth (testing "Request with SSL certificate via trapperkeeper-authorization handled" (logutils/with-test-logging (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path} :authorization {:version 1 :allow-header-cert-info false :rules [{:match-request {:path "^/puppet/v3/catalog/private$" :type "regex"} :allow ["private" "localhost"] :sort-order 1 :name "catalog unencoded"} {:match-request {:path "^/puppet/v3/node/private$" :type "regex"} :allow ["private" "localhost"] :sort-order 1 :name "node"} {:match-request {:path "^/puppet/v3/catalog/%65ncoded$" :type "regex"} :allow ["localhost"] :sort-order 1 :name "catalog encoded"}]}} (logutils/with-test-logging (testing "for puppet 4 routes without url encoding" (let [response (http-get "puppet/v3/node/public?environment=production")] (is (= 403 (:status response)) (ks/pprint-to-string response))) (let [response (http-get "puppet/v3/node/private?environment=production")] (is (= 200 (:status response)) (ks/pprint-to-string response))) (let [response (http-get "puppet/v3/catalog/public?environment=production")] (is (= 403 (:status response)) (ks/pprint-to-string response))) (let [response (http-get "puppet/v3/catalog/private?environment=production")] (is (= 200 (:status response)) (ks/pprint-to-string response)) (is (testutils/catalog-name-matches? (testutils/catalog-ring-response->catalog response) "private")))) (testing "for puppet 4 routes with url encoding" (let [response (http-get "puppet/v3/%63atalog/%65ncoded?environment=production")] ;; The web server should decode the above URI path component to ;; "puppet/v3/catalog/encoded". There is a rule allowing ;; "localhost" for "%65ncoded" but no rule allowing "localhost" ;; for "encoded", so this should request should fail with a ;; 403 (Forbidden) error. (is (= 403 (:status response)) (ks/pprint-to-string response))) (let [response (http-get "puppet/v3/%63atalog/%2565ncoded?environment=production")] ;; The web server should decode the above URI path component to ;; "puppet/v3/catalog/%65ncoded". There is a rule allowing ;; "localhost" for "%65ncoded", so this should request should ;; succeed. (is (= 200 (:status response)) (ks/pprint-to-string response)) ;; The catalog which is returned should have a name of "%65ncoded" ;; since this should be the name derived from the web server ;; request after a single percent-decode. (is (testutils/catalog-name-matches? (testutils/catalog-ring-response->catalog response) "%65ncoded"))) (let [response (http-get (str "puppet/v3/%63atalog/private/%2E%2E/secret?" "environment=production"))] ;; The web server should decode the above URI path component to ;; "puppet/v3/catalog/private/../secret". The relative ;; path, "/../", inside of the path component is forbidden and ;; so should cause the webserver to throw a 'Bad Request' error. (is (= 400 (:status response)) (ks/pprint-to-string response))))))))) (deftest ^:integration request-with-x-client-headers-handled-via-tk-auth (testing "Request with X-Client headers via trapperkeeper-authorization handled" (let [extension-value "UUUU-IIIII-DDD" cert (:cert (ssl-simple/gen-self-signed-cert "ssl-client" 1 {:keylength 512 :extensions [{:oid "1.3.6.1.4.1.34380.1.1.1" :critical false :value extension-value}]})) url-encoded-cert (let [cert-writer (StringWriter.) _ (ssl-utils/cert->pem! cert cert-writer)] (ring-codec/url-encode cert-writer)) http-get-no-ssl (fn [path] (http-client/get (str "http://localhost:8080/" path) {:headers {"Accept" "application/json" "X-Client-Cert" url-encoded-cert "X-Client-DN" "CN=private" "X-Client-Verify" "SUCCESS"} :as :text}))] (logutils/with-test-logging (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path} :authorization {:version 1 :allow-header-cert-info true :rules [{:match-request {:path "^/puppet/v3/catalog/private$" :type "regex"} :allow ["private" "localhost"] :sort-order 1 :name "catalog"}]} :webserver {:host "localhost" :port 8080}} (testing "as 403 for unauthorized user" (logutils/with-test-logging (let [response (http-get-no-ssl "puppet/v3/catalog/public?environment=production")] (is (= 403 (:status response)) (ks/pprint-to-string response))))) (testing "for certificate when provided" (let [environment-dir (fs/file jruby-testutils/code-dir "environments") manifest-dir (fs/file environment-dir "production" "manifests")] (try (fs/mkdirs manifest-dir) (spit (fs/file manifest-dir "site.pp") (str/join "\n" ["notify {'trusty_info':" " message => $trusted[extensions][pp_uuid]" "}\n"])) (let [response (http-get-no-ssl "puppet/v3/catalog/private?environment=production") expected-content-in-catalog (str "\"parameters\":{\"message\":\"" extension-value "\"}")] (is (= 200 (:status response)) (ks/pprint-to-string response)) (is (.contains (:body response) expected-content-in-catalog) (str "Did not find '" expected-content-in-catalog "' in full response body: " (:body response)))) (finally (fs/delete-dir environment-dir)))))))))) (deftest ^:integration custom-oids-passed-to-tk-auth (testing "puppet server successfully utilizes custom oid mappings and puppet short names for authorization" (logutils/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jruby-puppet-fn "JRuby mocking is safe here because these tests are strictly validating the Clojure tk-auth checks." app {:jruby-puppet {:gem-path gem-path} :authorization {:version 1 :allow-header-cert-info true :rules [{:match-request {:path "/" :type "path"} :allow {:extensions {:shiningfinger "Burning Finger"}} :deny {:extensions {:pp_uuid "not a uuid"}} :sort-order 1 :name "all endpoints"}]} :webserver {:host "localhost" :port 8080} :puppet {"csr_attributes" (str test-resources-dir "/csr_attributes.yaml") "trusted_oid_mapping_file" (str test-resources-dir "/custom_trusted_oid_mapping.yaml")}} (jruby-testutils/create-mock-jruby-puppet-fn-with-handle-response-params 200 "we've been tk-authorized!") (let [good-exts [{:oid "1.3.6.1.4.1.34380.1.1.1" :critical false :value "12345"} {:oid "1.3.6.1.4.1.34380.1.2.2" :critical false :value "Burning Finger"}] bad-exts [{:oid "1.3.6.1.4.1.34380.1.1.1" :critical false :value "not a uuid"} {:oid "1.3.6.1.4.1.34380.1.2.2" :critical false :value "Burning Finger"}] create-cert (fn [extensions] (:cert (ssl-simple/gen-self-signed-cert "ssl-client" 1 {:keylength 512 :extensions extensions}))) allowable-cert (create-cert good-exts) deniable-cert (create-cert bad-exts) url-encode-cert (fn [cert] (let [cert-writer (StringWriter.) _ (ssl-utils/cert->pem! cert cert-writer)] (ring-codec/url-encode cert-writer))) url-encoded-allowable-cert (url-encode-cert allowable-cert) url-encoded-deniable-cert (url-encode-cert deniable-cert) http-get-no-ssl (fn [path cert] (http-client/get (str "http://localhost:8080/" path) {:headers {"Accept" "application/json" "X-Client-Cert" cert "X-Client-DN" "CN=private" "X-Client-Verify" "SUCCESS"} :as :text}))] (testing "ca endpoints use oid shortnames" (let [path "puppet-ca/v1/certificate_status/localhost" cert-status-response (http-get-no-ssl path url-encoded-allowable-cert) cert-status-body (-> cert-status-response :body cheshire/parse-string)] (is (= 200 (:status cert-status-response))) ;; Assert that some of the content looks like it came from the ;; certificate_statuses endpoint (is (= "localhost" (get cert-status-body "name"))) (is (= "signed" (get cert-status-body "state"))) (is (= 403 (:status (http-get-no-ssl path url-encoded-deniable-cert)))))) (testing "master endpoints use oid shortnames" (let [path "puppet/v3/catalog/private?environment=production" catalog-response (http-get-no-ssl path url-encoded-allowable-cert)] (is (= 200 (:status catalog-response))) (is (= "we've been tk-authorized!" (:body catalog-response))) (is (= 403 (:status (http-get-no-ssl path url-encoded-deniable-cert)))))) (testing "puppet-admin endpoints support oid shortnames" (let [path "puppet-admin-api/v1/environment-cache?environment=production" http-delete (fn [cert] (http-client/delete (str "http://localhost:8080/" path) {:headers {"Accept" "application/json" "X-Client-Cert" cert "X-Client-DN" "CN=private" "X-Client-Verify" "SUCCESS"} :as :text}))] (is (= 204 (:status (http-delete url-encoded-allowable-cert)))) (is (= 403 (:status (http-delete url-encoded-deniable-cert))))))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/puppetserver/bootstrap_int_test.clj000066400000000000000000000026231470345337400337360ustar00rootroot00000000000000(ns puppetlabs.puppetserver.bootstrap-int-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.kitchensink.file :as ks-file] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.trapperkeeper.testutils.logging :as logging] [puppetlabs.puppetserver.certificate-authority :as ca] [me.raynes.fs :as fs])) (use-fixtures :each logging/reset-logging-config-after-test #(logging/with-test-logging (%))) (deftest ^:integration test-app-startup (testing "Trapperkeeper can be booted successfully using the dev config files." (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because we're just testing service startup and CA file generation (which is all Clojure)." app {} (is (true? true)) (testing "Private keys have the correct permissions." (let [pk-dir (str bootstrap/server-conf-dir "/ssl/private_keys") pks (fs/find-files pk-dir #".*pem$")] (is (= ca/private-key-dir-perms (ks-file/get-perms pk-dir))) (is (= ca/private-key-perms (ks-file/get-perms (str bootstrap/server-conf-dir "/ca/ca_key.pem")))) (doseq [pk pks] (is (= ca/private-key-perms (ks-file/get-perms (.getPath pk))))))) (is (true? true))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/puppetserver/bootstrap_testutils.clj000066400000000000000000000177001470345337400341470ustar00rootroot00000000000000(ns puppetlabs.puppetserver.bootstrap-testutils (:require [puppetlabs.trapperkeeper.config :as tk-config] [puppetlabs.trapperkeeper.bootstrap :as tk-bootstrap] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-testutils] [puppetlabs.kitchensink.core :as ks] [me.raynes.fs :as fs] [puppetlabs.ssl-utils.core :as ssl-utils] [puppetlabs.ssl-utils.simple :as ssl-simple] [schema.core :as schema] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-puppet-testutils]) (:import (java.io ByteArrayInputStream ByteArrayOutputStream) (javax.net.ssl SSLContext))) (def dev-config-file "./dev/puppetserver.conf") (def dev-bootstrap-file "./dev/bootstrap.cfg") (def logging-test-conf-file "./dev-resources/logback-test.xml") (def server-conf-dir "./target/server-conf") (def server-code-dir "./target/server-code") (def server-var-dir "./target/server-var") (def server-run-dir "./target/server-var/run") (def server-log-dir "./target/server-var/log") (def multithreaded (= "true" (System/getenv "MULTITHREADED"))) (defn load-dev-config-with-overrides [overrides] (let [tmp-conf (ks/temp-file "puppetserver" ".conf")] (fs/copy dev-config-file tmp-conf) (-> (tk-config/load-config (.getPath tmp-conf)) (assoc-in [:global :logging-config] logging-test-conf-file) (assoc-in [:jruby-puppet :server-conf-dir] server-conf-dir) (assoc-in [:jruby-puppet :server-code-dir] server-code-dir) (assoc-in [:jruby-puppet :server-var-dir] server-var-dir) (assoc-in [:jruby-puppet :server-run-dir] server-run-dir) (assoc-in [:jruby-puppet :server-log-dir] server-log-dir) (assoc-in [:jruby-puppet :multithreaded] multithreaded) (ks/deep-merge overrides)))) (defn services-from-dev-bootstrap ([] (services-from-dev-bootstrap dev-bootstrap-file)) ([bootstrap-config-file] (tk-bootstrap/parse-bootstrap-config! bootstrap-config-file))) (defn services-from-dev-bootstrap-plus-mock-jruby-pool-manager-service ([config] (jruby-puppet-testutils/add-mock-jruby-pool-manager-service (services-from-dev-bootstrap) config)) ([config mock-jruby-puppet-fn] (jruby-puppet-testutils/add-mock-jruby-pool-manager-service (services-from-dev-bootstrap) config mock-jruby-puppet-fn))) (defmacro with-puppetserver-running-with-services [app services config-overrides & body] (let [config (load-dev-config-with-overrides config-overrides)] `(tk-testutils/with-app-with-config ~app ~services ~config ~@body))) (defmacro with-puppetserver-running-with-services-and-mock-jrubies "This macro should be used with caution; it makes tests run much more quickly, but you should be careful to make sure that the mocking won't be subverting any important test coverage. For this reason, we require a `docstring` argument to be passed in, as a sort of annotation explaining why you feel it's safe to use this mocking in your test." [_docstring app services config-overrides & body] (let [config (load-dev-config-with-overrides config-overrides)] `(let [services# (conj ~services (jruby-puppet-testutils/mock-jruby-pool-manager-service ~config))] (tk-testutils/with-app-with-config ~app services# ~config ~@body)))) (defmacro with-puppetserver-running-with-services-and-mock-jruby-puppet-fn "This macro should be used with caution; it makes tests run much more quickly, but you should be careful to make sure that the mocking won't be subverting any important test coverage. For this reason, we require a `docstring` argument to be passed in, as a sort of annotation explaining why you feel it's safe to use this mocking in your test." [_docstring app services config-overrides mock-jruby-puppet-fn & body] (let [config (load-dev-config-with-overrides config-overrides)] `(let [services# (conj ~services (jruby-puppet-testutils/mock-jruby-pool-manager-service ~config ~mock-jruby-puppet-fn))] (tk-testutils/with-app-with-config ~app services# ~config ~@body)))) (defmacro with-puppetserver-running-with-config [app config & body] `(let [services# (tk-bootstrap/parse-bootstrap-config! ~dev-bootstrap-file)] (tk-testutils/with-app-with-config ~app services# ~config ~@body))) (defmacro with-puppetserver-running [app config-overrides & body] `(let [config# (load-dev-config-with-overrides ~config-overrides)] (let [services# (tk-bootstrap/parse-bootstrap-config! ~dev-bootstrap-file)] (tk-testutils/with-app-with-config ~app services# config# ~@body)))) (defmacro with-puppetserver-running-with-mock-jrubies "This macro should be used with caution; it makes tests run much more quickly, but you should be careful to make sure that the mocking won't be subverting any important test coverage. For this reason, we require a `docstring` argument to be passed in, as a sort of annotation explaining why you feel it's safe to use this mocking in your test." [_docstring app config-overrides & body] (let [config (load-dev-config-with-overrides config-overrides)] `(let [services# (services-from-dev-bootstrap-plus-mock-jruby-pool-manager-service ~config)] (tk-testutils/with-app-with-config ~app services# ~config ~@body)))) (defmacro with-puppetserver-running-with-mock-jruby-puppet-fn "This macro should be used with caution; it makes tests run much more quickly, but you should be careful to make sure that the mocking won't be subverting any important test coverage. For this reason, we require a `docstring` argument to be passed in, as a sort of annotation explaining why you feel it's safe to use this mocking in your test." [_docstring app config-overrides mock-jruby-puppet-fn & body] (let [config (load-dev-config-with-overrides config-overrides)] `(let [services# (services-from-dev-bootstrap-plus-mock-jruby-pool-manager-service ~config ~mock-jruby-puppet-fn)] (tk-testutils/with-app-with-config ~app services# ~config ~@body)))) (defn write-to-stream [o] (let [s (ByteArrayOutputStream.)] (ssl-utils/obj->pem! o s) (-> s .toByteArray ByteArrayInputStream.))) (schema/defn get-ca-cert-for-running-server :- ca/Certificate [] (ssl-utils/pem->cert "./target/server-conf/ca/ca_crt.pem")) (schema/defn get-cert-signed-by-ca-for-running-server :- (schema/pred ssl-simple/ssl-cert?) [ca-cert :- ca/Certificate certname :- schema/Str] (let [ca-private-key (ssl-utils/pem->private-key (str "./target/server-conf/ca/ca_key.pem")) ca-dn (-> ca-cert (.getSubjectX500Principal) (.getName)) ca-map {:cert ca-cert :public-key (.getPublicKey ca-cert) :private-key ca-private-key :x500-name (-> (.getSubjectX500Principal ca-cert) (.getName)) :certname (ssl-utils/x500-name->CN ca-dn)}] (ssl-simple/gen-cert certname ca-map 1000 ;; Set this artificially lower than default 4K that Puppet Server uses ;; just to make it a bit faster. Key size is presumed not to matter ;; for the core functionality in any tests that use this. {:keylength 1024}))) (schema/defn get-ssl-context-for-cert-map :- SSLContext [ca-cert :- ca/Certificate cert-map :- (schema/pred ssl-simple/ssl-cert?)] (ssl-utils/generate-ssl-context {:ssl-cert (write-to-stream (:cert cert-map)) :ssl-key (write-to-stream (:private-key cert-map)) :ssl-ca-cert (write-to-stream ca-cert)})) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/puppetserver/error_handling_int_test.clj000066400000000000000000000111041470345337400347100ustar00rootroot00000000000000(ns puppetlabs.puppetserver.error-handling-int-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.puppetserver.common :as ps-common] [puppetlabs.trapperkeeper.testutils.logging :refer [with-test-logging]] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.services.request-handler.request-handler-core :as request-handler] [me.raynes.fs :as fs] [puppetlabs.kitchensink.core :as ks])) (def test-resources "./dev-resources/puppetlabs/puppetserver/error_handling_int_test") (def vcs-scripts "./dev-resources/puppetlabs/services/versioned_code_service/versioned_code_core_test") (use-fixtures :once (testutils/with-puppet-conf (fs/file test-resources "puppet.conf"))) (use-fixtures :each #(with-test-logging (%))) ;; Used in the test below. (defn just-throw-it [& _] (throw (Exception. "barf"))) (defn throw-npe [& _] (throw (NullPointerException.))) (deftest ^:integration test-HTTP-500 (testing "When returning an HTTP 500, the response body is a simple text message, not anything wacky like HTML (I'm looking at you, Jetty.)" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because the request handlers are being with-redef'd to throw exceptions." app {} (with-test-logging (testing "the Puppet Master's main API" ;; This next line of code is wacky, so here's an explanation - ;; this test is specifically written for the case an Exception is ;; thrown somewhere inside this codebase, and is not caught anywhere ;; until it gets all the way up the stack to jetty. To trigger this ;; sort of error, the next line of code re-defines one of the main ;; 'request handling' functions (which is part of the mapping layer ;; between the ring handler and the JRuby layer, and called on every ;; request) to simply ignore any arguments and just throw an Exception. (with-redefs [request-handler/as-jruby-request just-throw-it] (let [call-results (atom []) old-fn @ps-common/action-registration-function new-fn (fn [value] (swap! call-results conj value)) _ (reset! ps-common/action-registration-function new-fn) response (testutils/http-get "puppet/v3/catalog/localhost?environment=production")] (is (= 500 (:status response))) (is (= "Internal Server Error: java.lang.Exception: barf" (:body response))) (is (re-matches #"text/plain;\s*charset=.*" (get-in response [:headers "content-type"]))) (is (= [{:type :action, :targets ["localhost"], :meta {:type :certificate, :what :compile-catalog, :where :v3}}] @call-results)) (reset! ps-common/action-registration-function old-fn)))) (testing "the CA API - in particular, one of the endpoints implemented via liberator" ;; Yes, this is weird - see comment above. (with-redefs [ca/get-cert-or-csr-status throw-npe] (let [response (testutils/http-get "puppet-ca/v1/certificate_status/localhost")] (is (= 500 (:status response))) (is (= "Internal Server Error: java.lang.NullPointerException" (:body response))) (is (re-matches #"text/plain;\s*charset=.*" (get-in response [:headers "content-type"])))))))))) (deftest ^:integration test-invalid-code-id-error (let [vcs-script (ks/absolute-path (fs/file vcs-scripts "invalid_code_id"))] (testing "Catalog request fails when user provided code-id-command returns invalid code-id" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because the Clojure code will throw the code-id-command error before the request ever makes it to JRuby." app {:versioned-code {:code-id-command vcs-script :code-content-command vcs-script}} (with-test-logging (let [response (testutils/http-get "puppet/v3/catalog/localhost?environment=production")] (is (= 500 (:status response))) (is (re-matches #"Internal Server Error: java.lang.IllegalStateException: Invalid code-id.+" (:body response))))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/puppetserver/testutils.clj000066400000000000000000000376731470345337400320650ustar00rootroot00000000000000(ns puppetlabs.puppetserver.testutils (:require [clojure.java.io :as io] [me.raynes.fs :as fs] [schema.core :as schema] [cheshire.core :as json] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.ringutils :as ringutils]) (:import (java.io File) (java.net URL))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Schemas (def PuppetConfFiles {schema/Str (schema/pred (some-fn string? #(instance? File %) #(instance? URL %)))}) (def PuppetResource "Schema for a Puppet resource. Based on the resource within the catalog schema." {(schema/required-key "type") schema/Str (schema/required-key "title") schema/Str (schema/optional-key "line") schema/Int (schema/optional-key "file") schema/Str (schema/required-key "exported") schema/Bool (schema/optional-key "sensitive_parameters") [schema/Str] (schema/required-key "tags") [schema/Str] (schema/optional-key "parameters") {schema/Str schema/Str} (schema/optional-key "ext_parameters") {schema/Str schema/Str} schema/Str schema/Str}) (def PuppetCatalog "Schema for a Puppet catalog. Based on https://github.com/puppetlabs/puppet/blob/stable/api/schemas/catalog.json" {(schema/required-key "name") schema/Str (schema/required-key "classes") [schema/Str] (schema/required-key "environment") schema/Str (schema/required-key "version") schema/Any (schema/required-key "resources") [PuppetResource] (schema/required-key "edges") [{schema/Str schema/Str}] (schema/optional-key "code_id") (schema/maybe schema/Str) (schema/optional-key "tags") [schema/Str] (schema/optional-key "catalog_uuid") schema/Str (schema/optional-key "catalog_format") schema/Int schema/Str schema/Str}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Default settings (schema/def ^:always-validate conf-dir :- schema/Str "./target/server-conf") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Certificates and keys (schema/defn ^:always-validate pem-file :- schema/Str [& args :- [schema/Str]] (str (apply fs/file conf-dir "ssl" args))) (schema/def ^:always-validate ca-cert :- schema/Str (pem-file "certs" "ca.pem")) (schema/def ^:always-validate localhost-cert :- schema/Str (pem-file "certs" "localhost.pem")) (schema/def ^:always-validate localhost-key :- schema/Str (pem-file "private_keys" "localhost.pem")) (def ssl-request-options {:ssl-cert localhost-cert :ssl-key localhost-key :ssl-ca-cert ca-cert}) (def catalog-request-options (merge ssl-request-options {:headers {"Accept" "application/json"} :as :text})) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Internal functions (schema/defn ^:always-validate get-with-puppet-conf-target-paths :- PuppetConfFiles "Helper function that joins the filename onto the dest-dir for each file in puppet-conf-files." [puppet-conf-files :- PuppetConfFiles dest-dir :- schema/Str] (reduce (fn [acc filename] (assoc acc filename (fs/file dest-dir filename))) {} (keys puppet-conf-files))) (schema/defn ^:always-validate copy-with-puppet-conf-files-into-place! "Copies each file in puppet-conf-files into the corresponding destination in target-paths." [puppet-conf-files :- PuppetConfFiles target-paths :- PuppetConfFiles] (doseq [filename (keys puppet-conf-files)] (let [dest (io/file (get target-paths filename)) dest-dir (.getParentFile dest)] (when dest-dir (ks/mkdirs! dest-dir)) (with-open [source (io/input-stream (get puppet-conf-files filename))] (io/copy source dest))))) (schema/defn ^:always-validate cleanup-with-puppet-conf-files! "Deletes all of the files in the target-paths map." [target-paths :- PuppetConfFiles] (doseq [target-path (vals target-paths)] (fs/delete target-path))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utilities (schema/defn ^:always-validate http-get [path :- schema/Str] (http-client/get (str "https://localhost:8140/" path) catalog-request-options)) (defn create-file [file content] (ks/mkdirs! (fs/parent file)) (spit file content)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Interacting with puppet code and catalogs (schema/defn ^:always-validate module-dir :- File [env-name :- schema/Str module-name :- schema/Str] (fs/file conf-dir "environments" env-name "modules" module-name)) (schema/defn ^:always-validate create-module :- schema/Str [module-name :- schema/Str options :- {(schema/optional-key :env-name) schema/Str (schema/optional-key :module-version) schema/Str}] (let [default-options {:env-name "production" :module-version "1.0.0"} options (merge default-options options) module-dir (module-dir (:env-name options) module-name) metadata-json {"name" module-name "version" (:module-version options) "author" "Puppet" "license" "apache" "dependencies" [] "source" "https://github.com/puppetlabs"}] (fs/mkdirs module-dir) (spit (fs/file module-dir "metadata.json") (json/generate-string metadata-json)) (.getCanonicalPath module-dir))) (schema/defn ^:always-validate write-pp-file :- schema/Str ([pp-contents :- schema/Str module-name :- schema/Str] (write-pp-file pp-contents module-name "init")) ([pp-contents :- schema/Str module-name :- schema/Str pp-name :- schema/Str] (write-pp-file pp-contents module-name pp-name "production")) ([pp-contents :- schema/Str module-name :- schema/Str pp-name :- schema/Str env-name :- schema/Str] (write-pp-file pp-contents module-name pp-name env-name "1.0.0")) ([pp-contents :- schema/Str module-name :- schema/Str pp-name :- schema/Str env-name :- schema/Str module-version :- schema/Str] (let [pp-file (fs/file (module-dir env-name module-name) "manifests" (str pp-name ".pp"))] (create-module module-name {:env-name env-name :module-version module-version}) (fs/mkdirs (fs/parent pp-file)) (spit pp-file pp-contents) (.getCanonicalPath pp-file)))) (schema/defn ^:always-validate write-foo-pp-file :- schema/Str [foo-pp-contents] (write-pp-file foo-pp-contents "foo")) (schema/defn ^:always-validate write-tasks-files :- schema/Str ([module-name :- schema/Str task-name :- schema/Str task-file-contents :- schema/Str task-metadata :- schema/Any] (let [module-dir (create-module module-name {}) tasks-dir (fs/file module-dir "tasks") metadata-file-path (fs/file tasks-dir (str task-name ".json"))] (create-file metadata-file-path task-metadata) (create-file (fs/file tasks-dir (str task-name ".sh")) task-file-contents) (.getCanonicalPath metadata-file-path))) ([module-name :- schema/Str task-name :- schema/Str task-file-contents :- schema/Str] (write-tasks-files module-name task-name task-file-contents (json/encode {"description" "This is a description. It describes a thing."})))) (schema/defn ^:always-validate write-plans-files :- schema/Str ([module-name :- schema/Str plan-name :- schema/Str plan-arguments :- schema/Str plan-body :- schema/Str] (let [module-dir (create-module module-name {}) plans-dir (fs/file module-dir "plans") plan-path (fs/file plans-dir (str plan-name ".pp")) scoped-plan-name (if (= plan-name "init") module-name (str module-name "::" plan-name)) plan-file-contents (str scoped-plan-name "(" plan-arguments ") {" plan-body "}")] (create-file plan-path plan-file-contents) (.getCanonicalPath plan-path))) ([module-name :- schema/Str plan-name :- schema/Str plan-body :- schema/Str] (write-plans-files module-name plan-name "" plan-body))) (defn create-env-conf [env-dir content] (create-file (fs/file env-dir "environment.conf") (str "environment_timeout = unlimited\n" content))) (schema/defn ^:always-validate get-static-file-content ([url-end :- schema/Str] (get-static-file-content url-end true)) ([url-end :- schema/Str include-ssl-certs? :- schema/Bool] (let [request-options (if include-ssl-certs? catalog-request-options {:ssl-ca-cert ca-cert :headers {"Accept" "application/json"}})] (http-client/get (str "https://localhost:8140/puppet/v3/static_file_content/" url-end) (assoc request-options :as :text))))) (schema/defn ^:always-validate catalog-ring-response->catalog :- PuppetCatalog "Convert a response from a catalog request into a catalog map" [response :- ringutils/RingResponse] (-> response :body json/parse-string)) (schema/defn ^:always-validate get-catalog :- PuppetCatalog "Make an HTTP get request for a catalog." [] (-> (http-client/get "https://localhost:8140/puppet/v3/catalog/localhost?environment=production" catalog-request-options) :body json/parse-string)) (schema/defn ^:always-validate post-catalog :- PuppetCatalog "Make an HTTP post request for a catalog." [] (-> (http-client/post "https://localhost:8140/puppet/v3/catalog/localhost" (assoc-in (assoc catalog-request-options :body "environment=production") [:headers "Content-Type"] "application/x-www-form-urlencoded")) :body json/parse-string)) (schema/defn ^:always-validate write-site-pp-file ([site-pp-contents :- schema/Str] (write-site-pp-file (fs/file conf-dir "environments" "production") site-pp-contents)) ([base-dir :- File site-pp-contents :- schema/Str] (let [site-pp-file (fs/file base-dir "manifests" "site.pp")] (fs/mkdirs (fs/parent site-pp-file)) (spit site-pp-file site-pp-contents)))) (schema/defn ^:always-validate catalog-name-matches? :- schema/Bool "Return whether the name (host) found in the catalog matches the supplied name parameter." [catalog :- PuppetCatalog name :- schema/Str] (= name (get catalog "name"))) (schema/defn ^:always-validate resource-matches? :- schema/Bool ([resource-type :- schema/Str resource-title :- schema/Str resource :- PuppetResource] (and (= resource-type (resource "type")) (= resource-title (resource "title")))) ([resource-type :- schema/Str resource-title :- schema/Str resource :- PuppetResource param-name :- schema/Str param-value :- schema/Any] (and (resource-matches? resource-type resource-title resource) (= param-value (get-in resource ["parameters" param-name]))))) (schema/defn ^:always-validate catalog-contains? :- schema/Bool ([catalog :- PuppetCatalog resource-type :- schema/Str resource-title :- schema/Str] (let [resources (get catalog "resources")] (->> resources (some (partial resource-matches? resource-type resource-title)) nil? not))) ([catalog :- PuppetCatalog resource-type :- schema/Str resource-title :- schema/Str param-name :- schema/Str param-value :- schema/Any] (let [resources (get catalog "resources")] (some #(resource-matches? resource-type resource-title % param-name param-value) resources)))) (schema/defn catalog-code-id :- (schema/maybe schema/Str) "Given a catalog, returns the code_id from the catalog." [catalog :- PuppetCatalog] (get catalog "code_id")) (schema/defn ^:always-validate num-catalogs-containing :- schema/Int [catalogs :- [PuppetCatalog] resource-type :- schema/Str resource-title :- schema/Str] (count (filter #(catalog-contains? % resource-type resource-title) catalogs))) (defmacro with-puppet-conf-files "A macro that can be used to wrap a single test with the setup and teardown of with-puppet-conf. Accepts a map with the following characteristics: * keys are simple filenames (no paths) that will be created in puppet's $confdir * values are paths to a test-specific file that should be copied to puppet's confdir, a la `$confdir/`. For each entry in the map, copies the files into $confdir. Then it runs the body. Then after running the body it deletes all of the files from $confdir. Optionally accepts a second argument `dest-dir`, which specifies the location of Puppet's $confdir. If this argument is not provided, defaults to `jruby-testutils/conf-dir`." [puppet-conf-files dest-dir & body] `(let [target-paths# (get-with-puppet-conf-target-paths ~puppet-conf-files ~dest-dir)] (copy-with-puppet-conf-files-into-place! ~puppet-conf-files target-paths#) (try ~@body (finally (cleanup-with-puppet-conf-files! target-paths#))))) (schema/defn ^:always-validate with-puppet-conf-fixture "Test fixture; Accepts a map with the following characteristics: * keys are simple filenames (no paths) that will be created in puppet's $confdir * values are paths to a test-specific file that should be copied to puppet's confdir, a la `$confdir/`. For each entry in the map, copies the files into $confdir, runs the test function, and then deletes all of the files from $confdir. Optionally accepts a second argument `dest-dir`, which specifies the location of Puppet's $confdir. If this argument is not provided, defaults to `jruby-testutils/conf-dir`." ([puppet-conf-files] (with-puppet-conf-fixture puppet-conf-files conf-dir)) ([puppet-conf-files :- PuppetConfFiles dest-dir :- schema/Str] (fn [f] (with-puppet-conf-files puppet-conf-files dest-dir (f))))) (defn with-puppet-conf "This function returns a test fixture that will copy a specified puppet.conf file into the provided location for testing, and then delete it after the tests have completed. If no destination dir is provided then the puppet.conf file is copied to the default location of './target/server-conf'." ([puppet-conf-file] (with-puppet-conf puppet-conf-file conf-dir)) ([puppet-conf-file dest-dir] (with-puppet-conf-fixture {"puppet.conf" puppet-conf-file} dest-dir))) (defmacro with-stub-puppet-conf "Provides similar functionality of `with-puppet-conf` but uses a default stub puppet.conf for testing and is not meant to be used inline in tests (not as a `use-fixtures` fn). More advanced uses should create a fixture directory." [body] `(let [content# (str "[main]\n cadir = " conf-dir "/ca") file# (str (ks/temp-file))] (spit file# content#) (with-puppet-conf-files {"puppet.conf" file#} conf-dir ~body))) (defn copy-config-files [dirs-to-copy] (doseq [[src target] dirs-to-copy] (fs/mkdirs target) (let [[_ dirs files] (first (fs/iterate-dir src))] (doseq [d dirs] (fs/copy-dir (fs/file src d) target)) (doseq [f files] (fs/copy (fs/file src f) (fs/file target f)))))) (defn remove-config-files [dirs-to-copy] (doseq [[src target] dirs-to-copy] (let [[_ dirs files] (first (fs/iterate-dir src))] (doseq [d dirs] (fs/delete-dir (fs/file target d))) (doseq [f files] (fs/delete (fs/file target f)))))) (defmacro with-config-dirs "Evaluates the supplied body after copying the source directory (key) to target directory (value) for each element in the supplied dirs-to-copy map. After the body is evaluated, all of the copied directory content is removed. For example: (with-config-dirs {\"/my/source-dir1\" \"/my/target-dir1\" \"/my/source-dir2\" \"/my/target-dir2\"} (println \"Do something interesting\"))" [dirs-to-copy & body] `(do (copy-config-files ~dirs-to-copy) (try ~@body (finally (remove-config-files ~dirs-to-copy))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/000077500000000000000000000000001470345337400263725ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/analytics/000077500000000000000000000000001470345337400303615ustar00rootroot00000000000000analytics_service_test.clj000066400000000000000000000077211470345337400355510ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/analytics(ns puppetlabs.services.analytics.analytics-service-test (:require [clojure.test :refer [deftest is testing]] [puppetlabs.dujour.version-check :as version-check] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap-testutils] [puppetlabs.trapperkeeper.testutils.logging :as logutils])) (deftest ^:integration version-check-test (testing "master calls into the dujour version check library using the correct values" ; This promise will store the parameters passed to the version-check-test-fn, which allows us to keep the ; assertions about their values inside the version-check-test and will also ensure failures will appear if ; the master stops calling the check-for-updates! function (let [version-check-params (promise) version-check-test-fn (fn [request-values update-server-url] (deliver version-check-params {:request-values request-values :update-server-url update-server-url}))] (with-redefs [version-check/check-for-update version-check-test-fn] (logutils/with-test-logging (bootstrap-testutils/with-puppetserver-running-with-mock-jrubies "Mocking is safe here because we're not doing anything with JRubies, just making sure the service starts and makes the right dujour calls" app {:jruby-puppet {:max-active-instances 1} :webserver {:port 8081} :product {:update-server-url "http://notarealurl/" :name {:group-id "puppets" :artifact-id "yoda"}}} (let [params-received (deref version-check-params 30000 {:request-values {:product-name :no-product-name-received-before-time-out-reached} :update-server-url :no-update-server-url-received-before-time-out-reached})] (is (= {:group-id "puppets" :artifact-id "yoda"} (get-in params-received [:request-values :product-name]))) (is (= "http://notarealurl/" (:update-server-url params-received))))))))) (testing "master does not make an analytics call to dujour if opt-out exists" ; This promise will store the parameters passed to the version-check-test-fn, which allows us to keep the ; assertions about their values inside the version-check-test and will also ensure failures will appear if ; the master stops calling the check-for-updates! function (let [version-check-params (promise) version-check-test-fn (fn [request-values update-server-url] (deliver version-check-params {:request-values request-values :update-server-url update-server-url}))] (with-redefs [version-check/check-for-updates! version-check-test-fn] (logutils/with-test-logging (bootstrap-testutils/with-puppetserver-running-with-mock-jrubies "Mocking is safe here because we're not doing anything with JRubies, just making sure the service starts and makes the right dujour calls" app {:jruby-puppet {:max-active-instances 1} :webserver {:port 8081} :product {:update-server-url "http://notarealurl/" :name {:group-id "puppets" :artifact-id "yoda"} :check-for-updates false}} (is (logutils/logged? #"Not checking for updates - opt-out setting exists" :info)) (let [params-received (deref version-check-params 100 :no-params-received-before-time-out-reached)] (is (= :no-params-received-before-time-out-reached params-received))))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/certificate_authority/000077500000000000000000000000001470345337400327645ustar00rootroot00000000000000certificate_authority_int_test.clj000066400000000000000000003357011470345337400417130ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/certificate_authority(ns puppetlabs.services.certificate-authority.certificate-authority-int-test (:require [cheshire.core :as json] [clj-time.core :as time] [clj-time.format :as time-format] [clojure.java.io :as io] [clojure.test :refer [deftest is testing use-fixtures]] [me.raynes.fs :as fs] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.kitchensink.file :as ks-file] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.puppetserver.common :as common] [puppetlabs.puppetserver.testutils :as testutils :refer [http-get]] [puppetlabs.rbac-client.protocols.activity :as act-proto] [puppetlabs.rbac-client.testutils.dummy-rbac-service :refer [dummy-rbac-service]] [puppetlabs.services.ca.ca-testutils :as ca-test-utils] [puppetlabs.services.ca.certificate-authority-core :refer [handle-get-certificate-revocation-list]] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.ssl-utils.core :as ssl-utils] [puppetlabs.ssl-utils.simple :as simple] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [ring.mock.request :as mock] [ring.util.codec :as ring-codec] [schema.test :as schema-test]) (:import (java.util Date Random) (java.util.concurrent TimeUnit) (javax.net.ssl SSLException))) (def test-resources-dir "./dev-resources/puppetlabs/services/certificate_authority/certificate_authority_int_test") (use-fixtures :once schema-test/validate-schemas) (use-fixtures :each #(logutils/with-test-logging (%))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utilities ;; TODO remove the loops that used to use this to test legacy routes (def ca-mount-points ["puppet-ca/v1/"]) ; puppet 4 style (defn cert-status-request-params ([] {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :headers {"content-type" "application/json"}}) ([body] (merge (cert-status-request-params) {:body body}))) (defn create-ca-cert [name serial] (let [keypair (ssl-utils/generate-key-pair) public-key (ssl-utils/get-public-key keypair) private-key (ssl-utils/get-private-key keypair) x500-name (ssl-utils/cn name) validity (ca/cert-validity-dates 3600) ca-exts (ca/create-ca-extensions public-key public-key)] {:public-key public-key :private-key private-key :x500-name x500-name :certname name :cert (ssl-utils/sign-certificate x500-name private-key serial (:not-before validity) (:not-after validity) x500-name public-key ca-exts)})) (defn generate-a-csr [certname extensions attributes] (let [key-pair (ssl-utils/generate-key-pair) csr (ssl-utils/generate-certificate-request key-pair (ssl-utils/cn certname) extensions attributes) csr-path (str bootstrap/server-conf-dir "/ca/requests/" certname ".pem")] (ssl-utils/obj->pem! csr csr-path) key-pair)) (defn delete-all-csrs [] (let [csr-path (str bootstrap/server-conf-dir "/ca/requests/")] (ks-file/delete-recursively csr-path))) (defn generate-and-sign-a-cert! [certname] (let [cert-path (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") key-path (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") ca-cert-path (str bootstrap/server-conf-dir "/ca/ca_crt.pem") status-url (str "https://localhost:8140/puppet-ca/v1/certificate_status/" certname) cert-endpoint (str "https://localhost:8140/puppet-ca/v1/certificate/" certname) request-opts {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path} key-pair (generate-a-csr certname [] [])] (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json"}})) (let [cert-request (http-client/get cert-endpoint {:ssl-ca-cert ca-cert-path}) private-key-file (ks/temp-file) public-key-file (ks/temp-file)] (ssl-utils/key->pem! (ssl-utils/get-public-key key-pair) public-key-file) (ssl-utils/key->pem! (ssl-utils/get-private-key key-pair) private-key-file) {:signed-cert (slurp (:body cert-request)) :public-key public-key-file :private-key private-key-file}))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Tests (deftest reporting-activity-handles-errors (let [cert-path (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") key-path (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") ca-cert-path (str bootstrap/server-conf-dir "/ca/ca_crt.pem") crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem") test-service (tk-services/service act-proto/ActivityReportingService [] (report-activity! [_this body] (throw (Exception. "Foo"))))] (testing "returns expiration dates for all CA certs and CRLs" (testutils/with-stub-puppet-conf (bootstrap/with-puppetserver-running-with-services app (concat (bootstrap/services-from-dev-bootstrap) [test-service]) {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path :ssl-crl-path crl-path}} (let [certname "test_cert" csr (ssl-utils/generate-certificate-request (ssl-utils/generate-key-pair) (ssl-utils/cn certname)) csr-path (str bootstrap/server-conf-dir "/ca/requests/" certname ".pem") signed-cert-path (str bootstrap/server-conf-dir "/ca/signed/" certname ".pem") status-url (str "https://localhost:8140/puppet-ca/v1/certificate_status/" certname) request-opts {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path}] (ssl-utils/obj->pem! csr csr-path) (testing "Sign the waiting CSR" (logutils/with-test-logging (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json"}}))] (is (= 204 (:status response))) (is (logged? #"Reporting CA event failed with: Foo" :error)) (is (logged? #"Payload.*commit" :error)) (is (fs/exists? signed-cert-path)) (is (logged? #"Entity localhost signed 1 certificate.*" :info))))) (testing "Revoke the cert" (logutils/with-test-logging (let [call-results (atom []) old-fn @common/action-registration-function new-fn (fn [value] (swap! call-results conj value)) _ (reset! common/action-registration-function new-fn) response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"revoked\"}" :headers {"content-type" "application/json" "X-Authentication" "test"}}))] (is (= 204 (:status response))) (is (logged? #"Reporting CA event failed with: Foo" :error)) (is (logged? #"Payload.*commit" :error)) (is (logged? #"Entity localhost revoked 1 certificate.*" :info)) (is (= [{:type :remove, :targets ["test_cert"], :meta {:type :certificate}}] @call-results)) (reset! common/action-registration-function old-fn)))))))))) (deftest new-cert-signing-respects-agent-renewal-support-indication (testutils/with-config-dirs {(str test-resources-dir "/infracrl_test/master/conf/ssl") (str bootstrap/server-conf-dir "/ssl") (str test-resources-dir "/infracrl_test/master/conf/ca") (str bootstrap/server-conf-dir "/ca")} (let [cert-path (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") key-path (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") ca-cert-path (str bootstrap/server-conf-dir "/ca/ca_crt.pem")] (testing "with a puppetserver configured for auto-renewal" (testutils/with-stub-puppet-conf (bootstrap/with-puppetserver-running app {:certificate-authority { :allow-auto-renewal true} :jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")}} (testing "signs a cert with a short ttl when the capability indicator is present" (let [certname (ks/rand-str :alpha-lower 8) csr (ssl-utils/generate-certificate-request (ssl-utils/generate-key-pair) (ssl-utils/cn certname) [] [{:oid "1.3.6.1.4.1.34380.1.3.2" :value true}]) csr-path (ks/temp-file "test_csr.pem") signed-cert-path (str bootstrap/server-conf-dir "/ca/signed/" certname ".pem") status-url (str "https://localhost:8140/puppet-ca/v1/certificate_status/" certname) url (str "https://localhost:8140/puppet-ca/v1/certificate_request/" certname) request-opts {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path}] (ssl-utils/obj->pem! csr csr-path) (testing "submit a CSR via the API" (let [response (http-client/put url (merge request-opts {:body (slurp csr-path) :headers {"x-puppet-version" "8.2.0"}}))] (is (= 200 (:status response))))) (testing "Sign the waiting CSR" (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json"}}))] (is (= 204 (:status response))) (is (fs/exists? signed-cert-path)) (let [signed-cert (ssl-utils/pem->cert signed-cert-path)] (testing "new not-after should be 89 days (and some fraction) away" (let [diff (- (.getTime (.getNotAfter signed-cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] (is (= 89 days))))))))) (testing "signs a cert with a long ttl when the capability indicator is not present" (let [certname (ks/rand-str :alpha-lower 8) csr (ssl-utils/generate-certificate-request (ssl-utils/generate-key-pair) (ssl-utils/cn certname)) csr-path (ks/temp-file "test_csr.pem") signed-cert-path (str bootstrap/server-conf-dir "/ca/signed/" certname ".pem") status-url (str "https://localhost:8140/puppet-ca/v1/certificate_status/" certname) url (str "https://localhost:8140/puppet-ca/v1/certificate_request/" certname) request-opts {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path}] (ssl-utils/obj->pem! csr csr-path) (testing "submit a CSR via the API" (let [response (http-client/put url (merge request-opts {:body (slurp csr-path) :headers {"x-puppet-version" "7.1.8"}}))] (is (= 200 (:status response))))) (testing "Sign the waiting CSR" (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json"}}))] (is (= 204 (:status response))) (is (fs/exists? signed-cert-path)) (let [signed-cert (ssl-utils/pem->cert signed-cert-path)] (testing "new not-after should be 5 years (and some fraction) away" (let [diff (- (.getTime (.getNotAfter signed-cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] (is (= (- (* 365 5) 1) days))))))))))))))) (deftest ^:integration cert-on-whitelist-test (testing "requests made when cert is on whitelist" (logutils/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:certificate-authority {:certificate-status {:client-whitelist ["localhost"]}} :authorization {:version 1 :rules [{:match-request {:path "/puppet-ca/v1/certificate" :type "path"} :allow ["nonlocalhost"] :sort-order 1 :name "cert"}]}} (testing "are allowed" (doseq [ca-mount-point ca-mount-points endpoint ["certificate_status/localhost" "certificate_statuses/ignored"]] (testing (str "for the " endpoint " endpoint") (let [response (http-get (str ca-mount-point endpoint))] (is (= 200 (:status response)) (ks/pprint-to-string response)))))) (logutils/with-test-logging (testing "are denied when denied by rule to the certificate endpoint" (doseq [ca-mount-point ca-mount-points] (let [response (http-get (str ca-mount-point "certificate/localhost"))] (is (= 403 (:status response)) (ks/pprint-to-string response)))))))))) (deftest ^:integration cert-not-on-whitelist-test (testing "requests made when cert not on whitelist" (logutils/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:certificate-authority {:certificate-status {:client-whitelist ["notlocalhost"]}} :authorization {:version 1 :rules [{:match-request {:path "/puppet-ca/v1/certificate" :type "path"} :allow ["localhost"] :sort-order 1 :name "cert"}]}} (logutils/with-test-logging (testing "are denied" (doseq [ca-mount-point ca-mount-points endpoint ["certificate_status/localhost" "certificate_statuses/ignored"]] (testing (str "for the " endpoint " endpoint") (let [response (http-get (str ca-mount-point endpoint))] (is (= 403 (:status response)) (ks/pprint-to-string response))))))) (testing "are allowed when allowed by rule to the certificate endpoint" (doseq [ca-mount-point ca-mount-points] (let [response (http-get (str ca-mount-point "certificate/localhost"))] (is (= 200 (:status response)) (ks/pprint-to-string response))))))))) (deftest ^:integration empty-whitelist-defined-test (testing "requests made when no whitelist is defined" (logutils/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:certificate-authority {:certificate-status {:client-whitelist []}} :authorization {:version 1 :rules [{:match-request {:path "^/puppet-ca/v1/certificate_status(?:es)?/([^/]+)$" :type "regex"} :allow ["$1"] :sort-order 1 :name "cert status"}]}} (testing "are allowed for matching client" (doseq [ca-mount-point ca-mount-points endpoint ["certificate_status/localhost" "certificate_statuses/localhost"]] (testing (str "for the " endpoint " endpoint") (let [response (http-get (str ca-mount-point endpoint))] (is (= 200 (:status response)) (ks/pprint-to-string response)))))) (logutils/with-test-logging (testing "are denied for non-matching client" (doseq [ca-mount-point ca-mount-points endpoint ["certificate_status/nonlocalhost" "certificate_statuses/nonlocalhost"]] (testing (str "for the " endpoint " endpoint") (let [response (http-get (str ca-mount-point endpoint))] (is (= 403 (:status response)) (ks/pprint-to-string response))))))))))) (deftest ^:integration no-whitelist-defined-test (testing "requests made when no whitelist is defined" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:authorization {:version 1 :rules [{:match-request {:path "^/puppet-ca/v1/certificate_status(?:es)?/([^/]+)$" :type "regex"} :allow ["$1"] :sort-order 1 :name "cert status"}]}} (testing "are allowed for matching client with no encoded characters" (doseq [ca-mount-point ca-mount-points endpoint ["certificate_status/localhost" "certificate_statuses/localhost"]] (testing (str "for the " endpoint " endpoint") (let [response (http-get (str ca-mount-point endpoint))] (is (= 200 (:status response)) (ks/pprint-to-string response)))))) (testing "are allowed for matching client with some encoded characters" (let [response (http-get (str "puppet-ca/v1/certificate_status/" "%6cocalhost"))] (is (= 200 (:status response)) (ks/pprint-to-string response)) (is (= "localhost" (-> response :body json/parse-string (get "name")))))) (logutils/with-test-logging (testing "are denied for non-matching client" (doseq [ca-mount-point ca-mount-points endpoint ["certificate_status/nonlocalhost" "certificate_statuses/nonlocalhost"]] (testing (str "for the " endpoint " endpoint") (let [response (http-get (str ca-mount-point endpoint))] (is (= 403 (:status response)) (ks/pprint-to-string response)))))))))) (deftest ^:integration certificate-with-ca-true-extension-refused (testing "Validates that the server rejects a csr for signing that has the v3 CA:TRUE extension" (let [test-conf-dir (str test-resources-dir "/ca_true_test/master/conf") req-dir (str bootstrap/server-conf-dir "/ca/requests") key-pair (ssl-utils/generate-key-pair) subjectDN (ssl-utils/cn "test_cert_ca_true") ca-ext [(ssl-utils/basic-constraints-for-ca)] csr (ssl-utils/generate-certificate-request key-pair subjectDN ca-ext)] (testutils/with-config-dirs {test-conf-dir bootstrap/server-conf-dir} (fs/mkdir req-dir) (ssl-utils/obj->pem! csr (str req-dir "/test_cert_ca_true.pem")) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:server-conf-dir bootstrap/server-conf-dir}} (let [response (http-client/put (str "https://localhost:8140/" "puppet-ca/v1/certificate_status/test_cert_ca_true") {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json"}})] (is (= 409 (:status response))) (is (.startsWith (:body response) "Found extensions")) (is (.contains (:body response) "2.5.29.19")) (fs/delete-dir req-dir))))))) (deftest ^:integration double-encoded-request-not-allowed (testing "client not able to unintentionally get access to CA endpoint by double-encoding request uri" ;; The following tests are intended to show that a client is not able ;; to unintentionally gain access to info for a different client by ;; double-encoding a character in the client name portion of the ;; request. This test is a bit odd in that: ;; ;; 1) The 'path' for the auth-rule needs to have an allow access control ;; entry which uses the regular expression format, e.g., "/%6cocalhost/" ;; instead of just "/%6cocalhost", because tk-auth only permits a ;; percent character to be used in the entry name for the regular ;; expression format. Other formats generate an exception because the ;; percent character is not legal for a domain type entry. ;; ;; 2) The requests still fail with an HTTP 404 (Not Found) error because ;; the subject parameter is destructured in the certificate_status route ;; definition... ;; ;; (ANY ["/certificate_status/" :subject] [subject] ;; ;; ... and a comidi route evaluation will fail to match a 'subject' that ;; has a percent character in the name. ;; ;; This test may be more useful at the point tk-auth and comidi were to ;; more generally handle the presence of a percent character. (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:authorization {:version 1 :rules [{:match-request {:path (str "/puppet-ca/v1/certificate_status/" "%6cocalhost") :type "path"} :allow ["/%6cocalhost/"] :sort-order 1 :name "cert status"}]}} (let [ca-cert (bootstrap/get-ca-cert-for-running-server) client-cert (bootstrap/get-cert-signed-by-ca-for-running-server ca-cert "%6cocalhost") ssl-context (bootstrap/get-ssl-context-for-cert-map ca-cert client-cert)] (testing "for a puppet v4 style CA request" (let [response (http-client/get (str "https://localhost:8140/puppet-ca/v1/" "certificate_status/%256cocalhost") {:ssl-context ssl-context :as :text})] (is (= 404 (:status response)) (ks/pprint-to-string response)) (is (= "Not Found" (:body response))))))))) (deftest ^:integration crl-reloaded-without-server-restart (testutils/with-stub-puppet-conf (with-redefs [act-proto/report-activity! (fn [_ _] nil)] (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")}} (let [key-pair (ssl-utils/generate-key-pair) subject "crl_reload" subject-dn (ssl-utils/cn subject) private-key (ssl-utils/get-private-key key-pair) private-key-file (ks/temp-file) csr (ssl-utils/generate-certificate-request key-pair subject-dn) options {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text} _ (ssl-utils/key->pem! private-key private-key-file) _ (ssl-utils/obj->pem! csr (str bootstrap/server-conf-dir "/ca/requests/" subject ".pem")) cert-status-request (fn [action] (http-client/put (str "https://localhost:8140/" "puppet-ca/v1/certificate_status/" subject) (merge options {:body (str "{\"desired_state\": \"" action "\"}") :headers {"content-type" "application/json"}}))) client-request #(http-client/get "https://localhost:8140/status/v1/services" (merge options {:ssl-key (str private-key-file) :ssl-cert (str bootstrap/server-conf-dir "/ca/signed/" subject ".pem")}))] (testing "node certificate request can be signed successfully" (let [sign-response (cert-status-request "signed")] (is (= 204 (:status sign-response))))) (testing "node request before revocation is successful" (let [node-response-before-revoke (client-request)] (is (= 200 (:status node-response-before-revoke))))) (testing "node certificate can be successfully revoked" (let [revoke-response (cert-status-request "revoked")] (is (= 204 (:status revoke-response))))) (testing "node request after revocation fails" (let [ssl-exception-for-request? #(try (client-request) false (catch SSLException _ true))] (is (loop [times 30] (cond (ssl-exception-for-request?) true (zero? times) false :else (do (Thread/sleep 500) (recur (dec times))))))))))))) (deftest ^:integration revoke-compiler-test (testing "Compiler certificate revocation " (with-redefs [act-proto/report-activity! (fn [_ _] nil)] (testutils/with-config-dirs {(str test-resources-dir "/infracrl_test/master/conf/ssl") (str bootstrap/server-conf-dir "/ssl") (str test-resources-dir "/infracrl_test/master/conf/ca") (str bootstrap/server-conf-dir "/ca")} (let [subject "compile-master" node-subject "agent-node" infra-crl (str bootstrap/server-conf-dir "/ca/infra_crl.pem") signed-dir (str bootstrap/server-conf-dir "/ca/signed") ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") ca-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") ca-crl (str bootstrap/server-conf-dir "/ca/ca_crl.pem")] (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:certificate-authority {:enable-infra-crl true}} (testing "should update infrastructure CRL" (let [call-results (atom []) old-fn @common/action-registration-function new-fn (fn [value] (swap! call-results conj value)) _ (reset! common/action-registration-function new-fn) ca-cert' (ssl-utils/pem->ca-cert ca-cert ca-key) cm-cert (ssl-utils/pem->cert (ca/path-to-cert signed-dir subject)) node-cert (ssl-utils/pem->cert (ca/path-to-cert signed-dir node-subject)) options {:ssl-cert ca-cert :ssl-key ca-key :ssl-ca-cert ca-cert :as :text} cert-status-request (fn [action certtorevoke] (http-client/put (str "https://localhost:8140/" "puppet-ca/v1/certificate_status/" certtorevoke) (merge options {:body (str "{\"desired_state\": \"" action "\"}") :headers {"content-type" "application/json"}})))] (testing "Infra CRL should contain the revoked compiler's certificate" (let [revoke-response (cert-status-request "revoked" subject)] ;; If the revocation was successful infra CRL should contain above revoked compiler's cert (is (= 204 (:status revoke-response))) (is (ssl-utils/revoked? (ssl-utils/pem->ca-crl infra-crl ca-cert') cm-cert)))) (testing "Infra CRL should NOT contain a revoked non-compiler's certificate" (let [revoke-response (cert-status-request "revoked" node-subject)] (is (= 204 (:status revoke-response))) (is (not (ssl-utils/revoked? (ssl-utils/pem->ca-crl infra-crl ca-cert') node-cert))))) (is (= [{:type :remove, :targets ["compile-master"], :meta {:type :certificate}} {:type :remove, :targets ["agent-node"], :meta {:type :certificate}}] @call-results)) (reset! common/action-registration-function old-fn))) (testing "Verify correct CRL is returned depending on enable-infra-crl" (let [request (mock/request :get "/v1/certificate_revocation_list/mynode") ca-settings (ca-test-utils/ca-settings "") infra-crl-response (handle-get-certificate-revocation-list request (assoc ca-settings :cacrl ca-crl :infra-crl-path infra-crl :enable-infra-crl true)) infra-crl-response-body (:body infra-crl-response) full-crl-response (handle-get-certificate-revocation-list request (assoc ca-settings :cacrl ca-crl :infra-crl-path infra-crl :enable-infra-crl false)) full-crl-response-body (:body full-crl-response)] (is (map? infra-crl-response)) (is (= 200 (:status infra-crl-response))) (is (= "text/plain" (get-in infra-crl-response [:headers "Content-Type"]))) (is (string? infra-crl-response-body)) (is (= infra-crl-response-body (slurp infra-crl))) (is (map? full-crl-response)) (is (= 200 (:status full-crl-response))) (is (= "text/plain" (get-in full-crl-response [:headers "Content-Type"]))) (is (string? full-crl-response-body)) (is (= full-crl-response-body (slurp ca-crl)))))) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:certificate-authority {:enable-infra-crl true}} (testing "Verify infrastructure CRL is returned " (let [options {:ssl-ca-cert ca-cert :as :text} crl-response (http-client/get "https://localhost:8140/puppet-ca/v1/certificate_revocation_list/ca" (merge options {:headers {"Accept" "text/plain"}})) crl-response-body (:body crl-response)] (is (map? crl-response)) (is (= 200 (:status crl-response))) (is (string? crl-response-body)) (is (= crl-response-body (slurp infra-crl)))))) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:certificate-authority {:enable-infra-crl false}} (testing "Verify full CRL is returned " (let [options {:ssl-ca-cert ca-cert :as :text} crl-response (http-client/get "https://localhost:8140/puppet-ca/v1/certificate_revocation_list/ca" (merge options {:headers {"Accept" "text/plain"}})) crl-response-body (:body crl-response)] (is (map? crl-response)) (is (= 200 (:status crl-response))) (is (string? crl-response-body)) (is (= crl-response-body (slurp ca-crl))))))))))) (deftest ^:integration clean-infrastructure-certs (with-redefs [act-proto/report-activity! (fn [_ _] nil)] (testutils/with-config-dirs {(str test-resources-dir "/infracrl_test/master/conf/ssl") (str bootstrap/server-conf-dir "/ssl") (str test-resources-dir "/infracrl_test/master/conf/ca") (str bootstrap/server-conf-dir "/ca")} (let [infra-inventory-path (str bootstrap/server-conf-dir "/ca/infra_inventory.txt") infra-inventory-content (slurp infra-inventory-path) ;; We're going to pretend this is an infra cert for this test subject2 "agent-node"] ;; Add another cert to the infra inventory (spit infra-inventory-path (str infra-inventory-content subject2)) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:certificate-authority {:enable-infra-crl true}} (let [subject1 "compile-master" cert1-path (ca/path-to-cert (str bootstrap/server-conf-dir "/ca/signed") subject1) cert1 (ssl-utils/pem->cert cert1-path) cert2-path (ca/path-to-cert (str bootstrap/server-conf-dir "/ca/signed") subject2) cert2 (ssl-utils/pem->cert cert2-path)] (testing "should update infrastructure CRL with multiple certs" (let [ca-cert (ssl-utils/pem->ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") (str bootstrap/server-conf-dir "/ca/ca_key.pem")) options {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text}] (testing "Infra CRL should contain the revoked compiler's certificate" (let [revoke-response (http-client/put "https://localhost:8140/puppet-ca/v1/clean" (merge options {:body (format "{\"certnames\":[\"%s\",\"%s\"]}" subject1 subject2) :headers {"content-type" "application/json"}}))] ;; If the revocation was successful infra CRL should contain above revoked compiler's cert (is (= 200 (:status revoke-response))) (is (ssl-utils/revoked? (ssl-utils/pem->ca-crl (str bootstrap/server-conf-dir "/ca/infra_crl.pem") ca-cert) cert1)) (is (ssl-utils/revoked? (ssl-utils/pem->ca-crl (str bootstrap/server-conf-dir "/ca/infra_crl.pem") ca-cert) cert2)) (is (false? (fs/exists? cert1-path))) (is (false? (fs/exists? cert2-path))))))))))))) (deftest ^:integration certificate-status-returns-auth-ext-info (testing "Validates that the certificate_status endpoint includes authorization extensions for certs and CSRs" (with-redefs [act-proto/report-activity! (fn [_ _] nil)] (let [request-dir (str bootstrap/server-conf-dir "/ca/requests") key-pair (ssl-utils/generate-key-pair) subjectDN (ssl-utils/cn "test_cert_with_auth_ext") auth-ext-short-name {:oid (:pp_auth_role ca/puppet-short-names) :critical false :value "true"} auth-ext-oid {:oid "1.3.6.1.4.1.34380.1.3.1.2" :critical false :value "true"} csr (ssl-utils/generate-certificate-request key-pair subjectDN [auth-ext-short-name auth-ext-oid])] (fs/mkdirs request-dir) (ssl-utils/obj->pem! csr (str request-dir "/test_cert_with_auth_ext.pem")) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-authorization-extensions true}} (testing "Auth extensions on a CSR" (let [response (http-client/get (str "https://localhost:8140/" "puppet-ca/v1/certificate_status/test_cert_with_auth_ext") (cert-status-request-params)) auth-exts {"pp_auth_role" "true" "1.3.6.1.4.1.34380.1.3.1.2" "true"}] (is (= 200 (:status response))) (let [status-body (json/parse-string (:body response))] (is (= auth-exts (get status-body "authorization_extensions"))) (is (= "requested" (get status-body "state")))))) (testing "Auth extensions on a cert" (let [sign-response (http-client/put (str "https://localhost:8140/" "puppet-ca/v1/certificate_status/test_cert_with_auth_ext") (cert-status-request-params "{\"desired_state\": \"signed\"}")) status-response (http-client/get (str "https://localhost:8140/" "puppet-ca/v1/certificate_status/test_cert_with_auth_ext") (cert-status-request-params)) auth-exts {"pp_auth_role" "true" "1.3.6.1.4.1.34380.1.3.1.2" "true"}] (is (= 204 (:status sign-response))) (is (= 200 (:status status-response))) (let [status-body (json/parse-string (:body status-response))] (is (= auth-exts (get status-body "authorization_extensions"))) (is (= "signed" (get status-body "state")))))))) (fs/delete (str bootstrap/server-conf-dir "/ca/signed/test_cert_with_auth_ext.pem"))))) (defn generate-inventory-entry [^Random random-generator number] (format "0x%H 2023-09-20T16:28:17UTC 2028-09-19T16:28:17UTC host-%d-name.thing.to.take.up.spaces\n" (abs (.nextInt random-generator)) number)) (deftest ^:integration certificate-inventory-file-management (testing "Validates that the certificate_status endpoint includes authorization extensions for certs and CSRs" (with-redefs [act-proto/report-activity! (fn [_ _] nil)] (let [inventory-path (str bootstrap/server-conf-dir "/ca/inventory.txt") inventory-content (if (fs/exists? inventory-path) (slurp inventory-path) "") request-dir (str bootstrap/server-conf-dir "/ca/requests") key-pair (ssl-utils/generate-key-pair) subjectDN (ssl-utils/cn "test_cert_with_auth_ext") auth-ext-short-name {:oid (:pp_auth_role ca/puppet-short-names) :critical false :value "true"} auth-ext-oid {:oid "1.3.6.1.4.1.34380.1.3.1.2" :critical false :value "true"} csr (ssl-utils/generate-certificate-request key-pair subjectDN [auth-ext-short-name auth-ext-oid]) random-generator (Random.)] (fs/mkdirs request-dir) (ssl-utils/obj->pem! csr (str request-dir "/test_cert_with_auth_ext.pem")) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-authorization-extensions true}} (testing "Adding to a very large inventory file works correctly" (spit inventory-path inventory-content) ;; internally the inventory append uses a 64K buffer, so make sure it is larger than that. (loop [hostnames (map (partial generate-inventory-entry random-generator) (range 0 10000)) hostname (first hostnames)] (when hostname (spit inventory-path hostname :append true) (recur (rest hostnames) (second hostnames)))) (let [sign-response (http-client/put (str "https://localhost:8140/" "puppet-ca/v1/certificate_status/test_cert_with_auth_ext") (cert-status-request-params "{\"desired_state\": \"signed\"}"))] (is (= 204 (:status sign-response))) ;; inventory file should have "test_cert_with_auth_ext" in it (let [new-inventory-contents (slurp inventory-path)] (is (re-find #"test_cert_with_auth_ext" new-inventory-contents))))))) (fs/delete (str bootstrap/server-conf-dir "/ca/signed/test_cert_with_auth_ext.pem"))))) (deftest csr-api-test (testutils/with-stub-puppet-conf (bootstrap/with-puppetserver-running-with-config app (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")}}) (let [request-dir (str bootstrap/server-conf-dir "/ca/requests") key-pair (ssl-utils/generate-key-pair) subjectDN (ssl-utils/cn "test_cert") csr (ssl-utils/generate-certificate-request key-pair subjectDN) csr-file (ks/temp-file "test_csr.pem") saved-csr (str request-dir "/test_cert.pem") url "https://localhost:8140/puppet-ca/v1/certificate_request/test_cert" request-opts {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :headers {"content-type" "text/plain"}} call-results (atom []) old-fn @common/action-registration-function new-fn (fn [value] (swap! call-results conj value))] (reset! common/action-registration-function new-fn) (ssl-utils/obj->pem! csr csr-file) (testing "submit a CSR via the API" (let [response (http-client/put url (merge request-opts {:body (slurp csr-file)}))] (is (= 200 (:status response))) (is (= (slurp csr-file) (slurp saved-csr))))) (testing "get a CSR from the API" (let [response (http-client/get url request-opts) csr (:body response)] (is (= 200 (:status response))) (is (= (slurp csr-file) csr)))) (testing "delete a CSR via the API" (let [response (http-client/delete url request-opts)] (is (= 204 (:status response))) (is (not (fs/exists? saved-csr))))) (fs/delete csr-file) (is (= [{:type :info :targets ["test_cert"] :meta {:what :csr :action :submit}}] @call-results)) (reset! common/action-registration-function old-fn))))) (deftest csr-api-puppet-version-test (testutils/with-stub-puppet-conf (bootstrap/with-puppetserver-running-with-config app (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")}}) (let [request-dir (str bootstrap/server-conf-dir "/ca/requests") key-pair (ssl-utils/generate-key-pair) subjectDN (ssl-utils/cn "test_version_cert") csr (ssl-utils/generate-certificate-request key-pair subjectDN) csr-file (ks/temp-file "test_version_csr.pem") saved-csr (str request-dir "/test_version_cert.pem") url "https://localhost:8140/puppet-ca/v1/certificate_request/test_version_cert" request-opts {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :headers {"content-type" "text/plain" "x-puppet-version" "8.2.0"}}] (ssl-utils/obj->pem! csr csr-file) (testing "submit a CSR via the API" (let [response (http-client/put url (merge request-opts {:body (slurp csr-file)}))] (is (= 200 (:status response))) (fs/delete csr-file))) (testing "delete a CSR via the API" (let [response (http-client/delete url request-opts)] (is (= 204 (:status response))) (is (not (fs/exists? saved-csr))))))))) (deftest csr-activity-service-cert (let [reported-activity (atom []) test-service (tk-services/service act-proto/ActivityReportingService [] (report-activity! [_this body] (swap! reported-activity conj body))) cert-path (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") key-path (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") ca-cert-path (str bootstrap/server-conf-dir "/ca/ca_crt.pem") crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")] (testutils/with-stub-puppet-conf (bootstrap/with-puppetserver-running-with-services app (concat (bootstrap/services-from-dev-bootstrap) [test-service]) (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path :ssl-crl-path crl-path}}) (let [certname "test_cert" csr (ssl-utils/generate-certificate-request (ssl-utils/generate-key-pair) (ssl-utils/cn certname)) csr-path (str bootstrap/server-conf-dir "/ca/requests/" certname ".pem") status-url (str "https://localhost:8140/puppet-ca/v1/certificate_status/" certname) request-opts {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path} requester-name (-> (ssl-utils/pem->ca-cert cert-path key-path) (ssl-utils/get-subject-from-x509-certificate) (ssl-utils/x500-name->CN))] (ssl-utils/obj->pem! csr csr-path) (testing "Sign the waiting CSR" (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json"}})) activity-events (get-in (first @reported-activity) [:commit :events]) msg-matcher (re-pattern (str "Entity " requester-name " signed 1 certificate: " certname))] (is (= 204 (:status response))) (is (re-find msg-matcher (:message (first activity-events)))) (is (= 1 (count @reported-activity))))) (testing "Revoke the cert" (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"revoked\"}" :headers {"content-type" "application/json"}})) activity-events (get-in (second @reported-activity) [:commit :events]) msg-matcher (re-pattern (str "Entity " requester-name " revoked 1 certificate: " certname))] (is (= 204 (:status response))) (is (re-find msg-matcher (:message (first activity-events)))) (is (= 2 (count @reported-activity))))) (fs/delete csr-path)))))) (deftest csr-activity-service-token (testutils/with-config-dirs {(str test-resources-dir "/infracrl_test/master/conf/ssl") (str bootstrap/server-conf-dir "/ssl") (str test-resources-dir "/infracrl_test/master/conf/ca") (str bootstrap/server-conf-dir "/ca")} (let [reported-activity (atom []) test-service (tk-services/service act-proto/ActivityReportingService [] (report-activity! [_this body] (swap! reported-activity conj body)))] (testutils/with-stub-puppet-conf (bootstrap/with-puppetserver-running-with-services app (concat (bootstrap/services-from-dev-bootstrap) [test-service dummy-rbac-service]) (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :authorization {:version 1 :rules [{:match-request {:path "/" :type "path"} :allow [{:rbac {:permission "cert_requests:accept_reject:*"}}] :sort-order 1 :name "cert"}]}}) (let [request-dir (str bootstrap/server-conf-dir "/ca/requests") key-pair (ssl-utils/generate-key-pair) certname "test_cert" subjectDN (ssl-utils/cn certname) csr (ssl-utils/generate-certificate-request key-pair subjectDN) saved-csr (str request-dir "/test_cert.pem") status-url (str "https://localhost:8140/puppet-ca/v1/certificate_status/" certname) request-opts {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem")}] (ssl-utils/obj->pem! csr saved-csr) (testing "Sign the waiting CSR" (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json" "X-Authentication" "test"}})) activity-events (get-in (first @reported-activity) [:commit :events]) msg-matcher (re-pattern (str "Entity test_user signed 1 certificate: " certname))] (is (= 204 (:status response))) (is (re-find msg-matcher (:message (first activity-events)))) (is (= 1 (count @reported-activity))))) (testing "Revoke the cert" (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"revoked\"}" :headers {"content-type" "application/json" "X-Authentication" "test"}})) activity-events (get-in (second @reported-activity) [:commit :events]) msg-matcher (re-pattern (str "Entity test_user revoked 1 certificate: " certname))] (is (= 204 (:status response))) (is (re-find msg-matcher (:message (first activity-events)))) (is (= 2 (count @reported-activity))))) (fs/delete saved-csr))))))) (deftest csr-activity-service-default (let [reported-activity (atom []) test-service (tk-services/service act-proto/ActivityReportingService [] (report-activity! [_this body] (swap! reported-activity conj body)))] (testutils/with-stub-puppet-conf (bootstrap/with-puppetserver-running-with-services app (concat (bootstrap/services-from-dev-bootstrap) [test-service]) (update-in (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:host "0.0.0.0" :port 8140}}) [:webserver] dissoc :ssl-host :ssl-port) (let [request-dir (str bootstrap/server-conf-dir "/ca/requests") key-pair (ssl-utils/generate-key-pair) certname "test_cert" subjectDN (ssl-utils/cn certname) csr (ssl-utils/generate-certificate-request key-pair subjectDN) saved-csr (str request-dir "/test_cert.pem") status-url (str "http://localhost:8140/puppet-ca/v1/certificate_status/" certname) request-opts {}] (ssl-utils/obj->pem! csr saved-csr) (testing "Sign the waiting CSR" (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json"}})) activity-events (get-in (first @reported-activity) [:commit :events]) msg-matcher (re-pattern (str "Entity CA signed 1 certificate: " certname))] (is (= 204 (:status response))) (is (re-find msg-matcher (:message (first activity-events)))) (is (= 1 (count @reported-activity))))) (testing "Revoke the cert" (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"revoked\"}" :headers {"content-type" "application/json"}})) activity-events (get-in (second @reported-activity) [:commit :events]) msg-matcher (re-pattern (str "Entity CA revoked 1 certificate: " certname))] (is (= 204 (:status response))) (is (re-find msg-matcher (:message (first activity-events)))) (is (= 2 (count @reported-activity))))) (fs/delete saved-csr)))))) (deftest ca-expirations-endpoint-test (testing "returns expiration dates for all CA certs and CRLs" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")}} (let [response (http-client/get "https://localhost:8140/puppet-ca/v1/expirations" {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :headers {"Accept" "application/json"}})] (is (= 200 (:status response))) (let [body (json/parse-string (:body response)) ca-exp (get-in body ["ca-certs" "Puppet CA: localhost"]) crl-exp (get-in body ["crls" "Puppet CA: localhost"]) formatter (time-format/formatter "YYY-MM-dd'T'HH:mm:ssz")] (is (time/after? (time-format/parse formatter ca-exp) (time/now))) (is (time/after? (time-format/parse formatter crl-exp) (time/now)))))))) (deftest update-crl-endpoint-test (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")}} (testing "valid CRL returns 200" (let [response (http-client/put "https://localhost:8140/puppet-ca/v1/certificate_revocation_list" {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :body (slurp (str bootstrap/server-conf-dir "/ssl/crl.pem"))})] (is (= 200 (:status response))))) (testing "bad data returns 400" (let [response (http-client/put "https://localhost:8140/puppet-ca/v1/certificate_revocation_list" {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :body "Bad data"})] (is (= 400 (:status response))))))) (deftest ca-bulk-signing-endpoint-test (testing "ca bulk signing endpoint " (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")}} (testing "returns 200 with valid payload" ;; note- more extensive testing of the behavior is done with the testing in sign-multiple-certificate-signing-requests!-test (let [certname (ks/rand-str :alpha-lower 16) certname-no-exist (ks/rand-str :alpha-lower 16) certname-with-bad-extension (ks/rand-str :alpha-lower 16) call-results (atom []) old-fn @common/action-registration-function new-fn (fn [value] (swap! call-results conj value)) _ (reset! common/action-registration-function new-fn) _ (generate-a-csr certname [] []) _ (generate-a-csr certname-with-bad-extension [{:oid "1.9.9.9.9.9.0" :value "true" :critical false}] []) response (http-client/post "https://localhost:8140/puppet-ca/v1/sign" {:body (json/encode {:certnames [certname certname-no-exist certname-with-bad-extension]}) :ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :headers {"Accept" "application/json"}})] (is (= 200 (:status response))) (is (= {:signed [certname] :no-csr [certname-no-exist] :signing-errors [certname-with-bad-extension]} (json/parse-string (:body response) true))) (is (= [{:type :add :targets [certname] :meta {:type :certificate}}] @call-results)) (reset! common/action-registration-function old-fn))) (testing "throws schema violation for invalid certname" (let [error-msg "{\"kind\":\"schema-violation\"" response (http-client/post "https://localhost:8140/puppet-ca/v1/sign" {:body (json/encode {:certnames [1 2 3]}) :ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :headers {"Accept" "application/json"}}) body (:body response)] (is (= 422 (:status response))) (is (.contains body error-msg))))))) (deftest ca-bulk-signing-all-endpoint-test ;; ensure the csr directory is empty as other tests leave cruft behind (delete-all-csrs) (testing "returns 200 response" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")}} (let [old-fn @common/action-registration-function call-results (atom []) new-fn (fn [value] (swap! call-results conj value))] (reset! common/action-registration-function new-fn) (testing "PE-37634 PE-sign-all with no pending certs returns 200 with expected payload" (let [response (http-client/post "https://localhost:8140/puppet-ca/v1/sign/all" {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :headers {"Accept" "application/json"}})] (is (= 200 (:status response))) (is (= {:signed [] :no-csr [] :signing-errors []} (json/parse-string (:body response) true))) (is (= [] @call-results)))) (testing "returns 200 with valid payload" ;; note- more extensive testing of the behavior is done with the testing in sign-multiple-certificate-signing-requests!-test (let [certname (ks/rand-str :alpha-lower 16) certname-with-bad-extension (ks/rand-str :alpha-lower 16) _ (generate-a-csr certname [] []) _ (generate-a-csr certname-with-bad-extension [{:oid "1.9.9.9.9.9.0" :value "true" :critical false}] []) response (http-client/post "https://localhost:8140/puppet-ca/v1/sign/all" {:ssl-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text :headers {"Accept" "application/json"}})] (is (= 200 (:status response))) (is (= {:signed [certname] ;; this would represent any files that are removed between when the set is collected, and when they are processed. :no-csr [] :signing-errors [certname-with-bad-extension]} (json/parse-string (:body response) true))) (is (= [{:type :add :targets [certname] :meta {:type :certificate}}] @call-results)))) (reset! common/action-registration-function old-fn))))) (deftest ca-certificate-renew-endpoint-test (testing "with the feature enabled" (testing "with allow-header-cert-info = false (default)" (testing "returns a 200 OK response when feature is enabled, a certificate is present in the request, and that cert matches the signing cert" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true}} (let [random-certname (ks/rand-str :alpha-lower 16) generated-cert-info (generate-and-sign-a-cert! random-certname) signed-cert-file (ks/temp-file) _ (spit signed-cert-file (:signed-cert generated-cert-info)) _ (Thread/sleep 1000) ;; ensure some time has passed so the timestamps are different response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:ssl-cert (str signed-cert-file) :ssl-key (str (:private-key generated-cert-info)) :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 200 (:status response))) (let [renewed-cert-pem (:body response) renewed-cert-file (ks/temp-file) _ (spit renewed-cert-file renewed-cert-pem) renewed-cert (ssl-utils/pem->cert renewed-cert-file) signed-cert (ssl-utils/pem->cert signed-cert-file)] (testing "serial number has been incremented" (is (< (.getSerialNumber signed-cert) (.getSerialNumber renewed-cert)))) (testing "not before time stamps have changed" (is (true? (.before (.getNotBefore signed-cert) (.getNotBefore renewed-cert))))) (testing "new not-after is earlier than before" (is (true? (.after (.getNotAfter signed-cert) (.getNotAfter renewed-cert))))) (testing "new not-after should be 89 days (and some fraction) away" (let [diff (- (.getTime (.getNotAfter renewed-cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] (is (= 89 days)))))))) (testing "Honors non-default auto-renewal-cert-ttl" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true :auto-renewal-cert-ttl "42d"}} (let [random-certname (ks/rand-str :alpha-lower 16) generated-cert-info (generate-and-sign-a-cert! random-certname) signed-cert-file (ks/temp-file) _ (spit signed-cert-file (:signed-cert generated-cert-info)) _ (Thread/sleep 1000) ;; ensure some time has passed so the timestamps are different response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:ssl-cert (str signed-cert-file) :ssl-key (str (:private-key generated-cert-info)) :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 200 (:status response))) (let [renewed-cert-pem (:body response) renewed-cert-file (ks/temp-file) _ (spit renewed-cert-file renewed-cert-pem) renewed-cert (ssl-utils/pem->cert renewed-cert-file) signed-cert (ssl-utils/pem->cert signed-cert-file)] (testing "certificates are same subject" (is (= (ssl-utils/get-subject-from-x509-certificate signed-cert) (ssl-utils/get-subject-from-x509-certificate renewed-cert)))) (testing "serial number has been incremented" (is (< (.getSerialNumber signed-cert) (.getSerialNumber renewed-cert)))) (testing "not before time stamps have changed" (is (true? (.before (.getNotBefore signed-cert) (.getNotBefore renewed-cert))))) (testing "new not-after is earlier than before" (is (true? (.after (.getNotAfter signed-cert) (.getNotAfter renewed-cert))))) (testing "new not-after should be 41 days (and some fraction) away" (let [diff (- (.getTime (.getNotAfter renewed-cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] (is (= 41 days)))))))) (testing "respects x-client-cert header when requester is in infra-nodes file" (let [infra-inventory-path (str bootstrap/server-conf-dir "/ca/infra_inventory.txt") infra-inventory-content (slurp infra-inventory-path) ;; We're going to pretend this is an infra cert for this test compiler "compiler.puppet.com"] ;; Add another cert to the infra inventory (spit infra-inventory-path (str infra-inventory-content compiler)) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true :auto-renewal-cert-ttl "42d"}} (let [generated-agent-cert-info (generate-and-sign-a-cert! "agent.puppet.com") generated-compiler-cert-info (generate-and-sign-a-cert! "compiler.puppet.com") compiler-signed-cert-file (ks/temp-file) agent-signed-cert-file (ks/temp-file) _ (spit compiler-signed-cert-file (:signed-cert generated-compiler-cert-info)) _ (spit agent-signed-cert-file (:signed-cert generated-agent-cert-info)) _ (Thread/sleep 1000) ;; ensure some time has passed so the timestamps are different response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" (ring-codec/url-encode (:signed-cert generated-agent-cert-info))} :ssl-cert (str compiler-signed-cert-file) :ssl-key (str (:private-key generated-compiler-cert-info)) :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 200 (:status response))) (let [renewed-cert-pem (:body response) renewed-cert-file (ks/temp-file) _ (spit renewed-cert-file renewed-cert-pem) renewed-cert (ssl-utils/pem->cert renewed-cert-file) signed-cert (ssl-utils/pem->cert agent-signed-cert-file)] (testing "certificates are the same agent subject" (is (= (ssl-utils/get-subject-from-x509-certificate signed-cert) (ssl-utils/get-subject-from-x509-certificate renewed-cert)))) (testing "serial number has been incremented" (is (< (.getSerialNumber signed-cert) (.getSerialNumber renewed-cert)))) (testing "not before time stamps have changed" (is (true? (.before (.getNotBefore signed-cert) (.getNotBefore renewed-cert))))) (testing "new not-after is earlier than before" (is (true? (.after (.getNotAfter signed-cert) (.getNotAfter renewed-cert))))) (testing "new not-after should be 41 days (and some fraction) away" (let [diff (- (.getTime (.getNotAfter renewed-cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] (is (= 41 days))))))) ;; restore the content of the inventory file (spit infra-inventory-path infra-inventory-content))) (testing "rejects x-client-cert header when requester revoked" (let [infra-inventory-path (str bootstrap/server-conf-dir "/ca/infra_inventory.txt") random-agent-certname (ks/rand-str :alpha-lower 16) random-compiler-certname (ks/rand-str :alpha-lower 16) infra-inventory-content (slurp infra-inventory-path)] ;; We're going to pretend this is an infra cert for this test (spit infra-inventory-path (str infra-inventory-content random-compiler-certname)) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true :auto-renewal-cert-ttl "42d"}} (let [generated-agent-cert-info (generate-and-sign-a-cert! random-agent-certname) generated-compiler-cert-info (generate-and-sign-a-cert! random-compiler-certname) compiler-signed-cert-file (ks/temp-file) agent-signed-cert-file (ks/temp-file) _ (spit compiler-signed-cert-file (:signed-cert generated-compiler-cert-info)) _ (spit agent-signed-cert-file (:signed-cert generated-agent-cert-info)) revoke-response (http-client/put (str "https://localhost:8140/puppet-ca/v1/certificate_status/" random-agent-certname) {:body "{\"desired_state\": \"revoked\"}" :ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :headers {"content-type" "application/json"}})] (is (= 204 (:status revoke-response))) (Thread/sleep 1000) ;; ensure some time has passed so the timestamps are different (let [response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" (ring-codec/url-encode (:signed-cert generated-agent-cert-info))} :ssl-cert (str compiler-signed-cert-file) :ssl-key (str (:private-key generated-compiler-cert-info)) :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 400 (:status response))) (is (= "No valid certificate found in renewal request" (:body response))) ;; restore the content of the inventory file (spit infra-inventory-path infra-inventory-content)))))) (testing "fails for x-client-cert header when requester is not in infra-nodes file" (let [infra-inventory-path (str bootstrap/server-conf-dir "/ca/infra_inventory.txt") infra-inventory-content (slurp infra-inventory-path) ;; We're going to pretend this is an infra cert for this test compiler "compiler.puppet.com"] ;; Add another cert to the infra inventory (spit infra-inventory-path (str infra-inventory-content compiler)) (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true :auto-renewal-cert-ttl "42d"}} (let [generated-agent-cert-info (generate-and-sign-a-cert! "agent.puppet.com") generated-compiler-cert-info (generate-and-sign-a-cert! "maliciousagent.puppet.com") compiler-signed-cert-file (ks/temp-file) agent-signed-cert-file (ks/temp-file) _ (spit compiler-signed-cert-file (:signed-cert generated-compiler-cert-info)) _ (spit agent-signed-cert-file (:signed-cert generated-agent-cert-info)) _ (Thread/sleep 1000) ;; ensure some time has passed so the timestamps are different response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" (ring-codec/url-encode (:signed-cert generated-agent-cert-info))} :ssl-cert (str compiler-signed-cert-file) :ssl-key (str (:private-key generated-compiler-cert-info)) :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 400 (:status response))) (is (= "No valid certificate found in renewal request" (:body response))))) ;; restore the content of the inventory file (spit infra-inventory-path infra-inventory-content))) (testing "fails for x-client-cert header when infra-nodes-file is missing" (let [infra-inventory-path (str bootstrap/server-conf-dir "/ca/infra_inventory.txt") infra-inventory-content (slurp infra-inventory-path)] (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true :auto-renewal-cert-ttl "42d"}} (io/delete-file infra-inventory-path) (let [generated-agent-cert-info (generate-and-sign-a-cert! "agent.puppet.com") generated-compiler-cert-info (generate-and-sign-a-cert! "compiler.puppet.com") compiler-signed-cert-file (ks/temp-file) agent-signed-cert-file (ks/temp-file) _ (spit compiler-signed-cert-file (:signed-cert generated-compiler-cert-info)) _ (spit agent-signed-cert-file (:signed-cert generated-agent-cert-info)) _ (Thread/sleep 1000) ;; ensure some time has passed so the timestamps are different response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" (ring-codec/url-encode (:signed-cert generated-agent-cert-info))} :ssl-cert (str compiler-signed-cert-file) :ssl-key (str (:private-key generated-compiler-cert-info)) :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 400 (:status response))) (is (= "No valid certificate found in renewal request" (:body response))))) ;; restore the content of the inventory file (spit infra-inventory-path infra-inventory-content))) (testing "returns a 400 bad request response when the ssl-client-cert is not present" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true}} (let [response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 400 (:status response))) (is (= "No valid certificate found in renewal request" (:body response)))))) (testing "returns a 400 bad request when ssl-client-cert is not present and x-client-cert is specified" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true}} (let [random-certname (ks/rand-str :alpha-lower 16) generated-cert-info (generate-and-sign-a-cert! random-certname) signed-cert-file (ks/temp-file) _ (spit signed-cert-file (:signed-cert generated-cert-info)) header-cert (ring-codec/url-encode (:signed-cert generated-cert-info)) _ (Thread/sleep 1000) response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" header-cert} :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 400 (:status response))) (is (= "No valid certificate found in renewal request" (:body response))))))) (testing "with allow-header-cert-info = true" (testing "returns a 200 OK response when the feature is enabled, a cert is supplied in header and the signing certificate matches" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true} :authorization {:allow-header-cert-info true}} (let [random-certname (ks/rand-str :alpha-lower 16) generated-cert-info (generate-and-sign-a-cert! random-certname) signed-cert-file (ks/temp-file) _ (spit signed-cert-file (:signed-cert generated-cert-info)) header-cert (ring-codec/url-encode (:signed-cert generated-cert-info)) _ (Thread/sleep 1000) response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" header-cert} :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 200 (:status response))) (let [renewed-cert-pem (:body response) renewed-cert-file (ks/temp-file) _ (spit renewed-cert-file renewed-cert-pem) renewed-cert (ssl-utils/pem->cert renewed-cert-file) signed-cert (ssl-utils/pem->cert signed-cert-file)] (testing "serial number has been incremented" (is (< (.getSerialNumber signed-cert) (.getSerialNumber renewed-cert)))) (testing "not before time stamps have changed" (is (true? (.before (.getNotBefore signed-cert) (.getNotBefore renewed-cert))))) (testing "new not-after is earlier than before" (is (true? (.after (.getNotAfter signed-cert) (.getNotAfter renewed-cert))))) (testing "new not-after should be 89 days (and some fraction) away" (let [diff (- (.getTime (.getNotAfter renewed-cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] (is (= 89 days)))))))) (testing "returns a 400 bad request response when the feature is enabled, a revoked cert is supplied in header and the signing certificate matches" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true} :authorization {:allow-header-cert-info true}} (let [random-certname (ks/rand-str :alpha-lower 16) generated-cert-info (generate-and-sign-a-cert! random-certname) signed-cert-file (ks/temp-file) _ (spit signed-cert-file (:signed-cert generated-cert-info)) ;; revoke the cert revoke-response (http-client/put (str "https://localhost:8140/puppet-ca/v1/certificate_status/" random-certname) {:body "{\"desired_state\": \"revoked\"}" :ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :headers {"content-type" "application/json"}})] (is (= 204 (:status revoke-response))) (let [header-cert (ring-codec/url-encode (:signed-cert generated-cert-info)) _ (Thread/sleep 1000) response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" header-cert} :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 400 (:status response))) (is (= "No valid certificate found in renewal request" (:body response))))))) (testing "Can revoke a renewed certificate" (testing "using certificate status" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true} :authorization {:allow-header-cert-info true}} (let [random-certname (ks/rand-str :alpha-lower 16) generated-cert-info (generate-and-sign-a-cert! random-certname) signed-cert-file (ks/temp-file) _ (spit signed-cert-file (:signed-cert generated-cert-info)) header-cert (ring-codec/url-encode (:signed-cert generated-cert-info)) _ (Thread/sleep 1000) response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" header-cert} :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 200 (:status response))) (logutils/with-test-logging (let [ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") ca-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") ca-crl (str bootstrap/server-conf-dir "/ca/ca_crl.pem") ca-cert' (ssl-utils/pem->ca-cert ca-cert ca-key) revoke-response (http-client/put (str "https://localhost:8140/puppet-ca/v1/certificate_status/" random-certname) {:body "{\"desired_state\": \"revoked\"}" :ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :headers {"content-type" "application/json"}})] (is (= 204 (:status revoke-response))) (is (ssl-utils/revoked? (ssl-utils/pem->ca-crl ca-crl ca-cert') (ssl-utils/pem->cert signed-cert-file))) (is (logged? #"Entity CA revoked 1 certificate.*" :info))))))) (testing "using clean" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true} :authorization {:allow-header-cert-info true}} (let [random-certname (ks/rand-str :alpha-lower 16) generated-cert-info (generate-and-sign-a-cert! random-certname) signed-cert-file (ks/temp-file) _ (spit signed-cert-file (:signed-cert generated-cert-info)) header-cert (ring-codec/url-encode (:signed-cert generated-cert-info)) _ (Thread/sleep 1000) response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" header-cert} :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 200 (:status response))) (logutils/with-test-logging (let [ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") ca-key (str bootstrap/server-conf-dir "/ca/ca_key.pem") ca-crl (str bootstrap/server-conf-dir "/ca/ca_crl.pem") ca-cert' (ssl-utils/pem->ca-cert ca-cert ca-key) revoke-response (http-client/put (str "https://localhost:8140/puppet-ca/v1/clean") {:body (json/encode {:certnames [random-certname]}) :ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert ca-cert :headers {"content-type" "application/json"}})] (is (= 200 (:status revoke-response))) (is (ssl-utils/revoked? (ssl-utils/pem->ca-crl ca-crl ca-cert') (ssl-utils/pem->cert signed-cert-file))) (is (logged? #"Entity CA revoked 1 certificate.*" :info)))))))) (testing "returns a 400 bad request response when the feature is enabled, and a bogus cert is supplied in the header" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true} :authorization {:allow-header-cert-info true}} (let [header-cert "abadstring" response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" header-cert} :ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 400 (:status response))) (is (= "No certs found in PEM read from x-client-cert" (:body response)))))) (testing "returns a 403 forbidden response when a certificate is present in the request, but that cert does not match the signing cert" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal true} :authorization {:allow-header-cert-info true}} (let [ca-cert (create-ca-cert "ca-nomatch" 42) ca-cert-file (ks/temp-file) _ (ssl-utils/cert->pem! (:cert ca-cert) ca-cert-file) cert-1 (simple/gen-cert "localhost" ca-cert 4 {:extensions [(ssl-utils/authority-key-identifier-options (:cert ca-cert))]}) cert-1-file (ks/temp-file) _ (ssl-utils/cert->pem! (:cert cert-1) cert-1-file) header-cert (ring-codec/url-encode (slurp cert-1-file)) private-key-file (ks/temp-file) _ (ssl-utils/key->pem! (:private-key cert-1) private-key-file) response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:headers {"x-client-cert" header-cert} :ssl-cert (str cert-1-file) :ssl-key (str private-key-file) :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 403 (:status response))) (is (= "Certificate present, but does not match signature" (:body response)))))))) (testing "with the feature disabled" (testing "returns a 404 not found response when feature is disabled" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because all of the requests are to the CA endpoints, which are implemented in Clojure." app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :ssl-crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem")} :certificate-authority {:allow-auto-renewal false}} (let [response (http-client/post "https://localhost:8140/puppet-ca/v1/certificate_renewal" {:ssl-cert (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") :ssl-key (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") :ssl-ca-cert (str bootstrap/server-conf-dir "/ca/ca_crt.pem") :as :text})] (is (= 404 (:status response)))))))) (deftest issue-2851-deleted-cert-still-in-inventory (let [cert-path (str bootstrap/server-conf-dir "/ssl/certs/localhost.pem") key-path (str bootstrap/server-conf-dir "/ssl/private_keys/localhost.pem") ca-cert-path (str bootstrap/server-conf-dir "/ca/ca_crt.pem") crl-path (str bootstrap/server-conf-dir "/ssl/crl.pem") test-service (tk-services/service act-proto/ActivityReportingService [] (report-activity! [_this body] (throw (Exception. "Foo"))))] (testing "returns expiration dates for all CA certs and CRLs" (testutils/with-stub-puppet-conf (bootstrap/with-puppetserver-running-with-services app (concat (bootstrap/services-from-dev-bootstrap) [test-service]) {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]} :webserver {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path :ssl-crl-path crl-path}} (let [certname "test_cert" csr (ssl-utils/generate-certificate-request (ssl-utils/generate-key-pair) (ssl-utils/cn certname)) csr-path (str bootstrap/server-conf-dir "/ca/requests/" certname ".pem") status-url (str "https://localhost:8140/puppet-ca/v1/certificate_status/" certname) request-opts {:ssl-cert cert-path :ssl-key key-path :ssl-ca-cert ca-cert-path}] (ssl-utils/obj->pem! csr csr-path) (testing "Sign the waiting CSR" (logutils/with-test-logging (let [response (http-client/put status-url (merge request-opts {:body "{\"desired_state\": \"signed\"}" :headers {"content-type" "application/json"}}))] (is (= 204 (:status response)))))) (testing "Delete the cert" (logutils/with-test-logging (let [response (http-client/delete status-url (merge request-opts {:headers {"content-type" "application/json" "X-Authentication" "test"}}))] (is (= 204 (:status response)))))) (testing "getting the cert returns a 404" (let [response (http-client/get status-url (merge request-opts {:headers {"content-type" "application/json" "X-Authentication" "test"}}))] (is (= 404 (:status response))))))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby/000077500000000000000000000000001470345337400275255ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby/class_info_test.clj000066400000000000000000000434531470345337400334070ustar00rootroot00000000000000(ns puppetlabs.services.jruby.class-info-test (:require [clojure.test :refer [deftest is testing]] [clojure.string :as str] [puppetlabs.kitchensink.core :as ks] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.services.jruby.puppet-environments :as puppet-env] [me.raynes.fs :as fs] [cheshire.core :as cheshire] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-bootstrap])) (defn gen-module-classes [[mod-dir manifests]] (let [manifest-dir (fs/file mod-dir "manifests") mod-name (fs/base-name mod-dir)] (ks/mkdirs! manifest-dir) (doseq [manifest manifests] (spit (fs/file manifest-dir (str manifest ".pp")) (str "class " mod-name "::" manifest "($" manifest "_a, Integer $" manifest "_b, String $" manifest "_c = 'c default value') { }\n" "class " mod-name "::" manifest "2($" manifest "2_a, Integer $" manifest "2_b, String $" manifest "2_c = 'c default value') { }\n"))))) (defn gen-classes [[env-dir manifests]] (let [manifest-dir (fs/file env-dir "manifests")] (ks/mkdirs! manifest-dir) (doseq [manifest manifests] (spit (fs/file manifest-dir (str manifest ".pp")) (str "class " manifest "($" manifest "_a, Integer $" manifest "_b, String $" manifest "_c = 'c default value') { }\n" "class " manifest "2($" manifest "2_a, Integer $" manifest "2_b, String $" manifest "2_c = 'c default value') { }\n"))))) (defn create-env [[env-dir manifests]] (testutils/create-env-conf env-dir "") (gen-classes [env-dir manifests])) (defn roundtrip-via-json [obj] (-> obj (cheshire/generate-string) (cheshire/parse-string))) (defn expected-class-info ([class-name] {"name" class-name "params" [{"name" (str class-name "_a")} {"name" (str class-name "_b"), "type" "Integer"} {"name" (str class-name "_c"), "type" "String", "default_literal" "c default value" "default_source" "'c default value'"}]}) ([mod-name class-name] {"name" (str mod-name "::" class-name) "params" [{"name" (str class-name "_a")} {"name" (str class-name "_b"), "type" "Integer"} {"name" (str class-name "_c"), "type" "String", "default_literal" "c default value" "default_source" "'c default value'"}]})) (defn expected-manifests-info [manifests] (into {} (apply concat (for [[dir names] manifests] (let [mod-name (fs/base-name dir)] (for [class-name names] [(.getAbsolutePath (fs/file dir "manifests" (str class-name ".pp"))) {"classes" (if (str/starts-with? mod-name "mod") [(expected-class-info mod-name class-name) (expected-class-info mod-name (str class-name "2"))] [(expected-class-info class-name) (expected-class-info (str class-name "2"))])}])))))) (deftest ^:integration class-info-test (testing "class info properly enumerated for" (let [code-dir (ks/temp-dir) conf-dir (ks/temp-dir) config (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:server-code-dir (.getAbsolutePath code-dir) :server-conf-dir (.getAbsolutePath conf-dir)}))] (tk-bootstrap/with-app-with-config app jruby-testutils/jruby-service-and-dependencies config (let [jruby-service (tk-app/get-service app :JRubyPuppetService) instance (jruby-testutils/borrow-instance jruby-service :test) jruby-puppet (:jruby-puppet instance) env-registry (:environment-registry instance) _ (testutils/create-file (fs/file conf-dir "puppet.conf") "[main]\nenvironment_timeout=unlimited\nbasemodulepath=$codedir/modules\n") env-dir (fn [env-name] (fs/file code-dir "environments" env-name)) env-1-dir (env-dir "env1") env-1-dir-and-manifests [env-1-dir ["foo" "bar"]] _ (create-env env-1-dir-and-manifests) env-2-dir (env-dir "env2") env-2-dir-and-manifests [env-2-dir ["baz" "bim" "boom"]] _ (create-env env-2-dir-and-manifests) env-1-mod-dir (fs/file env-1-dir "modules") env-1-mod-1-dir-and-manifests [(fs/file env-1-mod-dir "mod1env1") ["baz" "bim"]] _ (gen-module-classes env-1-mod-1-dir-and-manifests) env-1-mod-2-dir (fs/file env-1-mod-dir "mod2env1") env-1-mod-2-dir-and-manifests [env-1-mod-2-dir ["baz" "bim"]] _ (gen-module-classes env-1-mod-2-dir-and-manifests) env-3-dir-and-manifests [(env-dir "env3") ["dip" "dap" "dup"]] base-mod-dir (fs/file code-dir "modules") base-mod-1-and-manifests [(fs/file base-mod-dir "mod1envbase") ["bap"]] _ (gen-module-classes base-mod-1-and-manifests) bogus-env-dir (env-dir "bogus-env") _ (create-env [bogus-env-dir []]) _ (gen-classes [bogus-env-dir ["envbogus"]]) _ (gen-module-classes [(fs/file base-mod-dir "base-bogus") ["base-bogus1"]]) get-class-info-for-env (fn [env] (-> (.getClassInfoForEnvironment jruby-puppet env) (roundtrip-via-json)))] (try (testing "initial parse" (let [expected-envs-info {"env1" (expected-manifests-info [env-1-dir-and-manifests env-1-mod-1-dir-and-manifests env-1-mod-2-dir-and-manifests base-mod-1-and-manifests]) "env2" (expected-manifests-info [env-2-dir-and-manifests base-mod-1-and-manifests])}] (is (= (expected-envs-info "env1") (get-class-info-for-env "env1")) "Unexpected info retrieved for 'env1'") (is (= (expected-envs-info "env2") (get-class-info-for-env "env2")) "Unexpected info retrieved for 'env2'"))) (testing "changes to module and manifest paths" (testutils/create-env-conf env-1-dir (str "manifest=" (.getAbsolutePath (fs/file env-1-dir "manifests" "foo.pp")) "\nmodulepath=" (.getAbsolutePath (fs/file env-2-dir "modules")) "\n")) (testutils/create-env-conf env-2-dir (str "modulepath=" (.getAbsolutePath env-1-mod-dir) "\n")) (let [foo-manifest (.getAbsolutePath (fs/file env-1-dir "manifests" "foo.pp")) expected-envs-info {"env1" {foo-manifest {"classes" [(expected-class-info "foo") (expected-class-info "foo2")]}} "env2" (expected-manifests-info [env-2-dir-and-manifests env-1-mod-1-dir-and-manifests env-1-mod-2-dir-and-manifests])}] (puppet-env/mark-all-environments-expired! env-registry) (testing "one environment by name" (is (= (expected-envs-info "env1") (get-class-info-for-env "env1")) "Unexpected info retrieved for 'env1'") (is (= (expected-envs-info "env2") (get-class-info-for-env "env2")) "Unexpected info retrieved for 'env2'")))) (testing "changes to manifest content" (fs/delete-dir env-1-mod-2-dir) (let [foo-manifest (.getAbsolutePath (fs/file env-1-dir "manifests" "foo.pp")) _ (testutils/create-file foo-manifest "class foo () {} \n") expected-envs-info {"env1" {foo-manifest {"classes" [{"name" "foo" "params" []}]}} "env2" (expected-manifests-info [env-2-dir-and-manifests env-1-mod-1-dir-and-manifests])}] (puppet-env/mark-environment-expired! env-registry "env1") (is (= (expected-envs-info "env1") (get-class-info-for-env "env1")) "Unexpected info retrieved for 'env1'") (puppet-env/mark-environment-expired! env-registry "env2") (is (= (expected-envs-info "env2") (get-class-info-for-env "env2")) "Unexpected info retrieved for 'env2'"))) (testing "changes to environments" (fs/delete-dir env-1-dir) (let [_ (create-env env-3-dir-and-manifests) expected-envs-info {"env2" (expected-manifests-info [env-2-dir-and-manifests]) "env3" (expected-manifests-info [env-3-dir-and-manifests base-mod-1-and-manifests])}] (puppet-env/mark-all-environments-expired! env-registry) (is (nil? (get-class-info-for-env "env1")) "Unexpected info retrieved for 'env1'") (is (= (expected-envs-info "env2") (get-class-info-for-env "env2")) "Unexpected info retrieved for 'env2'") (is (= (expected-envs-info "env3") (get-class-info-for-env "env3")) "Unexpected info retrieved for 'env3'"))) (testing "non existent manifest dir for environment" (create-env [(env-dir "env4") nil]) (let [expected-envs-info {"env4" (expected-manifests-info [base-mod-1-and-manifests])}] (is (= (expected-envs-info "env4") (get-class-info-for-env "env4")) "Unexpected info retrieved for 'env4'"))) (testing "non-existent environment" (is (nil? (get-class-info-for-env "bogus-env")))) (testing "(PUP-5744) non-JSON safe default_literals omitted" (let [env-5-dir (env-dir "env5") _ (testutils/create-env-conf env-5-dir "modulepath=\n") foo-manifest (.getAbsolutePath (fs/file env-5-dir "manifests" "foo.pp"))] (testutils/create-file foo-manifest (str "class foo (\n" " Regexp $some_regex = /^.*/,\n" " Default $some_default = default,\n" " Hash $some_hash = { 1 => 2, " "\"two\" => 3},\n" " Hash $some_nested_hash = { \"one\" => 2, " "\"two\" => { 3 => 4 }},\n" " Hash $another_nested_hash = { \"one\" => 2, " "\"two\" => { \"three\" => 4 }},\n" " Array $some_array = [ 1, /^*$/ ],\n" " Array $some_nested_array = [ 1, [ 2, " "default ] ],\n" " Array $another_nested_array = [ 1, [ 2, 3 ] ]\n" "){}")) (is (= {foo-manifest {"classes" [{"name" "foo", "params" [{"default_source" "/^.*/" "name" "some_regex" "type" "Regexp"} {"default_source" "default" "name" "some_default" "type" "Default"} {"default_source" "{ 1 => 2, \"two\" => 3}" "name" "some_hash" "type" "Hash"} {"default_source" (str "{ \"one\" => 2, " "\"two\" => { 3 => 4 }}") "name" "some_nested_hash" "type" "Hash"} {"default_literal" {"one" 2 "two" {"three" 4}} "default_source" (str "{ \"one\" => 2, " "\"two\" => { \"three\"" " => 4 }}") "name" "another_nested_hash" "type" "Hash"} {"default_source" "[ 1, /^*$/ ]" "name" "some_array" "type" "Array"} {"default_source" "[ 1, [ 2, default ] ]" "name" "some_nested_array" "type" "Array"} {"default_source" "[ 1, [ 2, 3 ] ]" "default_literal" [1 [2 3]] "name" "another_nested_array" "type" "Array"}]}]}} (get-class-info-for-env "env5")) "Unexpected info retrieved for 'env5'"))) (testing (str "(PUP-5713) Default parameter value with expression " "parsed properly") (let [env-6-dir (env-dir "env6") _ (testutils/create-env-conf env-6-dir "modulepath=\n") foo-manifest (.getAbsolutePath (fs/file env-6-dir "manifests" "foo.pp"))] (testutils/create-file foo-manifest (str "class foo (\n" " String $one_literal = 'literal string',\n" " String $another_literal = \"literal string\",\n" " String $with_exp = \"for os in $::osfamily\")" "{} \n")) (is (= {foo-manifest {"classes" [{"name" "foo", "params" [{"default_literal" "literal string" "default_source" "'literal string'" "name" "one_literal" "type" "String"} {"default_literal" "literal string" "default_source" "\"literal string\"" "name" "another_literal" "type" "String"} {"default_source" "\"for os in $::osfamily\"" "name" "with_exp" "type" "String"}]}]}} (get-class-info-for-env "env6")) "Unexpected info retrieved for 'env6'"))) (finally (jruby-testutils/return-instance jruby-service instance :test)))))))) jruby_metrics_service_test.clj000066400000000000000000001400121470345337400355760ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby(ns puppetlabs.services.jruby.jruby-metrics-service-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.trapperkeeper.core :as tk] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.trapperkeeper.testutils.bootstrap :as bootstrap] [puppetlabs.trapperkeeper.testutils.logging :as logging] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.services.jruby.jruby-puppet-service :as jruby-service] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [puppetlabs.services.protocols.jruby-metrics :as jruby-metrics-protocol] [puppetlabs.services.protocols.puppet-server-config :as ps-config-protocol] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap-testutils] [schema.test :as schema-test] [puppetlabs.metrics :as metrics] [puppetlabs.http.client.sync :as http-client] [puppetlabs.comidi :as comidi] [lambdaisland.uri :as uri] [puppetlabs.testutils.task-coordinator :as coordinator] [puppetlabs.services.jruby.jruby-metrics-core :as jruby-metrics-core] [clojure.string :as str] [clojure.tools.logging :as log] [schema.core :as schema] [cheshire.core :as json]) (:import (com.puppetlabs.puppetserver JRubyPuppetResponse JRubyPuppet) (clojure.lang IFn Atom) (java.util.concurrent TimeUnit))) (use-fixtures :once schema-test/validate-schemas) (use-fixtures :each #(logging/with-test-logging (%))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Config / constants (def default-test-config (-> {:jruby-puppet {:max-active-instances 2} :metrics {:server-id "localhost"}} bootstrap-testutils/load-dev-config-with-overrides (assoc :webserver {:port 8140 :host "localhost"}))) (def request-phases [:http-handler-invoked :borrowed-jruby :returning-jruby :request-complete]) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Basic utility fns (defn http-get ([uri] (http-get uri {})) ([uri opts] (http-client/get uri (merge opts {:as :text})))) (defn timestamp-after? [start-time event-time] (let [now (System/currentTimeMillis)] (if (and (<= start-time event-time) (>= now event-time)) true (throw (IllegalStateException. (format "Timestamp seems wrong: '%s'; expected it to be between '%s' and '%s'" event-time start-time now)))))) (defn async-request ([coordinator request-id uri] (async-request coordinator request-id uri nil)) ([coordinator request-id uri phase] ;; add the request id into the url as a query param ;; for use with the coordinator (let [url (-> (str "http://localhost:8140" uri) uri/uri (uri/assoc-query :request-id request-id)) ;; our request function to pass to the coordinator ;; is just a simple HTTP GET. req-fn (fn [] (http-get (str url)))] (coordinator/initialize-task coordinator request-id req-fn phase)))) (defn sync-request [coordinator request-id uri] (async-request coordinator request-id uri :request-complete) (coordinator/final-result coordinator request-id)) (defn current-jruby-status-metrics [] (-> (str "http://localhost:8140/status/v1/" "services/jruby-metrics?level=debug") http-get :body (json/parse-string true) (get-in [:status :experimental :metrics]))) (defn jruby-status-metric-counters [jruby-status-metrics] (-> jruby-status-metrics (select-keys [:borrow-count :borrow-retry-count :borrow-timeout-count :num-free-jrubies :num-jrubies :requested-count :return-count]) (assoc :current-borrowed-instances (count (:borrowed-instances jruby-status-metrics)) :current-requested-instances (count (:requested-instances jruby-status-metrics))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Test services/mocks ;; The request handler service depends on the PuppetServerConfigService, ;; but we don't actually need any of the puppet config values, so here ;; we just create a mock services that passes through to the normal ;; TK config service to make the tests run faster. (tk/defservice mock-puppetserver-config-service ps-config-protocol/PuppetServerConfigService [[:ConfigService get-config get-in-config]] (get-config [this] (get-config)) (get-in-config [this ks] (get-in-config ks))) (schema/defn ^:always-validate comidi-handler-service :- (schema/protocol tk-services/ServiceDefinition) [coordinator :- (schema/protocol coordinator/TaskCoordinator)] (tk/service [[:WebserverService add-ring-handler] [:RequestHandlerService handle-request]] (start [this context] (let [app-request-handler (fn [request] ;; we pass the request-id as a query-param, so that ;; the comidi handler can interact with the ;; test request coordinator (let [request-id (-> (:query-string request) uri/query-string->map (get :request-id))] ;; notify the coordinator that we've begun to handle the request (coordinator/notify-task-progress coordinator request-id :http-handler-invoked) ;; delegate to the jruby request handler (let [resp (handle-request request)] ;; notify the coordinator that the request is complete (coordinator/notify-task-progress coordinator request-id :request-complete) resp))) routes (comidi/context "/foo" (comidi/routes ;; Route handler that isn't wrapped with the request ;; coordinator. (comidi/GET ["/uncoord/" :uncoord] request (handle-request request)) (comidi/GET ["/bar/" :bar] request (app-request-handler request)) (comidi/GET ["/baz/" :baz] request (app-request-handler request)))) handler (-> routes comidi/routes->handler (comidi/wrap-with-route-metadata routes))] (add-ring-handler handler "/foo")) context))) ;; here we're creating a custom jruby instance so that interacts with the ;; Coordinator, so that we have fine-grained control over how we handle the ;; incoming requests (schema/defn ^:always-validate coordinated-mock-jruby-instance [coordinator :- (schema/protocol coordinator/TaskCoordinator) config :- {schema/Keyword schema/Any}] (let [puppet-config (jruby-testutils/mock-puppet-config-settings (:jruby-puppet config))] (reify JRubyPuppet (getSetting [_this setting] (get puppet-config setting)) (handleRequest [_this request] ;; read the request-id from the query params so that we can ;; interact with the test coordinator (let [request-id (get-in request ["params" "request-id"])] ;; notify the coordinator that we've borrowed a jruby instance (when request-id (coordinator/notify-task-progress coordinator request-id :borrowed-jruby)) ;; if the request has a 'sleep' query param, sleep (when-let [sleep (get-in request ["params" "sleep"])] (log/debugf "JRuby handler: request '%s' sleeping '%s'" request-id sleep) (Thread/sleep (Long/parseLong sleep))) ;; notify coordinator that we're about to return the jruby to the pool (when request-id (coordinator/notify-task-progress coordinator request-id :returning-jruby)) (JRubyPuppetResponse. (int 200) "hi!" "text/plain" "9.0.0.0"))) (puppetVersion [_] "1.2.3") (terminate [_] (log/info "Terminating Master"))))) (def TestEnvironment {:metrics jruby-metrics-core/JRubyMetrics :sample-metrics! IFn :sampling-scheduled? Atom :coordinator (schema/protocol coordinator/TaskCoordinator) :expected-metrics-values IFn :update-expected-values IFn :current-metrics-values IFn :jruby-service (schema/protocol jruby-protocol/JRubyPuppetService)}) (schema/defn ^:always-validate build-test-env :- TestEnvironment [sampling-scheduled? :- Atom coordinator :- (schema/protocol coordinator/TaskCoordinator) app] (let [jruby-metrics-service (tk-app/get-service app :JRubyMetricsService) {:keys [num-jrubies num-free-jrubies requested-count borrow-count borrow-timeout-count borrow-retry-count return-count borrowed-instances requested-instances] :as metrics} (jruby-metrics-protocol/get-metrics jruby-metrics-service) jruby-service (tk-app/get-service app :JRubyPuppetService) sample-metrics! #(jruby-metrics-core/sample-jruby-metrics! jruby-service metrics) ;; an atom to track the expected values for the basic metrics, so ;; that we don't have to keep track of the latest counts by hand ;; in all of the tests expected-values-atom (atom {:num-jrubies 2 :num-free-jrubies 2 :requested-count 0 :borrow-count 0 :borrow-timeout-count 0 :borrow-retry-count 0 :return-count 0 :current-requested-instances 0 :current-borrowed-instances 0}) ;; convenience functions to use for comparing current metrics ;; values with expected values. current-metrics-values (fn [] {:num-jrubies (.getValue num-jrubies) :num-free-jrubies (.getValue num-free-jrubies) :requested-count (.getCount requested-count) :borrow-count (.getCount borrow-count) :borrow-timeout-count (.getCount borrow-timeout-count) :borrow-retry-count (.getCount borrow-retry-count) :return-count (.getCount return-count) :current-requested-instances (count @requested-instances) :current-borrowed-instances (count @borrowed-instances)}) update-expected-values (fn [deltas] (reset! expected-values-atom (reduce (fn [acc [k delta]] (update-in acc [k] + delta)) @expected-values-atom deltas))) expected-metrics-values (fn [] @expected-values-atom)] {:metrics metrics :sample-metrics! sample-metrics! :sampling-scheduled? sampling-scheduled? :coordinator coordinator :expected-metrics-values expected-metrics-values :update-expected-values update-expected-values :current-metrics-values current-metrics-values :jruby-service jruby-service})) (defmacro with-metrics-test-env [test-env-var-name config & body] `(let [coordinator# (coordinator/task-coordinator request-phases) ;; we will stub out the call that would normal schedule a recurring ;; job to take samples of the metrics, so that we have control over ;; when the sampling occurs. Otherwise these tests would be very racy. sampling-scheduled?# (atom false) mock-schedule-metrics-sampler# (fn [_# _# _#] (reset! sampling-scheduled?# true))] (with-redefs [puppetlabs.services.jruby.jruby-metrics-core/schedule-metrics-sampler! mock-schedule-metrics-sampler# puppetlabs.trapperkeeper.services.protocols.scheduler/stop-job (constantly true)] (bootstrap/with-app-with-config app# (jruby-testutils/add-mock-jruby-pool-manager-service (conj (bootstrap-testutils/services-from-dev-bootstrap) (comidi-handler-service coordinator#)) ~config (partial coordinated-mock-jruby-instance coordinator#)) ~config (let [~test-env-var-name (build-test-env sampling-scheduled?# coordinator# app#)] ~@body))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Tests (deftest ^:metrics basic-metrics-test (with-metrics-test-env test-env default-test-config (let [{:keys [num-jrubies num-free-jrubies requested-count requested-jrubies-histo borrow-count borrow-timeout-count borrow-retry-count return-count free-jrubies-histo borrow-timer wait-timer requested-instances borrowed-instances]} (:metrics test-env) {:keys [update-expected-values current-metrics-values expected-metrics-values coordinator]} test-env] (testing "initial metrics values" (is (= 2 (.getValue num-jrubies))) (is (= 2 (.getValue num-free-jrubies))) (is (= 0 (.getCount requested-count))) (is (= 0.0 (metrics/mean requested-jrubies-histo))) (is (= 0 (.getCount borrow-count))) (is (= 0 (.getCount borrow-timeout-count))) (is (= 0 (.getCount borrow-retry-count))) (is (= 0 (.getCount return-count))) (is (= 0.0 (metrics/mean free-jrubies-histo))) (is (= 0 (metrics/mean-millis borrow-timer))) (is (= 0 (metrics/mean-millis wait-timer))) (is (= 0 (count @requested-instances))) (is (= 0 (count @borrowed-instances)))) (testing "basic metrics values: happy-path" (sync-request coordinator 1 "/foo/bar/req1") (sync-request coordinator 2 "/foo/baz/req2") (update-expected-values {:requested-count 2 :borrow-count 2 :return-count 2}) (let [expected-metrics (expected-metrics-values)] (is (= expected-metrics (current-metrics-values))) (is (= expected-metrics (-> (current-jruby-status-metrics) (jruby-status-metric-counters))))))))) (deftest ^:metrics borrowed-instances-test (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator update-expected-values expected-metrics-values current-metrics-values jruby-service]} test-env {:keys [borrowed-instances]} (:metrics test-env) start-time (System/currentTimeMillis)] (testing "introspect reasons for borrowed instances" (async-request coordinator 1 "/foo/bar/async1" :returning-jruby) (async-request coordinator 2 "/foo/baz/async2" :returning-jruby) ;; when we get here we should have two active requests blocked, so ;; we can check out some of those metrics. (update-expected-values {:num-free-jrubies -2 :requested-count 2 :borrow-count 2 :current-borrowed-instances 2}) (let [expected-metrics (expected-metrics-values) jruby-status-metrics (current-jruby-status-metrics)] (is (= expected-metrics (current-metrics-values))) (is (= expected-metrics (-> (current-jruby-status-metrics) (jruby-status-metric-counters)))) ;; let's take a peek at the info about the borrowed instances. (let [expected-uris #{"/foo/bar/async1" "/foo/baz/async2"} actual-uris #(set (map (fn [instance] (get-in instance [:reason :request :uri])) %))] (is (= expected-uris (actual-uris (vals @borrowed-instances)))) (is (= expected-uris (actual-uris (:borrowed-instances jruby-status-metrics))))) (let [expected-routes #{"foo-baz-:baz" "foo-bar-:bar"} actual-routes #(set (map (fn [instance] (get-in instance %1)) %2))] (is (= expected-routes (actual-routes [:reason :request :route-info :route-id] (vals @borrowed-instances)))) (is (= expected-routes (actual-routes [:reason :request :route-id] (:borrowed-instances jruby-status-metrics))))) (doseq [borrowed (vals @borrowed-instances)] (is (= :get (get-in borrowed [:reason :request :request-method]))) (is (timestamp-after? start-time (:time borrowed)))) (doseq [borrowed (:borrowed-instances jruby-status-metrics)] (is (= "get" (get-in borrowed [:reason :request :request-method]))) (is (timestamp-after? start-time (:time borrowed))))) ;; unblock both of our requests (coordinator/final-result coordinator 1) (coordinator/final-result coordinator 2) ;; validate that the metrics are updated after the unblocks (update-expected-values {:num-free-jrubies 2 :return-count 2 :current-borrowed-instances -2}) (is (= (expected-metrics-values) (current-metrics-values)))) (testing "introspect borrows that did not come from an http request" ;; borrow an instance manually (rather than via an HTTP request) (let [instance (jruby-testutils/borrow-instance jruby-service :metrics-manual-borrow-test)] (update-expected-values {:num-free-jrubies -1 :requested-count 1 :borrow-count 1 :current-borrowed-instances 1}) (is (= (expected-metrics-values) (current-metrics-values))) ;; validate that the metrics show info about the borrowed instance (let [borrowed (first (vals @borrowed-instances))] (is (timestamp-after? start-time (:time borrowed))) (is (= :metrics-manual-borrow-test (:reason borrowed)))) (jruby-testutils/return-instance jruby-service instance :metrics-manual-borrow-test)) (update-expected-values {:num-free-jrubies 1 :return-count 1 :current-borrowed-instances -1}) (is (= (expected-metrics-values) (current-metrics-values))))))) (deftest ^:metrics requested-instances-test (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator update-expected-values expected-metrics-values current-metrics-values jruby-service]} test-env {:keys [requested-count requested-instances borrowed-instances]} (:metrics test-env) start-time (System/currentTimeMillis)] (testing "introspect reasons for requested instances" ;; this test is about validating that requests that are stuck ;; waiting for a jruby instance from an empty pool show up in ;; the metrics. ;; ;; first we'll queue up a few requests to consume the 2 jruby instances (async-request coordinator 1 "/foo/bar/async1" :returning-jruby) (async-request coordinator 2 "/foo/baz/async2" :returning-jruby) (update-expected-values {:num-free-jrubies -2 :requested-count 2 :borrow-count 2 :current-borrowed-instances 2}) (let [expected-metrics (expected-metrics-values)] (is (= expected-metrics (current-metrics-values))) (is (= expected-metrics (-> (current-jruby-status-metrics) (jruby-status-metric-counters))))) ;; now we'll create a few more requests and tell them they may ;; try to proceed to the :borrowed-jruby phase; they won't ;; be able to get there, because the pool is empty, so we won't ;; block waiting for them. (async-request coordinator 3 "/foo/bar/async3") (coordinator/unblock-task-to coordinator 3 :borrowed-jruby) (async-request coordinator 4 "/foo/baz/async4") (coordinator/unblock-task-to coordinator 4 :borrowed-jruby) ;; wait for requests 3 and 4 to progress to their attempts to ;; borrow jrubies (let [expected-requested-count (+ 2 (:requested-count (expected-metrics-values)))] (while (> expected-requested-count (.getCount requested-count)))) (update-expected-values {:requested-count 2 :current-requested-instances 2}) (let [expected-metrics (expected-metrics-values) jruby-status-metrics (current-jruby-status-metrics)] (is (= expected-metrics (current-metrics-values))) (is (= expected-metrics (-> (current-jruby-status-metrics) (jruby-status-metric-counters)))) ;; now, make sure we can see info about requests 3 and 4 in the ;; metrics (let [expected-uris #{"/foo/bar/async3" "/foo/baz/async4"} actual-uris #(set (map (fn [instance] (get-in instance [:reason :request :uri])) %))] (is (= expected-uris (actual-uris (vals @requested-instances))))) (let [expected-routes #{"foo-baz-:baz" "foo-bar-:bar"} actual-routes #(set (map (fn [instance] (get-in instance %1)) %2))] (is (= expected-routes (actual-routes [:reason :request :route-info :route-id] (vals @requested-instances)))) (is (= expected-routes (actual-routes [:reason :request :route-id] (:requested-instances jruby-status-metrics))))) (doseq [borrowed (vals @requested-instances)] (is (= :get (get-in borrowed [:reason :request :request-method]))) (is (timestamp-after? start-time (:time borrowed)))) (doseq [borrowed (:requested-instances jruby-status-metrics)] (is (= "get" (get-in borrowed [:reason :request :request-method]))) (is (timestamp-after? start-time (:time borrowed))))) ;; finish the first two requests (coordinator/final-result coordinator 1) (coordinator/final-result coordinator 2) ;; make sure requests 3 and 4 have successfully borrowed (coordinator/wait-for-task coordinator 3 :borrowed-jruby) (coordinator/wait-for-task coordinator 4 :borrowed-jruby) (update-expected-values {:return-count 2 :borrow-count 2 :current-requested-instances -2}) (is (= (expected-metrics-values) (current-metrics-values))) ;; finish 3 and 4 (coordinator/final-result coordinator 3) (coordinator/final-result coordinator 4) (update-expected-values {:num-free-jrubies 2 :return-count 2 :current-borrowed-instances -2}) (is (= (expected-metrics-values) (current-metrics-values)))) (testing "introspect requested instances that did not come from an http request" ;; this test is about validating that borrow attempts, which ;; did not originate from an HTTP request, but are stuck ;; waiting for a jruby instance from an empty pool show up in ;; the metrics. ;; first we'll queue up a few requests to consume the 2 jruby instances (async-request coordinator 1 "/foo/bar/async1" :borrowed-jruby) (async-request coordinator 2 "/foo/baz/async2" :borrowed-jruby) (update-expected-values {:num-free-jrubies -2 :requested-count 2 :borrow-count 2 :current-borrowed-instances 2}) (is (= (expected-metrics-values) (current-metrics-values))) ;; manually borrow an instance, but do it on another thread because ;; we know it will block right now due to the empty pool (let [instance-borrowed (promise) return-instance (promise) pool-worker (future (let [instance (jruby-testutils/borrow-instance jruby-service :metrics-manual-borrow-test2)] (deliver instance-borrowed instance) @return-instance (jruby-testutils/return-instance jruby-service instance :metrics-manual-borrow-test2))) expected-request-count (inc (:requested-count (expected-metrics-values)))] ;; wait for manual borrow attempt to register as a requested instance (while (> expected-request-count (.getCount requested-count))) (update-expected-values {:requested-count 1 :current-requested-instances 1}) (is (= (expected-metrics-values) (current-metrics-values))) ;; validate that we can see it in the metrics (let [requested (first (vals @requested-instances))] (is (timestamp-after? start-time (:time requested))) (is (= :metrics-manual-borrow-test2 (:reason requested)))) (coordinator/final-result coordinator 1) (coordinator/final-result coordinator 2) @instance-borrowed (update-expected-values {:num-free-jrubies 1 :return-count 2 :borrow-count 1 :current-borrowed-instances -1 :current-requested-instances -1}) (is (= (expected-metrics-values) (current-metrics-values))) (let [borrowed (first (vals @borrowed-instances))] (is (timestamp-after? start-time (:time borrowed))) (is (= :metrics-manual-borrow-test2 (:reason borrowed)))) (deliver return-instance true) @pool-worker) (update-expected-values {:num-free-jrubies 1 :return-count 1 :current-borrowed-instances -1}) (is (= (expected-metrics-values) (current-metrics-values))))))) (deftest ^:metrics timers-test (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator sampling-scheduled? sample-metrics! expected-metrics-values update-expected-values current-metrics-values]} test-env {:keys [requested-jrubies-histo free-jrubies-histo borrow-timer wait-timer requested-count num-free-jrubies]} (:metrics test-env)] (testing "borrow/wait timers, histograms and sampling" ;; under normal circumstances, we'd be taking samples for the ;; histogram metrics at a scheduled interval. However, for the ;; purposes of testing, we mocked that out so that we can ;; trigger the sampling explicitly. ;; ;; first we should double-check that the sampler *would* have ;; been scheduled if it hadn't been mocked out. (testing "metrics sampling is scheduled" (is (true? @sampling-scheduled?))) ;; now let's just validate that we know what our starting values ;; are. (is (= 0.0 (metrics/mean requested-jrubies-histo))) (is (= 0.0 (metrics/mean free-jrubies-histo))) (is (= 0 (metrics/mean-millis borrow-timer))) (is (= 0 (metrics/mean-millis wait-timer))) (testing "wait timer increases under load" ;; we're going to run a bunch of requests that sleep for 10 ;; millis each, and take a sample after we unblock each one. ;; the samples should all be increasing. (let [samples (atom []) done? (promise) create-requests (fn [] (doseq [request-id (range 10)] (async-request coordinator request-id "/foo/bar/foo?sleep=10") ;; allow each request to proceed as far as borrowing ;; a jruby, but don't wait for them. (most ;; of them will be blocked because the pool ;; will be empty.) (coordinator/unblock-task-to coordinator request-id :borrowed-jruby))) run-request-and-take-sample (fn [request-id _phase] ;; block until the request has borrowed a jruby; we need ;; to do this since we told them they were unblocked to ;; that point. (coordinator/wait-for-task coordinator request-id :borrowed-jruby) (let [current-wait-time (metrics/mean-millis wait-timer)] ;; now we know the request is blocked at the :borrowed-jruby phase. ;; sleep for a few ms longer than the current wait time, to make sure ;; that the other queued requests show a noticeable difference in their ;; borrow time. (Thread/sleep (+ current-wait-time 10))) ;; and now we can advance it to the end. (coordinator/final-result coordinator request-id) ;; take a sample and add it to the samples atom (sample-metrics!) (swap! samples conj (metrics/mean-millis wait-timer)) ;; check to see if all of the requests are done (when (= 10 (count @samples)) (deliver done? true)))] (create-requests) ;; block until all of the requests have reached the point ;; where they either have a jruby or are blocked in an ;; attempt to take one from the empty pool. (let [expected-requested-count (+ 10 (:requested-count (expected-metrics-values)))] (while (> expected-requested-count (.getCount requested-count)))) ;; add callbacks that get fired when each request reaches ;; the :borrowed-jruby phase (doseq [request-id (range 10)] (coordinator/callback-at-phase coordinator request-id :borrowed-jruby run-request-and-take-sample)) ;; block until all requests are completed @done? ;; we drop the first two samples because those came from the ;; first two jrubies borrowed, so, should have had basically zero ;; wait time. All subsequent requests will have ;; been queued and blocked waiting for a jruby together, ;; so the wait times should be increasing for each request. (let [relevant-samples (drop 2 @samples)] ;; To validate that the samples are all increasing, we can just ;; compare it to a sorted version of itself (is (= (sort relevant-samples) relevant-samples))) (update-expected-values {:requested-count 10 :borrow-count 10 :return-count 10}) (is (= (expected-metrics-values) (current-metrics-values))))) (testing "free-jrubies histo increases when no instances are borrowed" ;; validate that all the jrubies are free (is (= 2 (.getValue num-free-jrubies))) (let [initial-value (metrics/mean free-jrubies-histo)] ;; take 10 samples; no jrubies are in use, so the average ;; should increase with each sample. (let [samples (for [_ (range 10)] (do (sample-metrics!) (metrics/mean free-jrubies-histo)))] (is (= (sort samples) samples))) (is (< initial-value (metrics/mean free-jrubies-histo)))) (is (= (expected-metrics-values) (current-metrics-values)))) (testing "requested-jrubies histo decreases when requests are not queued" (let [initial-value (metrics/mean requested-jrubies-histo)] ;; take 10 samples; the average should increase with each sample. (let [samples (for [_ (range 10)] (do (sample-metrics!) (metrics/mean requested-jrubies-histo)))] (is (= (reverse (sort samples)) samples))) (is (> initial-value (metrics/mean requested-jrubies-histo)))) (is (= (expected-metrics-values) (current-metrics-values))))))) (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator sample-metrics! expected-metrics-values update-expected-values current-metrics-values]} test-env {:keys [requested-jrubies-histo requested-count]} (:metrics test-env)] (testing "requested-jrubies histo increases when requests are queued" ;; take a sample to ensure that the requested-jrubies-histo is updated (sample-metrics!) (is (= 0.0 (metrics/mean requested-jrubies-histo))) ;; get ourselves to a state where two jrubies instance requests are queued (async-request coordinator 1 "/foo/bar/req" :borrowed-jruby) (async-request coordinator 2 "/foo/bar/req" :borrowed-jruby) ;; the next two requests won't be able to make it all the way to ;; ':borrowed-jruby', because the pool is empty, so we won't ;; block waiting for them to get there. (async-request coordinator 3 "/foo/bar/req") (coordinator/unblock-task-to coordinator 3 :borrowed-jruby) (async-request coordinator 4 "/foo/bar/req") (coordinator/unblock-task-to coordinator 4 :borrowed-jruby) ;; wait until all of the jrubies have been requested so we know ;; that requests 3 and 4 are blocked trying to take a jruby ;; from the pool (let [expected-requested-count (+ 4 (:requested-count (expected-metrics-values)))] (while (> expected-requested-count (.getCount requested-count)))) ;; ok, now we have two jruby instance requests pending. ;; take some samples and validate that the histogram is ;; increasing. (let [initial-value (metrics/mean requested-jrubies-histo)] (let [samples (for [_ (range 10)] (do (sample-metrics!) (metrics/mean requested-jrubies-histo)))] (is (= (sort samples) samples))) (is (< initial-value (metrics/mean requested-jrubies-histo)))) ;; finish up the requests (coordinator/final-result coordinator 1) (coordinator/final-result coordinator 2) (coordinator/wait-for-task coordinator 3 :borrowed-jruby) (coordinator/wait-for-task coordinator 4 :borrowed-jruby) (coordinator/final-result coordinator 3) (coordinator/final-result coordinator 4) (update-expected-values {:requested-count 4 :borrow-count 4 :return-count 4}) (is (= (expected-metrics-values) (current-metrics-values)))))) (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator sample-metrics! expected-metrics-values update-expected-values current-metrics-values]} test-env {:keys [free-jrubies-histo num-free-jrubies]} (:metrics test-env)] (testing "free-jrubies histo decreases when instances are borrowed" ;; take a sample to ensure that the free-jrubies-histo is updated (sample-metrics!) (let [initial-value (metrics/mean free-jrubies-histo)] (is (= 2.0 initial-value)) ;; borrow two instances so we know that there are no free jrubies (async-request coordinator 1 "/foo/bar/req" :borrowed-jruby) (async-request coordinator 2 "/foo/bar/req" :borrowed-jruby) (is (= 0 (.getValue num-free-jrubies))) ;; take 10 samples; the average should decrease with each sample. (let [samples (for [_ (range 10)] (do (sample-metrics!) (metrics/mean free-jrubies-histo)))] (is (= (reverse (sort samples)) samples))) (is (> initial-value (metrics/mean free-jrubies-histo))) ;; free up our blocked requests (coordinator/final-result coordinator 1) (coordinator/final-result coordinator 2)) (update-expected-values {:requested-count 2 :borrow-count 2 :return-count 2}) (is (= (expected-metrics-values) (current-metrics-values)))))) (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator sample-metrics! expected-metrics-values update-expected-values current-metrics-values]} test-env {:keys [wait-timer num-free-jrubies]} (:metrics test-env)] (testing "wait timer decreases when not under load" ;; set the wait timer to an artificially super-high value so that we ;; can be reasonably assured that subsequent borrows will reduce the mean (.update wait-timer 1 TimeUnit/HOURS) ;; make sure there are no jrubies in use, so we know that there ;; should be no wait times. (is (= 2 (.getValue num-free-jrubies))) (let [start-wait-time (metrics/mean-millis wait-timer)] (dotimes [request-id 10] (let [last-wait-time (metrics/mean-millis wait-timer)] ;; make a request (should have zero wait time) (sync-request coordinator request-id "/foo/bar/req") ;; take a sample and confirm that the mean wait time has decreased (sample-metrics!) (is (>= last-wait-time (metrics/mean-millis wait-timer))))) (is (> start-wait-time (metrics/mean-millis wait-timer)))) (update-expected-values {:requested-count 10 :borrow-count 10 :return-count 10}) (is (= (expected-metrics-values) (current-metrics-values)))))) (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator sample-metrics! expected-metrics-values update-expected-values current-metrics-values]} test-env {:keys [borrow-timer]} (:metrics test-env)] (testing "borrow timer increases when requests are slower" (dotimes [request-id 10] (let [last-borrow-time (metrics/mean-millis borrow-timer) longer-borrow-time (+ 50 last-borrow-time)] (sync-request coordinator request-id (format "/foo/bar/req?sleep=%s" longer-borrow-time)) ;; sample and validate that the borrow time has increased (sample-metrics!) (let [new-borrow-time (metrics/mean-millis borrow-timer)] (is (<= last-borrow-time new-borrow-time) (format (str "Borrow time did not increase! " "last-borrow-time: '%s', longer-borrow-time: '%s', " "new-borrow-time: '%s'") last-borrow-time longer-borrow-time new-borrow-time))))) (update-expected-values {:requested-count 10 :borrow-count 10 :return-count 10}) (is (= (expected-metrics-values) (current-metrics-values)))))) (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator sample-metrics! expected-metrics-values update-expected-values current-metrics-values]} test-env {:keys [borrow-timer]} (:metrics test-env)] (testing "borrow timer decreases when requests are faster" ;; set the borrow timer to an artificially super-high value so that we ;; can be reasonably assured that subsequent borrows will reduce the mean (.update borrow-timer 1 TimeUnit/HOURS) (let [start-borrow-time (metrics/mean-millis borrow-timer)] ;; make some requests with no sleep (dotimes [request-id 10] (let [last-borrow-time (metrics/mean-millis borrow-timer)] (sync-request coordinator request-id "/foo/bar/req") ;; sample and validate that the borrow time has decreased (sample-metrics!) (is (>= last-borrow-time (metrics/mean-millis borrow-timer))))) (is (> start-borrow-time (metrics/mean-millis borrow-timer)))) (update-expected-values {:requested-count 10 :borrow-count 10 :return-count 10}) (is (= (expected-metrics-values) (current-metrics-values)))))) (with-metrics-test-env test-env default-test-config (let [{:keys [coordinator jruby-service metrics]} test-env] (testing "borrow times are tracked for each comidi route" (async-request coordinator 1 "/foo/bar/async1" :request-complete) (async-request coordinator 2 "/foo/baz/async2" :request-complete) (coordinator/final-result coordinator 1) (coordinator/final-result coordinator 2) (let [timers (jruby-metrics-core/borrow-timers metrics)] (doseq [timer-name ["foo-bar-bar" "foo-baz-baz"] :let [[_ timer] (some (fn [[k v]] (when (str/ends-with? k timer-name) [k v])) timers)]] (is (some? timer) (str "Timer exists for borrow reason: " timer-name)) (is (= 1 (.getCount timer)) (str "Timer has a accumulated a count for borrow reason: " timer-name))))) (testing "borrow times are tracked when keywords are given as a request reason" (let [namespaced-kwd ::bar-reason test-namespace (namespace ::bar-reason)] (jruby-service/with-jruby-puppet jruby-instance jruby-service :foo-reason true) (jruby-service/with-jruby-puppet jruby-instance jruby-service namespaced-kwd true) (let [timers (jruby-metrics-core/borrow-timers metrics)] (doseq [timer-name ["foo-reason" (str test-namespace ".bar-reason")] :let [[_ timer] (some (fn [[k v]] (when (str/ends-with? k timer-name) [k v])) timers)]] (is (some? timer) (str "Timer exists for borrow reason: " timer-name)) (is (= 1 (.getCount timer)) (str "Timer has a accumulated a count for borrow reason: " timer-name))))))))) (deftest ^:metrics borrow-timeout-test (with-metrics-test-env test-env (assoc-in default-test-config ;;; set the borrow timeout to a low value so that we can test ;;; timeout handling without making the test too slow [:jruby-puppet :borrow-timeout] 1000) (let [{:keys [coordinator update-expected-values expected-metrics-values current-metrics-values jruby-service]} test-env] (testing "borrow timeout" ;; first we'll queue up a few requests to consume the 2 jruby instances (async-request coordinator 1 "/foo/bar/async1" :returning-jruby) (async-request coordinator 2 "/foo/baz/async2" :returning-jruby) (update-expected-values {:num-free-jrubies -2 :requested-count 2 :borrow-count 2 :current-borrowed-instances 2}) (is (= (expected-metrics-values) (current-metrics-values))) ;; now attempt a manual borrow and allow it to timeout (let [borrow-result (jruby-testutils/borrow-instance jruby-service :introspect-manual-borrow-test2)] (is (nil? borrow-result))) (update-expected-values {:requested-count 1 :borrow-timeout-count 1}) (is (= (expected-metrics-values) (current-metrics-values))) (coordinator/final-result coordinator 1) (coordinator/final-result coordinator 2) (update-expected-values {:num-free-jrubies 2 :return-count 2 :current-borrowed-instances -2}) (is (= (expected-metrics-values) (current-metrics-values))))))) (deftest request-queue-limit (with-metrics-test-env test-env (-> default-test-config (assoc-in [:jruby-puppet :max-active-instances] 2) (assoc-in [:jruby-puppet :max-queued-requests] 2)) (let [{:keys [coordinator]} test-env {:keys [requested-count queue-limit-hit-meter]} (:metrics test-env)] (logging/with-test-logging ;; Block up two JRuby instances (async-request coordinator 1 "/foo/bar/async1" :returning-jruby) (async-request coordinator 2 "/foo/bar/async2" :returning-jruby) ;; Create two pending requests (async-request coordinator 3 "/foo/bar/async3") (async-request coordinator 4 "/foo/bar/async4") (coordinator/unblock-task-to coordinator 3 :borrowed-jruby) (coordinator/unblock-task-to coordinator 4 :borrowed-jruby) ; Wait for coordinated requests to hit metrics. (while (> 4 (.getCount requested-count))) (let [new-agent (future (http-get "http://127.0.0.1:8140/foo/uncoord/sync1" {:headers {"X-Puppet-Version" "5.5.0"}})) old-agent (future (http-get "http://127.0.0.1:8140/foo/uncoord/sync2" {:headers {"X-Puppet-Version" "4.10"}})) not-agent (future (http-get "http://127.0.0.1:8140/foo/uncoord/sync3")) silly-agent (future (http-get "http://127.0.0.1:8140/foo/uncoord/sync4" {:headers {"X-Puppet-Version" "6.majestik.møøse"}}))] (testing "denies requests from agents newer than 5.3.1 when rate limit hit" (is (= 503 (:status @new-agent))) (is (<= 0 (-> @new-agent (get-in [:headers "retry-after"]) Integer/parseInt) 1800)) (is (= "close" (get-in @new-agent [:headers "connection"])))) ;; Unblock all async requests (doseq [i (range 1 5)] (coordinator/final-result coordinator i)) (testing "allows requests from old or unknown agents when rate limit hit" (doseq [response (map deref [old-agent not-agent silly-agent])] (is (= 200 (:status response)))))) (is (logged? #"The number of requests waiting for a JRuby instance has exceeded the limit" :error)) ;; Assert that one instance of the rate limit being applied was ;; recorded to metrics. (is (= 1 (.getCount queue-limit-hit-meter))))))) jruby_puppet_pool_int_test.clj000066400000000000000000001051341470345337400356360ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby(ns puppetlabs.services.jruby.jruby-puppet-pool-int-test (:require [clojure.test :refer [are deftest is testing use-fixtures]] [clojure.java.io :as io] [clojure.set :as set] [clojure.tools.logging :as log] [me.raynes.fs :as fs] [schema.test :as schema-test] [puppetlabs.http.client.metrics :as metrics] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.kitchensink.testutils :as ks-testutils] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.puppetserver.testutils :as testutils :refer [ssl-request-options]] [puppetlabs.services.config.puppet-server-config-service :as ps-config] [puppetlabs.services.jruby.jruby-metrics-service :as jruby-metrics-service] [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.services.jruby-pool-manager.impl.jruby-agents :as jruby-agents] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [puppetlabs.services.protocols.request-handler :as handler] [puppetlabs.services.request-handler.request-handler-core :as handler-core] [puppetlabs.services.request-handler.request-handler-service :as handler-service] [puppetlabs.services.versioned-code-service.versioned-code-service :as vcs] [puppetlabs.ssl-utils.core :as ssl-utils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.config :as tk-config] [puppetlabs.trapperkeeper.core :as tk] [puppetlabs.trapperkeeper.internal :as tk-internal] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.trapperkeeper.services.protocols.metrics :as metrics-protocol] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-testutils] [puppetlabs.trapperkeeper.testutils.logging :as logutils]) (:import (com.codahale.metrics MetricRegistry) (java.io ByteArrayOutputStream) (org.jruby RubyInstanceConfig$CompileMode RubyInstanceConfig$ProfilingMode) (org.jruby.embed EvalFailedException))) (def test-resources-dir "./dev-resources/puppetlabs/services/jruby/jruby_pool_int_test") (use-fixtures :once schema-test/validate-schemas (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utilities (def default-borrow-timeout 300000) (def gem-path [(ks/absolute-path jruby-testutils/gem-path)]) (defn timed-deref [ref] (deref ref 240000 :timed-out)) (defn get-stack-trace-for-thread-as-str [stack-trace-elements] (reduce (fn [acc stack-trace-element] (str acc " " (.getClassName stack-trace-element) "." (.getMethodName stack-trace-element) "(" (.getFileName stack-trace-element) ":" (.getLineNumber stack-trace-element) ")" "\n")) "" stack-trace-elements)) (defn get-all-stack-traces-as-str [] (reduce (fn [acc thread-stack-element] (let [thread (key thread-stack-element)] (str acc "\"" (.getName thread) "\" id=" (.getId thread) " state=" (.getState thread) "\n" (get-stack-trace-for-thread-as-str (val thread-stack-element))))) "" (Thread/getAllStackTraces))) (def script-to-check-if-constant-is-defined "! $instance_id.nil?") (defn add-watch-for-flush-complete [pool-context] (let [flush-complete (promise)] (add-watch (get-in pool-context [:internal :modify-instance-agent]) :flush-callback (fn [k a _old-state _new-state] (when (= k :flush-callback) (remove-watch a :flush-callback) (deliver flush-complete true)))) flush-complete)) (defn add-watch-for-flush-complete-multithreaded [pool-context] (let [flush-complete (promise)] (add-watch (:borrow-count pool-context) :flush-callback (fn [k a old-count new-count] (when (and (= k :flush-callback ) (< new-count old-count)) (remove-watch a :flush-callback) (deliver flush-complete true)))) flush-complete)) (defn set-constants-and-verify [pool-context num-instances] ;; here we set a variable called 'instance_id' in each instance (jruby-testutils/reduce-over-jrubies! pool-context num-instances #(format "$instance_id = %s" %)) ;; and validate that we can read that value back from each instance (= (set (range num-instances)) (-> (jruby-testutils/reduce-over-jrubies! pool-context num-instances (constantly "$instance_id")) set))) (defn constant-defined? [jruby-instance] (let [sc (:scripting-container jruby-instance)] (.runScriptlet sc script-to-check-if-constant-is-defined))) (defn check-all-jrubies-for-constants [pool-context num-instances] (jruby-testutils/reduce-over-jrubies! pool-context num-instances (constantly script-to-check-if-constant-is-defined))) (defn verify-no-constants [pool-context num-instances] ;; verify that the constants are cleared out from the instances by looping ;; over them and expecting a 'NameError' when we reference the constant by name. (every? false? (check-all-jrubies-for-constants pool-context num-instances))) (defn trigger-flush [ssl-options] (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/jruby-pool" ssl-options)] (= 204 (:status response)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Tests (deftest ^:integration ^:single-threaded-only admin-api-flush-jruby-pool-single-threaded-test (testing "Flushing the instance pool results in all new JRuby instances" (logutils/with-test-logging (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 4 :borrow-timeout default-borrow-timeout}} (let [jruby-service (tk-app/get-service app :JRubyPuppetService) context (tk-services/service-context jruby-service) pool-context (:pool-context context)] ;; set a ruby constant in each instance so that we can recognize them (is (true? (set-constants-and-verify pool-context 4))) (let [flush-complete (add-watch-for-flush-complete pool-context)] (is (true? (trigger-flush ssl-request-options))) (is (true? (timed-deref flush-complete)) (str "timed out waiting for the flush to complete, stack:\n" (get-all-stack-traces-as-str)))) ;; now the pool is flushed, so the constants should be cleared (is (true? (verify-no-constants pool-context 4)))))))) ;; Copies the test above, but for multithreaded mode (single jruby instance) (deftest ^:integration ^:multithreaded-only admin-api-flush-jruby-ref-pool-multi-threaded-test (testing "Flushing the reference pool results in a new JRuby instance" (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 4 :borrow-timeout default-borrow-timeout :multithreaded true}} (let [jruby-service (tk-app/get-service app :JRubyPuppetService) context (tk-services/service-context jruby-service) pool-context (:pool-context context)] ;; set a ruby constant in the instance so that we can recognize it (is (true? (set-constants-and-verify pool-context 1))) (let [flush-complete (add-watch-for-flush-complete-multithreaded pool-context)] (is (true? (trigger-flush ssl-request-options))) (is (true? (timed-deref flush-complete)) (str "timed out waiting for the flush to complete, stack:\n" (get-all-stack-traces-as-str)))) ;; now the pool is flushed, so the constant should be cleared (is (true? (verify-no-constants pool-context 1))))))) (defprotocol BonusService (bonus-service-fn [this])) (deftest ^:integration test-restart-comes-back (testing "After a TK restart puppetserver can still handle requests" (let [call-seq (atom []) debug-log "./target/test-restart-comes-back.log" lc-fn (fn [context action] (swap! call-seq conj action) context) bonus-service (tk-services/service BonusService [[:MasterService]] (init [this context] (lc-fn context :init-bonus-service)) (start [this context] (lc-fn context :start-bonus-service)) (stop [this context] (lc-fn context :stop-bonus-service)) (bonus-service-fn [this] (lc-fn nil :bonus-service-fn))) config-overrides {:global {:logging-config (str "./dev-resources/puppetlabs/services/" "jruby/jruby_pool_int_test/" "logback-test-restart-comes-back.xml")} :jruby-puppet {:max-active-instances 1 :borrow-timeout default-borrow-timeout}} config (bootstrap/load-dev-config-with-overrides config-overrides) mock-jruby-puppet-fn (jruby-testutils/create-mock-jruby-puppet-fn-with-handle-response-params 200 "success response from restart test")] (fs/delete debug-log) (tk-testutils/with-app-with-config app (conj (bootstrap/services-from-dev-bootstrap-plus-mock-jruby-pool-manager-service config mock-jruby-puppet-fn) bonus-service) config (tk-internal/restart-tk-apps [app]) (let [start (System/currentTimeMillis)] (while (and (not= (count @call-seq) 5) (< (- (System/currentTimeMillis) start) 300000)) (Thread/yield))) (let [shutdown-service (tk-app/get-service app :ShutdownService)] (is (nil? (tk-internal/get-shutdown-reason shutdown-service)) "shutdown reason was unexpectedly set after restart")) (is (= @call-seq [:init-bonus-service :start-bonus-service :stop-bonus-service :init-bonus-service :start-bonus-service]) (str "dumping puppetserver.log\n" (slurp debug-log))) (let [get-results (http-client/get "https://localhost:8140/puppet/v3/environments" testutils/catalog-request-options)] (is (= 200 (:status get-results))) (is (= "success response from restart test" (:body get-results)))))))) (deftest ^:integration test-503-when-app-shuts-down (logutils/with-test-logging (testing "After the app is shutdown the agent requests result in a 503 response" (ks-testutils/with-no-jvm-shutdown-hooks (let [config (-> (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances 2 :borrow-timeout default-borrow-timeout})) (assoc :webserver {:port 8081 :shutdown-timeout-seconds 1})) mock-jruby-puppet-fn (jruby-testutils/create-mock-jruby-puppet-fn-with-handle-response-params 200 (str "response body doesn't matter, just " "provide a successful response so the " "test knows the webserver is still running")) services (jruby-testutils/add-mock-jruby-pool-manager-service (conj jruby-testutils/jruby-service-and-dependencies jruby-metrics-service/jruby-metrics-service handler-service/request-handler-service ps-config/puppet-server-config-service vcs/versioned-code-service) config mock-jruby-puppet-fn) app (tk/boot-services-with-config services config)] (try (let [cert (ssl-utils/pem->cert (str test-resources-dir "/localhost-cert.pem")) handler-service (tk-app/get-service app :RequestHandlerService) request {:uri "/puppet/v3/environments", :params {}, :headers {}, :request-method :get, :body "", :ssl-client-cert cert, :content-type ""} ping-environment #(->> request (handler-core/wrap-params-for-jruby) (handler/handle-request handler-service)) ping-before-stop (ping-environment) stop-complete? (future (tk-app/stop app))] (is (= 200 (:status ping-before-stop)) "environment request before stop failed") (let [start (System/currentTimeMillis)] (logutils/with-test-logging (while (and (< (- (System/currentTimeMillis) start) 10000) (not= 503 (:status (ping-environment)))) (Thread/yield)) (is (= 503 (:status (ping-environment))))) (is (not= :timed-out (timed-deref stop-complete?)) (str "timed out waiting for the stop to complete, stack:\n" (get-all-stack-traces-as-str))) (logutils/with-test-logging (is (= 503 (:status (ping-environment))))))) (finally ;; Stop the tk app. In success cases, this will end up being done ;; twice - which is benign. This is done in the finally block so ;; that it is done even if the test errors out prematurely. Not ;; doing so could leave a Jetty webserver running indefinitely - ;; causing many tests downstream from this one that try to create ;; new Jetty servers to fail. (tk-app/stop app)))))))) (deftest ^:integration test-503-when-jruby-is-first-to-shutdown (logutils/with-test-logging (testing "After the jruby service is shutdown, requests result in 503 http responses" ;; The difference between this test and the test-503-when-app-shuts-down test is that ;; This test only shuts down the jruby service as opposed to the entire app. This way ;; we can test that the behavior is the same even if the app is in a partial shutdown ;; state when a request comes in (bootstrap/with-puppetserver-running-with-mock-jruby-puppet-fn "JRuby mocking is safe here, because we're just looking to see that the HTTP response for an environment request transitions from success to a 503 failure after the Jetty webserver has been shut down. Having a 'real' response body to the successful environment request isn't essential to observing the transition from success to failure." app {:jruby-puppet {:gem-path gem-path :max-active-instances 2 :borrow-timeout default-borrow-timeout}} (jruby-testutils/create-mock-jruby-puppet-fn-with-handle-response-params 200 "our env request has been mocked!") (let [jruby-service (tk-app/get-service app :JRubyPuppetService) context (tk-services/service-context jruby-service) ping-environment #(testutils/http-get "puppet/v3/environments") ping-before-stop (ping-environment) stop-complete? (future (tk-services/stop jruby-service context))] (is (= 200 (:status ping-before-stop)) "environment request before stop failed") (is (= "our env request has been mocked!" (:body ping-before-stop)) "environment response did not have our mock response body") (logutils/with-test-logging (let [start (System/currentTimeMillis)] (while (and (< (- (System/currentTimeMillis) start) 10000) (not= 503 (:status (ping-environment)))) (Thread/yield))) (is (= 503 (:status (ping-environment))))) (is (not= :timed-out (timed-deref stop-complete?)) (str "timed out waiting for the stop to complete, stack:\n" (get-all-stack-traces-as-str))) (let [app-context (tk-app/app-context app)] ;; We have to re-initialize the JRubyPuppetService here because ;; otherwise the tk-app/stop that is included in the ;; with-puppetserver-running macro will fail, as the ;; JRubyPuppetService is already stopped. (swap! app-context assoc-in [:service-contexts :JRubyPuppetService] {}) (tk-internal/run-lifecycle-fn! app-context tk-services/init "init" :JRubyPuppetService jruby-service) (tk-internal/run-lifecycle-fn! app-context tk-services/start "start" :JRubyPuppetService jruby-service))))))) (deftest ^:integration settings-plumbed-into-jruby-container (testing "setting plumbed into jruby container for" (let [profiler-file (str (ks/temp-file-name "foo")) jruby-puppet-config (jruby-testutils/jruby-puppet-config {:max-active-instances 1 :compile-mode :jit :profiling-mode :flat :profiler-output-file profiler-file}) config (assoc (jruby-testutils/jruby-puppet-tk-config jruby-puppet-config) :http-client {:connect-timeout-milliseconds 2 :idle-timeout-milliseconds 5 :cipher-suites ["TLS_RSA_WITH_AES_256_CBC_SHA256" "TLS_RSA_WITH_AES_256_CBC_SHA"] :ssl-protocols ["TLSv1" "TLSv1.2"]})] (logutils/with-test-logging (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies config (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :test) container (:scripting-container jruby-instance)] (try (testing "compile mode" (is (= RubyInstanceConfig$CompileMode/JIT (.getCompileMode container)))) (testing "profiling mode" (is (= RubyInstanceConfig$ProfilingMode/FLAT (.getProfilingMode container)))) (let [settings (into {} (.runScriptlet container "java.util.HashMap.new (Puppet::Server::HttpClient.settings)"))] (testing "http_connect_timeout_milliseconds" (is (= 2 (settings "http_connect_timeout_milliseconds")))) (testing "http_idle_timeout_milliseconds" (is (= 5 (settings "http_idle_timeout_milliseconds")))) (testing "cipher_suites" (is (= ["TLS_RSA_WITH_AES_256_CBC_SHA256" "TLS_RSA_WITH_AES_256_CBC_SHA"] (into [] (settings "cipher_suites"))))) (testing "ssl_protocols" (is (= ["TLSv1" "TLSv1.2"] (into [] (settings "ssl_protocols")))))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :settings-plumbed-test) ;; Because we add the current datetime and scripting container ;; hashcode to the profiler filename we need to glob for it here. (let [profiler-files (fs/glob (fs/parent profiler-file) (str (fs/base-name profiler-file) "*"))] (is (= 1 (count profiler-files)))))))))))) (deftest ^:integration http-client-metrics-enabled-test (let [config (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config))] (testing "when http client metrics are disabled, http client does not use a metric registry" (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (assoc-in config [:http-client :metrics-enabled] false) (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :no-metrics-test) container (:scripting-container jruby-instance)] (try (let [client (.runScriptlet container "Puppet::Server::HttpClient.client")] (testing "client does not have a registry" (is (= nil (.getMetricRegistry client))))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :no-metrics-test)))))) (testing "when http client metrics are enabled, http client uses a metric registry" (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies config (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :metrics-test) container (:scripting-container jruby-instance)] (try (let [client (.runScriptlet container "Puppet::Server::HttpClient.client")] (testing "client has a registry" (is (instance? MetricRegistry (.getMetricRegistry client)))) (testing "server id is passed through to client" (is (= "puppetlabs.localhost.http-client.experimental" (.getMetricNamespace client))))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :metrics-test)))))))) (tk/defservice test-metric-web-service [[:WebserverService add-ring-handler]] (init [this context] (add-ring-handler (fn [_] {:status 200 :body "Hello, World!"}) "/hello") context)) (deftest ^:integration http-client-metrics-test (let [config (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config)) add-metric-ns #(format "puppetlabs.localhost.http-client.experimental.%s.full-response" %)] (testing "metrics get registered with metric registry when http client makes requests" (tk-testutils/with-app-with-config app (conj jruby-testutils/jruby-service-and-dependencies test-metric-web-service) (assoc-in config [:webserver :host] "localhost") (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :http-client-metrics-test) container (:scripting-container jruby-instance)] (try (.runScriptlet container "$c = Puppet::Server::HttpClient.new;") (let [metrics-svc (tk-app/get-service app :MetricsService) metric-registry (metrics-protocol/get-metrics-registry metrics-svc :puppetserver) url "http://localhost:8080/hello"] (testing "metric registry has no metrics when no http requests have been made" (is (= {:url [] :url-and-method [] :metric-id []} (metrics/get-client-metrics-data metric-registry)))) (testing "metric registry does not have any metrics by default" (testing "GET request" (.runScriptlet container (format "$c.get(URI('%s'))" url)) (let [metrics-data (metrics/get-client-metrics-data metric-registry)] (is (= [] (:url metrics-data))) (is (= [] (:url-and-method metrics-data))))) (testing "POST request" (.runScriptlet container (format "$c.post(URI('%s'), 'body')" url)) (let [metrics-data (metrics/get-client-metrics-data metric-registry)] (is (= [] (:url metrics-data))) (is (= [] (:url-and-method metrics-data))))) (testing "no metric-id metrics are registered" (is (= [] (:metric-id (metrics/get-client-metrics-data metric-registry)))))) (testing (str "metric registry has metric-id metrics after http requests have been made" " with metric-id specified") (testing "GET request" (.runScriptlet container (format "$c.get(URI('%s'), options: {:metric_id => ['foo', 'get']})" url)) (let [metric-id-data (:metric-id (metrics/get-client-metrics-data metric-registry))] (is (= 2 (count metric-id-data))) (is (= #{(add-metric-ns "with-metric-id.foo") (add-metric-ns "with-metric-id.foo.get")} (set (map :metric-name metric-id-data))))) (is (= 1 (:count (first (metrics/get-client-metrics-data-by-metric-id metric-registry ["foo"]))))) (is (= 1 (:count (first (metrics/get-client-metrics-data-by-metric-id metric-registry ["foo" "get"])))))) (testing "POST request" (.runScriptlet container (format "$c.post(URI('%s'), 'body', options: {:metric_id => ['foo', 'post']})" url)) (let [metric-id-data (:metric-id (metrics/get-client-metrics-data metric-registry))] ;; there should now be two requests with the 'foo' metric id, one with 'foo.get', ;; and one with 'foo.post' (is (= 3 (count metric-id-data))) (is (= #{(add-metric-ns "with-metric-id.foo") (add-metric-ns "with-metric-id.foo.get") (add-metric-ns "with-metric-id.foo.post")} (set (map :metric-name metric-id-data))))) (is (= 2 (:count (first (metrics/get-client-metrics-data-by-metric-id metric-registry ["foo"]))))) (is (= 1 (:count (first (metrics/get-client-metrics-data-by-metric-id metric-registry ["foo" "get"]))))) (is (= 1 (:count (first (metrics/get-client-metrics-data-by-metric-id metric-registry ["foo" "post"])))))))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :http-client-metrics-test)))))))) (deftest create-jruby-instance-test (testing "Directories can be configured programatically (and take precedence over puppet.conf)" (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:ruby-load-path jruby-testutils/ruby-load-path :gem-home jruby-testutils/gem-home :gem-path jruby-testutils/gem-path :server-conf-dir jruby-testutils/conf-dir :server-code-dir jruby-testutils/code-dir :server-var-dir jruby-testutils/var-dir :server-run-dir jruby-testutils/run-dir :server-log-dir jruby-testutils/log-dir})) (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :test) jruby-puppet (:jruby-puppet jruby-instance)] (try (are [setting expected] (= (-> expected (ks/normalized-path) (ks/absolute-path)) (.getSetting jruby-puppet setting)) "confdir" jruby-testutils/conf-dir "codedir" jruby-testutils/code-dir "vardir" jruby-testutils/var-dir "rundir" jruby-testutils/run-dir "logdir" jruby-testutils/log-dir) (finally (jruby-testutils/return-instance jruby-service jruby-instance :settings-plumbed-test)))))) (testing "Settings from Ruby Puppet are available" (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config)) (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :test) jruby-puppet (:jruby-puppet jruby-instance)] (try (testing "Various data types" (is (= "ldap" (.getSetting jruby-puppet "ldapserver"))) (is (= 8140 (.getSetting jruby-puppet "serverport"))) (is (= false (.getSetting jruby-puppet "onetime")))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :settings-plumbed-test))))))) (deftest jruby-environment-vars-test (testing "Make sure that the environment variables whitelisted in puppetserver.conf are being set" (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (let [tmp-conf (ks/temp-file "puppetserver" ".conf")] (spit tmp-conf "environment-vars: { \"FOO\": ${HOME} }") (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config (merge {:ruby-load-path jruby-testutils/ruby-load-path :gem-home jruby-testutils/gem-home :gem-path jruby-testutils/gem-path :server-conf-dir jruby-testutils/conf-dir :server-code-dir jruby-testutils/code-dir :server-var-dir jruby-testutils/var-dir :server-run-dir jruby-testutils/run-dir :server-log-dir jruby-testutils/log-dir} (tk-config/load-config (.getPath tmp-conf)))))) (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :test) jruby-scripting-container (:scripting-container jruby-instance) jruby-env (.runScriptlet jruby-scripting-container "ENV")] (try ;; Note that other environment variables are allowed through ;; (HTTP_PROXY, HTTPS_PROXY, NO_PROXY, or their lowercase ;; variants) but are not expected to be set in most environments. ;; However, in order to make this test more robust, these variables ;; are always filtered out. (is (= #{"HOME" "PATH" "GEM_HOME" "GEM_PATH" "JARS_NO_REQUIRE" "JARS_REQUIRE" "RUBY" "FOO"} (set (remove (set jruby-core/proxy-vars-allowed-list) (keys jruby-env))))) (is (= (.get jruby-env "FOO") (System/getenv "HOME"))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :test))))))) (deftest master-termination-test (testing "Flushing the pool causes masters to be terminated" (with-redefs [jruby-puppet-core/cleanup-fn (fn [instance] (log/info "In cleanup fn") (.terminate (:jruby-puppet instance)))] (logutils/with-test-logging (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances 1})) (let [jruby-service (tk-app/get-service app :JRubyPuppetService) pool-context (jruby-protocol/get-pool-context jruby-service) pool-agent (jruby-agents/get-modify-instance-agent pool-context)] (jruby-protocol/flush-jruby-pool! jruby-service) ; wait until the flush is complete (await pool-agent) (is (logged? #"In cleanup fn"))))))) (testing "flushing the pool does not leave orphaned timeout threads" (logutils/with-test-logging (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances 1})) ;; getAllStackTraces returns a HashMap of Thread to StackTraceElement[] (let [threads-before-jruby (set (keys (Thread/getAllStackTraces))) jruby-service (tk-app/get-service app :JRubyPuppetService) pool-context (jruby-protocol/get-pool-context jruby-service) pool-agent (jruby-agents/get-modify-instance-agent pool-context) instance (jruby-testutils/borrow-instance jruby-service :test) scripting-container (:scripting-container instance) ;; Timeout will print to stderr otherwise _ (.setErrorWriter scripting-container (io/writer (ByteArrayOutputStream.))) script "require 'timeout'; Timeout::timeout(0.1) { sleep(5) }"] (try (.runScriptlet scripting-container script) (catch EvalFailedException _)) (let [threads-during-jruby (set (keys (Thread/getAllStackTraces)))] (jruby-testutils/return-instance jruby-service instance :test) (jruby-protocol/flush-jruby-pool! jruby-service) ; wait until the flush is complete (await pool-agent) (Thread/sleep 5000) (let [threads-after-jruby (set (keys (Thread/getAllStackTraces))) threads-created-by-jruby (set/difference threads-during-jruby threads-before-jruby) threads-orphaned-by-jruby (set/intersection threads-created-by-jruby threads-after-jruby)] (is (empty? threads-orphaned-by-jruby))))))))) (deftest compat-version-in-config-throws-exception-test (testing "compat-version setting in configuration throws exception" (logutils/with-test-logging (is (thrown-with-msg? IllegalArgumentException #"jruby-puppet.compat-version setting no longer supported" (tk-testutils/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (assoc-in (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config)) [:jruby-puppet :compat-version] "2.0"))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby/module_info_test.clj000066400000000000000000000066141470345337400335650ustar00rootroot00000000000000(ns puppetlabs.services.jruby.module-info-test (:require [clojure.test :refer [deftest is testing]] [puppetlabs.kitchensink.core :as ks] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [me.raynes.fs :as fs] [cheshire.core :as cheshire] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-bootstrap])) (defn gen-modules [[mod-dir manifests]] (let [modules-dir (fs/file mod-dir "modules")] (ks/mkdirs! modules-dir) (doseq [manifest manifests] (let [module-dir (fs/file modules-dir manifest) metadata-json {"name" manifest "version" "1.0.0" "author" "Puppet" "license" "apache" "dependencies" [] "source" "https://github.com/puppetlabs"}] (ks/mkdirs! (fs/file module-dir)) (spit (fs/file module-dir "metadata.json") (cheshire/generate-string metadata-json)))))) (defn create-env [[env-dir manifests]] (testutils/create-env-conf env-dir "") (gen-modules [env-dir manifests])) (defn roundtrip-via-json [obj] (-> obj (cheshire/generate-string) (cheshire/parse-string))) (deftest ^:integration module-info-test (testing "module info properly enumerated for" (let [code-dir (ks/temp-dir) conf-dir (ks/temp-dir) config (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:server-code-dir (.getAbsolutePath code-dir) :server-conf-dir (.getAbsolutePath conf-dir)}))] (tk-bootstrap/with-app-with-config app jruby-testutils/jruby-service-and-dependencies config (let [jruby-service (tk-app/get-service app :JRubyPuppetService) instance (jruby-testutils/borrow-instance jruby-service :test) jruby-puppet (:jruby-puppet instance) _ (testutils/create-file (fs/file conf-dir "puppet.conf") "[main]\nenvironment_timeout=unlimited\nbasemodulepath=$codedir/modules\n") env-dir (fn [env-name] (fs/file code-dir "environments" env-name)) env-1-dir (env-dir "env1") env-1-dir-and-manifests [env-1-dir ["foo" "bar"]] _ (create-env env-1-dir-and-manifests) get-module-info-for-env (fn [env] (-> (.getModuleInfoForEnvironment jruby-puppet env) (roundtrip-via-json)))] (try (testing "retrieves basic module information about installed modules" (let [env-1-module-info #{{"name" "foo", "version" "1.0.0"} {"name" "bar", "version" "1.0.0"}}] (is (= env-1-module-info (set (get-module-info-for-env "env1"))) "Unexpected info retrieved for 'env1'"))) (testing "returns nothing if a fake env is given" (is (= nil (get-module-info-for-env "bogus_env")))) (finally (jruby-testutils/return-instance jruby-service instance :test)))))))) puppet_environments_int_test.clj000066400000000000000000000237431470345337400362060ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby(ns puppetlabs.services.jruby.puppet-environments-int-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.http.client.sync :as http-client] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.puppetserver.testutils :as testutils :refer [ssl-request-options get-catalog]] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [me.raynes.fs :as fs] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.kitchensink.core :as ks])) (def test-resources-dir "./dev-resources/puppetlabs/services/jruby/puppet_environments_int_test") (use-fixtures :once (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (use-fixtures :each #(logutils/with-test-logging (%))) (def num-jrubies 2) (def gem-path [(ks/absolute-path jruby-testutils/gem-path)]) (defn get-catalog-and-borrow-jruby "Gets a catalog, and then borrows a JRuby instance from a pool to ensure that a subsequent catalog request will be directed to a different JRuby. Returns a map containing both the catalog and the JRuby instance. This function relies on the fact that we are using a LIFO algorithm for allocating JRuby instances to handle requests." [borrow-jruby-fn] (let [catalog (get-catalog) jruby (borrow-jruby-fn)] {:catalog catalog :jruby jruby})) (defn get-catalog-and-return-jruby "Given a map containing a catalog and a JRuby instance, return the JRuby instance to the pool and return the catalog." [return-jruby-fn m] (return-jruby-fn (:jruby m)) (:catalog m)) (defn get-catalog-from-each-jruby "Iterates through all of the JRuby instances and gets a catalog from each of them. Returns the sequence of catalogs." [borrow-jruby-fn return-jruby-fn] ;; iterate over all of the jrubies and call get-catalog-and-borrow-jruby. It's ;; important that this is not done lazily, otherwise the jrubies could be returned ;; to the pool before the next borrow occurs. (let [jrubies-and-catalogs (doall (repeatedly num-jrubies (partial get-catalog-and-borrow-jruby borrow-jruby-fn)))] ;; now we can return the jrubies to the pool, and return the seq of catalogs ;; to our caller (map (partial get-catalog-and-return-jruby return-jruby-fn) jrubies-and-catalogs))) ;; This test is written in a way that relies on knowledge about ;; the underlying implementation of the JRuby pool. That is admittedly ;; not ideal, but we discussed it at length and agreed that the test has ;; value in terms of simulating an end user's experience, which could not ;; be achieved w/o some such assumptions, and thus is worth keeping. ;; ;; This test does NOT make sense in multithreaded mode: because there is only a ;; single jruby instance, any environment context would be shared amongst all ;; workers (threads in this case, since they share the jruby instance). (deftest ^:integration ^:single-threaded-only environment-flush-integration-test (testing "environments are flushed after marking expired" ;; This test is a bit complicated, so warrants some 'splainin. ;; ;; Note that we start off with a puppet.conf file from the fixture ;; above, which enables directory environments and sets the ;; timeout to 'unlimited' so that we know that puppet will ;; never expire entries from the environment cache without ;; our help. ;; ;; The first thing we do is write out a site.pp that includes a ;; class that we'll create for our environment. (testutils/write-site-pp-file "include foo") ;; Now we define the class; just a notify with 'hello1'. (testutils/write-foo-pp-file "class foo { notify {'hello1': } }") ;; Now we're going to start up puppetserver with 2 jrubies. We need ;; two of them so that we can illustrate that the cache can ;; be out of sync between the two of them. (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances num-jrubies}} (let [jruby-service (tk-app/get-service app :JRubyPuppetService) borrow-jruby-fn (partial jruby-testutils/borrow-instance jruby-service :environment-flush-integration-test) return-jruby-fn (fn [instance] (jruby-testutils/return-instance jruby-service instance :environment-flush-integration-test))] ;; wait for all of the jrubies to be ready so that we can ;; validate cache state differences between them. (jruby-testutils/wait-for-jrubies app) (testing "flush called when no jrubies are borrowed" ;;; Now we grab a catalog from the first jruby instance. This ;;; catalog should contain the 'hello1' notify, and will cause ;;; the first jruby instance to cache the manifests. (let [catalog1 (get-catalog)] (is (testutils/catalog-contains? catalog1 "Notify" "hello1")) (is (not (testutils/catalog-contains? catalog1 "Notify" "hello2")))) ;; Now we modify the class definition to have a 'hello2' notify, ;; instead of 'hello1'. (testutils/write-foo-pp-file "class foo { notify {'hello2': } }") ;; Now we grab a catalog from both of the jrubies. One should have the ;; old, cached state, and one should have the new state. (let [catalogs (get-catalog-from-each-jruby borrow-jruby-fn return-jruby-fn)] (is (= 1 (testutils/num-catalogs-containing catalogs "Notify" "hello1"))) (is (= 1 (testutils/num-catalogs-containing catalogs "Notify" "hello2")))) ;; Now, make a DELETE request to the /environment-cache endpoint. ;; This flushes Puppet's cache for all environments. (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" ssl-request-options)] (testing "A successful DELETE request to /environment-cache returns an HTTP 204" (is (= 204 (:status response)) (ks/pprint-to-string response)))) ;; Now if we get catalogs from both of the JRubies again, we should get ;; the 'hello2' catalog from both, since the cache should have been ;; cleared. (let [catalogs (get-catalog-from-each-jruby borrow-jruby-fn return-jruby-fn)] (is (= 0 (testutils/num-catalogs-containing catalogs "Notify" "hello1"))) (is (= 2 (testutils/num-catalogs-containing catalogs "Notify" "hello2"))))) (testing "flush called when a jruby is borrowed" ;; change the resource again (testutils/write-foo-pp-file "class foo { notify {'hello3': } }") ;; borrow an instance (let [instance (borrow-jruby-fn)] ;; flush the cache (try (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" ssl-request-options)] (is (= 204 (:status response)) (ks/pprint-to-string response))) (finally ;; return the instance after the cache flush (return-jruby-fn instance)))) (let [catalogs (get-catalog-from-each-jruby borrow-jruby-fn return-jruby-fn)] (is (= 0 (testutils/num-catalogs-containing catalogs "Notify" "hello1"))) (is (= 0 (testutils/num-catalogs-containing catalogs "Notify" "hello2"))) (is (= 2 (testutils/num-catalogs-containing catalogs "Notify" "hello3"))))))))) (deftest ^:integration single-environment-flush-integration-test (testing "a single environment is flushed after marking expired" (testutils/write-site-pp-file "include foo") (testutils/write-foo-pp-file "class foo { notify {'hello1': } }") (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1}} ;;; Validate that the catalog has `hello1` (let [catalog1 (get-catalog)] (is (testutils/catalog-contains? catalog1 "Notify" "hello1")) (is (not (testutils/catalog-contains? catalog1 "Notify" "hello2")))) ;; Now we modify the class definition to have a 'hello2' notify, ;; instead of 'hello1'. (testutils/write-foo-pp-file "class foo { notify {'hello2': } }") ;; Now, make a DELETE request to the /environment-cache endpoint, specifying ;; an environment OTHER THAN the production environment. This should not ;; cause the cache to be flushed for the production environment. (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache?environment=foo" ssl-request-options)] (is (= 204 (:status response)) (ks/pprint-to-string response))) ;;; Validate that the catalog still has `hello1` (let [catalog1 (get-catalog)] (is (testutils/catalog-contains? catalog1 "Notify" "hello1")) (is (not (testutils/catalog-contains? catalog1 "Notify" "hello2")))) (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache?environment=production" ssl-request-options)] (is (= 204 (:status response)) (ks/pprint-to-string response))) ;;; Validate that the catalog now has `hello2` (let [catalog1 (get-catalog)] (is (not (testutils/catalog-contains? catalog1 "Notify" "hello1"))) (is (testutils/catalog-contains? catalog1 "Notify" "hello2")))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby/request_handler_test.clj000066400000000000000000000073651470345337400344560ustar00rootroot00000000000000(ns puppetlabs.services.jruby.request-handler-test (:import (java.io ByteArrayInputStream) (java.security MessageDigest) (org.apache.commons.io IOUtils)) (:require [clojure.string :as string] [clojure.java.io :as io] [clojure.test :refer [deftest is testing use-fixtures]] [me.raynes.fs :as fs] [puppetlabs.kitchensink.core :as ks] [schema.test :as schema-test] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.http.client.sync :as http-client] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [puppetlabs.puppetserver.testutils :as testutils :refer [ssl-request-options]])) (def test-resources-dir "./dev-resources/puppetlabs/services/jruby/request_handler_test") (use-fixtures :once schema-test/validate-schemas (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (use-fixtures :each #(logutils/with-test-logging (%))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Tests (deftest ^:integration file-bucket-test (testing "that a file bucket upload with *binary*, non-UTF-8, content is successful (SERVER-269)" (let [bucket-dir (str bootstrap/server-var-dir "/bucket")] (fs/delete-dir bucket-dir) (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]}} (try (let [raw-byte-arr (byte-array [(byte -128) (byte -127) (byte -126)]) digested (.digest (MessageDigest/getInstance "SHA-256") raw-byte-arr) expected-sha256 (.toString (BigInteger. 1 digested) 16) expected-bucket-file (string/join "/" [bucket-dir (string/join "/" (subs expected-sha256 0 8)) expected-sha256 "contents"]) options (merge ssl-request-options {:body (ByteArrayInputStream. raw-byte-arr) :headers {"accept" "binary" "content-type" "application/octet-stream"}}) response (http-client/put (str "https://localhost:8140/" "puppet/v3/file_bucket_file/sha256/" expected-sha256 "?environment=production") options)] (is (= 200 (:status response)) "Bucket PUT request failed") (is (fs/exists? expected-bucket-file) "Bucket file not stored at expected location") (is (= (seq raw-byte-arr) (when (fs/exists? expected-bucket-file) (-> expected-bucket-file (io/input-stream) (IOUtils/toByteArray) (seq)))) "Did not find expected content in bucket file")) (finally (fs/delete-dir bucket-dir))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby/service_macros_test.clj000066400000000000000000000017461470345337400342720ustar00rootroot00000000000000(ns puppetlabs.services.jruby.service-macros-test (:require [clojure.test :refer [deftest is testing]] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.services.jruby.jruby-puppet-service :as jruby-puppet] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-testutils] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils])) (deftest simple-with-lock-test (testing "using with-lock doesn't throw any errors" (let [config (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config))] (tk-testutils/with-app-with-config app (jruby-testutils/jruby-service-and-dependencies-with-mocking config) config (let [jruby-service (tk-app/get-service app :JRubyPuppetService)] (jruby-puppet/with-lock jruby-service :with-lock-test ; Just make sure the macro doesn't fail (is (true? true))) (is (true? true))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/jruby/tasks_test.clj000066400000000000000000000462271470345337400324160ustar00rootroot00000000000000(ns puppetlabs.services.jruby.tasks-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [clojure.string :as str] [clojure.walk :refer [keywordize-keys]] [puppetlabs.kitchensink.core :as ks] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.services.master.master-core :as mc] [me.raynes.fs :as fs] [cheshire.core :as cheshire] [schema.core :as schema] [schema.test :as schema-test] [slingshot.test :refer :all] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-bootstrap]) (:import [java.io File ByteArrayInputStream] [org.jruby.exceptions RaiseException])) (schema/defn puppet-tk-config [code-dir :- File, conf-dir :- File] (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:server-code-dir (.getAbsolutePath code-dir) :server-conf-dir (.getAbsolutePath conf-dir)}))) (def puppet-conf-file-contents "[main]\nenvironment_timeout=0\nbasemodulepath=$codedir/modules\n") (def ^:dynamic *code-dir* nil) (def ^:dynamic *jruby-service* nil) (def ^:dynamic *jruby-puppet* nil) (defn with-running-server [f] (let [code-dir (ks/temp-dir) conf-dir (ks/temp-dir)] (testutils/create-file (fs/file conf-dir "puppet.conf") puppet-conf-file-contents) (tk-bootstrap/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (puppet-tk-config code-dir conf-dir) (let [jruby-service (tk-app/get-service app :JRubyPuppetService) instance (jruby-testutils/borrow-instance jruby-service :test) jruby-puppet (:jruby-puppet instance)] (binding [*code-dir* code-dir *jruby-service* jruby-service *jruby-puppet* jruby-puppet] (try (f) (finally (jruby-testutils/return-instance jruby-service instance :test)))))))) (use-fixtures :once schema-test/validate-schemas) (use-fixtures :each with-running-server) (def TaskOptions {:name schema/Str :module-name schema/Str (schema/optional-key :metadata) schema/Any :number-of-files (schema/pred #(<= % 5))}) (schema/defn gen-empty-task "Assumes tasks dir already exists -- generates a set of task files for a single task. All the generated payload files are empty, and all generated metadata files contain {\"meta\": \"data\"} This function exists in addition to the tasks-generating utilities in puppetlabs.puppetserver.testutils primarily because those other utilites only generate things inside a hardcoded conf-dir at 'target/server-conf'." [env-dir :- (schema/cond-pre File schema/Str) task :- TaskOptions] (let [task-name (:name task) extensions '(".rb" "" ".sh" ".exe" ".py") task-dir (fs/file env-dir "modules" (:module-name task) "tasks") files (concat (get-in task [:metadata :files]) (mapcat :files (get-in task [:metadata :implementations])))] (fs/mkdirs task-dir) (doseq [file files] (cond (str/ends-with? file "/") (do (fs/mkdirs (fs/file env-dir "modules" file)) (fs/create (fs/file env-dir "modules" file "temp.rb"))) :else (do (fs/mkdirs (fs/parent (fs/file env-dir "modules" file))) (fs/create (fs/file env-dir "modules" file))))) (when-let [metadata (:metadata task)] (spit (fs/file task-dir (str task-name ".json")) (cheshire/generate-string metadata))) (dotimes [n (:number-of-files task)] (fs/create (fs/file task-dir (str task-name (nth extensions n ".rb"))))))) (defn gen-empty-tasks "Tasks is a list of task maps, with keys: :name String, file name of task :module-name String, name of module task is in :metadata Map of metadata to write :number-of-files Number, how many executable files to generate for the task (0 or more) All generated files are empty, except metadata files, which contain the empty JSON object. This function exists in addition to the tasks-generating utilities in puppetlabs.puppetserver.testutils primarily because those other utilites only generate things inside a hardcoded conf-dir at 'target/server-conf'." [env-dir tasks] (dorun (map (partial gen-empty-task env-dir) tasks))) (defn create-env [env-dir tasks] (gen-empty-tasks env-dir tasks)) (defn env-dir [code-dir env-name] (fs/file code-dir "environments" env-name)) (defn expected-tasks-info [tasks] (map (fn [{:keys [name module-name metadata]}] {:module {:name module-name} :metadata (keywordize-keys metadata) :name (if (= "init" name) module-name (str module-name "::" name))}) tasks)) (defn simple-impl-metadata [task] {"implemenations" [{"name" (str task ".rb")}]}) (deftest ^:integration task-data-test (testing "requesting data about a specific task" (let [tasks [{:name "install" :module-name "apache" :metadata (simple-impl-metadata "install") :number-of-files 2} {:name "init" :module-name "apache" :number-of-files 1}] get-task-data (fn [env module task] (-> (.getTaskData *jruby-puppet* env module task) mc/sort-nested-info-maps))] (create-env (env-dir *code-dir* "env1") tasks) (testing "when the environment, module, and task do exist" (testing "with the init task" (let [res (get-task-data "env1" "apache" "init")] (is (nil? (schema/check mc/TaskData res))) (is (= "init.rb" (-> res :files first :name))) (is (re-matches #".*init\.rb" (-> res :files first :path))))) (testing "with another named task" (let [res (get-task-data "env1" "apache" "install")] (is (nil? (schema/check mc/TaskData res))) (is (= [] (:files res)))))) (testing "when the environment does not exist" (is (thrown-with-msg? RaiseException #"(EnvironmentNotFound)" (get-task-data "env2" "doesnotmatter" "whatever")))) (testing "when the module does not exist" (is (thrown-with-msg? RaiseException #"(MissingModule)" (get-task-data "env1" "notamodule" "install")))) (testing "when the module name is invalid" (is (thrown-with-msg? RaiseException #"(MissingModule)" (get-task-data "env1" "7!" "install")))) (testing "when the task does not exist" (is (thrown-with-msg? RaiseException #"(TaskNotFound)" (get-task-data "env1" "apache" "recombobulate")))) (testing "when the task does not exist" (is (thrown-with-msg? RaiseException #"(TaskNotFound)" (get-task-data "env1" "apache" "recombobulate")))) (testing "when the task name is invalid" (is (thrown-with-msg? RaiseException #"(TaskNotFound)" (get-task-data "env1" "apache" "&&&"))))))) (deftest ^:integration all-tasks-test (testing "requesting all tasks" (let [tasks [{:name "init" :module-name "apache" :number-of-files 1}] get-tasks (fn [env] (.getTasks *jruby-puppet* env))] (create-env (env-dir *code-dir* "env1") tasks) (testing "for environment that does exist" (is (= (->> tasks expected-tasks-info (sort-by :name)) (->> (get-tasks "env1") mc/sort-nested-info-maps (sort-by :name))) "Unexpected info retrieved for 'env1'")) (testing "for environment that does not exist" (is (nil? (get-tasks "env2"))))))) (deftest ^:integration task-details-test (testing "getting details for a specific task" (let [tasks [{:name "install_mods" :module-name "apache" :metadata {"meta" "data"} :number-of-files 1} {:name "init" :module-name "apache" :number-of-files 1} {:name "init" :module-name "othermod" :metadata {} :number-of-files 1} {:name "impl" :module-name "othermod" :metadata {} :number-of-files 1} {:name "files" :module-name "apache" :metadata {:files ["othermod/files/helper.rb", "othermod/files/morefiles/" "apache/lib/puppet/ruby_file.rb"] :implementations [{:name "files.rb" :files ["othermod/files/impl_helper.rb"]}]} :number-of-files 1} {:name "about" :metadata {} :module-name "apache" :number-of-files 0}]] (create-env (env-dir *code-dir* "production") tasks) (testing "without code management" (let [code-fn (fn [_ _ _] (throw (Exception. "Versioned code not supported."))) get-task-details (fn [env module task] (mc/task-details *jruby-service* *jruby-puppet* code-fn env nil module task))] (testing "when the environment exists" (testing "and the module exists" (testing "and the task exists" (testing "with metadata and payload files" (let [expected-info {:metadata {:meta "data"} :name "apache::install_mods" :files [{:filename "install_mods.rb" :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" :size_bytes 0 :uri {:path "/puppet/v3/file_content/tasks/apache/install_mods.rb" :params {:environment "production"}}}]}] (get-task-details "production" "othermod" "init") (is (= expected-info (get-task-details "production" "apache" "install_mods"))))) (testing "with metadata and library files" (let [sorted (sort-by :filename [{:filename "files.rb", :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", :size_bytes 0, :uri {:path "/puppet/v3/file_content/tasks/apache/files.rb", :params {:environment "production"}}} {:filename "apache/lib/puppet/ruby_file.rb", :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", :size_bytes 0, :uri {:path "/puppet/v3/file_content/plugins/puppet/ruby_file.rb", :params {:environment "production"}}} {:filename "othermod/files/impl_helper.rb", :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", :size_bytes 0, :uri {:path "/puppet/v3/file_content/modules/othermod/impl_helper.rb", :params {:environment "production"}}} {:filename "othermod/files/helper.rb", :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", :size_bytes 0, :uri {:path "/puppet/v3/file_content/modules/othermod/helper.rb", :params {:environment "production"}}} {:filename "othermod/files/morefiles/temp.rb", :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", :size_bytes 0, :uri {:path "/puppet/v3/file_content/modules/othermod/morefiles/temp.rb", :params {:environment "production"}}}]) expected-info {:metadata {:files (seq ["othermod/files/helper.rb" "othermod/files/morefiles/" "apache/lib/puppet/ruby_file.rb"]), :implementations (seq [{:files (seq ["othermod/files/impl_helper.rb"]), :name "files.rb"}])}, :name "apache::files", :files sorted} actual-info (update (get-task-details "production" "apache" "files") :files (partial sort-by :filename))] (is (= (keys expected-info) (keys actual-info))) (is (= (:metadata expected-info) (:metadata actual-info))) (is (= sorted (:files actual-info))) (doall (map (fn [expected actual] (is (= expected actual))) sorted (:files actual-info))))) (testing "without a metadata file" (let [expected-info {:metadata {} :name "apache" :files [{:filename "init.rb" :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" :size_bytes 0 :uri {:path "/puppet/v3/file_content/tasks/apache/init.rb" :params {:environment "production"}}}]}] (is (= expected-info (get-task-details "production" "apache" "init"))))) (testing "with no payload files" (let [_expected-info {:metadata {:meta "data"} :name "apache::about" :files []}] (is (thrown+? [:kind "puppet.tasks/no-implementation"] (get-task-details "production" "apache" "about")))))) (testing "but the task doesn't exist" (is (thrown-with-msg? RaiseException #"(TaskNotFound)" (get-task-details "production" "apache" "refuel"))))) (testing "but the module doesn't exist" (is (thrown-with-msg? RaiseException #"(MissingModule)" (get-task-details "production" "mahjoule" "heat"))))) (testing "when the environment doesn't exist" (is (thrown-with-msg? RaiseException #"(EnvironmentNotFound)" (get-task-details "DNE" "module" "missing")))))) (testing "with code management" (let [get-task-details (fn [env module task code-fn code-id] (mc/task-details *jruby-service* *jruby-puppet* code-fn env code-id module task))] (testing "uses static-file-content endpoint when code is available" (let [code-fn (fn [_ _ _] (ByteArrayInputStream. (.getBytes "" "UTF-8"))) expected-info {:metadata {:meta "data"} :name "apache::install_mods" :files [{:filename "install_mods.rb" :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" :size_bytes 0 :uri {:path "/puppet/v3/static_file_content/modules/apache/tasks/install_mods.rb" :params {:environment "production" :code_id "code-id"}}}]}] (is (= expected-info (get-task-details "production" "apache" "install_mods" code-fn "code-id"))))) (testing "uses file-content endpoint when code content differs from content reported by Puppet" (let [code-fn (fn [_ _ _] (ByteArrayInputStream. (.getBytes "some script" "UTF-8"))) expected-info {:metadata {:meta "data"} :name "apache::install_mods" :files [{:filename "install_mods.rb" :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" :size_bytes 0 :uri {:path "/puppet/v3/file_content/tasks/apache/install_mods.rb" :params {:environment "production"}}}]}] (is (= expected-info (get-task-details "production" "apache" "install_mods" code-fn "code-id"))))) (testing "uses file-content endpoint when code is unavailable" (let [code-fn (fn [_ _ _] (throw (Exception. "Versioned code not supported."))) expected-info {:metadata {:meta "data"} :name "apache::install_mods" :files [{:filename "install_mods.rb" :sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" :size_bytes 0 :uri {:path "/puppet/v3/file_content/tasks/apache/install_mods.rb" :params {:environment "production"}}}]}] (is (= expected-info (get-task-details "production" "apache" "install_mods" code-fn "code-id")))))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/master/000077500000000000000000000000001470345337400276655ustar00rootroot00000000000000environment_classes_int_test.clj000066400000000000000000001126171470345337400363020ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/master(ns puppetlabs.services.master.environment-classes-int-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [clojure.string :as str] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-bootstrap-testutils] [puppetlabs.trapperkeeper.testutils.webserver :as jetty10] [puppetlabs.services.master.master-core :as master-core] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [cheshire.core :as cheshire] [me.raynes.fs :as fs] [clojure.tools.logging :as log] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.trapperkeeper.testutils.logging :as logutils]) (:import (com.puppetlabs.puppetserver JRubyPuppetResponse JRubyPuppet) (java.util HashMap))) (def test-resources-dir "./dev-resources/puppetlabs/services/master/environment_classes_int_test") (def gem-path [(ks/absolute-path jruby-testutils/gem-path)]) (defn purge-env-dir [] (-> testutils/conf-dir (fs/file "environments") fs/delete-dir)) (use-fixtures :once (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (use-fixtures :each #(logutils/with-test-logging (%)) (fn [f] (purge-env-dir) (try (f) (finally (purge-env-dir))))) (defn get-env-classes ([env-name] (get-env-classes env-name nil)) ([env-name if-none-match] (let [opts (when if-none-match {:headers {"If-None-Match" if-none-match}})] (try (http-client/get (str "https://localhost:8140/puppet/v3/" "environment_classes?" "environment=" env-name) (merge testutils/ssl-request-options {:as :text} opts)) (catch Exception e (throw (Exception. "environment_classes http get failed" e))))))) (defn purge-all-env-caches [] (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" testutils/ssl-request-options)) (defn purge-env-cache [env] (http-client/delete (str "https://localhost:8140/puppet-admin-api/v1/environment-cache?" "environment=" env) testutils/ssl-request-options)) (defn response-etag [request] (get-in request [:headers "etag"])) (defn etag-with-gzip-suffix [etag] (if (.endsWith etag "--gzip") etag (str etag "--gzip"))) (defn without-gzip-suffix [etag] (if (.endsWith etag "--gzip") (str/replace etag "--gzip" "") etag)) (defn response->class-info-map [response] (-> response :body cheshire/parse-string)) (deftest ^:integration environment-classes-integration-cache-disabled-test (testing "when environment classes cache is disabled for a class request" (bootstrap/with-puppetserver-running-with-config app (-> {:jruby-puppet {:gem-path gem-path :max-active-instances 1}} (bootstrap/load-dev-config-with-overrides) (ks/dissoc-in [:jruby-puppet :environment-class-cache-enabled])) (let [foo-file (testutils/write-foo-pp-file "class foo (String $foo_1 = \"is foo\"){}") expected-response { "files" [ {"path" foo-file, "classes" [ { "name" "foo" "params" [ {"name" "foo_1", "type" "String", "default_literal" "is foo", "default_source" "\"is foo\""}]}]}] "name" "production"} response (get-env-classes "production")] (testing "a successful status code is returned" (is (= 200 (:status response)) (str "unexpected status code for response, response: " (ks/pprint-to-string response)))) (testing "no etag is returned" (is (false? (contains? (:headers response) "etag")))) (testing "the expected response body is returned" (is (= expected-response (response->class-info-map response)))))))) (deftest ^:integration environment-classes-are-cached-after-eviction (let [debug-log "./target/environment-classes-integration-cache-enabled.log"] (fs/delete debug-log) (bootstrap/with-puppetserver-running app {:global {:logging-config (str "./dev-resources/puppetlabs/services/" "master/environment_classes_int_test/" "logback-environment-classes-integration-cache-enabled-test.xml")} :jruby-puppet {:gem-path gem-path :max-active-instances 1 :environment-class-cache-enabled true}} (let [_foo-file (testutils/write-pp-file "class foo (String $foo_1 = \"is foo\"){}" "foo") _bar-file (testutils/write-pp-file "class foo::bar (Integer $foo_2 = 3){}" "bar") initial-response (get-env-classes "production") initial-etag (-> initial-response response-etag without-gzip-suffix)] (testing "initial fetch of environment_classes info is good" (is (= 200 (:status initial-response)) (str "unexpected status code for initial response, response: " (ks/pprint-to-string initial-response))) (is (not (nil? initial-etag)) "no etag found for initial response")) (testing "ensure the env cache is purged" (purge-env-cache "production") (is (= nil (jruby-protocol/get-cached-info-tag (tk-app/get-service app :JRubyPuppetService) "production" :classes)))) (testing "Env cache is updated when given correct etag but cache was nil" (let [next-response (get-env-classes "production" initial-etag)] (is (= 304 (:status next-response)) (str "unexpected status code for initial response, response: " (ks/pprint-to-string initial-response))) (is (= initial-etag (jruby-protocol/get-cached-info-tag (tk-app/get-service app :JRubyPuppetService) "production" :classes))))))))) (deftest ^:integration environment-classes-integration-cache-enabled-test (let [debug-log "./target/environment-classes-integration-cache-enabled.log"] (fs/delete debug-log) (bootstrap/with-puppetserver-running app {:global {:logging-config (str "./dev-resources/puppetlabs/services/" "master/environment_classes_int_test/" "logback-environment-classes-integration-cache-enabled-test.xml")} :jruby-puppet {:gem-path gem-path :max-active-instances 1 :environment-class-cache-enabled true}} (try (let [foo-file (testutils/write-pp-file "class foo (String $foo_1 = \"is foo\"){}" "foo") bar-file (testutils/write-pp-file "class foo::bar (Integer $foo_2 = 3){}" "bar") expected-initial-response { "files" [ {"path" bar-file "classes" [ { "name" "foo::bar" "params" [ {"name" "foo_2", "type" "Integer", "default_literal" 3, "default_source" "3"}]}]} {"path" foo-file, "classes" [ { "name" "foo" "params" [ {"name" "foo_1", "type" "String", "default_literal" "is foo", "default_source" "\"is foo\""}]}]}] "name" "production"} initial-response (get-env-classes "production") initial-etag (response-etag initial-response) initial-etag-with-gzip-suffix (etag-with-gzip-suffix initial-etag)] (testing "initial fetch of environment_classes info is good" (is (= 200 (:status initial-response)) (str "unexpected status code for initial response, response: " (ks/pprint-to-string initial-response))) (is (not (nil? initial-etag)) "no etag found for initial response") (is (= expected-initial-response (response->class-info-map initial-response)) "unexpected body for initial response")) (testing "etag not updated when code has not changed" (let [response (get-env-classes "production")] (is (= 200 (:status response)) "unexpected status code for response following no code change") (is (= initial-etag (response-etag response)) "etag changed even though code did not") (is (= expected-initial-response (response->class-info-map response)) "unexpected body for response"))) (testing (str "HTTP 304 (not modified) returned when request " "roundtrips last etag and code has not changed") (let [response (get-env-classes "production" initial-etag)] (is (= 304 (:status response)) (str "unexpected status code for response for no code change and " "original etag roundtripped")) (is (= initial-etag (response-etag response)) "etag changed even though code did not") (is (empty? (:body response)) "unexpected body for response"))) (testing (str "SERVER-1153 - HTTP 304 (not modified) returned when " "request roundtrips last etag with '--gzip' suffix and " "code has not changed") (let [response (get-env-classes "production" initial-etag-with-gzip-suffix)] (is (= 304 (:status response)) (str "unexpected status code for response for no code change and " "etag with '--gzip' suffix roundtripped")) (is (= initial-etag (response-etag response)) "etag changed even though code did not") (is (empty? (:body response)) "unexpected body for response"))) (testing (str "environment_classes fetch without if-none-match " "header includes latest info after code update") (testutils/write-pp-file (str "class foo (Hash[String, Integer] $foo_hash = {" " foo_1 => 1, foo_2 => 2 }){}") "foo") (testutils/write-pp-file "" "bar") (let [baz-file (testutils/write-pp-file (str "class foo::baz (String $baz_1 = 'the baz',\n" " Array[String] $baz_arr = ['one', 'two', " "'three']){}\n" "class foo::morebaz ($baz) {}") "baz") borked-file (testutils/write-pp-file "borked manifest" "borked") _ (purge-all-env-caches) response (get-env-classes "production")] (is (= 200 (:status response)) (str "unexpected status code for response following code change," "response: " (ks/pprint-to-string response))) (is (not= initial-etag (response-etag response)) "etag did not change even though code did") (is (= {"name" "production", "files" [ {"path" bar-file "classes" []} {"path" baz-file "classes" [{ "name" "foo::baz" "params" [ {"name" "baz_1", "type" "String", "default_literal" "the baz", "default_source" "'the baz'"} {"name" "baz_arr" "type" "Array[String]" "default_literal" ["one" "two" "three"] "default_source" "['one', 'two', 'three']"}]} { "name" "foo::morebaz" "params" [ {"name" "baz"}]}]} {"path" borked-file "error" (str "This Name has no effect. A value " "was produced and then forgotten (" "one or more preceding expressions " "may have the wrong form) (file: " borked-file ", line: 1, column: 1)")} {"path" foo-file, "classes" [{ "name" "foo" "params" [ {"name" "foo_hash", "type" "Hash[String, Integer]", "default_literal" {"foo_1" 1 "foo_2" 2}, "default_source" (str "{ foo_1 => 1, " "foo_2 => 2 }")}]}]}]} (response->class-info-map response)) "unexpected body following code change"))) (testing "environment class cache invalidation for one environment" ;; This test is about ensuring that when the environment-cache ;; endpoint is hit for a single environment that only that the ;; environment class info cached for that environment - but not the ;; info cached for other environments - is invalidated, meaning that ;; the next request for class info for that environment will get fresh ;; data. ;; ;; The test has the following basic steps: ;; ;; 1) Purge the current environment files on disk and hit the ;; environment-cache endpoint to flush the cache for all ;; environments, basically to ensure nothing is left around from ;; other tests. ;; 2) Populate code for the 'test' and 'production' environments and ;; see that environment_classes queries return the right info for ;; them. ;; 3) Do one more environment_classes query for each environment, ;; using the etag from the initial queries, to ensure that a 304 ;; (Not Modified) is returned. ;; 4) Change code on disk for both the 'test' and 'production' ;; environments. ;; 5) Hit the environment-cache endpoint for the 'production' ;; environment (but not for the 'test' environment). ;; 6) Do two more environment_classes queries for the 'test' and ;; 'production' environments using the etags from the initial ;; queries. Confirm that the information reflects the latest data on ;; disk for the 'production' environment but still reflects the old ;; data for the 'test' environment - expected, in this case, because ;; the 'test' environment was not flushed. (purge-env-dir) (purge-all-env-caches) (let [prod-file (testutils/write-pp-file "class oneprod {}" "somemod" "prod" "production") test-file (testutils/write-pp-file "class onetest {}" "somemod" "test" "test") production-response-initial (get-env-classes "production") production-etag-initial (response-etag production-response-initial) test-response-initial (get-env-classes "test") test-etag-initial (response-etag test-response-initial)] (is (= 200 (:status production-response-initial)) (str "unexpected status code for initial production response" "response: " (ks/pprint-to-string production-response-initial))) (is (not (nil? production-etag-initial)) "no etag returned for production response") (is (= {"name" "production", "files" [{"path" prod-file, "classes" [{"name" "oneprod", "params" []}]}]} (response->class-info-map production-response-initial)) "unexpected body for production response") (is (= 200 (:status test-response-initial)) (str "unexpected status code for initial test response" "response: " (ks/pprint-to-string test-response-initial))) (is (not (nil? test-etag-initial)) "no etag returned for test response") (is (= {"name" "test", "files" [{"path" test-file, "classes" [{"name" "onetest", "params" []}]}]} (response->class-info-map test-response-initial)) "unexpected body for test response") (testutils/write-pp-file "class oneflushprod {}" "somemod" "prod" "production") (testutils/write-pp-file "class oneflushtest {}" "somemod" "test" "test") (let [production-response-before-flush (get-env-classes "production" production-etag-initial) test-response-before-flush (get-env-classes "test" test-etag-initial)] (is (= 304 (:status production-response-before-flush)) (str "unexpected status code for prod response after code change " "but before flush")) (is (= production-etag-initial (response-etag production-response-before-flush)) "unexpected etag change when no production environment change") (is (empty? (:body production-response-before-flush)) "unexpected body for production response") (is (= 304 (:status test-response-before-flush)) (str "unexpected status code for test response after code change " "but before flush")) (is (= test-etag-initial (response-etag test-response-before-flush)) "unexpected etag change when no test environment change") (is (empty? (:body test-response-before-flush)) "unexpected body for test response") (purge-env-cache "production") (let [production-response-after-prod-flush (get-env-classes "production" production-etag-initial) production-etag-after-prod-flush (response-etag production-response-after-prod-flush) test-response-after-prod-flush (get-env-classes "test" test-etag-initial)] (is (= 200 (:status production-response-after-prod-flush)) (str "unexpected status code for prod response after code change " "and prod flush")) (is (not (nil? production-etag-after-prod-flush)) "no etag returned for production response") (is (not= production-etag-initial production-etag-after-prod-flush) (str "etag unexpectedly stayed the same even though " "the production environment changed")) (is (= {"name" "production", "files" [{"path" prod-file "classes" [{"name" "oneflushprod", "params" []}]}]} (response->class-info-map production-response-after-prod-flush)) "unexpected body for production response") (is (= 304 (:status test-response-after-prod-flush)) (str "unexpected status code for test response after code change " "but test environment not invalidated")) (is (= test-etag-initial (response-etag test-response-after-prod-flush)) "unexpected etag change when test environment not invalidated") (is (empty? (:body test-response-after-prod-flush)) "unexpected body for test response"))))) (testing "environment class cache invalidation for all environments" ;; This test is about ensuring that when the environment-cache ;; endpoint is hit with no environment parameter that any previously ;; cached environment class info is invalidated, meaning that ;; the next request for class info for all environments will get fresh ;; data. ;; ;; To eliminate some of the redundancy between tests, this test doesn't ;; repeat the intermediate step of checking to see that the first two ;; environment queries were cached - 304 (Not Modified) returns - ;; between the first set of environment_classes queries and the second ;; set, done after the code on disk for both environments has changed. ;; ;; The test has the following basic steps: ;; ;; 1) Purge the current environment files on disk and hit the ;; environment-cache endpoint to flush the cache for all ;; environments, basically to ensure nothing is left around from ;; other tests. ;; 2) Populate code for the 'test' and 'production' environments and ;; see that environment_classes queries return the right info for ;; them. ;; 3) Change code on disk for both the 'test' and 'production' ;; environments. ;; 4) Hit the environment-cache endpoint with no environment ;; parameter, expected to have the effect of flushing the cache for ;; all environments. ;; 5) Do two more environment_classes queries for the 'test' and ;; 'production' environments with the corresponding etags returned ;; from the first two queries. Confirm that the information ;; reflects the latest data on disk for both environments. (purge-env-dir) (purge-all-env-caches) (let [prod-file (testutils/write-pp-file "class allprod {}" "somemod" "prod" "production") test-file (testutils/write-pp-file "class alltest {}" "somemod" "test" "test") production-response-initial (get-env-classes "production") production-etag-initial (response-etag production-response-initial) test-response-initial (get-env-classes "test") test-etag-initial (response-etag test-response-initial)] (is (= 200 (:status production-response-initial)) (str "unexpected status code for initial production response" "response: " (ks/pprint-to-string production-response-initial))) (is (not (nil? production-etag-initial)) "no etag returned for production response") (is (= {"name" "production", "files" [{"path" prod-file, "classes" [{"name" "allprod", "params" []}]}]} (response->class-info-map production-response-initial)) "unexpected body for production response") (is (= 200 (:status test-response-initial)) (str "unexpected status code for initial test response" "response: " (ks/pprint-to-string test-response-initial))) (is (not (nil? test-etag-initial)) "no etag returned for test response") (is (= {"name" "test", "files" [{"path" test-file "classes" [{"name" "alltest" "params" []}]}]} (response->class-info-map test-response-initial)) "unexpected body for test response") (testutils/write-pp-file "class allflushprod {}" "somemod" "prod" "production") (testutils/write-pp-file "class allflushtest {}" "somemod" "test" "test") (purge-all-env-caches) (let [production-response-after-all-flush (get-env-classes "production" production-etag-initial) production-etag-after-all-flush (response-etag production-response-after-all-flush)] (is (= 200 (:status production-response-after-all-flush)) (str "unexpected status code for prod response after code change " "and all environment flush")) (is (not (nil? production-etag-after-all-flush)) "no etag returned for production response") (is (not= production-etag-initial production-etag-after-all-flush) (str "etag unexpectedly stayed the same even though " "the production environment changed")) (is (= {"name" "production", "files" [{"path" prod-file "classes" [{"name" "allflushprod", "params" []}]}]} (response->class-info-map production-response-after-all-flush)) "unexpected body for production response")) (let [test-response-after-all-flush (get-env-classes "test" test-etag-initial) test-etag-after-all-flush (response-etag test-response-after-all-flush)] (is (= 200 (:status test-response-after-all-flush)) (str "unexpected status code for test response after code change " "and all environment flush")) (is (not (nil? test-etag-after-all-flush)) "no etag returned for test response") (is (not= test-etag-initial test-etag-after-all-flush) (str "etag unexpectedly stayed the same even though " "the test environment changed")) (is (= {"name" "test", "files" [{"path" test-file "classes" [{"name" "allflushtest", "params" []}]}]} (response->class-info-map test-response-after-all-flush)) "unexpected body for test response"))))) (catch Exception e (println "dumping puppetserver.log\n" (slurp debug-log)) (throw e)))))) (deftest ^:integration not-modified-returned-for-environment-class-info-request-with-gzip-tag (testing "SERVER-1153 - when the webserver gzips the response containing environment_classes etag, the next request roundtripping that etag returns an HTTP 304 (Not Modified)" (let [expected-etag "abcd1234" body-length 200000 jruby-service (reify jruby-protocol/JRubyPuppetService (get-cached-info-tag [_ _ _] expected-etag)) app (-> (fn [_] (master-core/response-with-etag (apply str (repeat body-length "a")) expected-etag)) (master-core/wrap-with-cache-check jruby-service))] (jetty10/with-test-webserver app port (let [request-url (str "http://localhost:" port) initial-response (http-client/get request-url {:as :text}) response-tag (response-etag initial-response) response-with-tag (http-client/get request-url {:headers {"If-None-Match" response-tag} :as :text})] (is (= 200 (:status initial-response)) "response for initial request is not 'successful'") (is (= (get-in initial-response [:headers "content-encoding"]) "gzip") "response from initial request was not gzipped") (is (= body-length (count (:body initial-response))) "unexpected response body length for initial response") (is (= (str expected-etag "--gzip") response-tag) "unexpected etag returned for initial response") (is (= 304 (:status response-with-tag)) (str "request with prior etag did not return http 304 (not " "modified) status code")) (is (empty? (:body response-with-tag)) "unexpected body for request with prior etag") (is (= (str expected-etag "--gzip") (response-etag response-with-tag)) "unexpected etag returned for request with prior etag")))))) (defn create-jruby-instance-with-mock-class-info [wait-atom class-info-atom config] (let [puppet-config (jruby-testutils/mock-puppet-config-settings (:jruby-puppet config))] (reify JRubyPuppet (getSetting [_ setting] (get puppet-config setting)) (getClassInfoForEnvironment [_ _] (let [class-info {"/some/file" (doto (HashMap.) (.put "classes" @class-info-atom))}] (when-let [promises @wait-atom] (deliver (:wait-promise promises) true) @(:continue-promise promises)) class-info)) (handleRequest [_ _] (JRubyPuppetResponse. 0 nil nil nil)) (puppetVersion [_] "1.2.3") (terminate [_] (log/info "Terminating Master"))))) (deftest ^:integration class-info-updated-after-cache-flush-during-prior-request (let [class-info-atom (atom [{"name" "someclass" "params" []}]) wait-atom (atom nil) config (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :environment-class-cache-enabled true}}) mock-jruby-fn (partial create-jruby-instance-with-mock-class-info wait-atom class-info-atom)] ;; This test uses a mock jruby instance function which can provide mock ;; data for an environment class info query and can suspend a request ;; long enough for the cached environment data to be invalidated. (tk-bootstrap-testutils/with-app-with-config app (bootstrap/services-from-dev-bootstrap-plus-mock-jruby-pool-manager-service config mock-jruby-fn) config (let [continue-promise (promise) wait-promise (promise) _ (reset! wait-atom {:continue-promise continue-promise :wait-promise wait-promise}) initial-response-future (future (get-env-classes "production"))] (is (true? (deref wait-promise 10000 :timed-out)) (str "timed out waiting for get class info call to be reached " "in mock jrubypuppet instance")) (reset! class-info-atom [{"name" "updatedclass" "params" []}]) (purge-env-cache "production") (deliver continue-promise true) (let [initial-response @initial-response-future initial-response-etag (response-etag initial-response) _ (reset! wait-atom nil) response-after-update (get-env-classes "production" initial-response-etag)] (testing (str "initial request in progress while environment " "cache is invalidated contains original class info") (is (= 200 (:status initial-response)) (str "unexpected status code for initial response" "response: " (ks/pprint-to-string initial-response))) (is (not (nil? initial-response-etag)) "no etag returned for initial response") (is (= {"name" "production", "files" [{"path" "/some/file" "classes" [{"name" "someclass" "params" []}]}]} (response->class-info-map initial-response)) "unexpected body for initial response")) (testing (str "SERVER-1130 - class info updated properly for " "request made after environment cache was purged " "during a previous class info request") (is (= 200 (:status response-after-update)) (str "unexpected status code for response after update, " "response: " (ks/pprint-to-string response-after-update))) (is (not= initial-response-etag (response-etag response-after-update)) "unexpected etag for response after update") (is (= {"name" "production", "files" [{"path" "/some/file" "classes" [{"name" "updatedclass" "params" []}]}]} (response->class-info-map response-after-update)) "unexpected body for response after update"))))))) environment_modules_int_test.clj000066400000000000000000000112611470345337400363060ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/master(ns puppetlabs.services.master.environment-modules-int-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [puppetlabs.puppetserver.testutils :as testutils] [cheshire.core :as cheshire] [me.raynes.fs :as fs])) (def test-resources-dir "./dev-resources/puppetlabs/services/master/environment_modules_int_test") (defn purge-env-dir [] (-> testutils/conf-dir (fs/file "environments") fs/delete-dir)) (use-fixtures :once (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (use-fixtures :each (fn [f] (purge-env-dir) (try (f) (finally (purge-env-dir))))) (defn get-env-modules [env-name] (try (http-client/get (str "https://localhost:8140/puppet/v3/" "environment_modules?" "environment=" env-name) (merge testutils/ssl-request-options {:as :text})) (catch Exception e (throw (Exception. "environment_modules http get failed" e))))) (defn get-all-env-modules [] (try (http-client/get (str "https://localhost:8140/puppet/v3/" "environment_modules") (merge testutils/ssl-request-options {:as :text})) (catch Exception e (throw (Exception. "environment_modules http get failed" e))))) (defn response->module-info-map [response] (-> response :body cheshire/parse-string)) (deftest ^:integration environment-modules-integration-cache-disabled-test (testing "when environment modules cache is disabled for a module request" (bootstrap/with-puppetserver-running-with-config app (-> {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)] :max-active-instances 1}} (bootstrap/load-dev-config-with-overrides) (ks/dissoc-in [:jruby-puppet :environment-class-cache-enabled])) (logutils/with-test-logging (let [_foo-file (testutils/write-foo-pp-file "class foo (String $foo_1 = \"is foo\"){}") _all-foo-file (testutils/write-pp-file "class foo (String $foo_1 = \"is foo\"){}" "foo" "woo" "hoo" "1.0.0") expected-response {"modules" [{"name" "foo", "version" "1.0.0"}] "name" "production"} expected-all-response '({"modules" [{"name" "foo" "version" "1.0.0"}] "name" "hoo"} {"modules" [{"name" "foo" "version" "1.0.0"}] "name" "production"}) response (get-env-modules "production") all-response (get-all-env-modules) emptyenv-response (get-env-modules "") notreal-response (get-env-modules "notreal")] (testing "a successful status code is returned" (is (= 200 (:status response)) (str "unexpected status code for response, response: " (ks/pprint-to-string response)))) (testing "a failed status code is returned" (is (= 404 (:status notreal-response)) (str "unexpected status code for response, response: " (ks/pprint-to-string notreal-response)))) (testing "a failed status code is returned" (is (= 400 (:status emptyenv-response)) (str "unexpected status code for response, response: " (ks/pprint-to-string emptyenv-response)))) (testing "the expected response body is returned" (is (= expected-response (response->module-info-map response)))) (testing "a successful status code is returned" (is (= 200 (:status all-response)) (str "unexpected status code for response, response: " (ks/pprint-to-string all-response)))) (testing "the expected response body is returned" (is (= expected-all-response (response->module-info-map all-response))))))))) environment_transports_int_test.clj000066400000000000000000000650061470345337400370630ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/master(ns puppetlabs.services.master.environment-transports-int-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [clojure.string :as str] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-bootstrap-testutils] [puppetlabs.trapperkeeper.testutils.webserver :as jetty10] [puppetlabs.services.master.master-core :as master-core] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [cheshire.core :as json] [me.raynes.fs :as fs] [clojure.tools.logging :as log] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.trapperkeeper.testutils.logging :as logutils]) (:import (com.puppetlabs.puppetserver JRubyPuppetResponse JRubyPuppet) (java.util ArrayList))) (def test-resources-dir "./dev-resources/puppetlabs/services/master/environment_transports_int_test") (def gem-path [(ks/absolute-path jruby-testutils/gem-path)]) (def schema1 "require 'puppet/resource_api' Puppet::ResourceApi.register_transport( name: 'test_device', desc: 'Connects to a device', connection_info: { username: { type: 'String', desc: 'The name of the resource you want to manage.', }, variant_secret: { type: 'Optional[Variant[Array[String], Integer]]', desc: 'An array secret to protect.', sensitive: true, }, }, ) ") (def schema1-serialized {:name "test_device" :desc "Connects to a device" :connection_info_order ["username" "variant_secret"] :connection_info {:username {:type "String" :desc "The name of the resource you want to manage."} :variant_secret {:type "Optional[Variant[Array[String], Integer]]" :desc "An array secret to protect." :sensitive true}}}) (def schema2 "require 'puppet/resource_api' Puppet::ResourceApi.register_transport( name: 'another_device', desc: 'Connects to a network device', connection_info: { username: { type: 'String', desc: 'The name of the resource you want to manage.', }, secret: { type: 'String', desc: 'A secret to protect.', sensitive: true, }, }, )") (def schema2-serialized {:name "another_device" :desc "Connects to a network device" :connection_info_order ["username" "secret"] :connection_info {:username {:type "String" :desc "The name of the resource you want to manage."} :secret {:type "String" :desc "A secret to protect." :sensitive true}}}) (defn make-module ([] (make-module "production")) ([env] (let [module-dir (testutils/create-module "test_module" {:env-name env}) schema-dir (str/join "/" [module-dir "lib" "puppet" "transport" "schema"]) schema-file (str schema-dir "/test_device.rb")] (fs/mkdirs schema-dir) (spit schema-file schema1) schema-dir))) (defn purge-env-dir [] (-> testutils/conf-dir (fs/file "environments") fs/delete-dir)) (use-fixtures :once (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (use-fixtures :each #(logutils/with-test-logging (%)) (fn [f] (purge-env-dir) (try (f) (finally (purge-env-dir))))) (defn get-env-transports ([env-name] (get-env-transports env-name nil)) ([env-name if-none-match] (let [opts (when if-none-match {:headers {"If-None-Match" if-none-match}})] (try (http-client/get (str "https://localhost:8140/puppet/v3/" "environment_transports?" "environment=" env-name) (merge testutils/ssl-request-options {:as :text} opts)) (catch Exception e (throw (Exception. "environment_transports http get failed" e))))))) (defn purge-all-env-caches [] (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" testutils/ssl-request-options)) (defn purge-env-cache [env] (http-client/delete (str "https://localhost:8140/puppet-admin-api/v1/environment-cache?" "environment=" env) testutils/ssl-request-options)) (defn response-etag [request] (get-in request [:headers "etag"])) (defn etag-with-gzip-suffix [etag] (if (.endsWith etag "--gzip") etag (str etag "--gzip"))) (defn response->map [response] (-> response :body (json/parse-string true))) (deftest ^:integration environment-transports-integration-cache-disabled-test (testing "when environment cache is disabled for a transport request" (bootstrap/with-puppetserver-running-with-config app (-> {:jruby-puppet {:gem-path gem-path :max-active-instances 1}} (bootstrap/load-dev-config-with-overrides) (ks/dissoc-in [:jruby-puppet :environment-class-cache-enabled])) (let [_ (make-module) expected-response {:name "production" :transports [schema1-serialized]} response (get-env-transports "production")] (testing "a successful status code is returned" (is (= 200 (:status response)) (str "unexpected status code for response, response: " (ks/pprint-to-string response)))) (testing "no etag is returned" (is (false? (contains? (:headers response) "etag")))) (testing "the expected response body is returned" (is (= expected-response (response->map response)))))))) (deftest ^:integration environment-transports-integration-cache-enabled-test1 (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :environment-class-cache-enabled true}} (testing "environment transport cache invalidation for one environment" ;; This test is about ensuring that when the environment-cache ;; endpoint is hit for a single environment that only that the ;; environment class info cached for that environment - but not the ;; info cached for other environments - is invalidated, meaning that ;; the next request for class info for that environment will get fresh ;; data. ;; ;; The test has the following basic steps: ;; ;; 1) Purge the current environment files on disk and hit the ;; environment-cache endpoint to flush the cache for all ;; environments, basically to ensure nothing is left around from ;; other tests. ;; 2) Populate code for the 'test' and 'production' environments and ;; see that environment_transports queries return the right info for ;; them. ;; 3) Do one more environment_transports query for each environment, ;; using the etag from the initial queries, to ensure that a 304 ;; (Not Modified) is returned. ;; 4) Change code on disk for both the 'test' and 'production' ;; environments. ;; 5) Hit the environment-cache endpoint for the 'production' ;; environment (but not for the 'test' environment). ;; 6) Do two more environment_transports queries for the 'test' and ;; 'production' environments using the etags from the initial ;; queries. Confirm that the information reflects the latest data on ;; disk for the 'production' environment but still reflects the old ;; data for the 'test' environment - expected, in this case, because ;; the 'test' environment was not flushed. (purge-env-dir) (purge-all-env-caches) (let [prod-schema-dir (make-module) ;; should this have different content then above? test-schema-dir (make-module "test") production-response-initial (get-env-transports "production") production-etag-initial (response-etag production-response-initial) test-response-initial (get-env-transports "test") test-etag-initial (response-etag test-response-initial)] (is (= 200 (:status production-response-initial)) (str "unexpected status code for initial production response" "response: " (ks/pprint-to-string production-response-initial))) (is (not (nil? production-etag-initial)) "no etag returned for production response") (is (= {:name "production" :transports [schema1-serialized]} (response->map production-response-initial)) "unexpected body for production response") (is (= 200 (:status test-response-initial)) (str "unexpected status code for initial test response" "response: " (ks/pprint-to-string test-response-initial))) (is (not (nil? test-etag-initial)) "no etag returned for test response") (is (= {:name "test" :transports [schema1-serialized]} (response->map test-response-initial)) "unexpected body for test response") (spit (str prod-schema-dir "/test_device.rb") schema2) (spit (str test-schema-dir "/test_device.rb") schema2) (let [production-response-before-flush (get-env-transports "production" production-etag-initial) test-response-before-flush (get-env-transports "test" test-etag-initial)] (is (= 304 (:status production-response-before-flush)) (str "unexpected status code for prod response after code change " "but before flush")) (is (= production-etag-initial (response-etag production-response-before-flush)) "unexpected etag change when no production environment change") (is (empty? (:body production-response-before-flush)) "unexpected body for production response") (is (= 304 (:status test-response-before-flush)) (str "unexpected status code for test response after code change " "but before flush")) (is (= test-etag-initial (response-etag test-response-before-flush)) "unexpected etag change when no test environment change") (is (empty? (:body test-response-before-flush)) "unexpected body for test response")) (purge-env-cache "production") (let [production-response-after-prod-flush (get-env-transports "production" production-etag-initial) production-etag-after-prod-flush (response-etag production-response-after-prod-flush)] (is (= 200 (:status production-response-after-prod-flush)) (str "unexpected status code for prod response after code change " "and prod flush")) (is (not (nil? production-etag-after-prod-flush)) "no etag returned for production response") (is (not= production-etag-initial production-etag-after-prod-flush) (str "etag unexpectedly stayed the same even though " "the production environment changed"))))))) (deftest ^:integration environment-transports-integration-cache-enabled-test2 (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :environment-class-cache-enabled true}} (let [schema-dir (make-module) expected-initial-response {:name "production" :transports [schema1-serialized]} initial-response (get-env-transports "production") initial-etag (response-etag initial-response) initial-etag-with-gzip-suffix (etag-with-gzip-suffix initial-etag)] (testing "initial fetch of environment_transports info is good" (is (= 200 (:status initial-response)) (str "unexpected status code for initial response, response: " (ks/pprint-to-string initial-response))) (is (not (nil? initial-etag)) "no etag found for initial response") (is (= expected-initial-response (response->map initial-response)) "unexpected body for initial response")) (testing "etag not updated when code has not changed" (let [response (get-env-transports "production")] (is (= 200 (:status response)) "unexpected status code for response following no code change") (is (= initial-etag (response-etag response)) "etag changed even though code did not") (is (= expected-initial-response (response->map response)) "unexpected body for response"))) (testing (str "HTTP 304 (not modified) returned when request " "roundtrips last etag and code has not changed") (let [response (get-env-transports "production" initial-etag)] (is (= 304 (:status response)) (str "unexpected status code for response for no code change and " "original etag roundtripped")) (is (= initial-etag-with-gzip-suffix (response-etag response)) "etag changed even though code did not") (is (empty? (:body response)) "unexpected body for response"))) (testing (str "SERVER-1153 - HTTP 304 (not modified) returned when " "request roundtrips last etag with '--gzip' suffix and " "code has not changed") (let [response (get-env-transports "production" initial-etag-with-gzip-suffix)] (is (= 304 (:status response)) (str "unexpected status code for response for no code change and " "etag with '--gzip' suffix roundtripped")) (is (= initial-etag-with-gzip-suffix (response-etag response)) "etag changed even though code did not") (is (empty? (:body response)) "unexpected body for response"))) (testing (str "environment_transport fetch without if-none-match " "header includes latest info after code update") (let [_ (spit (str schema-dir "/test_device.rb") schema2) _ (purge-all-env-caches) response (get-env-transports "production")] (is (= 200 (:status response)) (str "unexpected status code for response following code change," "response: " (ks/pprint-to-string response))) (is (not= initial-etag (response-etag response)) "etag did not change even though code did")))))) (deftest ^:integration environment-transports-integration-cache-enabled-test3 (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :environment-class-cache-enabled true}} (testing "environment transports cache invalidation for all environments" ;; This test is about ensuring that when the environment-cache ;; endpoint is hit with no environment parameter that any previously ;; cached environment class info is invalidated, meaning that ;; the next request for class info for all environments will get fresh ;; data. ;; ;; To eliminate some of the redundancy between tests, this test doesn't ;; repeat the intermediate step of checking to see that the first two ;; environment queries were cached - 304 (Not Modified) returns - ;; between the first set of environment_transports queries and the second ;; set, done after the code on disk for both environments has changed. ;; ;; The test has the following basic steps: ;; ;; 1) Purge the current environment files on disk and hit the ;; environment-cache endpoint to flush the cache for all ;; environments, basically to ensure nothing is left around from ;; other tests. ;; 2) Populate code for the 'test' and 'production' environments and ;; see that environment_transports queries return the right info for ;; them. ;; 3) Change code on disk for both the 'test' and 'production' ;; environments. ;; 4) Hit the environment-cache endpoint with no environment ;; parameter, expected to have the effect of flushing the cache for ;; all environments. ;; 5) Do two more environment_transports queries for the 'test' and ;; 'production' environments with the corresponding etags returned ;; from the first two queries. Confirm that the information ;; reflects the latest data on disk for both environments. (purge-env-dir) (purge-all-env-caches) (let [prod-schema-dir (make-module) test-schema-dir (make-module "test") production-response-initial (get-env-transports "production") production-etag-initial (response-etag production-response-initial) test-response-initial (get-env-transports "test") test-etag-initial (response-etag test-response-initial)] (is (= 200 (:status production-response-initial)) (str "unexpected status code for initial production response" "response: " (ks/pprint-to-string production-response-initial))) (is (not (nil? production-etag-initial)) "no etag returned for production response") (is (= {:name "production" :transports [schema1-serialized]} (response->map production-response-initial)) "unexpected body for production response") (is (= 200 (:status test-response-initial)) (str "unexpected status code for initial test response" "response: " (ks/pprint-to-string test-response-initial))) (is (not (nil? test-etag-initial)) "no etag returned for test response") (is (= {:name "test" :transports [schema1-serialized]} (response->map test-response-initial)) "unexpected body for test response") (spit (str prod-schema-dir "/test_device.rb") schema2) (spit (str test-schema-dir "/test_device.rb") schema2) (purge-all-env-caches) (let [production-response-after-all-flush (get-env-transports "production" production-etag-initial) production-etag-after-all-flush (response-etag production-response-after-all-flush)] (is (= 200 (:status production-response-after-all-flush)) (str "unexpected status code for prod response after code change " "and all environment flush")) (is (not (nil? production-etag-after-all-flush)) "no etag returned for production response") (is (not= production-etag-initial production-etag-after-all-flush) (str "etag unexpectedly stayed the same even though " "the production environment changed"))) (let [test-response-after-all-flush (get-env-transports "test" test-etag-initial) test-etag-after-all-flush (response-etag test-response-after-all-flush)] (is (= 200 (:status test-response-after-all-flush)) (str "unexpected status code for test response after code change " "and all environment flush")) (is (not (nil? test-etag-after-all-flush)) "no etag returned for test response") (is (not= test-etag-initial test-etag-after-all-flush) (str "etag unexpectedly stayed the same even though " "the test environment changed"))))))) (deftest ^:integration not-modified-returned-for-environment-transports-info-request-with-gzip-tag (testing "SERVER-1153 - when the webserver gzips the response containing environment_transports etag, the next request roundtripping that etag returns an HTTP 304 (Not Modified)" (let [expected-etag "abcd1234" body-length 200000 jruby-service (reify jruby-protocol/JRubyPuppetService (get-cached-info-tag [_ _ _] expected-etag)) app (-> (fn [_] (master-core/response-with-etag (apply str (repeat body-length "a")) expected-etag)) (master-core/wrap-with-cache-check jruby-service))] (jetty10/with-test-webserver app port (let [request-url (str "http://localhost:" port) initial-response (http-client/get request-url {:as :text}) response-tag (response-etag initial-response) response-with-tag (http-client/get request-url {:headers {"If-None-Match" response-tag} :as :text})] (is (= 200 (:status initial-response)) "response for initial request is not 'successful'") (is (= (get-in initial-response [:headers "content-encoding"]) "gzip") "response from initial request was not gzipped") (is (= body-length (count (:body initial-response))) "unexpected response body length for initial response") (is (= (str expected-etag "--gzip") response-tag) "unexpected etag returned for initial response") (is (= 304 (:status response-with-tag)) (str "request with prior etag did not return http 304 (not " "modified) status code")) (is (empty? (:body response-with-tag)) "unexpected body for request with prior etag") (is (= (str expected-etag "--gzip") (response-etag response-with-tag)) "unexpected etag returned for request with prior etag")))))) (defn create-jruby-instance-with-mock-transports-info [wait-atom transports-info-atom config] (let [puppet-config (jruby-testutils/mock-puppet-config-settings (:jruby-puppet config))] (reify JRubyPuppet (getSetting [_ setting] (get puppet-config setting)) (getClassInfoForEnvironment [_ _] (let [class-info {"/some/file" {"classes" "foo"}}] class-info)) (getTransportInfoForEnvironment [_ _] (let [a (ArrayList.)] (.add a @transports-info-atom) (when-let [promises @wait-atom] (deliver (:wait-promise promises) true) @(:continue-promise promises)) a)) (handleRequest [_ _] (JRubyPuppetResponse. 0 nil nil nil)) (puppetVersion [_] "1.2.3") (terminate [_] (log/info "Terminating Master"))))) (deftest ^:integration transports-info-updated-after-cache-flush-during-prior-request (let [transports-info-atom (atom {:name "transport1"}) wait-atom (atom nil) config (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :environment-class-cache-enabled true}}) mock-jruby-fn (partial create-jruby-instance-with-mock-transports-info wait-atom transports-info-atom)] ;; This test uses a mock jruby instance function which can provide mock ;; data for an environment class info query and can suspend a request ;; long enough for the cached environment data to be invalidated. (tk-bootstrap-testutils/with-app-with-config app (bootstrap/services-from-dev-bootstrap-plus-mock-jruby-pool-manager-service config mock-jruby-fn) config (let [continue-promise (promise) wait-promise (promise) _ (reset! wait-atom {:continue-promise continue-promise :wait-promise wait-promise}) initial-response-future (future (get-env-transports "production"))] (is (true? (deref wait-promise 10000 :timed-out)) (str "timed out waiting for get transports info call to be reached " "in mock jrubypuppet instance")) (reset! transports-info-atom {:name "transport2"}) (purge-env-cache "production") (deliver continue-promise true) (let [initial-response @initial-response-future initial-response-etag (response-etag initial-response) _ (reset! wait-atom nil) response-after-update (get-env-transports "production" initial-response-etag)] (testing (str "initial request in progress while environment " "cache is invalidated contains original transports info") (is (= 200 (:status initial-response)) (str "unexpected status code for initial response" "response: " (ks/pprint-to-string initial-response))) (is (not (nil? initial-response-etag)) "no etag returned for initial response") (is (= {:name "production" :transports [{:name "transport1"}]} (response->map initial-response)) "unexpected body for initial response")) (testing (str "transports info updated properly for " "request made after environment cache was purged " "during a previous transports info request") (is (= 200 (:status response-after-update)) (str "unexpected status code for response after update, " "response: " (ks/pprint-to-string response-after-update))) (is (not= initial-response-etag (response-etag response-after-update)) "unexpected etag for response after update") (is (= {:name "production" :transports [{:name "transport2"}]} (response->map response-after-update)) "unexpected body for response after update"))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/master/master_service_test.clj000066400000000000000000001235441470345337400344420ustar00rootroot00000000000000(ns puppetlabs.services.master.master-service-test (:require [clojure.test :refer [deftest is testing use-fixtures]] ; [puppetlabs.services.master.master-service :refer :all] [cheshire.core :as json] [clojure.set :as setutils] [clojure.string :as str] [me.raynes.fs :as fs] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap-testutils] [puppetlabs.puppetserver.common :as common] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.services.jruby.jruby-metrics-core :as jruby-metrics-core] [puppetlabs.services.jruby.jruby-puppet-service :as jruby-service] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.services.master.master-core :as master-core] [puppetlabs.services.protocols.jruby-metrics :as jruby-metrics] [puppetlabs.services.protocols.puppet-profiler :as profiler-protocol] [puppetlabs.services.puppet-profiler.puppet-profiler-core :as puppet-profiler-core] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.services :as tk-services] [puppetlabs.trapperkeeper.services.metrics.metrics-core :as metrics-core] [puppetlabs.trapperkeeper.services.metrics.metrics-testutils :as metrics-testutils] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [schema.core :as schema] [schema.test :as schema-test])) (def test-resources-path "./dev-resources/puppetlabs/services/master/master_service_test") (def test-resources-code-dir (str test-resources-path "/codedir")) (def test-resources-conf-dir (str test-resources-path "/confdir")) (def master-service-test-runtime-dir "target/master-service-test") (def gem-path [(ks/absolute-path jruby-testutils/gem-path)]) (use-fixtures :once schema-test/validate-schemas (fn [f] (testutils/with-config-dirs {test-resources-conf-dir master-service-test-runtime-dir} (f)))) (use-fixtures :each #(logutils/with-test-logging (%))) (defn http-get [url] (let [master-service-test-runtime-ssl-dir (str master-service-test-runtime-dir "/ssl")] (http-client/get (str "https://localhost:8140" url) {:ssl-cert (str master-service-test-runtime-ssl-dir "/certs/localhost.pem") :ssl-key (str master-service-test-runtime-ssl-dir "/private_keys/localhost.pem") :ssl-ca-cert (str master-service-test-runtime-ssl-dir "/certs/ca.pem") :headers {"Accept" "application/json"} :as :text}))) (defn http-put [url body] (let [master-service-test-runtime-ssl-dir (str master-service-test-runtime-dir "/ssl")] (http-client/put (str "https://localhost:8140" url) {:ssl-cert (str master-service-test-runtime-ssl-dir "/certs/localhost.pem") :ssl-key (str master-service-test-runtime-ssl-dir "/private_keys/localhost.pem") :ssl-ca-cert (str master-service-test-runtime-ssl-dir "/certs/ca.pem") :body body :headers {"Accept" "application/json" "Content-type" "application/json"} :as :text}))) (defn http-post [url body] (let [master-service-test-runtime-ssl-dir (str master-service-test-runtime-dir "/ssl")] (http-client/post (str "https://localhost:8140" url) {:ssl-cert (str master-service-test-runtime-ssl-dir "/certs/localhost.pem") :ssl-key (str master-service-test-runtime-ssl-dir "/private_keys/localhost.pem") :ssl-ca-cert (str master-service-test-runtime-ssl-dir "/certs/ca.pem") :body body :headers {"Accept" "application/json" "Content-type" "application/json" "X-Puppet-Version" "6.3.0"} :as :text}))) (deftest ^:integration master-service-http-metrics (testing "HTTP metrics computed via use of the master service are correct" (bootstrap-testutils/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir} :metrics {:server-id "localhost"}} ;; mostly just making sure we can get here w/o exception (is (true? true)) ;; validate a few of the http metrics as long as we have the server up ;; anyway :) (let [master-service (tk-app/get-service app :MasterService) svc-context (tk-services/service-context master-service) http-metrics (:http-metrics svc-context) profiler-service (tk-app/get-service app :PuppetProfilerService) puppet-profiler (profiler-protocol/get-profiler profiler-service)] (logutils/with-test-logging (let [node-response (logutils/with-test-logging (http-get "/puppet/v3/node/foo?environment=production")) node-response-body (-> node-response :body json/parse-string)] (is (= 200 (:status node-response))) ;; Assert that some of the content looks like it came from the ;; node endpoint (is (= "foo" (get node-response-body "name"))) (is (= "production" (get node-response-body "environment")))) (let [old-fn @common/action-registration-function call-results (atom []) new-fn (fn [value] (swap! call-results conj value)) _ (reset! common/action-registration-function new-fn) catalog-response (logutils/with-test-logging (http-get "/puppet/v3/catalog/foo?environment=production")) catalog-response-body (-> catalog-response :body json/parse-string)] (is (= 200 (:status catalog-response))) ;; Assert that some of the content looks like it came from the ;; catalog endpoint (is (testutils/catalog-contains? catalog-response-body "Class" "Foo")) (is (= "foo" (get catalog-response-body "name"))) (is (= "production" (get catalog-response-body "environment"))) (testing "correctly reports node activity" (is (= [{:type :action, :targets ["foo"], :meta {:type :certificate, :what :compile-catalog, :where :v3}}] @call-results))) (reset! common/action-registration-function old-fn)) (is (= 404 (:status (http-get "/puppet/funky/town"))))) (is (= 3 (-> http-metrics :total-timer .getCount))) (is (= 1 (-> http-metrics :route-timers :other .getCount))) (is (= 1 (-> http-metrics :route-timers (get "puppet-v3-node-/*/") .getCount))) (is (= 1 (-> http-metrics :route-timers (get "puppet-v3-catalog-/*/") .getCount))) (is (= 0 (-> http-metrics :route-timers (get "puppet-v3-report-/*/") .getCount))) (testing "Catalog compilation increments catalog metrics and adds timing data" (let [profiler-status (puppet-profiler-core/v1-status puppet-profiler :debug) catalog-metrics (get-in profiler-status [:status :experimental :catalog-metrics]) metric-names (map :metric catalog-metrics) expected-metrics #{"compile" "find_node"}] ;; NOTE: If this test fails, then likely someone changed a metric ;; name passed to Puppet::Util::Profiler.profile over in the Puppet ;; project without realizing that is a breaking change to metrics ;; critical for measuring compiler performance. (is (setutils/subset? expected-metrics (set metric-names))) (doseq [metric-name expected-metrics :let [metric (first (filter #(= metric-name (:metric %)) catalog-metrics))]] (is (= 1 (metric :count))) (is (= (metric :aggregate) (metric :mean))))))) (let [resp (http-get "/status/v1/services?level=debug")] (is (= 200 (:status resp))) (let [status (json/parse-string (:body resp) true)] (is (= #{:ca :jruby-metrics :master :puppet-profiler :status-service :server} (set (keys status)))) (is (= 1 (get-in status [:jruby-metrics :service_status_version]))) (is (= "running" (get-in status [:jruby-metrics :state]))) (is (nil? (schema/check jruby-metrics-core/JRubyMetricsStatusV1 (get-in status [:jruby-metrics :status])))) (is (= jruby-metrics-core/jruby-pool-lock-not-in-use (get-in status [:jruby-metrics :status :experimental :jruby-pool-lock-status :current-state]))) (is (= 1 (get-in status [:master :service_status_version]))) (is (= "running" (get-in status [:master :state]))) (is (nil? (schema/check master-core/MasterStatusV1 (get-in status [:master :status])))) (testing "HTTP metrics in status endpoint are sorted in order of aggregate amount of time spent" (let [hit-routes #{"total" "puppet-v3-node-/*/" "puppet-v3-catalog-/*/" "other"} http-metrics (get-in status [:master :status :experimental :http-metrics])] (testing "'total' should come first since it is the sum of the other endpoints" (is (= "total" (:route-id (first http-metrics))))) (testing "The other two routes that actually received requests should come next" (is (= #{"puppet-v3-node-/*/" "puppet-v3-catalog-/*/"} (set (map :route-id (rest (take 3 http-metrics))))))) (testing "The aggregate times should be in descending order" (let [aggregate-times (map :aggregate http-metrics)] (= aggregate-times (reverse (sort aggregate-times))))) (testing "The counts should be accurate for the endpoints that we hit" (let [find-route (fn [route-metrics route-id] (first (filter #(= (:route-id %) route-id) route-metrics)))] (is (= 3 (:count (find-route http-metrics "total")))) (is (= 1 (:count (find-route http-metrics "puppet-v3-node-/*/")))) (is (= 1 (:count (find-route http-metrics "puppet-v3-catalog-/*/")))) (is (= 1 (:count (find-route http-metrics "other")))))) (testing "The counts should be zero for endpoints that we didn't hit" (is (every? #(= 0 %) (map :count (filter #(not (hit-routes (:route-id %))) http-metrics))))))) (testing "JRuby borrow times are tracked per-reason" (let [jruby-metrics (get-in status [:jruby-metrics :status :experimental :metrics])] (is (contains? jruby-metrics :borrow-timers)) (is (= #{:total :puppet-v3-catalog :puppet-v3-node} (set (keys (:borrow-timers jruby-metrics))))) (doseq [[_k v] (:borrow-timers jruby-metrics)] (is (nil? (schema/check jruby-metrics-core/TimerSummary v)))))) (is (= 1 (get-in status [:puppet-profiler :service_status_version]))) (is (= "running" (get-in status [:puppet-profiler :state]))) (is (nil? (schema/check puppet-profiler-core/PuppetProfilerStatusV1 (get-in status [:puppet-profiler :status])))) (let [function-metrics (get-in status [:puppet-profiler :status :experimental :function-metrics]) function-names (set (mapv :function function-metrics))] (is (contains? function-names "digest")) (is (contains? function-names "include"))) (let [resource-metrics (get-in status [:puppet-profiler :status :experimental :resource-metrics]) resource-names (set (mapv :resource resource-metrics))] (is (contains? resource-names "Class[Foo]")) (is (contains? resource-names "Class[Foo::Params]")) (is (contains? resource-names "Class[Foo::Bar]")))))))) (deftest ^:integration master-service-jruby-metrics (testing "JRuby metrics computed via use of the master service actions are correct" (bootstrap-testutils/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir} :metrics {:server-id "localhost"}} (let [jruby-metrics-service (tk-app/get-service app :JRubyMetricsService) svc-context (tk-services/service-context jruby-metrics-service) jruby-metrics (:metrics svc-context) jruby-service (tk-app/get-service app :JRubyPuppetService) time-before-first-borrow (System/currentTimeMillis)] ;; Use with-jruby-puppet to borrow the lone jruby out of the pool, ;; which should cause a subsequent catalog request to block on a borrow ;; request (jruby-service/with-jruby-puppet jruby-puppet jruby-service :master-service-metrics-test (let [time-before-second-borrow (System/currentTimeMillis)] (future (logutils/with-test-logging (http-get "/puppet/v3/catalog/localhost?environment=production"))) ;; Wait up to 10 seconds for the catalog request to get to the ;; point where it is in the jruby borrow queue. (while (and (< (- (System/currentTimeMillis) time-before-second-borrow) 10000) (nil? (-> jruby-metrics :requested-instances deref first (get-in [:reason :request :uri])))) (Thread/yield)) (let [resp (http-get "/status/v1/services/jruby-metrics?level=debug")] (is (= 200 (:status resp))) (let [status (json/parse-string (:body resp) true)] (is (= 1 (:service_status_version status))) (is (= "running" (:state status))) (testing "Info for borrowed instance is correct" (let [borrowed-instances (get-in status [:status :experimental :metrics :borrowed-instances]) borrowed-instance (first borrowed-instances)] (is (= 1 (count borrowed-instances))) (is (= "master-service-metrics-test" (:reason borrowed-instance))) (is (>= (:time borrowed-instance) time-before-first-borrow)) (is (> (:duration-millis borrowed-instance) 0)) (is (>= (System/currentTimeMillis) (+ (:duration-millis borrowed-instance) (:time borrowed-instance)))))) (testing "Info for requested instance is correct" (let [requested-instances (get-in status [:status :experimental :metrics :requested-instances]) requested-instance (first requested-instances)] (is (= 1 (count requested-instances))) (is (= {:request {:request-method "get" :route-id "puppet-v3-catalog-/*/" :uri "/puppet/v3/catalog/localhost"}} (:reason requested-instance))) (is (>= (:time requested-instance) time-before-second-borrow)) (is (> (:duration-millis requested-instance) 0)) (is (>= (System/currentTimeMillis) (+ (:duration-millis requested-instance) (:time requested-instance)))))))))))))) (def graphite-enabled-config {:metrics {:server-id "localhost" :reporters {:graphite {:update-interval-seconds 5000 :port 10001 :host "foo.localdomain"}} :registries {:puppetserver {:reporters {:graphite {:enabled true}}}}} :jruby-puppet {:gem-path gem-path :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir}}) (defn get-puppetserver-registry-context [app] (-> app (tk-app/get-service :MetricsService) tk-services/service-context :registries deref :puppetserver)) (defn get-puppetserver-graphite-reporter [app] (:graphite-reporter (get-puppetserver-registry-context app))) (deftest graphite-filtering-works (testing "default filter works" (let [reported-metrics-atom (atom {})] (with-redefs [metrics-core/build-graphite-sender (fn [_ domain] (metrics-testutils/make-graphite-sender reported-metrics-atom domain))] (logutils/with-test-logging (bootstrap-testutils/with-puppetserver-running app graphite-enabled-config (http-get "/puppet/v3/catalog/localhost?environment=production") (.report (get-puppetserver-graphite-reporter app)) (testing "reports metrics on the default list" (is (metrics-testutils/reported? @reported-metrics-atom :puppetserver "puppetlabs.localhost.compiler.compile.mean"))) (testing "doesn't report metrics not on the default list" (is (not (metrics-testutils/reported? @reported-metrics-atom :puppetserver "puppetlabs.localhost.compiler.compile.production.mean"))))))))) (testing "can add metrics to export to Graphite with the `metrics-allowed` setting" (let [reported-metrics-atom (atom {})] (with-redefs [metrics-core/build-graphite-sender (fn [_ domain] (metrics-testutils/make-graphite-sender reported-metrics-atom domain))] (logutils/with-test-logging (bootstrap-testutils/with-puppetserver-running app (assoc-in graphite-enabled-config [:metrics :registries :puppetserver :metrics-allowed] ["compiler.compile.production"]) (http-get "/puppet/v3/catalog/localhost?environment=production") (.report (get-puppetserver-graphite-reporter app)) (testing "reports metrics on the default list" (is (metrics-testutils/reported? @reported-metrics-atom :puppetserver "puppetlabs.localhost.compiler.compile.mean"))) (testing "reports metrics on the metrics-allowed list" (is (metrics-testutils/reported? @reported-metrics-atom :puppetserver "puppetlabs.localhost.compiler.compile.production.mean"))))))))) (deftest jvm-metrics-sent-to-graphite-test (let [reported-metrics-atom (atom {})] (with-redefs [metrics-core/build-graphite-sender (fn [_ domain] (metrics-testutils/make-graphite-sender reported-metrics-atom domain))] (bootstrap-testutils/with-puppetserver-running app graphite-enabled-config (let [registry (:registry (get-puppetserver-registry-context app)) get-memory-map (fn [mem-type] (ks/mapvals #(.getValue %) (filter #(.matches (key %) (format "puppetlabs.localhost.memory.%s.*" mem-type)) (.getMetrics registry)))) heap-memory-map (get-memory-map "heap") non-heap-memory-map (get-memory-map "non-heap") total-memory-map (get-memory-map "total")] (testing "heap memory metrics work" (is (= #{"puppetlabs.localhost.memory.heap.committed" "puppetlabs.localhost.memory.heap.init" "puppetlabs.localhost.memory.heap.max" "puppetlabs.localhost.memory.heap.used"} (ks/keyset heap-memory-map))) (is (every? #(< 0 %) (vals heap-memory-map)))) (testing "non-heap memory metrics work" (is (= #{"puppetlabs.localhost.memory.non-heap.committed" "puppetlabs.localhost.memory.non-heap.init" "puppetlabs.localhost.memory.non-heap.max" "puppetlabs.localhost.memory.non-heap.used"} (ks/keyset non-heap-memory-map))) ;; Some of the memory metrics don't propagate correctly on OS X, which can result in a ;; value of -1. This is here so that these tests will pass when run in developers local ;; environments. (is (every? #(or (< 0 %) (= -1 %)) (vals non-heap-memory-map)))) (testing "total memory metrics work" (is (= #{"puppetlabs.localhost.memory.total.committed" "puppetlabs.localhost.memory.total.init" "puppetlabs.localhost.memory.total.max" "puppetlabs.localhost.memory.total.used"} (ks/keyset total-memory-map))) (is (every? #(< 0 %) (vals total-memory-map)))) (testing "uptime metric works" (let [get-uptime (fn [] (-> registry .getMetrics (get "puppetlabs.localhost.uptime") .getValue)) uptime (get-uptime)] (is (< 0 uptime)) ;; Make sure uptime can be updated after initialization. (Thread/sleep 1) (is (not= uptime (get-uptime)))))) (.report (get-puppetserver-graphite-reporter app)) (testing "jvm metrics are reported to graphite" (is (every? #(metrics-testutils/reported? @reported-metrics-atom :puppetserver %) (map #(format "puppetlabs.localhost.memory.%s" %) ["heap.committed" "heap.init" "heap.max" "heap.used" "non-heap.committed" "non-heap.init" "non-heap.max" "non-heap.used" "total.committed" "total.init" "total.max" "total.used"]))) (is (metrics-testutils/reported? @reported-metrics-atom :puppetserver "puppetlabs.localhost.uptime"))))))) (defn get-http-client-metrics-status [] (-> "/status/v1/services/master?level=debug" http-get :body (json/parse-string true) (get-in [:status :experimental :http-client-metrics]))) (deftest ^:integration master-service-http-client-metrics (let [reported-metrics-atom (atom {})] (with-redefs [metrics-core/build-graphite-sender (fn [_ domain] (metrics-testutils/make-graphite-sender reported-metrics-atom domain))] (testing "HTTP client metrics are present in the master status" (bootstrap-testutils/with-puppetserver-running app graphite-enabled-config (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :http-client-metrics-test) container (:scripting-container jruby-instance)] (try (.runScriptlet container ;; create a client and assign it to a global variable "$c = Puppet::Server::HttpClient.new;") (let [make-request-with-metric-id (fn [metric-id-as-string] (.runScriptlet container ;; So long as the server and port are accessible, it ;; doesn't actually matter whether the endpoint is ;; reachable or not - we just need to make requests ;; with the given metric ids. (format "$c.get(URI('https://localhost:8140/fake'), options: {:metric_id => %s})" metric-id-as-string)))] (testing "http-client-metrics key in master status" (testing "empty array if no requests have been made" (is (= [] (get-http-client-metrics-status)))) (testing "doesn't include metrics for metric-ids it is not supposed to have" (make-request-with-metric-id "['fake', 'fake', 'fakery']") (is (= [] (get-http-client-metrics-status)))) (testing "includes metrics for metric-ids it is supposed to have" (make-request-with-metric-id "['puppetdb', 'query']") (is (= [["puppetdb" "query"]] (map :metric-id (get-http-client-metrics-status))))) (testing "only includes exact metric-ids it's supposed to have" (make-request-with-metric-id "['puppetdb', 'command', 'replace_catalog', 'foonode']") (let [metric-ids (map :metric-id (get-http-client-metrics-status))] (is (= #{["puppetdb" "query"] ["puppetdb" "command" "replace_catalog"]} (set metric-ids))))) (testing "includes all metrics it is supposed to have" (make-request-with-metric-id "['puppet', 'report', 'http']") (make-request-with-metric-id "['puppetdb', 'command', 'replace_facts', 'foonode']") (make-request-with-metric-id "['puppetdb', 'command', 'store_report', 'foonode']") (make-request-with-metric-id "['puppetdb', 'facts', 'find', 'foonode']") (make-request-with-metric-id "['puppetdb', 'facts', 'search']") (make-request-with-metric-id "['puppetdb', 'resource', 'search', 'Package']") (is (= (set master-core/puppet-server-http-client-metrics-for-status) (set (map :metric-id (get-http-client-metrics-status)))))) (testing "all metrics contain information they are supposed to have" (let [metrics (get-http-client-metrics-status)] (testing "contains correct keys" (is (every? #(= #{:metric-id :metric-name :count :mean :aggregate} (set (keys %))) metrics))) (testing "count is correct" (is (every? #(= 1 %) (map :count metrics)))) (testing "mean is correct" (is (every? #(< 0 %) (map :mean metrics)))) (testing "aggregate is correct" ;; since each metric-id has only been hit once, aggregate and mean should be the ;; same (is (every? (fn [{:keys [aggregate mean]}] #(= aggregate mean)) metrics))) (testing "metric-name is correct" (is (= (set (map #(str/join "." %) master-core/puppet-server-http-client-metrics-for-status)) (set (map ;; re-find returns a vector of results, the second element being the ;; capture match #(second (re-find #"puppetlabs.localhost.http-client.experimental.with-metric-id.(.*).full-response" (:metric-name %))) metrics))))))))) (testing "http client metrics are reported to graphite" (.report (get-puppetserver-graphite-reporter app)) (is (every? #(metrics-testutils/reported? @reported-metrics-atom :puppetserver %) (map #(format "puppetlabs.localhost.http-client.experimental.with-metric-id.%s.full-response.mean" %) ["puppet.report.http" "puppetdb.command.replace_catalog" "puppetdb.command.replace_facts" "puppetdb.command.store_report" "puppetdb.facts.find" "puppetdb.facts.search" "puppetdb.resource.search" "puppetdb.query"])))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :http-client-metrics-test))))))))) (deftest ^:integration add-metric-ids-to-http-client-metrics-list-test (let [test-service (tk-services/service [[:MasterService add-metric-ids-to-http-client-metrics-list!]] (init [_this context] (add-metric-ids-to-http-client-metrics-list! [["foo" "bar"] ["hello" "cruel" "world"]]) context))] (testing "add-metric-ids-to-http-client-metrics-list-fn works" (bootstrap-testutils/with-puppetserver-running-with-services app (conj (bootstrap-testutils/services-from-dev-bootstrap) test-service) {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir} :metrics {:server-id "localhost"}} (testing "atom has correct metric-ids" (let [master-service (tk-app/get-service app :MasterService) context (tk-services/service-context master-service)] (is (= (set (conj master-core/puppet-server-http-client-metrics-for-status ["foo" "bar"] ["hello" "cruel" "world"])) (set @(:http-client-metric-ids-for-status context)))))) (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :add-metric-ids-test) container (:scripting-container jruby-instance)] (try (.runScriptlet container ;; create a client and assign it to a global variable "$c = Puppet::Server::HttpClient.new;") (let [make-request-with-metric-id (fn [metric-id-as-string] (.runScriptlet container ;; So long as the server and port are accessible, it ;; doesn't actually matter whether the endpoint is ;; reachable or not - we just need to make requests ;; with the given metric ids. (format "$c.get(URI('https://localhost:8140/fake'), options: {:metric_id => %s})" metric-id-as-string)))] (testing "http-client-metrics key in master status" (make-request-with-metric-id "['foo', 'bar', 'baz']") (make-request-with-metric-id "['hello', 'cruel', 'world']") (make-request-with-metric-id "['puppetdb', 'query']") (make-request-with-metric-id "['fake', 'fake', 'fakery']") (let [metric-ids (map :metric-id (get-http-client-metrics-status))] (testing "has metric-ids from master service" (is (some #(= ["puppetdb" "query"] %) metric-ids))) (testing "has metric-ids added by `add-metric-ids-to-http-client-metrics-list`" (is (some #(= ["foo" "bar"] %) metric-ids)) (is (some #(= ["hello" "cruel" "world"] %) metric-ids))) (testing "doesn't include metrics for metric-ids it is not supposed to have" (is (not-any? #(= ["fake" "fake" "fakery"] %) metric-ids))) (testing "has correct set of metric-ids" (is (= #{["foo" "bar"] ["hello" "cruel" "world"] ["puppetdb" "query"]} (set metric-ids))))))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :add-metric-ids-test)))))))) (deftest ^:integration http-report-processor-client-metrics-test (testing "HTTP client metrics from the http report processor are added to status" (bootstrap-testutils/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 2 ; we need 2 jruby-instances since processing the report uses an instance :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir} :metrics {:server-id "localhost"}} (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :http-report-processor-metrics-test) container (:scripting-container jruby-instance)] (try ;; we don't care at all about the content of the report, just that it is valid (let [report (.runScriptlet container "Puppet::Transaction::Report.new('apply').to_json")] (logutils/with-test-logging ;; this test relies on the http report processor being configured in the puppet.conf ;; defined by `test-resources-puppet-conf`. We don't care whether the report is actually ;; submitted successfully, just that the underlying http client actually makes the ;; request, so the configured `reporturl` doesn't have a valid url, and we use ;; `with-test-logging` around this request to suppress the error. (let [resp (http-put "/puppet/v3/report/localhost?environment=production" report)] (testing "report was successfully submitted to http report processor" (is (= 200 (:status resp))) (is (= "[\"http\"]" (:body resp)))))) (testing "http-client-metrics key in status has metric for processing report" (let [metrics (get-http-client-metrics-status) {:keys [metric-id count mean aggregate metric-name]} (first metrics)] (is (= ["puppet" "report" "http"] metric-id)) (is (= 1 count)) (is (< 0 mean)) (is (= (* count mean) aggregate)) (is (= "puppetlabs.localhost.http-client.experimental.with-metric-id.puppet.report.http.full-response" metric-name))))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :http-report-processor-metrics-test))))))) (deftest ^:integration compiler-name-as-header (testing "POSTs to the v3 catalog endpoint return the certname as a header" (bootstrap-testutils/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir}} (let [resp (http-post "/puppet/v3/catalog/foo?environment=production" "")] (is (= "localhost" (get-in resp [:headers "x-puppet-compiler-name"]))))))) (deftest encoded-spaces-test (testing "Encoded spaces should be routed correctly" (bootstrap-testutils/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :server-conf-dir master-service-test-runtime-dir}} ;; SERVER-1954 - In bidi 1.25.0 and later, %20 in a URL would cause a 500 to be raised here instead (let [resp (http-get "/puppet/v3/enviro%20nment")] (is (= 404 (:status resp))))))) (deftest ^:integration facts-upload-api (let [tmpdir (fs/tmpdir)] (fs/mkdir (str tmpdir "/yaml")) (bootstrap-testutils/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 2 ; we need 2 jruby-instances since processing the upload uses an instance :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir :server-var-dir (fs/tmpdir)}} (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :facts-upload-endpoint-test) container (:scripting-container jruby-instance)] (try (let [facts (.runScriptlet container "facts = Puppet::Node::Facts.new('puppet.node.test') facts.values['foo'] = 'bar' facts.to_json") response (http-put "/puppet/v3/facts/puppet.node.test?environment=production" facts)] (testing "Puppet Server responds to PUT requests for /puppet/v3/facts" (is (= 200 (:status response)))) (testing "Puppet Server saves facts to the configured facts terminus" ;; Ensure the test is configured properly (is (= "yaml" (.runScriptlet container "Puppet::Node::Facts.indirection.terminus_class"))) (let [stored-facts (-> (.runScriptlet container "facts = Puppet::Node::Facts.indirection.find('puppet.node.test') (facts.nil? ? {} : facts).to_json") (json/parse-string))] (is (= "bar" (get-in stored-facts ["values" "foo"])))))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :facts-upload-endpoint-test))))))) (deftest ^:integration rich-data-is-honored (let [tmpdir (fs/tmpdir)] (fs/mkdir (str tmpdir "/yaml")) (bootstrap-testutils/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir :server-var-dir (fs/tmpdir)}} (let [jruby-service (tk-app/get-service app :JRubyPuppetService) jruby-instance (jruby-testutils/borrow-instance jruby-service :rich-data-test)] (try (let [container (:scripting-container jruby-instance) puppet-instance (:jruby-puppet jruby-instance) catalog-compiler (.runScriptlet container "o = Object.new; o.define_singleton_method(:compile) {|args| Puppet.lookup(:rich_data) }; o") _ (.callMethodWithArgArray container puppet-instance "instance_variable_set" (into-array Object ["@catalog_compiler" catalog-compiler]) Object) rich-data (.callMethodWithArgArray container puppet-instance "compileCatalog" (into-array Object [{}]) Boolean)] (testing "rich_data is true by default" (is (= true rich-data)))) (finally (jruby-testutils/return-instance jruby-service jruby-instance :rich-data-test))))))) (deftest ^:integration v4-queue-limit (bootstrap-testutils/with-puppetserver-running app {:jruby-puppet {:gem-path gem-path :max-active-instances 1 :max-retry-delay 1800 :max-queued-requests 1 :server-code-dir test-resources-code-dir :server-conf-dir master-service-test-runtime-dir :server-var-dir (fs/tmpdir)}} (let [metrics-svc (tk-app/get-service app :JRubyMetricsService) metrics (jruby-metrics/get-metrics metrics-svc) _ (swap! (:requested-instances metrics) assoc :foo "bar" :baz "bar")] (logutils/with-test-logging (testing "v4 catalog endpoint is affected by the jruby queue limit" (let [body "{\"certname\": \"foo\", \"persistence\": {\"facts\": false, \"catalog\": false}}" response (http-post "/puppet/v4/catalog" body) status-code (:status response) retry-after (-> response (get-in [:headers "retry-after"]) Integer/parseInt)] (is (= 503 status-code)) (is (<= 0 retry-after 1800)))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/master/plans_int_test.clj000066400000000000000000000136151470345337400334130ustar00rootroot00000000000000(ns puppetlabs.services.master.plans-int-test (:require [clojure.string :as str] [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [cheshire.core :as json] [me.raynes.fs :as fs])) (def test-resources-dir (ks/absolute-path "./dev-resources/puppetlabs/services/master/plans_int_test")) (defn plan-path [plan-name] (str test-resources-dir "/" plan-name)) (defn purge-env-dir [] (-> testutils/conf-dir (fs/file "environments") fs/delete-dir)) (use-fixtures :once (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (use-fixtures :each #(logutils/with-test-logging (%)) (fn [f] (purge-env-dir) (try (f) (finally (purge-env-dir))))) (def request-as-text-with-ssl (assoc testutils/ssl-request-options :as :text)) (defn get-all-plans [env-name] (let [url (str "https://localhost:8140/puppet/v3/plans" (when env-name (str "?environment=" env-name)))] (try (http-client/get url request-as-text-with-ssl) (catch Exception e (throw (Exception. "plans http get failed" e)))))) (defn get-plan-details "plan-name is the plan's full name, e.g. 'apache::reboot'." [env-name full-plan-name] (let [[module-name plan-name] (str/split full-plan-name #"::") url (str "https://localhost:8140/puppet/v3/plans/" module-name "/" plan-name (when env-name (str "?environment=" env-name)))] (try (http-client/get url request-as-text-with-ssl) (catch Exception e (throw (Exception. "plan info http get failed" e)))))) (defn parse-response [response] (-> response :body json/parse-string)) (defn sort-plans [plans] (sort-by #(get % "name") plans)) (def puppet-config (-> (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)] :max-active-instances 1}}) (ks/dissoc-in [:jruby-puppet :environment-class-cache-enabled]))) (deftest ^:integration all-plans-with-env (testing "full stack plans listing smoke test" (bootstrap/with-puppetserver-running-with-config app puppet-config (do (testutils/write-plans-files "apache" "announce" "return 'Hi!'") (testutils/write-plans-files "graphite" "init" "return 'Wheeeee'") (let [expected-response '({"name" "apache::announce" "environment" [{"name" "production" "code_id" nil}]} {"name" "graphite" "environment" [{"name" "production" "code_id" nil}]}) response (get-all-plans "production")] (testing "a successful status code is returned" (is (= 200 (:status response)) (str "unexpected status code for response, response: " (ks/pprint-to-string response)))) (testing "the expected response body is returned" (is (= expected-response (sort-plans (parse-response response)))))))))) (deftest ^:integration plan-details (testing "full stack plan metadata smoke test:" (bootstrap/with-puppetserver-running-with-config app puppet-config (let [metadata {}] (testutils/write-plans-files "shell" "poc" "String $message" "return $message") (testing "on a successful request," (let [response (get-plan-details "production" "shell::poc") code (:status response)] (testing "a successful status code is returned" (is (= 200 code) (str "unexpected status code " code " for response: " (ks/pprint-to-string response)))) (testing "the expected response body is returned" (let [expected-response {"metadata" metadata "name" "shell::poc"}] (is (= expected-response (parse-response response))))))) (testing "on a request that should error," (let [assert-plan-error (fn [status pattern env full-plan-name] (let [result (get-plan-details env full-plan-name)] (is (= status (:status result))) (is (re-find pattern (:body result)))))] (testing "returns 404 when the environment does not exist" (assert-plan-error 404 #"Could not find environment" "nopers" "shell::poc")) (testing "returns 404 when the module does not exist" (assert-plan-error 404 #"Could not find module" "production" "nomodule::poc")) (testing "returns 404 when the module name is invalid" (assert-plan-error 404 #"Could not find module" "production" "000::poc")) (testing "returns 404 when the plan does not exist" (assert-plan-error 404 #"Could not find plan" "production" "shell::noplan")) (testing "returns 404 when the plan name is invalid" (assert-plan-error 404 #"Could not find plan" "production" "shell::...")))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/master/tasks_int_test.clj000066400000000000000000000272011470345337400334170ustar00rootroot00000000000000(ns puppetlabs.services.master.tasks-int-test (:require [clojure.string :as str] [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.http.client.sync :as http-client] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [cheshire.core :as json] [me.raynes.fs :as fs])) (def test-resources-dir (ks/absolute-path "./dev-resources/puppetlabs/services/master/tasks_int_test")) (defn script-path [script-name] (str test-resources-dir "/" script-name)) (defn purge-env-dir [] (-> testutils/conf-dir (fs/file "environments") fs/delete-dir)) (use-fixtures :once (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) (use-fixtures :each #(logutils/with-test-logging (%)) (fn [f] (purge-env-dir) (try (f) (finally (purge-env-dir))))) (def request-as-text-with-ssl (assoc testutils/ssl-request-options :as :text)) (defn get-all-tasks [env-name] (let [url (str "https://localhost:8140/puppet/v3/tasks" (when env-name (str "?environment=" env-name)))] (try (http-client/get url request-as-text-with-ssl) (catch Exception e (throw (Exception. "tasks http get failed" e)))))) (defn get-task-details "task-name is the task's full name, e.g. 'apache::reboot'." [env-name full-task-name] (let [[module-name task-name] (str/split full-task-name #"::") url (str "https://localhost:8140/puppet/v3/tasks/" module-name "/" task-name (when env-name (str "?environment=" env-name)))] (try (http-client/get url request-as-text-with-ssl) (catch Exception e (throw (Exception. "task info http get failed" e)))))) (defn parse-response [response] (-> response :body json/parse-string)) (defn sort-tasks [tasks] (sort-by #(get % "name") tasks)) (def puppet-config (-> (bootstrap/load-dev-config-with-overrides {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)] :max-active-instances 1}}) (ks/dissoc-in [:jruby-puppet :environment-class-cache-enabled]))) (deftest ^:integration all-tasks-with-env (testing "full stack tasks listing smoke test" (bootstrap/with-puppetserver-running-with-config app puppet-config (do (testutils/write-tasks-files "apache" "announce" "echo 'Hi!'" (json/encode { "private" true "description" "the apache module" })) (testutils/write-tasks-files "graphite" "install" "wheeee" (json/encode {})) (let [expected-response '({"name" "apache::announce" "environment" [{"name" "production" "code_id" nil}] "private" true "description" "the apache module"} {"name" "graphite::install" "environment" [{"name" "production" "code_id" nil}] "private" false "description" ""}) response (get-all-tasks "production")] (testing "a successful status code is returned" (is (= 200 (:status response)) (str "unexpected status code for response, response: " (ks/pprint-to-string response)))) (testing "the expected response body is returned" (is (= expected-response (sort-tasks (parse-response response)))))))))) (deftest ^:integration task-details (testing "full stack task metadata smoke test:" (bootstrap/with-puppetserver-running-with-config app puppet-config (let [metadata {"description" "This is a test task" "output" "'Hello, world!'"}] (testutils/write-tasks-files "shell" "poc" "echo 'Hello, world!'" (json/encode metadata)) (testing "on a successful request," (let [response (get-task-details "production" "shell::poc") code (:status response)] (testing "a successful status code is returned" (is (= 200 code) (str "unexpected status code " code " for response: " (ks/pprint-to-string response)))) (testing "the expected response body is returned" (let [expected-response {"metadata" metadata "name" "shell::poc" "files" [{"filename" "poc.sh" "sha256" "f24ce8f82408237beebf1fadd8a3da74ebd44512c02eee5ec24cf536871359f7" "size_bytes" 20 "uri" {"path" "/puppet/v3/file_content/tasks/shell/poc.sh" "params" {"environment" "production"}}}]}] (is (= expected-response (parse-response response))))))) (testing "on a request that should error," (let [assert-task-error (fn [status pattern env full-task-name] (let [result (get-task-details env full-task-name)] (is (= status (:status result))) (is (re-find pattern (:body result)))))] (testutils/write-tasks-files "mysql" "test" "echo 'Hello, world!'" "This isn't JSON.") (testing "returns 404 when the environment does not exist" (assert-task-error 404 #"Could not find environment" "nopers" "shell::poc")) (testing "returns 404 when the module does not exist" (assert-task-error 404 #"Could not find module" "production" "nomodule::poc")) (testing "returns 404 when the module name is invalid" (assert-task-error 404 #"Could not find module" "production" "000::poc")) (testing "returns 404 when the task does not exist" (assert-task-error 404 #"Could not find task" "production" "shell::notask")) (testing "returns 404 when the task name is invalid" (assert-task-error 404 #"Could not find task" "production" "shell::...")) (testing "returns 500 when the metadata file is unparseable" (assert-task-error 500 #"puppet\.tasks/unparseable-metadata" "production" "mysql::test"))))))) (testing "full stack task metadata smoke test with code management:" (bootstrap/with-puppetserver-running-with-config app (assoc puppet-config :versioned-code {:code-id-command (script-path "echo") :code-content-command (script-path "hello_world")}) (let [metadata {"description" "This is a test task" "output" "'Hello, world!'"}] (testutils/write-tasks-files "shell" "echo" "echo 'Hello, world!'" (json/encode metadata)) (testing "on a successful request," (let [response (get-task-details "production" "shell::echo") code (:status response)] (testing "a successful status code is returned" (is (= 200 code) (str "unexpected status code " code " for response: " (ks/pprint-to-string response)))) (testing "the expected response body is returned" (let [expected-response {"metadata" metadata "name" "shell::echo" "files" [{"filename" "echo.sh" "sha256" "f24ce8f82408237beebf1fadd8a3da74ebd44512c02eee5ec24cf536871359f7" "size_bytes" 20 "uri" {"path" "/puppet/v3/static_file_content/modules/shell/tasks/echo.sh" "params" {"environment" "production" "code_id" "production"}}}]}] (is (= expected-response (parse-response response)))))))) (let [metadata {"description" "This is a test task" "output" "'Hello; world!'"}] (testutils/write-tasks-files "shell" "fail" "echo 'Hello; world!'" (json/encode metadata)) (testing "on a request that should error," (let [response (get-task-details "production" "shell::fail") code (:status response)] (testing "a successful status code is returned" (is (= 200 code) (str "unexpected status code " code " for response: " (ks/pprint-to-string response)))) (testing "the expected response body is returned" (let [expected-response {"metadata" metadata "name" "shell::fail" "files" [{"filename" "fail.sh" "sha256" "02ac3362307a6d18d4aa718ffd9a4de31e0233148faf57c6a002c5d6a9c3e57c" "size_bytes" 20 "uri" {"path" "/puppet/v3/file_content/tasks/shell/fail.sh" "params" {"environment" "production"}}}]}] (is (= expected-response (parse-response response)))))))))) (testing "full stack task metadata smoke test with unmanaged code:" (bootstrap/with-puppetserver-running-with-config app (assoc puppet-config :versioned-code {:code-id-command (script-path "echo") :code-content-command (script-path "warn_echo_and_error")}) (let [metadata {"description" "This is a test task" "output" "'Hello, world!'"}] (testutils/write-tasks-files "shell" "skip" "echo 'Hello, world!'" (json/encode metadata)) (testing "on a successful request," (let [response (get-task-details "production" "shell::skip") code (:status response)] (testing "a successful status code is returned" (is (= 200 code) (str "unexpected status code " code " for response: " (ks/pprint-to-string response)))) (testing "the expected response body is returned" (let [expected-response {"metadata" metadata "name" "shell::skip" "files" [{"filename" "skip.sh" "sha256" "f24ce8f82408237beebf1fadd8a3da74ebd44512c02eee5ec24cf536871359f7" "size_bytes" 20 "uri" {"path" "/puppet/v3/file_content/tasks/shell/skip.sh" "params" {"environment" "production"}}}]}] (is (= expected-response (parse-response response))))))))))) puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/puppet_admin/000077500000000000000000000000001470345337400310575ustar00rootroot00000000000000puppet_admin_int_test.clj000066400000000000000000000253331470345337400360760ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/integration/puppetlabs/services/puppet_admin(ns puppetlabs.services.puppet-admin.puppet-admin-int-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.kitchensink.core :as ks] [puppetlabs.http.client.sync :as http-client] [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [schema.test :as schema-test] [me.raynes.fs :as fs] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.puppetserver.testutils :as testutils :refer [ssl-request-options]] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core]) (:import (org.jruby.util.cli Options))) (use-fixtures :each #(logutils/with-test-logging (%)) ;; Clear changes to JRuby management settings after each test. (fn [f] (f) (.unforce Options/MANAGEMENT_ENABLED))) (def test-resources-dir "./dev-resources/puppetlabs/services/puppet_admin/puppet_admin_int_test") (def gem-path [(ks/absolute-path jruby-testutils/gem-path)]) (use-fixtures :once schema-test/validate-schemas (testutils/with-puppet-conf (fs/file test-resources-dir "puppet.conf"))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Tests ;; These tests use the `DELETE /environment-cache` endpoint as representative for testing ;; the whitelist functionality, since it interacts the best with mock JRubies, ;; making the tests faster. The same behavior applies also to the `DELETE /jruby-pool` ;; and the `GET /jruby-pool/thread-dump` endpoints. (deftest ^:integration admin-api-access-whitelist-control-test (testing "access denied when cert not on whitelist" (logutils/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because we do not care about the results of the API call." app {:jruby-puppet {:gem-path gem-path} :puppet-admin {:client-whitelist ["notlocalhost"]} :authorization {:version 1 :rules []}} (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" ssl-request-options)] (is (= 403 (:status response)) (ks/pprint-to-string response)))))) (testing "access allowed when cert on whitelist" (logutils/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because we do not care about the results of the API call." app {:jruby-puppet {:gem-path gem-path} :puppet-admin {:client-whitelist ["localhost"]} :authorization {:version 1 :rules []}} (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" ssl-request-options)] (is (<= 200 (:status response) 299) (ks/pprint-to-string response)))))) (testing "access allowed when whitelist disabled and no cert provided" (logutils/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because we do not care about the results of the API call." app {:jruby-puppet {:gem-path gem-path} :puppet-admin {:authorization-required false} :authorization {:version 1 :rules []}} (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" (select-keys ssl-request-options [:ssl-ca-cert]))] (is (<= 200 (:status response) 299) (ks/pprint-to-string response)))))) (testing "access denied when cert denied by rule" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because we do not care about the results of the API call." app {:jruby-puppet {:gem-path gem-path} :puppet-admin nil :authorization {:version 1 :rules [{:match-request {:path "/puppet-admin-api/v1" :type "path"} :allow "notlocalhost" :sort-order 1 :name "admin api"}]}} (logutils/with-test-logging (testing "when no encoded characters in uri" (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" ssl-request-options)] (is (= 403 (:status response)) (ks/pprint-to-string response)))) (testing "when encoded characters in uri" (let [response (http-client/delete (str "https://localhost:8140/pu%70pet-admin-api/" "v1/%65nvironment-cache") ssl-request-options)] (is (= 403 (:status response)) (ks/pprint-to-string response))))))) (testing "when cert allowed by rule and whitelist not configured" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because we do not care about the results of the API call." app {:jruby-puppet {:gem-path gem-path} :puppet-admin nil :authorization {:version 1 :rules [{:match-request {:path "/puppet-admin-api/v1" :type "path"} :allow "localhost" :sort-order 1 :name "admin api"}]}} (testing "access allowed when no encoded characters in uri" (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" ssl-request-options)] (is (<= 200 (:status response) 299) (ks/pprint-to-string response)))) (testing "access allowed for appropriate encoded characters in uri" (let [response (http-client/delete (str "https://localhost:8140/pu%70pet-admin-api/" "v1/%65nvironment-cache") ssl-request-options)] (is (= 204 (:status response)) (ks/pprint-to-string response)))) (testing "bad request returned when relative path in uri" (let [response (http-client/delete (str "https://localhost:8140/pu%70pet-admin-api/" "v1/%65nvironment-cache/%2E%2E/bad-place") ssl-request-options)] (is (= 400 (:status response)) (ks/pprint-to-string response)))))) (testing "access allowed when cert allowed by rule and whitelist empty" (logutils/with-test-logging (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because we do not care about the results of the API call." app {:jruby-puppet {:gem-path gem-path} :puppet-admin {:client-whitelist []} :authorization {:version 1 :rules [{:match-request {:path "/puppet-admin-api/v1" :type "path"} :allow "localhost" :sort-order 1 :name "admin api"}]}} (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" ssl-request-options)] (is (<= 200 (:status response) 299) (ks/pprint-to-string response)))))) (testing "server tolerates client specifying an 'Accept: */*' header" (bootstrap/with-puppetserver-running-with-mock-jrubies "JRuby mocking is safe here because we do not care about the results of the API call." app {:jruby-puppet {:gem-path gem-path}} (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/environment-cache" (assoc ssl-request-options :headers {"Accept" "*/*"}))] (is (<= 200 (:status response) 299) (ks/pprint-to-string response)))))) (deftest ^:integration admin-api-pool-timeout-test (testing "pool lock timeout results in 503" (logutils/with-test-logging (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)] :flush-timeout 0}} ; Borrow a jruby instance so that the timeout of 0 is reached immediately (let [jruby-service (tk-app/get-service app :JRubyPuppetService) pool-context (jruby-protocol/get-pool-context jruby-service) pool (jruby-core/get-pool pool-context) borrowed-instance (.borrowItem pool)] (try (let [response (http-client/delete "https://localhost:8140/puppet-admin-api/v1/jruby-pool" ssl-request-options)] (is (= 503 (:status response))) (is (= "An attempt to lock the JRubyPool failed with a timeout" (slurp (:body response))))) (finally (.releaseItem pool borrowed-instance)))))))) (deftest ^:integration admin-api-jruby-thread-dump-test (testing "returns a 200 result when jruby.management.enabled is set to true" (.force Options/MANAGEMENT_ENABLED "true") (logutils/with-test-logging (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]}} (let [response (http-client/get "https://localhost:8140/puppet-admin-api/v1/jruby-pool/thread-dump" ssl-request-options)] (is (= 200 (:status response))) (is (re-find #"All threads known to Ruby instance" (slurp (:body response)))))))) (testing "returns a 500 result when jruby.management.enabled is set to false" (.force Options/MANAGEMENT_ENABLED "false") (logutils/with-test-logging (bootstrap/with-puppetserver-running app {:jruby-puppet {:gem-path [(ks/absolute-path jruby-testutils/gem-path)]}} (let [response (http-client/get "https://localhost:8140/puppet-admin-api/v1/jruby-pool/thread-dump" ssl-request-options)] (is (= 500 (:status response))) (is (re-find #"JRuby management interface not enabled" (slurp (:body response))))))))) ;; See 'environment-flush-integration-test' ;; for additional test coverage on the /environment-cache endpoint puppetlabs-puppetserver-7e1a9a8/test/unit/000077500000000000000000000000001470345337400210245ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/000077500000000000000000000000001470345337400232035ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/puppetserver/000077500000000000000000000000001470345337400257475ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/puppetserver/certificate_authority_test.clj000066400000000000000000003602501470345337400341000ustar00rootroot00000000000000(ns puppetlabs.puppetserver.certificate-authority-test (:require [clj-time.coerce :as time-coerce] [clj-time.core :as time] [clojure.java.io :as io] [clojure.set :as set] [clojure.string :as string] [clojure.test :refer [deftest is testing use-fixtures]] [me.raynes.fs :as fs] [puppetlabs.kitchensink.core :as ks] [puppetlabs.kitchensink.file :as ks-file] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.puppetserver.common :as common] [puppetlabs.services.ca.ca-testutils :as testutils] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.ssl-utils.core :as utils] [puppetlabs.ssl-utils.simple :as simple] [puppetlabs.trapperkeeper.testutils.logging :refer [logged?] :as logutils] [schema.test :as schema-test] [slingshot.test :refer :all]) (:import (com.puppetlabs.ssl_utils SSLUtils) (java.io ByteArrayInputStream ByteArrayOutputStream File StringReader StringWriter) (java.nio.file Files Path) (java.nio.file.attribute FileAttribute) (java.security MessageDigest PublicKey) (java.security.cert X509CRL X509Certificate) (java.time LocalDateTime ZoneOffset) (java.util Date) (java.util.concurrent TimeUnit) (java.util.concurrent.locks ReentrantReadWriteLock) (org.bouncycastle.asn1.x509 SubjectPublicKeyInfo) (org.joda.time DateTime Period))) (use-fixtures :once schema-test/validate-schemas) (use-fixtures :each #(logutils/with-test-logging (%))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Test Data (def test-resources-dir "./dev-resources/puppetlabs/puppetserver/certificate_authority_test") (def confdir (str test-resources-dir "/master/conf")) (def ssldir (str confdir "/ssl")) (def cadir (str confdir "/ca")) (def cacert (str cadir "/ca_crt.pem")) (def cakey (str cadir "/ca_key.pem")) (def capub (str cadir "/ca_pub.pem")) (def cacrl (str cadir "/ca_crl.pem")) (def csrdir (str cadir "/requests")) (def signeddir (str cadir "/signed")) (def test-pems-dir (str test-resources-dir "/pems")) (def autosign-confs-dir (str test-resources-dir "/autosign_confs")) (def autosign-exes-dir (str test-resources-dir "/autosign_exes")) (def csr-attributes-dir (str test-resources-dir "/csr_attributes")) (def bundle-dir (str test-pems-dir "/bundle")) (def bundle-cadir (str bundle-dir "/ca")) (defn test-pem-file [pem-file-name] (str test-pems-dir "/" pem-file-name)) (defn autosign-conf-file [autosign-conf-file-name] (str autosign-confs-dir "/" autosign-conf-file-name)) (defn autosign-exe-file [autosign-exe-file-name] (ks/absolute-path (str autosign-exes-dir "/" autosign-exe-file-name))) (defn csr-attributes-file [csr-attributes-file-name] (str csr-attributes-dir "/" csr-attributes-file-name)) (def all-perms (for [r "r-" w "w-" x "x-"] (str r w x))) (def attribute-file-extensions "These are the extensions defined in the test fixture csr_attributes.yaml, used in this test namespace." [{:oid "1.3.6.1.4.1.34380.1.1.1" :critical false :value "ED803750-E3C7-44F5-BB08-41A04433FE2E"} {:oid "1.3.6.1.4.1.34380.1.1.1.4" :critical false :value "I am undefined but still work"} {:oid "1.3.6.1.4.1.34380.1.1.2" :critical false :value "thisisanid"} {:oid "1.3.6.1.4.1.34380.1.1.3" :critical false :value "my_ami_image"} {:oid "1.3.6.1.4.1.34380.1.1.4" :critical false :value "342thbjkt82094y0uthhor289jnqthpc2290"} {:oid "1.3.6.1.4.1.34380.1.1.5" :critical false :value "center"} {:oid "1.3.6.1.4.1.34380.1.1.6" :critical false :value "product"} {:oid "1.3.6.1.4.1.34380.1.1.7" :critical false :value "project"} {:oid "1.3.6.1.4.1.34380.1.1.8" :critical false :value "application"} {:oid "1.3.6.1.4.1.34380.1.1.9" :critical false :value "service"} {:oid "1.3.6.1.4.1.34380.1.1.10" :critical false :value "employee"} {:oid "1.3.6.1.4.1.34380.1.1.11" :critical false :value "created"} {:oid "1.3.6.1.4.1.34380.1.1.12" :critical false :value "environment"} {:oid "1.3.6.1.4.1.34380.1.1.13" :critical false :value "role"} {:oid "1.3.6.1.4.1.34380.1.1.14" :critical false :value "version"} {:oid "1.3.6.1.4.1.34380.1.1.15" :critical false :value "deparment"} {:oid "1.3.6.1.4.1.34380.1.1.16" :critical false :value "cluster"} {:oid "1.3.6.1.4.1.34380.1.1.17" :critical false :value "provisioner"}]) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utilities (defn tmp-whitelist! [& lines] (let [whitelist (ks/temp-file)] (doseq [line lines] (spit whitelist (str line "\n") :append true)) (str whitelist))) (def empty-stream (ByteArrayInputStream. (.getBytes ""))) (defn csr-stream [subject] (io/input-stream (ca/path-to-cert-request csrdir subject))) (defn write-to-stream [o] (let [s (ByteArrayOutputStream.)] (utils/obj->pem! o s) (-> s .toByteArray ByteArrayInputStream.))) (defn assert-autosign [whitelist subject] (testing subject (is (true? (ca/autosign-csr? whitelist subject empty-stream))))) (defn assert-no-autosign [whitelist subject] (testing subject (is (false? (ca/autosign-csr? whitelist subject empty-stream))))) (defn contains-ext? "Does the provided extension list contain an extensions with the given OID." [ext-list oid] (> (count (filter #(= oid (:oid %)) ext-list)) 0)) ;; TODO copied from jvm-ssl-utils testutils. That lib should be updated ;; to expose its test jar so we can use this directly instead. (defn pubkey-sha1 "Gets the SHA-1 digest of the raw bytes of the provided publickey." [pub-key] {:pre [(utils/public-key? pub-key)] :post [(vector? %) (every? integer? %)]} (let [bytes (-> ^PublicKey pub-key .getEncoded SubjectPublicKeyInfo/getInstance .getPublicKeyData .getBytes)] (vec (.digest (MessageDigest/getInstance "SHA1") bytes)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Tests (deftest symlink-cadir-test (testing "does not symlink if custom cadir" (let [tmpdir (ks/temp-dir) cadir (str tmpdir "/foo/bar") ssldir (str tmpdir "puppet/ssl")] (fs/mkdirs cadir) (fs/mkdirs ssldir) (ca/symlink-cadir cadir) (is (not (fs/exists? (str ssldir "/ca")))))) (testing "symlinks correctly and removes existing old-cadir if needed" (let [tmpdir (ks/temp-dir) cadir (str tmpdir "/puppetserver/ca") ssldir (str tmpdir "/puppet/ssl") old-cadir (str ssldir "/ca")] (fs/mkdirs ssldir) (fs/mkdirs cadir) (ca/symlink-cadir cadir) (is (fs/link? old-cadir)) (let [target (-> old-cadir fs/read-sym-link str)] (is (= target cadir)))))) (deftest validate-settings-test (testing "invalid ca-ttl is rejected" (let [settings (assoc (testutils/ca-settings cadir) :ca-ttl (+ ca/max-ca-ttl 1))] (is (thrown-with-msg? IllegalStateException #"ca_ttl must have a value below" (ca/validate-settings! settings))))) (testing "warns if :client-whitelist is set in c-a.c-s section" (let [settings (assoc-in (testutils/ca-settings cadir) [:access-control :certificate-status :client-whitelist] ["whitelist"])] (logutils/with-test-logging (ca/validate-settings! settings) (is (logutils/logged? #"Remove these settings and create" :warn))))) (testing "warns if :authorization-required is overridden in c-a.c-s section" (let [settings (assoc-in (testutils/ca-settings cadir) [:access-control :certificate-status :authorization-required] false)] (logutils/with-test-logging (ca/validate-settings! settings) (is (logutils/logged? #"Remove these settings and create" :warn))))) (testing "warns if :client-whitelist is set incorrectly" (let [settings (assoc-in (testutils/ca-settings cadir) [:access-control :certificate-status :client-whitelist] [])] (logutils/with-test-logging (ca/validate-settings! settings) (is (logutils/logged? #"remove the 'certificate-authority' configuration" :warn)))))) (deftest get-certificate-test (testing "returns CA certificate when subject is 'ca'" (let [actual (ca/get-certificate "ca" cacert signeddir) expected (slurp cacert)] (is (= expected actual)))) (testing "returns localhost certificate when subject is 'localhost'" (let [localhost-cert (ca/get-certificate "localhost" cacert signeddir) expected (slurp (ca/path-to-cert signeddir "localhost"))] (is (= expected localhost-cert)))) (testing "returns nil when certificate not found for subject" (is (nil? (ca/get-certificate "not-there" cacert signeddir))))) (deftest get-certificate-request-test (testing "returns certificate request for subject" (let [cert-req (ca/get-certificate-request "test-agent" csrdir) expected (slurp (ca/path-to-cert-request csrdir "test-agent"))] (is (= expected cert-req)))) (testing "returns nil when certificate request not found for subject" (is (nil? (ca/get-certificate-request "not-there" csrdir))))) (deftest autosign-csr?-test (testing "boolean values" (is (true? (ca/autosign-csr? true "unused" empty-stream))) (is (false? (ca/autosign-csr? false "unused" empty-stream)))) (testing "whitelist" (testing "autosign is false when whitelist doesn't exist" (is (false? (ca/autosign-csr? "Foo/conf/autosign.conf" "doubleagent" empty-stream)))) (testing "exact certnames" (doto (tmp-whitelist! "foo" "UPPERCASE" "this.THAT." "bar1234" "AB=foo,BC=bar,CD=rab,DE=oof,EF=1a2b3d") (assert-autosign "foo") (assert-autosign "UPPERCASE") (assert-autosign "this.THAT.") (assert-autosign "bar1234") (assert-autosign "AB=foo,BC=bar,CD=rab,DE=oof,EF=1a2b3d") (assert-no-autosign "Foo") (assert-no-autosign "uppercase") (assert-no-autosign "this-THAT-"))) (testing "domain-name globs" (doto (tmp-whitelist! "*.red" "*.black.local" "*.UPPER.case") (assert-autosign "red") (assert-autosign ".red") (assert-autosign "green.red") (assert-autosign "blue.1.red") (assert-no-autosign "red.white") (assert-autosign "black.local") (assert-autosign ".black.local") (assert-autosign "blue.black.local") (assert-autosign "2.three.black.local") (assert-no-autosign "red.local") (assert-no-autosign "black.local.white") (assert-autosign "one.0.upper.case") (assert-autosign "two.upPEr.case") (assert-autosign "one-two-three.red"))) (testing "allow all with '*'" (doto (tmp-whitelist! "*") (assert-autosign "foo") (assert-autosign "BAR") (assert-autosign "baz-buz.") (assert-autosign "0.qux.1.xuq") (assert-autosign "AB=foo,BC=bar,CD=rab,DE=oof,EF=1a2b3d"))) (testing "ignores comments and blank lines" (doto (tmp-whitelist! "#foo" " " "bar" "" "# *.baz" "*.qux") (assert-no-autosign "foo") (assert-no-autosign " ") (assert-autosign "bar") (assert-no-autosign "foo.baz") (assert-autosign "bar.qux"))) (testing "invalid lines logged and ignored" (doseq [invalid-line ["bar#bar" " #bar" "bar " " bar"]] (let [whitelist (tmp-whitelist! "foo" invalid-line "qux")] (assert-autosign whitelist "foo") (logutils/with-test-logging (assert-no-autosign whitelist invalid-line) (is (logged? (re-pattern (format "Invalid pattern '%s' found in %s" invalid-line whitelist)))) (assert-autosign whitelist "qux"))))) (testing "sample file that covers everything" (logutils/with-test-logging (doto (autosign-conf-file "autosign-whitelist.conf") (assert-no-autosign "aaa") (assert-autosign "bbb123") (assert-autosign "one_2.red") (assert-autosign "1.blacK.6") (assert-no-autosign "black.white") (assert-no-autosign "coffee") (assert-no-autosign "coffee#tea") (assert-autosign "qux")))))) (deftest autosign-csr?-ruby-exe-test (let [executable (autosign-exe-file "ruby-autosign-executable") csr-fn #(csr-stream "test-agent") ruby-load-path jruby-testutils/ruby-load-path ruby-gem-path jruby-testutils/gem-path] (testing "stdout is added to master's log at debug level" (logutils/with-test-logging (ca/autosign-csr? executable "test-agent" (csr-fn) ruby-load-path ruby-gem-path) (is (logged? #"print to stdout" :debug) "Do you have puppet installed locally in addition to the submodule?"))) (testing "stderr is added to master's log at warn level" (logutils/with-test-logging (ca/autosign-csr? executable "test-agent" (csr-fn) ruby-load-path ruby-gem-path) (is (logged? #"generated output to stderr: print to stderr" :warn) "Do you have puppet installed locally in addition to the submodule?"))) (testing "non-zero exit-code generates a log entry at warn level" (logutils/with-test-logging (ca/autosign-csr? executable "foo" (csr-fn) ruby-load-path ruby-gem-path) (is (logged? #"rejected certificate 'foo'" :warn)))) (testing "subject is passed as argument and CSR is provided on stdin" (logutils/with-test-logging (ca/autosign-csr? executable "test-agent" (csr-fn) ruby-load-path ruby-gem-path) (is (logged? #"subject: test-agent")) (is (logged? #"CSR for: test-agent")))) (testing "only exit code 0 results in autosigning" (logutils/with-test-logging (is (true? (ca/autosign-csr? executable "test-agent" (csr-fn) ruby-load-path ruby-gem-path))) (is (false? (ca/autosign-csr? executable "foo" (csr-fn) ruby-load-path ruby-gem-path))))))) (deftest autosign-csr?-bash-exe-test (let [executable (autosign-exe-file "bash-autosign-executable") csr-fn #(csr-stream "test-agent")] (testing "stdout is added to master's log at debug level" (logutils/with-test-logging (ca/autosign-csr? executable "test-agent" (csr-fn)) (is (logged? #"print to stdout" :debug)))) (testing "stderr is added to master's log at warn level" (logutils/with-test-logging (ca/autosign-csr? executable "test-agent" (csr-fn)) (is (logged? #"generated output to stderr: print to stderr" :warn)))) (testing "non-zero exit-code generates a log entry at warn level" (logutils/with-test-logging (ca/autosign-csr? executable "foo" (csr-fn)) (is (logged? #"rejected certificate 'foo'" :warn)))) (testing "subject is passed as argument and CSR is provided on stdin" (logutils/with-test-logging (ca/autosign-csr? executable "test-agent" (csr-fn)) (is (logged? #"subject: test-agent")) (is (logged? #"-----BEGIN CERTIFICATE REQUEST-----")))) (testing "only exit code 0 results in autosigning" (logutils/with-test-logging (is (true? (ca/autosign-csr? executable "test-agent" (csr-fn)))) (is (false? (ca/autosign-csr? executable "foo" (csr-fn)))))))) (deftest save-certificate-request!-test (testing "requests are saved to disk" (let [csrdir (:csrdir (testutils/ca-sandbox! cadir)) csr (utils/pem->csr (ca/path-to-cert-request csrdir "test-agent")) path (ca/path-to-cert-request csrdir "foo")] (is (false? (fs/exists? path))) (ca/save-certificate-request! "foo" csr csrdir) (is (true? (fs/exists? path))) (is (= (ca/get-certificate-request csrdir "foo") (ca/get-certificate-request csrdir "test-agent")))))) (deftest autosign-certificate-request!-test (let [now (time/epoch) two-years (* 60 60 24 365 2) settings (-> (testutils/ca-sandbox! cadir) (assoc :ca-ttl two-years)) csr (-> (:csrdir settings) (ca/path-to-cert-request "test-agent") (utils/pem->csr)) expected-cert-path (ca/path-to-cert (:signeddir settings) "test-agent") old-fn @common/action-registration-function call-results (atom []) new-fn (fn [value] (swap! call-results conj value))] (reset! common/action-registration-function new-fn) ;; Fix the value of "now" so we can reliably test the dates (time/do-at now (ca/autosign-certificate-request! "test-agent" csr settings (constantly nil))) (testing "requests are autosigned and saved to disk" (is (fs/exists? expected-cert-path))) (let [cert (utils/pem->cert expected-cert-path)] (testing "The subject name on the agent's cert" (testutils/assert-subject cert "CN=test-agent")) (testing "The cert is issued by the name on the CA's cert" (testutils/assert-issuer cert "CN=Puppet CA: localhost")) (testing "certificate has not-before/not-after dates based on $ca-ttl" (let [not-before (time-coerce/from-date (.getNotBefore cert)) not-after (time-coerce/from-date (.getNotAfter cert))] (testing "not-before is 1 day before now" (is (= (time/minus now (time/days 1)) not-before))) (testing "not-after is 2 years from now" (is (= (time/plus now (time/years 2)) not-after))))) (testing "correctly reports node activity" (is (= [{:type :add, :targets ["test-agent"], :meta {:type :certificate}}] @call-results))) (reset! common/action-registration-function old-fn)))) (deftest autosign-without-capub (testing "The CA public key file is not necessary to autosign" (let [settings (testutils/ca-sandbox! cadir) csr (-> (:csrdir settings) (ca/path-to-cert-request "test-agent") (utils/pem->csr)) cert-path (ca/path-to-cert (:signeddir settings) "test-agent")] (fs/delete (:capub settings)) (ca/autosign-certificate-request! "test-agent" csr settings (constantly nil)) (is (true? (fs/exists? cert-path))) (let [cert (utils/pem->cert cert-path) capub (-> (:cacert settings) (utils/pem->cert) (.getPublicKey))] (is (nil? (.verify cert capub))))))) (deftest autosign-as-intermediate-ca (testing "The CA certificate file can be a bundle of certs" (let [settings (testutils/ca-sandbox! bundle-cadir) csr (-> (:csrdir settings) (ca/path-to-cert-request "test-agent") (utils/pem->csr)) cert-path (ca/path-to-cert (:signeddir settings) "test-agent")] (ca/autosign-certificate-request! "test-agent" csr settings (constantly nil)) (is (true? (fs/exists? cert-path))) (let [cert (utils/pem->cert cert-path) capub (-> (:cacert settings) (utils/pem->certs) (first) (.getPublicKey))] (is (nil? (.verify cert capub))))))) (deftest revoke-without-capub (testing "The CA public key file is not necessary to revoke" (let [settings (testutils/ca-sandbox! cadir) cert (-> (:signeddir settings) (ca/path-to-cert "localhost") (utils/pem->cert)) revoked? (fn [cert] (-> (:cacrl settings) (utils/pem->crl) (utils/revoked? cert)))] (fs/delete (:capub settings)) (is (false? (revoked? cert))) (ca/revoke-existing-certs! settings ["localhost"] (constantly nil)) (is (true? (revoked? cert)))))) (deftest revoke-as-intermediate-ca (testing "The CA certificate file can be a bundle when revoking a certificate" (let [settings (testutils/ca-sandbox! bundle-cadir) cert (-> (:signeddir settings) (ca/path-to-cert "localhost") (utils/pem->cert)) ca-cert (utils/pem->ca-cert (:cacert settings) (:cakey settings)) revoked? (fn [cert] (-> (:cacrl settings) (utils/pem->ca-crl ca-cert) (utils/revoked? cert)))] (is (false? (revoked? cert))) (ca/revoke-existing-certs! settings ["localhost"] (constantly nil)) (is (true? (revoked? cert)))))) (deftest revoke-multiple-certs (testing "The revocation function can accept a list of certs to revoke" (let [settings (testutils/ca-sandbox! cadir) cert1 (-> (:signeddir settings) (ca/path-to-cert "localhost") (utils/pem->cert)) cert2 (-> (:signeddir settings) (ca/path-to-cert "test_cert") (utils/pem->cert)) revoked? (fn [cert] (-> (:cacrl settings) (utils/pem->crl) (utils/revoked? cert))) old-fn @common/action-registration-function call-results (atom []) new-fn (fn [value] (swap! call-results conj value))] (reset! common/action-registration-function new-fn) (is (false? (revoked? cert1))) (is (false? (revoked? cert2))) (ca/revoke-existing-certs! settings ["localhost" "test_cert"] (constantly nil)) (is (true? (revoked? cert1))) (is (true? (revoked? cert2))) (is (= [{:type :remove, :targets ["localhost" "test_cert"], :meta {:type :certificate}}] @call-results)) (reset! common/action-registration-function old-fn)))) (defn make-big-integers [integers] (map biginteger integers)) (deftest filter-already-revoked-serials-test (let [lock (new ReentrantReadWriteLock) descriptor "test-crl" timeout 1 crl (-> (ca/get-certificate-revocation-list cacrl lock descriptor timeout) StringReader. utils/pem->crl)] (testing "Return an empty vector when all supplied serials are already in CRL" (let [test-serial (make-big-integers [(biginteger 4)]) filtered-serial (ca/filter-already-revoked-serials test-serial crl)] (is (empty? filtered-serial)))) (testing "Return a vector of serials not yet in CRL" (let [test-serial (make-big-integers [1 2 3 4]) filtered-serial (ca/filter-already-revoked-serials test-serial crl)] (is (true? (= (sort filtered-serial) [1 2 3]))))) (testing "Deduplicates the vector of serials to be revoked" (let [test-serial (make-big-integers [1 1 2 2 3 3]) filtered-serial (ca/filter-already-revoked-serials test-serial crl)] (is (apply distinct? filtered-serial)))))) (deftest get-certificate-revocation-list-test (testing "`get-certificate-revocation-list` returns a valid CRL file." (let [lock (new ReentrantReadWriteLock) descriptor "test-crl" timeout 1 crl (-> (ca/get-certificate-revocation-list cacrl lock descriptor timeout) StringReader. utils/pem->crl)] (testutils/assert-issuer crl "CN=Puppet CA: localhost")))) (deftest update-crls-test (let [update-crl-fixture-dir (str test-resources-dir "/update_crls/") cert-chain-path (str update-crl-fixture-dir "ca_crt.pem") crl-path (str update-crl-fixture-dir "ca_crl.pem") crl-backup-path (str update-crl-fixture-dir "ca_crl.pem.bak")] (logutils/with-test-logging (testing "a single newer CRL is used" (let [new-crl-path (str update-crl-fixture-dir "new_root_crl.pem") incoming-crls (utils/pem->crls new-crl-path)] (testutils/with-backed-up-crl crl-path crl-backup-path (ca/update-crls incoming-crls crl-path cert-chain-path) (let [old-crls (utils/pem->crls crl-backup-path) new-crls (utils/pem->crls crl-path) old-number (utils/get-crl-number (last old-crls)) new-number (utils/get-crl-number (last new-crls))] (is (> new-number old-number)))))) (testing "the newest CRL given is used" (let [multiple-new-crls-path (str update-crl-fixture-dir "multiple_new_root_crls.pem") incoming-crls (utils/pem->crls multiple-new-crls-path)] (testutils/with-backed-up-crl crl-path crl-backup-path (ca/update-crls incoming-crls crl-path cert-chain-path) (let [old-crls (utils/pem->crls crl-backup-path) new-crls (utils/pem->crls crl-path) old-number (utils/get-crl-number (last old-crls)) new-number (utils/get-crl-number (last new-crls))] (is (> new-number old-number)) (is (= 10 new-number)))))) (testing "multiple newer CRLs are used" (let [three-cert-path (str update-crl-fixture-dir "three_cert_chain.pem") three-crl-path (str update-crl-fixture-dir "three_crl.pem") three-newer-crls-path (str update-crl-fixture-dir "three_newer_crl_chain.pem") incoming-crls (utils/pem->crls three-newer-crls-path)] (testutils/with-backed-up-crl three-crl-path crl-backup-path (ca/update-crls incoming-crls three-crl-path three-cert-path) (let [old-crls (utils/pem->crls crl-backup-path) new-crls (utils/pem->crls three-crl-path)] (is (> (utils/get-crl-number (.get new-crls 2)) (utils/get-crl-number (.get old-crls 2)))) (is (> (utils/get-crl-number (.get new-crls 1)) (utils/get-crl-number (.get old-crls 1)))) ;; Leaf CRL is never replaced (is (= (utils/get-crl-number (.get new-crls 0)) (utils/get-crl-number (.get old-crls 0)))))))) (testing "unrelated CRLs are ignored while newer relevant CRLs are used" (let [new-and-unrelated-crls-path (str update-crl-fixture-dir "new_crls_and_unrelated_crls.pem") incoming-crls (utils/pem->crls new-and-unrelated-crls-path)] (testutils/with-backed-up-crl crl-path crl-backup-path (ca/update-crls incoming-crls crl-path cert-chain-path) (let [old-crls (utils/pem->crls crl-backup-path) new-crls (utils/pem->crls crl-path)] (is (> (utils/get-crl-number (last new-crls)) (utils/get-crl-number (last old-crls)))) ;; Leaf CRL is never replaced (is (= (utils/get-crl-number (first new-crls)) (utils/get-crl-number (first old-crls)))) (testing "CRLs with same issuer name but different auth keys are not used" (is (= (utils/get-extension-value (last new-crls) utils/authority-key-identifier-oid) (utils/get-extension-value (last old-crls) utils/authority-key-identifier-oid))) (is (= (utils/get-extension-value (first new-crls) utils/authority-key-identifier-oid) (utils/get-extension-value (first old-crls) utils/authority-key-identifier-oid)))))))) (testing "all unrelated CRLs are ignored entirely" (let [unrelated-crls-path (str update-crl-fixture-dir "unrelated_crls.pem") incoming-crls (utils/pem->crls unrelated-crls-path)] (testutils/with-backed-up-crl crl-path crl-backup-path (ca/update-crls incoming-crls crl-path cert-chain-path) (let [old-crls (utils/pem->crls crl-backup-path) new-crls (utils/pem->crls crl-path)] (is (= (count old-crls) (count new-crls))) (is (= (set old-crls) (set new-crls))))))) (testing "older CRLs are ignored" (let [new-root-crl-chain-path (str update-crl-fixture-dir "chain_with_new_root.pem") old-root-crl-path (str update-crl-fixture-dir "old_root_crl.pem") incoming-crls (utils/pem->crls old-root-crl-path)] (testutils/with-backed-up-crl new-root-crl-chain-path crl-backup-path (ca/update-crls incoming-crls new-root-crl-chain-path cert-chain-path) (let [old-crls (utils/pem->crls crl-backup-path) new-crls (utils/pem->crls new-root-crl-chain-path)] (is (= (set new-crls) (set old-crls))))))) (let [multiple-newest-crls-path (str update-crl-fixture-dir "multiple_newest_root_crls.pem") delta-crl-path (str test-resources-dir "/update_crls/delta_crl.pem") missing-auth-id-crl-path (str test-resources-dir "/update_crls/missing_auth_id_crl.pem") bad-inputs-and-error-msgs {multiple-newest-crls-path #"Could not determine newest CRL." delta-crl-path #"Cannot support delta CRL." missing-auth-id-crl-path #"CRLs do not have an authority key"}] (doseq [[path error-message] bad-inputs-and-error-msgs] (testing (str "CRLs from " path " are rejected") (let [incoming-crls (utils/pem->crls path)] (testutils/with-backed-up-crl crl-path crl-backup-path (is (thrown-with-msg? IllegalArgumentException error-message (ca/update-crls incoming-crls crl-path cert-chain-path))) (let [old-crls (utils/pem->crls crl-backup-path) new-crls (utils/pem->crls crl-path)] (is (= (set old-crls) (set new-crls)))))))))))) (deftest initialize!-test (let [settings (testutils/ca-settings (ks/temp-dir))] (ca/initialize! settings) (testing "Generated SSL file" (doseq [file (-> (ca/settings->cadir-paths settings) (select-keys (ca/required-ca-files (:enable-infra-crl settings))) (vals))] (testing file (is (fs/exists? file))))) (testing "cacrl" (let [crl (-> settings :cacrl utils/pem->crl)] (testutils/assert-issuer crl "CN=test ca") (testing "has CRLNumber and AuthorityKeyIdentifier extensions" (is (not (nil? (utils/get-extension-value crl utils/crl-number-oid)))) (is (not (nil? (utils/get-extension-value crl utils/authority-key-identifier-oid))))))) (testing "cacert" (let [cert (-> settings :cacert utils/pem->cert)] (is (utils/certificate? cert)) (testutils/assert-subject cert "CN=test ca") (testutils/assert-issuer cert "CN=test ca") (testing "has at least one expected extension - key usage" (let [key-usage (utils/get-extension-value cert "2.5.29.15")] (is (= #{:key-cert-sign :crl-sign} key-usage)))) (testing "does not have any SANs" (is (nil? (utils/get-extension-value cert ca/subject-alt-names-oid)))) (testing "authority key identifier is SHA of public key" (let [ca-pub-key (-> settings :capub utils/pem->public-key) pub-key-sha (pubkey-sha1 ca-pub-key)] (is (= pub-key-sha (:key-identifier (utils/get-extension-value cert utils/authority-key-identifier-oid)))))))) (testing "cakey" (let [key (-> settings :cakey utils/pem->private-key)] (is (utils/private-key? key)) (is (= 512 (utils/keylength key))))) (testing "capub" (let [key (-> settings :capub utils/pem->public-key)] (is (utils/public-key? key)) (is (= 512 (utils/keylength key))))) (testing "cert-inventory" (is (fs/exists? (:cert-inventory settings)))) (testing "serial" (is (fs/exists? (:serial settings)))) (testing "allow-auto-renewal" (is (= false (:allow-auto-renewal settings)))) (testing "auto-renewal-cert-ttl" (is (= "90d" (:auto-renewal-cert-ttl settings)))) (testing "Does not replace files if they all exist" (let [files (-> (ca/settings->cadir-paths (assoc settings :enable-infra-crl false)) (dissoc :csrdir :signeddir :cadir) (vals))] (doseq [f files] (spit f "testable string")) (ca/initialize! settings) (doseq [f files] (is (= "testable string" (slurp f)) (str "File " f " was replaced"))))))) (deftest initialize!-test-with-keylength-in-settings (let [settings (assoc (testutils/ca-settings (ks/temp-dir)) :keylength 768)] (ca/initialize! settings) (testing "cakey with keylength" (let [key (-> settings :cakey utils/pem->private-key)] (is (utils/private-key? key)) (is (= 768 (utils/keylength key))))) (testing "capub with keylength" (let [key (-> settings :capub utils/pem->public-key)] (is (utils/public-key? key)) (is (= 768 (utils/keylength key))))))) (deftest ca-fail-fast-test (testing "Directories not required but are created if absent" (doseq [dir [:signeddir :csrdir]] (testing dir (let [settings (testutils/ca-sandbox! cadir)] (fs/delete-dir (get settings dir)) (is (nil? (ca/initialize! settings))) (is (true? (fs/exists? (get settings dir)))))))) (testing "CA public key not required" (let [settings (testutils/ca-sandbox! cadir)] (fs/delete (:capub settings)) (is (nil? (ca/initialize! settings))))) (testing "Exception is thrown when required file is missing" (doseq [file (ca/required-ca-files true)] (testing file (let [settings (assoc (testutils/ca-sandbox! cadir) :enable-infra-crl true) path (get settings file)] (fs/delete path) (is (thrown-with-msg? IllegalStateException (re-pattern (str "Missing:\n" path)) (ca/initialize! settings))))))) (testing "The CA private key has its permissions properly reset when :manage-internal-file-permissions is true." (let [settings (testutils/ca-sandbox! cadir)] (ks-file/set-perms (:cakey settings) "rw-r--r--") (logutils/with-test-logging (ca/initialize! settings) (is (logged? #"/ca/ca_key.pem' was found to have the wrong permissions set as 'rw-r--r--'. This has been corrected to 'rw-r-----'.")) (is (= ca/private-key-perms (ks-file/get-perms (:cakey settings))))))) (testing "The CA private key's permissions are not reset if :manage-internal-file-permissions is false." (let [perms "rw-r--r--" settings (assoc (testutils/ca-sandbox! cadir) :manage-internal-file-permissions false)] (ks-file/set-perms (:cakey settings) perms) (ca/initialize! settings) (is (= perms (ks-file/get-perms (:cakey settings))))))) (deftest retrieve-ca-cert!-test (testing "CA file copied when it doesn't already exist" (let [tmp-confdir (fs/copy-dir confdir (ks/temp-dir)) settings (testutils/master-settings tmp-confdir) ca-settings (testutils/ca-settings (str tmp-confdir "/ca")) cacert (:cacert ca-settings) localcacert (:localcacert settings) cacert-text (slurp cacert)] (testing "Copied cacert to localcacert when localcacert not present" (ca/retrieve-ca-cert! cacert localcacert) (is (= (slurp localcacert) cacert-text) (str "Unexpected content for localcacert: " localcacert))) (testing "Doesn't copy cacert over localcacert when different localcacert present" (let [localcacert-contents "12345"] (spit (:localcacert settings) localcacert-contents) (ca/retrieve-ca-cert! cacert localcacert) (is (= (slurp localcacert) localcacert-contents) (str "Unexpected content for localcacert: " localcacert)))) (testing "Throws exception if no localcacert and no cacert to copy" (fs/delete localcacert) (let [copy (fs/copy cacert (ks/temp-file))] (fs/delete cacert) (is (thrown? IllegalStateException (ca/retrieve-ca-cert! cacert localcacert)) "No exception thrown even though no file existed for copying") (fs/copy copy cacert)))))) (deftest retrieve-ca-crl!-test (testing "CRL file copied when it doesn't already exist" (let [tmp-confdir (fs/copy-dir confdir (ks/temp-dir)) settings (testutils/master-settings tmp-confdir) ca-settings (testutils/ca-settings (str tmp-confdir "/ca")) cacrl (:cacrl ca-settings) hostcrl (:hostcrl settings) cacrl-text (slurp cacrl)] (testing "Copied cacrl to hostcrl when hostcrl not present" (ca/retrieve-ca-crl! cacrl hostcrl) (is (= (slurp hostcrl) cacrl-text) (str "Unexpected content for hostcrl: " hostcrl))) (testing "Copied cacrl to hostcrl when different hostcrl present" (spit (:hostcrl settings) "12345") (ca/retrieve-ca-crl! cacrl hostcrl) (is (= (slurp hostcrl) cacrl-text) (str "Unexpected content for hostcrl: " hostcrl))) (testing "Doesn't throw exception or create dummy file if no hostcrl and no cacrl to copy" (fs/delete hostcrl) (let [copy (fs/copy cacrl (ks/temp-file))] (fs/delete cacrl) (is (not (fs/exists? hostcrl)) "hostcrl file present even though no file existed for copying") (fs/copy copy cacrl)))))) (deftest initialize-master-ssl!-test (let [tmp-confdir (fs/copy-dir confdir (ks/temp-dir)) settings (-> (testutils/master-settings tmp-confdir "master") (assoc :dns-alt-names "onefish,twofish")) ca-settings (testutils/ca-settings (str tmp-confdir "/ca"))] (ca/retrieve-ca-cert! (:cacert ca-settings) (:localcacert settings)) (ca/retrieve-ca-crl! (:cacrl ca-settings) (:hostcrl settings)) (ca/initialize-master-ssl! settings "master" ca-settings) (testing "Generated SSL file" (doseq [file (vals (ca/settings->ssldir-paths settings))] (testing file (is (fs/exists? file))))) (testing "hostcert" (let [hostcert (-> settings :hostcert utils/pem->cert)] (is (utils/certificate? hostcert)) (testutils/assert-subject hostcert "CN=master") (testutils/assert-issuer hostcert "CN=Puppet CA: localhost") (testing "has alt names extension" (let [dns-alt-names (utils/get-subject-dns-alt-names hostcert)] (is (= #{"master" "onefish" "twofish"} (set dns-alt-names)) "The Subject Alternative Names extension should contain the master's actual hostname and the hostnames in $dns-alt-names"))) (testing "has CLI auth extension" (let [cli-auth-ext (utils/get-extension-value hostcert ca/cli-auth-oid)] (is (= "true" cli-auth-ext) "The master cert should have the auth extension for the CA CLI."))) (testing "is also saved in the CA's $signeddir" (let [signedpath (ca/path-to-cert (:signeddir ca-settings) "master")] (is (fs/exists? signedpath)) (is (= hostcert (utils/pem->cert signedpath))))))) (testing "hostprivkey" (let [key (-> settings :hostprivkey utils/pem->private-key)] (is (utils/private-key? key)) (is (= 512 (utils/keylength key))))) (testing "hostpubkey" (let [key (-> settings :hostpubkey utils/pem->public-key)] (is (utils/public-key? key)) (is (= 512 (utils/keylength key))))) (testing "Does not replace files if they all exist" (let [files (-> (ca/settings->ssldir-paths settings) (dissoc :certdir :requestdir :privatekeydir) (vals)) file-content-fn (fn [files-to-read] (reduce #(assoc %1 %2 (slurp %2)) {} files-to-read)) file-content-before-reinit (file-content-fn files) _ (ca/initialize-master-ssl! settings "master" ca-settings) file-content-after-reinit (file-content-fn files)] (is (= file-content-before-reinit file-content-after-reinit) "File content unexpectedly changed after initialization called"))) (testing "Throws an exception if the cert is present but private key is missing" (let [private-key-path (:hostprivkey settings) private-key-backup (fs/copy private-key-path (ks/temp-file))] (fs/delete private-key-path) (is (thrown-with-msg? IllegalStateException (re-pattern (str "Found master cert '" (:hostcert settings) "' but master private key '" (:hostprivkey settings) "' is missing")) (ca/initialize-master-ssl! settings "master" ca-settings))) (fs/copy private-key-backup private-key-path))) (testing "Throws an exception if the private key is present but cert and public key are missing" (let [public-key-path (:hostpubkey settings) public-key-backup (fs/copy public-key-path (ks/temp-file)) cert-path (:hostcert settings) cert-backup (fs/copy cert-path (ks/temp-file))] (fs/delete public-key-path) (fs/delete cert-path) (is (thrown-with-msg? IllegalStateException (re-pattern (str "Found master private key '" (:hostprivkey settings) "' but master public key '" (:hostpubkey settings) "' is missing")) (ca/initialize-master-ssl! settings "master" ca-settings))) (fs/copy public-key-backup public-key-path) (fs/copy cert-backup cert-path))) (testing "Throws an exception if the public key is present but cert and private key are missing" (let [private-key-path (:hostprivkey settings) private-key-backup (fs/copy private-key-path (ks/temp-file)) cert-path (:hostcert settings) cert-backup (fs/copy cert-path (ks/temp-file))] (fs/delete private-key-path) (fs/delete cert-path) (is (thrown-with-msg? IllegalStateException (re-pattern (str "Found master public key '" (:hostpubkey settings) "' but master private key '" (:hostprivkey settings) "' is missing")) (ca/initialize-master-ssl! settings "master" ca-settings))) (fs/copy private-key-backup private-key-path) (fs/copy cert-backup cert-path))) (testing "hostcert regenerated if keys already present at initialization time" (let [hostcert-path (:hostcert settings) hostcert-backup (fs/copy hostcert-path (ks/temp-file)) public-key-before-init (slurp (:hostpubkey settings)) _ (fs/delete hostcert-path) _ (ca/initialize-master-ssl! settings "master" ca-settings) hostcert-after-init (utils/pem->cert hostcert-path) public-key-from-new-cert (StringWriter.)] (-> hostcert-after-init (.getPublicKey) (utils/obj->pem! public-key-from-new-cert)) (testutils/assert-subject hostcert-after-init "CN=master") (testutils/assert-issuer hostcert-after-init "CN=Puppet CA: localhost") (is (= public-key-before-init (.toString public-key-from-new-cert)) "regenerated public key embedded in regenerated hostcert") (fs/copy hostcert-backup hostcert-path))))) (deftest initialize-master-ssl!-test-with-keylength-settings (let [tmp-confdir (fs/copy-dir confdir (ks/temp-dir)) settings (-> (testutils/master-settings tmp-confdir) (assoc :keylength 768)) ca-settings (assoc (testutils/ca-settings (str tmp-confdir "/ca")) :keylength 768)] (ca/retrieve-ca-cert! (:cacert ca-settings) (:localcacert settings)) (ca/initialize-master-ssl! settings "master" ca-settings) (testing "hostprivkey should have correct keylength" (let [key (-> settings :hostprivkey utils/pem->private-key)] (is (utils/private-key? key)) (is (= 768 (utils/keylength key))))) (testing "hostpubkey should have correct keylength" (let [key (-> settings :hostpubkey utils/pem->public-key)] (is (utils/public-key? key)) (is (= 768 (utils/keylength key))))))) (when-not (SSLUtils/isFIPS) (deftest initialize-master-ssl!-test-with-incorrect-keylength (let [tmp-confdir (fs/copy-dir confdir (ks/temp-dir)) settings (testutils/master-settings tmp-confdir) ca-settings (testutils/ca-settings (str tmp-confdir "/ca"))] (ca/retrieve-ca-cert! (:cacert ca-settings) (:localcacert settings)) (testing "should throw an error message with too short keylength" (is (thrown? IllegalArgumentException (ca/initialize-master-ssl! (assoc settings :keylength 128) "master" ca-settings)))) (testing "should throw an error message with too large keylength" (is (thrown? IllegalArgumentException (ca/initialize-master-ssl! (assoc settings :keylength 32768) "master" ca-settings))))))) (deftest parse-serial-number-test (is (= (ca/parse-serial-number "0001") 1)) (is (= (ca/parse-serial-number "0010") 16)) (is (= (ca/parse-serial-number "002A") 42))) (deftest format-serial-number-test (is (= (ca/format-serial-number 1) "0001")) (is (= (ca/format-serial-number 16) "0010")) (is (= (ca/format-serial-number 42) "002A"))) (deftest next-serial-number!-test (let [serial-file (str (ks/temp-file)) ca-settings (assoc (testutils/ca-settings (ks/temp-dir)) :serial serial-file)] (testing "Serial file is initialized to 1" (ca/initialize-serial-file! ca-settings) (is (= (ca/next-serial-number! ca-settings) 1))) (testing "The serial number file should contain the next serial number" (is (= "0002" (slurp serial-file)))) (testing "subsequent calls produce increasing serial numbers" (is (= (ca/next-serial-number! ca-settings) 2)) (is (= "0003" (slurp serial-file))) (is (= (ca/next-serial-number! ca-settings) 3)) (is (= "0004" (slurp serial-file)))))) ;; If the locking is deleted from `next-serial-number!`, this test will hang, ;; which is not as nice as simply failing ... ;; This seems to happen due to a deadlock caused by concurrently reading and ;; writing to the same file (via `slurp` and `spit`) (deftest next-serial-number-threadsafety (testing "next-serial-number! is thread-safe and never returns a duplicate serial number" (let [serial-file (doto (str (ks/temp-file)) (spit "0001")) serials (atom []) ca-settings (assoc (testutils/ca-settings (ks/temp-dir)) :serial serial-file) ;; spin off a new thread for each CPU promises (for [_ (range (ks/num-cpus))] (let [p (promise)] (future ;; get a bunch of serial numbers and keep track of them (dotimes [_ 100] (let [serial-number (ca/next-serial-number! ca-settings)] (swap! serials conj serial-number))) (deliver p 'done)) p)) contains-duplicates? #(not= (count %) (count (distinct %)))] ; wait on all the threads to finish (doseq [p promises] (deref p)) (is (false? (contains-duplicates? @serials)) "Got a duplicate serial number"))) (testing "next-serial-number! will timeout if lock is held" (let [serial-file (str (ks/temp-file)) ca-settings (assoc (testutils/ca-settings (ks/temp-dir)) :serial serial-file :serial-lock-timeout-seconds 1) write-lock (.writeLock (:serial-lock ca-settings)) completed (promise) caught-timeout (promise)] ;; acquire and hold the lock (.lock write-lock) ;; in a separate thread, try to increment the serial number (deref (future (try (ca/next-serial-number! ca-settings) ;; we should never get here because the lock is held, and timeout should occur (deliver completed true) (catch Exception _e ;; timeout occurred (deliver caught-timeout false))))) (.unlock write-lock) (is (not (realized? completed))) (is (realized? caught-timeout))))) (defn verify-inventory-entry! [inventory-entry serial-number subject] (let [parts (string/split inventory-entry #" ")] (is (= serial-number (first parts))) (is (re-matches #"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}UTC" (second parts))) (is (re-matches #"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}UTC" (nth parts 2))) (is (= subject (string/join " " (subvec parts 3)))))) (deftest test-write-cert-to-inventory (testing "Certs can be written to an inventory file." (let [first-cert (utils/pem->cert cacert) second-cert (utils/pem->cert (ca/path-to-cert signeddir "localhost")) inventory-file (str (ks/temp-file)) ca-settings (assoc (testutils/ca-settings cadir) :cert-inventory inventory-file)] (ca/write-cert-to-inventory! first-cert ca-settings) (ca/write-cert-to-inventory! second-cert ca-settings) (testing "The format of a cert in the inventory matches the existing format used by the ruby puppet code." (let [inventory (slurp inventory-file) entries (string/split inventory #"\n")] (is (= (count entries) 2)) (verify-inventory-entry! (first entries) "0x0001" "/CN=Puppet CA: localhost") (verify-inventory-entry! (second entries) "0x0002" "/CN=localhost")))))) (deftest allow-duplicate-certs-test (let [settings (assoc (testutils/ca-sandbox! cadir) :autosign false)] (testing "when false" (let [settings (assoc settings :allow-duplicate-certs false)] (testing "throws exception if CSR already exists" (is (thrown+? [:kind :duplicate-cert :msg "test-agent already has a requested certificate; ignoring certificate request"] (ca/process-csr-submission! "test-agent" (csr-stream "test-agent") settings (constantly nil))))) (testing "throws exception if certificate already exists" (is (thrown+? [:kind :duplicate-cert :msg "localhost already has a signed certificate; ignoring certificate request"] (ca/process-csr-submission! "localhost" (io/input-stream (test-pem-file "localhost-csr.pem")) settings (constantly nil)))) (is (thrown+? [:kind :duplicate-cert :msg "revoked-agent already has a revoked certificate; ignoring certificate request"] (ca/process-csr-submission! "revoked-agent" (io/input-stream (test-pem-file "revoked-agent-csr.pem")) settings (constantly nil))))))) (testing "when true" (let [settings (assoc settings :allow-duplicate-certs true)] (testing "new CSR overwrites existing one" (let [csr-path (ca/path-to-cert-request (:csrdir settings) "test-agent") csr (ByteArrayInputStream. (.getBytes (slurp csr-path)))] (spit csr-path "should be overwritten") (logutils/with-test-logging (ca/process-csr-submission! "test-agent" csr settings (constantly nil)) (is (logged? #"test-agent already has a requested certificate; new certificate will overwrite it" :info)) (is (not= "should be overwritten" (slurp csr-path)) "Existing CSR was not overwritten")))) (testing "new certificate overwrites existing one" (let [settings (assoc settings :autosign true) cert-path (ca/path-to-cert (:signeddir settings) "localhost") old-cert (slurp cert-path) csr (io/input-stream (test-pem-file "localhost-csr.pem"))] (logutils/with-test-logging (ca/process-csr-submission! "localhost" csr settings (constantly nil)) (is (logged? #"localhost already has a signed certificate; new certificate will overwrite it" :info)) (is (not= old-cert (slurp cert-path)) "Existing certificate was not overwritten")))))))) (deftest process-csr-submission!-test (let [settings (testutils/ca-sandbox! cadir)] (testing "CSR validation policies" (testing "when autosign is false" (let [settings (assoc settings :autosign false)] (testing "subject policies are checked" (doseq [[policy subject csr-file exception] [["subject-hostname mismatch" "foo" "hostwithaltnames.pem" #(= {:kind :hostname-mismatch :msg "Instance name \"hostwithaltnames\" does not match requested key \"foo\""} (select-keys % [:kind :msg]))] ["invalid characters in name" "super/bad" "bad-subject-name-1.pem" #(= {:kind :invalid-subject-name :msg "Subject hostname format is invalid"} (select-keys % [:kind :msg]))] ["wildcard in name" "foo*bar" "bad-subject-name-wildcard.pem" #(= {:kind :invalid-subject-name :msg "Subject contains a wildcard, which is not allowed: foo*bar"} (select-keys % [:kind :msg]))]]] (testing policy (let [path (ca/path-to-cert-request (:csrdir settings) subject) csr (io/input-stream (test-pem-file csr-file))] (is (false? (fs/exists? path))) (is (thrown+? exception (ca/process-csr-submission! subject csr settings (constantly nil)))) (is (false? (fs/exists? path))))))) (testing "extension & key policies are not checked" (doseq [[policy subject csr-file] [["subject alt name extension" "hostwithaltnames" "hostwithaltnames.pem"] ["unknown extension" "meow" "meow-bad-extension.pem"] ["public-private key mismatch" "luke.madstop.com" "luke.madstop.com-bad-public-key.pem"]]] (testing policy (let [path (ca/path-to-cert-request (:csrdir settings) subject) csr (io/input-stream (test-pem-file csr-file))] (is (false? (fs/exists? path))) (ca/process-csr-submission! subject csr settings (constantly nil)) (is (true? (fs/exists? path))) (fs/delete path))))) (testing "writes indicator file when asked to" (let [subject "meow" path (ca/path-to-cert-request (:csrdir settings) subject) csr (io/input-stream (test-pem-file "meow-bad-extension.pem"))] (is (false? (fs/exists? path))) (ca/process-csr-submission! subject csr settings (constantly nil)) (is (true? (fs/exists? path))) (fs/delete path))))) (testing "when autosign is true, all policies are checked, and" (let [settings (assoc settings :autosign true)] (testing "CSR will not be saved when" (doseq [[policy subject csr-file expected] [["subject-hostname mismatch" "foo" "hostwithaltnames.pem" #(= {:kind :hostname-mismatch :msg "Instance name \"hostwithaltnames\" does not match requested key \"foo\""} (select-keys % [:kind :msg]))] ["subject contains invalid characters" "super/bad" "bad-subject-name-1.pem" #(= {:kind :invalid-subject-name :msg "Subject hostname format is invalid"} (select-keys % [:kind :msg]))] ["subject contains wildcard character" "foo*bar" "bad-subject-name-wildcard.pem" #(= {:kind :invalid-subject-name :msg "Subject contains a wildcard, which is not allowed: foo*bar"} (select-keys % [:kind :msg]))]]] (testing policy (let [path (ca/path-to-cert-request (:csrdir settings) subject) csr (io/input-stream (test-pem-file csr-file))] (is (false? (fs/exists? path))) (is (thrown+? expected (ca/process-csr-submission! subject csr settings (constantly nil)))) (is (false? (fs/exists? path))))))) (testing "CSR will be saved when" (doseq [[policy subject csr-file expected] [["subject alt name extension exists" "hostwithaltnames" "hostwithaltnames.pem" #(= {:kind :disallowed-extension :msg (str "CSR 'hostwithaltnames' contains extra subject alternative names " "(DNS:altname1, DNS:altname2, DNS:altname3), which are disallowed. " "To allow subject alternative names, set allow-subject-alt-names to " "true in your ca.conf file. Then restart the puppetserver " "and try signing this certificate again.")} (select-keys % [:kind :msg]))] ["unknown extension exists" "meow" "meow-bad-extension.pem" #(= {:kind :disallowed-extension :msg "Found extensions that are not permitted: 1.9.9.9.9.9.9"} (select-keys % [:kind :msg]))] ["public-private key mismatch" "luke.madstop.com" "luke.madstop.com-bad-public-key.pem" #(= {:kind :invalid-signature :msg "CSR contains a public key that does not correspond to the signing key"} (select-keys % [:kind :msg]))]]] (testing policy (let [path (ca/path-to-cert-request (:csrdir settings) subject) csr (io/input-stream (test-pem-file csr-file))] (is (false? (fs/exists? path))) (is (thrown+? expected (ca/process-csr-submission! subject csr settings (constantly nil)))) (is (true? (fs/exists? path))) (fs/delete path))))))) (testing "order of validations" (testing "duplicates checked before subject policies" (let [settings (assoc settings :allow-duplicate-certs false) csr-with-mismatched-name (csr-stream "test-agent")] (is (thrown+? [:kind :duplicate-cert :msg "test-agent already has a requested certificate; ignoring certificate request"] (ca/process-csr-submission! "not-test-agent" csr-with-mismatched-name settings (constantly nil)))))) (testing "subject policies checked before extension & key policies" (let [csr-with-disallowed-alt-names (io/input-stream (test-pem-file "hostwithaltnames.pem"))] (is (thrown+? [:kind :hostname-mismatch :msg "Instance name \"hostwithaltnames\" does not match requested key \"foo\""] (ca/process-csr-submission! "foo" csr-with-disallowed-alt-names settings (constantly nil)))))))) (testing "action correctly reported" (let [keypair (utils/generate-key-pair) subject-name (ks/rand-str :alpha-lower 8) subject (utils/cn subject-name) csr (utils/generate-certificate-request keypair subject) csr-file (ks/temp-file "csr") path-to-csr (.toString csr-file) _ (utils/obj->pem! csr path-to-csr) csr (io/input-stream path-to-csr) old-fn @common/action-registration-function call-results (atom []) new-fn (fn [value] (swap! call-results conj value))] (reset! common/action-registration-function new-fn) (ca/process-csr-submission! subject-name csr settings (constantly nil)) (is (= [{:type :info :targets [subject-name] :meta {:what :csr :action :submit}} {:type :add :targets [subject-name] :meta {:type :certificate}}] @call-results)) (reset! common/action-registration-function old-fn))))) (deftest cert-signing-extension-test (let [issuer-keys (utils/generate-key-pair 512) issuer-pub (utils/get-public-key issuer-keys) subject-keys (utils/generate-key-pair 512) subject-pub (utils/get-public-key subject-keys) subject "subject" subject-dn (utils/cn subject) not-after (-> (DateTime/now) (.plus (Period/years 5)) (.toDate)) not-before (-> (DateTime/now) (.plus (Period/years 5)) (.toDate)) cn (utils/cn "Root CA") cert (utils/sign-certificate cn (utils/get-private-key issuer-keys) 666 not-before not-after cn issuer-pub (utils/create-ca-extensions issuer-pub issuer-pub))] (testing "basic extensions are created for an agent" (let [csr (utils/generate-certificate-request subject-keys subject-dn) exts (ca/create-agent-extensions csr cert) exts-expected [{:oid "2.16.840.1.113730.1.13" :critical false :value ca/netscape-comment-value} {:oid "2.5.29.17" :critical false :value {:dns-name [subject]}} {:oid "2.5.29.35" :critical false :value {:issuer-dn nil :public-key nil :cert cert :serial-number nil}} {:oid "2.5.29.19" :critical true :value {:is-ca false}} {:oid "2.5.29.37" :critical true :value [ca/ssl-server-cert ca/ssl-client-cert]} {:oid "2.5.29.15" :critical true :value #{:digital-signature :key-encipherment}} {:oid "2.5.29.14" :critical false :value subject-pub}]] (is (= (set exts) (set exts-expected))))) (testing "basic extensions are created for an agent csr with dns-alt-names specified, aka subject alternative names, aka san" (let [alt-names-list [subject "altname1"] csr (utils/generate-certificate-request subject-keys subject-dn [(utils/subject-dns-alt-names alt-names-list false)]) exts (ca/create-agent-extensions csr cert) exts-expected [{:oid "2.16.840.1.113730.1.13" :critical false :value ca/netscape-comment-value} {:oid "2.5.29.17" :critical false :value {:dns-name alt-names-list}} {:oid "2.5.29.35" :critical false :value {:issuer-dn nil :public-key nil :cert cert :serial-number nil}} {:oid "2.5.29.19" :critical true :value {:is-ca false}} {:oid "2.5.29.37" :critical true :value [ca/ssl-server-cert ca/ssl-client-cert]} {:oid "2.5.29.15" :critical true :value #{:digital-signature :key-encipherment}} {:oid "2.5.29.14" :critical false :value subject-pub}]] (is (= (set exts) (set exts-expected))))) (testing "basic extensions are created for an agent csr with no CN in SAN" (let [alt-names-list ["altname1" "altname2"] csr (utils/generate-certificate-request subject-keys subject-dn [(utils/subject-dns-alt-names alt-names-list false)]) exts (ca/create-agent-extensions csr cert) exts-expected [{:oid "2.16.840.1.113730.1.13" :critical false :value ca/netscape-comment-value} {:oid "2.5.29.17" :critical false :value {:dns-name (conj alt-names-list subject)}} {:oid "2.5.29.35" :critical false :value {:issuer-dn nil :public-key nil :cert cert :serial-number nil}} {:oid "2.5.29.19" :critical true :value {:is-ca false}} {:oid "2.5.29.37" :critical true :value [ca/ssl-server-cert ca/ssl-client-cert]} {:oid "2.5.29.15" :critical true :value #{:digital-signature :key-encipherment}} {:oid "2.5.29.14" :critical false :value subject-pub}]] (is (= (set exts) (set exts-expected))))) (testing "basic extensions are created for a master" (let [settings (assoc (testutils/master-settings confdir) :csr-attributes "doesntexist") exts (ca/create-master-extensions subject subject-pub cert settings) exts-expected [{:oid "2.16.840.1.113730.1.13" :critical false :value ca/netscape-comment-value} {:oid "2.5.29.35" :critical false :value {:issuer-dn nil :public-key nil :cert cert :serial-number nil}} {:oid "2.5.29.19" :critical true :value {:is-ca false}} {:oid "2.5.29.37" :critical true :value [ca/ssl-server-cert ca/ssl-client-cert]} {:oid "2.5.29.15" :critical true :value #{:digital-signature :key-encipherment}} {:oid "2.5.29.14" :critical false :value subject-pub} {:oid "1.3.6.1.4.1.34380.1.3.39" :critical false :value "true"} {:oid utils/subject-alt-name-oid :critical false :value {:dns-name ["puppet" "subject"]}}]] (is (= (set exts) (set exts-expected))))) (testing "additional extensions are created for a master" (let [dns-alt-names "DNS:onefish,twofish,DNS:threefish,fourfish" settings (-> (testutils/master-settings confdir) (assoc :dns-alt-names dns-alt-names) (assoc :csr-attributes (csr-attributes-file "csr_attributes.yaml"))) exts (ca/create-master-extensions subject subject-pub cert settings) exts-expected (concat attribute-file-extensions [{:oid "2.16.840.1.113730.1.13" :critical false :value ca/netscape-comment-value} {:oid "2.5.29.35" :critical false :value {:issuer-dn nil :public-key nil :cert cert :serial-number nil}} {:oid "2.5.29.19" :critical true :value {:is-ca false}} {:oid "2.5.29.37" :critical true :value [ca/ssl-server-cert ca/ssl-client-cert]} {:oid "2.5.29.15" :critical true :value #{:digital-signature :key-encipherment}} {:oid "2.5.29.14" :critical false :value subject-pub} {:oid "1.3.6.1.4.1.34380.1.3.39" :critical false :value "true"} {:oid "2.5.29.17" :critical false :value {:dns-name ["onefish" "twofish" "threefish" "fourfish" "subject"] :ip []}}])] (is (= (set exts) (set exts-expected))))) (testing "correct subject alt name extensions are created for a master" (let [dns-alt-names "onefish,twofish,DNS:threefish,IP:192.168.69.90,fivefish,IP:192.168.69.91" exts-expected {:oid "2.5.29.17" :critical false :value {:dns-name ["onefish" "twofish" "threefish" "fivefish" "subject"] :ip ["192.168.69.90" "192.168.69.91"]}}] (is (= (ca/create-subject-alt-names-ext "subject" dns-alt-names) exts-expected)))) (testing "A non-puppet OID read from a CSR attributes file is rejected" (let [config (assoc (testutils/master-settings confdir) :csr-attributes (csr-attributes-file "insecure_csr_attributes.yaml"))] (is (thrown+? [:kind :disallowed-extension :msg "Found extensions that are not permitted: 1.2.3.4"] (ca/create-master-extensions subject subject-pub cert config))))) (testing "invalid DNS alt names are rejected" (let [dns-alt-names "*.wildcard"] (is (thrown+? [:kind :invalid-alt-name :msg "Cert subjectAltName contains a wildcard, which is not allowed: *.wildcard"] (ca/create-master-extensions subject subject-pub cert (assoc (testutils/master-settings confdir) :dns-alt-names dns-alt-names)))))) (testing "basic extensions are created for a CA" (let [exts (ca/create-ca-extensions subject-pub subject-pub) exts-expected [{:oid "2.16.840.1.113730.1.13" :critical false :value ca/netscape-comment-value} {:oid "2.5.29.35" :critical false :value {:issuer-dn nil :public-key subject-pub :cert nil :serial-number nil}} {:oid "2.5.29.19" :critical true :value {:is-ca true}} {:oid "2.5.29.15" :critical true :value #{:crl-sign :key-cert-sign}} {:oid "2.5.29.14" :critical false :value subject-pub}]] (is (= (set exts) (set exts-expected))))) (testing "trusted fact extensions are properly unfiltered" (let [csr-exts [(utils/puppet-node-image-name "imagename" false) (utils/puppet-node-preshared-key "key" false) (utils/puppet-node-instance-id "instance" false) (utils/puppet-node-uid "UUUU-IIIII-DDD" false)] csr (utils/generate-certificate-request subject-keys subject-dn csr-exts) exts (ca/create-agent-extensions csr cert) exts-expected [{:oid "2.16.840.1.113730.1.13" :critical false :value ca/netscape-comment-value} {:oid "2.5.29.35" :critical false :value {:issuer-dn nil :public-key nil :cert cert :serial-number nil}} {:oid "2.5.29.17" :critical false :value {:dns-name ["subject"]}} {:oid "2.5.29.19" :critical true :value {:is-ca false}} {:oid "2.5.29.37" :critical true :value [ca/ssl-server-cert ca/ssl-client-cert]} {:oid "2.5.29.15" :critical true :value #{:digital-signature :key-encipherment}} {:oid "2.5.29.14" :critical false :value subject-pub} {:oid "1.3.6.1.4.1.34380.1.1.1" :critical false :value "UUUU-IIIII-DDD"} {:oid "1.3.6.1.4.1.34380.1.1.2" :critical false :value "instance"} {:oid "1.3.6.1.4.1.34380.1.1.3" :critical false :value "imagename"} {:oid "1.3.6.1.4.1.34380.1.1.4" :critical false :value "key"}]] (is (= (set exts) (set exts-expected)) "The puppet trusted facts extensions were not added by create-agent-extensions"))))) (deftest netscape-comment-value-test (testing "Netscape comment constant has expected value" (is (= "Puppet Server Internal Certificate" ca/netscape-comment-value)))) (deftest ensure-alt-names-allowed-test (let [subject-keys (utils/generate-key-pair 512) subject "new-cert" subject-dn (utils/cn subject)] (logutils/with-test-logging (testing "when allow-subject-alt-names is false" (testing "rejects alt names that don't match the subject" (let [alt-name-ext {:oid utils/subject-alt-name-oid :value {:dns-name ["bad-name"]} :critical false} csr (utils/generate-certificate-request subject-keys subject-dn [alt-name-ext])] (is (thrown+-with-msg? [:kind :disallowed-extension] #".*new-cert.*subject alternative names.*bad-name.*" (ca/ensure-subject-alt-names-allowed! csr false)))) (let [alt-name-ext {:oid utils/subject-alt-name-oid :value {:dns-name ["bad-name" subject]} :critical false} csr (utils/generate-certificate-request subject-keys subject-dn [alt-name-ext])] (is (thrown+-with-msg? [:kind :disallowed-extension] #".*new-cert.*subject alternative names.*bad-name.*" (ca/ensure-subject-alt-names-allowed! csr false))))) (testing "allows a single alt name matching the subject" (let [alt-name-ext {:oid utils/subject-alt-name-oid :value {:dns-name [subject]} :critical false} csr (utils/generate-certificate-request subject-keys subject-dn [alt-name-ext])] (is (nil? (ca/ensure-subject-alt-names-allowed! csr false))) (is (logutils/logged? #"Allowing subject alt name" :debug)))))) (testing "when allow-subject-alt-names is true" (testing "allows all alt names" (let [alt-name-ext {:oid utils/subject-alt-name-oid :value {:dns-name [subject "another-name"]} :critical false} csr (utils/generate-certificate-request subject-keys subject-dn [alt-name-ext])] (is (nil? (ca/ensure-subject-alt-names-allowed! csr true)))))))) (deftest ensure-no-authorization-extensions!-test (testing "when checking a csr for authorization extensions" (let [subject-keys (utils/generate-key-pair 512) subject "borges" subject-dn (utils/cn subject) pp-auth-ext {:oid (:pp_authorization ca/puppet-short-names) :value "true" :critical false} pp-auth-role {:oid (:pp_auth_role ca/puppet-short-names) :value "com" :critical false} auth-csr (utils/generate-certificate-request subject-keys subject-dn [pp-auth-ext]) auth-role-csr (utils/generate-certificate-request subject-keys subject-dn [pp-auth-role])] (testing "pp_authorization is caught" (is (thrown+-with-msg? [:kind :disallowed-extension] #".*borges.*contains an authorization extension.*" (ca/ensure-no-authorization-extensions! auth-csr false)))) (testing "pp_auth_role is caught" (is (thrown+-with-msg? [:kind :disallowed-extension] #".*borges.*contains an authorization extension..*" (ca/ensure-no-authorization-extensions! auth-role-csr false))))))) (deftest validate-subject!-test (testing "an exception is thrown when the hostnames don't match" (is (thrown+? [:kind :hostname-mismatch :msg "Instance name \"test-agent\" does not match requested key \"not-test-agent\""] (ca/validate-subject! "not-test-agent" "test-agent")))) (testing "an exception is thrown if the subject name contains a capital letter" (is (thrown+? [:kind :invalid-subject-name :msg "Certificate names must be lower case."] (ca/validate-subject! "Host-With-Capital-Letters" "Host-With-Capital-Letters")))) (testing "an exception is thrown when the hostnames ends in hyphen" (is (thrown+? [:kind :invalid-subject-name :msg "Subject hostname format is invalid"] (ca/validate-subject! "rootca-.example.org" "rootca-.example.org")))) (testing "an exception is thrown when the hostnames starts with hyphen" (is (thrown+? [:kind :invalid-subject-name :msg "Subject hostname format is invalid"] (ca/validate-subject! "-rootca.example.org" "-rootca.example.org")))) (testing "an exception is thrown when the hostnames contains a space" (is (thrown+? [:kind :invalid-subject-name :msg "Subject hostname format is invalid"] (ca/validate-subject! "root ca.example.org" "root ca.example.org")))) (testing "an exception is thrown when the hostnames contain an ampersand" (is (thrown+? [:kind :invalid-subject-name :msg "Subject hostname format is invalid"] (ca/validate-subject! "root&ca.example.org" "root&ca.example.org")))) (testing "an exception is thrown when the hostname is empty" (is (thrown+? [:kind :invalid-subject-name :msg "Subject hostname format is invalid"] (ca/validate-subject! "" "")))) (testing "an exception is thrown when the hostnames contain multiple dots in a row" (is (thrown+? [:kind :invalid-subject-name :msg "Subject hostname format is invalid"] (ca/validate-subject! "rootca..example.org" "rootca..example.org")))) (testing "subjects that end end in dot are valid" (is (nil? (ca/validate-subject! "rootca." "rootca.")))) (testing "subjects that end in an underscore are valid" (is (nil? (ca/validate-subject! "rootca_" "rootca_")))) (testing "subjects that start in an underscore are valid" (is (nil? (ca/validate-subject! "_x-puppet._tcp.example.com" "_x-puppet._tcp.example.com")))) (testing "single letter segments are valid" (is (nil? (ca/validate-subject! "a.example.com" "a.example.com"))) (is (nil? (ca/validate-subject! "_.example.com" "_.example.com"))) (is (nil? (ca/validate-subject! "foo.a.example.com" "foo.a.example.com")))) (testing "Single word hostnames are allowed" (is (nil? (ca/validate-subject! "rootca" "rootca")))) (testing "Domain names are allowed" (is (nil? (ca/validate-subject! "puppet.com" "puppet.com")))) (testing "Subdomains are allowed" (is (nil? (ca/validate-subject! "ca.puppet.com" "ca.puppet.com")))) (testing "Hostnames containing underscores are allowed" (is (nil? (ca/validate-subject! "root_ca" "root_ca")))) (testing "Hostnames containing dashes are allowed" (is (nil? (ca/validate-subject! "root-ca" "root-ca")))) (testing "Hostnames containing numbers are allowed" (is (nil? (ca/validate-subject! "root123" "root123")))) (testing "Domains containing numbers are allowed" (is (nil? (ca/validate-subject! "root123.com" "root123.com"))))) (deftest validate-subject-alt-names!-test (testing "Both DNS and IP alt names are allowed" (is (nil? (ca/validate-subject-alt-names! {:oid "2.5.29.17" :critical false :value {:ip ["12.34.5.6"] :dns-name ["ahostname"]}})))) (testing "Non-DNS and IP names are not allowed" (is (thrown+? [:kind :invalid-alt-name :msg "Only DNS and IP names are allowed in the Subject Alternative Names extension"] (ca/validate-subject-alt-names! {:oid "2.5.29.17" :critical false :value {:uri ["12.34.5.6"]}})))) (testing "No DNS wildcards are allowed" (is (thrown+? [:kind :invalid-alt-name :msg "Cert subjectAltName contains a wildcard, which is not allowed: foo*bar"] (ca/validate-subject-alt-names! {:oid "2.5.29.17" :critical false :value {:dns-name ["ahostname" "foo*bar"]}}))))) (deftest default-master-dns-alt-names (testing "Master certificate has default DNS alt names if none are specified" (let [settings (assoc (testutils/master-settings confdir) :dns-alt-names "") pubkey (-> (utils/generate-key-pair 512) (utils/get-public-key)) ca-key-pair (utils/generate-key-pair 512) ca-priv-key (utils/get-private-key ca-key-pair) ca-pub-key (utils/get-public-key ca-key-pair) not-after (-> (DateTime/now) (.plus (Period/years 5)) (.toDate)) not-before (-> (DateTime/now) (.plus (Period/years 5)) (.toDate)) cn (utils/cn "Root CA") cert (utils/sign-certificate cn ca-priv-key 666 not-before not-after cn ca-pub-key (utils/create-ca-extensions ca-pub-key ca-pub-key)) alt-names (-> (ca/create-master-extensions "master" pubkey cert settings) (utils/get-extension-value utils/subject-alt-name-oid) (:dns-name))] (is (= #{"puppet" "master"} (set alt-names)))))) (deftest file-permissions (testing "A newly created file contains the properly set permissions" (doseq [u all-perms g all-perms o all-perms] (let [tmp-file (fs/temp-name "ca-file-perms-test") perms (str u g o)] (ca/create-file-with-perms tmp-file perms) (is (= perms (ks-file/get-perms tmp-file))) (fs/delete tmp-file)))) (testing "Changing the perms of an already created file" (let [perms-list (for [u all-perms g all-perms o all-perms] (str u g o))] (loop [perms perms-list] (when-not (empty? perms) (let [tmp-file (fs/temp-name "ca-file-perms-test") [init-perm change-perm] (take 2 perms)] (ca/create-file-with-perms tmp-file init-perm) (ks-file/set-perms tmp-file change-perm) (is (= change-perm (ks-file/get-perms tmp-file))) (fs/delete tmp-file) (recur (nthnext perms 2)))))))) (deftest create-csr-attrs-exts-test (testing "when parsing a csr_attributes file using short names" (testing "and the file exists" (testing "and it has non-whitelisted OIDs we properly translate the short names." (let [extensions (ca/create-csr-attrs-exts (csr-attributes-file "csr_attributes_with_auth.yaml")) expected (concat attribute-file-extensions [{:oid "1.3.6.1.4.1.34380.1.3.1" ;; :pp_authorization :critical false :value "true"} {:oid "1.3.6.1.4.1.34380.1.3.13" ;; :pp_auth_role :critical false :value "com"}])] (is (= (set extensions) (set expected))))) (testing "and it has whitelisted OIDs we properly translate the short names." (let [extensions (ca/create-csr-attrs-exts (csr-attributes-file "csr_attributes.yaml"))] (is (= (set extensions) (set attribute-file-extensions)))))) (testing "and the file doesn't exist" (testing "the result is nil" (is (nil? (ca/create-csr-attrs-exts "does/not/exist.yaml"))))))) (deftest ca-expiration-dates-test (testing "returns a map of names to dates" (let [settings (testutils/ca-sandbox! bundle-cadir) expiration-map (ca/ca-expiration-dates (:cacert settings))] (is (= "2036-09-06T05:58:33UTC" (get expiration-map "rootca.example.org"))) (is (= "2036-09-06T06:09:14UTC" (get expiration-map "intermediateca.example.org")))))) (deftest crl-expiration-dates-test (testing "returns a map of names to dates" (let [settings (testutils/ca-sandbox! bundle-cadir) expiration-map (ca/crl-expiration-dates (:cacrl settings))] (is (= "2016-10-11T06:42:52UTC" (get expiration-map "rootca.example.org"))) (is (= "2016-10-11T06:40:47UTC" (get expiration-map "intermediateca.example.org")))))) (deftest get-cert-or-csr-statuses-test (let [lock (new ReentrantReadWriteLock) descriptor "test-crl" timeout 1 crl (-> (ca/get-certificate-revocation-list cacrl lock descriptor timeout) StringReader. utils/pem->crl)] (testing "returns a collection of 'requested' statuses when queried for CSR" (let [request-statuses (ca/get-cert-or-csr-statuses csrdir crl false) result-states (map :state request-statuses)] (is (every? #(= "requested" %) result-states)))) (testing "returns a collection of 'signed' or 'revoked' statuses when queried for cert" (let [cert-statuses (ca/get-cert-or-csr-statuses signeddir crl true) result-states (map :state cert-statuses)] (is (every? #(or (= "signed" %) (= "revoked" %)) result-states)))) (testing "errors when given wrong directory path for querying CSR" (is (thrown? java.lang.ClassCastException (ca/get-cert-or-csr-statuses signeddir crl false)))))) (defn create-ca-cert [name serial] (let [keypair (utils/generate-key-pair) public-key (utils/get-public-key keypair) private-key (utils/get-private-key keypair) x500-name (utils/cn name) validity (ca/cert-validity-dates 3600) ca-exts (ca/create-ca-extensions public-key public-key)] {:public-key public-key :private-key private-key :x500-name x500-name :certname name :cert (utils/sign-certificate x500-name private-key serial (:not-before validity) (:not-after validity) x500-name public-key ca-exts)})) (deftest cert-authority-id-match-ca-subject-id?-test (let [ca-cert-1 (create-ca-cert "ca1" 1) ca-cert-2 (create-ca-cert "ca2" 2) ca-cert-3 (create-ca-cert "ca3" 3) cert-1 (simple/gen-cert "foo" ca-cert-1 4 {:extensions [(utils/authority-key-identifier (:cert ca-cert-1))]}) cert-2 (simple/gen-cert "foo" ca-cert-2 5 {:extensions [(utils/authority-key-identifier (:cert ca-cert-2))]}) cert-3 (simple/gen-cert "foo" ca-cert-3 5 {:extensions [(utils/authority-key-identifier (:cert ca-cert-3))]})] (testing "Certificates that match CA report as matching" (is (true? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-1) (:cert ca-cert-1)))) (is (true? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-2) (:cert ca-cert-2)))) (is (true? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-3) (:cert ca-cert-3))))) (testing "Certificates that don't match CA report as not matching" (is (false? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-1) (:cert ca-cert-2)))) (is (false? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-1) (:cert ca-cert-3)))) (is (false? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-2) (:cert ca-cert-1)))) (is (false? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-2) (:cert ca-cert-3)))) (is (false? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-3) (:cert ca-cert-1)))) (is (false? (ca/cert-authority-id-match-ca-subject-id? (:cert cert-3) (:cert ca-cert-2))))))) (deftest duration-string-conversion-test (testing "a valid duration string coverts to expected seconds" (let [duration-str-1 "1y 1d 1h 1m 1s" duration-str-2 "800y 0d 0h 0m 0s" duration-str-3 "22d1s" duration-str-4 "0s"] (is (= 31626061 (ca/duration-str->sec duration-str-1))) (is (= 25228800000 (ca/duration-str->sec duration-str-2))) (is (= 1900801 (ca/duration-str->sec duration-str-3))) (is (= 0 (ca/duration-str->sec duration-str-4))))) (testing "an invalid duration string returns nil" (let [duration-str-1 "not a duration string 283q 3z 3x 03o" duration-str-2 "not a duration string 20d 20s" duration-str-3 "1 y 1__d 30 m s22 m39 thirtym" duration-str-4 "0y 0d 0h 0m 0s 0x 0y 0z" duration-str-5 33 duration-str-6 nil] (is (= nil (ca/duration-str->sec duration-str-1))) (is (= nil (ca/duration-str->sec duration-str-2))) (is (= nil (ca/duration-str->sec duration-str-3))) (is (= nil (ca/duration-str->sec duration-str-4))) (is (= nil (ca/duration-str->sec duration-str-5))) (is (= nil (ca/duration-str->sec duration-str-6)))))) (deftest renew-certificate!-test (testing "creates a new signed cert" (let [settings (testutils/ca-sandbox! cadir) ;; auto-renewal-cert-ttl is expected to be an int ;; unit tests skip some of the conversion flow so ;; transform the duration here converted-auto-renewal-cert-ttl (ca/duration-str->sec (:auto-renewal-cert-ttl settings)) updated-settings (assoc settings :auto-renewal-cert-ttl converted-auto-renewal-cert-ttl) ca-cert (create-ca-cert "ca1" 1) keypair (utils/generate-key-pair) subject (utils/cn "foo") csr (utils/generate-certificate-request keypair subject) validity (ca/cert-validity-dates 3600) signed-cert (utils/sign-certificate (utils/get-subject-from-x509-certificate (:cert ca-cert)) (:private-key ca-cert) (ca/next-serial-number! settings) (:not-before validity) (:not-after validity) subject (utils/get-public-key csr) (ca/create-agent-extensions csr (:cert ca-cert))) expected-cert-path (ca/path-to-cert (:signeddir settings) "foo")] (testing "simulate the cert being written" (ca/write-cert signed-cert expected-cert-path) (is (fs/exists? expected-cert-path))) (Thread/sleep 1000) ;; ensure there is some time elapsed between the two (let [renewed-cert (ca/renew-certificate! signed-cert updated-settings (constantly nil))] (is (some? renewed-cert)) (testing "serial number has increased" (is (< (.getSerialNumber signed-cert) (.getSerialNumber renewed-cert))) (is (= 6 (.getSerialNumber renewed-cert)))) (testing "not before time stamps have changed" (is (= -1 (.compareTo (.getNotBefore signed-cert) (.getNotBefore renewed-cert))))) (testing "new not-after is later than before" (is (= -1 (.compareTo (.getNotAfter signed-cert) (.getNotAfter renewed-cert))))) (testing "new not-after should be 89 days (and some faction) away" (let [diff (- (.getTime (.getNotAfter renewed-cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] (is (= 89 days)))) (testing "certificate should have been replaced" (is (fs/exists? expected-cert-path)) (testing "updated cert on disk matches renewed cert" (let [updated-cert (utils/pem->cert expected-cert-path)] (is (= 6 (.getSerialNumber updated-cert))) (is (zero? (.compareTo (.getNotBefore updated-cert) (.getNotBefore renewed-cert)))) (is (zero? (.compareTo (.getNotAfter updated-cert) (.getNotAfter renewed-cert))))))) (testing "extensions are preserved" (let [extensions-before (utils/get-extensions signed-cert) extensions-after (utils/get-extensions signed-cert)] ;; ordering may be different so use an unordered comparison (is (= (set extensions-before) (set extensions-after))))) (testing "the new entry is written to the inventory file" (let [entries (string/split (slurp (:cert-inventory settings)) #"\n") last-entry-fields (string/split (last entries) #" ")] ;; since the content of the inventory is well established (because of the sandbox), we can ;; just assert that the last entry is there, and makes sense ;; there are four fields, serial number, not before, not after, and subject ;; for ease of testing, just test the first and last (is (= "0x0006" (first last-entry-fields))) (is (= "/CN=foo" (last last-entry-fields))))) (testing "the new entry is not in the infra-serial file" (is (= "" (slurp (:infra-node-serials-path settings)))))))) (testing "infra inventory correctly writes files" (let [settings (testutils/ca-sandbox! cadir) ;; auto-renewal-cert-ttl is expected to be an int ;; unit tests skip some of the conversion flow so ;; transform the duration here converted-auto-renewal-cert-ttl (ca/duration-str->sec (:auto-renewal-cert-ttl settings)) updated-settings (assoc settings :auto-renewal-cert-ttl converted-auto-renewal-cert-ttl) ;; simulate the node being in the infra inventory file _ (spit (:infra-nodes-path settings) "bar\n") ca-cert (create-ca-cert "ca1" 1) keypair (utils/generate-key-pair) subject (utils/cn "bar") csr (utils/generate-certificate-request keypair subject) validity (ca/cert-validity-dates 3600) signed-cert (utils/sign-certificate (utils/get-subject-from-x509-certificate (:cert ca-cert)) (:private-key ca-cert) (ca/next-serial-number! settings) (:not-before validity) (:not-after validity) subject (utils/get-public-key csr) (ca/create-agent-extensions csr (:cert ca-cert))) expected-cert-path (ca/path-to-cert (:signeddir settings) "bar")] (testing "simulate the cert being written" (ca/write-cert signed-cert expected-cert-path) (is (fs/exists? expected-cert-path))) (Thread/sleep 1000) ;; ensure there is some time elapsed between the two (let [renewed-cert (ca/renew-certificate! signed-cert updated-settings (constantly nil))] (is (some? renewed-cert)) (testing "serial number has increased" (is (< (.getSerialNumber signed-cert) (.getSerialNumber renewed-cert))) (is (= 6 (.getSerialNumber renewed-cert)))) (testing "not before time stamps have changed" (is (= -1 (.compareTo (.getNotBefore signed-cert) (.getNotBefore renewed-cert))))) (testing "new not-after is later than before" (is (= -1 (.compareTo (.getNotAfter signed-cert) (.getNotAfter renewed-cert))))) (testing "new not-after should be 89 days (and some faction) away" (let [diff (- (.getTime (.getNotAfter renewed-cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] (is (= 89 days)))) (testing "certificate should have been replaced" (is (fs/exists? expected-cert-path)) (testing "updated cert on disk matches renewed cert" (let [updated-cert (utils/pem->cert expected-cert-path)] (is (= 6 (.getSerialNumber updated-cert))) (is (zero? (.compareTo (.getNotBefore updated-cert) (.getNotBefore renewed-cert)))) (is (zero? (.compareTo (.getNotAfter updated-cert) (.getNotAfter renewed-cert))))))) (testing "extensions are preserved" (let [extensions-before (utils/get-extensions signed-cert) extensions-after (utils/get-extensions signed-cert)] ;; ordering may be different so use an unordered comparison (is (= (set extensions-before) (set extensions-after))))) (testing "the new entry is written to the inventory file" (let [entries (string/split (slurp (:cert-inventory settings)) #"\n") last-entry-fields (string/split (last entries) #" ")] ;; since the content of the inventory is well established (because of the sandbox), we can ;; just assert that the last entry is there, and makes sense ;; there are four fields, serial number, not before, not after, and subject ;; for ease of testing, just test the first and last (is (= "0x0006" (first last-entry-fields))) (is (= "/CN=bar" (last last-entry-fields))))) (testing "the new entry is in the infra-serial file" (is (= "6\n" (slurp (:infra-node-serials-path settings))))))))) (deftest supports-auto-renewal?-test (let [keypair (utils/generate-key-pair) subject (utils/cn "foo")] (testing "should not support auto-renewal" (is (false? (ca/supports-auto-renewal? (utils/generate-certificate-request keypair subject [] [])))) (is (false? (ca/supports-auto-renewal? (utils/generate-certificate-request keypair subject [] [{:oid ca/pp_auth_auto_renew-attribute :value false}])))) (is (false? (ca/supports-auto-renewal? (utils/generate-certificate-request keypair subject [] [{:oid ca/pp_auth_auto_renew-attribute :value "false"}]))))) (testing "should support auto-renewal" (is (true? (ca/supports-auto-renewal? (utils/generate-certificate-request keypair subject [] [{:oid ca/pp_auth_auto_renew-attribute :value true}])))) (is (true? (ca/supports-auto-renewal? (utils/generate-certificate-request keypair subject [] [{:oid ca/pp_auth_auto_renew-attribute :value "true"}]))))))) (deftest get-csr-attributes-test (testing "extract attribute from CSR" (let [keypair (utils/generate-key-pair) subject (utils/cn "foo") csr (utils/generate-certificate-request keypair subject [] [{:oid ca/pp_auth_auto_renew-attribute :value true}])] (is (= [{:oid ca/pp_auth_auto_renew-attribute, :values ["true"]}] (ca/get-csr-attributes csr)))))) (deftest crl-expires-in-n-days?-test (let [settings (testutils/ca-sandbox! cadir)] ;; by default the crl expires in 5 years (testing "CRL with long expiration don't expire soon" (is (false? (ca/crl-expires-in-n-days? (:cacrl settings) settings 5)))) (testing "CRL with long expiration expires in ~6 years" (is (ca/crl-expires-in-n-days? (:cacrl settings) settings (* 365 6)))) (testing "created crl expires in 5 days" (let [[crl & rest-of-full-chain] (utils/pem->crls (:cacrl settings)) public-key (utils/pem->public-key (:capub settings)) private-key (utils/pem->private-key (:cakey settings)) new-crl (utils/generate-crl (.getSubjectX500Principal (utils/pem->ca-cert (:cacert settings) (:cakey settings))) private-key public-key (.getThisUpdate crl) ;; create a date 5 days from now using java.time (-> (LocalDateTime/now) (.plusDays 5) (.toInstant ZoneOffset/UTC) (Date/from)) (biginteger 1) nil) new-full-chain (cons new-crl (vec rest-of-full-chain)) temp-path (fs/temp-file "crl" "pem") path-as-string (.getCanonicalPath temp-path)] (ca/write-crls new-full-chain (.getCanonicalPath temp-path)) (doseq [i (range 0 4)] (is (false? (ca/crl-expires-in-n-days? path-as-string settings i)))) (is (ca/crl-expires-in-n-days? path-as-string settings 5)) (is (ca/crl-expires-in-n-days? path-as-string settings 6)))))) (deftest overwrite-existing-crl!-test (let [settings (testutils/ca-sandbox! bundle-cadir) [crl & rest-of-full-chain] (utils/pem->crls (:cacrl settings)) crl-serials (set (map #(.getSerialNumber %) (.getRevokedCertificates crl))) all-serials (set/union crl-serials (set (map biginteger (range 1000 2000)))) ca-cert (utils/pem->ca-cert (:cacert settings) (:cakey settings)) before-next-update (.getNextUpdate crl) crl-number (utils/get-crl-number crl)] (ca/overwrite-existing-crl! crl rest-of-full-chain (:capub settings) (:cakey settings) ca-cert (vec all-serials) (:cacrl settings)) (testing "overwritten crl has updated properties" (let [[updated-crl & _rest-of-full-chain] (utils/pem->crls (:cacrl settings))] (is (.after (.getNextUpdate updated-crl) before-next-update)) (is (< crl-number (utils/get-crl-number updated-crl))) (is (not= (set (map #(.getSerialNumber %) (.getRevokedCertificates updated-crl))) crl-serials)) (is (= (set (map #(.getSerialNumber %) (.getRevokedCertificates updated-crl))) all-serials)))))) (deftest expired-inventory-serials-test (let [settings (testutils/ca-sandbox! cadir) keypair (utils/generate-key-pair) subject (utils/cn "foo") csr (utils/generate-certificate-request keypair subject) serial-number (ca/next-serial-number! settings) ca-cert (utils/pem->ca-cert (:cacert settings) (:cakey settings)) private-key (utils/pem->private-key (:cakey settings)) signed-cert (utils/sign-certificate (utils/get-subject-from-x509-certificate ca-cert) private-key serial-number ;; valid from 100 days ago until yesterday (-> (LocalDateTime/now) (.minusDays 100) (.toInstant ZoneOffset/UTC) (Date/from)) (-> (LocalDateTime/now) (.minusDays 1) (.toInstant ZoneOffset/UTC) (Date/from)) subject (utils/get-public-key csr) (ca/create-agent-extensions csr ca-cert))] (ca/write-cert-to-inventory! signed-cert settings) ;; there are multiple entries in the inventory file that aren't expired by default (is (= [(biginteger serial-number)] (ca/expired-inventory-serials settings))))) (deftest update-and-sign-crl!-test (let [settings (testutils/ca-sandbox! bundle-cadir) [crl & rest-of-full-chain] (utils/pem->crls (:cacrl settings)) crl-serials (set (map #(.getSerialNumber %) (.getRevokedCertificates crl))) crl-number (utils/get-crl-number crl) serial-number (ca/next-serial-number! settings) keypair (utils/generate-key-pair) subject (utils/cn "foo") csr (utils/generate-certificate-request keypair subject) ca-cert (utils/pem->ca-cert (:cacert settings) (:cakey settings)) private-key (utils/pem->private-key (:cakey settings)) ;; create an add an expired cert to add to the inventory after we update the crl with ;; the serial number of the cert signed-cert (utils/sign-certificate (utils/get-subject-from-x509-certificate ca-cert) private-key serial-number ;; valid from 100 days ago until yesterday (-> (LocalDateTime/now) (.minusDays 100) (.toInstant ZoneOffset/UTC) (Date/from)) (-> (LocalDateTime/now) (.minusDays 1) (.toInstant ZoneOffset/UTC) (Date/from)) subject (utils/get-public-key csr) (ca/create-agent-extensions csr ca-cert)) extra-serials (set (map biginteger (range 1000 2000))) all-serials (set/union crl-serials #{(biginteger serial-number)} extra-serials)] (ca/overwrite-existing-crl! crl rest-of-full-chain (:capub settings) (:cakey settings) ca-cert (vec all-serials) (:cacrl settings)) (let [[updated-crl & _rest-of-full-chain] (utils/pem->crls (:cacrl settings)) updated-crl-number (utils/get-crl-number updated-crl)] (is (= (.getName (.getIssuerX500Principal ^X509CRL updated-crl)) (.getName (.getIssuerX500Principal ^X509CRL crl)))) (is (< crl-number updated-crl-number)) (ca/write-cert-to-inventory! signed-cert settings) (ca/update-and-sign-crl! (:cacrl settings) settings) (let [[final-updated-crl & _rest-of-full-chain] (utils/pem->crls (:cacrl settings)) final-crl-number (utils/get-crl-number final-updated-crl) final-crl-serials (set (map #(.getSerialNumber %) (.getRevokedCertificates final-updated-crl)))] (is (< updated-crl-number final-crl-number)) ;; should not contain the serial that was expired (is (= (set/union crl-serials extra-serials) final-crl-serials)))))) (deftest base-16-str->biginteger-test (testing "returns expected results" (doseq [i (range 1 10000)] (is (= (biginteger i) (ca/base-16-str->biginteger (format "0x%x" i))))))) (defn generate-csr [settings extensions attributes] (let [keypair (utils/generate-key-pair) subject-name (ks/rand-str :alpha-lower 8) subject (utils/cn subject-name) csr (utils/generate-certificate-request keypair subject extensions attributes) csr-path (ca/path-to-cert-request (:csrdir settings) subject-name)] (utils/obj->pem! csr csr-path) {:subject subject :subject-name subject-name :csr csr :csr-path csr-path})) (deftest sign-multiple-certificate-signing-requests!-test (let [inventory-file (str (ks/temp-file)) settings (-> (testutils/ca-sandbox! bundle-cadir) (assoc :cert-inventory inventory-file :allow-auto-renewal true) (update :auto-renewal-cert-ttl ca/duration-str->sec)) report-activity (fn [_a _b] nil)] (testing "single entry" (testing "happy path" (let [csr-info (generate-csr settings [] [{:oid ca/pp_auth_auto_renew-attribute :value true}])] (testing "csr should exist before the operation" (is (fs/exists? (:csr-path csr-info)))) (testing "correctly signs" (is (= {:signed [(:subject-name csr-info)] :no-csr [] :signing-errors []} (ca/sign-multiple-certificate-signing-requests! [(:subject-name csr-info)] settings report-activity)))) (testing "csr is removed after routine" (is (not (fs/exists? (:csr-path csr-info))))) (testing "signed cert" (let [cert-path (ca/path-to-cert (:signeddir settings) (:subject-name csr-info))] (testing "should exist" (is (fs/exists? cert-path))) (testing "signed cert should be valid" (let [^X509Certificate cert (utils/pem->cert cert-path) capub (-> (:cacert settings) (utils/pem->certs) (first) (.getPublicKey))] ;; this will throw an exception, causing the test to fail if it isn't valid. It returns void (.checkValidity cert) (is (nil? (.verify cert capub))) (testing "not after date should be ~90 days in the future" (let [diff (- (.getTime (.getNotAfter cert)) (.getTime (Date.))) days (.convert TimeUnit/DAYS diff TimeUnit/MILLISECONDS)] ;; 89 days plus some number of hour, minutes seconds (is (= 89 days)))))) ;; certificate should be in inventory (testing "should be in the inventory" (let [inventory (slurp inventory-file) entries (string/split inventory #"\n")] (is (= (count entries) 1)) (let [row (string/split (first entries) #" ")] ;; row is constructed of serial-number, start date, end date and name ;; sandbox has some used serial numbers (is (= "0x0003" (first row))) (is (= (str "/" (:subject csr-info)) (nth row 3)))))))))) (testing "correctly rejects a non-existent csr" (let [random-csr-name (ks/rand-str :alpha-lower 8)] (is (= {:signed [] :no-csr [random-csr-name] :signing-errors []} (ca/sign-multiple-certificate-signing-requests! [random-csr-name] settings report-activity))))) (testing "correctly rejects a cert with Subject alternative names" (let [alt-name-ext {:oid utils/subject-alt-name-oid :value {:dns-name ["bad-name"]} :critical false} csr-info (generate-csr settings [alt-name-ext] [{:oid ca/pp_auth_auto_renew-attribute :value true}])] (is (= {:signed [] :no-csr [] :signing-errors [(:subject-name csr-info)]} (ca/sign-multiple-certificate-signing-requests! [(:subject-name csr-info)] settings report-activity))))) (testing "correctly rejects a cert with authorization extensions when disabled" (let [csr-info (generate-csr settings [{:oid ca/ppAuthCertExt :value "true" :critical false}] [{:oid ca/pp_auth_auto_renew-attribute :value true}])] (is (= {:signed [] :no-csr [] :signing-errors [(:subject-name csr-info)]} (ca/sign-multiple-certificate-signing-requests! [(:subject-name csr-info)] settings report-activity))))) (testing "correctly rejects a cert with unapproved extensions" (let [csr-info (generate-csr settings [{:oid "1.9.9.9.9.9.0" :value "true" :critical false}] [{:oid ca/pp_auth_auto_renew-attribute :value true}])] (is (= {:signed [] :no-csr [] :signing-errors [(:subject-name csr-info)]} (ca/sign-multiple-certificate-signing-requests! [(:subject-name csr-info)] settings report-activity)))))) (testing "multiple entry with both bad and good csrs" (let [count-range (range 0 100) good-csrs (doall (pmap (fn [_i] (generate-csr settings [] [{:oid ca/pp_auth_auto_renew-attribute :value true}])) count-range)) random-csr-names (doall (pmap (fn [_i] (ks/rand-str :alpha-lower 8)) count-range)) alt-name-ext {:oid utils/subject-alt-name-oid :value {:dns-name ["bad-name"]} :critical false} bad-names (doall (pmap (fn [_i] (generate-csr settings [alt-name-ext] [{:oid ca/pp_auth_auto_renew-attribute :value true}])) count-range)) unauthorized (doall (pmap (fn [_i] (generate-csr settings [{:oid ca/ppAuthCertExt :value "true" :critical false}] [{:oid ca/pp_auth_auto_renew-attribute :value true}])) count-range)) unapproved-extensions (doall (pmap (fn [_i] (generate-csr settings [{:oid "1.9.9.9.9.9.0" :value "true" :critical false}] [{:oid ca/pp_auth_auto_renew-attribute :value true}])) count-range)) all-csrs (concat good-csrs bad-names unauthorized unapproved-extensions) all-names (shuffle (concat (map :subject-name all-csrs) random-csr-names)) old-fn @common/action-registration-function call-results (atom []) new-fn (fn [value] (swap! call-results conj value)) _ (reset! common/action-registration-function new-fn) result (ca/sign-multiple-certificate-signing-requests! all-names settings report-activity) signed-set (set (:signed result)) not-found-set (set (:no-csr result)) unsigned-set (set (:signing-errors result)) good-csrs-set (set (map :subject-name good-csrs)) random-names-set (set random-csr-names) bad-names-set (set (map :subject-name bad-names)) unauthorized-set (set (map :subject-name unauthorized)) unapproved-extensions-set (set (map :subject-name unapproved-extensions))] (testing "all the signed entries should be present" (is (= good-csrs-set signed-set)) (is (= 1 (count @call-results))) (is (= {:type :add :targets good-csrs-set :meta {:type :certificate}} ;; convert the targets to a set for comparison (update-in (first @call-results) [:targets] set))) (testing "none of the valid csrs should be in the not-signed set" (is (empty? (clojure.set/intersection unsigned-set good-csrs-set)))) (testing "all of the random names should be in the not-found-set" (is (= random-names-set (clojure.set/intersection not-found-set random-names-set)))) (testing "all of the alt names should be in the not-signed" (is (= bad-names-set (clojure.set/intersection unsigned-set bad-names-set)))) (testing "all of the unauthorized names should be in the not-signed" (is (= unauthorized-set (clojure.set/intersection unsigned-set unauthorized-set)))) (testing "all of the unapproved names should be in the not-signed" (is (= unapproved-extensions-set (clojure.set/intersection unsigned-set unapproved-extensions-set))))) (reset! common/action-registration-function old-fn))))) (def default-permissions (into-array FileAttribute [(ks-file/perms->attribute "rw-------")])) (deftest get-paths-to-all-certificate-requests-test (testing "finds all files in directory ending with the pem suffix" (let [^File temp-directory (ks/temp-dir) path-to-file (.toPath temp-directory) a-pem-file-names (set (for [i (range 0 100)] (format "a-%d.pem" i))) b-pem-file-names (set (for [i (range 0 100)] (format "b-%d.pem" i))) a-foo-file-names (set (for [i (range 0 100)] (format "a-%d.foo" i))) all-pem-file-names (clojure.set/union a-pem-file-names b-pem-file-names)] ;; create a lot of files that match that end with pem (doall (for [^String i all-pem-file-names] (Files/createFile (.resolve ^Path path-to-file i) default-permissions))) ;; create a lot of files that don't end that start with pem (doall (for [^String i a-foo-file-names] (Files/createFile (.resolve path-to-file i) default-permissions))) (let [result (ca/get-paths-to-all-certificate-requests (.toString temp-directory)) file-names (set (common/extract-file-names-from-paths result))] (is (= (set file-names) all-pem-file-names)))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/puppetserver/ringutils_test.clj000066400000000000000000000037461470345337400315320ustar00rootroot00000000000000(ns puppetlabs.puppetserver.ringutils-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.puppetserver.ringutils :refer [wrap-with-cert-whitelist-check]] [puppetlabs.ssl-utils.core :as ssl-utils] [schema.test :as schema-test])) (use-fixtures :once schema-test/validate-schemas) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utilities (def test-resources-dir "./dev-resources/puppetlabs/puppetserver/ringutils_test") (defn test-pem-file [pem-file-name] (str test-resources-dir "/" pem-file-name)) (def localhost-cert (ssl-utils/pem->cert (test-pem-file "localhost-cert.pem"))) (def other-cert (ssl-utils/pem->cert (test-pem-file "revoked-agent.pem"))) (def base-handler (fn [_req] {:status 200 :body "hello"})) (defn build-ring-handler [whitelist-settings] (-> base-handler (wrap-with-cert-whitelist-check whitelist-settings))) (defn test-request [cert] {:uri "/foo" :request-method :get :ssl-client-cert cert}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Test (deftest wrap-with-cert-whitelist-check-test (let [ring-handler (build-ring-handler {:client-whitelist ["localhost"]})] (testing "access allowed when cert is on whitelist" (let [response (ring-handler (test-request localhost-cert))] (is (= 200 (:status response))) (is (= "hello" (:body response))))) (testing "access denied when cert not on whitelist" (let [response (ring-handler (test-request other-cert))] (is (= 403 (:status response)))))) (let [ring-handler (build-ring-handler {:authorization-required false :client-whitelist []})] (testing "access allowed when auth not required" (let [response (ring-handler (test-request other-cert))] (is (= 200 (:status response))) (is (= "hello" (:body response))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/puppetserver/ruby/000077500000000000000000000000001470345337400267305ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/puppetserver/ruby/http_client_test.clj000066400000000000000000000420131470345337400327760ustar00rootroot00000000000000(ns puppetlabs.puppetserver.ruby.http-client-test (:import (org.jruby.embed EvalFailedException) (org.apache.http ProtocolException ConnectionClosedException) (com.puppetlabs.ssl_utils SSLUtils) (javax.net.ssl SSLHandshakeException SSLException) (java.util HashMap) (java.io IOException) (java.util.zip GZIPInputStream)) (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [puppetlabs.trapperkeeper.testutils.webserver :as jetty10] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-puppet-testutils] [ring.middleware.basic-authentication :as auth] [schema.core :as schema] [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.jruby-pool-manager.impl.jruby-pool-manager-core :as jruby-impl-core] [puppetlabs.services.jruby-pool-manager.jruby-schemas :as jruby-schemas])) ;; NOTE: this namespace is pretty disgusting. It'd be much nicer to test this ;; ruby code via ruby spec tests, but since we need to stand up a webserver to ;; make requests against, it's way easier to do it with clojure and tk-j9. (defn test-resource [filename] (str "./dev-resources/puppetlabs/puppetserver/ruby/http_client_test/" filename)) (defn ring-app [_req] {:status 200 :body "hi"}) (defn ring-app-alternate [_req] {:status 200 :body "bye"}) (defn ring-app-connection-closed [req] {:status 200 :body (str "The Connection header has value " ((:headers req) "connection"))}) (defn ring-app-decompressing-gzipped-request [req] {:status 200 :body (-> req :body (GZIPInputStream.) slurp)}) (defn authenticated? [name pass] (and (= name "foo") (= pass "bar"))) (def ring-app-with-auth (-> ring-app (auth/wrap-basic-authentication authenticated?))) (defn ssl-connection-exception? [ex] (or (instance? ConnectionClosedException ex) (instance? SSLHandshakeException ex) (and (instance? SSLException ex) (= "Received fatal alert: handshake_failure" (. ex getMessage))) (and (instance? IOException ex) (= "Connection reset by peer" (.getMessage ex))))) (defn get-http-client-settings [options] (let [result (HashMap.)] (when (contains? options :ssl-protocols) (.put result "ssl_protocols" (into-array String (:ssl-protocols options)))) (when (contains? options :cipher-suites) (.put result "cipher_suites" (into-array String (:cipher-suites options)))) result)) (def ca-pem (test-resource "ca.pem")) (def cert-pem (test-resource "localhost_cert.pem")) (def privkey-pem (test-resource "localhost_key.pem")) (schema/defn ^:always-validate jruby-config :- jruby-schemas/JRubyConfig "Create a JRubyConfig for testing. The optional map argument `options` may contain a map, which, if present, will be merged into the final JRubyConfig map. (This function differs from `jruby-tk-config` in that it returns a map that complies with the JRubyConfig schema, which differs slightly from the raw format that would be read from config files on disk.)" [] (jruby-core/initialize-config {:ruby-load-path (jruby-puppet-core/managed-load-path jruby-puppet-testutils/ruby-load-path) :gem-home jruby-puppet-testutils/gem-home :gem-path jruby-puppet-testutils/gem-path})) (defn create-scripting-container "A JRuby ScriptingContainer with an instance of 'Puppet::Server::HttpClient' assigned to a variable 'c'. The ScriptingContainer was created with LocalVariableBehavior.PERSISTENT so that the HTTP client instance will persistent across calls to 'runScriptlet' in tests." [] (let [jruby-config (jruby-config) scripting-container (-> (jruby-impl-core/create-pool jruby-config) (jruby-core/borrow-from-pool :http-client-test []) :scripting-container)] (doto scripting-container, (.runScriptlet "require 'puppet'") (.runScriptlet (format "Puppet[:hostcert] = '%s'" cert-pem)) (.runScriptlet (format "Puppet[:hostprivkey] = '%s'" privkey-pem)) (.runScriptlet (format "Puppet[:localcacert] = '%s'" ca-pem))) scripting-container)) (defn create-http-client [scripting-container options] (.runScriptlet scripting-container "require 'puppet/server/http_client'") (let [http-client-settings (get-http-client-settings (select-keys options [:ssl-protocols :cipher-suites])) http-client-class (.runScriptlet scripting-container "Puppet::Server::HttpClient")] (.callMethodWithArgArray scripting-container http-client-class "initialize_settings" (into-array Object [http-client-settings]) Object) (.runScriptlet scripting-container "$c = Puppet::Server::HttpClient.new;"))) (defn terminate-http-client [scripting-container] (.runScriptlet scripting-container "$c = nil") ;; This step purges the '@ssl_context' which may have been used with an http ;; client call. This is necessary to ensure that any subsequent http client ;; call utilizes a new SSL context rather than unintentionally using some ;; cached state - e.g., ssl parameters from prior connection attempt. (.runScriptlet scripting-container "Puppet::Server::Config.instance_variable_set('@ssl_context', nil)") (.runScriptlet scripting-container "Puppet::Server::HttpClient.terminate")) (defn terminate-scripting-container [scripting-container] (.terminate scripting-container)) (def ^:dynamic ^:private *scripting-container* nil) (defmacro with-scripting-container [scripting-container & body] `(let [~scripting-container (or *scripting-container* (create-scripting-container))] (try ~@body (finally (when-not *scripting-container* (terminate-scripting-container ~scripting-container)))))) (defmacro with-http-client [scripting-container options & body] `(try (create-http-client ~scripting-container ~options) ~@body (finally (terminate-http-client ~scripting-container)))) (defn http-client-scripting-container-fixture [test-fn] (with-scripting-container sc (binding [*scripting-container* sc] (test-fn)))) (use-fixtures :once http-client-scripting-container-fixture) (deftest test-ruby-http-client (jetty10/with-test-webserver ring-app port (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:" port)] (testing "HTTP GET" (is (= "hi" (.runScriptlet sc (format "$c.get(URI('%s')).body" url))))) (testing "HTTP POST" (is (= "hi" (.runScriptlet sc (format "$c.post(URI('%s'), 'foo').body" url)))))))))) (deftest http-escaped-urls-test (jetty10/with-test-webserver ring-app port (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:" port)] (testing "HTTP GET" (.runScriptlet sc (str "$response = $c.get(URI('" url "/a%20b%3Fc'), params: { foo: 'bar' })")) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= (str url "/a%20b%3Fc?foo=bar") (.runScriptlet sc "$response.url.to_s"))))))))) (deftest http-basic-auth (jetty10/with-test-webserver ring-app-with-auth port (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:" port)] (testing "no credentials" (.runScriptlet sc (format "$response = $c.post(URI('%s'), 'foo')" url)) (is (= 401 (.runScriptlet sc "$response.code"))) (is (= "Unauthorized" (.runScriptlet sc "$response.reason"))) (is (= "access denied" (.runScriptlet sc "$response.body")))) (testing "valid credentials" (let [auth "{ :basic_auth => { :user => 'foo', :password => 'bar' }}"] (.runScriptlet sc (format "$response = $c.post(URI('%s'), 'foo', options: %s)" url auth))) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= "hi" (.runScriptlet sc "$response.body")))) (testing "invalid credentials" (let [auth "{ :basic_auth => { :user => 'foo', :password => 'baz' }}"] (.runScriptlet sc (format "$response = $c.post(URI('%s'), 'foo', options: %s)" url auth))) (is (= 401 (.runScriptlet sc "$response.code"))) (is (= "access denied" (.runScriptlet sc "$response.body"))))))))) (deftest http-compressed-requests (jetty10/with-test-webserver ring-app-decompressing-gzipped-request port (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:" port)] (testing "GZIP compression format" (let [compress "{ :compress => :gzip }" body "howdy"] (.runScriptlet sc (format "$response = $c.post(URI('%s'), '%s', options: %s)" url body compress)) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= body (.runScriptlet sc "$response.body"))))) (testing "invalid compression format" (let [compress "{ :compress => :bunk }"] (is (= "Unsupported compression specified for request: bunk" (.runScriptlet sc (str "begin;" (format " $response = $c.post(URI('%s'), 'foo', options: %s);" url compress) " 'No error raised from post';" "rescue ArgumentError => e;" " e.message;" "end"))))))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; SSL Tests (defmacro with-webserver-with-protocols [protocols cipher-suites & body] `(jetty10/with-test-webserver-and-config ring-app port# (merge {:ssl-host "localhost" :ssl-port 10080 :ssl-ca-cert ca-pem :ssl-cert cert-pem :ssl-key privkey-pem} (if ~protocols {:ssl-protocols ~protocols}) (if ~cipher-suites {:cipher-suites ~cipher-suites})) ~@body)) (defn raise-caught-http-error "Returns a Ruby script string that executes `script', rescues the expected Puppet::Server::HttpClientError, and raises the nested exception for testing the underlying cause." [script] (str "begin;" script ";rescue Puppet::Server::HttpClientError => e;" " raise e.cause.getCause;" "end")) (deftest https-tls-defaults (testing "requests fail without an SSL client" (with-webserver-with-protocols nil nil (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:10080")] (logutils/with-test-logging (let [ex-class (if (SSLUtils/isFIPS) ConnectionClosedException ProtocolException)] (try (.runScriptlet sc (raise-caught-http-error (format "$c.get(URI('%s'))" url))) (is false "Expected HTTP connection to HTTPS port to fail") (catch EvalFailedException e (is (instance? ex-class (.getCause e)))))))))))) (testing "Can connect via TLSv1.3 by default" (with-webserver-with-protocols ["TLSv1.3"] nil (with-scripting-container sc (with-http-client sc {:cipher-suites ["TLS_AES_256_GCM_SHA384" "TLS_AES_128_GCM_SHA256"]} (let [url (str "https://localhost:10080")] (.runScriptlet sc (format "$response = $c.get(URI('%s'))" url)) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= "hi" (.runScriptlet sc "$response.body")))))))) (testing "Can connect via TLSv1.2 by default" (with-webserver-with-protocols ["TLSv1.2"] nil (with-scripting-container sc (with-http-client sc {} (let [url (str "https://localhost:10080")] (.runScriptlet sc (format "$response = $c.get(URI('%s'))" url)) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= "hi" (.runScriptlet sc "$response.body"))))))))) (deftest clients-persist (testing "client persists when making HTTP requests" (logutils/with-test-logging (jetty10/with-test-webserver ring-app port (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:" port) client1 (.runScriptlet sc (format "$c.get(URI('%s')); $c.class.client" url)) client2 (.runScriptlet sc (format "$c.post(URI('%s'), 'foo'); $c.class.client" url))] (is (= client1 client2)))))))) (testing "all instances of HttpClient have the same underlying client object" (logutils/with-test-logging (jetty10/with-test-webserver ring-app port (with-scripting-container sc (with-http-client sc {} (let [client1 (.runScriptlet sc "$c.class.client") client2 (.runScriptlet sc (str "$c2 = Puppet::Server::HttpClient.new;" "$c2.class.client"))] (is (= client1 client2))))))))) (deftest connections-closed (testing "connection header always set to close on get" (logutils/with-test-logging (jetty10/with-test-webserver ring-app-connection-closed port (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:" port)] (is (= "The Connection header has value close" (.runScriptlet sc (format "$c.get(URI('%s')).body" url)))))))))) (testing "connection header always set to close on post" (logutils/with-test-logging (jetty10/with-test-webserver ring-app-connection-closed port (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:" port)] (is (= "The Connection header has value close" (.runScriptlet sc (format "$c.post(URI('%s'), 'foo').body" url)))))))))) (testing "client's terminate function closes the client" (logutils/with-test-logging (jetty10/with-test-webserver ring-app-connection-closed port (with-scripting-container sc (with-http-client sc {} (let [url (str "http://localhost:" port)] (.runScriptlet sc (format "$response = $c.get(URI('%s'))" url)) (is (= 200 (.runScriptlet sc "$response.code"))) (.runScriptlet sc "$c.class.terminate") (try (.runScriptlet sc (format "$response = $c.get(URI('%s'))" url)) (catch EvalFailedException e (let [wrapped-exception (.getCause e) message (.getMessage e)] (is (instance? IllegalStateException wrapped-exception)) (is (re-find #"Request cannot be executed; I/O reactor status: STOPPED" message)))))))))))) (deftest http-and-https (testing "can make http calls after https calls without a new scripting container" (logutils/with-test-logging (jetty10/with-test-webserver ring-app-alternate port (with-webserver-with-protocols nil nil (with-scripting-container sc (with-http-client sc {} (let [url (str "https://localhost:10080")] (.runScriptlet sc (format "$response = $c.get(URI('%s'))" url)) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= "hi" (.runScriptlet sc "$response.body"))) (.runScriptlet sc (str "$c = Puppet::Server::HttpClient.new;" (format "$response = $c.get(URI('http://localhost:%s'))" port))) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= "bye" (.runScriptlet sc "$response.body")))))))))) (testing "can make https calls after http calls without a new scripting container" (logutils/with-test-logging (jetty10/with-test-webserver ring-app-alternate port (with-webserver-with-protocols nil nil (with-scripting-container sc (with-http-client sc {} (.runScriptlet sc (format "$response = $c.get(URI('http://localhost:%s'))" port)) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= "bye" (.runScriptlet sc "$response.body"))) (.runScriptlet sc (str "$c = Puppet::Server::HttpClient.new;" "$response = $c.get(URI('https://localhost:10080/'))")) (is (= 200 (.runScriptlet sc "$response.code"))) (is (= "hi" (.runScriptlet sc "$response.body")))))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/000077500000000000000000000000001470345337400250265ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/ca/000077500000000000000000000000001470345337400254115ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/ca/ca_testutils.clj000066400000000000000000000102531470345337400306070ustar00rootroot00000000000000(ns puppetlabs.services.ca.ca-testutils (:require [clojure.test :refer [is]] [me.raynes.fs :as fs] [puppetlabs.kitchensink.core :as ks] [puppetlabs.kitchensink.file :as ks-file] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils]) (:import (java.io ByteArrayInputStream) (java.util.concurrent.locks ReentrantReadWriteLock))) (defn assert-subject [o subject] (is (= subject (-> o .getSubjectX500Principal .getName)))) (defn assert-issuer [o issuer] (is (= issuer (-> o .getIssuerX500Principal .getName)))) (defn pem-to-stream [pem-string] (ByteArrayInputStream. (.getBytes (slurp pem-string)))) (defmacro with-backed-up-crl [crl-path crl-backup-path & body] `(do (fs/copy ~crl-path ~crl-backup-path) (try ~@body (finally (fs/delete ~crl-path) (fs/move ~crl-backup-path ~crl-path))))) (defn master-settings "Master configuration settings with defaults appropriate for testing. All file and directory paths will be rooted at the provided `confdir`." ([confdir] (master-settings confdir "localhost")) ([confdir hostname] (let [ssldir (str confdir "/ssl")] {:certdir (str ssldir "/certs") :dns-alt-names "" :hostcert (str ssldir "/certs/" hostname ".pem") :hostcrl (str ssldir "/certs/crl.pem") :hostprivkey (str ssldir "/private_keys/" hostname ".pem") :hostpubkey (str ssldir "/public_keys/" hostname ".pem") :localcacert (str ssldir "/certs/ca.pem") :privatekeydir (str ssldir "/private_keys") :requestdir (str ssldir "/certificate_requests") :csr-attributes (str confdir "/csr_attributes.yaml") :keylength 512}))) (defn ca-settings "CA configuration settings with defaults appropriate for testing. All file and directory paths will be rooted at the static 'cadir' in dev-resources, unless a different `cadir` is provided." [cadir] {:access-control {:certificate-status {:client-whitelist ["localhost"]}} :autosign true :allow-authorization-extensions false :allow-duplicate-certs false :allow-subject-alt-names false :allow-auto-renewal false :auto-renewal-cert-ttl "90d" :ca-name "test ca" :ca-ttl 1 :allow-header-cert-info false :cadir (str cadir) :cacrl (str cadir "/ca_crl.pem") :cacert (str cadir "/ca_crt.pem") :cakey (str cadir "/ca_key.pem") :capub (str cadir "/ca_pub.pem") :cert-inventory (str cadir "/inventory.txt") :csrdir (str cadir "/requests") :keylength 512 :manage-internal-file-permissions true :signeddir (str cadir "/signed") :serial (str cadir "/serial") :ruby-load-path jruby-testutils/ruby-load-path :gem-path jruby-testutils/gem-path :infra-nodes-path (str cadir "/infra_inventory.txt") :infra-node-serials-path (str cadir "/infra_serials") :infra-crl-path (str cadir "/infra_crl.pem") :enable-infra-crl false :serial-lock (new ReentrantReadWriteLock) :serial-lock-timeout-seconds 5 :crl-lock (new ReentrantReadWriteLock) :crl-lock-timeout-seconds 5 :inventory-lock (new ReentrantReadWriteLock) :inventory-lock-timeout-seconds 5}) (defn ca-sandbox! "Copy the `cadir` to a temporary directory and return the 'ca-settings' map rooted at the temporary directory. The directory will be deleted when the JVM exits." [cadir] (let [tmp-ssldir (ks/temp-dir)] (fs/copy-dir cadir tmp-ssldir) ;; This is to ensure no warnings are logged during tests (ks-file/set-perms (str tmp-ssldir "/ca/ca_key.pem") "rw-r-----") (ca-settings (str tmp-ssldir "/ca")))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/ca/certificate_authority_core_test.clj000066400000000000000000002071601470345337400345520ustar00rootroot00000000000000(ns puppetlabs.services.ca.certificate-authority-core-test (:require [cheshire.core :as json] [clojure.java.io :as io] [clojure.test :refer [deftest is testing use-fixtures]] [me.raynes.fs :as fs] [puppetlabs.ssl-utils.core :as utils] [puppetlabs.kitchensink.core :as ks] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.services.ca.ca-testutils :as testutils] [puppetlabs.services.ca.certificate-authority-core :refer [get-wrapped-handler web-routes handle-get-certificate-revocation-list handle-put-certificate-revocation-list! handle-put-certificate-request! handle-delete-certificate-request!]] [puppetlabs.trapperkeeper.testutils.logging :refer [logged?] :as logutils] [ring.mock.request :as mock] [schema.test :as schema-test] [puppetlabs.comidi :as comidi])) (use-fixtures :once schema-test/validate-schemas) (use-fixtures :each #(logutils/with-test-logging (%))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utilities (def test-resources-dir "./dev-resources/puppetlabs/services/ca/certificate_authority_core_test") (def cadir (str test-resources-dir "/master/conf/ca")) (def csrdir (str cadir "/requests")) (def test-pems-dir (str test-resources-dir "/pems")) (def autosign-files-dir (str test-resources-dir "/autosign")) (defn test-pem-file [pem-file-name] (str test-pems-dir "/" pem-file-name)) (defn test-autosign-file [autosign-file-name] (ks/absolute-path (str autosign-files-dir "/" autosign-file-name))) (def localhost-cert (utils/pem->cert (test-pem-file "localhost-cert.pem"))) (defn build-ring-handler [settings puppet-version] (get-wrapped-handler (-> (web-routes settings (constantly nil)) (comidi/routes->handler)) settings "" (fn [handler] (fn [request] (handler request))) puppet-version)) (defn gen-csr-input-stream! [subject] (let [key-pair (utils/generate-key-pair 512) csr (utils/generate-certificate-request key-pair (utils/cn subject)) pem (java.io.ByteArrayOutputStream.) _ (utils/obj->pem! csr pem)] (io/input-stream (.getBytes (.toString pem))))) (defn wrap-with-ssl-client-cert "Wrap a compojure app so all requests will include the localhost certificate to allow access to the certificate status endpoint." [app] (fn [request] (-> request (assoc :ssl-client-cert localhost-cert) (app)))) (defn body-stream [s] (io/input-stream (.getBytes s))) (def localhost-status {:authorization_extensions {:pp_cli_auth "true"} :dns_alt_names ["DNS:localhost" "DNS:djroomba.vpn.puppetlabs.net" "DNS:puppet.vpn.puppetlabs.net" "DNS:puppet"] :fingerprint "88:B1:67:67:78:E2:62:FD:8E:1B:8F:29:CB:2E:C9:41:E1:D3:36:44:27:AB:F9:E4:A7:87:C6:E3:FE:7C:C1:DC" :fingerprints {:SHA1 "D4:3F:14:87:B9:80:FF:FF:90:0B:F2:69:81:64:07:B4:D2:65:72:92" :SHA256 "88:B1:67:67:78:E2:62:FD:8E:1B:8F:29:CB:2E:C9:41:E1:D3:36:44:27:AB:F9:E4:A7:87:C6:E3:FE:7C:C1:DC" :SHA512 "E2:97:07:DB:5C:1B:FE:D2:04:4B:94:95:3C:06:4D:2F:6C:B6:67:98:F8:3D:86:82:D1:8E:16:C9:F9:59:8F:19:92:94:69:5B:8B:A8:0A:3E:FF:E4:52:57:79:74:75:79:33:E3:B4:69:C3:16:95:02:4D:D4:F5:60:67:13:11:F9" :default "88:B1:67:67:78:E2:62:FD:8E:1B:8F:29:CB:2E:C9:41:E1:D3:36:44:27:AB:F9:E4:A7:87:C6:E3:FE:7C:C1:DC"} :name "localhost" :not_after "2025-08-20T22:06:21UTC" :not_before "2020-08-20T22:06:21UTC" :serial_number 7 :state "signed" :subject_alt_names ["DNS:localhost" "DNS:djroomba.vpn.puppetlabs.net" "DNS:puppet.vpn.puppetlabs.net" "DNS:puppet"]}) (def test-agent-status {:authorization_extensions {} :dns_alt_names [] :fingerprint "D4:9C:03:6A:4B:4E:51:87:54:5B:BD:93:8E:4A:06:A7:6F:94:CE:33:62:F9:F4:74:61:4D:20:B1:A9:23:C8:0C" :fingerprints {:SHA1 "91:A4:AE:9C:8D:DF:D1:7D:77:85:97:19:C1:85:12:12:89:69:C5:73" :SHA256 "D4:9C:03:6A:4B:4E:51:87:54:5B:BD:93:8E:4A:06:A7:6F:94:CE:33:62:F9:F4:74:61:4D:20:B1:A9:23:C8:0C" :SHA512 "51:DE:0B:B1:B2:1A:5C:3E:2B:D8:84:DE:03:B0:AF:9B:78:2C:A3:9A:70:15:B2:15:00:2C:B5:4F:99:8B:CB:98:9F:CE:C3:28:5C:02:A9:CD:3B:D9:34:E7:CB:D8:E1:5D:24:11:B9:4A:78:FF:68:92:12:CA:B3:A7:D2:89:22:38" :default "D4:9C:03:6A:4B:4E:51:87:54:5B:BD:93:8E:4A:06:A7:6F:94:CE:33:62:F9:F4:74:61:4D:20:B1:A9:23:C8:0C"} :name "test-agent" :state "requested" :subject_alt_names []}) (def revoked-agent-status {:authorization_extensions {} :dns_alt_names ["DNS:BAR" "DNS:Baz4" "DNS:foo" "DNS:revoked-agent"] :subject_alt_names ["DNS:BAR" "DNS:Baz4" "DNS:foo" "DNS:revoked-agent"] :fingerprint "26:BE:A0:35:50:5E:C8:9A:BB:FB:12:EC:3A:CD:7E:F4:71:9B:86:C1:3B:CC:3B:3B:44:8D:9D:68:12:6A:C8:E2" :fingerprints {:SHA1 "22:37:E2:C9:FB:20:8F:AA:71:72:EE:B7:02:D8:BE:35:D5:91:61:1B" :SHA256 "26:BE:A0:35:50:5E:C8:9A:BB:FB:12:EC:3A:CD:7E:F4:71:9B:86:C1:3B:CC:3B:3B:44:8D:9D:68:12:6A:C8:E2" :SHA512 "7A:35:00:F1:F6:8F:72:01:D7:5F:95:EC:D7:D7:03:DC:BC:55:95:98:F4:48:5E:B4:22:3B:1B:B1:82:B9:6C:59:7C:05:54:86:40:33:CE:3A:9E:75:E9:27:23:95:6E:D8:04:7A:3C:26:8E:0D:70:9B:F6:1F:74:51:29:97:1E:28" :default "26:BE:A0:35:50:5E:C8:9A:BB:FB:12:EC:3A:CD:7E:F4:71:9B:86:C1:3B:CC:3B:3B:44:8D:9D:68:12:6A:C8:E2"} :name "revoked-agent" :not_after "2025-08-20T20:37:00UTC" :not_before "2020-08-20T20:37:00UTC" :serial_number 5 :state "revoked"}) (def test-cert-status {:authorization_extensions {} :dns_alt_names [] :subject_alt_names [] :fingerprint "00:A9:C2:5E:2A:66:18:E2:99:DF:27:13:36:7E:DB:4D:9B:DC:93:DD:3A:B2:69:48:AD:1A:3B:12:45:BF:CF:8A" :fingerprints {:SHA1 "CF:F9:E9:7E:05:13:1E:ED:CB:3B:94:49:07:D5:3E:6E:12:8C:5C:E4" :SHA256 "00:A9:C2:5E:2A:66:18:E2:99:DF:27:13:36:7E:DB:4D:9B:DC:93:DD:3A:B2:69:48:AD:1A:3B:12:45:BF:CF:8A" :SHA512 "7F:3A:D0:4C:12:68:FA:1C:B4:DE:7F:B7:39:AE:94:00:33:02:B9:E7:B1:2D:8F:6C:BB:58:84:0A:EF:98:D2:79:9F:12:76:23:58:2F:3D:CE:E9:34:16:88:43:DD:2E:A6:98:5E:33:FB:B1:61:38:5E:58:BC:EA:F9:4A:BC:E8:12" :default "00:A9:C2:5E:2A:66:18:E2:99:DF:27:13:36:7E:DB:4D:9B:DC:93:DD:3A:B2:69:48:AD:1A:3B:12:45:BF:CF:8A"} :name "test_cert" :not_after "2025-08-20T20:30:32UTC" :not_before "2020-08-20T20:30:32UTC" :serial_number 3 :state "signed"}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Tests (deftest crl-endpoint-test (testing "implementation of the CRL endpoint with no 'If-Modified-Since' header" (let [request (mock/request :get "/v1/certificate_revocation_list/mynode") ca-settings (testutils/ca-settings cadir) response (handle-get-certificate-revocation-list request (assoc ca-settings :cacrl (test-pem-file "crl.pem") :infra-crl-path (test-pem-file "crl.pem") :enable-infra-crl false))] (is (map? response)) (is (= 200 (:status response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (string? (:body response))))) (testing "with a malformed http-date 'If-Modified-Since' header" (let [ring-app (build-ring-handler (testutils/ca-settings cadir) "42.42.42") request {:uri "/v1/certificate_revocation_list/mynode" :request-method :get :headers {"If-Modified-Since" "Wed, 21 Oct 2015 07:28:00"}} response (ring-app request)] (is (= 200 (:status response))) (is (string? (:body response))))) (testing "with older 'If-Modified-Since' header" (let [ring-app (build-ring-handler (testutils/ca-settings cadir) "42.42.42") request {:uri "/v1/certificate_revocation_list/mynode" :request-method :get :headers {"If-Modified-Since" "Wed, 21 Oct 2015 07:28:00 GMT"}} response (ring-app request)] (is (= 200 (:status response))) (is (string? (:body response))))) (testing "with newer 'If-Modified-Since' header" (let [ring-app (build-ring-handler (testutils/ca-settings cadir) "42.42.42") request {:uri "/v1/certificate_revocation_list/mynode" :request-method :get :headers {"If-Modified-Since" "Wed, 21 Oct 3015 07:28:00 GMT"}} response (ring-app request)] (is (= 304 (:status response))) (is (nil? (:body response)))))) (deftest certificate-endpoint-test (testing "implementation of the CRL endpoint with no 'If-Modified-Since' header" (let [ring-app (build-ring-handler (testutils/ca-settings cadir) "42.42.42") request {:uri "/v1/certificate/localhost" :request-method :get :headers {}} response (ring-app request)] (is (= 200 (:status response))) (is (string? (:body response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))))) (testing "with a malformed http-date 'If-Modified-Since' header" (let [ring-app (build-ring-handler (testutils/ca-settings cadir) "42.42.42") request {:uri "/v1/certificate/localhost" :request-method :get :headers {"If-Modified-Since" "Wed, 21 Oct 2015 07:28:00"}} response (ring-app request)] (is (= 200 (:status response))) (is (string? (:body response))))) (testing "with older 'If-Modified-Since' header" (let [ring-app (build-ring-handler (testutils/ca-settings cadir) "42.42.42") request {:uri "/v1/certificate/localhost" :request-method :get :headers {"If-Modified-Since" "Wed, 21 Oct 2015 07:28:00 GMT"}} response (ring-app request)] (is (= 200 (:status response))) (is (string? (:body response))))) (testing "with newer 'If-Modified-Since' header" (let [ring-app (build-ring-handler (testutils/ca-settings cadir) "42.42.42") request {:uri "/v1/certificate/localhost" :request-method :get :headers {"If-Modified-Since" "Wed, 21 Oct 3015 07:28:00 GMT"}} response (ring-app request)] (is (= 304 (:status response))) (is (nil? (:body response)))))) (deftest handle-put-certificate-revocation-list!-test (let [{:keys [cacrl cacert] :as settings} (testutils/ca-sandbox! cadir) fixtures-dir (str test-resources-dir "/update_crls")] (fs/copy (str fixtures-dir "/ca_crl.pem") cacrl) (fs/copy (str fixtures-dir "/ca_crt.pem") cacert) (logutils/with-test-logging (testing "with a valid replacement CRL" (let [incoming-crl (testutils/pem-to-stream (str fixtures-dir "/new_root_crl.pem")) crl-backup-path (str test-resources-dir "/crl_backup.pem")] (testutils/with-backed-up-crl cacrl crl-backup-path (let [response (handle-put-certificate-revocation-list! incoming-crl settings) new-crl (utils/pem->crls cacrl) old-crl (utils/pem->crls crl-backup-path)] (is (= 200 (:status response))) (is (> (utils/get-crl-number (last new-crl)) (utils/get-crl-number (last old-crl)))))))) (testing "with an invalid replacement CRL" (let [incoming-crl (testutils/pem-to-stream (str fixtures-dir "/multiple_newest_root_crls.pem")) crl-backup-path (str test-resources-dir "/crl_backup.pem")] (testutils/with-backed-up-crl cacrl crl-backup-path (let [response (handle-put-certificate-revocation-list! incoming-crl settings) new-crl (utils/pem->crls cacrl) old-crl (utils/pem->crls crl-backup-path)] (is (= 400 (:status response))) (is (= "Could not determine newest CRL." (:body response))) (is (= new-crl old-crl)))))) (testing "with infra CRL enabled" (let [settings-infra-enabled (assoc settings :enable-infra-crl true) infra-crl-path (:infra-crl-path settings-infra-enabled) crl-backup-path (str test-resources-dir "/crl_backup.pem") infra-crl-backup-path (str test-resources-dir "/infra_crl_backup.pem")] (fs/copy (str fixtures-dir "/ca_crl.pem") (:infra-crl-path settings-infra-enabled)) (testing "with a valid replacement CRL" (testutils/with-backed-up-crl cacrl crl-backup-path (fs/copy infra-crl-path infra-crl-backup-path) (try (let [incoming-crl (testutils/pem-to-stream (str fixtures-dir "/new_root_crl.pem")) response (handle-put-certificate-revocation-list! incoming-crl settings-infra-enabled) new-crl (utils/pem->crls cacrl) old-crl (utils/pem->crls crl-backup-path) new-infra-crl (utils/pem->crls infra-crl-path) old-infra-crl (utils/pem->crls infra-crl-backup-path)] (is (= 200 (:status response))) (is (> (utils/get-crl-number (last new-crl)) (utils/get-crl-number (last old-crl)))) (is (> (utils/get-crl-number (last new-infra-crl)) (utils/get-crl-number (last old-infra-crl)))) (is (= (first new-crl) (first old-crl))) (is (= (first new-infra-crl) (first old-infra-crl)))) (finally (fs/delete infra-crl-path) (fs/move infra-crl-backup-path infra-crl-path))))) (testing "with a invalid replacement CRL" (testutils/with-backed-up-crl cacrl crl-backup-path (fs/copy infra-crl-path infra-crl-backup-path) (try (let [incoming-crls (testutils/pem-to-stream (str fixtures-dir "/multiple_newest_root_crls.pem")) response (handle-put-certificate-revocation-list! incoming-crls settings-infra-enabled) new-crl (utils/pem->crls cacrl) old-crl (utils/pem->crls crl-backup-path) new-infra-crl (utils/pem->crls infra-crl-path) old-infra-crl (utils/pem->crls infra-crl-backup-path)] (is (= 400 (:status response))) (is (= "Could not determine newest CRL." (:body response))) (is (= new-crl old-crl)) (is (= new-infra-crl old-infra-crl))) (finally (fs/delete infra-crl-path) (fs/move infra-crl-backup-path infra-crl-path)))))))))) (deftest puppet-version-header-test (testing "Responses contain a X-Puppet-Version header" (let [version-number "42.42.42" ring-app (build-ring-handler (testutils/ca-settings cadir) version-number) ;; we can just GET the /CRL endpoint, so that's an easy test here. request (mock/request :get "/v1/certificate_revocation_list/mynode") response (ring-app request)] (is (= version-number (get-in response [:headers "X-Puppet-Version"])))))) (deftest handle-delete-certificate-request!-test (let [settings (assoc (testutils/ca-sandbox! cadir) :allow-duplicate-certs true :autosign false) request {:authorization {:name "authname"} :remote-addr "1.1.1.1"}] (testing "successful csr deletion" (logutils/with-test-logging (let [subject "happy-agent" csr-stream (gen-csr-input-stream! subject) expected-path (ca/path-to-cert-request (:csrdir settings) subject) request (assoc request :route-params {:subject subject} :body csr-stream)] (try (handle-put-certificate-request! settings (constantly nil) request) (is (true? (fs/exists? expected-path))) (let [response (handle-delete-certificate-request! subject settings) msg-matcher (re-pattern (str "Deleted .* for " subject ".*"))] (is (false? (fs/exists? expected-path))) (is (= 204 (:status response))) (is (re-matches msg-matcher (:body response))) (is (logged? msg-matcher :debug))) (finally (fs/delete expected-path)))))) (testing "Attempted deletion of a non-existant CSR" (logutils/with-test-logging (let [subject "not-found-agent" response (handle-delete-certificate-request! subject settings) expected-path (ca/path-to-cert-request (:csrdir settings) subject) msg-matcher (re-pattern (str "No cert.*request for " subject " at.*" expected-path))] (is (false? (fs/exists? expected-path))) (is (= 404 (:status response))) (is (re-matches msg-matcher (:body response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (logged? msg-matcher :warn))))) (testing "Error during deletion of a CSR" (logutils/with-test-logging (let [subject "err-agent" csr-stream (gen-csr-input-stream! subject) expected-path (ca/path-to-cert-request (:csrdir settings) subject) request (assoc request :route-params {:subject subject} :body csr-stream)] (try (handle-put-certificate-request! settings (constantly nil) request) (is (true? (fs/exists? expected-path))) (fs/chmod "-w" (fs/parent expected-path)) (let [response (handle-delete-certificate-request! subject settings) msg-matcher (re-pattern (str "Path " expected-path " exists but.*"))] (is (= 500 (:status response))) (is (re-matches msg-matcher (:body response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (logged? msg-matcher :error))) (finally (fs/chmod "+w" (fs/parent expected-path))))))))) (deftest handle-put-certificate-request!-test (let [settings (assoc (testutils/ca-sandbox! cadir) :allow-duplicate-certs true) static-csr (ca/path-to-cert-request csrdir "test-agent") request {:authorization {:name "ca certname"} :remote-addr "1.1.1.1" :route-params {:subject "test-agent"}}] (logutils/with-test-logging (testing "when autosign results in true" (doseq [value [true (test-autosign-file "ruby-autosign-executable") (test-autosign-file "autosign-whitelist.conf")]] (let [settings (assoc settings :autosign value) csr-stream (io/input-stream static-csr) expected-path (ca/path-to-cert (:signeddir settings) "test-agent") request (assoc request :body csr-stream)] (testing "it signs the CSR, writes the certificate to disk, and returns a 200 response with empty plaintext body" (try (is (false? (fs/exists? expected-path))) (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (true? (fs/exists? expected-path))) (is (= 200 (:status response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (nil? (:body response)))) (finally (fs/delete expected-path)))))) (let [ca-cert-file (ca/path-to-cert cadir "ca_crt_multiple_rdns") ca-subject-bytes (-> ca-cert-file (utils/pem->cert) (.getSubjectX500Principal) (.getEncoded)) settings (assoc settings :autosign true :cacert ca-cert-file) csr-stream (io/input-stream static-csr) expected-path (ca/path-to-cert (:signeddir settings) "test-agent") request (assoc request :body csr-stream)] (testing "a multi-RDN CA subject is properly set as signed cert's issuer" (try (is (false? (fs/exists? expected-path))) (let [response (handle-put-certificate-request! settings (constantly nil) request) signed-cert-issuer-bytes (-> (utils/pem->cert expected-path) (.getIssuerX500Principal) (.getEncoded))] (is (true? (fs/exists? expected-path))) (is (= 200 (:status response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (nil? (:body response))) (is (= (seq ca-subject-bytes) (seq signed-cert-issuer-bytes)))) (finally (fs/delete expected-path)))))) (testing "when autosign results in false" (doseq [value [false (test-autosign-file "ruby-autosign-executable-false") (test-autosign-file "autosign-whitelist.conf")]] (let [settings (assoc settings :autosign value) csr-stream (io/input-stream (test-pem-file "foo-agent-csr.pem")) expected-path (ca/path-to-cert-request (:csrdir settings) "foo-agent") request (assoc request :route-params {:subject "foo-agent"} :body csr-stream)] (testing "it writes the CSR to disk and returns a 200 response with empty plaintext body" (try (is (false? (fs/exists? expected-path))) (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (true? (fs/exists? expected-path))) (is (false? (fs/exists? (ca/path-to-cert (:signeddir settings) "foo-agent")))) (is (= 200 (:status response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (nil? (:body response)))) (finally (fs/delete expected-path))))))) (testing "when $allow-duplicate-certs is false and we receive a new CSR, return a 400 response and error message" (let [settings (assoc settings :allow-duplicate-certs false) csr-stream (io/input-stream static-csr) request (assoc request :route-params {:subject "test-agent"} :body csr-stream)] ;; Put the duplicate in place (fs/copy static-csr (ca/path-to-cert-request (:csrdir settings) "test-agent")) (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (logged? #"ignoring certificate request" :error)) (is (= 400 (:status response))) (is (true? (.contains (:body response) "ignoring certificate request")))))) (testing "when the subject CN on a CSR does not match the hostname specified in the URL, the response is a 400" (let [csr-stream (io/input-stream static-csr) request (assoc request :route-params {:subject "NOT-test-agent"} :body csr-stream) response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 400 (:status response))) (is (re-matches #"Instance name \"test-agent\" does not match requested key \"NOT-test-agent\"" (:body response))))) (testing "when the public key on the CSR is bogus, the response is a 400" (let [csr-with-bad-public-key (test-pem-file "luke.madstop.com-bad-public-key.pem") csr-stream (io/input-stream csr-with-bad-public-key) request (assoc request :route-params {:subject "luke.madstop.com"} :body csr-stream) response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 400 (:status response))) (is (= "CSR contains a public key that does not correspond to the signing key" (:body response))))) (testing "when the CSR has disallowed extensions on it, the response is a 400" (let [csr-with-bad-ext (test-pem-file "meow-bad-extension.pem") csr-stream (io/input-stream csr-with-bad-ext) request (assoc request :route-params {:subject "meow"} :body csr-stream) response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 400 (:status response))) (is (= "Found extensions that are not permitted: 1.9.9.9.9.9.9" (:body response)))) (let [csr-with-bad-ext (test-pem-file "woof-bad-extensions.pem") csr-stream (io/input-stream csr-with-bad-ext) request (assoc request :route-params {:subject "woof"} :body csr-stream) response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 400 (:status response))) (is (= "Found extensions that are not permitted: 1.9.9.9.9.9.0, 1.9.9.9.9.9.1" (:body response))))) (testing "when the CSR subject contains invalid characters, the response is a 400" ;; These test cases are lifted out of the puppet spec tests. (let [bad-csrs #{{:subject "super/bad" :csr (test-pem-file "bad-subject-name-1.pem")} {:subject "not\neven\tkind\rof" :csr (test-pem-file "bad-subject-name-2.pem")} {:subject "hidden\b\b\b\b\b\bmessage" :csr (test-pem-file "bad-subject-name-3.pem")}}] (doseq [{:keys [subject csr]} bad-csrs] (let [csr-stream (io/input-stream csr) request (assoc request :route-params {:subject subject} :body csr-stream) response (handle-put-certificate-request! settings nil request)] (is (= 400 (:status response))) (is (= "Subject hostname format is invalid" (:body response))))))) (testing "no wildcards allowed" (let [csr-with-wildcard (test-pem-file "bad-subject-name-wildcard.pem") csr-stream (io/input-stream csr-with-wildcard) request (assoc request :route-params {:subject "foo*bar"} :body csr-stream) response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 400 (:status response))) (is (= "Subject contains a wildcard, which is not allowed: foo*bar" (:body response))))) (testing "a CSR w/ DNS alt-names and disallowed subject-alt-names gets a specific error response" (let [csr (io/input-stream (test-pem-file "hostwithaltnames.pem")) settings (assoc settings :allow-subject-alt-names false) request (assoc request :route-params {:subject "hostwithaltnames"} :body csr) response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 400 (:status response))) (is (re-find #"hostwithaltnames.*disallowed" (:body response))))) (testing "a CSR w/ DNS alt-names and allowed subject-alt-names returns 200" (let [csr (io/input-stream (test-pem-file "hostwithaltnames.pem")) settings (assoc settings :allow-subject-alt-names true) expected-path (ca/path-to-cert-request (:csrdir settings) "hostwithaltnames") request (assoc request :route-params {:subject "hostwithaltnames"} :body csr)] (try (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 200 (:status response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (nil? (:body response)))) (finally (fs/delete expected-path))))) (testing "a CSR w/ DNS and IP alt-names and disallowed subject-alt-names gets a specific error response" (let [csr (io/input-stream (test-pem-file "host-with-ip-and-dns-altnames.pem")) settings (assoc settings :allow-subject-alt-names false) request (assoc request :route-params {:subject "host-with-ip-and-dns-altnames"} :body csr) response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 400 (:status response))) (is (re-find #"host-with-ip-and-dns-altnames" (:body response))))) (testing "a CSR w/ DNS and IP alt-names and allowed subject-alt-names returns 200" (let [csr (io/input-stream (test-pem-file "host-with-ip-and-dns-altnames.pem")) settings (assoc settings :allow-subject-alt-names true) expected-path (ca/path-to-cert-request (:csrdir settings) "host-with-ip-and-dns-altnames") request (assoc request :route-params {:subject "host-with-ip-and-dns-altnames"} :body csr)] (try (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 200 (:status response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (nil? (:body response)))) (finally (fs/delete expected-path))))) (testing "a CSR w/ auth extensions and allowed auth extensions returns 200" (let [csr (io/input-stream (test-pem-file "csr-auth-extension.pem")) settings (assoc settings :allow-authorization-extensions true) expected-path (ca/path-to-cert-request (:csrdir settings) "csr-auth-extension") request (assoc request :route-params {:subject "csr-auth-extension"} :body csr)] (try (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 200 (:status response))) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (nil? (:body response)))) (finally (fs/delete expected-path))))) (testing "a CSR w/ auth extensions and disallowed auth extensions gets a specific error response" (let [csr (io/input-stream (test-pem-file "csr-auth-extension.pem")) settings (assoc settings :allow-authorization-extensions false) request (assoc request :route-params {:subject "csr-auth-extension"} :body csr) response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 400 (:status response))) (is (re-find #"csr-auth-extension.*disallowed" (:body response)))) (testing "when authname provided on signing" (logutils/with-test-logging (let [csr-stream (io/input-stream static-csr) signee "authname" certname "test-agent" request {:authorization {:name signee} :remote-addr "1.1.1.1" :body csr-stream :route-params {:subject certname}} msg-matcher (re-pattern (str "Entity " signee " signed 1 certificate: " certname)) expected-path (ca/path-to-cert (:signeddir settings) certname)] (try (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 200 (:status response))) (is (logged? msg-matcher :info))) (finally (fs/delete expected-path)))))) (testing "when rbac-subject provided on signing" (logutils/with-test-logging (let [csr-stream (io/input-stream static-csr) signee "rbac-subject" certname "test-agent" request {:rbac-subject {:login signee} :remote-addr "1.1.1.1" :body csr-stream :route-params {:subject certname}} msg-matcher (re-pattern (str "Entity " signee " signed 1 certificate: " certname)) expected-path (ca/path-to-cert (:signeddir settings) certname)] (try (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 200 (:status response))) (is (logged? msg-matcher :info))) (finally (fs/delete expected-path)))))) (testing "when no signee info provided" (logutils/with-test-logging (let [csr-stream (io/input-stream static-csr) certname "test-agent" request {:remote-addr "1.1.1.1" :body csr-stream :route-params {:subject certname}} msg-matcher (re-pattern (str "Entity CA signed 1 certificate: " certname)) expected-path (ca/path-to-cert (:signeddir settings) certname)] (try (let [response (handle-put-certificate-request! settings (constantly nil) request)] (is (= 200 (:status response))) (is (logged? msg-matcher :info))) (finally (fs/delete expected-path)))))))))) (deftest certificate-status-test (testing "read requests" (let [test-app (-> (build-ring-handler (testutils/ca-settings cadir) "42.42.42") (wrap-with-ssl-client-cert))] (testing "GET /certificate_status" (doseq [[subject status] [["localhost" localhost-status] ["test-agent" test-agent-status] ["revoked-agent" revoked-agent-status]]] (testing subject (let [response (test-app {:uri (str "/v1/certificate_status/" subject) :request-method :get})] (is (= 200 (:status response)) (str "Error requesting status for " subject)) (is (= status (json/parse-string (:body response) true)))))) (testing "returns a 404 when a non-existent certname is given" (let [request {:uri "/v1/certificate_status/doesnotexist" :request-method :get} response (test-app request)] (is (= 404 (:status response))))) (testing "returns json when no accept header specified" (let [request {:uri "/v1/certificate_status/localhost" :request-method :get :headers {}} response (test-app request)] (is (= 200 (:status response)) (ks/pprint-to-string response)) (is (.startsWith (get-in response [:headers "Content-Type"]) "application/json")))) (testing "honors 'Accept: pson' header" (let [request {:uri "/v1/certificate_status/localhost" :request-method :get :headers {"accept" "pson"}} response (test-app request)] (is (= 200 (:status response)) (ks/pprint-to-string response)) (is (.startsWith (get-in response [:headers "Content-Type"]) "pson")))) (testing "honors 'Accept: text/pson' header" (let [request {:uri "/v1/certificate_status/localhost" :request-method :get :headers {"accept" "text/pson"}} response (test-app request)] (is (= 200 (:status response)) (ks/pprint-to-string response)) (is (.startsWith (get-in response [:headers "Content-Type"]) "text/pson")))) (testing "honors 'Accept: application/json' header" (let [request {:uri "/v1/certificate_status/localhost" :request-method :get :headers {"accept" "application/json"}} response (test-app request)] (is (= 200 (:status response)) (ks/pprint-to-string response)) (is (.startsWith (get-in response [:headers "Content-Type"]) "application/json"))))) (testing "GET /certificate_statuses" (let [response (test-app {:uri "/v1/certificate_statuses/thisisirrelevant" :request-method :get})] (is (= 200 (:status response))) (is (= #{localhost-status test-agent-status test-cert-status revoked-agent-status} (set (json/parse-string (:body response) true))))) (testing "requires ignored path segment" (let [response (test-app {:uri "/v1/certificate_statuses/" :request-method :get})] (is (= 400 (:status response))) (is (= "text/plain; charset=utf-8" (get-in response [:headers "Content-Type"]))) (is (= "Missing URL Segment" (:body response))))) (testing "allows special characters in ignored path segment" (let [response (test-app {:uri "/v1/certificate_statuses/*" :request-method :get})] (is (= 200 (:status response))) (is (= #{localhost-status test-agent-status test-cert-status revoked-agent-status} (set (json/parse-string (:body response) true)))))) (testing "respects 'state' query param" (testing "requested" (let [response (test-app {:uri "/v1/certificate_statuses/thisisirrelevant" :params {"state" "requested"} :request-method :get})] (is (= 200 (:status response))) (is (= #{test-agent-status} (set (json/parse-string (:body response) true)))))) (testing "signed" (let [response (test-app {:uri "/v1/certificate_statuses/thisisirrelevant" :params {"state" "signed"} :request-method :get})] (is (= 200 (:status response))) (is (= #{localhost-status test-cert-status} (set (json/parse-string (:body response) true)))))) (testing "revoked" (let [response (test-app {:uri "/v1/certificate_statuses/thisisirrelevant" :params {"state" "revoked"} :request-method :get})] (is (= 200 (:status response))) (is (= #{revoked-agent-status} (set (json/parse-string (:body response) true))))))) (testing "returns json when no accept header specified" (let [response (test-app {:uri "/v1/certificate_statuses/thisisirrelevant" :request-method :get :headers {}})] (is (= 200 (:status response))) (is (.startsWith (get-in response [:headers "Content-Type"]) "application/json")) (is (= #{localhost-status test-agent-status test-cert-status revoked-agent-status} (set (json/parse-string (:body response) true)))))) (testing "with 'Accept: pson'" (let [response (test-app {:uri "/v1/certificate_statuses/thisisirrelevant" :request-method :get :headers {"accept" "pson"}})] (is (= 200 (:status response))) (is (.startsWith (get-in response [:headers "Content-Type"]) "pson")) (is (= #{localhost-status test-agent-status test-cert-status revoked-agent-status} (set (json/parse-string (:body response) true)))))) (testing "with 'Accept: text/pson'" (let [response (test-app {:uri "/v1/certificate_statuses/thisisirrelevant" :request-method :get :headers {"accept" "text/pson"}})] (is (= 200 (:status response))) (is (.startsWith (get-in response [:headers "Content-Type"]) "text/pson")) (is (= #{localhost-status test-agent-status test-cert-status revoked-agent-status} (set (json/parse-string (:body response) true)))))) (testing "with 'Accept: application/json'" (let [response (test-app {:uri "/v1/certificate_statuses/thisisirrelevant" :request-method :get :headers {"accept" "application/json"}})] (is (= 200 (:status response))) (is (.startsWith (get-in response [:headers "Content-Type"]) "application/json")) (is (= #{localhost-status test-agent-status test-cert-status revoked-agent-status} (set (json/parse-string (:body response) true))))))))) (testing "write requests" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert))] (testing "PUT" (testing "signing a cert with an hour ttl" (let [csr-path (ca/path-to-cert-request (:csrdir settings) "test-agent") signed-cert-path (ca/path-to-cert (:signeddir settings) "test-agent") static-csr (ca/path-to-cert-request csrdir "test-agent")] (is (false? (fs/exists? signed-cert-path))) (try (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :body (body-stream "{\"desired_state\":\"signed\",\"cert_ttl\":3600}")})] (is (true? (fs/exists? signed-cert-path))) (let [cert (utils/pem->cert signed-cert-path) date (java.util.Calendar/getInstance)] (is (nil? (.checkValidity cert (.getTime date)))) (.add date (java.util.Calendar/YEAR) 2) (is (thrown? java.security.cert.CertificateExpiredException (.checkValidity cert (.getTime date))))) (is (= 204 (:status response)) (ks/pprint-to-string response))) (finally (fs/copy static-csr csr-path) (fs/delete signed-cert-path))))) (testing "signing a cert with a CA that has multiple RDNs" (let [ca-cert-with-mult-rdns (ca/path-to-cert cadir "ca_crt_multiple_rdns") ca-subject-bytes (-> ca-cert-with-mult-rdns (utils/pem->cert) (.getSubjectX500Principal) (.getEncoded)) ca-cert-path (:cacert settings) csr-path (ca/path-to-cert-request (:csrdir settings) "test-agent") signed-cert-path (ca/path-to-cert (:signeddir settings) "test-agent") original-ca-cert (ca/path-to-cert cadir "ca_crt") static-csr (ca/path-to-cert-request csrdir "test-agent")] (try (is (false? (fs/exists? signed-cert-path))) (fs/copy ca-cert-with-mult-rdns ca-cert-path) (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :body (body-stream "{\"desired_state\":\"signed\"}")}) signed-cert-issuer-bytes (-> (utils/pem->cert signed-cert-path) (.getIssuerX500Principal) (.getEncoded))] (is (true? (fs/exists? signed-cert-path))) (is (= 204 (:status response)) (ks/pprint-to-string response)) (is (= "text/plain" (get-in response [:headers "Content-Type"]))) (is (= "" (:body response))) (is (= (seq ca-subject-bytes) (seq signed-cert-issuer-bytes)))) (finally (fs/copy static-csr csr-path) (fs/copy original-ca-cert ca-cert-path) (fs/delete signed-cert-path))))) (testing "revoking a cert" (let [cert (utils/pem->cert (ca/path-to-cert (:signeddir settings) "localhost"))] (is (false? (utils/revoked? (utils/pem->crl (:cacrl settings)) cert))) (let [response (test-app {:uri "/v1/certificate_status/localhost" :request-method :put :body (body-stream "{\"desired_state\":\"revoked\"}")})] (is (true? (utils/revoked? (utils/pem->crl (:cacrl settings)) cert))) (is (= 204 (:status response)))))) (testing "no body results in a 400" (let [request {:uri "/v1/certificate_status/test-agent" :request-method :put} response (test-app request)] (is (= 400 (:status response))) (is (= (:body response) "Empty request body.")))) (testing "a body that isn't JSON results in a 400" (let [request {:body (body-stream "this is not JSON") :uri "/v1/certificate_status/test-agent" :request-method :put} response (test-app request)] (is (= 400 (:status response))) (is (= (:body response) "Request body is not JSON.")))) (testing "invalid cert_ttl value results in a 400" (let [request {:uri "/v1/certificate_status/test-agent" :request-method :put :body (body-stream "{\"desired_state\":\"signed\",\"cert_ttl\":\"astring\"}")} response (test-app request)] (is (= 400 (:status response))) (is (= (:body response) "cert_ttl specified for host test-agent must be an integer, not \"astring\"")))) (testing "invalid cert status results in a 400" (let [request {:uri "/v1/certificate_status/test-agent" :request-method :put :body (body-stream "{\"desired_state\":\"bogus\"}")} response (test-app request)] (is (= 400 (:status response))) (is (= (:body response) "State bogus invalid; Must specify desired state of 'signed' or 'revoked' for host test-agent.")))) (testing "returns a 404 when a non-existent certname is given" (let [request {:uri "/v1/certificate_status/doesnotexist" :request-method :put :body (body-stream "{\"desired_state\":\"signed\"}")} response (test-app request)] (is (= 404 (:status response))) (is (= "text/plain; charset=UTF-8" (get-in response [:headers "Content-Type"])) "Unexpected content type for response") (is (= "Invalid certificate subject." (:body response))))) (testing "Additional error handling on PUT requests" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert))] (testing "Asking to revoke a cert that hasn't been signed yet is a 409" (let [request {:uri "/v1/certificate_status/test-agent" :request-method :put :body (body-stream "{\"desired_state\":\"revoked\"}")} response (test-app request)] (is (= 409 (:status response)) (ks/pprint-to-string response)) (is (= "text/plain; charset=UTF-8" (get-in response [:headers "Content-Type"])) "Unexpected content type for response") (is (= (:body response) "Cannot revoke certificate for host test-agent without a signed certificate") (ks/pprint-to-string response)))) (testing "trying to sign a cert that's already signed is a 409" (let [request {:uri "/v1/certificate_status/localhost" :request-method :put :body (body-stream "{\"desired_state\":\"signed\"}")} response (test-app request)] (is (= 409 (:status response))) (is (= "text/plain; charset=UTF-8" (get-in response [:headers "Content-Type"])) "Unexpected content type for response") (is (= (:body response) "Cannot sign certificate for host localhost without a certificate request")))) (testing "trying to revoke a cert that's already revoked is a 204" (let [request {:uri "/v1/certificate_status/revoked-agent" :request-method :put :body (body-stream "{\"desired_state\":\"revoked\"}")} response (test-app request)] (is (= 204 (:status response))))) (testing "failing to provide a desired_state returns 400" (let [request {:uri "/v1/certificate_status/revoked-agent" :request-method :put :body (body-stream "{\"foo_state\":\"revoked\"}")} response (test-app request)] (is (= 400 (:status response))) (is (= (:body response) "Missing required parameter \"desired_state\""))))))) (testing "DELETE" (let [csr (ca/path-to-cert-request (:csrdir settings) "test-agent")] (fs/copy (ca/path-to-cert-request csrdir "test-agent") csr) (is (true? (fs/exists? csr))) (is (= 204 (:status (test-app {:uri "/v1/certificate_status/test-agent" :request-method :delete})))) (is (false? (fs/exists? csr)))) (let [cert (ca/path-to-cert (:signeddir settings) "revoked-agent")] (is (true? (fs/exists? cert))) (is (= 204 (:status (test-app {:uri "/v1/certificate_status/revoked-agent" :request-method :delete})))) (is (false? (fs/exists? cert)))) (testing "returns a 404 when a non-existent certname is given" (is (= 404 (:status (test-app {:uri "/v1/certificate_status/doesnotexist" :request-method :delete})))))))) (testing "a signing request w/ a 'application/json' content-type succeeds" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) signed-cert-path (ca/path-to-cert (:signeddir settings) "test-agent")] (is (false? (fs/exists? signed-cert-path))) (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :headers {"content-type" "application/json"} :body (body-stream "{\"desired_state\":\"signed\"}")})] (is (true? (fs/exists? signed-cert-path))) (is (= 204 (:status response)))))) (testing "a signing request w/ a 'application/json' content-type and charset succeeds" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) signed-cert-path (ca/path-to-cert (:signeddir settings) "test-agent")] (is (false? (fs/exists? signed-cert-path))) (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :headers {"content-type" "application/json; charset=UTF-8"} :body (body-stream "{\"desired_state\":\"signed\"}")})] (is (true? (fs/exists? signed-cert-path))) (is (= 204 (:status response)))))) (testing "a signing request w/ a 'text/pson' content-type succeeds" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) signed-cert-path (ca/path-to-cert (:signeddir settings) "test-agent")] (is (false? (fs/exists? signed-cert-path))) (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :headers {"content-type" "text/pson"} :body (body-stream "{\"desired_state\":\"signed\"}")})] (is (true? (fs/exists? signed-cert-path))) (is (= 204 (:status response)))))) (testing "a signing request w/ a 'text/pson' content-type and charset succeeds" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) signed-cert-path (ca/path-to-cert (:signeddir settings) "test-agent")] (is (false? (fs/exists? signed-cert-path))) (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :headers {"content-type" "text/pson; charset=UTF-8"} :body (body-stream "{\"desired_state\":\"signed\"}")})] (is (true? (fs/exists? signed-cert-path))) (is (= 204 (:status response)))))) (testing "a signing request w/ a 'pson' content-type succeeds" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) signed-cert-path (ca/path-to-cert (:signeddir settings) "test-agent")] (is (false? (fs/exists? signed-cert-path))) (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :headers {"content-type" "pson"} :body (body-stream "{\"desired_state\":\"signed\"}")})] (is (true? (fs/exists? signed-cert-path))) (is (= 204 (:status response)))))) (testing "a signing request w/ a 'pson' content-type and charset succeeds" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) signed-cert-path (ca/path-to-cert (:signeddir settings) "test-agent")] (is (false? (fs/exists? signed-cert-path))) (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :headers {"content-type" "pson; charset=UTF-8"} :body (body-stream "{\"desired_state\":\"signed\"}")})] (is (true? (fs/exists? signed-cert-path))) (is (= 204 (:status response)))))) (testing "a signing request w/ a bogus content-type header results in a HTTP 415" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :headers {"content-type" "bogus"} :body (body-stream "{\"desired_state\":\"signed\"}")})] (is (= 415 (:status response)) (ks/pprint-to-string response)) (is (= (:body response) "Unsupported media type."))))) (deftest cert-status-invalid-csrs (testing "Asking /certificate_status to sign invalid CSRs" (let [settings (assoc (testutils/ca-settings cadir) :csrdir (str test-resources-dir "/alternate-csrdir")) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert))] (testing "one example - a CSR with DNS alt-names" (let [request {:uri "/v1/certificate_status/hostwithaltnames" :request-method :put :body (body-stream "{\"desired_state\":\"signed\"}")} response (test-app request)] (is (= 409 (:status response)) (ks/pprint-to-string response)) (is (= "text/plain; charset=UTF-8" (get-in response [:headers "Content-Type"])) "Unexpected content type for response") (is (re-find #"hostwithaltnames.*disallowed" (:body response))))) (testing "another example - a CSR with an invalid extension" (let [request {:uri "/v1/certificate_status/meow" :request-method :put :body (body-stream "{\"desired_state\":\"signed\"}")} response (test-app request)] (is (= 409 (:status response)) (ks/pprint-to-string response)) (is (= "text/plain; charset=UTF-8" (get-in response [:headers "Content-Type"])) "Unexpected content type for response") (is (= (:body response) "Found extensions that are not permitted: 1.9.9.9.9.9.9"))))))) (deftest cert-status-duplicate-certs (testing "signing a certificate doesn't depend on $allow-duplicate-certs" (doseq [bool [false true]] (testing bool (let [settings (assoc (testutils/ca-sandbox! cadir) :allow-duplicate-certs bool) test-app (-> (build-ring-handler settings "1.2.3.4") (wrap-with-ssl-client-cert)) signed-path (ca/path-to-cert (:signeddir settings) "test-agent")] (is (false? (fs/exists? signed-path))) (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :put :body (body-stream "{\"desired_state\":\"signed\"}")})] (is (true? (fs/exists? signed-path))) (is (= 204 (:status response)) (ks/pprint-to-string response)))))))) (deftest cert-status-access-control (testing "a request with no certificate is rejected with 403 Forbidden" (let [test-app (build-ring-handler (testutils/ca-settings cadir) "1.2.3.4")] (doseq [endpoint ["certificate_status" "certificate_statuses"]] (testing endpoint (let [response (test-app {:uri (str "/v1/" endpoint "/test-agent") :request-method :get})] (is (= 403 (:status response))) (is (= "Forbidden." (:body response)))))))) (testing "a request with a certificate not on the whitelist is rejected" (let [settings (assoc (testutils/ca-settings cadir) :access-control {:certificate-status {:client-whitelist ["not-localhost"]}}) test-app (build-ring-handler settings "1.2.3.4")] (doseq [endpoint ["certificate_status" "certificate_statuses"]] (testing endpoint (let [response (test-app {:uri (str "/v1/" endpoint "/test-agent") :request-method :get :ssl-client-cert localhost-cert})] (is (= 403 (:status response))) (is (= "Forbidden." (:body response)))))))) (testing "a request with a certificate that is on the whitelist is allowed" (doseq [whitelist [["localhost"] ["foo!" "localhost"]]] (testing "certificate_status" (let [settings (assoc (testutils/ca-settings cadir) :access-control {:certificate-status {:client-whitelist whitelist}}) test-app (build-ring-handler settings "1.2.3.4") response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :get :ssl-client-cert localhost-cert})] (is (= 200 (:status response))) (is (= test-agent-status (json/parse-string (:body response) true))))) (testing "certificate_statuses" (let [settings (assoc (testutils/ca-settings cadir) :access-control {:certificate-status {:client-whitelist whitelist}}) test-app (build-ring-handler settings "1.2.3.4") response (test-app {:uri "/v1/certificate_statuses/all" :request-method :get :ssl-client-cert localhost-cert})] (is (= 200 (:status response))) (is (= #{test-agent-status revoked-agent-status test-cert-status localhost-status} (set (json/parse-string (:body response) true)))))))) (testing "access control can be disabled" (let [settings (assoc (testutils/ca-settings cadir) :access-control {:certificate-status {:authorization-required false :client-whitelist []}}) test-app (build-ring-handler settings "1.2.3.4")] (testing "certificate_status" (let [response (test-app {:uri "/v1/certificate_status/test-agent" :request-method :get})] (is (= 200 (:status response))) (is (= test-agent-status (json/parse-string (:body response) true))))) (testing "certificate_statuses" (let [response (test-app {:uri "/v1/certificate_statuses/all" :request-method :get})] (is (= 200 (:status response))) (is (= #{test-agent-status revoked-agent-status test-cert-status localhost-status} (set (json/parse-string (:body response) true))))))))) (deftest cert-clean (testing "Cleaning one existing cert" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) cert-path (ca/path-to-cert (:signeddir settings) "localhost") cert (utils/pem->cert cert-path) response (test-app {:uri "/v1/clean" :request-method :put :body (body-stream "{\"certnames\":[\"localhost\"],\"async\":false}")})] (is (= 200 (:status response))) (is (true? (utils/revoked? (utils/pem->crl (:cacrl settings)) cert))) (is (false? (fs/exists? cert-path))))) (testing "Cleaning multiple existing certs" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) cert-path1 (ca/path-to-cert (:signeddir settings) "localhost") cert1 (utils/pem->cert cert-path1) cert-path2 (ca/path-to-cert (:signeddir settings) "test_cert") cert2 (utils/pem->cert cert-path2) response (test-app {:uri "/v1/clean" :request-method :put :body (body-stream "{\"certnames\":[\"localhost\",\"test_cert\"],\"async\":false}")})] (is (= 200 (:status response))) (is (true? (utils/revoked? (utils/pem->crl (:cacrl settings)) cert1))) (is (true? (utils/revoked? (utils/pem->crl (:cacrl settings)) cert2))) (is (false? (fs/exists? cert-path1))) (is (false? (fs/exists? cert-path2))))) (testing "Cleaning a missing cert" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) cert-path (ca/path-to-cert (:signeddir settings) "localhost") cert (utils/pem->cert cert-path) response (test-app {:uri "/v1/clean" :request-method :put :body (body-stream "{\"certnames\":[\"missing\",\"localhost\"],\"async\":false}")})] (is (= 200 (:status response))) (is (= "The following certs do not exist and cannot be revoked: [\"missing\"]" (:body response))) (is (true? (utils/revoked? (utils/pem->crl (:cacrl settings)) cert))) (is (false? (fs/exists? cert-path))))) (testing "Cleaning a revoked cert succeeds" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) cert-path (ca/path-to-cert (:signeddir settings) "revoked-agent") cert (utils/pem->cert cert-path) response (test-app {:uri "/v1/clean" :request-method :put :body (body-stream "{\"certnames\":[\"revoked-agent\"],\"async\":false}")})] (is (= 200 (:status response))) (is (= "Successfully cleaned all certs." (:body response))) (is (true? (utils/revoked? (utils/pem->crl (:cacrl settings)) cert))) (is (false? (fs/exists? cert-path))))) (testing "Malformed request body" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) response (test-app {:uri "/v1/clean" :request-method :put :body (body-stream "{\"certnames\":[\"bad-request\":true}")})] (is (= 400 (:status response))) (is (= "Request body is not JSON." (:body response))))) (testing "Missing certnames" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) response (test-app {:uri "/v1/clean" :request-method :put :body (body-stream "{\"async\":false}")})] (is (= 400 (:status response))) (is (re-matches #"Missing.*certnames.*" (:body response))))) (testing "Requesting async mode fails" (let [settings (testutils/ca-sandbox! cadir) test-app (-> (build-ring-handler settings "42.42.42") (wrap-with-ssl-client-cert)) response (test-app {:uri "/v1/clean" :request-method :put :body (body-stream "{\"certnames\":[\"revoked-agent\"],\"async\":true}")})] (is (= 400 (:status response))) (is (= "Async mode is not currently supported." (:body response)))))) certificate_authority_disabled_test.clj000066400000000000000000000035201470345337400353040ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/ca(ns puppetlabs.services.ca.certificate-authority-disabled-test (:require [clojure.test :refer [deftest is testing]] [me.raynes.fs :as fs] [puppetlabs.services.ca.certificate-authority-disabled-service :as disabled] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-testutils] [puppetlabs.trapperkeeper.services.authorization.authorization-service :as tk-auth] [puppetlabs.services.jruby.jruby-puppet-service :as jruby] [puppetlabs.kitchensink.core :as ks])) (deftest ca-disabled-files-test (testing "Ensure no certificates are generated when CA disabled service is enabled." (logutils/with-test-logging (let [puppet-conf-dir (str (ks/temp-dir)) config (-> (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances 1})) (assoc-in [:jruby-puppet :server-conf-dir] puppet-conf-dir) (assoc :puppet {"vardir" (str puppet-conf-dir "/var")}))] (tk-testutils/with-app-with-config app (jruby-testutils/add-mock-jruby-pool-manager-service (conj jruby-testutils/jruby-service-and-dependencies disabled/certificate-authority-disabled-service tk-auth/authorization-service) config) config (let [jruby-service (tk-app/get-service app :JRubyPuppetService)] (jruby/with-jruby-puppet jruby-puppet jruby-service :ca-disabled-files-test (is (not (fs/exists? (fs/file puppet-conf-dir "ssl"))))))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/config/000077500000000000000000000000001470345337400262735ustar00rootroot00000000000000puppet_server_config_core_test.clj000066400000000000000000000137161470345337400352150ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/config(ns puppetlabs.services.config.puppet-server-config-core-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.services.config.puppet-server-config-core :refer [Config get-puppet-config* get-puppet-config-value init-webserver! puppet-config-keys]] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.puppetserver.testutils :as testutils] [schema.core :as schema] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-bootstrap] [me.raynes.fs :as fs] [puppetlabs.kitchensink.core :as ks])) (use-fixtures :once (testutils/with-puppet-conf "./dev-resources/puppetlabs/services/config/puppet_server_config_core_test/puppet.conf")) (deftest ^:integration test-puppet-config-values (let [jruby-config (-> (jruby-testutils/jruby-puppet-config) (update :server-conf-dir #(str (fs/normalized %))) (update :server-code-dir #(str (fs/normalized %))))] (tk-bootstrap/with-app-with-config app jruby-testutils/jruby-service-and-dependencies (jruby-testutils/jruby-puppet-tk-config jruby-config) (let [jruby-service (tk-app/get-service app :JRubyPuppetService) pool-instance (jruby-testutils/borrow-instance jruby-service :test) jruby-puppet (:jruby-puppet pool-instance) mock-config (jruby-testutils/mock-puppet-config-settings jruby-config) actual-config (get-puppet-config* jruby-puppet) setting->keyword (fn [setting] (-> setting (.replace "_" "-") keyword))] (try (testing "usage of get-puppet-config-value" (is (= "ldap" (get-puppet-config-value jruby-puppet :ldapserver))) (is (= 8140 (get-puppet-config-value jruby-puppet :masterport))) (is (= false (get-puppet-config-value jruby-puppet :onetime))) (is (= true (get-puppet-config-value jruby-puppet :autoflush))) (is (= nil (get-puppet-config-value jruby-puppet :not-a-valid-setting)))) (testing "get-puppet-config* values match mock config values" (let [mock-config-with-keywordized-keys (ks/mapkeys setting->keyword mock-config)] (is (= mock-config-with-keywordized-keys actual-config)))) (testing (str "all needed config values from puppet are available in the map " "returned by `get-puppet-config`") (is (map? actual-config)) (doseq [k puppet-config-keys] (is (contains? actual-config k)) (is (not (nil? (get actual-config k)))))) (finally (jruby-testutils/return-instance jruby-service pool-instance :test))))))) (deftest test-schema-validation (testing "validating a data structure with a missing key" (let [config-with-missing-key (dissoc (zipmap puppet-config-keys (repeat 'anything)) :cacert)] (is (not (nil? (schema/check Config config-with-missing-key)))))) (testing "validating a map with a nil value" (let [config-with-nil-value (zipmap puppet-config-keys (repeat nil))] (is (not (nil? (schema/check Config config-with-nil-value))))))) (deftest test-init-webserver! (let [settings-passed (atom nil) override-fn (fn [settings] (reset! settings-passed settings)) puppet-config {:hostcert "thehostcert" :hostprivkey "thehostprivkey" :cacrl "thecacrl" :hostcrl "thehostcrl" :localcacert "thelocalcacert"} init-webserver-fn (fn [webserver-settings] (reset! settings-passed nil) (init-webserver! override-fn webserver-settings puppet-config) @settings-passed) webserver-ssl-config {:ssl-cert "thehostcert" :ssl-key "thehostprivkey" :ssl-ca-cert "thelocalcacert" :ssl-crl-path "thehostcrl"}] (testing "no call made to override default webserver settings if full ssl cert configuration already in webserver settings" (is (nil? (init-webserver-fn webserver-ssl-config)) "Override function unexpectedly called with non-nil args")) (testing "no call made to override default webserver settings if at least one overridable setting already in webserver settings" (doseq [[setting-key setting-value] webserver-ssl-config] (let [map-with-one-overridable-setting {setting-key setting-value}] (is (nil? (init-webserver-fn map-with-one-overridable-setting)) (str "Override function unexpectedly called with non-nil args " "for " map-with-one-overridable-setting))))) (testing "expected settings passed to override function when no overridable ones already exist in webserver settings" (is (= webserver-ssl-config (init-webserver-fn {})) "Unexpected settings passed into the override function")) (testing "expected settings passed to override function when no overridable ones already exist in webserver settings" (is (= webserver-ssl-config (init-webserver-fn {:x-non-overridable true})) "Unexpected settings passed into the override function")))) puppet_server_config_service_test.clj000066400000000000000000000212471470345337400357230ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/config(ns puppetlabs.services.config.puppet-server-config-service-test (:require [clojure.test :refer [deftest is testing]] [puppetlabs.services.protocols.puppet-server-config :refer [get-config get-in-config]] [puppetlabs.services.config.puppet-server-config-service :refer [puppet-server-config-service]] [puppetlabs.services.config.puppet-server-config-core :as core] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-testutils] [puppetlabs.puppetserver.certificate-authority :as ca] [puppetlabs.trapperkeeper.testutils.logging :refer [with-test-logging logged?]] [clj-semver.core :as semver] [puppetlabs.trapperkeeper.core :as tk] [puppetlabs.trapperkeeper.internal :as tk-internal] [puppetlabs.kitchensink.testutils :as ks-testutils])) (def service-and-deps (conj jruby-testutils/jruby-service-and-dependencies puppet-server-config-service)) (defn service-and-deps-with-mock-jruby [config] (jruby-testutils/add-mock-jruby-pool-manager-service service-and-deps config)) (def test-resources-dir "./dev-resources/puppetlabs/services/config/puppet_server_config_service_test") (def required-config (-> (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances 1})) (assoc :webserver {:port 8081}) (assoc-in [:jruby-puppet :server-conf-dir] (str test-resources-dir "/master/conf")))) (deftest config-service-functions (tk-testutils/with-app-with-config app service-and-deps (-> required-config (assoc :my-config {:foo "bar"})) (testing "Basic puppetserver config service function usage" (let [service (tk-app/get-service app :PuppetServerConfigService) service-config (get-config service)] (is (= (-> (:jruby-puppet service-config) (dissoc :server-conf-dir) (dissoc :profiler-output-file)) (-> (:jruby-puppet (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances 1}))) (dissoc :server-conf-dir) (dissoc :profiler-output-file)))) (is (= (:webserver service-config) {:port 8081})) (is (= (:my-config service-config) {:foo "bar"})) (is (= (set (keys (:puppetserver service-config))) (conj core/puppet-config-keys :puppet-version)) (str "config not as expected: " service-config)) (testing "The config service has puppet's version available." (is (semver/valid-format? (get-in-config service [:puppetserver :puppet-version])))) (testing "`get-in-config` functions" (testing "get a value from TK's config" (is (= "bar" (get-in-config service [:my-config :foo])))) (testing "get a value from JRuby's config" (is (= "localhost" (get-in-config service [:puppetserver :certname]))))) (testing "Default values passed to `get-in-config` are handled correctly" (is (= "default" (get-in-config service [:bogus] "default"))) (testing "get a value from TK's config (w/ default specified)" (is (= "bar" (get-in-config service [:my-config :foo] "default value, should not be returned")))) (testing "get a value from JRuby's config (w/ default specified" (is (= "localhost" (get-in-config service [:puppetserver :certname] "default value, should not be returned"))))))))) (deftest config-key-conflicts (testing "Providing config values that should be read from Puppet results in an error that mentions all offending config keys." (with-test-logging (ks-testutils/with-no-jvm-shutdown-hooks (let [config (assoc required-config :cacrl "bogus" :cacert "meow") app (tk/boot-services-with-config (service-and-deps-with-mock-jruby config) config)] (is (thrown-with-msg? Exception #".*configuration.*conflict.*:cacert, :cacrl" (tk-internal/throw-app-error-if-exists! app))) (tk-app/stop app)))))) (deftest certificate-authority-override (tk-testutils/with-app-with-config app service-and-deps (-> required-config (assoc :my-config {:foo "bar"})) (testing (str "certificate-authority settings work") (with-test-logging (ks-testutils/with-no-jvm-shutdown-hooks (let [config (-> (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances 2 :borrow-timeout 12})) (assoc :webserver {:port 8081 :shutdown-timeout-seconds 1})) service (tk-app/get-service app :PuppetServerConfigService) service-config (get-config service) merged-config (merge service-config {:certificate-authority {:allow-auto-renewal true :auto-renewal-cert-ttl "50d" :ca-ttl "50d"}}) settings (ca/config->ca-settings merged-config) app (tk/boot-services-with-config (service-and-deps-with-mock-jruby config) config)] (is (= true (:allow-auto-renewal settings))) (is (= 4320000 (:auto-renewal-cert-ttl settings))) (is (= 4320000 (:ca-ttl settings))) (is (logged? #"Detected ca-ttl setting in CA config which will take precedence over puppet.conf setting")) (tk-app/stop app))))))) (deftest certificate-authority-defaults (tk-testutils/with-app-with-config app service-and-deps (-> required-config (assoc :my-config {:foo "bar"})) (testing (str "certificate-authority settings work") (with-test-logging (ks-testutils/with-no-jvm-shutdown-hooks (let [config (-> (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances 2 :borrow-timeout 12})) (assoc :webserver {:port 8081 :shutdown-timeout-seconds 1})) service (tk-app/get-service app :PuppetServerConfigService) service-config (get-config service) merged-config (merge service-config {:certificate-authority {}}) settings (ca/config->ca-settings merged-config) app (tk/boot-services-with-config (service-and-deps-with-mock-jruby config) config)] (is (= false (:allow-auto-renewal settings))) (is (= 7776000 (:auto-renewal-cert-ttl settings))) (tk-app/stop app))))))) (deftest multi-webserver-setting-override (let [webserver-config {:ssl-cert "thehostcert" :ssl-key "thehostprivkey" :ssl-ca-cert "thelocalcacert" :ssl-crl-path "thecacrl" :port 8081 :default-server true}] (testing "webserver settings not overridden when mult-webserver config is provided and full ssl cert configuration is available" (with-test-logging (let [config (assoc required-config :webserver {:puppet-server webserver-config})] (tk-testutils/with-app-with-config app (service-and-deps-with-mock-jruby config) config (is (logged? #"Not overriding webserver settings with values from core Puppet")))))) (testing "webserver settings not overridden when single webserver is provided and full ssl cert configuration is available" (let [config (assoc required-config :webserver webserver-config)] (with-test-logging (tk-testutils/with-app-with-config app (service-and-deps-with-mock-jruby config) config (is (logged? #"Not overriding webserver settings with values from core Puppet")))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/jruby/000077500000000000000000000000001470345337400261615ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/jruby/jruby_puppet_core_test.clj000066400000000000000000000212061470345337400334530ustar00rootroot00000000000000(ns puppetlabs.services.jruby.jruby-puppet-core-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [schema.test :as schema-test] [puppetlabs.kitchensink.core :as ks] [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.trapperkeeper.testutils.logging :as logutils]) (:import (java.io ByteArrayOutputStream PrintStream))) (use-fixtures :once schema-test/validate-schemas) (defmacro capture-out "capture System.out and return it as the value of :out in the return map. The return value of body is available as :return in the return map. This macro is intended to be used for JRuby interop. Please see with-out-str for an idiomatic clojure equivalent. This macro is not thread safe." [& body] `(let [return-map# (atom {}) system-output# (System/out) captured-output# (new ByteArrayOutputStream) capturing-print-stream# (new PrintStream captured-output#)] (try (System/setOut capturing-print-stream#) (swap! return-map# assoc :return (do ~@body)) (finally (.flush capturing-print-stream#) (swap! return-map# assoc :out (.toString captured-output#)) (System/setOut system-output#))) @return-map#)) (deftest default-num-cpus-test (testing "1 jruby instance for a 1 or 2-core box" (is (= 1 (jruby-core/default-pool-size 1))) (is (= 1 (jruby-core/default-pool-size 2)))) (testing "2 jruby instances for a 3-core box" (is (= 2 (jruby-core/default-pool-size 3)))) (testing "3 jruby instances for a 4-core box" (is (= 3 (jruby-core/default-pool-size 4)))) (testing "4 jruby instances for anything above 5 cores" (is (= 4 (jruby-core/default-pool-size 5))) (is (= 4 (jruby-core/default-pool-size 8))) (is (= 4 (jruby-core/default-pool-size 16))) (is (= 4 (jruby-core/default-pool-size 32))) (is (= 4 (jruby-core/default-pool-size 64))))) (deftest initialize-puppet-config-test (testing "http-client values are used if present" (let [http-config {:ssl-protocols ["some-protocol"] :cipher-suites ["some-suite"] :connect-timeout-milliseconds 31415 :idle-timeout-milliseconds 42 :metrics-enabled false} initialized-config (jruby-puppet-core/initialize-puppet-config http-config {} false)] (is (= ["some-suite"] (:http-client-cipher-suites initialized-config))) (is (= ["some-protocol"] (:http-client-ssl-protocols initialized-config))) (is (= 42 (:http-client-idle-timeout-milliseconds initialized-config))) (is (= 31415 (:http-client-connect-timeout-milliseconds initialized-config))) (is (= false (:http-client-metrics-enabled initialized-config))))) (testing "jruby-puppet values are not overridden by defaults" (let [jruby-puppet-config {:server-run-dir "one" :server-var-dir "two" :server-conf-dir "three" :server-log-dir "four" :server-code-dir "five"} initialized-config (jruby-puppet-core/initialize-puppet-config {} jruby-puppet-config true)] (is (= "one" (:server-run-dir initialized-config))) (is (= "two" (:server-var-dir initialized-config))) (is (= "three" (:server-conf-dir initialized-config))) (is (= "four" (:server-log-dir initialized-config))) (is (= "five" (:server-code-dir initialized-config))) (is (= true (:disable-i18n initialized-config))))) (testing "jruby-puppet values are set to defaults if not provided" (let [initialized-config (jruby-puppet-core/initialize-puppet-config {} {} false)] (is (= "/var/run/puppetlabs/puppetserver" (:server-run-dir initialized-config))) (is (= "/opt/puppetlabs/server/data/puppetserver" (:server-var-dir initialized-config))) (is (= "/etc/puppetlabs/puppet" (:server-conf-dir initialized-config))) (is (= "/var/log/puppetlabs/puppetserver" (:server-log-dir initialized-config))) (is (= "/etc/puppetlabs/code" (:server-code-dir initialized-config))) (is (= false (:disable-i18n initialized-config))) (is (= true (:http-client-metrics-enabled initialized-config))))) (testing "jruby-puppet server-* prefer master-* variants to default values" (let [initialized-config (jruby-puppet-core/initialize-puppet-config {} {:master-conf-dir "/etc/puppetlabs/puppetserver" :master-code-dir "/etc/puppetlabs/puppetserver/code" :master-log-dir "/log/foo"} false)] (is (= "/var/run/puppetlabs/puppetserver" (:server-run-dir initialized-config))) (is (= "/opt/puppetlabs/server/data/puppetserver" (:server-var-dir initialized-config))) (is (= "/etc/puppetlabs/puppetserver" (:server-conf-dir initialized-config))) (is (= "/log/foo" (:server-log-dir initialized-config))) (is (= "/etc/puppetlabs/puppetserver/code" (:server-code-dir initialized-config))))) (testing "still provides proper values at master-* variants" (let [initialized-config (jruby-puppet-core/initialize-puppet-config {} {:master-conf-dir "/my/master/conf" :server-code-dir "/my/server/code"} false)] (is (= "/my/master/conf" (:master-conf-dir initialized-config))) (is (= "/my/master/conf" (:server-conf-dir initialized-config))) (is (= "/my/server/code" (:server-code-dir initialized-config))) (is (= "/my/server/code" (:master-code-dir initialized-config))) (is (= "/var/run/puppetlabs/puppetserver" (:server-run-dir initialized-config))) (is (= "/var/run/puppetlabs/puppetserver" (:master-run-dir initialized-config)))))) (deftest create-jruby-config-test (testing "provided values are not overriden" (let [jruby-puppet-config (jruby-puppet-core/initialize-puppet-config {} {} false) unitialized-jruby-config {:gem-home "/foo" :gem-path ["/foo" "/bar"] :compile-mode :jit :borrow-timeout 1234 :max-active-instances 4321 :max-borrows-per-instance 31415} shutdown-fn (fn [] 42) initialized-jruby-config (logutils/with-test-logging (jruby-puppet-core/create-jruby-config jruby-puppet-config unitialized-jruby-config shutdown-fn nil nil))] (testing "lifecycle functions are not overridden" (is (= 42 ((get-in initialized-jruby-config [:lifecycle :shutdown-on-error]))))) (testing "jruby-config values are not overridden if provided" (is (= "/foo" (:gem-home initialized-jruby-config))) (is (= "/foo:/bar" (:gem-path initialized-jruby-config))) (is (= :jit (:compile-mode initialized-jruby-config))) (is (= 1234 (:borrow-timeout initialized-jruby-config))) (is (= 4321 (:max-active-instances initialized-jruby-config))) (is (= 31415 (:max-borrows-per-instance initialized-jruby-config)))))) (testing "defaults are used if no values provided" (let [jruby-puppet-config (jruby-puppet-core/initialize-puppet-config {} {} false) unitialized-jruby-config {:gem-home "/foo"} shutdown-fn (fn [] 42) initialized-jruby-config (jruby-puppet-core/create-jruby-config jruby-puppet-config unitialized-jruby-config shutdown-fn nil nil)] (testing "jruby-config default values are used if not provided" (is (= :jit (:compile-mode initialized-jruby-config))) (is (= jruby-core/default-borrow-timeout (:borrow-timeout initialized-jruby-config))) (is (= (jruby-core/default-pool-size (ks/num-cpus)) (:max-active-instances initialized-jruby-config))) (is (= 0 (:max-borrows-per-instance initialized-jruby-config)))) (testing "gem-path defaults to gem-home plus the vendored gems dir if not provided" (is (= "/foo:/opt/puppetlabs/server/data/puppetserver/vendored-jruby-gems" (:gem-path initialized-jruby-config))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/jruby/jruby_puppet_service_test.clj000066400000000000000000000266201470345337400341700ustar00rootroot00000000000000(ns puppetlabs.services.jruby.jruby-puppet-service-test (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.trapperkeeper.app :as app] [puppetlabs.trapperkeeper.testutils.bootstrap :as bootstrap] [schema.test :as schema-test])) (use-fixtures :once schema-test/validate-schemas) (defn jruby-service-test-config [pool-size] (jruby-testutils/jruby-puppet-tk-config (jruby-testutils/jruby-puppet-config {:max-active-instances pool-size}))) (deftest environment-class-info-tags (testing "environment-class-info-tags cache has proper data" ;; This test uses a mock JRubyPoolManagerService. Where these tests are ;; largely about validating the content of the environment cache, whose ;; implementation lives in Clojure, having "real" JRuby instances running ;; in the application stack does not seem essential for these tests. ;; ;; There are related tests in other namespaces which do use real JRubyPuppet ;; instances: ;; ;; * puppetlabs.services.jruby.class-info-test - Makes direct calls on a ;; "real" JRubyPuppet to validate that the environment class content ;; matches the manifest content on disk. ;; ;; * puppetlabs.services.master.environment-classes-int-test - Stands up ;; a full application stack and makes calls to the "environment_classes" ;; HTTP endpoint which exercise both the Clojure-level environment class ;; cache and "real" JRubyPuppet instances for doing class info parsing. (let [config (jruby-service-test-config 1)] (bootstrap/with-app-with-config app (jruby-testutils/jruby-service-and-dependencies-with-mocking config) config (let [service (app/get-service app :JRubyPuppetService) production-cache-id-before-first-update (jruby-protocol/get-environment-class-info-cache-generation-id! service "production")] (testing "when environment not previously loaded to cache" (is (nil? (jruby-protocol/get-environment-class-info-tag service "production"))) (is (= 1 production-cache-id-before-first-update))) (testing "when environment info first set to cache" (jruby-protocol/set-environment-class-info-tag! service "production" "1234prod" production-cache-id-before-first-update) (is (= "1234prod" (jruby-protocol/get-environment-class-info-tag service "production"))) (is (nil? (jruby-protocol/get-environment-class-info-tag service "test"))) (jruby-protocol/set-environment-class-info-tag! service "test" "1234test" (jruby-protocol/get-environment-class-info-cache-generation-id! service "test")) (is (= "1234prod" (jruby-protocol/get-environment-class-info-tag service "production"))) (is (= "1234test" (jruby-protocol/get-environment-class-info-tag service "test")))) (let [production-cache-id-after-first-update (jruby-protocol/get-environment-class-info-cache-generation-id! service "production") test-cache-id-after-first-update (jruby-protocol/get-environment-class-info-cache-generation-id! service "test")] (testing "when environment info reset in the cache" (is (= 2 production-cache-id-after-first-update)) (is (= 2 test-cache-id-after-first-update)) (jruby-protocol/set-environment-class-info-tag! service "production" "5678prod" production-cache-id-after-first-update) (is (= "5678prod" (jruby-protocol/get-environment-class-info-tag service "production"))) (is (= "1234test" (jruby-protocol/get-environment-class-info-tag service "test"))) (is (= test-cache-id-after-first-update (jruby-protocol/get-environment-class-info-cache-generation-id! service "test"))) (testing "and environment expired between get and corresponding set" (let [production-cache-id-before-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "production") _ (jruby-protocol/mark-environment-expired! service "production") production-cache-id-after-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "production")] (is (not= production-cache-id-after-first-update production-cache-id-before-marked-expired)) (is (not= production-cache-id-before-marked-expired production-cache-id-after-marked-expired)) (is (= nil (jruby-protocol/get-environment-class-info-tag service "production")) (str "Tag was unexpectedly non-nil, however, it should have " "been because of the prior call to " "`mark-environment-expired`")) (jruby-protocol/set-environment-class-info-tag! service "production" "89abprod" production-cache-id-before-marked-expired) (is (= nil (jruby-protocol/get-environment-class-info-tag service "production")) (str "Tag should not have been changed by the prior set " "since the environment was marked expired after the " "cache was read for " "`production-cache-id-before-marked-expired`")) (is (= production-cache-id-after-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "production")) (str "Cache id should not have been changed by the prior " "set since the environment was marked expired after " "cache was read for " "`production-cache-id-before-marked-expired`"))))) (testing "when an individual environment is marked expired" (let [production-cache-id-before-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "production")] (jruby-protocol/mark-environment-expired! service "production") (is (nil? (jruby-protocol/get-environment-class-info-tag service "production"))) (is (not= production-cache-id-before-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "production")))) (is (= "1234test" (jruby-protocol/get-environment-class-info-tag service "test"))) (is (= test-cache-id-after-first-update (jruby-protocol/get-environment-class-info-cache-generation-id! service "test")))) (testing "when all environments are marked expired" (let [production-cache-id-before-set-tag (jruby-protocol/get-environment-class-info-cache-generation-id! service "production")] (jruby-protocol/set-environment-class-info-tag! service "production" "8910prod" production-cache-id-before-set-tag) (is (= "8910prod" (jruby-protocol/get-environment-class-info-tag service "production")))) (let [production-cache-id-before-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "production")] (jruby-protocol/mark-all-environments-expired! service) (is (nil? (jruby-protocol/get-environment-class-info-tag service "production"))) (is (not= production-cache-id-before-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "production"))) (is (nil? (jruby-protocol/get-environment-class-info-tag service "test"))) (is (not= test-cache-id-after-first-update (jruby-protocol/get-environment-class-info-cache-generation-id! service "test"))))) (testing (str "when all environments expired between get and set " "for environment that did not previously exist") (let [staging-cache-id-before-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "staging") _ (jruby-protocol/mark-all-environments-expired! service) staging-cache-id-after-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "staging")] (jruby-protocol/set-environment-class-info-tag! service "staging" "1234staging" staging-cache-id-before-marked-expired) (is (= nil (jruby-protocol/get-environment-class-info-tag service "staging")) (str "Tag should not have been changed by the prior set " "since the environment was marked expired after the " "`staging-cache-id-before-marked-expired` was read")) (is (= staging-cache-id-after-marked-expired (jruby-protocol/get-environment-class-info-cache-generation-id! service "staging")) (str "Cache id should not have been changed by the prior " "set since the environment was marked expired after the " "`staging-cache-id-before-marked-expired` was " "read")))))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/jruby/jruby_puppet_testutils.clj000066400000000000000000000423201470345337400335240ustar00rootroot00000000000000(ns puppetlabs.services.jruby.jruby-puppet-testutils (:require [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.jruby.jruby-puppet-schemas :as jruby-puppet-schemas] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.services :as tk-service] [schema.core :as schema] [puppetlabs.services.jruby-pool-manager.jruby-schemas :as jruby-schemas] [puppetlabs.services.jruby.puppet-environments :as puppet-env] [puppetlabs.services.protocols.pool-manager :as pool-manager-protocol] [puppetlabs.services.jruby-pool-manager.impl.jruby-pool-manager-core :as jruby-pool-manager-core] [puppetlabs.services.jruby-pool-manager.impl.jruby-internal :as jruby-internal] [puppetlabs.trapperkeeper.services.metrics.metrics-service :as metrics] [puppetlabs.services.jruby.jruby-puppet-service :as jruby-puppet] [puppetlabs.services.puppet-profiler.puppet-profiler-service :as profiler] [puppetlabs.trapperkeeper.services.webserver.jetty10-service :as jetty10-service] [puppetlabs.services.jruby-pool-manager.jruby-pool-manager-service :as jruby-pool-manager] [puppetlabs.trapperkeeper.services.scheduler.scheduler-service :as scheduler-service] [puppetlabs.trapperkeeper.services.status.status-service :as status-service] [puppetlabs.trapperkeeper.services.webrouting.webrouting-service :as webrouting-service]) (:import (clojure.lang IFn) (com.puppetlabs.jruby_utils.jruby ScriptingContainer) (puppetlabs.services.jruby_pool_manager.jruby_schemas JRubyInstance) (com.puppetlabs.puppetserver JRubyPuppet JRubyPuppetResponse))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Constants (def ruby-load-path ["./ruby/puppet/lib" "./ruby/facter/lib" "./ruby/hiera/lib"]) (def gem-home (str (System/getProperty "user.home") "/.puppetlabs/opt/server/data/puppetserver/jruby-gems")) (def gem-path (str gem-home ":" (System/getProperty "user.home") "/.puppetlabs/opt/server/data/puppetserver/vendored-jruby-gems")) (def conf-dir "./target/server-conf") (def code-dir "./target/server-code") (def var-dir "./target/server-var") (def run-dir "./target/server-var/run") (def log-dir "./target/server-var/log") (def multithreaded (= "true" (System/getenv "MULTITHREADED"))) (def jruby-service-and-dependencies [jruby-puppet/jruby-puppet-pooled-service profiler/puppet-profiler-service jruby-pool-manager/jruby-pool-manager-service metrics/metrics-service scheduler-service/scheduler-service status-service/status-service jetty10-service/jetty10-service webrouting-service/webrouting-service]) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Schemas (def JRubyPuppetTKConfig "Schema combining JRubyPuppetConfig and JRubyConfig. This represents what would be in a real TK configuration's jruby-puppet section, so we remove some things from the JRubyConfig: - remove :max-borrows-per-instance (keep :max-requests-per-instance) - remove :lifecycle" (-> jruby-puppet-schemas/JRubyPuppetConfig (merge jruby-schemas/JRubyConfig) (dissoc :max-borrows-per-instance :lifecycle))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; JRubyPuppet Test util functions (defn borrow-instance "Borrows an instance from the JRubyPuppet interpreter pool. If there are no interpreters left in the pool then the operation blocks until there is one available. A timeout (integer measured in milliseconds) can be configured which will either return an interpreter if one is available within the timeout length, or will return nil after the timeout expires if no interpreters are available. This timeout defaults to 1200000 milliseconds. `reason` is an identifier (usually a map) describing the reason for borrowing the JRuby instance. It may be used for metrics and logging purposes." [jruby-puppet-service reason] (let [{:keys [pool-context]} (tk-service/service-context jruby-puppet-service) event-callbacks (jruby-core/get-event-callbacks pool-context)] (jruby-core/borrow-from-pool-with-timeout pool-context reason event-callbacks))) (defn return-instance "Returns the JRubyPuppet interpreter back to the pool. `reason` is an identifier (usually a map) describing the reason for borrowing the JRuby instance. It may be used for metrics and logging purposes, so for best results it should be set to the same value as it was set during the `borrow-instance` call." [jruby-puppet-service jruby-instance reason] (let [pool-context (:pool-context (tk-service/service-context jruby-puppet-service)) event-callbacks (jruby-core/get-event-callbacks pool-context)] (jruby-core/return-to-pool pool-context jruby-instance reason event-callbacks))) (schema/defn create-mock-scripting-container :- ScriptingContainer [] (reify ScriptingContainer (terminate [_]))) (schema/defn ^:always-validate create-mock-pool-instance :- JRubyInstance [mock-jruby-instance-creator-fn :- IFn pool :- jruby-schemas/pool-queue-type id :- schema/Int config :- jruby-schemas/JRubyConfig] (let [instance (jruby-schemas/map->JRubyInstance {:id id :internal {:pool pool :max-borrows (:max-borrows-per-instance config) :initial-borrows nil :state (atom {:borrow-count 0})} :scripting-container (create-mock-scripting-container)}) modified-instance (merge instance {:jruby-puppet (mock-jruby-instance-creator-fn) :environment-registry (puppet-env/environment-registry)})] (.register pool modified-instance) modified-instance)) (defn jruby-puppet-tk-config "Create a JRubyPuppet pool config with the given pool config. Suitable for use in bootstrapping trapperkeeper (in other words, returns a representation of the config that matches what would be read directly from the config files on disk, as opposed to a version that has been processed and transformed to comply with the JRubyPuppetConfig schema)." [pool-config] {:product {:name "puppetserver" :update-server-url "http://localhost:11111"} :jruby-puppet pool-config :http-client {} :metrics {:server-id "localhost"} :authorization {:version 1 :rules [{:match-request {:path "/" :type "path"} :allow "*" :sort-order 1 :name "allow all"}]} :webserver {:host "localhost"} :web-router-service {:puppetlabs.trapperkeeper.services.status.status-service/status-service "/status"}}) (schema/defn ^:always-validate jruby-puppet-config :- JRubyPuppetTKConfig "Create a JRubyPuppetConfig for testing. The optional map argument `options` may contain a map, which, if present, will be merged into the final JRubyPuppetConfig map. (This function differs from `jruby-puppet-tk-config` in that it returns a map that complies with the JRubyPuppetConfig schema, which differs slightly from the raw format that would be read from config files on disk.)" ([] (let [combined-configs (merge (jruby-puppet-core/initialize-puppet-config {} {:server-conf-dir conf-dir :server-code-dir code-dir :server-var-dir var-dir :server-run-dir run-dir :server-log-dir log-dir} false) (jruby-core/initialize-config {:ruby-load-path ruby-load-path :gem-home gem-home :gem-path gem-path :multithreaded multithreaded})) max-requests-per-instance (:max-borrows-per-instance combined-configs) updated-config (-> combined-configs (assoc :max-requests-per-instance max-requests-per-instance) (dissoc :max-borrows-per-instance))] (dissoc updated-config :lifecycle))) ([options] (merge (jruby-puppet-config) options))) (defn drain-pool "Drains the JRubyPuppet pool and returns each instance in a vector." [pool-context size] (mapv (fn [_] (jruby-core/borrow-from-pool pool-context :test [])) (range size))) (defn fill-drained-pool "Returns a list of JRubyPuppet instances back to their pool." [pool-context instance-list] (doseq [instance instance-list] (jruby-core/return-to-pool pool-context instance :test []))) (defn reduce-over-jrubies! "Utility function; takes a JRuby pool and size, and a function f from integer to string. For each JRuby instance in the pool, f will be called, passing in an integer offset into the jruby array (0..size), and f is expected to return a string containing a script to run against the jruby instance. Returns a vector containing the results of executing the scripts against the JRuby instances." [pool-context size f] (let [jrubies (drain-pool pool-context size) result (reduce (fn [acc jruby-offset] (let [sc (:scripting-container (nth jrubies jruby-offset)) script (f jruby-offset) result (.runScriptlet sc script)] (conj acc result))) [] (range size))] (fill-drained-pool pool-context jrubies) result)) (defn wait-for-jrubies "Wait for all jrubies to land in the JRubyPuppetService's pool" [app] (let [pool-context (-> app (tk-app/get-service :JRubyPuppetService) tk-service/service-context :pool-context) num-jrubies (-> pool-context jruby-core/get-pool-state :size)] (while (< (count (jruby-core/registered-instances pool-context)) num-jrubies) (Thread/sleep 100)))) (schema/defn ^:always-validate mock-puppet-config-settings :- {schema/Str schema/Any} "Return a map of settings that mock the settings that core Ruby Puppet would return via a call to JRubyPuppet.getSetting()." [jruby-puppet-config :- {:server-conf-dir schema/Str :server-code-dir schema/Str schema/Keyword schema/Any}] (let [certname "localhost" confdir (:server-conf-dir jruby-puppet-config) ssldir (str confdir "/ssl") certdir (str ssldir "/certs") cadir (str confdir "/ca") private-key-dir (str ssldir "/private_keys")] {"allow_duplicate_certs" false "autosign" true "keylength" 2048 "cadir" cadir "cacert" (str cadir "/ca_crt.pem") "ca_name" (str "Puppet CA: " certname) "cacrl" (str cadir "/ca_crl.pem") "cakey" (str cadir "/ca_key.pem") "capub" (str cadir "/ca_pub.pem") "ca_ttl" 157680000 "certdir" certdir "certname" certname "cert_inventory" (str cadir "/inventory.txt") "codedir" (:server-code-dir jruby-puppet-config) "csr_attributes" (str confdir "/csr_attributes.yaml") "csrdir" (str cadir "/requests") "dns_alt_names" "" "hostcert" (str certdir "/" certname ".pem") "hostcrl" (str ssldir "/crl.pem") "hostprivkey" (str private-key-dir "/" certname ".pem") "hostpubkey" (str ssldir "/public_keys/" certname ".pem") "localcacert" (str certdir "/ca.pem") "manage_internal_file_permissions" true "privatekeydir" private-key-dir "requestdir" (str ssldir "/certificate_requests") "serial" (str cadir "/serial") "signeddir" (str cadir "/signed") "ssl_client_header" "HTTP_X_CLIENT_DN" "ssl_client_verify_header" "HTTP_X_CLIENT_VERIFY" "trusted_oid_mapping_file" (str confdir "/custom_trusted_oid_mapping.yaml")})) (schema/defn ^:always-validate create-mock-jruby-puppet :- JRubyPuppet "Create a 'mock' JRubyPuppet instance which returns fixed values for settings and puppet version and a hard-coded HTTP 200 response for any requests it handles." ([config :- {schema/Keyword schema/Any}] (create-mock-jruby-puppet (fn [_] (throw (UnsupportedOperationException. "Mock handleRequest not defined"))) config)) ([handle-request-fn :- IFn config :- {schema/Keyword schema/Any}] (let [puppet-config (merge (mock-puppet-config-settings (:jruby-puppet config)) (:puppet config))] (reify JRubyPuppet (getSetting [_ setting] (let [value (get puppet-config setting :not-found)] (if (= value :not-found) (throw (IllegalArgumentException. (str "Setting not in mock-puppet-config-settings " "requested: " setting ". Add an appropriate value " "to the map to correct this problem."))) value))) (puppetVersion [_] "1.2.3") (handleRequest [_ request] (handle-request-fn request)) (terminate [_]))))) (schema/defn ^:always-validate create-mock-jruby-puppet-fn-with-handle-response-params :- IFn "Return a function which, when invoked, will create a mock JRubyPuppet instance. Supplied arguments - 'status-code', 'response-body', 'response-content-type', and 'puppet-version' are returned in the 'JRubyPuppetResponse' that the JRubyPuppet instance's .handleRequest method returns when invoked. The default value for 'response-content-type', if not supplied, is 'text/plain'. The default value for 'puppet-version', if not supplied, is '1.2.3'." ([status-code :- schema/Int response-body :- schema/Str] (create-mock-jruby-puppet-fn-with-handle-response-params status-code response-body "text/plain")) ([status-code :- schema/Int response-body :- schema/Str response-content-type :- schema/Str] (create-mock-jruby-puppet-fn-with-handle-response-params status-code response-body response-content-type "1.2.3")) ([status-code :- schema/Int response-body :- schema/Str response-content-type :- schema/Str puppet-version :- schema/Str] (partial create-mock-jruby-puppet (fn [_] (JRubyPuppetResponse. (int status-code) response-body response-content-type puppet-version))))) (schema/defn ^:always-validate create-mock-pool :- jruby-schemas/PoolContext "Create a 'mock' JRuby pool. The pool is filled with the number 'mock' JRubyPuppet instances specified in the jruby-config. The supplied 'mock-jruby-puppet-fn' is invoked for each instance to be created for the pool and is expected to return an object of type 'JRubyPuppet'." [jruby-config :- jruby-schemas/JRubyConfig mock-jruby-puppet-fn :- IFn] ;; The implementation of this function is based on and very similar to ;; `prime-pool!` in `puppetlabs.services.jruby-pool-manager.impl.jruby-agents` ;; from the jruby-utils library. (let [pool-context (jruby-pool-manager-core/create-pool-context jruby-config) pool (jruby-internal/get-pool pool-context) count (.remainingCapacity pool)] (dotimes [i count] (let [id (inc i)] (create-mock-pool-instance mock-jruby-puppet-fn pool id jruby-config))) pool-context)) (schema/defn ^:always-validate mock-jruby-pool-manager-service :- (schema/protocol tk-service/ServiceDefinition) "Create a 'mock' JRubyPoolManagerService, with a create-pool function which returns a 'mock' JRuby pool when called. The supplied 'mock-jruby-puppet-fn' is invoked for each instance to be created for the pool and is expected to return an object of type 'JRubyPuppet'. The 'config' option is passed back as an argument to 'mock-jruby-puppet-fn', if supplied." ([config :- {schema/Keyword schema/Any}] (mock-jruby-pool-manager-service config create-mock-jruby-puppet)) ([config :- {schema/Keyword schema/Any} mock-jruby-puppet-fn :- IFn] (tk-service/service pool-manager-protocol/PoolManagerService [] (create-pool [_this jruby-config] (create-mock-pool jruby-config (partial mock-jruby-puppet-fn config)))))) (defn add-mock-jruby-pool-manager-service ([services config] (add-mock-jruby-pool-manager-service services config create-mock-jruby-puppet)) ([services config mock-jruby-puppet-fn] (->> services (remove #(= :PoolManagerService (tk-service/service-def-id %))) vec (cons (mock-jruby-pool-manager-service config mock-jruby-puppet-fn))))) (defn jruby-service-and-dependencies-with-mocking [config] (add-mock-jruby-pool-manager-service jruby-service-and-dependencies config)) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/jruby/puppet_environments_test.clj000066400000000000000000000060211470345337400340350ustar00rootroot00000000000000(ns puppetlabs.services.jruby.puppet-environments-test (:require [clojure.test :refer [deftest is testing]] [puppetlabs.services.jruby.puppet-environments :as puppet-env])) (defn contains-environment? [reg env-name] (contains? (-> reg puppet-env/environment-state deref) env-name)) (defn expired? [reg env-name] (-> reg puppet-env/environment-state deref env-name :expired)) (deftest environment-registry-test (testing "environments are not expired by default" (let [reg (puppet-env/environment-registry)] (.registerEnvironment reg "foo") (is (false? (.isExpired reg "foo"))) (is (false? (expired? reg :foo))) (.registerEnvironment reg "bar") (is (false? (.isExpired reg "foo"))) (is (false? (expired? reg :foo))) (is (false? (.isExpired reg "bar"))) (is (false? (expired? reg :bar))))) (testing "mark-all-environments-expired" (let [reg (puppet-env/environment-registry)] (.registerEnvironment reg "foo") (.registerEnvironment reg "bar") (is (false? (expired? reg :foo))) (is (false? (expired? reg :bar))) (puppet-env/mark-all-environments-expired! reg) (is (true? (.isExpired reg "foo"))) (is (true? (expired? reg :foo))) (is (true? (.isExpired reg "bar"))) (is (true? (expired? reg :bar))))) (testing "mark-environment-expired" (let [reg (puppet-env/environment-registry)] (.registerEnvironment reg "foo") (.registerEnvironment reg "bar") (is (false? (expired? reg :foo))) (is (false? (expired? reg :bar))) (puppet-env/mark-environment-expired! reg "foo") (is (true? (.isExpired reg "foo"))) (is (true? (expired? reg :foo))) (is (false? (.isExpired reg "bar"))) (is (false? (expired? reg :bar))) (puppet-env/mark-environment-expired! reg "bar") (is (true? (.isExpired reg "foo"))) (is (true? (expired? reg :foo))) (is (true? (.isExpired reg "bar"))) (is (true? (expired? reg :bar))))) (testing "removing and re-registering an environment clears staleness" (let [reg (puppet-env/environment-registry)] (.registerEnvironment reg "foo") (is (false? (.isExpired reg "foo"))) (is (false? (expired? reg :foo))) (puppet-env/mark-all-environments-expired! reg) (is (true? (.isExpired reg "foo"))) (is (true? (expired? reg :foo))) (is (true? (contains-environment? reg :foo))) (.removeEnvironment reg "foo") (is (false? (contains-environment? reg :foo))) (.registerEnvironment reg "foo") (is (false? (.isExpired reg "foo"))) (is (false? (expired? reg :foo))))) (testing "unregistered environments are expired by default" (let [reg (puppet-env/environment-registry)] (is (false? (contains-environment? reg :foo))) (is (true? (.isExpired reg "foo"))) ; expired? returns nil because it bypasses the ; EnvironmentRegistry.isExpired fn and accesses the underlying data ; directly, which of course not contain :foo (is (nil? (expired? reg :foo)))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/master/000077500000000000000000000000001470345337400263215ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/master/master_core_test.clj000066400000000000000000000664571470345337400323770ustar00rootroot00000000000000(ns puppetlabs.services.master.master-core-test (:require [cheshire.core :as json] [clojure.string :refer [split]] [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.comidi :as comidi] [puppetlabs.kitchensink.core :as ks] [puppetlabs.services.jruby-pool-manager.impl.jruby-pool-manager-core :as jruby-pool-manager-core] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.master.master-core :refer [root-routes wrap-middleware if-none-match-from-request class-info-from-jruby->class-info-for-json valid-static-file-path? validate-memory-requirements! meminfo-content max-heap-size task-file-uri-components all-tasks-response!]] [puppetlabs.services.master.master-service :as master-service] [puppetlabs.services.protocols.jruby-puppet :as jruby] [puppetlabs.trapperkeeper.testutils.logging :as logging] [ring.middleware.params :as ring] [ring.mock.request :as ring-mock] [schema.test :as schema-test]) (:import java.util.HashMap)) (use-fixtures :once schema-test/validate-schemas) (def dummy-jruby-service (reify jruby/JRubyPuppetService)) (defn construct-info-from-task-name "Given a task name in format 'module::task', construct a data structure that matches what the all-tasks function on the JRuby service would return. Also accepts name of 'module', for the special-cased init tasks." [task-name] (let [[module _] (split task-name #"::")] {:module {:name module} :name task-name :metadata {:private false :description "test description"}})) (defn build-ring-handler [request-handler puppet-version jruby-service] (-> (root-routes request-handler ring/wrap-params jruby-service identity (fn [___] (throw (IllegalStateException. "Versioned code not supported."))) (constantly nil) true nil "test-certname") (comidi/routes->handler) (wrap-middleware identity puppet-version))) (defn app-request ([app path] (app-request app :get path)) ([app method path] (app (ring-mock/request method path)))) (deftest test-master-routes (let [handler (fn ([req] {:request req})) app (build-ring-handler handler "1.2.3" dummy-jruby-service) request (partial app-request app)] (is (= 200 (:status (request "/v3/environments")))) (is (= 200 (:status (request "/v3/catalog/bar?environment=environment1234")))) (let [response (app (-> {:request-method :post :uri "/v3/catalog/bar" :content-type "application/x-www-form-urlencoded"} (ring-mock/body "environment=environment1234")))] (is (= "test-certname" (get-in response [:headers "X-Puppet-Compiler-Name"])) (is (= 200 (:status response))))) (is (nil? (request "/foo"))) (is (nil? (request "/foo/bar"))) (doseq [[method paths] {:get ["node" "file_metadata" "file_bucket_file"] :put ["file_bucket_file" "report"] :head ["file_bucket_file"]} path paths] (let [resp (request method (str "/v3/" path "/bar"))] (is (= 200 (:status resp)) (str "Did not get 200 for method: " method ", path: " path)))))) (deftest if-none-match-test (testing "if-none-match returns expected value when" (let [mock-request (ring-mock/request :get "env_classes")] (testing "header present without '--gzip' suffix" (is (= "abc123" (if-none-match-from-request (ring-mock/header mock-request "If-None-Match" "abc123"))))) (testing "header present with '--gzip' suffix (SERVER-1153)" (is (= "abc123" (if-none-match-from-request (ring-mock/header mock-request "If-None-Match" "abc123--gzip"))))) (testing "header present with empty value" (is (empty? (if-none-match-from-request (ring-mock/header mock-request "If-None-Match" ""))))) (testing "header absent" (is (nil? (if-none-match-from-request mock-request))))))) (deftest environment-classes-test (testing "environment_classes query" (with-redefs [jruby-core/borrow-from-pool-with-timeout (fn [_ _ _] {:jruby-puppet (Object.)}) jruby-core/return-to-pool (fn [_ _ _ _] #())] (let [jruby-service (reify jruby/JRubyPuppetService (get-pool-context [_] (jruby-pool-manager-core/create-pool-context (jruby-core/initialize-config {:gem-home "bar" :gem-path "bar:foobar" :ruby-load-path ["foo"]}))) (get-environment-class-info [_ _ env] (when (= env "production") {})) (get-cached-content-version [_ _ _]) (set-cache-info-tag! [_ _ _ _ _])) handler (fn ([req] {:request req})) app (build-ring-handler handler "1.2.3" jruby-service) request (partial app-request app) etag #(-> % (class-info-from-jruby->class-info-for-json "production") json/encode ks/utf8-string->sha256) map-with-classes #(doto (HashMap.) (.put "classes" %))] (testing "returns 200 for environment that exists" (is (= 200 (:status (request "/v3/environment_classes?environment=production"))))) (testing "returns 404 not found when non-existent environment supplied" (is (= 404 (:status (request "/v3/environment_classes?environment=test"))))) (testing "returns 400 bad request when environment not supplied" (logging/with-test-logging (is (= 400 (:status (request "/v3/environment_classes")))))) (testing (str "returns 400 bad request when environment has " "non-alphanumeric characters") (logging/with-test-logging (is (= 400 (:status (request "/v3/environment_classes?environment=~")))))) (testing "calculates etag properly for response payload" (is (= (etag {"/one/file" (map-with-classes [ {"name" "oneclass", "params" [ {"name" "oneparam", "type" "String", "default_literal" "'literal'", "default_source" "literal"}, {"name" "twoparam", "type" "Integer", "default_literal" "3", "default_source" "3"}] }, {"name" "twoclass" "params" []}]), "/two/file" (map-with-classes [])}) (etag {"/one/file" (map-with-classes [ {"name" "oneclass", "params" [ {"default_source" "literal" "type" "String", "name" "oneparam", "default_literal" "'literal'"}, {"name" "twoparam", "type" "Integer", "default_literal" "3", "default_source" "3"}] }, {"name" "twoclass" "params" []}]), "/two/file" (map-with-classes [])})) "hashes unexpectedly not equal for equal maps") (is (= (etag {"/one/file" (map-with-classes [ {"name" "oneclass", "params" [ {"name" "oneparam", "type" "String", "default_literal" "'literal'", "default_source" "literal"}, {"name" "twoparam", "type" "Integer", "default_literal" "3", "default_source" "3"}] }, {"name" "twoclass" "params" []}]), "/two/file" (map-with-classes [])}) (etag {"/one/file" (map-with-classes [ {"name" "oneclass", "params" [ {"default_source" "literal" "type" "String", "name" "oneparam", "default_literal" "'literal'"}, {"type" "Integer", "name" "twoparam", "default_literal" "3" "default_source" "3"}] }, {"params" [] "name" "twoclass"}]), "/two/file" (map-with-classes [])})) (str "hashes unexpectedly not equal for equal maps with out of " "order keys")) (is (not= (etag {"/one/file" (map-with-classes [ {"name" "oneclass", "params" [ {"name" "oneparam", "type" "String", "default_literal" "'literal'", "default_source" "literal"}, {"name" "twoparam", "type" "Integer", "default_literal" "3", "default_source" "3"}] }, {"name" "twoclass" "params" []}]), "/two/file" (map-with-classes [])}) (etag {"/two/file" (map-with-classes [])})) "hashes unexpectedly equal for different payloads")) (testing (str "throws IllegalArgumentException for response " "which contains invalid map key for etagging") (is (thrown-with-msg? IllegalArgumentException #"Object cannot be coerced to a keyword" (etag {"/one/file" (map-with-classes [{["array" "as" "map" "key" "not" "supported"] "bogus"}])})))))))) (deftest valid-static-file-path-test (let [valid-paths ["modules/foo/files/bar.txt" "modules/foo/files/bar" "modules/foo/files/bar/baz.txt" "modules/foo/files/bar/more/path/elements/baz.txt" "modules/foo/files/bar/%2E%2E/baz.txt" "modules/foo/scripts/qux.sh" "modules/foo/tasks/task.sh" "environments/production/files/~/.bash_profile" "dist/foo/files/bar.txt" "site/foo/files/bar.txt"] invalid-paths ["modules/foo/manifests/bar.pp" "modules/foo/files/" "manifests/site.pp" "environments/foo/bar/files" "environments/../manifests/files/site.pp" "environments/files/site.pp" "environments/../modules/foo/lib/puppet/parser/functions/site.rb" "environments/../modules/foo/files/site.pp" "environments/production/modules/foo/files/../../../../../../site.pp" "environments/production/modules/foo/files/bar.txt" "environments/production/modules/foo/files/..conf..d../..bar..txt.." "environments/test/modules/foo/files/bar/baz.txt" "environments/dev/modules/foo/files/path/to/file/something.txt"] check-valid-path (fn [path] {:path path :valid? (valid-static-file-path? path)}) valid-path-results (map check-valid-path valid-paths) invalid-path-results (map check-valid-path invalid-paths) get-validity (fn [{:keys [valid?]}] valid?)] (testing "Only files in 'modules/*/(files | scripts | tasks)/**' are valid" (is (every? get-validity valid-path-results) (ks/pprint-to-string valid-path-results)) (is (every? (complement get-validity) invalid-path-results) (ks/pprint-to-string invalid-path-results))))) (deftest file-bucket-file-content-type-test (testing "The 'Content-Type' header on incoming /file_bucket_file requests is not overwritten, and simply passed through unmodified." (let [handler (fn ([req] {:request req})) app (build-ring-handler handler "1.2.3" dummy-jruby-service) resp (app (-> {:request-method :put :content-type "application/octet-stream" :uri "/v3/file_bucket_file/bar"} (ring-mock/body "foo")))] (is (= "application/octet-stream" (get-in resp [:request :content-type]))) (testing "Even if the client sends something insane, just pass it through and let the puppet code handle it." (let [resp (app (-> {:request-method :put :content-type "something-crazy/for-content-type" :uri "/v3/file_bucket_file/bar"} (ring-mock/body "foo")))] (is (= "something-crazy/for-content-type" (get-in resp [:request :content-type])))))))) (deftest code-id-injection-test (testing "code_id is not added to non-catalog requests" (let [handler (fn ([req] {:request req})) app (build-ring-handler handler "1.2.3" dummy-jruby-service) request (partial app-request app)] (doseq [[method paths] {:get ["node" "file_content" "file_metadatas" "file_metadata" "file_bucket_file" "status"] :put ["file_bucket_file" "report"] :head ["file_bucket_file"]} path paths] (let [resp (request method (str "/v3/" path "/bar?environment=environment1234"))] (is (nil? (get-in resp [:request :params "code_id"]))) (is (nil? (get-in resp [:request :include-code-id?])))))))) (defn assert-failure-msg "Assert the message thrown by validate-memory-requirements! matches re" [re behavior-msg] (testing (str "the error " behavior-msg) (is (thrown-with-msg? Error re (validate-memory-requirements!))))) (deftest validate-memory-requirements!-test (testing "when ram is more than 2 TB" (with-redefs [meminfo-content #(str "MemTotal: 2319453408 kB") max-heap-size 2097152] (is (nil? (validate-memory-requirements!)) "fails to parse large ram info"))) (testing "when /proc/meminfo does not exist" (with-redefs [meminfo-content (constantly nil) max-heap-size 2097152] (is (nil? (validate-memory-requirements!)) "nil when /proc/meminfo does not exist"))) (testing "when ram is > 1.1 times JVM max heap" (with-redefs [meminfo-content #(str "MemTotal: 3878212 kB\n") max-heap-size 2097152] (is (nil? (validate-memory-requirements!)) "nil when ram is > 1.1 times JVM max heap"))) (testing "when ram is < 1.1 times JVM max heap" (with-redefs [meminfo-content #(str "MemTotal: 1878212 kB\n") max-heap-size 2097152] (assert-failure-msg #"RAM (.*) JVM heap" "mentions RAM and JVM Heap size") (assert-failure-msg #"JAVA_ARGS" "suggests the user configure JAVA_ARGS") (assert-failure-msg #"computed as 1.1 *" "informs the user how required memory is calculated") (assert-failure-msg #"/etc/sysconfig/puppetserver" "points the user to the EL config location") (assert-failure-msg #"/etc/default/puppetserver" "points the user to the debian config location")))) (deftest task-file-uri-components-test (is (= ["modules" "mymodule" "tasks" "foo.sh"] (task-file-uri-components "foo.sh" "/path/to/environment/modules/mymodule/tasks/foo.sh"))) (is (= ["modules" "mymodule" "scripts" "foo.sh"] (task-file-uri-components "mymodule/scripts/foo.sh" "/path/to/environment/modules/mymodule/scripts/foo.sh"))) (testing "works with nested files" (is (= ["modules" "mymodule" "lib" "baz/bar/foo.sh"] (task-file-uri-components "mymodule/lib/baz/bar/foo.sh" "/path/to/environment/modules/mymodule/lib/baz/bar/foo.sh")))) (testing "when the module name is the same as a module subdirectory" (doseq [module ["tasks" "scripts" "files" "lib"] subdir ["tasks" "scripts" "files" "lib"] :let [file-name (if (= subdir "tasks") "foo.sh" (format "%s/%s/foo.sh" module subdir))]] (is (= ["modules" module subdir "foo.sh"] (task-file-uri-components file-name (format "/path/to/environment/modules/%s/%s/foo.sh" module subdir))))))) (deftest all-tasks-response-test (testing "all-tasks query" (with-redefs [jruby-core/borrow-from-pool-with-timeout (fn [_ _ _] {:jruby-puppet (Object.)}) jruby-core/return-to-pool (fn [_ _ _ _] #())] (let [jruby-service (reify jruby/JRubyPuppetService (get-pool-context [_] (jruby-pool-manager-core/create-pool-context (jruby-core/initialize-config {:gem-home "bar" :gem-path "bar:foobar" :ruby-load-path ["foo"]}))) (get-tasks [_ _ env] (when (= env "production") []))) handler (fn ([req] {:request req})) app (build-ring-handler handler "1.2.3" jruby-service) request (partial app-request app) response (fn [info] (all-tasks-response! info "production")) response-format (fn [task-name] {:name task-name :environment [{:name "production" :code_id nil}] :private false :description "test description"}) expected-response (fn [task-names] (map response-format task-names)) task-names ["apache" "apache::configure" "mongodb::uninstall"]] (testing "returns 200 for environment that exists" (is (= 200 (:status (request "/v3/tasks?environment=production"))))) (testing "returns 404 not found when non-existent environment supplied" (is (= 404 (:status (request "/v3/tasks?environment=test"))))) (testing "returns 400 bad request when environment not supplied" (logging/with-test-logging (is (= 400 (:status (request "/v3/tasks")))))) (testing (str "returns 400 bad request when environment has " "non-alphanumeric characters") (logging/with-test-logging (is (= 400 (:status (request "/v3/tasks?environment=~")))))) (testing "formats response body properly" (is (= (set (expected-response task-names)) (-> (map construct-info-from-task-name task-names) response :body (json/decode true) set)))))))) (deftest compile-endpoint (with-redefs [jruby-core/borrow-from-pool-with-timeout (fn [_ _ _] {:jruby-puppet (Object.)}) jruby-core/return-to-pool (fn [_ _ _ _] #())] (let [jruby-service (reify jruby/JRubyPuppetService (get-pool-context [_] (jruby-pool-manager-core/create-pool-context (jruby-core/initialize-config {:gem-home "bar" :gem-path "bar:foobar" :ruby-load-path ["foo"]}))) (compile-catalog [_ _ _] {:cool "catalog"}) (compile-ast [_ _ _ _] {:cool "catalog"})) handler (fn ([req] {:request req})) app (build-ring-handler handler "1.2.3" jruby-service)] (testing "compile endpoint for environments" (let [response (app (-> {:request-method :post :uri "/v3/compile" :content-type "application/json"} (ring-mock/body (json/encode {:certname "foo" :environment "production" :code_ast "{\"__pcore_something\": \"Foo\"}" :facts {:values {}} :trusted_facts {:values {}} :variables {:values {}}}))))] (is (= 200 (:status response))))) (testing "compile endpoint fails with no environment" (let [response (app (-> {:request-method :post :uri "/v3/compile" :content-type "application/json"} (ring-mock/body (json/encode {:certname "foo" :code_ast "{\"__pcore_something\": \"Foo\"}" :facts {:values {}} :trusted_facts {:values {}} :variables {:values {}} :options {:compile_for_plan true}}))))] (is (= 400 (:status response)))))))) (deftest jdk-support-status-test (is (= :unsupported (master-service/jdk-support-status "1.7"))) (is (= :unsupported (master-service/jdk-support-status "1.7.0"))) (is (= :deprecated (master-service/jdk-support-status "1.8"))) (is (= :deprecated (master-service/jdk-support-status "1.8.0"))) (is (= :deprecated (master-service/jdk-support-status "1.9"))) (is (= :deprecated (master-service/jdk-support-status "1.9.0"))) (is (= :deprecated (master-service/jdk-support-status "10"))) (is (= :deprecated (master-service/jdk-support-status "10.0"))) (is (= :official (master-service/jdk-support-status "11.0"))) (is (= :official (master-service/jdk-support-status "11.0.7"))) (is (= :official (master-service/jdk-support-status "17.0"))) (is (= :official (master-service/jdk-support-status "17.0.4")))) (deftest v4-routes-test (with-redefs [jruby-core/borrow-from-pool-with-timeout (fn [_ _ _] {:jruby-puppet (Object.)}) jruby-core/return-to-pool (fn [_ _ _ _] #())] (let [jruby-service (reify jruby/JRubyPuppetService (get-pool-context [_] (jruby-pool-manager-core/create-pool-context (jruby-core/initialize-config {:gem-home "bar" :gem-path "bar:foobar" :ruby-load-path ["foo"]}))) (compile-catalog [_ _ _] {:cool "catalog"}) (compile-ast [_ _ _ _] {:cool "catalog"})) handler (fn ([req] {:request req})) app (build-ring-handler handler "1.2.3" jruby-service)] (testing "catalog endpoint succeeds" (let [response (app (-> {:request-method :post :uri "/v4/catalog" :content-type "application/json"} (ring-mock/body (json/encode {:certname "foo" :environment "production" :persistence {:catalog true :facts true}}))))] (is (= 200 (:status response))) (is (= {:cool "catalog"} (json/decode (:body response) true))))) (testing "catalog endpoint fails with invalid environment name" (let [response (app (-> {:request-method :post :uri "/v4/catalog" :content-type "application/json"} (ring-mock/body (json/encode {:certname "foo" :environment "" :persistence {:catalog true :facts true}}))))] (is (= 400 (:status response))) (is (re-matches #".*Invalid input:.*\"\".*" (:body response)))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/puppet_profiler/000077500000000000000000000000001470345337400302455ustar00rootroot00000000000000puppet_profiler_core_test.clj000066400000000000000000000122241470345337400361470ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/puppet_profiler(ns puppetlabs.services.puppet-profiler.puppet-profiler-core-test (:import (ch.qos.logback.core Appender) (org.slf4j LoggerFactory) (ch.qos.logback.classic Logger Level) (com.puppetlabs.puppetserver PuppetProfiler) (com.codahale.metrics MetricRegistry Timer)) (:require [clojure.test :refer [deftest is testing use-fixtures]] [puppetlabs.services.puppet-profiler.puppet-profiler-core :refer [initialize metrics-profiler v1-status]] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core] [puppetlabs.services.jruby-pool-manager.impl.jruby-internal :as jruby-internal] [schema.test :as schema-test])) (use-fixtures :once schema-test/validate-schemas) ;; Our normal testutils for logging only work with clojure.tools.logging. (defmacro with-test-logs [log-output-var & body] `(let [~log-output-var (atom []) appender# (proxy [Appender] [] (getName [] "test") (setName [name#]) (doAppend [e#] (swap! ~log-output-var conj e#))) root# (LoggerFactory/getLogger Logger/ROOT_LOGGER_NAME) orig-level# (.getLevel root#)] (.setLevel root# Level/DEBUG) (.addAppender root# appender#) ~@body (.detachAppender root# appender#) (.setLevel root# orig-level#))) (defn test-logs-contain? [logs pattern level] (some (fn [event] (and (re-find pattern (.getMessage event)) (= level (.getLevel event)))) @logs)) (defn profile [profiler message metric-id] (let [metric-id (into-array String metric-id) context (.start profiler message metric-id)] (.finish profiler context message metric-id))) (deftest test-metrics-profiler (testing "metrics profiler" (logutils/with-test-logging (with-test-logs logs (let [registry (MetricRegistry.) profiler (metrics-profiler "localhost" registry)] (profile profiler "hi" ["function" "hiera-lookup"]) (profile profiler "bye" ["compile" "init-environment"]) (testing "keeps timers for all metrics" (let [metrics-map (.getMetrics registry) expected-metrics ["puppetlabs.localhost.function" "puppetlabs.localhost.function.hiera-lookup" "puppetlabs.localhost.compile" "puppetlabs.localhost.compile.init-environment"]] (is (= (set expected-metrics) (.keySet metrics-map))) (is (every? #(instance? Timer (.get metrics-map %)) expected-metrics))))))))) (deftest test-profiler-via-ruby (let [sc (jruby-internal/create-scripting-container (jruby-core/initialize-config {:ruby-load-path (jruby-puppet-core/managed-load-path ["./ruby/puppet/lib" "./ruby/facter/lib"]) :gem-home jruby-testutils/gem-home :gem-path jruby-testutils/gem-path :compile-mode :off}))] (try (let [script " require 'puppet' require 'puppet/util/profiler' require 'puppet/server' require 'puppet/server/jvm_profiler' require 'java' java_import com.puppetlabs.puppetserver.MetricsPuppetProfiler java_import com.codahale.metrics.MetricRegistry registry = MetricRegistry.new profiler = MetricsPuppetProfiler.new('testhost', registry) Puppet::Util::Profiler.add_profiler(Puppet::Server::JvmProfiler.new(profiler)) Puppet::Util::Profiler.profile('test', ['foo', 'bar', 'baz']) do sleep(0.01) end registry" registry (.runScriptlet sc script)] (is (= #{"puppetlabs.testhost.foo" "puppetlabs.testhost.foo.bar" "puppetlabs.testhost.foo.bar.baz"} (into #{} (.getNames registry))))) (finally (.terminate sc))))) (deftest test-initialize (testing "initializes profiler by default" (let [registry (MetricRegistry.) context (initialize {} "localhost" registry)] (is (instance? PuppetProfiler (:profiler context))))) (testing "initializes profiler if explicitly enabled" (let [registry (MetricRegistry.) context (initialize {:enabled true} "localhost" registry)] (is (instance? PuppetProfiler (:profiler context))))) (testing "does not initialize profiler if profiler is explicitly disabled" (let [registry (MetricRegistry.) context (initialize {:enabled false} "localhost" registry)] (is (nil? (:profiler context)))))) (deftest status-tolerates-nil-profiler (is (= {:state :running :status {}} (v1-status nil :debug)))) puppet_profiler_service_test.clj000066400000000000000000000042501470345337400366570ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/puppet_profiler(ns puppetlabs.services.puppet-profiler.puppet-profiler-service-test (:import (com.puppetlabs.puppetserver PuppetProfiler)) (:require [clojure.test :refer [deftest is testing]] [puppetlabs.services.puppet-profiler.puppet-profiler-service :refer [puppet-profiler-service]] [puppetlabs.trapperkeeper.services.webserver.jetty10-service :as jetty10-service] [puppetlabs.trapperkeeper.services.metrics.metrics-service :as metrics-service] [puppetlabs.trapperkeeper.services.scheduler.scheduler-service :as scheduler-service] [puppetlabs.trapperkeeper.services.status.status-service :as status-service] [puppetlabs.trapperkeeper.services.webrouting.webrouting-service :as webrouting-service] [puppetlabs.services.protocols.puppet-profiler :refer [get-profiler]] [puppetlabs.trapperkeeper.testutils.bootstrap :as bootstrap] [puppetlabs.trapperkeeper.app :as app])) (defn call-get-profiler [config pred?] (bootstrap/with-app-with-config app [puppet-profiler-service jetty10-service/jetty10-service metrics-service/metrics-service scheduler-service/scheduler-service status-service/status-service webrouting-service/webrouting-service] (merge config {:metrics {:server-id "localhost"} :webserver {:host "localhost"} :web-router-service {:puppetlabs.trapperkeeper.services.status.status-service/status-service "/status"}}) (let [service (app/get-service app :PuppetProfilerService)] (is (pred? (get-profiler service)))))) (deftest test-profiler-service (testing "get-profiler returns nil if profiling is not enabled" (call-get-profiler {:profiler {:enabled "false"}} nil?) (call-get-profiler {:profiler {:enabled false}} nil?)) (testing "get-profiler returns a profiler if profiling is enabled" (call-get-profiler {} #(instance? PuppetProfiler %)) (call-get-profiler {:profiler {}} #(instance? PuppetProfiler %)) (call-get-profiler {:profiler {:enabled "true"}} #(instance? PuppetProfiler %)) (call-get-profiler {:profiler {:enabled true}} #(instance? PuppetProfiler %)))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/request_handler/000077500000000000000000000000001470345337400302135ustar00rootroot00000000000000request_handler_core_test.clj000066400000000000000000000542761470345337400361000ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/request_handler(ns puppetlabs.services.request-handler.request-handler-core-test (:import (java.io StringReader ByteArrayInputStream) (com.puppetlabs.puppetserver JRubyPuppetResponse)) (:require [clojure.test :refer [deftest is testing]] [slingshot.test :refer :all] [ring.util.codec :as ring-codec] [puppetlabs.ring-middleware.utils :as ringutils] [puppetlabs.services.request-handler.request-handler-core :as core] [puppetlabs.ssl-utils.core :as ssl-utils] [puppetlabs.ssl-utils.simple :as ssl-simple] [puppetlabs.trapperkeeper.testutils.logging :as logutils] [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.services :refer [service]] [puppetlabs.services.jruby.jruby-puppet-service :as jruby-service] [puppetlabs.puppetserver.bootstrap-testutils :as jruby-bootstrap] [puppetlabs.services.protocols.versioned-code :as vc] [puppetlabs.services.puppet-profiler.puppet-profiler-service :as profiler] [puppetlabs.trapperkeeper.services.webserver.jetty10-service :as jetty10] [puppetlabs.trapperkeeper.services.scheduler.scheduler-service :as tk-scheduler] [puppetlabs.services.request-handler.request-handler-service :as handler-service] [puppetlabs.services.config.puppet-server-config-service :as ps-config] [puppetlabs.services.master.master-service :as master-service] [puppetlabs.services.ca.certificate-authority-service :as ca-service] [puppetlabs.trapperkeeper.services.webrouting.webrouting-service :as routing-service] [puppetlabs.trapperkeeper.services.authorization.authorization-service :as authorization-service] [puppetlabs.trapperkeeper.services.metrics.metrics-service :as metrics] [puppetlabs.services.jruby.jruby-metrics-service :as jruby-metrics-service] [puppetlabs.trapperkeeper.services.status.status-service :as status-service] [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol] [puppetlabs.puppetserver.testutils :as testutils] [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core] [puppetlabs.services.jruby-pool-manager.impl.jruby-pool-manager-core :as jruby-pool-manager-core] [cheshire.core :as cheshire] [puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service :as filesystem-watch-service])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Test Data (def test-resources-dir (str "./dev-resources/puppetlabs/services/" "request_handler/request_handler_core_test")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utilities (defn puppetserver-config [allow-header-certs] (core/config->request-handler-settings {:puppetserver {:ssl-client-verify-header "HTTP_X_CLIENT_VERIFY" :ssl-client-header "HTTP_X_CLIENT_DN"} :master {:allow-header-cert-info allow-header-certs}})) (defn jruby-request-with-client-cert-header [cert] (core/as-jruby-request (puppetserver-config true) {:request-method :get :headers {"x-client-cert" cert}})) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Tests (deftest wrap-params-for-jruby-test (testing "get with no query parameters returns empty params" (let [wrapped-request (core/wrap-params-for-jruby {:body (StringReader. "") :content-type "text/plain"})] (is (= {} (:params wrapped-request)) "Unexpected params in wrapped request") (is (= "" (slurp (:body wrapped-request))) "Unexpected body for jruby in wrapped request"))) (testing "get with query parameters returns expected values" (let [wrapped-request (core/wrap-params-for-jruby {:body (StringReader. "") :content-type "text/plain" :query-string "one=1%201&two=2&arr[]=3&arr[]=4" :params {:bogus ""}})] (is (= {"one" "1 1", "two" "2", "arr[]" ["3", "4"] :bogus ""} (:params wrapped-request)) "Unexpected params in wrapped request") (is (= "" (slurp (:body wrapped-request))) "Unexpected body for jruby in wrapped request"))) (testing "post with form parameters returns expected values" (let [body-string "one=1&two=2%202&arr[]=3&arr[]=4" wrapped-request (core/wrap-params-for-jruby {:body (StringReader. body-string) :content-type "application/x-www-form-urlencoded" :params {:bogus ""}})] (is (= {"one" "1", "two" "2 2", "arr[]" ["3" "4"] :bogus ""} (:params wrapped-request)) "Unexpected params in wrapped request") (is (= body-string (:body wrapped-request)) "Unexpected body for jruby in wrapped request"))) (testing "post with plain text in default encoding returns expected values" (let [body-string "some random text" wrapped-request (core/wrap-params-for-jruby {:body (StringReader. body-string) :content-type "text/plain" :params {:bogus ""}})] (is (= {:bogus ""} (:params wrapped-request)) "Unexpected params in wrapped request") (is (= body-string (slurp (:body wrapped-request))) "Unexpected body for jruby in wrapped request"))) (testing "post with plain text in UTF-16 returns expected values" (let [body-string-from-utf16 (String. (.getBytes "some random text from utf-16" "UTF-16")) wrapped-request (core/wrap-params-for-jruby {:body (ByteArrayInputStream. (.getBytes body-string-from-utf16 "UTF-16")) :content-type "text/plain" :character-encoding "UTF-16" :params {:bogus ""}})] (is (= {:bogus ""} (:params wrapped-request)) "Unexpected params in wrapped request") (is (= body-string-from-utf16 (slurp (:body wrapped-request) :encoding "UTF-16")) "Unexpected body for jruby in wrapped request"))) (testing "request with binary content type does not consume body" (let [body-string "some random text"] (doseq [content-type [nil "" "application/octet-stream" "APPLICATION/octet-Stream" "application/x-msgpack"]] (let [body-reader (StringReader. body-string) wrapped-request (core/wrap-params-for-jruby {:body body-reader :content-type content-type})] (is (identical? body-reader (:body wrapped-request)) "Unexpected body for jruby instance in wrapped request") (is (= body-string (slurp body-reader)) "Unexpected body for jruby content in wrapped request")))))) (deftest unmunge-header-name-works (testing "Umunging a puppet.conf http header named works as expected" (is (= (core/unmunge-http-header-name "HTTP_X_CLIENT_VERIFY") "x-client-verify")) (is (= (core/unmunge-http-header-name "HTTP_X_CLIENT_DN") "x-client-dn")))) (deftest cert-info-from-authorization (testing "authorization section in request" (let [url-encoded-cert (-> (str test-resources-dir "/localhost.pem") slurp ring-codec/url-encode) cert-from-authorization (:cert (ssl-simple/gen-self-signed-cert "authorization-client" 1 {:keylength 512})) cert-from-ssl (:cert (ssl-simple/gen-self-signed-cert "ssl-client" 1 {:keylength 512}))] (doseq [allow-header-cert-info [false true]] (testing (str "for allow-header-cert-info " allow-header-cert-info) (let [req (core/as-jruby-request (puppetserver-config allow-header-cert-info) {:request-method :get :authorization {:name "authorization-client" :authenticated true :certificate cert-from-authorization} :headers {"x-client-verify" "SUCCESS" "x-client-dn" "CN=x-client" "x-client-cert" url-encoded-cert} :ssl-client-cert cert-from-ssl})] (testing "has proper authenticated value" (is (true? (get req :authenticated)))) (testing "has proper name" (is (= "authorization-client" (get req :client-cert-cn)))) (testing "has proper cert" (is (identical? cert-from-authorization (get req :client-cert)))))))))) (deftest cert-info-in-headers (testing "In the case where Puppet Server is running under HTTP with an upstream HTTPS terminator, the cert's CN, cert, and authenticated status will be provided as HTTP headers. If cert info is not provided in the headers but is available via SSL, the SSL info will be used." (logutils/with-test-logging (let [single-cert-url-encoded (-> (str test-resources-dir "/localhost.pem") slurp ring-codec/url-encode) second-cert-url-encoded (-> (str test-resources-dir "/master.pem") slurp ring-codec/url-encode)] (testing "providing headers but not the puppet server config won't work." (let [req (core/as-jruby-request (puppetserver-config false) {:request-method :get :headers {"x-client-verify" "SUCCESS" "x-client-dn" "CN=puppet" "x-client-cert" single-cert-url-encoded}})] (is (not (get req :authenticated))) (is (nil? (get req :client-cert-cn))) (is (nil? (get req :client-cert))))) (testing "providing headers and allow-header-cert-info to true works" (let [req (core/as-jruby-request (puppetserver-config true) {:request-method :get :headers {"x-client-verify" "SUCCESS" "x-client-dn" "CN=puppet" "x-client-cert" single-cert-url-encoded}})] (is (get req :authenticated)) (is (= "puppet" (get req :client-cert-cn))) (is (= "CN=localhost" (ssl-utils/get-subject-from-x509-certificate (get req :client-cert)))))) (testing "a malformed DN string fails" (let [req (core/as-jruby-request (puppetserver-config true) {:request-method :get :headers {"x-client-verify" "SUCCESS" "x-client-dn" "invalid-dn"}})] (is (not (get req :authenticated))) (is (nil? (get req :client-cert))) (is (nil? (get req :client-cert-cn))))) (testing "Setting the auth header to something other than 'SUCCESS' fails" (let [req (core/as-jruby-request (puppetserver-config true) {:request-method :get :headers {"x-client-verify" "fail" "x-client-dn" "CN=puppet"}})] (is (not (get req :authenticated))) (is (= "puppet" (get req :client-cert-cn))) (is (nil? (get req :client-cert))))) (testing "cert and cn from header used and not from SSL cert when allow-header-cert-info true" (let [cert (ssl-utils/pem->cert (str test-resources-dir "/localhost.pem")) req (core/as-jruby-request (puppetserver-config true) {:request-method :get :ssl-client-cert cert :headers {"x-client-verify" "SUCCESS" "x-client-dn" "CN=puppet" "x-client-cert" second-cert-url-encoded}})] (is (get req :authenticated)) (is (= "puppet" (get req :client-cert-cn))) (is (= "CN=master1.example.org" (ssl-utils/get-subject-from-x509-certificate (get req :client-cert)))))) (testing "cert and cn from ssl used when allow-header-cert-info false" (let [cert (ssl-utils/pem->cert (str test-resources-dir "/localhost.pem")) req (core/as-jruby-request (puppetserver-config false) {:request-method :get :ssl-client-cert cert :headers {"x-client-verify" "SUCCESS" "x-client-dn" "CN=puppet" "x-client-cert" second-cert-url-encoded}})] (is (get req :authenticated)) (is (= "localhost" (get req :client-cert-cn))) (is (identical? cert (get req :client-cert))))))))) (deftest cert-decoding-failures (testing "A cert provided in the x-client-cert header that cannot be decoded into an X509Certificate object throws the expected failure" (testing "Improperly URL encoded content" (is (thrown+? #(and (= (:kind %) :bad-request) (re-matches #"Unable to URL decode the x-client-cert header: For input string: \"1Q\".*" (:msg %))) (jruby-request-with-client-cert-header "%1Q%2")))) (testing "Bad certificate content" (is (thrown+? #(and (= (:kind %) :bad-request) (re-matches #"Unable to parse x-client-cert into certificate: -----END CERTIFICATE(-----)? not found" (:msg %))) (jruby-request-with-client-cert-header "-----BEGIN%20CERTIFICATE-----%0AM")))) (testing "No certificate in content" (is (thrown+? [:kind :bad-request :msg "No certs found in PEM read from x-client-cert"] (jruby-request-with-client-cert-header "NOCERTSHERE")))) (testing "More than 1 certificate in content" (is (thrown+? [:kind :bad-request :msg "Only 1 PEM should be supplied for x-client-cert but 3 found"] (jruby-request-with-client-cert-header (-> (str test-resources-dir "/master-with-all-cas.pem") slurp ring-codec/url-encode))))))) (deftest ^:integration test-jruby-pool-not-full-during-code-id-generation (testing "A jruby instance is held while code id is generated" ; Okay, some prose to describe the test at hand. ; ; Here we are validating that a JRubyPuppet instance is checked out of the ; pool at the point a request for the current-code-id is made. Reservation ; of a JRuby is done to protect the pool from potentially being locked (and ; underlying code updated) between the time that the code-id is calculated ; and a catalog request is fulfilled. Any changes to code on disk during ; this window could invalidate the code-id. ; ; For this test, we stand up most of the stack, and replace the ; current-code-id function with a variety that we can control entry into ; and exit from. This allows us to make a request, and then while the ; request is in progress, make some assertions about the pool state, and ; then finish the request. (let [first-promise (promise) second-promise (promise) original-code-id 42 code-id (atom original-code-id) custom-vcs (service vc/VersionedCodeService [] (current-code-id [_ _] (deliver first-promise true) (deref second-promise 5000 false) (let [current-id @code-id] (swap! code-id inc) (str current-id))) (get-code-content [_ _ _ _] nil)) services [master-service/master-service jruby-service/jruby-puppet-pooled-service profiler/puppet-profiler-service handler-service/request-handler-service ps-config/puppet-server-config-service jetty10/jetty10-service ca-service/certificate-authority-service authorization-service/authorization-service routing-service/webrouting-service custom-vcs tk-scheduler/scheduler-service filesystem-watch-service/filesystem-watch-service metrics/metrics-service jruby-metrics-service/jruby-metrics-service status-service/status-service]] (jruby-bootstrap/with-puppetserver-running-with-services-and-mock-jruby-puppet-fn "For this test we're basically just validating that a JRuby is reserved before a code-id is calculated. A JRuby mock is safe here in that we're just validating operations against the JRuby pool and not functionality in core Ruby Puppet." app services {:jruby-puppet {:max-active-instances 1}} (partial jruby-testutils/create-mock-jruby-puppet (fn [request] (JRubyPuppetResponse. (int 200) (cheshire/generate-string {"classes" [] "environment" "production" "version" "1.2.3" "resources" [] "edges" [] "code_id" (get-in request ["params" "code_id"]) "name" "localhost"}) "application/json" "1.2.3"))) (jruby-testutils/wait-for-jrubies app) (let [in-catalog-request-future (promise) jruby-service (tk-app/get-service app :JRubyPuppetService) catalog-response (future (deliver in-catalog-request-future true) (testutils/get-catalog))] (deref in-catalog-request-future) (is (deref first-promise 10000 false)) ; Because we are blocking inside current-code-id, which happens to be ; used during a jruby request, we can assert that there will be no ; jruby instances left in the pool. (is (zero? (jruby-protocol/free-instance-count jruby-service))) (deliver second-promise true) ; Simple validation that the code-id from our mock VersionedCodeService ; was passed through to the catalog response from our mock ; JRubyPuppet instance. (is (= (str original-code-id) (get @catalog-response "code_id")))))))) (deftest request-handler-test (let [dummy-service (reify jruby-protocol/JRubyPuppetService (get-pool-context [_] (jruby-pool-manager-core/create-pool-context (jruby-core/initialize-config {:gem-home "foo" :gem-path "foo:foobar" :ruby-load-path ["bar"]}))))] (logutils/with-test-logging (testing "slingshot bad requests translated to ring response" (let [bad-message "it's real bad"] (with-redefs [core/as-jruby-request (fn [_ _] (ringutils/throw-bad-request! bad-message)) jruby-core/return-to-pool (fn [_ _ _ _] #())] (with-redefs [jruby-core/borrow-from-pool-with-timeout (fn [_ _ _] {})] (let [request-handler (core/build-request-handler dummy-service {} (constantly nil)) response (request-handler {:body (StringReader. "blah")})] (is (= 400 (:status response)) "Unexpected response status") (is (= bad-message (:body response)) "Unexpected response body"))) (with-redefs [jruby-core/borrow-from-pool-with-timeout (fn [_ _ _] nil)] (let [request-handler (core/build-request-handler dummy-service {} (constantly nil)) response (request-handler {:body (StringReader. "")})] (is (= 503 (:status response)) "Unexpected response status") (is (.startsWith (:body response) "Attempt to borrow a JRubyInstance from the pool")))))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/versioned_code_service/000077500000000000000000000000001470345337400315365ustar00rootroot00000000000000versioned_code_core_test.clj000066400000000000000000000105151470345337400372120ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/versioned_code_service(ns puppetlabs.services.versioned-code-service.versioned-code-core-test (:require [clojure.test :refer [deftest is testing]] [puppetlabs.puppetserver.common :refer [CodeId]] [puppetlabs.services.versioned-code-service.versioned-code-core :as vc-core] [puppetlabs.trapperkeeper.testutils.logging :refer [logged?] :as logging] [puppetlabs.kitchensink.core :as ks] [schema.core :as schema]) (:import (org.apache.commons.io IOUtils))) (def test-resources (ks/absolute-path "./dev-resources/puppetlabs/services/versioned_code_service/versioned_code_core_test")) (defn script-path [script-name] (str test-resources "/" script-name)) (deftest test-code-id-execution (testing "code id is successfully generated" (is (= "foo" (vc-core/execute-code-id-script! (script-path "echo") "foo")))) (testing "stderr is logged if generated" (logging/with-test-logging (is (= "" (vc-core/execute-code-id-script! (script-path "warn") "foo"))) (is (logged? (format "Error output generated while running '%s'. stderr: '%s'" (script-path "warn") "foo\n"))))) (testing "an exception is thrown for non-zero exit of the code-id-script" (logging/with-test-logging (is (thrown? IllegalStateException (vc-core/execute-code-id-script! (script-path "warn_echo_and_error") "foo"))) (is (logged? "Executed an external process which logged to STDERR: foo\n")))) (testing "exception thrown and error logged for exception during execute-command" (logging/with-test-logging (is (thrown? IllegalArgumentException (vc-core/execute-code-id-script! "false" "foo")))))) (deftest test-code-content-execution (testing "when executing external code content command" (let [environment "test" code-id "bourgeoisie123" file-path "foo/bar/baz"] (testing "and code-id is nil we see a schema error" (is (thrown-with-msg? Exception #"code-id.*nil" (vc-core/execute-code-content-script! (script-path "echo") environment nil file-path)))) (testing "and we failed to run the command we see the expected exception" (is (thrown-with-msg? IllegalStateException #"generated an error.*false" (vc-core/execute-code-content-script! "false" environment code-id file-path)))) (testing "and the command returned nonzero" (logging/with-test-logging (is (thrown-with-msg? IllegalStateException #"Non-zero.*warn_echo_and_error" (vc-core/execute-code-content-script! (script-path "warn_echo_and_error") environment code-id file-path))))) (testing "and the command succeeded" (testing "with stderr" (logging/with-test-logging (let [result (vc-core/execute-code-content-script! (script-path "warn") environment code-id file-path)] (is (= "" (IOUtils/toString result "UTF-8"))) (is (logged? (format "Error output generated while running '%s'. stderr: '%s'" (script-path "warn") (format "%s %s %s\n" environment code-id file-path))))))) (testing "witout stderr" (let [result (vc-core/execute-code-content-script! (script-path "echo") environment code-id file-path)] (is (= (format "%s %s %s\n" environment code-id file-path) (IOUtils/toString result "UTF-8"))))))))) (deftest code-id-validation (let [goods ["dcf16ec" "whatMakesJavaBad;isPartlySemiColons;clojureIsRealNice" "master-plan:stage_1:destroy-all-humans" "combining:lots;of_valid-characters" "urn:code-id:1:4dcf1fd;production"] bads [nil "bad code id" "bad-code-id!" "123'456" "not-a-good-code-id?" "Östersund" "( ͡° ͜ʖ ͡°)"]] (doseq [good goods] (is (nil? (schema/check CodeId good)))) (doseq [bad bads] (is (not (nil? (schema/check CodeId bad))))))) (deftest get-current-code-id!-error-test (testing "get-current-code-id! throws on invalid code-ids" (let [invalid-code-id-script (script-path "invalid_code_id")] (is (thrown-with-msg? IllegalStateException #"Invalid code-id 'not a valid code id'.*" (vc-core/get-current-code-id! invalid-code-id-script "testenv")))))) versioned_code_service_test.clj000066400000000000000000000066121470345337400377250ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/services/versioned_code_service(ns puppetlabs.services.versioned-code-service.versioned-code-service-test (:require [clojure.test :refer [deftest is testing]] [puppetlabs.services.versioned-code-service.versioned-code-service :as vcs] [puppetlabs.services.protocols.versioned-code :as vc] [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-testutils] [puppetlabs.trapperkeeper.app :as tk-app] [puppetlabs.trapperkeeper.testutils.logging :refer [logged?] :as logging] [puppetlabs.kitchensink.core :as ks]) (:import (org.apache.commons.io IOUtils))) (def test-resources (ks/absolute-path "./dev-resources/puppetlabs/services/versioned_code_service/versioned_code_service_test")) (defn script-path [script-name] (str test-resources "/" script-name)) (defn vcs-config [script] {:versioned-code {:code-id-command script :code-content-command script}}) (deftest test-code-id-execution (testing "nil is returned if no code-id-command is set" (logging/with-test-logging (tk-testutils/with-app-with-config app [vcs/versioned-code-service] {} (let [vcs (tk-app/get-service app :VersionedCodeService)] (is (nil? (vc/current-code-id vcs "foo"))) (is (logged? #"No code-id-command set" :info)))))) (testing "code id is successfully generated" (tk-testutils/with-app-with-config app [vcs/versioned-code-service] (vcs-config (script-path "echo")) (let [vcs (tk-app/get-service app :VersionedCodeService)] (is (= "foo" (vc/current-code-id vcs "foo"))))))) (deftest test-code-content-execution (testing "When calling get-code-content" (testing "and there is no code-content-command" (logging/with-test-logging (tk-testutils/with-app-with-config app [vcs/versioned-code-service] {} (let [vcs (tk-app/get-service app :VersionedCodeService)] (is (thrown-with-msg? IllegalStateException #".*Cannot retrieve code content because the \"versioned-code.code-content-command\" setting is not present in configuration.*" (vc/get-code-content vcs "test" "foobar" "foo/bar/"))))))) (testing "and there is a code-content-command" (logging/with-test-logging (tk-testutils/with-app-with-config app [vcs/versioned-code-service] (vcs-config (script-path "echo")) (let [vcs (tk-app/get-service app :VersionedCodeService) result (-> (vc/get-code-content vcs "test" "foobar" "foo/bar/") (IOUtils/toString "UTF-8"))] (is (= "test foobar foo/bar/\n" result)))))))) (deftest ^:integration vcs-fails-startup-if-misconfigured (testing "If only :code-id-command is set, it will not start up" (logging/with-test-logging (try (tk-testutils/with-app-with-config app [vcs/versioned-code-service] {:versioned-code {:code-id-command (script-path "echo")}}) (catch IllegalStateException e (is (re-find #"Only one of .* was set." (.getMessage e))))))) (testing "If only :code-content-command is set, it will not start up" (logging/with-test-logging (try (tk-testutils/with-app-with-config app [vcs/versioned-code-service] {:versioned-code {:code-content-command (script-path "echo")}}) (catch IllegalStateException e (is (re-find #"Only one of .* was set." (.getMessage e)))))))) puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/testutils/000077500000000000000000000000001470345337400252435ustar00rootroot00000000000000puppetlabs-puppetserver-7e1a9a8/test/unit/puppetlabs/testutils/task_coordinator.clj000066400000000000000000000265041470345337400313110ustar00rootroot00000000000000(ns puppetlabs.testutils.task-coordinator "This namespace defines a TaskCoordinator protocol. It is used for testing in cases where you need a lot of control over asynchronous behaviors; it provides a mechanism for defining phases for a task, and blocking/unblocking the task at any phase of its life cycle." (:require [schema.core :as schema] [clojure.core.async.impl.protocols :as async-protocols] [clojure.tools.logging :as log] [clojure.core.async :as async]) (:import (clojure.lang IFn))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Private (defprotocol TaskCoordinator (initialize-task [this task-id task-fn] [this task-id task-fn phase] "Initialize a task given an id and a function that will actually perform the task. Also supports an optional `phase` keyword; if not provided, then the task will be blocked without having started yet. If `phase` is provided, the task will be executed synchronously until it reaches the specified `phase` (which must be a valid phase from `task-phases`).") (notify-task-progress [this task-id phase] "Notify the coordinator that the task with the given ID has reached the given phase. This function should be called from within the logic of the task itself, and will cause the task to block until the coordinator has given it permission to proceed.") (advance-task-to [this task-id phase] "Synchronously advance the task with the given id to the specified phase.") (unblock-task-to [this task-id phase] "Allow the task with the given id to proceed, asynchronously, to the specified phase. This call is asynchronous and returns immediately; it should always be followed by a call to `wait-for-task` to re-join the threads after some intermediate action.") (wait-for-task [this task-id phase] "Blocks until the task with the given id reaches the specified phase. This should only be called following a call to `unblock-task-to`.") (callback-at-phase [this task-id phase callback] "Register a callback function that should be called when a task reaches a certain phase. Used in combination with `unblock-task-to`. The callback function should accept two arguments: a task-id and a phase.") (final-result [this task-id] "Synchronously advance the task through to completion (if it has not already been completed), and return the result of the original `task-fn` that was passed in to `initialize-task`.") (task-phases [this] "For internal use; the sequence of phases making up the life cycle for a task managed by this coordinator.") (tasks [this] "For internal use; the state of all of the tasks currently being managed by this coordinator.")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Private (schema/defn wait-for-ack [channel :- (schema/protocol async-protocols/Channel)] (let [ack (async/!! channel {:task-id task-id :phase phase}) (log/debug "Blocking task; waiting for ack:" task-id phase) (wait-for-ack channel) (log/debug "task received ack, unblocking:" task-id phase))) (schema/defn ^:always-validate do-notify-task-progress [coordinator :- (schema/protocol TaskCoordinator) task-id :- Scalar phase :- schema/Keyword] (do-notify-task-progress* coordinator (str task-id) phase)) (schema/defn ^:always-validate do-advance-task-to* [coordinator :- (schema/protocol TaskCoordinator) task-id :- schema/Str desired-phase :- schema/Keyword] (log/debug "Advancing task to phase:" task-id desired-phase) (let [channel (:channel (get @(tasks coordinator) task-id)) next-phase (fn [] (:phase (async/!! channel :go) (loop [phase (next-phase)] (log/debug "Advancing task; reached phase:" task-id phase) (let [task (get @(tasks coordinator) task-id) next-expected-phase (first (:remaining-phases task))] (when-not (= next-expected-phase phase) (let [msg (format "Expected next phase '%s', got '%s'" next-expected-phase phase)] (log/error msg) (throw (IllegalStateException. msg)))) (let [remaining-phases (rest (:remaining-phases task))] (log/debug "Advancing task; remaining phases:" task-id remaining-phases) (swap! (tasks coordinator) assoc-in [task-id :remaining-phases] remaining-phases)) (swap! (tasks coordinator) assoc-in [task-id :current-phase] phase) (if (= desired-phase phase) (log/debug "task has reached desired phase:" task-id phase) (do (log/debug "Advancing task: sending ack" task-id) (async/>!! (:channel task) :go) (recur (next-phase)))))))) (schema/defn ^:always-validate do-advance-task-to [coordinator :- (schema/protocol TaskCoordinator) task-id :- Scalar desired-phase :- schema/Keyword] (do-advance-task-to* coordinator (str task-id) desired-phase)) (schema/defn ^:always-validate do-advance-task-through-all-phases* [coordinator :- (schema/protocol TaskCoordinator) task-id :- schema/Str] (let [task (get @(tasks coordinator) task-id)] (when-not (empty? (:remaining-phases task)) (log/debug "Advancing task to last phase:" task-id (last (task-phases coordinator))) (do-advance-task-to coordinator task-id (last (task-phases coordinator)))) (log/debug "Advancing task to completion:" task-id) (async/>!! (:channel task) :go))) (schema/defn ^:always-validate do-advance-task-through-all-phases [coordinator :- (schema/protocol TaskCoordinator) task-id :- Scalar] (do-advance-task-through-all-phases* coordinator (str task-id))) (schema/defn ^:always-validate do-unblock-task-to ([coordinator :- (schema/protocol TaskCoordinator) task-id :- Scalar desired-phase :- schema/Keyword] (do-unblock-task-to coordinator task-id desired-phase nil)) ([coordinator :- (schema/protocol TaskCoordinator) task-id :- Scalar desired-phase :- schema/Keyword callback :- (schema/maybe IFn)] (log/debug "Unblocking task to phase:" task-id desired-phase) (async/go (advance-task-to coordinator task-id desired-phase) (when callback (callback task-id desired-phase))))) (schema/defn ^:always-validate do-wait-for-task* [coordinator :- (schema/protocol TaskCoordinator) task-id :- schema/Str desired-phase :- schema/Keyword] (log/debug "Waiting for task to reach phase:" task-id desired-phase) (loop [task (get @(tasks coordinator) task-id)] (when-not (= desired-phase (:current-phase task)) (recur (get @(tasks coordinator) task-id))))) (schema/defn ^:always-validate do-wait-for-task [coordinator :- (schema/protocol TaskCoordinator) task-id :- Scalar desired-phase :- schema/Keyword] (do-wait-for-task* coordinator (str task-id) desired-phase)) (schema/defn ^:always-validate do-callback-at-phase [coordinator :- (schema/protocol TaskCoordinator) task-id :- Scalar desired-phase :- schema/Keyword callback :- IFn] (async/go (do-wait-for-task coordinator task-id desired-phase) (callback task-id desired-phase))) (schema/defn ^:always-validate do-final-result* [coordinator :- (schema/protocol TaskCoordinator) task-id :- schema/Str] (log/debug "Retrieving final result:" task-id) (let [task (get @(tasks coordinator) task-id)] (do-advance-task-through-all-phases coordinator task-id) (log/debug "Reading final result:" task-id) (let [result (async/