├── CODEOWNERS ├── Makefile ├── test-resources └── puppetlabs │ └── ssl_utils │ └── examples │ └── ssl │ ├── ca │ ├── serial │ ├── private │ │ └── ca.pass │ ├── inventory.txt │ ├── ca_pub.pem │ ├── ca_crl.pem │ ├── ca_crt.pem │ ├── signed │ │ └── localhost.pem │ ├── ca_key.pem │ └── ca_key_pkcs8.pem │ ├── private_keys │ ├── eckey.pem │ ├── keyonly.pem │ ├── localhost.pem │ └── multiple_pks.pem │ ├── certification_requests │ ├── bad_public_key.pem │ ├── ca_test_client.pem │ ├── ca_test_client_with_old_exts.pem │ └── ca_test_client_with_exts.pem │ ├── crl_validation │ ├── 1-crl-chain.pem │ ├── expired-crl.pem │ ├── not-yet-valid-crl.pem │ ├── crl-with-bad-signature.pem │ ├── 1-cert-chain.pem │ ├── cert-with-crl-bad-sig.pem │ ├── cert-with-expired-crl.pem │ ├── cert-with-not-valid-crl.pem │ ├── 2-crl-chain.pem │ ├── 3-crl-chain.pem │ ├── other-3-crl-chain.pem │ ├── crl-chain-with-cert-revoked.pem │ ├── 4-crl-chain.pem │ ├── 3-cert-chain.pem │ ├── other-3-cert-chain.pem │ └── cert-chain-with-revoked-cert.pem │ ├── public_keys │ └── localhost.pem │ ├── crl.pem │ ├── ca_crl.pem │ ├── ca_crl_multi.pem │ └── certs │ ├── ca.pem │ ├── localhost.pem │ ├── cert_with_old_exts.pem │ ├── cert_with_exts.pem │ ├── multiple.pem │ └── multiple_reverse.pem ├── .gitignore ├── .clj-kondo └── config.edn ├── jenkins └── deploy.sh ├── CONTRIBUTING.md ├── CHANGELOG.md ├── locales ├── ssl-utils.pot └── eo.po ├── .github └── workflows │ ├── pr-testing.yaml │ ├── clojure-linting.yaml │ └── mend.yml ├── .travis.yml ├── test └── puppetlabs │ └── ssl_utils │ ├── extensions_utils_test.clj │ ├── simple_test.clj │ └── testutils.clj ├── project.clj ├── dev-resources └── Makefile.i18n ├── src ├── clojure │ └── puppetlabs │ │ └── ssl_utils │ │ └── simple.clj └── java │ └── com │ └── puppetlabs │ └── ssl_utils │ └── ExtensionsUtils.java ├── README.md └── LICENSE /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @puppetlabs/dumpling 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include dev-resources/Makefile.i18n 2 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca/serial: -------------------------------------------------------------------------------- 1 | 0003 -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca/private/ca.pass: -------------------------------------------------------------------------------- 1 | =?ScA6k 3 | # This file is distributed under the same license as the puppetlabs.ssl_utils package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: puppetlabs.ssl_utils \n" 10 | "Report-Msgid-Bugs-To: docs@puppet.com\n" 11 | "POT-Creation-Date: \n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/clojure/puppetlabs/ssl_utils/core.clj 21 | msgid "Loaded PEM object of type ''{0}'' from ''{1}''" 22 | msgstr "" 23 | -------------------------------------------------------------------------------- /.github/workflows/pr-testing.yaml: -------------------------------------------------------------------------------- 1 | name: PR Testing 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | types: [opened, reopened, edited, synchronize] 7 | paths: ['src/**','test/**','project.clj'] 8 | 9 | jobs: 10 | pr-testing: 11 | name: PR Testing 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | version: ['8', '11', '17'] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: checkout repo 19 | uses: actions/checkout@v3 20 | with: 21 | submodules: recursive 22 | - name: setup java 23 | uses: actions/setup-java@v3 24 | with: 25 | distribution: 'temurin' 26 | java-version: ${{ matrix.version }} 27 | - name: clojure tests 28 | run: lein test 29 | timeout-minutes: 30 -------------------------------------------------------------------------------- /locales/eo.po: -------------------------------------------------------------------------------- 1 | # Esperanto translations for puppetlabs.ssl_utils package. 2 | # Copyright (C) 2017 Puppet 3 | # This file is distributed under the same license as the puppetlabs.ssl_utils package. 4 | # Automatically generated, 2017. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: puppetlabs.ssl_utils \n" 9 | "Report-Msgid-Bugs-To: docs@puppet.com\n" 10 | "POT-Creation-Date: \n" 11 | "PO-Revision-Date: \n" 12 | "Last-Translator: Automatically generated\n" 13 | "Language-Team: none\n" 14 | "Language: eo\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | 20 | #: src/clojure/puppetlabs/ssl_utils/core.clj 21 | msgid "Loaded PEM object of type ''{0}'' from ''{1}''" 22 | msgstr "" 23 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca/ca_pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1Dd+K00k5OlIx/2Iw3re 3 | WBKg58t1o1PJw+Czz91a8D3oxdbfdO7MA8kJL01AWpTiec4AO/grNe42NmDWQgd6 4 | hDi2r8lf86sS+vIo6nfId3aYzho2wHYNT2g5/6rR5odpJXzIMJ6RriczuuZ7DVIL 5 | oSH+jBU841gBJgFE9dxEChHeRsN9H5tqrLsZ1AylPJ6vGvTy3MZrP9Kjtx0pef8g 6 | jhOL7h0Ab1t1ZZmHrXkL6ikY1u6+4SeIqml/sNJtx0lG7cZtjmluWUpFIjEqpa1t 7 | 3afVCTeF1he3RxPxM8gyV6JpOJm9q3qBUnaTEHIlbsnEooYsXQQXloLang4vXzaU 8 | uB7iu7OvLZeGfeeTfPhhFgJ0VxV6KUTHOoGpSLWchWr7CgXSo3s+Y4ixJL6bswQg 9 | tSlP51hlvTP+nag1J1EDQsia+5c6erdOBl6tNfgu6GdqWYn8rjUsy9GWNNeP80M3 10 | IBX7V43nv8g7p2MyBZ7g94uUMbi04jqLEUjDJXkjKKtL/4GJm+kprv1BPWejuwyW 11 | +1xUdNkKw6B9Z0bsPA8FPrjt34pRg8sk3ivu/g1ml6VrevZnaOulqWS/8QdPk0Vl 12 | 0wtnsmBtluo3gir7I0LFSbLALnOw68SPwQkBys8Ajda9biovOOE3ZCoX3op802EA 13 | 3x6yXcDVyiJV3OifQ6t4yqsCAwEAAQ== 14 | -----END PUBLIC KEY----- 15 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/public_keys/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2fdYL2dgbrSAXhjmEUuo 3 | D+JSQeOo876FkkNAMJFmOncPLeZguL0jR1BY0n0jj0jF8r0rO9kNTZGVIq/z9Nd6 4 | gcR4NGEGQH63Hwe4xXOHax7ulyXemjMyqlZXOhKP7huYIp6Dp9aQuxLnrbe7rn/6 5 | tt8pZozUinEYKY3yHLs9ckJFAZz/T5sgO1oeq7Hx6RUvs6620p1U8bmStpQvdom0 6 | q6tFy71PUamIu0PFVOHBR9IGqNW6FhaeAieAy3ALBtH1/S5x1utiNORm4hCSGN7K 7 | ToEjJoCaNBqZnNy+V21RCRZkDYayJAwZg2nn0p8LASJD2g3LkFElI9cWbZwE1hGB 8 | pBpFoS+UesVwdQuWczgkvGlXBHq67Qovi9mmEoDliIYaft+1cv0EgyHCUza7VvsW 9 | IfmZVPu3lNRxnou2WA15EXKCBfa8GxjGM2caj9fRrTFMBUpHzIkmi0vgwbpe9zHi 10 | SofZfBXJDGXbWLlZNsfMtsov/yNcQjBfn9G035YL78fLNcJcewdTkhxOVRFoy0C3 11 | SX7pjZngUG4IyjQbRQb+1wAGsyDE0nWpoyVfaL+tS34WCO5ebYaGXSqp8Ivaigdg 12 | PtEHE7r6stgDSumGGW9lBA8n6nhFwuVjMc5uZeJMz3PRcMJKg/JmWiATp1vAMguq 13 | 6f8sqdex1G13ed16KnOfCbUCAwEAAQ== 14 | -----END PUBLIC KEY----- 15 | -------------------------------------------------------------------------------- /.github/workflows/clojure-linting.yaml: -------------------------------------------------------------------------------- 1 | name: Clojure Linting 2 | 3 | on: 4 | pull_request: 5 | types: [opened, reopened, edited, synchronize] 6 | paths: ['src/**','test/**','.clj-kondo/config.edn','project.clj','.github/**'] 7 | 8 | jobs: 9 | clojure-linting: 10 | name: Clojure Linting 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: setup java 14 | uses: actions/setup-java@v3 15 | with: 16 | distribution: temurin 17 | java-version: 17 18 | - name: checkout repo 19 | uses: actions/checkout@v2 20 | - name: install clj-kondo (this is quite fast) 21 | run: | 22 | curl -sLO https://raw.githubusercontent.com/clj-kondo/clj-kondo/master/script/install-clj-kondo 23 | chmod +x install-clj-kondo 24 | ./install-clj-kondo --dir . 25 | - name: kondo lint 26 | run: ./clj-kondo --lint src test 27 | - name: eastwood lint 28 | run: | 29 | java -version 30 | lein eastwood -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: clojure 2 | install: 3 | - sudo env LEIN_ROOT=true curl -L -o /usr/local/bin/lein https://raw.githubusercontent.com/technomancy/leiningen/2.9.1/bin/lein 4 | - sudo chmod a+x /usr/local/bin/lein 5 | - lein self-install 6 | jobs: 7 | include: 8 | - stage: jdk8 without FIPS 9 | script: lein with-profile dev test 10 | jdk: openjdk8 11 | - stage: jdk8 with FIPS 12 | script: lein with-profile fips test 13 | jdk: openjdk8 14 | 15 | - stage: jdk11 without FIPS 16 | script: lein with-profile dev test 17 | jdk: openjdk11 18 | - stage: jdk11 with FIPS 19 | script: lein with-profile fips test 20 | jdk: openjdk11 21 | 22 | - stage: jdk8 without FIPS 23 | script: lein with-profile dev test 24 | jdk: openjdk8 25 | arch: ppc64le 26 | 27 | - stage: jdk11 without FIPS 28 | script: lein with-profile dev test 29 | jdk: openjdk11 30 | arch: ppc64le 31 | 32 | sudo: false 33 | notifications: 34 | email: false 35 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIICmTCBggIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 3 | IGV4cGxvc2l2bxcNMTcwODAzMTYyODE0WhcNMjIwODAyMTYyODE1WqAvMC0wHwYD 4 | VR0jBBgwFoAUbFDtfev3eTVf9i8IVmy9z8+SIUgwCgYDVR0UBAMCAQAwDQYJKoZI 5 | hvcNAQEFBQADggIBAJZ0oKDUJVyvDjPqSt7Kz6KpBFOFB+SiDdJhBzmV0roAirRu 6 | wAvS71eLgkM6ggtv5q5TCVEyQW0I5u3Oa2u0cMzO0zsw3nEnXO1kW6gZACf/D5VM 7 | uxdeQvCWkNzkUhZ57dWlKlZYV1FvA5JEaSUh6y3oMaeH6gvW/qulvr7auxgpLM+O 8 | IXW/i5jmvsOWRC22pfOrNjMH22x2p9ws3AX4vS+ff1iVvCxSF1Vy2z4lrXK7XmNM 9 | iRhlBQjLexfFRW9ijRkUx7jexthchfqwAc9l7WxkTSqqDwk7COrwrghF12um9RVD 10 | 1Z00HHyKhA6NIsMMteoAvkXX5J4qtIl68Nkrq4BNsgCtAKxpCdJz0ka61vbSyl/N 11 | FHt8N+fHDJv/t6No82H3yAGTWoK6mEh8XiVB9SyCAJbBwDQ86wJNDGKikiwHkUAJ 12 | qsoeQnDACqIl4+1lIOgyq+CczpKVaXRvWf4lLstQ66qEr9XJRIy1FjiKGora5HF8 13 | S+QvrASGzbMqKF57RqVAaflZexmxi1lJ/xF01yFTWxtmksm9lN4X11oysj3z0naT 14 | UKMW2xZmN6Y4CjjgxHLZTscWH/cJWReVEQr8g7mkyYz+4j8iNKmg8aiDmhCs/J0r 15 | gLzhG0uO3dsXg0ANZGxyWtrRaSjB7ALEPHP4kZ9tuRXPGE8XWWxmOvbfxxJK 16 | -----END X509 CRL----- 17 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca/ca_crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIICmTCBggIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 3 | IGV4cGxvc2l2bxcNMTcwODAzMTYyODE0WhcNMjIwODAyMTYyODE1WqAvMC0wHwYD 4 | VR0jBBgwFoAUbFDtfev3eTVf9i8IVmy9z8+SIUgwCgYDVR0UBAMCAQAwDQYJKoZI 5 | hvcNAQEFBQADggIBAJZ0oKDUJVyvDjPqSt7Kz6KpBFOFB+SiDdJhBzmV0roAirRu 6 | wAvS71eLgkM6ggtv5q5TCVEyQW0I5u3Oa2u0cMzO0zsw3nEnXO1kW6gZACf/D5VM 7 | uxdeQvCWkNzkUhZ57dWlKlZYV1FvA5JEaSUh6y3oMaeH6gvW/qulvr7auxgpLM+O 8 | IXW/i5jmvsOWRC22pfOrNjMH22x2p9ws3AX4vS+ff1iVvCxSF1Vy2z4lrXK7XmNM 9 | iRhlBQjLexfFRW9ijRkUx7jexthchfqwAc9l7WxkTSqqDwk7COrwrghF12um9RVD 10 | 1Z00HHyKhA6NIsMMteoAvkXX5J4qtIl68Nkrq4BNsgCtAKxpCdJz0ka61vbSyl/N 11 | FHt8N+fHDJv/t6No82H3yAGTWoK6mEh8XiVB9SyCAJbBwDQ86wJNDGKikiwHkUAJ 12 | qsoeQnDACqIl4+1lIOgyq+CczpKVaXRvWf4lLstQ66qEr9XJRIy1FjiKGora5HF8 13 | S+QvrASGzbMqKF57RqVAaflZexmxi1lJ/xF01yFTWxtmksm9lN4X11oysj3z0naT 14 | UKMW2xZmN6Y4CjjgxHLZTscWH/cJWReVEQr8g7mkyYz+4j8iNKmg8aiDmhCs/J0r 15 | gLzhG0uO3dsXg0ANZGxyWtrRaSjB7ALEPHP4kZ9tuRXPGE8XWWxmOvbfxxJK 16 | -----END X509 CRL----- 17 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca_crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIICmTCBggIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 3 | IGxvY2FsaG9zdBcNMTQwNjA0MTgyMjQyWhcNMTkwNjAzMTgyMjQzWqAvMC0wHwYD 4 | VR0jBBgwFoAU1etN1YnFeqOA3cHNnYwcqJjocNswCgYDVR0UBAMCAQAwDQYJKoZI 5 | hvcNAQEFBQADggIBADnmOeX7aBp+IJ1ccgPFTI+j27iE30Cp0shm87Up0p1cIMmd 6 | 3eRwo5Zxc88fpGPfwRq6Xe214mt2MmvUdlA9pazZ717lAm/4nSkbhOm5fcHX8hH8 7 | tJYIULm5+c9oHXLnafZPXS/VJHQfisWKekV9XU8sIAUyax3tZrGlbaOzu1jWBZDQ 8 | MI0UOT9SzDBEM4rxICWdbhNVCFQB3AGzH+n4cOkqA/pPVNLindDJ3GLhVPeogm3o 9 | rX4wzJrZDzcrrP3Wu8YE1UQReTz2CT3L1zFDA5Jbig7TKVCquUvUVl8SGKnrLddN 10 | Y2h/VTwCh6i6ldWDWZ/jsbXFQUZ8kw7KVN7TUev+NJ+cU1MPqkCPFnGLOxG9Tx5u 11 | yX/BD3Uu4cbqVGE5OFSiUzpMR5Uj0NWcsS/0KpELYtCmHfzuEgAQ/vu77Fqx4GIo 12 | Sve3Xm9bsMkSsthM4hqy2rTQjrvdlkwuxv/uvADYLzSK1O7gvOPPx3O1fQLLqjIT 13 | i9AFfLPkIvVP9kWbrlzdlaM9zDhMArbP26BbgMphMZ30jHZdn72nnuM+ha5MA/n+ 14 | HkeoLTG0aeCxjpg/cLKwo0WMswlz4d8vJjaarcMbNznx9eF/ufZIKWb4JhWMTxRx 15 | er6ttMIEp/yEKkvqwWS5TZicaHbrm5Zo5cuwwNRh5sG3r4Uyt44U6IqzZT33 16 | -----END X509 CRL----- 17 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/1-cert-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v 3 | dCBDQTAeFw0yMTA1MDIxOTMwMzNaFw0yNjA1MDMxOTMwMzNaMBIxEDAOBgNVBAMM 4 | B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQcLjfE9fE 5 | Lrq4EiH4xQ4FwYur5C/n10zwn3R6SF0KeNLNZ3eJs3FRhkDUyQeYcqbDThC08zi2 6 | 5buksqK3Obu6Wv0JmrStxHdqhbvxtf8f+XHi10LtYyzh2KHm24tk4hWEVNP272eP 7 | z0hvq1ZemY3WUR9kJi/qoTt0EKPm0uXLDP9lHGD+5M9/bHhR11GwEUF03C/i5/bC 8 | NWT8vMG6j+A2pGJJD1PvjKSizqgn+wRBA4NZs6UxTUq9m+3ztUtVJO9Bywv50V5n 9 | 7tHPmHnTfE8SrpLw88lvq4Z2WiqP8HVAYv2ihNI/YhQccUAsSTvCVijHID01Ln9O 10 | q3ldUQ2yPCMxAgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv 11 | b3QgQ0GCAgKaMB0GA1UdDgQWBBTuhCMI2UaWPQi1kUp83IaO4YllfzAPBgNVHRMB 12 | Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAbS8L 13 | CsVWh9OShUp5lI7M0ybmuRbh0OWlp1PPW4FqkiFYxtqZiCjQuYwcpO3THvT1a4L0 14 | WK+pGVa8WYh+Wf0kKUGyJ6VZicEF4cf8zQyc4ht6Xr/ZEFq2gF2+TsJ2i3dqCoou 15 | 6dCdC4rxIBvD9uTKdMZ2+91uKdpJLvOZS7Q+xbZY4eJx5uKMHBkTbG4k1xyJCCjt 16 | rM3mXw7HSbM/6mMYybiEnD0gyM5rZYCZKISH723D+BWU9wnc9gFNe03zdsVtlcPt 17 | vcav2qimEceat4ULVFCYnjUFgCgROfFm6EE/1n41+zAMpN6Mb6mvb5Ui50ZHGTS0 18 | Sr2iJIyTy7PNFDo48A== 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/cert-with-crl-bad-sig.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v 3 | dCBDQTAeFw0yMTA1MDIyMDE1NTJaFw0yNjA1MDMyMDE1NTJaMBIxEDAOBgNVBAMM 4 | B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD1WCUkwSfi 5 | kkSmQoDIGhHbz4g64YOTQ6gT8FrOiQGdb2uZ1oqgX5HIID/mdIfMiiaHWBRtU/tD 6 | YDvmwPjhxQbQ+NbqAXRNce1GsIg891Ph7OFIm5LGYg2CpfuDwRBG8lOECNt67X4A 7 | Tor9jCuWgz4EHzTiIJtMlGp2mrmSgAvuksUFJ3OSsnQK9NeT7GJumhGk04PNrl/i 8 | Y9hhWwHEFEAFDUrgjYzz+4Z+A6cgnO6+qkB2wXiQfx/hVY9QNU9PWsmvabmlC5ee 9 | ESjAnTAb/6gcereTaLcIBrTLUoXYBVeb1/elljeCA29PZhfdq2m0Dx+GfsJXdjIa 10 | w++OTxcKdGTtAgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv 11 | b3QgQ0GCAgKaMB0GA1UdDgQWBBReaRj5pWwMTw6lNQHgT1oNqG/rGTAPBgNVHRMB 12 | Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEACBto 13 | W+89ROV5HDx2D0oP2xyfyFmkytT0hWHrsYCLamZdDBQwOdOChoaGIGFT2JOcX6FZ 14 | DNHuUv7XFYdZAT5PUmOlKYgyT5ED6t3l6YOyIFz+kaoco3GlocHrnwdeempk3XHE 15 | Wg0Co3Opgd+WkF3fYa896uAbjlDAiAsuUSVNCmkijuKCxCFKg40LhOEifRw7kJ3S 16 | sRoDQa1JC/1/rqlH8FDJ3HueiMt4DmqXFJprU44UKzZa77UGWuIMU2qZ4JRaMMuH 17 | iayAZUaHl8mdN2NSBed6wg3Fc+Do/DzAtXgCcC94HJMlsDGtYmREd6sdGHJEjNdS 18 | MVi9KL7/Qp5VJfi5yQ== 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/cert-with-expired-crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v 3 | dCBDQTAeFw0yMTA1MDIyMDE0MjJaFw0yNjA1MDMyMDE0MjJaMBIxEDAOBgNVBAMM 4 | B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXHMRCdcq4 5 | KDUU4ZhD3A1lCnJQb4sZlpUQYbVtiGYTHg9HiF5MXyoC+oMuTp2sCNTH2lFepf2X 6 | Sjmncf2SZTLjrmgm+YucUYV7B8Tp5TAhKTh/cFQTmq6OfRWQBrvtOqEBwbmm7GWD 7 | 701SohvaZis4oJdf6z78MQjza+0dnR90dxuES91dSZ7KaMTkIYyuT67YGA/1q+2b 8 | x4JjCENmLniMZ82TvdV3M4bxSLG1qMj9o2Eq3WmofXKclSCsTiWdmuk7T0MjsIDS 9 | 4WnKjbRxE7VyMsd32k4TSHfo71mTGbFgIbwoAbChhM4CaXMDxKA4LNGZRi1OkCm0 10 | bUDqcgaWya4pAgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv 11 | b3QgQ0GCAgKaMB0GA1UdDgQWBBSwYwCkspvqGwZk8/ghyC4LlMuIFDAPBgNVHRMB 12 | Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAZdvk 13 | bhV5if/lHA5A3nyqm7CbkpB7YuTfHJMM5sgaAQieEQmH7igGTr59MfHPsTIfKf5Q 14 | 53FIqriuLrA8ShErPpG256u3nSrHn3R+WcTpLwMEOFJ4zFTDuMhwUuY9IS0LdLr5 15 | qgR6hnnwvSlUbHaPTpfCfSQ3M3+lC0B/9Oc5Vs+Vv2g4o8yNl3twn5cNMjdKboDZ 16 | bGNo6aoBpivuJazSEBNyPlL6HOfddd2bAenPRTm52p/Yq06K8bWz1NDbpN4H5jZ/ 17 | +1AlfOBtrbhcnHoP6wodU5JFAmmdDYlqDUqnZuAD53TT/bMb5XCHSKWMLVqCIPid 18 | rHRLeNmJyKjCymECKw== 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/cert-with-not-valid-crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v 3 | dCBDQTAeFw0yMTA1MDIyMDE1MzhaFw0yNjA1MDMyMDE1MzhaMBIxEDAOBgNVBAMM 4 | B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCPY3v3YrdF 5 | 6ENxymrxj6e367jmXzhIyEt/m//XiJz8BMRBrAcVKLRQXbalWj9jLuNwP3gFX41P 6 | Zm0SHs0ISchJwdCq+O5k+AX3ffM2HcB8u/nAgs0RPLkZaj76c25zGy/Jw+5hpVTs 7 | xmInX+mmdT9YTTFMxq1w/CNsqWJcYeGFRflLMvfIx/wdNPL5GVqIMYv070DXgGJu 8 | /XTpXHnmoQi43DCeyD/0jWlzFB4trfm1iCvZAvZRUOKZBD9tTzE22aqghWGpHPur 9 | uMn2lUCg/uF8eCvagee50GHTeXrKfNgmIM59MxJCOSijfUV2KCSgVLJAbME95aNq 10 | vvEmbVi1pcX9AgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv 11 | b3QgQ0GCAgKaMB0GA1UdDgQWBBSdH5zbzDzVAV55HIGWeU9dsCGwuzAPBgNVHRMB 12 | Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAF+bV 13 | uHIm5qhTWQBrqAvL35BNqaSJzmdJgmkFRlayzN11SUuMZUjqY1MdQaGyU7CsQafS 14 | AwHlYfsbsUifzT0ZF2s+Enqqft+eSCF9xOoYkuEWVxlBflgWObYzMOZM3XL90CSt 15 | mow7mDLqpLG25GXhlsYVYAuQYCXrnUqCobSHFQjtOTwj/19y3Qo28EchLdMD2759 16 | OUymgAXA4YAA1HnJJaE81KgQ/wpSDXNFVlevVs10Bo9DLhXXoRh6ij+x06npIJTw 17 | E5l6TdBkAtU0BhX+71TnBDShkhAQKFZ0X4+1fXtm08zAYeCZqjStY44GMlZbgTUc 18 | cfeqMICjcJiMHPpVpQ== 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/2-crl-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 3 | ZSBDQSAxFw0yMTA1MDMyMDE3NDdaFw0yNjA1MDMyMDE3NDdaoC8wLTAfBgNVHSME 4 | GDAWgBS4+q81U1SALApa6n0SKT60dKN9qjAKBgNVHRQEAwIBADANBgkqhkiG9w0B 5 | AQsFAAOCAQEAP1bubYtfvEsLzLw7gl4lqHiVlT7iaSqxjsxm7cL9qB41nPnwSloG 6 | 6EovLEo4doPdgQV1Zuc0hfSHC4afnziua54NNZ+VVhmi2UbtozzvfxyZ4eevujEi 7 | dQ1V53hrP3TPatj3e018LOlMUrUkifhEPllQrWbAuGwddpxnaeni57BKjX4NYgYm 8 | BsJZIvLvMRG8BMfgoITkKVr4yfoc0wRN563rD96xpT4Obl0fv3zw4+zA5tt8QfKP 9 | t/q6vfg1IIMCyze3AgTOzKCCqhAJFWsxeg0m/+rx9YlBCwJjyMMRSxans1DRzwpK 10 | vBrKGFyV3Hdx8mDtVmfVBG4Umws3E8xqlQ== 11 | -----END X509 CRL----- 12 | -----BEGIN X509 CRL----- 13 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 14 | ZSBDQSAyFw0yMTA1MDMyMDE3NDRaFw0yNjA1MDMyMDE3NDRaoC8wLTAfBgNVHSME 15 | GDAWgBTac952FxGfhUaIhusQD/GIbx5knDAKBgNVHRQEAwIBADANBgkqhkiG9w0B 16 | AQsFAAOCAQEAQcRtEHND8gFdmoMLS0EC+6Hx2vRHWtPYZRlQxxAJuf9Wj3uWJ1qL 17 | OCA62Yr1ZDClliRHWjk/kors5JGl3HD+k5CWPNO2oytI1cUy6x/9I+eK8//fZbE0 18 | vrR1wYgEtAwBxLa/eOPVgm/Y0d45b7GdUoSJZCO07KS6VvMC5V4ZxhwyErj8iIRa 19 | ztzgU/rWExDFvdK2RAjEe+Tzw4a7sxd0/RIAaFJZF+FEKEaX7MFNfQZ8vUgd7K2g 20 | 8TmlBMg3DksHLnDT5r4zpsPvrBcjP/NYf/42p5LeaZG7otFPP5I0tD1+uXWM72AB 21 | ygvxpZQkG+xro5sU4P9DEO5uBPhhaceTfQ== 22 | -----END X509 CRL----- 23 | -------------------------------------------------------------------------------- /test/puppetlabs/ssl_utils/extensions_utils_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.ssl-utils.extensions-utils-test 2 | (:require [clojure.test :refer :all] 3 | [puppetlabs.ssl-utils.simple-test :as simple-test] 4 | [puppetlabs.ssl-utils.core :as ssl-utils] 5 | [puppetlabs.ssl-utils.simple :as simple]) 6 | (:import (java.net InetAddress))) 7 | 8 | (deftest general-names 9 | (testing "InetAddress.toString() returns proper string form." 10 | (let [addr (InetAddress/getByAddress (byte-array [192 168 2 1]))] 11 | (is (= "/192.168.2.1" (.toString addr))))) 12 | 13 | (testing "Can encode and decode all General Names types" 14 | (let [gns {:rfc822-name ["foo@bar.com"] 15 | :dns-name ["localhost.localdomain"] 16 | :uri ["file:///foo/bar"] 17 | :ip ["192.168.69.90"] 18 | :registered-id ["1.2.3.4"]} 19 | in-exts [{:oid ssl-utils/subject-alt-name-oid 20 | :critical true 21 | :value gns}] 22 | opts {:extensions in-exts 23 | :keylength 512} 24 | ssl-cert (simple/gen-self-signed-cert "test" 42 opts) 25 | cert (simple-test/roundtrip-pem 26 | ssl-utils/cert->pem! ssl-utils/pem->cert (:cert ssl-cert)) 27 | out-exts (ssl-utils/get-extensions cert)] 28 | (is (= in-exts out-exts))))) 29 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certification_requests/ca_test_client.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIEXjCCAkYCAQAwGTEXMBUGA1UEAwwOY2FfdGVzdF9jbGllbnQwggIiMA0GCSqG 3 | SIb3DQEBAQUAA4ICDwAwggIKAoICAQDTI6sWYs5iHviDpUxoRblddfkFNIO09WAy 4 | MOgRISkjWWPKoLJwUksKIlpVWJpZ5cZXQ1++x87xw4vtoNs0zfhQLADqt7ESrAac 5 | F3qf2aSRimPLDlZis4zq7zqcXDqV/+SQseosBGJvTrOZLNg7Bhi5uVg4apmNKWTV 6 | N0y0ofB6AG1aEfE4znehqoI3lXHacIC7y0h0rpBwMVyyMWNcUB8GcA5I/qaDH0wd 7 | VCMYupwcKluaY0mYX7ynw0C58uW2X/AymwiEt30f+TgCNdddw0+IxirSGmrac77s 8 | F5kSz5WXiI9HI9F6PGGjxcjbDisN9TL9q/KiYoOJ9gP/gu5oLH7Bed7Cudgh+Gpu 9 | SJ5TELRpCCb2kCrFKGwvjLnn75vZwI1qKFVbuNVKwsrN3wfYQncJ5jbxiHeO0QJB 10 | J5Z8hAEPJtcMkARgLi6TZxaGlBp6mz3Tj4YVNB7ERSdwJLRHmgmvnyDbrW36oy7n 11 | e884usoi0EzwX3V31fFCP9z/s8vguYGD20Yho9nCqekziYwS+phT20WGYTBsIgYn 12 | qEGbE8BO5pw/jMSwHN7RNXsIhZJhtVq3oGd9ubaojd6omLWI13bY2p59pSUB783D 13 | 3fS0KouvayKiG4DfId5GKQ+LMytSQulvdJgBBJw/oxheJxk5k2SHvOHdb883ZV5c 14 | 6AnlpK66pQIDAQABoAAwDQYJKoZIhvcNAQELBQADggIBAASUS1UJsbhYrTwCZ+DI 15 | 67309w5uzfevoq6LEK6RyIBrYiQMrFYrG+kvGDdHr9KQ0mcoduv+dnlrE5ZFfjPq 16 | xLfGVc3yknrEFlDEkB4wPfPa0FH9R0gXXLuzdnHBrmnYcVtJF/Azhlv1wfIh7hWK 17 | Z3qPYP9fq8G/E1IXXKmp1YV0Q5ecZU7XgZBTmppxxDYGd0edUOq799ZQpfo3rp3J 18 | C81gKd2+O+VHVaxOtnyKcYrET8/7T16ekCqB8j1Hn/MHcNe7onEhYtvDmP73+JGI 19 | gNACDoAa721cEyWhYsYif8xufWfeIQYS97MuvWT4BfW0vnBiL0P7ddSJFDWmFsAX 20 | PDGrNumgwmPYmBAmHOx13dGvX51OoyZjh4mYX9vvAXllpYoU0ilB8uzP3jBiwXPe 21 | nzmbwCFKh38ln2esXzgZdW37t6ouY8zf6NpaaKlmGBgH8zcAjh7Q+DqDJ/PowYIp 22 | HbywNi+qGfwnklHFB4WhEQ+Vhr88LRe466lwPVvHc/TlSFsfC/1B5rQPijl3PH5X 23 | sDJCIQ1n+Vw3qChdKgN3Zj6y831TWmbdzuFi2T51DkD+d8yY+yr5BZ90ub58EsCl 24 | v5DzKKoqzTUCUxLzpLWwKWkNuQHKFAa3ER/o/nZ/DqSbd1gY0g9eO1hJzZ+PSa+S 25 | u2C1xT9i8Rm7C3a5v10EPDzP 26 | -----END CERTIFICATE REQUEST----- 27 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca_crl_multi.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIB2jCBwzANBgkqhkiG9w0BAQUFADB+MSQwIgYDVQQDExtJbnRlcm1lZGlhdGUg 3 | Q0EgKG1hc3Rlci1jYSkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5vcmcx 4 | GTAXBgNVBAoTEEV4YW1wbGUgT3JnLCBMTEMxGjAYBgNVBAsTEVNlcnZlciBPcGVy 5 | YXRpb25zFw0xNDA0MDgwMTI1MzlaFw0zNDA0MDMwMTI1MzlaMBQwEgIBARcNMTQw 6 | NDA4MDEyNTM5WjANBgkqhkiG9w0BAQUFAAOCAQEAYMRAzRxGX0SaCUYZKNn25JyK 7 | uNoT91hdmUuSYnIiHkNxft/8x6EKSllrc1nzn0/sBBfzZ1VAK6tZTPHhWZ3m/JDy 8 | B40ovaz/jgQEowKf+LL8lI8wVqa3ycwAclpACmvMpwhVIWTGOSI5kDA3+rI24J+k 9 | z8mlTWJ56JcdWlbniZ9TPR73LixUvBq8t1dZGsj8Xez+BHcgcdT79M7HMuGgXws1 10 | JHbHc4N8s5Ursp6np6o56YRSU/24kH/Dzp+4ddSGV+nTEX8y/tQsIgSLlZ9fJoQi 11 | HSDe5/yTzhYVvOyW7ZLDvuy409kyNuESsur3iTKLPLQNFQwMsM++yt2nKWOzcQ== 12 | -----END X509 CRL----- 13 | -----BEGIN X509 CRL----- 14 | MIICmTCBggIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 15 | IGxvY2FsaG9zdBcNMTQwNjA0MTgyMjQyWhcNMTkwNjAzMTgyMjQzWqAvMC0wHwYD 16 | VR0jBBgwFoAU1etN1YnFeqOA3cHNnYwcqJjocNswCgYDVR0UBAMCAQAwDQYJKoZI 17 | hvcNAQEFBQADggIBADnmOeX7aBp+IJ1ccgPFTI+j27iE30Cp0shm87Up0p1cIMmd 18 | 3eRwo5Zxc88fpGPfwRq6Xe214mt2MmvUdlA9pazZ717lAm/4nSkbhOm5fcHX8hH8 19 | tJYIULm5+c9oHXLnafZPXS/VJHQfisWKekV9XU8sIAUyax3tZrGlbaOzu1jWBZDQ 20 | MI0UOT9SzDBEM4rxICWdbhNVCFQB3AGzH+n4cOkqA/pPVNLindDJ3GLhVPeogm3o 21 | rX4wzJrZDzcrrP3Wu8YE1UQReTz2CT3L1zFDA5Jbig7TKVCquUvUVl8SGKnrLddN 22 | Y2h/VTwCh6i6ldWDWZ/jsbXFQUZ8kw7KVN7TUev+NJ+cU1MPqkCPFnGLOxG9Tx5u 23 | yX/BD3Uu4cbqVGE5OFSiUzpMR5Uj0NWcsS/0KpELYtCmHfzuEgAQ/vu77Fqx4GIo 24 | Sve3Xm9bsMkSsthM4hqy2rTQjrvdlkwuxv/uvADYLzSK1O7gvOPPx3O1fQLLqjIT 25 | i9AFfLPkIvVP9kWbrlzdlaM9zDhMArbP26BbgMphMZ30jHZdn72nnuM+ha5MA/n+ 26 | HkeoLTG0aeCxjpg/cLKwo0WMswlz4d8vJjaarcMbNznx9eF/ufZIKWb4JhWMTxRx 27 | er6ttMIEp/yEKkvqwWS5TZicaHbrm5Zo5cuwwNRh5sG3r4Uyt44U6IqzZT33 28 | -----END X509 CRL----- 29 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/private_keys/keyonly.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3986OFH0Vkw3i 3 | bJ8BicJzJjqEuYwZYrm9QPBN1fTOgEXHQrGVL8L1XA6QT1XknBT4o3zw+PuQuvUy 4 | Gm9pyTl4/wkt5llBPg6tfL7JhgFpKvDaZzxa51lKvnRUVYuLwNL+hKPvvsPOLdcF 5 | +/x3+cGzc+M7FpPLm/V+VGqiCoc9LnDOh9iSUD5ONrKjzHVzNT0IFSSGNEhYMIcG 6 | Ogf0hmFCnd1w9mcghnm+qMKN5LVdT6maPtpTAKaDYVvX0UiZldWP172r2fu22sNN 7 | B5JNMJ4LFQ7pOO6psyMZmPidhCBHlueya2Vq3PURH9G3heYhQyX/AYnXaT7wTZk4 8 | Jfr+oVCnAgMBAAECggEAWQHQMfW/vxxy70XWeIwKRGQOlAChw/Z8HxC4MzB9TRvK 9 | pumhuahuDwAHG9MGn6DUlKek34HXVOLfluorVWdCI0RhUI/ORz6bI1zjgeUP8a4Q 10 | 8dpY3TJphTw4VEU/StJ0QygxmOEXIz4SdpbAQ9vW19gN7JyzzSMb149IODYX0IVA 11 | 8bJI1oV9ig2vp+JZyOVQLpXn5EdKlHtVjInSGOMPyFNZ1QkcyQFoozSw/XJ8vyk3 12 | 4bskjaTyF85cgkTgwy674iVnKu+3wVpcyzq8elJDEzKz6CH6nQO6/xTHv+tm6yQu 13 | f3HuXEaIysGw0i6qbEtP5VSx6DCANcwdWUwtTVrboQKBgQDqxh23m/2uh2U9d5xW 14 | BhUWIGXBIBgEYxdXayh69796Bg2HHtOt5VeRPXHHLGaieYC9qUUHm2ppJBx2LdDQ 15 | M7UGoShmyUrnA8HDrjn6BHkmeFGjDdsw5Y4t2QRh3B0rEFIwYoSonYpnWDnJh6Qe 16 | SU/adCN+j8z59HcIqLC20bLU7QKBgQDImcd45OWZTqfptiJ7HfJApQtX8uv+fk2V 17 | dtbJEOMfmIOH9GSGguygUjccC7jVGMm63KNaDs1/gW7o8/pPUZGhGV48oG2qmlfD 18 | FlRc6vmxNSBv73h1h/XfTS1aKjzSm5U+66e3S0v9ObO4Y0ybSQhI/GkkuIaIK6G0 19 | hnfDqZ69YwKBgHkK7fVlUpSyL+tSCON9PU/sIipBHsDcSgODNxq3Mxx5lG3u4dpN 20 | XSl/0XKMHNp15H9kjzeN1H4i5R21H2zIy/OAEXF1JM4YbMUzxaZ2ufOwov57PWBn 21 | ajePJShDMTKrtoRFtvmsR9hib2DNMzt+NtJ9gHNXNqpEdT6cooePdDE9AoGABG0Q 22 | L6StRDKuFcQFAr5oZ/C8TVZ4yoay44dZudn7iOjujgNgbG9bFTZ7LM09aMZBPTQ9 23 | DnGhKx0J+23WqgVctzc+EwxfHxKEuTM27U3p8HUBoDaia8VyMVkclQ61hNgV9Oty 24 | KeMpbA7n3juipxJ3clTPZRYFMd/0k20cG18Ut40CgYEAngAQc4wZjvQSLlcmHw2V 25 | xWa5Reug51D609MRXfHJOXtyVmlAFAOcTe/P/xr+0R7uAz9JHiSLBiXzxROmeczW 26 | HjO5uOTfh+UjUl8Dfy5R4mq3XVLtdMTfBG8lxPsKUMUvOEwc+JHh0JriwN2+aVqv 27 | CRMCwm+RRhWwCqOoqKfNBio= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/3-crl-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 3 | ZSBDQSAxFw0yMTA1MDMyMDE3NDdaFw0yNjA1MDMyMDE3NDdaoC8wLTAfBgNVHSME 4 | GDAWgBS4+q81U1SALApa6n0SKT60dKN9qjAKBgNVHRQEAwIBADANBgkqhkiG9w0B 5 | AQsFAAOCAQEAP1bubYtfvEsLzLw7gl4lqHiVlT7iaSqxjsxm7cL9qB41nPnwSloG 6 | 6EovLEo4doPdgQV1Zuc0hfSHC4afnziua54NNZ+VVhmi2UbtozzvfxyZ4eevujEi 7 | dQ1V53hrP3TPatj3e018LOlMUrUkifhEPllQrWbAuGwddpxnaeni57BKjX4NYgYm 8 | BsJZIvLvMRG8BMfgoITkKVr4yfoc0wRN563rD96xpT4Obl0fv3zw4+zA5tt8QfKP 9 | t/q6vfg1IIMCyze3AgTOzKCCqhAJFWsxeg0m/+rx9YlBCwJjyMMRSxans1DRzwpK 10 | vBrKGFyV3Hdx8mDtVmfVBG4Umws3E8xqlQ== 11 | -----END X509 CRL----- 12 | -----BEGIN X509 CRL----- 13 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 14 | ZSBDQSAyFw0yMTA1MDMyMDE3NDRaFw0yNjA1MDMyMDE3NDRaoC8wLTAfBgNVHSME 15 | GDAWgBTac952FxGfhUaIhusQD/GIbx5knDAKBgNVHRQEAwIBADANBgkqhkiG9w0B 16 | AQsFAAOCAQEAQcRtEHND8gFdmoMLS0EC+6Hx2vRHWtPYZRlQxxAJuf9Wj3uWJ1qL 17 | OCA62Yr1ZDClliRHWjk/kors5JGl3HD+k5CWPNO2oytI1cUy6x/9I+eK8//fZbE0 18 | vrR1wYgEtAwBxLa/eOPVgm/Y0d45b7GdUoSJZCO07KS6VvMC5V4ZxhwyErj8iIRa 19 | ztzgU/rWExDFvdK2RAjEe+Tzw4a7sxd0/RIAaFJZF+FEKEaX7MFNfQZ8vUgd7K2g 20 | 8TmlBMg3DksHLnDT5r4zpsPvrBcjP/NYf/42p5LeaZG7otFPP5I0tD1+uXWM72AB 21 | ygvxpZQkG+xro5sU4P9DEO5uBPhhaceTfQ== 22 | -----END X509 CRL----- 23 | -----BEGIN X509 CRL----- 24 | MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx 25 | MDUwMzIwMTc0M1oXDTI2MDUwMzIwMTc0M1qgLzAtMB8GA1UdIwQYMBaAFHx1U1ZP 26 | RR89jsP80QcF41C/jifvMAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQAq 27 | C/WCvBHbzwW5+vRvW3TuX1iK7JUJt1JHVLIevy32g4I8ZQ7+EZHIAr9Gzg2eed2/ 28 | vIg9Tg6KYGtPVb6QqGDan17lwYPnu3gm14QAU3pqmLtev0SPKefSqp08dnk3JMTP 29 | fYVvjXBoGCJCCLLz3eqUWlQS+aL2sSXwppJk4ADi3lOfEQYwQMQ/ljw4zc0Ss+v4 30 | GrilMx//BstCgTmk96NaTFcT+klMlUAUiHyxMfaXCaHfEOAwiYb2I4S3Jwy4jqNB 31 | 6Gj/n8h0bTT32g5SFLJZEUv1sQ2XNKkofObx8EscE4himUSuhz8vw+hKhzG50iWG 32 | 2WIxGnoNC0IDubSk0wZa 33 | -----END X509 CRL----- 34 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/other-3-crl-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 3 | ZSBDQSAxFw0yMTA1MDMyMTEwNTVaFw0yNjA1MDMyMTEwNTVaoC8wLTAfBgNVHSME 4 | GDAWgBSPEiPxv6v41g6qJngRTOfiDTmIuTAKBgNVHRQEAwIBADANBgkqhkiG9w0B 5 | AQsFAAOCAQEAkj/eoPJhyZ4/tuXo5GO+T+T+5UVBDTol109RXxV+n50n89CEn08L 6 | kkb6gw+CbC0svJoXLJRMX/vb7Esym8mBtsWrt6XMY4EWo/fiQaU1zQHyme45ThZw 7 | djdFklhAFUwDMJEXslFQ0RJ/15dnvrpmhuPuPVwKNdqca91MdYD5Bw7APV/N0FT5 8 | CDZe40AryHPGosO+jbrwMxHf2Hon6hztPIBQMP5YcUi4y5XaVgAwcTyAV7fAv1fn 9 | zaeVaZ4yF8mo4QS/KxOTT76tVXho53X0bwa1S7ZIjShhtGOYhnVjuw6xnvwcuTxd 10 | KN04onkVyCW5eqNZr44F4bDLV9a9JH4oNg== 11 | -----END X509 CRL----- 12 | -----BEGIN X509 CRL----- 13 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 14 | ZSBDQSAyFw0yMTA1MDMyMTEwNTVaFw0yNjA1MDMyMTEwNTVaoC8wLTAfBgNVHSME 15 | GDAWgBSgaJZ+dObbuFezAnPdmHOUICGG2TAKBgNVHRQEAwIBADANBgkqhkiG9w0B 16 | AQsFAAOCAQEAG9/nSsdq19h+HgL/e3qe363jB803UIQLlpR1mtfdkWkK5buX/Mnw 17 | x8oO4fli+4CjslrUBVID/ZnpN3+gx/osxjcJX1rM1ouBII2hZy3Gp96DEM7GsPju 18 | yKdTxt0vuGSWHEl+EeIW957lgUvj4DxfF26HqE2mt9W80q2GBJHzSYDMH6M9LSQt 19 | OD2Y8I1ZjlFbVWFoRKk0TWDsHkvwXV7MQ7W5mjKBRrKuGWHQYZKw3NcNvbB1fDgV 20 | wm1g96BQl8fgzmq/EjNEVfHXjEwax3oti2x7SKkqzlY7Uwt4Vn6SbyNzlGBLMhgs 21 | ax3MCukiH+HWm91fNtSWdJ/bCGk0bAHrGw== 22 | -----END X509 CRL----- 23 | -----BEGIN X509 CRL----- 24 | MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx 25 | MDUwMzIxMTA1NFoXDTI2MDUwMzIxMTA1NFqgLzAtMB8GA1UdIwQYMBaAFAls8gQe 26 | EhTqJX+wDYf6SjWXnbXfMAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQC0 27 | RSqReA/2V0XkBloMgZcDpE6MXcVYCnBK/zSXDrXE0TjdCCYcMcu9iqnr8MWsltKt 28 | 0Flj83tE9I9LlW6o9SxZGbOJdLdBtOA3aLCsm65JkXb5DfTvv36z+oyGfg8eQtux 29 | BtF0dOZSYEWMyObJ+l20z3NMtbB6KJqAlA40OZrPKjC1r40qeqFIp0PvBHJ63te1 30 | 8fU8FuZsv75DlikAwMV7m1a03SthfB8Yk+xgsV+3LOjRrBaiAyvWfQhLHmj6SCIg 31 | H9mkr3K3WoiD+CQnW7YNOlbmbu8fVW0Sjgi2PE4B/4z38xLKsXS9pgftkdyJNCyk 32 | QWQaIVG6vMBzN1WqfQpR 33 | -----END X509 CRL----- 34 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/crl-chain-with-cert-revoked.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIBsDCBmQIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwdSb290IENBFw0y 3 | MTA1MDMyMTA4NDhaFw0yNjA1MDMyMTA4NDlaMCIwIAIBAhcNMjEwNTAzMjEwODQ5 4 | WjAMMAoGA1UdFQQDCgEBoC8wLTAKBgNVHRQEAwIBATAfBgNVHSMEGDAWgBQJdfA7 5 | 4L4kkPg8lvcxBs8Q2aoofTANBgkqhkiG9w0BAQsFAAOCAQEAqb5Z341gADSJro85 6 | Nk+VRVV7aMJgplqGXOb2DZVNRF265KoIXanY3UG233PtKdac/ZYzeNtTs5z0OMgy 7 | rgvYFOpCH+bajYaAU1LtV6PwDtYq17pHgFhbyoRZ7zlZ8cCVAK5N9f/RPt51Awsk 8 | 34eE05Q9z+WvSQDZ5Pbw76c8FxJxyj4+5QgeDfjRdlHLZ/uIZZA74WJE3V3WjxqH 9 | n8mRjrfbeHrvQ7g0lWvqVgfik2olrQLH8NwesrINmN7o28wQYaF5zT2J0ou+Y8La 10 | 650Th2sh3CaYQ/icoiR8VsmMwt0J+9xYuJd7VjF+RyqwfSEte8sf6QU8MYKhTjkA 11 | sS90FQ== 12 | -----END X509 CRL----- 13 | -----BEGIN X509 CRL----- 14 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 15 | ZSBDQSAxFw0yMTA1MDMyMTA4NDlaFw0yNjA1MDMyMTA4NDlaoC8wLTAfBgNVHSME 16 | GDAWgBQ1ePwXp7mB7ho/Txi1Vtdt38BU3jAKBgNVHRQEAwIBADANBgkqhkiG9w0B 17 | AQsFAAOCAQEAFGgAtjeeAGnOY2A/6JrB7HkWolsDGDIs9R6fVTRWT4tp3HfZgAO2 18 | J5gcW8FW7c3V5iDBje9lLbEOty+4cbmdExOZitZcOHk6ucRHKTXgnwej9LcONFaX 19 | rgsptssb50LgGhqh2fRB8IP1EMU7ugpNYDDxPG2cKa5HF8Rm8me3gtYrl62FkMqB 20 | 6Ow+7yz1XHZW+iJHDdGTfG1im9+SPmAtEwfC15h9PQS5+WtH+UdLpKyqULVtr1XF 21 | rWBvWA/lcVlpXtKRwplfACjr1judQVb3iTjjJ8aeqD37mAqAPFvOmN+NxW4Ghcup 22 | f6TupPw0r0KVLP1b6uZ6RpH+oJGwh892uA== 23 | -----END X509 CRL----- 24 | -----BEGIN X509 CRL----- 25 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 26 | ZSBDQSAyFw0yMTA1MDMyMTA4NDhaFw0yNjA1MDMyMTA4NDhaoC8wLTAfBgNVHSME 27 | GDAWgBT5GEvSd10qEiGQJXnbJ6qORNmAeTAKBgNVHRQEAwIBADANBgkqhkiG9w0B 28 | AQsFAAOCAQEAMSz2v+NFnuXmw6XdqA0np4lThU5lAYkfqxRJ2bpD1oVlWfcCiqMe 29 | RJkqAsYLcsmYW0NDaZvy/v1sBc6oAHgdqllcs55489+fwqasc1Z8icFgoHS4/CLI 30 | A9aMdIlqv9gb5gfJZLXiwRogBgnEmetZ+r3z3SSUKQZXdU/ko2868auNJdiKaj0A 31 | v6IAZmVDaE/9f7zkCilXhNPkR48z4trfCpJ+b/pyJlEdEud/QK/l5wsUQfz9dOv3 32 | zlzTuG7w9bAKvA5QBWayimOYIiLaFsoYdbW4KqZxFDmPQ4TD3pt4dCF2wtbz6YdR 33 | x49GbQxlsNv5/t7yH7KRqBToeKEWUzH0rA== 34 | -----END X509 CRL----- 35 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca/ca_crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFaTCCA1GgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xNzA4MDIxNjI4MTVaFw0yMjA4MDIxNjI4MTVa 4 | MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogZXhwbG9zaXZvMIICIjANBgkqhkiG9w0B 5 | AQEFAAOCAg8AMIICCgKCAgEA1Dd+K00k5OlIx/2Iw3reWBKg58t1o1PJw+Czz91a 6 | 8D3oxdbfdO7MA8kJL01AWpTiec4AO/grNe42NmDWQgd6hDi2r8lf86sS+vIo6nfI 7 | d3aYzho2wHYNT2g5/6rR5odpJXzIMJ6RriczuuZ7DVILoSH+jBU841gBJgFE9dxE 8 | ChHeRsN9H5tqrLsZ1AylPJ6vGvTy3MZrP9Kjtx0pef8gjhOL7h0Ab1t1ZZmHrXkL 9 | 6ikY1u6+4SeIqml/sNJtx0lG7cZtjmluWUpFIjEqpa1t3afVCTeF1he3RxPxM8gy 10 | V6JpOJm9q3qBUnaTEHIlbsnEooYsXQQXloLang4vXzaUuB7iu7OvLZeGfeeTfPhh 11 | FgJ0VxV6KUTHOoGpSLWchWr7CgXSo3s+Y4ixJL6bswQgtSlP51hlvTP+nag1J1ED 12 | Qsia+5c6erdOBl6tNfgu6GdqWYn8rjUsy9GWNNeP80M3IBX7V43nv8g7p2MyBZ7g 13 | 94uUMbi04jqLEUjDJXkjKKtL/4GJm+kprv1BPWejuwyW+1xUdNkKw6B9Z0bsPA8F 14 | Prjt34pRg8sk3ivu/g1ml6VrevZnaOulqWS/8QdPk0Vl0wtnsmBtluo3gir7I0LF 15 | SbLALnOw68SPwQkBys8Ajda9biovOOE3ZCoX3op802EA3x6yXcDVyiJV3OifQ6t4 16 | yqsCAwEAAaOBrzCBrDA3BglghkgBhvhCAQ0EKgwoUHVwcGV0IFJ1YnkvT3BlblNT 17 | TCBJbnRlcm5hbCBDZXJ0aWZpY2F0ZTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ 18 | BAUwAwEB/zAdBgNVHQ4EFgQUbFDtfev3eTVf9i8IVmy9z8+SIUgwMQYDVR0jBCow 19 | KKEjpCEwHzEdMBsGA1UEAwwUUHVwcGV0IENBOiBleHBsb3Npdm+CAQEwDQYJKoZI 20 | hvcNAQELBQADggIBAATT5735CD4s/DKGIF/VqbE9L5dCFwiUMp3pJozdo+gM7gNb 21 | hqhYWPwWYslEt9F110sF/50BnmJtLxUOhnwklbvnvKIKnKph2tg6bofrPuV/3IET 22 | 4eDXIVuSic2V9tx+M/xQ/KRj2Coxhee4Y0VA+uP1Rx+BGMGbKLjseNPB/xJzhrRx 23 | 6t9PBDqKgu1ah7LzuANNJjI1c4Jr/r/113FUBg8IGxc9n9pUpG+cPU+ertroaQ3m 24 | iU68QQ/qPixHCd4X+iB0uy8pk+eO9jd+o6YwwmeU9qrKpIqRCUfM2VD0PRUW+nIN 25 | MC8oZs5r2Q7fTBGXcdLnW91DDXEGpX/WC1BYwLiiXUWFCQRbc1GyJa7IRiAkPCSc 26 | +uCCwRlvfGsTBcgfhALZhmTkOfQ+vBuotZfEIQ/noaG7ofSuCsrc+hfzh6iEdCWS 27 | GG3Uat3Z2fBH7uXhAdiqkRjqw+/M6HfPn6X4WKVp8GHHmZi8WJ0TQF5zhPaMPeix 28 | ViANR2MBrVzrYK389dd0U1GXYO0oSUQ3Skt+t4CEzwQGbILBtZMPovoi64Fcn4IT 29 | lKSlotvgphpoSdqMh+Qmgc2p7jsQwiojB7Gt+N3tcVr7J93iv9LPRDnwIq02AX2H 30 | Z7wQlzL/VqGD2Qa4RtL+xJfQEE6FO8yeQcfHBy6hb/wiL9Hz0GUlaMN7TWY+ 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certs/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFaTCCA1GgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xNzA4MDIxNjI4MTVaFw0yMjA4MDIxNjI4MTVa 4 | MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogZXhwbG9zaXZvMIICIjANBgkqhkiG9w0B 5 | AQEFAAOCAg8AMIICCgKCAgEA1Dd+K00k5OlIx/2Iw3reWBKg58t1o1PJw+Czz91a 6 | 8D3oxdbfdO7MA8kJL01AWpTiec4AO/grNe42NmDWQgd6hDi2r8lf86sS+vIo6nfI 7 | d3aYzho2wHYNT2g5/6rR5odpJXzIMJ6RriczuuZ7DVILoSH+jBU841gBJgFE9dxE 8 | ChHeRsN9H5tqrLsZ1AylPJ6vGvTy3MZrP9Kjtx0pef8gjhOL7h0Ab1t1ZZmHrXkL 9 | 6ikY1u6+4SeIqml/sNJtx0lG7cZtjmluWUpFIjEqpa1t3afVCTeF1he3RxPxM8gy 10 | V6JpOJm9q3qBUnaTEHIlbsnEooYsXQQXloLang4vXzaUuB7iu7OvLZeGfeeTfPhh 11 | FgJ0VxV6KUTHOoGpSLWchWr7CgXSo3s+Y4ixJL6bswQgtSlP51hlvTP+nag1J1ED 12 | Qsia+5c6erdOBl6tNfgu6GdqWYn8rjUsy9GWNNeP80M3IBX7V43nv8g7p2MyBZ7g 13 | 94uUMbi04jqLEUjDJXkjKKtL/4GJm+kprv1BPWejuwyW+1xUdNkKw6B9Z0bsPA8F 14 | Prjt34pRg8sk3ivu/g1ml6VrevZnaOulqWS/8QdPk0Vl0wtnsmBtluo3gir7I0LF 15 | SbLALnOw68SPwQkBys8Ajda9biovOOE3ZCoX3op802EA3x6yXcDVyiJV3OifQ6t4 16 | yqsCAwEAAaOBrzCBrDA3BglghkgBhvhCAQ0EKgwoUHVwcGV0IFJ1YnkvT3BlblNT 17 | TCBJbnRlcm5hbCBDZXJ0aWZpY2F0ZTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ 18 | BAUwAwEB/zAdBgNVHQ4EFgQUbFDtfev3eTVf9i8IVmy9z8+SIUgwMQYDVR0jBCow 19 | KKEjpCEwHzEdMBsGA1UEAwwUUHVwcGV0IENBOiBleHBsb3Npdm+CAQEwDQYJKoZI 20 | hvcNAQELBQADggIBAATT5735CD4s/DKGIF/VqbE9L5dCFwiUMp3pJozdo+gM7gNb 21 | hqhYWPwWYslEt9F110sF/50BnmJtLxUOhnwklbvnvKIKnKph2tg6bofrPuV/3IET 22 | 4eDXIVuSic2V9tx+M/xQ/KRj2Coxhee4Y0VA+uP1Rx+BGMGbKLjseNPB/xJzhrRx 23 | 6t9PBDqKgu1ah7LzuANNJjI1c4Jr/r/113FUBg8IGxc9n9pUpG+cPU+ertroaQ3m 24 | iU68QQ/qPixHCd4X+iB0uy8pk+eO9jd+o6YwwmeU9qrKpIqRCUfM2VD0PRUW+nIN 25 | MC8oZs5r2Q7fTBGXcdLnW91DDXEGpX/WC1BYwLiiXUWFCQRbc1GyJa7IRiAkPCSc 26 | +uCCwRlvfGsTBcgfhALZhmTkOfQ+vBuotZfEIQ/noaG7ofSuCsrc+hfzh6iEdCWS 27 | GG3Uat3Z2fBH7uXhAdiqkRjqw+/M6HfPn6X4WKVp8GHHmZi8WJ0TQF5zhPaMPeix 28 | ViANR2MBrVzrYK389dd0U1GXYO0oSUQ3Skt+t4CEzwQGbILBtZMPovoi64Fcn4IT 29 | lKSlotvgphpoSdqMh+Qmgc2p7jsQwiojB7Gt+N3tcVr7J93iv9LPRDnwIq02AX2H 30 | Z7wQlzL/VqGD2Qa4RtL+xJfQEE6FO8yeQcfHBy6hb/wiL9Hz0GUlaMN7TWY+ 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certification_requests/ca_test_client_with_old_exts.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIFQzCCAysCAQAwEjEQMA4GA1UEAwwHbXlhZ2VudDCCAiIwDQYJKoZIhvcNAQEB 3 | BQADggIPADCCAgoCggIBALuhlv8DukjVy1Qf109GH731LqHug6XdQakj+b8hZKTh 4 | Aj+1S+DOsA4O4MOVkQ/b1esnmrfDjDOqtQjcysJF2zNZbwdBBFe3zILOYWBcCssl 5 | GDnRu7tjlv9WxDyKjs+JU2+HJ1H7nxL56ep7pUTrInfyq+Ue1YUOb0cr14ncux1t 6 | gaoeTMswefMJAGxMcAMQ/Rbv+nAcaDVYS/+PHk9yp5/XxhRPzqQ+NfSyOmQA5wON 7 | ziCnIzar9ahl9XXqAnzdE1JxwPGJBefO+HYEYEHDAL41/cLBawCcPLd/ZJ+IYxjA 8 | zKBYP3OKOCBHvlijNIsUFLdyQMNIFQFsT3eiuHpY+H89lpc3fVyU3u6tIpRyaMhB 9 | 00NlwEBDhyMUbME/3u1WU+ZXlsGjTvszG2N1IDgIjYFwVTypmA4EFNmnonK+U9GT 10 | sgnFHNctung5QSIyKtJe+TeYioGxSbyKT7WKU540UGdk+xuYzxMkVk3HhutrA8bP 11 | uwXAMGqkv+1balDlEH3zjSoUHdQzS5ccdQAp41IaYl53S5Tf6G654rK68wdgQZRe 12 | ciG5N/zqCVZM/qiDTitba49JQUVyJ0JNkuWw5oIV+5Wdef4U1AYTgAERUbt7Nk0Z 13 | OC81bPOKLznvHu8rJWk/IAkRnUzlExscGOXT1II6Jj+JH9EdNGCq/8PVPz072jZl 14 | AgMBAAGggeswMwYJKoZIhvcNAQkHMSYTJDM0MnRoYmprdDgyMDk0eTB1dGhob3Iy 15 | ODlqbnF0aHBjMjI5MDCBswYJKoZIhvcNAQkOMYGlMIGiMDMGCysGAQQBgoxMAQEB 16 | BCRFRDgwMzc1MC1FM0M3LTQ0RjUtQkIwOC00MUEwNDQzM0ZFMkUwGwYLKwYBBAGC 17 | jEwBAQMEDG15X2FtaV9pbWFnZTAzBgsrBgEEAYKMTAEBBAQkMzQydGhiamt0ODIw 18 | OTR5MHV0aGhvcjI4OWpucXRocGMyMjkwMBkGCysGAQQBgoxMAQECBAoxMjM0NTY3 19 | ODkwMA0GCSqGSIb3DQEBCwUAA4ICAQBO6m58K19citPe/SOtETvw7q/l3YCXp+zL 20 | YmwvOuVhRKgqvzWDUWRgTpWEDYzTudzw6DuOyQwzEvOvetBbPOqsrz6RacTUBrfr 21 | WTJWPKkQuIN95VvMPhNn7D57MxXGiJrIIiNlSWm7eELcU79PcgKVPzQQG/kNlZj5 22 | iCwp6MeVmK8Lw+hZXjnnBKMj8iRlGgfFBbJIFqoU49OSBJyxavDiQ4V4ALlSntDa 23 | kst8liLXlSKLq6OgZBSSt/0rtlOEMxBKZ700kNCBbopQsL83mVJ6H+CrT/f6k8A9 24 | d0jB0pnko+7BNqh+iz1EnfMEGLLxBairYaBh6ti++AnMWafOV6bH9OmuHAAKnOcG 25 | nne05j8nP1HNnLmdZ95NLeDIOm7j/HadLQ/VD7PcwxzHtrXj6j5HZapBjj89bT8t 26 | p/U5Fo4Hq41yjHEUhpwgsnaHedFguGWvswwbqqKobN9vWTsuArz795yfy60i6Ejd 27 | I18/p4jr+zNmZLHffbaQVu9+NdCrDPd/q3j8Gjv+1fQmAmaqcpXbxQ6O+VNmuRUG 28 | p3VeKYAsIgnB3553k3DXWJlCCddcsTG9lVDF4SL+krBrBLErPzU5SZzycfzFq5UW 29 | MDwuaGnVK095GYp3OR0vmDIqua0yI3DBISCZhaGtS1e4DDACuHiuavHECAPyP/R5 30 | QY6sSSwKaA== 31 | -----END CERTIFICATE REQUEST----- 32 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certs/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFazCCA1OgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xNzA4MDIxNjI4MTZaFw0yMjA4MDIxNjI4MTZa 4 | MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 5 | AgoCggIBANn3WC9nYG60gF4Y5hFLqA/iUkHjqPO+hZJDQDCRZjp3Dy3mYLi9I0dQ 6 | WNJ9I49IxfK9KzvZDU2RlSKv8/TXeoHEeDRhBkB+tx8HuMVzh2se7pcl3pozMqpW 7 | VzoSj+4bmCKeg6fWkLsS5623u65/+rbfKWaM1IpxGCmN8hy7PXJCRQGc/0+bIDta 8 | Hqux8ekVL7OuttKdVPG5kraUL3aJtKurRcu9T1GpiLtDxVThwUfSBqjVuhYWngIn 9 | gMtwCwbR9f0ucdbrYjTkZuIQkhjeyk6BIyaAmjQamZzcvldtUQkWZA2GsiQMGYNp 10 | 59KfCwEiQ9oNy5BRJSPXFm2cBNYRgaQaRaEvlHrFcHULlnM4JLxpVwR6uu0KL4vZ 11 | phKA5YiGGn7ftXL9BIMhwlM2u1b7FiH5mVT7t5TUcZ6LtlgNeRFyggX2vBsYxjNn 12 | Go/X0a0xTAVKR8yJJotL4MG6Xvcx4kqH2XwVyQxl21i5WTbHzLbKL/8jXEIwX5/R 13 | tN+WC+/HyzXCXHsHU5IcTlURaMtAt0l+6Y2Z4FBuCMo0G0UG/tcABrMgxNJ1qaMl 14 | X2i/rUt+FgjuXm2Ghl0qqfCL2ooHYD7RBxO6+rLYA0rphhlvZQQPJ+p4RcLlYzHO 15 | bmXiTM9z0XDCSoPyZlogE6dbwDILqun/LKnXsdRtd3ndeipznwm1AgMBAAGjgbww 16 | gbkwNwYJYIZIAYb4QgENBCoMKFB1cHBldCBSdWJ5L09wZW5TU0wgSW50ZXJuYWwg 17 | Q2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUF 18 | BwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQxV/ZSr//hEAy2 19 | 6l0/Rbm2ws12NDAfBgNVHSMEGDAWgBRsUO196/d5NV/2LwhWbL3Pz5IhSDANBgkq 20 | hkiG9w0BAQsFAAOCAgEABfb/9YkmrlX0v8ROswCqf7AhJ3zrXn1o+QU7qRWO6yGj 21 | eVfNRDP1mN3xlp4p9o8gSpuPiPkWAXIV9p13twPZr95pjqBTJMuf4wN48mrKMA95 22 | kY3OzpidOUinweLUKLGYTnRRRx517uhoUZZV1itBEakWF3Ab+zY9JZns6J27xYZu 23 | +EXJa+L7w0reeiS/f4gzK9bUBH3WbP9Efa/GFk5zKK3NAi/0URxSuDyeaG9ub0Z2 24 | bECAkKYCK/XxY67jx+/6QanB4aLAJiLeOlCez9qcpmH61/26zCCPfPaTbl7xuVTe 25 | kTAhfdSGhO1PPZ75k7sSipL9JfprNSnZg6nPcT72qxc6l0lIJiQ6uGxYDtp0PwDQ 26 | wOuUbCbG3Qe+z6bPsBbNtI1nSrJqtZPbezx970I+0rlEztu4CjZvbcALfcipLLvd 27 | pq9j9k5yBmB23sq1Hj3zdPI5TezGKtIiEFwiIPZQ1QSwB829P7PQOE+/wrWmAUie 28 | cMij57ETLw+JRQ7F6xuAficOJFXiunp011Zg2BiTd5phV8MuiWpcrzyVIQKemdo4 29 | KPJ4B+mf1IvPkOCvnHwPueai/QNgx5v0k5UyaXUHuCZgYuATtn1LjM5Crsxka/OZ 30 | ctyUGY+0SN7L8URhbDbN3539dBL7ZBfPVlv3BEzrNRi8uXWrdTiV4cVaEyTWJ6Q= 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca/signed/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFazCCA1OgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xNzA4MDIxNjI4MTZaFw0yMjA4MDIxNjI4MTZa 4 | MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 5 | AgoCggIBANn3WC9nYG60gF4Y5hFLqA/iUkHjqPO+hZJDQDCRZjp3Dy3mYLi9I0dQ 6 | WNJ9I49IxfK9KzvZDU2RlSKv8/TXeoHEeDRhBkB+tx8HuMVzh2se7pcl3pozMqpW 7 | VzoSj+4bmCKeg6fWkLsS5623u65/+rbfKWaM1IpxGCmN8hy7PXJCRQGc/0+bIDta 8 | Hqux8ekVL7OuttKdVPG5kraUL3aJtKurRcu9T1GpiLtDxVThwUfSBqjVuhYWngIn 9 | gMtwCwbR9f0ucdbrYjTkZuIQkhjeyk6BIyaAmjQamZzcvldtUQkWZA2GsiQMGYNp 10 | 59KfCwEiQ9oNy5BRJSPXFm2cBNYRgaQaRaEvlHrFcHULlnM4JLxpVwR6uu0KL4vZ 11 | phKA5YiGGn7ftXL9BIMhwlM2u1b7FiH5mVT7t5TUcZ6LtlgNeRFyggX2vBsYxjNn 12 | Go/X0a0xTAVKR8yJJotL4MG6Xvcx4kqH2XwVyQxl21i5WTbHzLbKL/8jXEIwX5/R 13 | tN+WC+/HyzXCXHsHU5IcTlURaMtAt0l+6Y2Z4FBuCMo0G0UG/tcABrMgxNJ1qaMl 14 | X2i/rUt+FgjuXm2Ghl0qqfCL2ooHYD7RBxO6+rLYA0rphhlvZQQPJ+p4RcLlYzHO 15 | bmXiTM9z0XDCSoPyZlogE6dbwDILqun/LKnXsdRtd3ndeipznwm1AgMBAAGjgbww 16 | gbkwNwYJYIZIAYb4QgENBCoMKFB1cHBldCBSdWJ5L09wZW5TU0wgSW50ZXJuYWwg 17 | Q2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUF 18 | BwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQxV/ZSr//hEAy2 19 | 6l0/Rbm2ws12NDAfBgNVHSMEGDAWgBRsUO196/d5NV/2LwhWbL3Pz5IhSDANBgkq 20 | hkiG9w0BAQsFAAOCAgEABfb/9YkmrlX0v8ROswCqf7AhJ3zrXn1o+QU7qRWO6yGj 21 | eVfNRDP1mN3xlp4p9o8gSpuPiPkWAXIV9p13twPZr95pjqBTJMuf4wN48mrKMA95 22 | kY3OzpidOUinweLUKLGYTnRRRx517uhoUZZV1itBEakWF3Ab+zY9JZns6J27xYZu 23 | +EXJa+L7w0reeiS/f4gzK9bUBH3WbP9Efa/GFk5zKK3NAi/0URxSuDyeaG9ub0Z2 24 | bECAkKYCK/XxY67jx+/6QanB4aLAJiLeOlCez9qcpmH61/26zCCPfPaTbl7xuVTe 25 | kTAhfdSGhO1PPZ75k7sSipL9JfprNSnZg6nPcT72qxc6l0lIJiQ6uGxYDtp0PwDQ 26 | wOuUbCbG3Qe+z6bPsBbNtI1nSrJqtZPbezx970I+0rlEztu4CjZvbcALfcipLLvd 27 | pq9j9k5yBmB23sq1Hj3zdPI5TezGKtIiEFwiIPZQ1QSwB829P7PQOE+/wrWmAUie 28 | cMij57ETLw+JRQ7F6xuAficOJFXiunp011Zg2BiTd5phV8MuiWpcrzyVIQKemdo4 29 | KPJ4B+mf1IvPkOCvnHwPueai/QNgx5v0k5UyaXUHuCZgYuATtn1LjM5Crsxka/OZ 30 | ctyUGY+0SN7L8URhbDbN3539dBL7ZBfPVlv3BEzrNRi8uXWrdTiV4cVaEyTWJ6Q= 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certification_requests/ca_test_client_with_exts.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIFUjCCAzoCAQAwGTEXMBUGA1UEAwwOZmlyZWhvc2UtYWdlbnQwggIiMA0GCSqG 3 | SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwYX0/PV0Vre7bxfhLBTg+4y2w9YvAHYjr 4 | YL2Iu9fecIyUHu+rFMYiqLk1JlOLwFh9v2htmfNt8vpCRNlxepdq+k+xQcFIrjqF 5 | 4Yh/h4m56UWPZf0SlSarX72YskCw0a62pIr/UIsFMvLOnpCWsd6FejU6AgakBVDC 6 | Uom/Sor8y5h/EaKQZnUoIIxLW/9nGANUylo/AAtDPVmPO+HyFeJt2FvQDtEQgtvQ 7 | oq3GtgsoZFc5aDvbuuiwbAz6UxnSD5WwnN60Okcwb2/GPfOtu/LPw01xtYRF2WIA 8 | gIZdVg/DqIdNhS3sXytSSGnELyG2DLrw1Tra4Dx2sTLD/PGSvweyXNCPmZOigQp4 9 | z+qGHG8nIsrMh836YOMpJmAzrP1nfvdSdGq9zcA0q/1ZlJd78xLXcXNzrvxE6zax 10 | 4ljyOvCq271m+nnlWzNxvgF1V+Wz3Gwvo5gMEPPHEdou+Z+E2YgoDJG8q9AX81eG 11 | gkIg5JUyJ40lqQjkWTUFrXThSSOzV5VT4Pu87QbkdwZ/yemNOay9Tp/Z0wGZxdIO 12 | DeTuAqCbC+mo8aA66BSR/TBgLexXaHgWylw+XJqLMIo0wsrzpYbDl89CSr9SfKf5 13 | hQr1vsipLW8ygf/klQINuUx37IRAOS3c9bpdR97Tb6sOjz971fT8jlS00djFPIHs 14 | XBYBlFHstwIDAQABoIHzMDMGCSqGSIb3DQEJBzEmEyQzNDJ0aGJqa3Q4MjA5NHkw 15 | dXRoaG9yMjg5am5xdGhwYzIyOTAwgbsGCSqGSIb3DQEJDjGBrTCBqjA1BgsrBgEE 16 | AYKMTAEBAQQmDCRFRDgwMzc1MC1FM0M3LTQ0RjUtQkIwOC00MUEwNDQzM0ZFMkUw 17 | HQYLKwYBBAGCjEwBAQMEDgwMbXlfYW1pX2ltYWdlMDUGCysGAQQBgoxMAQEEBCYM 18 | JDM0MnRoYmprdDgyMDk0eTB1dGhob3IyODlqbnF0aHBjMjI5MDAbBgsrBgEEAYKM 19 | TAEBAgQMDAoxMjM0NTY3ODkwMA0GCSqGSIb3DQEBCwUAA4ICAQBpI2GtsKLc8uNp 20 | oqmz/pbcjgKUuY1xITK1OfID5baGHJIfHVsfEVBy7J4k7AknOb74T0OM/mOOLzQg 21 | /64/GY6hnUrG6QScwTAcKZ70gHOw/2hOXK7LplDIz9Tb5latrFDFrtvvFFN8BPuH 22 | 555smAUtWLfpujFIlXom/YfuoDqc1HKDgtiuraY9juBjWTwMe5hLAqJq5OfNEZP6 23 | p0c1lotjH65mt7Hn9maU/nTOX9SWEXaZjrRA/6i3r89Sy4DJN8IRgPZOmGRYsKxF 24 | G1XSrRyqzxmaZNVVu9fjhDsguXJsPjKabjW27e9K5r5tmjgp2dZMqUSW67Y/vknB 25 | BVg38RNh+gE8nHwNxUSLafsiimIcDT8yf6dzmCA5NC0EAokNiHQ1GI+U30ml+X2e 26 | Epmvbnv4dgv+Eh/33bhWSwryCxicTqtNs7PESy7Y7xohp8k+GL74WQSYxSNibwDa 27 | Mr2vIJ+ubAXlUDWmaz6jvJLXpK/pGwRF8MFHAOBrHVwU+AWV0FAlVOxk7Ad5+nK4 28 | Xt42/oA+dOY4WXcrMvbvX8OWlSKVyAxUEki1g0wCu6VQoH2bmvfR9TkogfLBD0mq 29 | cAPZ2wky6N6J4OW89+1jQ1LZz3ojfiANZ5ExFiYi/5zvaJxgeFKOFq8Qd/Tise04 30 | viqte29t+CbFyPaXhD7rKHGuYX30uw== 31 | -----END CERTIFICATE REQUEST----- 32 | -------------------------------------------------------------------------------- /.github/workflows/mend.yml: -------------------------------------------------------------------------------- 1 | name: mend_scan 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: connect_twingate 12 | uses: twingate/github-action@v1 13 | with: 14 | service-key: ${{ secrets.TWINGATE_PUBLIC_REPO_KEY }} 15 | - name: checkout repo content 16 | uses: actions/checkout@v2 # checkout the repository content to github runner. 17 | with: 18 | fetch-depth: 1 19 | # install java which is required for mend and clojure 20 | - name: setup java 21 | uses: actions/setup-java@v3 22 | with: 23 | distribution: temurin 24 | java-version: 17 25 | # install clojure tools 26 | - name: Install Clojure tools 27 | uses: DeLaGuardo/setup-clojure@10.1 28 | with: 29 | # Install just one or all simultaneously 30 | # The value must indicate a particular version of the tool, or use 'latest' 31 | # to always provision the latest version 32 | cli: latest # Clojure CLI based on tools.deps 33 | lein: latest # Leiningen 34 | boot: latest # Boot.clj 35 | bb: latest # Babashka 36 | clj-kondo: latest # Clj-kondo 37 | cljstyle: latest # cljstyle 38 | zprint: latest # zprint 39 | # run lein gen 40 | - name: create pom.xml 41 | run: lein pom 42 | # download mend 43 | - name: download_mend 44 | run: curl -o wss-unified-agent.jar https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar 45 | - name: run mend 46 | run: env WS_INCLUDES=pom.xml java -jar wss-unified-agent.jar 47 | env: 48 | WS_APIKEY: ${{ secrets.MEND_API_KEY }} 49 | WS_WSS_URL: https://saas-eu.whitesourcesoftware.com/agent 50 | WS_USERKEY: ${{ secrets.MEND_TOKEN }} 51 | WS_PRODUCTNAME: Puppet Enterprise 52 | WS_PROJECTNAME: ${{ github.event.repository.name }} 53 | WS_FILESYSTEMSCAN: true 54 | WS_CHECKPOLICIES: true 55 | WS_FORCEUPDATE: true 56 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certs/cert_with_old_exts.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGCzCCA/OgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNDA2MDkyMjU3NDlaFw0xOTA2MDkyMjU3NDla 4 | MBIxEDAOBgNVBAMMB215YWdlbnQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK 5 | AoICAQDN7qadIwjVC9sSSVvJzZwJIfhMNre85ScbJuyVroeEDrDtKiYha4VGmURF 6 | xDzKqOjiL0hoK7QDHkDKj2ykKjqP5urX0h4qDxm7n9JtSmJ3atwD9dUm2UgeevhR 7 | v+7WFIi6mlsrckIaQoZHuSAZ/jdJsXvDv452PnCbwrAwLnePU3HkjK8lEFoNt1RP 8 | hohD2dANWQLaDVqw1B8FCh7c+2HjeyvBVW4j0MGqgQmAn818eyJNAZTE2aL3nerO 9 | 5jFORGa4nO0nn4YOkXkSvNfOU2+R7iSI6txTPi00ZfSrr/qtJFXy1bs1BnDjNrq8 10 | z/4m/W6dtLrUFeDPhxrnJDxEvGW+NIHeZ5mO4eF91Zg8GQZlU2L/0qKALik7iqgY 11 | 5wXrdBtfff20PRCjSZn6taa7eCB/7oU7hJttIbz11kxqLGbyfVA6sbX+3vSNuDVJ 12 | WykjznL1JTntDJNDFVBxkBhDMYKuT7g4C7kccbVP8fqw3cBxWZt325FAzp16VNqb 13 | NZXg7VZ9I3sDBcvn919YbVljhjj5vK3DhfJvgmcB849W4QzLUGQGXnZrDXA/gdm6 14 | qItHR7/Ku8gTqkOj6V6bCMWz92LaeakCiqk67xvED6uiV2yqy15xu6bhn0pdW6RZ 15 | lowRXuydfGLUlPjnEjD88peFkrOsbYMf0S7gJe+z+MJHdBswsQIDAQABo4IBXTCC 16 | AVkwNQYJYIZIAYb4QgENBChQdXBwZXQgUnVieS9PcGVuU1NMIEludGVybmFsIENl 17 | cnRpZmljYXRlMDMGCysGAQQBgoxMAQEBBCRFRDgwMzc1MC1FM0M3LTQ0RjUtQkIw 18 | OC00MUEwNDQzM0ZFMkUwGwYLKwYBBAGCjEwBAQMEDG15X2FtaV9pbWFnZTAzBgsr 19 | BgEEAYKMTAEBBAQkMzQydGhiamt0ODIwOTR5MHV0aGhvcjI4OWpucXRocGMyMjkw 20 | MBkGCysGAQQBgoxMAQECBAoxMjM0NTY3ODkwMA4GA1UdDwEB/wQEAwIFoDAgBgNV 21 | HSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNV 22 | HQ4EFgQUPHnmMHX+cpxZkYJuzENWb0dEzncwHwYDVR0jBBgwFoAUL/eJxsQyqTkO 23 | KB04HOV9w5a+ssQwDQYJKoZIhvcNAQELBQADggIBACn/ghcqlo3gq2BxwTP+YLGd 24 | DVMPdeUhvMfcZzbTJiFhelIEcFUR2zFhPg/X0RdmVM+cM+eeM81Kn0EJwRBmVOE9 25 | 0YISM8Llr8ujIPJFgRcD6kwDsetKEFQhADEJtpBb2pRuB5RB7zi8xGPcU/ZyL2JV 26 | 4USHDThNKNexbHiSrBVMGxPCK9psW5nOZBeY4TACjsue2seFoQg99/nurHHsTSfx 27 | Lwqag3/8WBNufx++vqyqwz8gIIzXH44yiGPmhbEgaiXOQYvFggXEZ4eXxHYcbHWo 28 | Uj2DgWgvZgivzVG6Pvs84hgnHFjtrUAIdrW67J510BFqgpi8akg5ogsDF7+Xoo/i 29 | c+uayPEIzrb53hiGQPNjaqDtuZ6VTHeOk+u5NbUBOzCPNoDlbYD+zKNX/lvays/V 30 | ZOHkNvmXEaGqIRpMDq3IwpYLh92/Yxyykl81ofygqVlOhm7cIPm/D3S6fN5Vorlq 31 | NbE60J/fdctaY2ND8dWlgXtd9ev88DvElwUqY2neULZqEaGSu8JovuGsAGgoCYyR 32 | quIjgTDBCk/y2CGSitAJhLQUu+2+yG/eFB9TO7vu/3+j5ZaFLT8e/jbRWXB9+dD+ 33 | VM+34JOdo3hcNFUqIeOV+eI/fkK7etTXSSySB8r034xDWlWoLKxdfdjNyKUY/USz 34 | tBmyXcHO0I/nucSdPZoJ 35 | -----END CERTIFICATE----- 36 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certs/cert_with_exts.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGHDCCBASgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGxvY2FsaG9zdDAeFw0xNTAxMjUyMjAzMDBaFw0yMDAxMjUyMjAzMDBa 4 | MBkxFzAVBgNVBAMMDmZpcmVob3NlLWFnZW50MIICIjANBgkqhkiG9w0BAQEFAAOC 5 | Ag8AMIICCgKCAgEAsGF9Pz1dFa3u28X4SwU4PuMtsPWLwB2I62C9iLvX3nCMlB7v 6 | qxTGIqi5NSZTi8BYfb9obZnzbfL6QkTZcXqXavpPsUHBSK46heGIf4eJuelFj2X9 7 | EpUmq1+9mLJAsNGutqSK/1CLBTLyzp6QlrHehXo1OgIGpAVQwlKJv0qK/MuYfxGi 8 | kGZ1KCCMS1v/ZxgDVMpaPwALQz1Zjzvh8hXibdhb0A7REILb0KKtxrYLKGRXOWg7 9 | 27rosGwM+lMZ0g+VsJzetDpHMG9vxj3zrbvyz8NNcbWERdliAICGXVYPw6iHTYUt 10 | 7F8rUkhpxC8htgy68NU62uA8drEyw/zxkr8HslzQj5mTooEKeM/qhhxvJyLKzIfN 11 | +mDjKSZgM6z9Z373UnRqvc3ANKv9WZSXe/MS13Fzc678ROs2seJY8jrwqtu9Zvp5 12 | 5Vszcb4BdVfls9xsL6OYDBDzxxHaLvmfhNmIKAyRvKvQF/NXhoJCIOSVMieNJakI 13 | 5Fk1Ba104Ukjs1eVU+D7vO0G5HcGf8npjTmsvU6f2dMBmcXSDg3k7gKgmwvpqPGg 14 | OugUkf0wYC3sV2h4FspcPlyaizCKNMLK86WGw5fPQkq/Unyn+YUK9b7IqS1vMoH/ 15 | 5JUCDblMd+yEQDkt3PW6XUfe02+rDo8/e9X0/I5UtNHYxTyB7FwWAZRR7LcCAwEA 16 | AaOCAWcwggFjMDcGCWCGSAGG+EIBDQQqDChQdXBwZXQgUnVieS9PcGVuU1NMIElu 17 | dGVybmFsIENlcnRpZmljYXRlMDUGCysGAQQBgoxMAQEBBCYMJEVEODAzNzUwLUUz 18 | QzctNDRGNS1CQjA4LTQxQTA0NDMzRkUyRTAdBgsrBgEEAYKMTAEBAwQODAxteV9h 19 | bWlfaW1hZ2UwNQYLKwYBBAGCjEwBAQQEJgwkMzQydGhiamt0ODIwOTR5MHV0aGhv 20 | cjI4OWpucXRocGMyMjkwMBsGCysGAQQBgoxMAQECBAwMCjEyMzQ1Njc4OTAwDgYD 21 | VR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM 22 | BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvteXSSCCW4B6Fsv2Csm12XQ7RiDAfBgNV 23 | HSMEGDAWgBQ7xKznNsTROtlYOQrez2TxrM16GzANBgkqhkiG9w0BAQsFAAOCAgEA 24 | bGkRukJkWxit505VXRLilvLLQT1nVxs7DKb0oS0sn2A5aXfGSPGMsgo+jVbQSS54 25 | 5pCrMoPx3PL3R3rwWNkuXn1HRmlpbmGGzryL+iSdKqUWnnNDcQs+b4e4ULLZ/qIc 26 | HCOmr0Wl7fOnfj81viU27hCCS17qKskeyGZ0tIsVJpxgu0JLNKjGVkUyv/EMyDKj 27 | 2kZbWSHtGNKDUKuRasbWobVbXCNQCYp3Yr1anUywBsb8ozW91EwSgqKeabO6lcgF 28 | s46ekUlRTrlLAFevVoJzA6o2gBBNPItEAyY0tndaIppYub20fOUQ26YdZvCapgp0 29 | 1dHr5XmoM+itGecVaCp+pwZ+2jcl96K1U8ae35LQYvBTvlKM2gROHmVpEL4rTr0h 30 | jRls2vAuWsh3umONuD1Yfd7WqQd5QLrATd5ojkpzyBJFCCnI+zt29R5+bTPDkqNB 31 | hMy3J++yE3WqV0wouHNTzS90YUHJ/Z8fR99Fmt3+DaJdQ073bEQKfjtn7+n09RKX 32 | G6RaFyhFmS3Nn5ZulWTcQx+Wiu2pS7CyyRp66nSyNA0mnx2LZJ3M6F8iNOVG33Ie 33 | VbVG24AXQ6xTVtTsP48Z0vk2aXXG9NYO5jrt5EjzCU28HXh2iYN99qadlMI+slI7 34 | 83/06PghjLXC9WmNfuXbC58YDiY49fgycAGx9aPdUAA= 35 | -----END CERTIFICATE----- 36 | -------------------------------------------------------------------------------- /test/puppetlabs/ssl_utils/simple_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.ssl-utils.simple-test 2 | (:require [clojure.test :refer :all] 3 | [puppetlabs.ssl-utils.simple :as simple] 4 | [puppetlabs.ssl-utils.core :as ssl-utils]) 5 | (:import (java.io ByteArrayOutputStream ByteArrayInputStream))) 6 | 7 | (defn roundtrip-pem 8 | [to-pem-fn from-pem-fn obj] 9 | (let [outstream (ByteArrayOutputStream.)] 10 | (to-pem-fn obj outstream) 11 | (let [instream (ByteArrayInputStream. (.toByteArray outstream))] 12 | (from-pem-fn instream)))) 13 | 14 | (deftest basic-ca-cert-crl-test 15 | (testing "Can generate a valid CA cert, cert, and CRL through simple API" 16 | (let [ca-cert (simple/gen-self-signed-cert "ca" 1 {} true) 17 | cert (simple/gen-cert "foo.localdomain" ca-cert 2) 18 | crl (simple/gen-crl ca-cert) 19 | read-ca-cert (roundtrip-pem ssl-utils/cert->pem! ssl-utils/pem->cert (:cert ca-cert)) 20 | read-cert (roundtrip-pem ssl-utils/cert->pem! ssl-utils/pem->cert (:cert cert)) 21 | read-crl (roundtrip-pem ssl-utils/crl->pem! ssl-utils/pem->crl crl)] 22 | (is (ssl-utils/certificate? read-ca-cert)) 23 | (is (ssl-utils/certificate? read-cert)) 24 | (is (ssl-utils/certificate-revocation-list? read-crl)) 25 | (is (= "ca" (ssl-utils/get-cn-from-x509-certificate read-ca-cert))) 26 | (is (= "foo.localdomain" (ssl-utils/get-cn-from-x509-certificate read-cert))) 27 | (is (= "ca" (ssl-utils/get-cn-from-x500-principal (.getIssuerX500Principal read-cert)))) 28 | (is (= "ca" (ssl-utils/get-cn-from-x500-principal (.getIssuerX500Principal read-crl))))))) 29 | 30 | (deftest optional-parameters-test 31 | (testing "Can specify keylength when generating a certificate" 32 | (let [cacert (simple/gen-self-signed-cert "CA" 0) 33 | cert (simple/gen-cert "foo" cacert 1 {:keylength 512})] 34 | (is (= simple/default-keylength (ssl-utils/keylength (:public-key cacert)))) 35 | (is (= simple/default-keylength (ssl-utils/keylength (:private-key cacert)))) 36 | (is (= 512 (ssl-utils/keylength (:public-key cert)))) 37 | (is (= 512 (ssl-utils/keylength (:private-key cert)))))) 38 | (testing "Can specify extensions when generating a certificate" 39 | (let [extensions [(ssl-utils/subject-dns-alt-names ["bar" "baz"] false)] 40 | cacert (simple/gen-self-signed-cert "CA" 0) 41 | cert (simple/gen-cert "foo" cacert 1 {:extensions extensions})] 42 | (is (= [] (ssl-utils/get-extensions (:cert cacert)))) 43 | (is (= ["bar" "baz"] (ssl-utils/get-subject-dns-alt-names (:cert cert))))))) 44 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/4-crl-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 3 | ZSBDQSAxFw0yMTA1MDMyMDE3NDdaFw0yNjA1MDMyMDE3NDdaoC8wLTAfBgNVHSME 4 | GDAWgBS4+q81U1SALApa6n0SKT60dKN9qjAKBgNVHRQEAwIBADANBgkqhkiG9w0B 5 | AQsFAAOCAQEAP1bubYtfvEsLzLw7gl4lqHiVlT7iaSqxjsxm7cL9qB41nPnwSloG 6 | 6EovLEo4doPdgQV1Zuc0hfSHC4afnziua54NNZ+VVhmi2UbtozzvfxyZ4eevujEi 7 | dQ1V53hrP3TPatj3e018LOlMUrUkifhEPllQrWbAuGwddpxnaeni57BKjX4NYgYm 8 | BsJZIvLvMRG8BMfgoITkKVr4yfoc0wRN563rD96xpT4Obl0fv3zw4+zA5tt8QfKP 9 | t/q6vfg1IIMCyze3AgTOzKCCqhAJFWsxeg0m/+rx9YlBCwJjyMMRSxans1DRzwpK 10 | vBrKGFyV3Hdx8mDtVmfVBG4Umws3E8xqlQ== 11 | -----END X509 CRL----- 12 | -----BEGIN X509 CRL----- 13 | MIICmTCBggIBATANBgkqhkiG9w0BAQUFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 14 | IGV4cGxvc2l2bxcNMTcwODAzMTYyODE0WhcNMjIwODAyMTYyODE1WqAvMC0wHwYD 15 | VR0jBBgwFoAUbFDtfev3eTVf9i8IVmy9z8+SIUgwCgYDVR0UBAMCAQAwDQYJKoZI 16 | hvcNAQEFBQADggIBAJZ0oKDUJVyvDjPqSt7Kz6KpBFOFB+SiDdJhBzmV0roAirRu 17 | wAvS71eLgkM6ggtv5q5TCVEyQW0I5u3Oa2u0cMzO0zsw3nEnXO1kW6gZACf/D5VM 18 | uxdeQvCWkNzkUhZ57dWlKlZYV1FvA5JEaSUh6y3oMaeH6gvW/qulvr7auxgpLM+O 19 | IXW/i5jmvsOWRC22pfOrNjMH22x2p9ws3AX4vS+ff1iVvCxSF1Vy2z4lrXK7XmNM 20 | iRhlBQjLexfFRW9ijRkUx7jexthchfqwAc9l7WxkTSqqDwk7COrwrghF12um9RVD 21 | 1Z00HHyKhA6NIsMMteoAvkXX5J4qtIl68Nkrq4BNsgCtAKxpCdJz0ka61vbSyl/N 22 | FHt8N+fHDJv/t6No82H3yAGTWoK6mEh8XiVB9SyCAJbBwDQ86wJNDGKikiwHkUAJ 23 | qsoeQnDACqIl4+1lIOgyq+CczpKVaXRvWf4lLstQ66qEr9XJRIy1FjiKGora5HF8 24 | S+QvrASGzbMqKF57RqVAaflZexmxi1lJ/xF01yFTWxtmksm9lN4X11oysj3z0naT 25 | UKMW2xZmN6Y4CjjgxHLZTscWH/cJWReVEQr8g7mkyYz+4j8iNKmg8aiDmhCs/J0r 26 | gLzhG0uO3dsXg0ANZGxyWtrRaSjB7ALEPHP4kZ9tuRXPGE8XWWxmOvbfxxJK 27 | -----END X509 CRL----- 28 | -----BEGIN X509 CRL----- 29 | MIIBlTB/AgEBMA0GCSqGSIb3DQEBCwUAMBwxGjAYBgNVBAMMEUludGVybWVkaWF0 30 | ZSBDQSAyFw0yMTA1MDMyMDE3NDRaFw0yNjA1MDMyMDE3NDRaoC8wLTAfBgNVHSME 31 | GDAWgBTac952FxGfhUaIhusQD/GIbx5knDAKBgNVHRQEAwIBADANBgkqhkiG9w0B 32 | AQsFAAOCAQEAQcRtEHND8gFdmoMLS0EC+6Hx2vRHWtPYZRlQxxAJuf9Wj3uWJ1qL 33 | OCA62Yr1ZDClliRHWjk/kors5JGl3HD+k5CWPNO2oytI1cUy6x/9I+eK8//fZbE0 34 | vrR1wYgEtAwBxLa/eOPVgm/Y0d45b7GdUoSJZCO07KS6VvMC5V4ZxhwyErj8iIRa 35 | ztzgU/rWExDFvdK2RAjEe+Tzw4a7sxd0/RIAaFJZF+FEKEaX7MFNfQZ8vUgd7K2g 36 | 8TmlBMg3DksHLnDT5r4zpsPvrBcjP/NYf/42p5LeaZG7otFPP5I0tD1+uXWM72AB 37 | ygvxpZQkG+xro5sU4P9DEO5uBPhhaceTfQ== 38 | -----END X509 CRL----- 39 | -----BEGIN X509 CRL----- 40 | MIIBizB1AgEBMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNVBAMTB1Jvb3QgQ0EXDTIx 41 | MDUwMzIwMTc0M1oXDTI2MDUwMzIwMTc0M1qgLzAtMB8GA1UdIwQYMBaAFHx1U1ZP 42 | RR89jsP80QcF41C/jifvMAoGA1UdFAQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQAq 43 | C/WCvBHbzwW5+vRvW3TuX1iK7JUJt1JHVLIevy32g4I8ZQ7+EZHIAr9Gzg2eed2/ 44 | vIg9Tg6KYGtPVb6QqGDan17lwYPnu3gm14QAU3pqmLtev0SPKefSqp08dnk3JMTP 45 | fYVvjXBoGCJCCLLz3eqUWlQS+aL2sSXwppJk4ADi3lOfEQYwQMQ/ljw4zc0Ss+v4 46 | GrilMx//BstCgTmk96NaTFcT+klMlUAUiHyxMfaXCaHfEOAwiYb2I4S3Jwy4jqNB 47 | 6Gj/n8h0bTT32g5SFLJZEUv1sQ2XNKkofObx8EscE4himUSuhz8vw+hKhzG50iWG 48 | 2WIxGnoNC0IDubSk0wZa 49 | -----END X509 CRL----- 50 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca/ca_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/private_keys/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/ca/ca_key_pkcs8.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | aIF9f5b1wyjrF0yDufb43y2uDb0a 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/3-cert-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDJTCCAg2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFJbnRl 3 | cm1lZGlhdGUgQ0EgMjAeFw0yMTA1MDIyMDE3NDdaFw0yNjA1MDMyMDE3NDdaMBwx 4 | GjAYBgNVBAMMEUludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOC 5 | AQ8AMIIBCgKCAQEAmTP8DNDXm9M1anRkkvgh5kLlZY9KAXGF6Hx3YPFXzc7sZhXE 6 | WQeCz2gc66p3iPIaBpS0E4J/oD+XIP0IdmaYNxsIDr0/uA/w+g9A5QdzU8z3Djbs 7 | guJF5EJiLyixfqfF67DS4/4nCNSJ2ROkYNWct5CBXuoW512ynF9fsH5rfNO6rOV5 8 | og65EuBeWvIhXqARnb/BWI43s41AQ0qcAxz2rdB178fd6uhZ1q0Qss5JdDW/5xru 9 | pTzJGHLyw+BHc0crvj/U1FAH3pF8QRqdEvXecCEscISrvQgAySBBl98+IUyeOlnX 10 | 4L/Wrbdc7ajPSNpEoWcFsvWE7YqoD9IGnQHUvQIDAQABo3IwcDAuBgNVHSMEJzAl 11 | oSCkHjAcMRowGAYDVQQDDBFJbnRlcm1lZGlhdGUgQ0EgMYIBATAdBgNVHQ4EFgQU 12 | uPqvNVNUgCwKWup9Eik+tHSjfaowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E 13 | BAMCAQYwDQYJKoZIhvcNAQELBQADggEBALKZSjyRvUWskrjyj+rdgK/sMq/OQcuR 14 | kJRzT2sXWLCZ1BTcMS09AACy9BpJtA5EZQh6aZIsLb7cxvliO6+ps6Z1QPkefAlE 15 | 5SqWWB2B56+Yn/HHwfDbiYdlAM9v5ffZvvp4z8ozunGU4PO7Pje+qOM/ODykXQ59 16 | o0J0I4iyE0obE8uirQrgTTLatRc97nzlCf3RDWBpre6Djq0lDU7Akq9o9zrScGmJ 17 | msePmjQwCQ4C+SyyZ8ra/hWLR+N9QbNLQCHkK7xr+tJAQY/OrGm7rD3GevGL+q/k 18 | 6ue94kcvkB8uhJt8go5Bd29uPbZhWrVPH85tiweqs07N1nuDjgDN1tM= 19 | -----END CERTIFICATE----- 20 | -----BEGIN CERTIFICATE----- 21 | MIIDGzCCAgOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 22 | IENBMB4XDTIxMDUwMjIwMTc0NFoXDTI2MDUwMzIwMTc0NFowHDEaMBgGA1UEAwwR 23 | SW50ZXJtZWRpYXRlIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 24 | AQDGQAug1H2NbhXPNc2hvUrVLz6ZhtmRZ7h4+IIP6cMcgRlvhJhs/oRfg+f+Zv7p 25 | 7si9d6bS2Ffz0wNvzctq2nENJ7VJf5eHFXHoG9ctVZZSu6c9ze2Yvd9DrJMSyEwM 26 | OpBU/rKX6wHW5Z/9py53evn4fjTcA2jOzZzkn9MAiLncwHgFsKJ5fyWRAYHyHfE0 27 | +zHfYFvtoktiNRbfUX4hT4cxWKz0ZUYhBO20C08Wqr4xYvMR/Y2i9dBgt/D0wpA1 28 | tiVFrCUi3/LmSJjAgUPfRhIV3bRvsPlargpXZ103OTCj3n9gn0eN0rsnhBD1paxl 29 | jKxqIDPRNyXTO0+nxOCk3R63AgMBAAGjcjBwMC4GA1UdIwQnMCWhIKQeMBwxGjAY 30 | BgNVBAMMEUludGVybWVkaWF0ZSBDQSAyggECMB0GA1UdDgQWBBTac952FxGfhUaI 31 | husQD/GIbx5knDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkq 32 | hkiG9w0BAQsFAAOCAQEAYEJCoYLuGjYA0J8g5WhuU9oSdG7Sf1KLq1iP9KAoSBVD 33 | VM4SXAdv+8KaD3hm7wxQaK1ouc5fiSLSDj7juA8g0JCaDHuUxGdgeTNHdAcl+u/A 34 | ZZfH3qWISSAhSRQRRyG78FMUW6Gj/ltsKV3s62kFMy7lpNuCL8XMOoHpdMlP0NGh 35 | 3p8hli933hBJMqlrYSOqPC8ft/u5QBA885CU4QjobchfWwZqdEPCPoKY/xaRh98s 36 | lwQfVAFyRNMZSrhq5ZNX+Bfx69X4Csa0PoI9ONrNQ0Sr5aRVKiYkCdssVTYY9SA9 37 | 9GmcBEafm5Bojh0Bij5prpXGcDorLvpw4Iubj1hgXA== 38 | -----END CERTIFICATE----- 39 | -----BEGIN CERTIFICATE----- 40 | MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v 41 | dCBDQTAeFw0yMTA1MDIyMDE3NDNaFw0yNjA1MDMyMDE3NDNaMBIxEDAOBgNVBAMM 42 | B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCMJLo9EVvz 43 | zwbTh4RmVngzYSu2IlGakBvQXRunboh8TITWwHaUMC4VK5iqtfm4n30BgAn1Kn3G 44 | nyauoPz8W0DJB9e8aOZSsGT3rvdSFVndOkGbp/mmtl36OkMu2CiOUH7mtUJJs101 45 | VLebngx81QPpTHBhD5FiA6Kl8PlDiIf28ntZuSfMLeTV5FCzam/eCLTyuVgTreSg 46 | ywgctyylFjJDmpEVGYo0YNnNettpVGH0OgUAQuQi5sv/ml2/5/a5n9dj7IIlK4bp 47 | bMdqbsVlKq2Q7AVeoF3Ip1MY31WT1fKHFPsLzXR4uxrpvWEPc2WEyIBUkQHJmv5s 48 | xzRU61vISzd9AgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv 49 | b3QgQ0GCAgKaMB0GA1UdDgQWBBR8dVNWT0UfPY7D/NEHBeNQv44n7zAPBgNVHRMB 50 | Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAMJ8b 51 | sCSyzjG/5IJLW0m7vgUM5VaOkVfLD5v8jnwbd2F+7toyB5yReq2QCqEGRLsbh5of 52 | pbQvOwKpETOzDygzEli4cWhfyX9CUrFMmFUz6lNjC1Fn6pui2uReeFAn/MhVrcGD 53 | aO4J5IlmuG/Zr59bP2YoTRAmw0+w6oKEXfRWyPMiJwd541ZCEBu1HIgjT4Me2KXn 54 | S4vGSv8hkWj4LJ5gKavQ6HGkuT1oxE1a9dsVgjHjNiu+h7SkN/mGLX0S8wI4oOa0 55 | qfjFrrRbXnbi5+/Q8FiXAw0jlJ/3tcG6EHlcDc707bI6dDnkhyLATeVQrbJvG96b 56 | KLSyP2r4RAYWBfii/A== 57 | -----END CERTIFICATE----- 58 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/other-3-cert-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDJTCCAg2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFJbnRl 3 | cm1lZGlhdGUgQ0EgMjAeFw0yMTA1MDIyMTEwNTVaFw0yNjA1MDMyMTEwNTVaMBwx 4 | GjAYBgNVBAMMEUludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOC 5 | AQ8AMIIBCgKCAQEAwljoBCJsm5yCD9fVGNljtBkWXKvZ/X3PyP0ZW/mAXGVZ7irO 6 | xy+0KLGShKlzPWTkgy61gyQOMid7v7CAWLxP6yunNRTdz4zNQ7gAWb5UKvs3OOBl 7 | z+83kuxvn5m56l5RKcSzm62qC6FzIxQ1dmlxVD3SjAOl6P74VVQ4gTt7arVYvi/L 8 | eqz4if0+R/19iXYVLPdfKqNqV+nQ17cD9U1aHWm5O9V/y8wXpdq69hbkb2O94QeN 9 | JfRB4zcWpedMw71m4DZ395HmULYSNfZj6iF3grhlEskp/0lZpuPHsmwn8d/uJo9W 10 | pXxx4rS2VMoEjjyJWEMFjF60FB3olbkD8afcJQIDAQABo3IwcDAuBgNVHSMEJzAl 11 | oSCkHjAcMRowGAYDVQQDDBFJbnRlcm1lZGlhdGUgQ0EgMYIBATAdBgNVHQ4EFgQU 12 | jxIj8b+r+NYOqiZ4EUzn4g05iLkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E 13 | BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAJohYddveuE+8wJ6KLIhw35FrXfT3MKH 14 | rjAQQKdIEdcz3xxhOtqucCF3W2ABbotki6bzU2026ML7VPBy+4A+6vNr3ADB6jdC 15 | IiQlM1WpmPiC3cX7MHkLkEAQzr8WVWRG7Pf4mPdxrvymYBvzPi2mFsHKw4ER6wDe 16 | GDypumHXRYR6xnRcoi+FJ72ybVDsMxC/P8hnzurzQxJQRd+BNa4Ik4thM2fq2Od1 17 | QrUTvdZSFNJvb+wnySEp+qVsSgBdeOzJ9dL8/KpA/RoJSsF6GDyQw2mYc4xtKXX7 18 | PDjlY3NOoQ325OE1+slb/yik8KJy7pe0nL2sM+fe4N0tyVuL7SNDT5Q= 19 | -----END CERTIFICATE----- 20 | -----BEGIN CERTIFICATE----- 21 | MIIDGzCCAgOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 22 | IENBMB4XDTIxMDUwMjIxMTA1NVoXDTI2MDUwMzIxMTA1NVowHDEaMBgGA1UEAwwR 23 | SW50ZXJtZWRpYXRlIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 24 | AQDJMoUTSvssZPEnSbX1UYxpXBVsvkDJo2OdpP+4g38UFun423dV7zxjd1+ZCmtj 25 | uc6Hj0MH1AuKhY4D1k4eXpswFAxkaYNQanhJkg9T6VxwU/0+WAJqeTKtL0qg15Dc 26 | GpeWQojaqtm1DUQvcgu3sRz9Jsj/r1ePvCbHlWkiFfZF9RXD6GEjr20xliPN5z2o 27 | cjF0U38jyoP4Il4CMu1ymNcq8c9uAA0m5M+zP0AxJg7IwfnUiTjhibOazJLqhrLE 28 | /RavdA7GZia9YtgwP5ZNPzDE6JPI00MPEjVH1mMChyeG0/IcBkVnm7bsi6wW8x/R 29 | 5Qr78dyB2JfYb6/M74rUFlnxAgMBAAGjcjBwMC4GA1UdIwQnMCWhIKQeMBwxGjAY 30 | BgNVBAMMEUludGVybWVkaWF0ZSBDQSAyggECMB0GA1UdDgQWBBSgaJZ+dObbuFez 31 | AnPdmHOUICGG2TAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkq 32 | hkiG9w0BAQsFAAOCAQEAeRYAbnXEu/V8SHtJsIblKmbXMFmubQIRv+TlleDFbsUS 33 | CJ6Ypsqb9ZRQN4uHYsd6PvkuQU6pi/6eHyMI4YsnRk5jBaoT1WrHiT05Rm2ueqMD 34 | daq/cWPXlOicnm9CnkL4hxNfK5kiPCA5uBlI+bJJlaOQnAhVV0Ce2PxCRXL+kIBd 35 | QcExIMZ7RqSefx4HFCieFalbcTFcJ2LvzEwIgz9gs7BYGYyCW8ppY8BQsDJE4FPs 36 | WpeNLmpOvv6358JozRvQ50mgTRj+aVIMKCfXSc+HLlOAU6AIoT+zlCDWi5T+Gl/h 37 | 9fq5IFx6Em3dp0PHaDyLcEkoXZW0VAO0SDHSgZm48w== 38 | -----END CERTIFICATE----- 39 | -----BEGIN CERTIFICATE----- 40 | MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v 41 | dCBDQTAeFw0yMTA1MDIyMTEwNTNaFw0yNjA1MDMyMTEwNTRaMBIxEDAOBgNVBAMM 42 | B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDG+QScTu3C 43 | uHww0n1m5epGvL4ARES2Vy3kfYtUJYKT56ahXzaO0yVx2+TyDY6g319rwCtcFt7q 44 | kP1YH94l89I6vn2GstXG1k2OrHAmV7aBWLgNslSWidipr1eWFt3//yZkzy769RAM 45 | I4oUHSDHav6k+CEAj88urnD2XJIBRiOmrRZlpHv1d2P1TUl1Htouq0aYNzSu9ydN 46 | YPfqaUN60vuXBjACokcN73TkDGFP9q/10AtfuGV09gHba3U8DUdfNRCIONGAp+6n 47 | Ey2afBlBEfEKkfns9PwaudVqh/JOh0opBRJEmxKQGdB65btPoplLSuaudnmNOT8I 48 | gs2HpfI233gXAgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv 49 | b3QgQ0GCAgKaMB0GA1UdDgQWBBQJbPIEHhIU6iV/sA2H+ko1l5213zAPBgNVHRMB 50 | Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAOatW 51 | OET8IKfJymMgjb/tnvGmdgcqEJc4k/9yLz8bRN0M6JD4fskruxd/HkZuBgCtA5cu 52 | qfDUEWnwJJei+ppvbzMoVWOEFZftrdwOLH/iq9niirTcGhQKE8pHWMaxBIwN6woR 53 | O+MY3SfbwJsx/A9mukwriLANMSEoDQBjSbEwGzxeFKAw7VSZTPcfecf0JpWsUhAe 54 | XrpccKo7BndK+4TQJN6dj2w9e0SLL+S7ObZTCCc9R5nV9SY9Dk+VbQnuzn2fD8zL 55 | CL4vca0Ua3qj87xobx460SAbhcLXlSPhKRWgkS9mNvmaq68y1pAdM37JaL0T80wb 56 | qfhnFeMUltAMuOF1gA== 57 | -----END CERTIFICATE----- 58 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/crl_validation/cert-chain-with-revoked-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDJTCCAg2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFJbnRl 3 | cm1lZGlhdGUgQ0EgMjAeFw0yMTA1MDIyMTA4NDlaFw0yNjA1MDMyMTA4NDlaMBwx 4 | GjAYBgNVBAMMEUludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOC 5 | AQ8AMIIBCgKCAQEAxmjvEAQO2IyVta0CeihOgXFp5lKtoMkGGsTFOvT2VyvPXl2w 6 | 3Ut+Ow2/2i4rZu4HsMszx3PXHz94+hGSsYbZmo7y171oKoBIjctcU4KzLp6sUlKA 7 | bBeARDvd6CSv9YcKOOeU03oyFvMED2dXf9Ie36unpx7W3mTa02vZPNynGpeT2ZZU 8 | 6z9O1Pa4i+tzKLY2Q4rs/GPvMZXiFrWGTUzo5wagd21Ntj47NU5bT9FGnX9c2NVb 9 | xEx3ByH274mB5H2uGWaZPMB+UWRlyLGAtcNDGH8qK033V70R6XqiJl7NUuzgJN2v 10 | h7bdAnLtOp8ZZkZGI+kgtjn05gHJoq58bxF3IQIDAQABo3IwcDAuBgNVHSMEJzAl 11 | oSCkHjAcMRowGAYDVQQDDBFJbnRlcm1lZGlhdGUgQ0EgMYIBATAdBgNVHQ4EFgQU 12 | NXj8F6e5ge4aP08YtVbXbd/AVN4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E 13 | BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAELC83ewyJEVMf/GgyzObafcpEchzm7d 14 | rSSD5/Q2NvFilApja/u5KmvltcPd4Up+Vui5EBLyHqkEbDs7VVJlJgLzQckgz611 15 | opgHL9i+nKz1t7AGxcC7aHck1QAAQHTqBxqbuJCQYlkamIQDhE9qjbotGnw+ueo3 16 | ysv+It9aBWeqZKMVmkwSW4GwRYzu2Yr3MzGw11eCaPZQLhGt1Z2Nl7WkG8KP2+QY 17 | +/KUmnr4YbU+Z408uKHSHpP+XkocNRgfETkeVpvX4uLlEJem8RIVu4yWerZZbMzz 18 | dRQ9GIXzgxPmz1FN2KdZGSmkR9HqfZ5paFgJz7aJk7NLC1l9ay67wHo= 19 | -----END CERTIFICATE----- 20 | -----BEGIN CERTIFICATE----- 21 | MIIDGzCCAgOgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 22 | IENBMB4XDTIxMDUwMjIxMDg0OFoXDTI2MDUwMzIxMDg0OFowHDEaMBgGA1UEAwwR 23 | SW50ZXJtZWRpYXRlIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 24 | AQDLJYNLuLqUsWzQcFuJY9zxxc/3gGSlAH01xnAgPBuXQr73IONoeDoB6qaRhQFT 25 | 4mWy5a9h0qGFja44PCGN+ZTmhEpz34hUy9W1d8gzFCwWAUSTn9SwF7a3xIEISL9f 26 | tfCM2vbTaMqgk75cuuxEhISKJ5lIASK1quwlNxcCH+8QVGQDdfNGz5mexMYlu9WP 27 | ktHeGwVlYhQLbgDWnBqJdMmavePVhH0LkR1IAj+/tDVeEJytjMdvJiD6oCx0Wc77 28 | pUgClHTSimHusgftbsEkqGCJvwzohWjyHBoqWK93n34Ua3cTxoaZ5wZzy42BiMhy 29 | gSGA/tZKs0p/quDHRAeH5SnvAgMBAAGjcjBwMC4GA1UdIwQnMCWhIKQeMBwxGjAY 30 | BgNVBAMMEUludGVybWVkaWF0ZSBDQSAyggECMB0GA1UdDgQWBBT5GEvSd10qEiGQ 31 | JXnbJ6qORNmAeTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkq 32 | hkiG9w0BAQsFAAOCAQEAvgSS3qtyjTPWGNW9yGbsi/Z4PYWg5h3ZTBtbOCzQ7j9M 33 | Ecd/vnvuJMjaUxtUzK40AojUcSTZ29UDIK31RWtHq2g62Rkn4HkIii27lXQ2zXzr 34 | vDskBt5fUvTyfSMFm/JrrNQBSwHWqPyQnQewgHR4Pzt0J5OxoAWB905NsySZb4pd 35 | OgbsKudPfIoTG8SjKZ5fRq+iE5rpNGkVnGiy4/vvcl2VRdufZeU+GTr5+wrf40mx 36 | O3Y7KGGoJbnyBFp0OxU7jTnD6E0mv1CkS7m6K2A7Ry2xj1Tw5xRK6XzMyEZPdtFC 37 | mlGj2Z7BWFiYNe68oMWTdQiCFa+Jyl+V77J9G2da2w== 38 | -----END CERTIFICATE----- 39 | -----BEGIN CERTIFICATE----- 40 | MIIDCTCCAfGgAwIBAgICApowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHUm9v 41 | dCBDQTAeFw0yMTA1MDIyMTA4NDdaFw0yNjA1MDMyMTA4NDdaMBIxEDAOBgNVBAMM 42 | B1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDfBdK7m4lB 43 | djlbWCv+qun4DUeWYIhTPRYEqrDaS2GxyLQ4OUkIqIBIV30abQrsRI8yrEFNmMjl 44 | NNH9hPmqGX0aN3Vmk/hAp9e4tfJowuqhyYq9GM6nq+z9852tbWN75NFfEidEI0sf 45 | gSJ62Gdsk+8P92ZK+/A12yhZfDHMPeW++HrtsJjiUwWF60BXGU0ppwWLMslIHMQ8 46 | lHJe5gDv05NI+yOnarOnVYb3ak0KxrUDdY4loycA81kPDFR4s8KBqpar2wz9iLKp 47 | nPm2lcq+CslWhM+SV5ui2LqQsW6UXvy6ZiRGgcYiVNXaITYZCMrPa7V9SQNgJ+0C 48 | bpDDjCXZxQCDAgMBAAGjaTBnMCUGA1UdIwQeMByhFqQUMBIxEDAOBgNVBAMMB1Jv 49 | b3QgQ0GCAgKaMB0GA1UdDgQWBBQJdfA74L4kkPg8lvcxBs8Q2aoofTAPBgNVHRMB 50 | Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAgSmo 51 | gJ/WvOuVGtqBv3D1wOvMWZH1UmtLBpl7wBApQaWhfU8APfokrAwUySV+SejGwCVY 52 | YILqczdfd56IqbAJN0rB8UtoHZfglqXQJYzoEfa/vVdiQtdXQRD/N1phkM8lojKL 53 | E4DElysiORbM2Ed+q/JK0dx5nQl9wM93fdsxfnkL9SXONjasA9j5eH5fRRLrAmdq 54 | VNRzbXn9tQxVYKiT/3WgxZV4T/ZJFc/lR6aAhlOZZ1G/Hhqc6UTXJkxEH8Y+Lbha 55 | maDBmgPXtWfa7NcxV58n05f8o8CxYwWQz96YqY6k6iuU+MmmPi022LQ9fCWsUPhL 56 | W4btL6XUy8YKinQDOg== 57 | -----END CERTIFICATE----- 58 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certs/multiple.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFaTCCA1GgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xNzA4MDIxNjI4MTVaFw0yMjA4MDIxNjI4MTVa 4 | MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogZXhwbG9zaXZvMIICIjANBgkqhkiG9w0B 5 | AQEFAAOCAg8AMIICCgKCAgEA1Dd+K00k5OlIx/2Iw3reWBKg58t1o1PJw+Czz91a 6 | 8D3oxdbfdO7MA8kJL01AWpTiec4AO/grNe42NmDWQgd6hDi2r8lf86sS+vIo6nfI 7 | d3aYzho2wHYNT2g5/6rR5odpJXzIMJ6RriczuuZ7DVILoSH+jBU841gBJgFE9dxE 8 | ChHeRsN9H5tqrLsZ1AylPJ6vGvTy3MZrP9Kjtx0pef8gjhOL7h0Ab1t1ZZmHrXkL 9 | 6ikY1u6+4SeIqml/sNJtx0lG7cZtjmluWUpFIjEqpa1t3afVCTeF1he3RxPxM8gy 10 | V6JpOJm9q3qBUnaTEHIlbsnEooYsXQQXloLang4vXzaUuB7iu7OvLZeGfeeTfPhh 11 | FgJ0VxV6KUTHOoGpSLWchWr7CgXSo3s+Y4ixJL6bswQgtSlP51hlvTP+nag1J1ED 12 | Qsia+5c6erdOBl6tNfgu6GdqWYn8rjUsy9GWNNeP80M3IBX7V43nv8g7p2MyBZ7g 13 | 94uUMbi04jqLEUjDJXkjKKtL/4GJm+kprv1BPWejuwyW+1xUdNkKw6B9Z0bsPA8F 14 | Prjt34pRg8sk3ivu/g1ml6VrevZnaOulqWS/8QdPk0Vl0wtnsmBtluo3gir7I0LF 15 | SbLALnOw68SPwQkBys8Ajda9biovOOE3ZCoX3op802EA3x6yXcDVyiJV3OifQ6t4 16 | yqsCAwEAAaOBrzCBrDA3BglghkgBhvhCAQ0EKgwoUHVwcGV0IFJ1YnkvT3BlblNT 17 | TCBJbnRlcm5hbCBDZXJ0aWZpY2F0ZTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ 18 | BAUwAwEB/zAdBgNVHQ4EFgQUbFDtfev3eTVf9i8IVmy9z8+SIUgwMQYDVR0jBCow 19 | KKEjpCEwHzEdMBsGA1UEAwwUUHVwcGV0IENBOiBleHBsb3Npdm+CAQEwDQYJKoZI 20 | hvcNAQELBQADggIBAATT5735CD4s/DKGIF/VqbE9L5dCFwiUMp3pJozdo+gM7gNb 21 | hqhYWPwWYslEt9F110sF/50BnmJtLxUOhnwklbvnvKIKnKph2tg6bofrPuV/3IET 22 | 4eDXIVuSic2V9tx+M/xQ/KRj2Coxhee4Y0VA+uP1Rx+BGMGbKLjseNPB/xJzhrRx 23 | 6t9PBDqKgu1ah7LzuANNJjI1c4Jr/r/113FUBg8IGxc9n9pUpG+cPU+ertroaQ3m 24 | iU68QQ/qPixHCd4X+iB0uy8pk+eO9jd+o6YwwmeU9qrKpIqRCUfM2VD0PRUW+nIN 25 | MC8oZs5r2Q7fTBGXcdLnW91DDXEGpX/WC1BYwLiiXUWFCQRbc1GyJa7IRiAkPCSc 26 | +uCCwRlvfGsTBcgfhALZhmTkOfQ+vBuotZfEIQ/noaG7ofSuCsrc+hfzh6iEdCWS 27 | GG3Uat3Z2fBH7uXhAdiqkRjqw+/M6HfPn6X4WKVp8GHHmZi8WJ0TQF5zhPaMPeix 28 | ViANR2MBrVzrYK389dd0U1GXYO0oSUQ3Skt+t4CEzwQGbILBtZMPovoi64Fcn4IT 29 | lKSlotvgphpoSdqMh+Qmgc2p7jsQwiojB7Gt+N3tcVr7J93iv9LPRDnwIq02AX2H 30 | Z7wQlzL/VqGD2Qa4RtL+xJfQEE6FO8yeQcfHBy6hb/wiL9Hz0GUlaMN7TWY+ 31 | -----END CERTIFICATE----- 32 | -----BEGIN CERTIFICATE----- 33 | MIIFSjCCAzKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 34 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xMzAxMDEyMTQ0MjhaFw0xODAxMDEyMTQ0Mjha 35 | MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 36 | AgoCggIBANCEYBvEIdTXFOMwz18wahs6tg26C+LT2XOwQspb/Aj5WT2EBwnG2leD 37 | CzfOAKyhHDL6jRqrYU32jqoqBzmzkeVsHzqOMNFosyvcBLU8zyLZU+IP1rjJCyE8 38 | xx9HsdhPKJj93f/gSNR5NQlRcZfqahhOwh/nYdY3pFiNgjUoRwhV2Q01n+ku8WJw 39 | kLVT1TREW9TiSWk7cHWF/ZltPOMMxvJ9q0kXh8sVYK4Gtt3pphTUW0qgXQ2NnNWT 40 | W+7vciRjnHxeoY3q6ZG7vZ8HewYKR4W8D6FA32xCsWELSsWlAABt1lBjKGas/fiY 41 | SeDqSfIxknFn/CIM9AIp2PLS3wh5e0o98qey9AN2WRyG7Qs0ijhwKx9bsMxbM0LR 42 | 5jXuXjBnjGQ69fwCjwlUsOSpNPWLibM+GmxvhghJgAlH5dD4+GqN77WLncQTWYXX 43 | GnOw5efVivS4bgU3t8l8mHLH6quLolR1KLfCv+HuqkvRposAqqLwKH+dhlbq1Y+i 44 | 4siPxfYV5NZ092Z9R0F4BPEmLhKngkK+/eQXxLY2zfaR6Ns83yRJfMXRyElECX/+ 45 | RBT1LyIRZg+MbsRg7DsKWI0plzxso/4CgSmYSfPku5nkekrMN34YhUtcxsdHSmY1 46 | 5/p2olvKpTJj3e5fa2KVswcv77FsC17gIfMXqvN3tITP+q1LLJHNAgMBAAGjgZsw 47 | gZgwNwYJYIZIAYb4QgENBCoWKFB1cHBldCBSdWJ5L09wZW5TU0wgSW50ZXJuYWwg 48 | Q2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUF 49 | BwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT3awXrPXSWNszZ 50 | tlLKoXQ8LRjJ3DANBgkqhkiG9w0BAQsFAAOCAgEAYTFx++uptZxgptFmkPfT1f2W 51 | 6djOOVULmlLGPC6Ovbe5v0ksA2hbLW3eSmfL28Ku0WC8gRl0/PhyiyW77M1jp9dV 52 | ztsFkXjMiIIcY0B7Hgqh1kpK1CFvSbsD3piXcDLlZ1CwSAXuohp+J2fUblHRfAUD 53 | Th9qrm3g4uNFp0wXxO1+GgXeDrGRqYosb0wAhB7/BhW2WbOFtVYdFoyyXJFJYx/3 54 | Gj7ZTE3rvGGxOEEuww0pFmuGCflZYxEu15Rynej7soGaE80+wRk+gMS26WKwRQ/0 55 | TGovOHSLo/fpOjjHIoqbQLH3S08jUfAYjjP7Rd01SiztUjZMILC2WCnpdYN+2O9O 56 | rGTj2Zl3oRtE67NwxgKlo2GIFghSF366XOF8O4z1e9id6u5XEdoz8uGFkHyMu79N 57 | cdYcUtmAqLvJ0Ubewg+TfNDcfk1akNtHtIJDNqFwHlZ9R1GIupHQs10R4YxJv3I2 58 | LojJbtcgWcDg9StwCHRA0SuLrWnHPnm+glzXM5HTNJZ6vcrM0SrcnZ59p3o3ZULL 59 | JTJikA+pcs+WAWz1yTNg/ywxYPnFrs8A4MEC43XFe2dS96a7VcNqpMMya+DAWWCS 60 | +51lDlMLuz+q5WHDGh3ouTNYMdcSLo8bHzKInDYnK/DzUpdJ5OKYwqfxv5n0bJs6 61 | fRA2buaQo0zJeid7G2Q= 62 | -----END CERTIFICATE----- 63 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/certs/multiple_reverse.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFSjCCAzKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xMzAxMDEyMTQ0MjhaFw0xODAxMDEyMTQ0Mjha 4 | MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 5 | AgoCggIBANCEYBvEIdTXFOMwz18wahs6tg26C+LT2XOwQspb/Aj5WT2EBwnG2leD 6 | CzfOAKyhHDL6jRqrYU32jqoqBzmzkeVsHzqOMNFosyvcBLU8zyLZU+IP1rjJCyE8 7 | xx9HsdhPKJj93f/gSNR5NQlRcZfqahhOwh/nYdY3pFiNgjUoRwhV2Q01n+ku8WJw 8 | kLVT1TREW9TiSWk7cHWF/ZltPOMMxvJ9q0kXh8sVYK4Gtt3pphTUW0qgXQ2NnNWT 9 | W+7vciRjnHxeoY3q6ZG7vZ8HewYKR4W8D6FA32xCsWELSsWlAABt1lBjKGas/fiY 10 | SeDqSfIxknFn/CIM9AIp2PLS3wh5e0o98qey9AN2WRyG7Qs0ijhwKx9bsMxbM0LR 11 | 5jXuXjBnjGQ69fwCjwlUsOSpNPWLibM+GmxvhghJgAlH5dD4+GqN77WLncQTWYXX 12 | GnOw5efVivS4bgU3t8l8mHLH6quLolR1KLfCv+HuqkvRposAqqLwKH+dhlbq1Y+i 13 | 4siPxfYV5NZ092Z9R0F4BPEmLhKngkK+/eQXxLY2zfaR6Ns83yRJfMXRyElECX/+ 14 | RBT1LyIRZg+MbsRg7DsKWI0plzxso/4CgSmYSfPku5nkekrMN34YhUtcxsdHSmY1 15 | 5/p2olvKpTJj3e5fa2KVswcv77FsC17gIfMXqvN3tITP+q1LLJHNAgMBAAGjgZsw 16 | gZgwNwYJYIZIAYb4QgENBCoWKFB1cHBldCBSdWJ5L09wZW5TU0wgSW50ZXJuYWwg 17 | Q2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUF 18 | BwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT3awXrPXSWNszZ 19 | tlLKoXQ8LRjJ3DANBgkqhkiG9w0BAQsFAAOCAgEAYTFx++uptZxgptFmkPfT1f2W 20 | 6djOOVULmlLGPC6Ovbe5v0ksA2hbLW3eSmfL28Ku0WC8gRl0/PhyiyW77M1jp9dV 21 | ztsFkXjMiIIcY0B7Hgqh1kpK1CFvSbsD3piXcDLlZ1CwSAXuohp+J2fUblHRfAUD 22 | Th9qrm3g4uNFp0wXxO1+GgXeDrGRqYosb0wAhB7/BhW2WbOFtVYdFoyyXJFJYx/3 23 | Gj7ZTE3rvGGxOEEuww0pFmuGCflZYxEu15Rynej7soGaE80+wRk+gMS26WKwRQ/0 24 | TGovOHSLo/fpOjjHIoqbQLH3S08jUfAYjjP7Rd01SiztUjZMILC2WCnpdYN+2O9O 25 | rGTj2Zl3oRtE67NwxgKlo2GIFghSF366XOF8O4z1e9id6u5XEdoz8uGFkHyMu79N 26 | cdYcUtmAqLvJ0Ubewg+TfNDcfk1akNtHtIJDNqFwHlZ9R1GIupHQs10R4YxJv3I2 27 | LojJbtcgWcDg9StwCHRA0SuLrWnHPnm+glzXM5HTNJZ6vcrM0SrcnZ59p3o3ZULL 28 | JTJikA+pcs+WAWz1yTNg/ywxYPnFrs8A4MEC43XFe2dS96a7VcNqpMMya+DAWWCS 29 | +51lDlMLuz+q5WHDGh3ouTNYMdcSLo8bHzKInDYnK/DzUpdJ5OKYwqfxv5n0bJs6 30 | fRA2buaQo0zJeid7G2Q= 31 | -----END CERTIFICATE----- 32 | -----BEGIN CERTIFICATE----- 33 | MIIFaTCCA1GgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 34 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xNzA4MDIxNjI4MTVaFw0yMjA4MDIxNjI4MTVa 35 | MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogZXhwbG9zaXZvMIICIjANBgkqhkiG9w0B 36 | AQEFAAOCAg8AMIICCgKCAgEA1Dd+K00k5OlIx/2Iw3reWBKg58t1o1PJw+Czz91a 37 | 8D3oxdbfdO7MA8kJL01AWpTiec4AO/grNe42NmDWQgd6hDi2r8lf86sS+vIo6nfI 38 | d3aYzho2wHYNT2g5/6rR5odpJXzIMJ6RriczuuZ7DVILoSH+jBU841gBJgFE9dxE 39 | ChHeRsN9H5tqrLsZ1AylPJ6vGvTy3MZrP9Kjtx0pef8gjhOL7h0Ab1t1ZZmHrXkL 40 | 6ikY1u6+4SeIqml/sNJtx0lG7cZtjmluWUpFIjEqpa1t3afVCTeF1he3RxPxM8gy 41 | V6JpOJm9q3qBUnaTEHIlbsnEooYsXQQXloLang4vXzaUuB7iu7OvLZeGfeeTfPhh 42 | FgJ0VxV6KUTHOoGpSLWchWr7CgXSo3s+Y4ixJL6bswQgtSlP51hlvTP+nag1J1ED 43 | Qsia+5c6erdOBl6tNfgu6GdqWYn8rjUsy9GWNNeP80M3IBX7V43nv8g7p2MyBZ7g 44 | 94uUMbi04jqLEUjDJXkjKKtL/4GJm+kprv1BPWejuwyW+1xUdNkKw6B9Z0bsPA8F 45 | Prjt34pRg8sk3ivu/g1ml6VrevZnaOulqWS/8QdPk0Vl0wtnsmBtluo3gir7I0LF 46 | SbLALnOw68SPwQkBys8Ajda9biovOOE3ZCoX3op802EA3x6yXcDVyiJV3OifQ6t4 47 | yqsCAwEAAaOBrzCBrDA3BglghkgBhvhCAQ0EKgwoUHVwcGV0IFJ1YnkvT3BlblNT 48 | TCBJbnRlcm5hbCBDZXJ0aWZpY2F0ZTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ 49 | BAUwAwEB/zAdBgNVHQ4EFgQUbFDtfev3eTVf9i8IVmy9z8+SIUgwMQYDVR0jBCow 50 | KKEjpCEwHzEdMBsGA1UEAwwUUHVwcGV0IENBOiBleHBsb3Npdm+CAQEwDQYJKoZI 51 | hvcNAQELBQADggIBAATT5735CD4s/DKGIF/VqbE9L5dCFwiUMp3pJozdo+gM7gNb 52 | hqhYWPwWYslEt9F110sF/50BnmJtLxUOhnwklbvnvKIKnKph2tg6bofrPuV/3IET 53 | 4eDXIVuSic2V9tx+M/xQ/KRj2Coxhee4Y0VA+uP1Rx+BGMGbKLjseNPB/xJzhrRx 54 | 6t9PBDqKgu1ah7LzuANNJjI1c4Jr/r/113FUBg8IGxc9n9pUpG+cPU+ertroaQ3m 55 | iU68QQ/qPixHCd4X+iB0uy8pk+eO9jd+o6YwwmeU9qrKpIqRCUfM2VD0PRUW+nIN 56 | MC8oZs5r2Q7fTBGXcdLnW91DDXEGpX/WC1BYwLiiXUWFCQRbc1GyJa7IRiAkPCSc 57 | +uCCwRlvfGsTBcgfhALZhmTkOfQ+vBuotZfEIQ/noaG7ofSuCsrc+hfzh6iEdCWS 58 | GG3Uat3Z2fBH7uXhAdiqkRjqw+/M6HfPn6X4WKVp8GHHmZi8WJ0TQF5zhPaMPeix 59 | ViANR2MBrVzrYK389dd0U1GXYO0oSUQ3Skt+t4CEzwQGbILBtZMPovoi64Fcn4IT 60 | lKSlotvgphpoSdqMh+Qmgc2p7jsQwiojB7Gt+N3tcVr7J93iv9LPRDnwIq02AX2H 61 | Z7wQlzL/VqGD2Qa4RtL+xJfQEE6FO8yeQcfHBy6hb/wiL9Hz0GUlaMN7TWY+ 62 | -----END CERTIFICATE----- 63 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defn deploy-info 2 | [url] 3 | { :url url 4 | :username :env/clojars_jenkins_username 5 | :password :env/clojars_jenkins_password 6 | :sign-releases false}) 7 | 8 | (defproject puppetlabs/ssl-utils "3.5.4-SNAPSHOT" 9 | :url "http://www.github.com/puppetlabs/jvm-ssl-utils" 10 | 11 | :description "SSL certificate management on the JVM." 12 | 13 | :min-lein-version "2.9.10" 14 | 15 | :parent-project {:coords [puppetlabs/clj-parent "5.6.6"] 16 | :inherit [:managed-dependencies]} 17 | 18 | ;; Abort when version ranges or version conflicts are detected in 19 | ;; dependencies. Also supports :warn to simply emit warnings. 20 | :pedantic? :abort 21 | 22 | :dependencies [[org.clojure/clojure] 23 | [org.clojure/tools.logging] 24 | [commons-codec] 25 | [clj-commons/fs] 26 | [clj-time] 27 | [puppetlabs/i18n] 28 | [prismatic/schema]] 29 | 30 | :source-paths ["src/clojure"] 31 | :java-source-paths ["src/java"] 32 | :jar-exclusions [#".*\.java$"] 33 | 34 | ;; By declaring a classifier here and a corresponding profile below we'll get an additional jar 35 | ;; during `lein jar` that has all the source code (including the java source). Downstream projects can then 36 | ;; depend on this source jar using a :classifier in their :dependencies. 37 | :classifiers [["sources" :sources-jar]] 38 | 39 | :profiles {:dev {:dependencies [[org.bouncycastle/bcpkix-jdk18on]] 40 | :resource-paths ["test-resources"]} 41 | 42 | ;; per https://github.com/technomancy/leiningen/issues/1907 43 | ;; the provided profile is necessary for lein jar / lein install 44 | :provided {:dependencies [[org.bouncycastle/bcpkix-jdk18on]] 45 | :resource-paths ["test-resources"]} 46 | 47 | :fips {:dependencies [[org.bouncycastle/bctls-fips "2.0.19" :exclusions [org.bouncycastle/bcutil-fips]] 48 | [org.bouncycastle/bcpkix-fips "2.0.7" :exclusions [org.bouncycastle/bcutil-fips]] 49 | [org.bouncycastle/bcutil-fips "2.0.3"] 50 | [org.bouncycastle/bc-fips "2.0.0"]] 51 | ;; this only ensures that we run with the proper profiles 52 | ;; during testing. This JVM opt will be set in the puppet module 53 | ;; that sets up the JVM classpaths during installation. 54 | :jvm-opts ~(let [version (System/getProperty "java.specification.version") 55 | [major minor _] (clojure.string/split version #"\.") 56 | unsupported-ex (ex-info "Unsupported major Java version. Expects 8, 11, or 17." 57 | {:major major 58 | :minor minor})] 59 | (condp = (java.lang.Integer/parseInt major) 60 | 1 (if (= 8 (java.lang.Integer/parseInt minor)) 61 | ["-Djava.security.properties==jdk8-fips-security"] 62 | (throw unsupported-ex)) 63 | 11 ["-Djava.security.properties==jdk11-fips-security"] 64 | 17 ["-Djava.security.properties==jdk17-fips-security"] 65 | (throw unsupported-ex))) 66 | :resource-paths ["test-resources"]} 67 | 68 | :sources-jar {:java-source-paths ^:replace [] 69 | :jar-exclusions ^:replace [] 70 | :source-paths ^:replace ["src/clojure" "src/java"]}} 71 | 72 | :plugins [[lein-parent "0.3.9"] 73 | [puppetlabs/i18n "0.9.2"] 74 | [jonase/eastwood "1.2.2" :exclusions [org.clojure/clojure]]] 75 | 76 | :eastwood {:exclude-linters [:no-ns-form-found :reflection] 77 | :continue-on-exception true} 78 | 79 | :lein-release {:scm :git 80 | :deploy-via :lein-deploy} 81 | :deploy-repositories [["releases" ~(deploy-info "https://clojars.org/repo")] 82 | ["snapshots" ~(deploy-info "https://clojars.org/repo")]] 83 | 84 | :repositories [["puppet-releases" "https://artifactory.delivery.puppetlabs.net/artifactory/list/clojure-releases__local/"] 85 | ["puppet-snapshots" "https://artifactory.delivery.puppetlabs.net/artifactory/list/clojure-snapshots__local/"]]) 86 | 87 | -------------------------------------------------------------------------------- /dev-resources/Makefile.i18n: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | # This file was generated by the i18n leiningen plugin 3 | # Do not edit this file; it will be overwritten the next time you run 4 | # lein i18n init 5 | # 6 | 7 | # The name of the package into which the translations bundle will be placed 8 | BUNDLE=puppetlabs.ssl_utils 9 | 10 | # The name of the POT file into which the gettext code strings (msgid) will be placed 11 | POT_NAME=ssl-utils.pot 12 | 13 | # The list of names of packages covered by the translation bundle; 14 | # by default it contains a single package - the same where the translations 15 | # bundle itself is placed - but this can be overridden - preferably in 16 | # the top level Makefile 17 | PACKAGES?=$(BUNDLE) 18 | LOCALES=$(basename $(notdir $(wildcard locales/*.po))) 19 | BUNDLE_DIR=$(subst .,/,$(BUNDLE)) 20 | BUNDLE_FILES=$(patsubst %,resources/$(BUNDLE_DIR)/Messages_%.class,$(LOCALES)) 21 | FIND_SOURCES=find src -name \*.clj 22 | # xgettext before 0.19 does not understand --add-location=file. Even CentOS 23 | # 7 ships with an older gettext. We will therefore generate full location 24 | # info on those systems, and only file names where xgettext supports it 25 | LOC_OPT=$(shell xgettext --add-location=file -f - /dev/null 2>&1 && echo --add-location=file || echo --add-location) 26 | 27 | LOCALES_CLJ=resources/locales.clj 28 | define LOCALES_CLJ_CONTENTS 29 | { 30 | :locales #{$(patsubst %,"%",$(LOCALES))} 31 | :packages [$(patsubst %,"%",$(PACKAGES))] 32 | :bundle $(patsubst %,"%",$(BUNDLE).Messages) 33 | } 34 | endef 35 | export LOCALES_CLJ_CONTENTS 36 | 37 | 38 | i18n: msgfmt 39 | 40 | # Update locales/.pot 41 | update-pot: locales/$(POT_NAME) 42 | 43 | locales/$(POT_NAME): $(shell $(FIND_SOURCES)) | locales 44 | @tmp=$$(mktemp $@.tmp.XXXX); \ 45 | $(FIND_SOURCES) \ 46 | | xgettext --from-code=UTF-8 --language=lisp \ 47 | --copyright-holder='Puppet ' \ 48 | --package-name="$(BUNDLE)" \ 49 | --package-version="$(BUNDLE_VERSION)" \ 50 | --msgid-bugs-address="docs@puppet.com" \ 51 | -k \ 52 | -kmark:1 -ki18n/mark:1 \ 53 | -ktrs:1 -ki18n/trs:1 \ 54 | -ktru:1 -ki18n/tru:1 \ 55 | -ktrun:1,2 -ki18n/trun:1,2 \ 56 | -ktrsn:1,2 -ki18n/trsn:1,2 \ 57 | $(LOC_OPT) \ 58 | --add-comments --sort-by-file \ 59 | -o $$tmp -f -; \ 60 | sed -i.bak -e 's/charset=CHARSET/charset=UTF-8/' $$tmp; \ 61 | sed -i.bak -e 's/POT-Creation-Date: [^\\]*/POT-Creation-Date: /' $$tmp; \ 62 | rm -f $$tmp.bak; \ 63 | if ! diff -q -I POT-Creation-Date $$tmp $@ >/dev/null 2>&1; then \ 64 | mv $$tmp $@; \ 65 | else \ 66 | rm $$tmp; touch $@; \ 67 | fi 68 | 69 | # Run msgfmt over all .po files to generate Java resource bundles 70 | # and create the locales.clj file 71 | msgfmt: $(BUNDLE_FILES) $(LOCALES_CLJ) clean-orphaned-bundles 72 | 73 | # Force rebuild of locales.clj if its contents is not the the desired one. The 74 | # shell echo is used to add a trailing newline to match the one from `cat` 75 | ifneq ($(shell cat $(LOCALES_CLJ) 2> /dev/null),$(shell echo '$(LOCALES_CLJ_CONTENTS)')) 76 | .PHONY: $(LOCALES_CLJ) 77 | endif 78 | $(LOCALES_CLJ): | resources 79 | @echo "Writing $@" 80 | @echo "$$LOCALES_CLJ_CONTENTS" > $@ 81 | 82 | # Remove every resource bundle that wasn't generated from a PO file. 83 | # We do this because we used to generate the english bundle directly from the POT. 84 | .PHONY: clean-orphaned-bundles 85 | clean-orphaned-bundles: 86 | @for bundle in resources/$(BUNDLE_DIR)/Messages_*.class; do \ 87 | locale=$$(basename "$$bundle" | sed -E -e 's/\$$?1?\.class$$/_class/' | cut -d '_' -f 2;); \ 88 | if [ ! -f "locales/$$locale.po" ]; then \ 89 | rm "$$bundle"; \ 90 | fi \ 91 | done 92 | 93 | resources/$(BUNDLE_DIR)/Messages_%.class: locales/%.po | resources 94 | msgfmt --java2 -d resources -r $(BUNDLE).Messages -l $(*F) $< 95 | 96 | # Use this to initialize translations. Updating the PO files is done 97 | # automatically through a CI job that utilizes the scripts in the project's 98 | # `bin` file, which themselves come from the `clj-i18n` project. 99 | locales/%.po: | locales 100 | @if [ ! -f $@ ]; then \ 101 | touch $@ && msginit --no-translator -l $(*F) -o $@ -i locales/$(POT_NAME); \ 102 | fi 103 | 104 | resources locales: 105 | @mkdir $@ 106 | 107 | help: 108 | $(info $(HELP)) 109 | @echo 110 | 111 | .PHONY: help 112 | 113 | define HELP 114 | This Makefile assists in handling i18n related tasks during development. Files 115 | that need to be checked into source control are put into the locales/ directory. 116 | They are 117 | 118 | locales/$(POT_NAME) - the POT file generated by 'make update-pot' 119 | locales/$$LANG.po - the translations for $$LANG 120 | 121 | Only the $$LANG.po files should be edited manually; this is usually done by 122 | translators. 123 | 124 | You can use the following targets: 125 | 126 | i18n: refresh all the files in locales/ and recompile resources 127 | update-pot: extract strings and update locales/$(POT_NAME) 128 | locales/LANG.po: create translations for LANG 129 | msgfmt: compile the translations into Java classes; this step is 130 | needed to make translations available to the Clojure code 131 | and produces Java class files in resources/ 132 | endef 133 | # @todo lutter 2015-04-20: for projects that use libraries with their own 134 | # translation, we need to combine all their translations into one big po 135 | # file and then run msgfmt over that so that we only have to deal with one 136 | # resource bundle 137 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/ssl_utils/examples/ssl/private_keys/multiple_pks.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -----BEGIN RSA PRIVATE KEY----- 53 | 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 102 | -----END RSA PRIVATE KEY----- 103 | -------------------------------------------------------------------------------- /src/clojure/puppetlabs/ssl_utils/simple.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.ssl-utils.simple 2 | (:import (java.util Date) 3 | (java.security PublicKey PrivateKey) 4 | (java.security.cert X509Certificate X509CRL)) 5 | (:require [puppetlabs.ssl-utils.core :as ssl-utils] 6 | [clj-time.core :as time] 7 | [schema.core :as schema])) 8 | 9 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10 | ;;; Schemas 11 | 12 | (def SSLKeyPair 13 | "A schema for the map used to describe an SSL KeyPair internally." 14 | {:public-key PublicKey 15 | :private-key PrivateKey 16 | :x500-name ssl-utils/ValidX500Name 17 | :certname schema/Str}) 18 | 19 | (def SSLCert 20 | "A schema for the map used to describe an SSL Certificate internally." 21 | (assoc SSLKeyPair 22 | :cert X509Certificate)) 23 | 24 | (def SSLOptions 25 | "A schema for the SSL Options that can be used with the cert and key 26 | generation functions." 27 | {(schema/optional-key :extensions) [Object] 28 | (schema/optional-key :keylength) schema/Int}) 29 | 30 | (def SSLValidDateRange 31 | "A schema for the map representing a valid date range for an SSL certificate." 32 | {:not-before Date 33 | :not-after Date}) 34 | 35 | 36 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 37 | ;;; Predicates - no longer used internally now that there are schemas 38 | 39 | (defn validity-date-range? 40 | "Returns true if the given map contains all the fields required to define a 41 | validity date range for a certificate." 42 | [x] 43 | (and (map? x) 44 | (instance? Date (:not-before x)) 45 | (instance? Date (:not-after x)))) 46 | 47 | (defn ssl-keys? 48 | "Returns true if the given map contains all the fields required to define an 49 | SSL keypair and associated certname info." 50 | [x] 51 | (and (map? x) 52 | (ssl-utils/public-key? (:public-key x)) 53 | (ssl-utils/private-key? (:private-key x)) 54 | (ssl-utils/valid-x500-name? (:x500-name x)) 55 | (string? (:certname x)))) 56 | 57 | (defn ssl-cert? 58 | "Returns true if the given map contains all the fields required to define a 59 | certificate, keypair, and associated certname info." 60 | [x] 61 | (and (ssl-keys? x) 62 | (ssl-utils/certificate? (:cert x)))) 63 | 64 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 65 | ;;; Public 66 | 67 | (schema/defn ^:always-validate cert-validity-dates :- SSLValidDateRange 68 | "Calculate the not-before & not-after dates that define a certificate's 69 | period of validity. The value of `ca-ttl` is expected to be in seconds, 70 | and the dates will be based on the current time. Returns a map in the 71 | form {:not-before Date :not-after Date}." 72 | [ca-ttl :- schema/Int] 73 | (let [now (time/now) 74 | not-before (time/minus now (time/days 1)) 75 | not-after (time/plus now (time/seconds ca-ttl))] 76 | {:not-before (.toDate not-before) 77 | :not-after (.toDate not-after)})) 78 | 79 | (def default-keylength 80 | "The default bit length to use when generating keys. 81 | Note that all API functions accept an `options' map which may 82 | have a :keylength for specifying this value." 83 | 4096) 84 | 85 | (schema/defn ^:always-validate gen-keys :- SSLKeyPair 86 | "Generate public and private keys and the X500 name for the given `certname'. 87 | An optional map may be provided to specify: 88 | 89 | * :keylength Bit length to use for the public/private keys; 90 | defaults to 4096." 91 | ([certname] (gen-keys certname {})) 92 | ([certname :- schema/Str 93 | options :- SSLOptions] 94 | (let [keylength (get options :keylength default-keylength) 95 | keypair (ssl-utils/generate-key-pair keylength)] 96 | {:public-key (ssl-utils/get-public-key keypair) 97 | :private-key (ssl-utils/get-private-key keypair) 98 | :x500-name (ssl-utils/cn certname) 99 | :certname certname}))) 100 | 101 | (schema/defn ^:always-validate gen-cert* :- X509Certificate 102 | "Internal helper function to generate a certificate; see `gen-cert' for the 103 | public version of this function. 104 | An optional map may be provided to specify: 105 | 106 | * :extensions List of certificate extensions to include on the certificate; 107 | defaults to []." 108 | ([ca-keys host-keys serial] (gen-cert* ca-keys host-keys serial {})) 109 | ([ca-keys host-keys serial options] (gen-cert* ca-keys host-keys serial options false)) 110 | ([ca-keys :- (schema/conditional 111 | (fn [cert] (some #(= :cert %) (keys cert))) SSLCert 112 | :else SSLKeyPair) 113 | host-keys :- SSLKeyPair 114 | serial :- schema/Int 115 | options :- SSLOptions 116 | ca? :- schema/Bool] 117 | (let [validity (cert-validity-dates (* 5 60 60 24 365)) 118 | extensions (if ca? 119 | (ssl-utils/create-ca-extensions 120 | (:x500-name host-keys) 121 | serial 122 | (:public-key host-keys)) 123 | (get options :extensions []))] 124 | (ssl-utils/sign-certificate 125 | (:x500-name ca-keys) 126 | (:private-key ca-keys) 127 | serial 128 | (:not-before validity) 129 | (:not-after validity) 130 | (:x500-name host-keys) 131 | (:public-key host-keys) 132 | extensions)))) 133 | 134 | (schema/defn ^:always-validate gen-cert :- SSLCert 135 | "Generate a certificate. An optional map may be provided to specify: 136 | 137 | * :keylength Bit length to use for the public/private keys; 138 | defaults to 4096. 139 | * :extensions List of certificate extensions to include on the certificate; 140 | defaults to []." 141 | ([certname ca-cert serial] (gen-cert certname ca-cert serial {})) 142 | ([certname ca-cert serial options] (gen-cert certname ca-cert serial options false)) 143 | ([certname :- schema/Str 144 | ca-cert :- SSLCert 145 | serial :- schema/Int 146 | options :- SSLOptions 147 | ca? :- schema/Bool] 148 | (let [cert-keys (gen-keys certname options)] 149 | (assoc cert-keys :cert (gen-cert* ca-cert cert-keys serial options ca?))))) 150 | 151 | (schema/defn ^:always-validate gen-self-signed-cert :- SSLCert 152 | "Generate a self-signed certificate. 153 | An optional map may be provided to specify: 154 | 155 | * :keylength Bit length to use for the public/private keys; 156 | defaults to 4096. 157 | * :extensions List of certificate extensions to include on the certificate; 158 | defaults to []." 159 | ([certname serial] (gen-self-signed-cert certname serial {})) 160 | ([certname serial options] (gen-self-signed-cert certname serial options false)) 161 | ([certname :- schema/Str 162 | serial :- schema/Int 163 | options :- SSLOptions 164 | ca? :- schema/Bool] 165 | (let [cert-keys (gen-keys certname options)] 166 | (assoc cert-keys :cert (gen-cert* cert-keys cert-keys serial options ca?))))) 167 | 168 | (schema/defn ^:always-validate gen-crl :- X509CRL 169 | [ca-cert :- SSLCert] 170 | (ssl-utils/generate-crl 171 | (.getIssuerX500Principal (:cert ca-cert)) 172 | (:private-key ca-cert) 173 | (:public-key ca-cert))) 174 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jvm-ssl-utils 2 | 3 | [![Build Status](https://travis-ci.org/puppetlabs/jvm-ssl-utils.png?branch=master)](https://travis-ci.org/puppetlabs/jvm-ssl-utils) 4 | 5 | SSL certificate management on the JVM. 6 | 7 | ## Installation 8 | 9 | Add the following dependency to your `project.clj` file: 10 | 11 | [![Clojars Project](http://clojars.org/puppetlabs/ssl-utils/latest-version.svg)](http://clojars.org/puppetlabs/ssl-utils) 12 | 13 | ## Handling X.509 certificate extensions 14 | 15 | X.509 certificates and certificate requests can optionally contain a list of 16 | extensions which may further specify how the certificate is to be used. Each of 17 | the functions which either return or accept X.509 extensions expect them to 18 | be a list of maps. Each map contains the following keys: 19 | 20 | * `oid` A string containing the extension's OID. 21 | * `critical` A boolean which is true if the extension is marked as critical. 22 | * `value` A primitive value, or data structure representing the data contained 23 | in the extension. The exact format of the `value` data is dependent 24 | upon the OID of the extension, which are described below. 25 | 26 | ### Supported extensions and their data structures 27 | 28 | Currently only a subset of the defined X.509 extensions are supported by this 29 | library, more will be supported in the future. Note that in the Java API all 30 | map keys are snake-cased strings, in the Clojure API all map keys are kebab-cased 31 | keywords. 32 | 33 | #### Subject Key Identifier: `2.5.29.14` 34 | 35 | When writing a _Subject Key Identifier_ extension, set the `value` key of the 36 | extension map to an instance of the subject's `java.security.PublicKey`. When 37 | extension is written to the certificate or certificate request then the SHA-1 38 | hash of the key will be computed and written to the object. 39 | 40 | When a _Subject Key Identifier_ extensions is read from a certificate its value 41 | is a byte array containing the SHA-1 hash. 42 | 43 | #### Key Usage: `2.5.29.15` 44 | 45 | Key usage is defined by a set of keywords which indicate how the certificate is 46 | to be used. The following keywords are used: 47 | 48 | | Keyword | Meaning | 49 | |----------------------|-------------------------------------------------------------------------------------------| 50 | | `:digital-signature` | The public key can be used for encrypting data. | 51 | | `:non-repudiation` | The public key is used to verify digital signatures. | 52 | | `:key-encipherment` | The certificate will be used with a protocol that encrypts keys. | 53 | | `:data-encipherment` | The public key is used for encrypting user data. | 54 | | `:key-agreement` | The sender and receiver of the public key need to derive the key without using encryption.| 55 | | `:key-cert-sign` | The subject public key is used to verify a signature on certificates. | 56 | | `:crl-sign` | The subject public key is to verify a signature on a CRL. | 57 | | `:encipher-only` | The public key is to be used only for enciphering data while performing key agreement. | 58 | | `:decipher-only` | The public key is to be used only for deciphering data while performing key agreement. | 59 | 60 | #### Subject Alternative Names: `2.5.29.17` 61 | 62 | This extensions is represented as a map where each key is name type, and the 63 | value is a list of names of that type to be aliased. The following hash keys 64 | correspond to the listed types. 65 | 66 | | Key | Type | 67 | |-------------------|------------------------------------------| 68 | | `:rfc822-name` | An RFC822 compliant e-mail address | 69 | | `:dns-name` | A host name which can be resolved by DNS | 70 | | `:directory-name` | A fully-qualified DN | 71 | | `:uri` | A URI | 72 | | `:ip` | An IP address | 73 | 74 | For example: 75 | 76 | ```clojure 77 | (let [exts [;; Subject alternative DNS names 78 | {:oid "2.5.29.17" 79 | :value {:dns-name ["aliasname1.domain.tld" 80 | "aliasname2.domain.tld"]} 81 | :critical false} 82 | ;; Issuer alternative DNS name 83 | {:oid "2.5.29.18" 84 | :value {:dns-name ["aliasname3.domain.tld"} 85 | :critical false}]]) 86 | ``` 87 | 88 | #### Issuer Alternative Names: `2.5.29.18` 89 | 90 | The format of this extension is the same as `Subject Alternative Names` above. 91 | 92 | #### Basic Constraints: `2.5.29.19` 93 | 94 | Defines basic constraints for the certificate as a map with these two keys: 95 | 96 | | Key | Type | Value | 97 | |------------------------|---------|--------------------------------------------------------------------------------------------------------------------------------------| 98 | | `:is-ca` | boolean | True if the subject may act as a CA. | 99 | | `:path-len-constraint` | integer | If this is a CA cert, the max certification path length. A value of nil or absence of this key indicates that no length is imposed. | 100 | 101 | #### CRL Number: `2.5.29.20` 102 | 103 | The value of this extension is a `java.math.BigInteger` representing the 104 | sequence number for a CRL (Certificate Revocation List). 105 | 106 | #### Authority Key Identifier: `2.5.29.35` 107 | 108 | When writing this extension to a certificate the value should be a map 109 | which contains one of the following combinations of keys (with corresponding 110 | values): 111 | 112 | * `:public-key` 113 | * `:serial-number` and `:issuer-dn` 114 | * `:public-key`, `:serial-number`, and `:issuer-dn` 115 | 116 | These keys are defined as: 117 | 118 | | Key | Type | Value | 119 | |------------------|-------------------------|------------------------------------------| 120 | | `:public-key` | java.security.PublicKey | CA's public key. | 121 | | `:issuer-dn` | string | A Distinguished Name identifying the CA. | 122 | | `:serial-number` | java.math.BigInteger | CA's serial number. | 123 | 124 | When this extension is read back from a certificate, it will be a map containing 125 | the following keys. Note that if the corresponding value for any key was not 126 | specified, it will be set to nil. 127 | 128 | | Key | Type | Value | 129 | |------------------------|----------------------|----------------------------------------------------------------| 130 | | `:key-identifier` | byte vector | A byte array containing the SHA-1 hash of the CA's public key. | 131 | | `:issuer` | string | A Distinguished Name identifying the CA. | 132 | | `:serial-number` | java.math.BigInteger | CA's serial number. | 133 | 134 | #### Extended Key Usage: `2.5.29.37` 135 | 136 | #### Netscape Certificate Comment: `2.16.840.1.113730.1.13` 137 | 138 | The value of this extension is a string containing a comment about the certificate. 139 | 140 | ## License 141 | 142 | See [LICENSE](LICENSE) file. 143 | 144 | ## Support 145 | 146 | Please log issues in the GitHub issue tracker. 147 | 148 | We use semantic version numbers for our releases, and recommend that users stay 149 | as up-to-date as possible by upgrading to patch releases and minor releases as 150 | they become available. 151 | 152 | Bugfixes and ongoing development will occur in minor releases for the current 153 | major version. Security fixes will be backported to a previous major version on 154 | a best-effort basis, until the previous major version is no longer maintained. 155 | 156 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright (C) 2015 Puppet Labs Inc 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /test/puppetlabs/ssl_utils/testutils.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.ssl-utils.testutils 2 | (:import (java.io ByteArrayOutputStream ByteArrayInputStream) 3 | (java.security.cert X509Certificate) 4 | (java.security MessageDigest PublicKey) 5 | (javax.security.auth.x500 X500Principal) 6 | (org.bouncycastle.asn1.x500 X500Name) 7 | (org.bouncycastle.pkcs PKCS10CertificationRequest) 8 | (org.joda.time DateTime Period) 9 | (org.bouncycastle.asn1.x509 SubjectPublicKeyInfo) 10 | (com.puppetlabs.ssl_utils SSLUtils)) 11 | (:require [clojure.test :refer :all] 12 | [clojure.java.io :refer [resource]] 13 | [me.raynes.fs :as fs] 14 | [puppetlabs.ssl-utils.core :refer :all])) 15 | 16 | (defn pubkey-sha1 17 | "Gets the SHA-1 digest of the raw bytes of the provided publickey." 18 | [pub-key] 19 | {:pre [(public-key? pub-key)] 20 | :post [(vector? %) 21 | (every? integer? %)]} 22 | (let [bytes (-> ^PublicKey 23 | pub-key 24 | .getEncoded 25 | SubjectPublicKeyInfo/getInstance 26 | .getPublicKeyData 27 | .getBytes)] 28 | (vec (.digest (MessageDigest/getInstance "SHA1") bytes)))) 29 | 30 | (defn open-ssl-file 31 | [filepath] 32 | (resource (str "puppetlabs/ssl_utils/examples/ssl/" filepath))) 33 | 34 | (defn write-to-pem-stream 35 | ([object] (write-to-pem-stream object obj->pem!)) 36 | ([object write-function] 37 | (let [pem-stream (ByteArrayOutputStream.)] 38 | (write-function object pem-stream) 39 | (-> pem-stream 40 | (.toByteArray) 41 | (ByteArrayInputStream.))))) 42 | 43 | (defmulti has-subject? 44 | "Returns true if x has the subject identified by the x500-name string or `X500Name`. 45 | Default implementations are provided for `X509Certificate` and `PKCS10CertificationRequest`." 46 | (fn [x x500-name] 47 | [(class x) (class x500-name)])) 48 | 49 | (defmethod has-subject? [X509Certificate String] 50 | [cert x500-name] 51 | (= x500-name (-> ^X509Certificate cert .getSubjectX500Principal .getName))) 52 | 53 | (defmethod has-subject? [X509Certificate X500Name] 54 | [cert x500-name] 55 | (has-subject? cert (str x500-name))) 56 | 57 | (defmethod has-subject? [PKCS10CertificationRequest String] 58 | [csr x500-name] 59 | (= x500-name (-> csr .getSubject str))) 60 | 61 | (defmethod has-subject? [PKCS10CertificationRequest X500Name] 62 | [csr x500-name] 63 | (= x500-name (.getSubject csr))) 64 | 65 | (defmulti issued-by? 66 | "Returns true if x was issued by the x500-name string or `X500Name`. 67 | Default implementations are provided for `X509Certificate` and `X509CRL`." 68 | (fn [_ x500-name] 69 | (class x500-name))) 70 | 71 | (defmethod issued-by? String 72 | [x x500-name] 73 | (= x500-name (-> x .getIssuerX500Principal .getName))) 74 | 75 | (defmethod issued-by? X500Name 76 | [x x500-name] 77 | (issued-by? x (str x500-name))) 78 | 79 | (defn generate-past-date [] 80 | (-> (DateTime/now) 81 | (.minus (Period/days 1)) 82 | (.toDate))) 83 | 84 | (defn generate-not-before-date [] 85 | (generate-past-date)) 86 | 87 | (defn generate-future-date [] 88 | (-> (DateTime/now) 89 | (.plus (Period/years 5)) 90 | (.toDate))) 91 | 92 | (defn generate-not-after-date [] 93 | (generate-future-date)) 94 | 95 | (defn str->bytes 96 | "Turn a `String s` into `bytes[]`" 97 | [^String s] 98 | (bytes (byte-array (map (comp byte int) s)))) 99 | 100 | (defn generate-expired-crl 101 | [issuer issuer-private-key issuer-public-key] 102 | (SSLUtils/generateCRL issuer issuer-private-key issuer-public-key 103 | (.toDate (DateTime/now)) 104 | (generate-past-date) 105 | BigInteger/ZERO 106 | nil)) 107 | 108 | (defn generate-not-yet-valid-crl 109 | [issuer issuer-private-key issuer-public-key] 110 | (SSLUtils/generateCRL issuer issuer-private-key issuer-public-key 111 | (generate-future-date) 112 | (generate-future-date) 113 | BigInteger/ZERO 114 | nil)) 115 | 116 | (defn generate-newer-crl 117 | [issuer issuer-private-key issuer-public-key] 118 | (SSLUtils/generateCRL issuer issuer-private-key issuer-public-key 119 | (.toDate (DateTime/now)) 120 | (generate-future-date) 121 | BigInteger/ONE 122 | nil)) 123 | 124 | (defn generate-newest-crl 125 | [issuer issuer-private-key issuer-public-key] 126 | (SSLUtils/generateCRL issuer issuer-private-key issuer-public-key 127 | (.toDate (DateTime/now)) 128 | (generate-future-date) 129 | BigInteger/TEN 130 | nil)) 131 | 132 | ;; This does not contain delta CRL content, just the delta CRL indicator, 133 | ;; so should only be used for testing purposes. 134 | (defn generate-delta-crl 135 | [issuer issuer-private-key issuer-public-key] 136 | (SSLUtils/generateCRL issuer issuer-private-key issuer-public-key 137 | (.toDate (DateTime/now)) 138 | (generate-future-date) 139 | BigInteger/ONE 140 | [(javaize (delta-crl-indicator BigInteger/ZERO))])) 141 | 142 | (defn create-truncated-subject-key-identifier 143 | [key] 144 | {:oid subject-key-identifier-oid 145 | :critical false 146 | :value key 147 | :options {:truncate true}}) 148 | 149 | (defn create-truncated-authority-key-identifier 150 | [key] 151 | {:oid authority-key-identifier-oid 152 | :critical false 153 | :value {:public-key key 154 | :serial-number nil 155 | :issuer-dn nil 156 | :cert nil} 157 | :options {:truncate true}}) 158 | 159 | (defn swap-extension 160 | [extensions extension] 161 | (-> (remove #(= (:oid extension) (:oid %)) extensions) 162 | (conj extension))) 163 | 164 | (defn generate-crl-with-bad-signature 165 | [issuer _ _] 166 | (let [random-keys (generate-key-pair 2048) 167 | public-key (get-public-key random-keys) 168 | private-key (get-private-key random-keys)] 169 | (SSLUtils/generateCRL issuer private-key public-key))) 170 | 171 | (defn generate-multiple-crls 172 | [issuer issuer-private-key issuer-public-key] 173 | {:original (generate-crl issuer issuer-private-key issuer-public-key) 174 | :new (generate-newer-crl issuer issuer-private-key issuer-public-key) 175 | :newest (generate-newest-crl issuer issuer-private-key issuer-public-key)}) 176 | 177 | (defn generate-ca-cert 178 | [issuer-name issuer-key-pair serial root?] 179 | (let [subject-name (if root? 180 | issuer-name 181 | (cn (format "Intermediate CA %d" serial))) 182 | key-pair (if root? 183 | issuer-key-pair 184 | (generate-key-pair 2048)) 185 | public-key (get-public-key key-pair) 186 | not-before (generate-not-before-date) 187 | not-after (generate-not-after-date) 188 | cert (sign-certificate issuer-name (get-private-key issuer-key-pair) 189 | serial not-before not-after subject-name public-key 190 | (create-ca-extensions (get-public-key issuer-key-pair) public-key))] 191 | [cert key-pair])) 192 | 193 | (defn generate-cert-chain-with-crls 194 | ([number-of-certs] 195 | (generate-cert-chain-with-crls number-of-certs 196 | generate-crl 197 | (generate-key-pair 2048))) 198 | ([number-of-certs generate-crl-fn] 199 | (generate-cert-chain-with-crls number-of-certs 200 | generate-crl-fn 201 | (generate-key-pair 2048))) 202 | ([number-of-certs generate-crl-fn root-key-pair] 203 | (let [root-public-key (get-public-key root-key-pair) 204 | root-private-key (get-private-key root-key-pair) 205 | root-name (cn "Root CA") 206 | root-cert (first (generate-ca-cert root-name root-key-pair 666 true)) 207 | root-crl (generate-crl-fn (X500Principal. root-name) 208 | root-private-key root-public-key)] 209 | (loop [certs [root-cert] 210 | crls [root-crl] 211 | certs-to-generate (dec number-of-certs) 212 | issuer root-cert 213 | issuer-key-pair root-key-pair] 214 | (if (< certs-to-generate 1) 215 | [certs crls issuer-key-pair] 216 | (let [[new-cert new-key-pair] (generate-ca-cert 217 | (cn (get-cn-from-x509-certificate issuer)) 218 | issuer-key-pair 219 | certs-to-generate 220 | false) 221 | new-private-key (get-private-key new-key-pair) 222 | new-public-key (get-public-key new-key-pair) 223 | new-crl (generate-crl-fn (.getSubjectX500Principal ^X509Certificate new-cert) 224 | new-private-key new-public-key)] 225 | (recur (cons new-cert certs) 226 | (cons new-crl crls) 227 | (dec certs-to-generate) 228 | new-cert 229 | new-key-pair))))))) 230 | 231 | (defn generate-cert-chain-with-revoked-cert 232 | [number-of-certs] 233 | (when (< number-of-certs 2) 234 | (throw (Exception. (format "Can't perform revocations on a %d-cert chain." 235 | number-of-certs)))) 236 | (let [root-key-pair (generate-key-pair 2048) 237 | [certs crls leaf-keys] (generate-cert-chain-with-crls number-of-certs 238 | generate-crl 239 | root-key-pair) 240 | cert-to-revoke (nth certs (- number-of-certs 2)) 241 | crl-to-update (last crls) 242 | updated-crl (revoke crl-to-update 243 | (get-private-key root-key-pair) 244 | (get-public-key root-key-pair) 245 | (get-serial cert-to-revoke))] 246 | [certs (-> crls drop-last (conj updated-crl) leaf-keys)])) 247 | 248 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 249 | ;;; Writing test files 250 | 251 | ;; The following helpers can be used to create test fixtures via the repl. 252 | ;; To start the repl, run `lein repl`. 253 | ;; Within the repl, run the following (with your desired function and arguments): 254 | ;; ``` 255 | ;; (require '[puppetlabs.ssl-utils.testutils :as t]) 256 | ;; (t/write-valid-cert-chain-and-crls 3 "your-subpath") 257 | ;; ``` 258 | 259 | (def test-files-path "test-resources/puppetlabs/ssl_utils/examples/ssl") 260 | 261 | (defn write-certs-and-crls 262 | [certs crls test-subpath certs-filename crls-filename] 263 | (let [dir-path (fs/file test-files-path test-subpath) 264 | certs-path (fs/file dir-path certs-filename) 265 | crls-path (fs/file dir-path crls-filename)] 266 | (fs/mkdirs dir-path) 267 | (objs->pem! certs certs-path) 268 | (objs->pem! crls crls-path))) 269 | 270 | (defn write-valid-cert-chain-and-crls 271 | [number-of-certs test-subpath] 272 | (let [certs-filename (str number-of-certs "-cert-chain.pem") 273 | crls-filename (str number-of-certs "-crl-chain.pem") 274 | [certs crls _] (generate-cert-chain-with-crls number-of-certs)] 275 | (write-certs-and-crls certs crls test-subpath certs-filename crls-filename))) 276 | 277 | (defn write-expired-crl 278 | [test-subpath] 279 | (let [cert-filename "cert-with-expired-crl.pem" 280 | crl-filename "expired-crl.pem" 281 | [cert expired-crl _] (generate-cert-chain-with-crls 1 generate-expired-crl)] 282 | (write-certs-and-crls cert expired-crl test-subpath cert-filename crl-filename))) 283 | 284 | (defn write-not-yet-valid-crl 285 | [test-subpath] 286 | (let [cert-filename "cert-with-not-valid-crl.pem" 287 | crl-filename "not-yet-valid-crl.pem" 288 | [cert crl _] (generate-cert-chain-with-crls 1 generate-not-yet-valid-crl)] 289 | (write-certs-and-crls cert crl test-subpath cert-filename crl-filename))) 290 | 291 | (defn write-crl-with-bad-sig 292 | [test-subpath] 293 | (let [cert-filename "cert-with-crl-bad-sig.pem" 294 | crl-filename "crl-with-bad-signature.pem" 295 | [cert bad-crl _] (generate-cert-chain-with-crls 1 generate-crl-with-bad-signature)] 296 | (write-certs-and-crls cert bad-crl test-subpath cert-filename crl-filename))) 297 | 298 | (defn write-cert-chain-with-revoked-cert 299 | [number-of-certs test-subpath] 300 | (let [certs-filename "cert-chain-with-revoked-cert.pem" 301 | crls-filename "crl-chain-with-cert-revoked.pem" 302 | [certs crls] (generate-cert-chain-with-revoked-cert number-of-certs)] 303 | (write-certs-and-crls certs crls test-subpath certs-filename crls-filename))) 304 | 305 | (defn write-bundle-for-manual-validation 306 | [number-of-certs output-dir] 307 | (let [[certs crls-with-updates leaf-keys] (generate-cert-chain-with-crls 308 | number-of-certs 309 | generate-multiple-crls) 310 | original-crls (map :original crls-with-updates) 311 | new-crls (map :new crls-with-updates) 312 | newest-crls (map :newest crls-with-updates)] 313 | (fs/mkdirs output-dir) 314 | ;; The file names `ca-bundle.pem`, `crls.pem`, and `puppet_ca_key.pem` are used 315 | ;; in the instructions for setting up an intermediate CA with an external root 316 | ;; (https://puppet.com/docs/puppet/latest/server/intermediate_ca.html#set-up-puppet-as-an-intermediate-ca-with-an-external-root), 317 | ;; which should allow for easily copy-pasting the example `import` command. 318 | (objs->pem! certs (fs/file output-dir "ca-bundle.pem")) 319 | (objs->pem! original-crls (fs/file output-dir "crls.pem")) 320 | (objs->pem! new-crls (fs/file output-dir "new-crls.pem")) 321 | (objs->pem! newest-crls (fs/file output-dir "newest-crls.pem")) 322 | (key->pem! (get-private-key leaf-keys) (fs/file output-dir "puppet_ca_key.pem")) 323 | (key->pem! (get-public-key leaf-keys) (fs/file output-dir "puppet_ca_pubkey.pem")))) 324 | -------------------------------------------------------------------------------- /src/java/com/puppetlabs/ssl_utils/ExtensionsUtils.java: -------------------------------------------------------------------------------- 1 | package com.puppetlabs.ssl_utils; 2 | 3 | import org.bouncycastle.asn1.ASN1Encodable; 4 | import org.bouncycastle.asn1.ASN1Object; 5 | import org.bouncycastle.asn1.ASN1ObjectIdentifier; 6 | import org.bouncycastle.asn1.ASN1OctetString; 7 | import org.bouncycastle.asn1.ASN1Primitive; 8 | import org.bouncycastle.asn1.ASN1Sequence; 9 | import org.bouncycastle.asn1.ASN1Set; 10 | import org.bouncycastle.asn1.ASN1String; 11 | import org.bouncycastle.asn1.ASN1TaggedObject; 12 | import org.bouncycastle.asn1.DERBitString; 13 | import org.bouncycastle.asn1.DERIA5String; 14 | import org.bouncycastle.asn1.DEROctetString; 15 | import org.bouncycastle.asn1.DERUTF8String; 16 | import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; 17 | import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 18 | import org.bouncycastle.asn1.pkcs.Attribute; 19 | import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 20 | import org.bouncycastle.asn1.x500.X500Name; 21 | import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 22 | import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; 23 | import org.bouncycastle.asn1.x509.BasicConstraints; 24 | import org.bouncycastle.asn1.x509.CRLNumber; 25 | import org.bouncycastle.asn1.x509.ExtendedKeyUsage; 26 | import org.bouncycastle.asn1.x509.Extension; 27 | import org.bouncycastle.asn1.x509.Extensions; 28 | import org.bouncycastle.asn1.x509.GeneralName; 29 | import org.bouncycastle.asn1.x509.GeneralNames; 30 | import org.bouncycastle.asn1.x509.KeyPurposeId; 31 | import org.bouncycastle.asn1.x509.KeyUsage; 32 | import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; 33 | import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 34 | import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; 35 | import org.bouncycastle.cert.X509CRLHolder; 36 | import org.bouncycastle.cert.X509CertificateHolder; 37 | import org.bouncycastle.cert.X509ExtensionUtils; 38 | import org.bouncycastle.operator.DigestCalculator; 39 | import org.bouncycastle.operator.OperatorCreationException; 40 | import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; 41 | import org.bouncycastle.pkcs.PKCS10CertificationRequest; 42 | 43 | import java.io.IOException; 44 | import java.math.BigInteger; 45 | import java.net.InetAddress; 46 | import java.net.UnknownHostException; 47 | import java.nio.charset.Charset; 48 | import java.security.PublicKey; 49 | import java.security.cert.CRLException; 50 | import java.security.cert.CertificateEncodingException; 51 | import java.security.cert.X509CRL; 52 | import java.security.cert.X509Certificate; 53 | import java.util.ArrayList; 54 | import java.util.Arrays; 55 | import java.util.HashMap; 56 | import java.util.HashSet; 57 | import java.util.List; 58 | import java.util.Map; 59 | import java.util.Set; 60 | 61 | /** 62 | * Utilities for working with X509 extensions. 63 | */ 64 | public class ExtensionsUtils { 65 | public static class AttributeDescriptor { 66 | public String oid; 67 | public ArrayList values; 68 | 69 | AttributeDescriptor(){ 70 | this.values = new ArrayList(); 71 | } 72 | } 73 | /** 74 | * CRLNumber OID 2.5.29.20 75 | */ 76 | public static final String CRL_NUMBER_OID = Extension.cRLNumber.toString(); 77 | 78 | /** 79 | * AuthorityKeyIdentifier OID 2.5.29.35 80 | */ 81 | public static final String AUTHORITY_KEY_IDENTIFIER_OID = 82 | Extension.authorityKeyIdentifier.toString(); 83 | 84 | /** 85 | * SubjectKeyIdentifier OID 2.5.29.14 86 | */ 87 | public static final String SUBJECT_KEY_IDENTIFIER_OID = 88 | Extension.subjectKeyIdentifier.toString(); 89 | 90 | /** 91 | * SubjectAlternativeName OID 2.5.29.17 92 | */ 93 | public static final String SUBJECT_ALTERNATIVE_NAME_OID = 94 | Extension.subjectAlternativeName.toString(); 95 | 96 | /** 97 | * DeltaCRLIndicator OID 2.5.29.27 98 | */ 99 | public static final String DELTA_CRL_INDICATOR_OID = 100 | Extension.deltaCRLIndicator.toString(); 101 | 102 | /** 103 | * Return true if the given OID is contained within the subtree of parent OID. 104 | * 105 | * @param parentOid The OID of the parent tree. 106 | * @param oid The OID to compare. 107 | * @return True if OID is a subtree 108 | */ 109 | public static boolean isSubtreeOf(String parentOid, String oid) { 110 | String[] parentParts = parentOid.split("\\."); 111 | String[] oidParts = oid.split("\\."); 112 | 113 | if (parentParts.length >= oidParts.length) { 114 | return false; 115 | } else { 116 | for (int i=0; i < parentParts.length; i++) { 117 | if (!parentParts[i].equals(oidParts[i])) { 118 | return false; 119 | } 120 | } 121 | return true; 122 | } 123 | } 124 | 125 | /** 126 | * Given a Java X509Certificate object, return a list of maps representing 127 | * all the X509 extensions embedded in the certificate. If no extensions 128 | * exist on the certificate, then null is returned. 129 | * 130 | * @param cert The X509 certificate object. 131 | * @return A list of maps describing each extensions in the provided 132 | * certificate. 133 | * @throws IOException 134 | * @throws CertificateEncodingException 135 | * @see #getExtensionList(Extensions) 136 | */ 137 | public static List> getExtensionList(X509Certificate cert) 138 | throws IOException, CertificateEncodingException 139 | { 140 | Extensions extensions = getExtensionsFromCert(cert); 141 | 142 | if (extensions != null) { 143 | return getExtensionList(extensions); 144 | } else { 145 | return null; 146 | } 147 | } 148 | 149 | /** 150 | * Given a Java X509CRL object, return a list of maps representing 151 | * all the X509 extensions embedded in the CRL. If no extensions 152 | * exist on the CRL, then null is returned. 153 | * 154 | * @param crl The X509 CRL object. 155 | * @return A list of maps describing each extensions in the provided CRL. 156 | * @throws IOException 157 | * @throws CRLException 158 | * @see #getExtensionList(Extensions) 159 | */ 160 | public static List> getExtensionList(X509CRL crl) 161 | throws IOException, CRLException 162 | { 163 | Extensions extensions = getExtensionsFromCRL(crl); 164 | 165 | if (extensions != null) { 166 | return getExtensionList(extensions); 167 | } else { 168 | return null; 169 | } 170 | } 171 | 172 | /** 173 | * Given a Bouncy Castle CSR object, return a list of maps representing 174 | * all the X509 extensions embedded in the CSR. If no extensions exist on 175 | * the CSR, then null is returned. 176 | * 177 | * @param csr The Bouncy Castle CertificationRequest object 178 | * @return A list of maps describing each extensions in the provided 179 | * certificate. 180 | * @throws IOException 181 | * @see #getExtensionList(Extensions) 182 | */ 183 | public static List> getExtensionList(PKCS10CertificationRequest csr) 184 | throws IOException 185 | { 186 | Extensions extensions = getExtensionsFromCSR(csr); 187 | 188 | if (extensions != null) { 189 | return getExtensionList(extensions); 190 | } else{ 191 | return null; 192 | } 193 | } 194 | 195 | /** 196 | * Given a bouncy Castle Certification Request, extract the attributes from that 197 | * request 198 | * @param csr - Bouncy Castle certification request 199 | * @return an array of attributes in the CSR 200 | */ 201 | public static AttributeDescriptor[] getAttributesList(PKCS10CertificationRequest csr) throws IOException { 202 | Attribute[] attr = csr.getAttributes(); 203 | AttributeDescriptor[] result = new AttributeDescriptor[(attr.length)]; 204 | for (int i = 0; i < attr.length; i++){ 205 | result[i] = makeAttributeDescriptor(attr[i]); 206 | } 207 | return result; 208 | } 209 | 210 | /** 211 | * Given a Java certificate, get a map containing the value 212 | * and criticality of the extensions described by the given OID. If the OID 213 | * is not found in the certificate then null is returned. 214 | * 215 | * @param cert The Java X509 certificate object. 216 | * @param oid The OID of the extension to be found. 217 | * @return The map containing the extension value and critical flag. 218 | * @throws IOException 219 | * @throws CertificateEncodingException 220 | */ 221 | public static Map getExtension(X509Certificate cert, String oid) 222 | throws IOException, CertificateEncodingException 223 | { 224 | Extensions extensions = getExtensionsFromCert(cert); 225 | 226 | if (extensions != null) { 227 | return makeExtensionMap(extensions, new ASN1ObjectIdentifier(oid)); 228 | } else { 229 | return null; 230 | } 231 | } 232 | 233 | /** 234 | * Given a Java X509CRL object, get a map containing the value and 235 | * criticality of the extensions described by the given OID. If the OID 236 | * is not found in the CRL, then null is returned. If no extensions exist 237 | * on the CRL, then null is returned. 238 | * 239 | * @param crl The X509 CRL object. 240 | * @param oid The OID of the extension to be found. 241 | * @return The map containing the extension value and critical flag. 242 | * @throws IOException 243 | * @throws CRLException 244 | */ 245 | public static Map getExtension(X509CRL crl, String oid) 246 | throws IOException, CRLException 247 | { 248 | Extensions extensions = getExtensionsFromCRL(crl); 249 | 250 | if (extensions != null) { 251 | return makeExtensionMap(extensions, new ASN1ObjectIdentifier(oid)); 252 | } else { 253 | return null; 254 | } 255 | } 256 | 257 | /** 258 | * Given a Bouncy Castle CSR, get a map describing an extension value and 259 | * its criticality from its OID. If the extension is not found then null 260 | * is returned. 261 | * 262 | * @param csr The Bouncy Castle CSR to extract an extension from. 263 | * @param oid The OID of extension to find. 264 | * @return A map describing the extension requested by its OID. 265 | * @throws IOException 266 | */ 267 | public static Map getExtension(PKCS10CertificationRequest csr, String oid) 268 | throws IOException 269 | { 270 | Extensions extensions = getExtensionsFromCSR(csr); 271 | 272 | if (extensions != null) { 273 | return makeExtensionMap(extensions, new ASN1ObjectIdentifier(oid)); 274 | } else { 275 | return null; 276 | } 277 | } 278 | 279 | /** 280 | * Given a list of maps describing extensions, return a map containing 281 | * the extensions described by the provided OID. Returns null if the OID 282 | * doesn't exist in the provided list. 283 | * 284 | * @param extList A list of extensions returned by getExtensionList(). 285 | * @param oid The OID of the extension to find. 286 | * @return The map describing the found extension, null if the oid doesn't exist. 287 | * @see #getExtensionList(org.bouncycastle.asn1.x509.Extensions) 288 | * @see #getExtensionList(java.security.cert.X509Certificate) 289 | */ 290 | public static Map getExtension(List> extList, 291 | String oid) 292 | { 293 | for (Map ext: extList) { 294 | if (ext.get("oid").equals(oid)) { 295 | return ext; 296 | } 297 | } 298 | 299 | return null; 300 | } 301 | 302 | public static Object getExtensionValue(X509Certificate cert, String oid) 303 | throws IOException, CertificateEncodingException 304 | { 305 | return getExtensionValue(getExtension(cert, oid)); 306 | } 307 | 308 | public static Object getExtensionValue(X509CRL crl, String oid) 309 | throws IOException, CRLException 310 | { 311 | return getExtensionValue(getExtension(crl, oid)); 312 | } 313 | 314 | public static Object getExtensionValue(PKCS10CertificationRequest csr, 315 | String oid) 316 | throws IOException 317 | { 318 | return getExtensionValue(getExtension(csr, oid)); 319 | } 320 | 321 | public static Object getExtensionValue(List> extList, 322 | String oid) 323 | { 324 | return getExtensionValue(getExtension(extList, oid)); 325 | } 326 | 327 | public static Object getExtensionValue(Map extMap) { 328 | if (extMap != null) { 329 | return extMap.get("value"); 330 | } else { 331 | return null; 332 | } 333 | } 334 | 335 | /** 336 | * Given a Bouncy Castle Extensions container, return a list of maps 337 | * representing all the X509 extensions embedded in the certificate. 338 | * 339 | * @param exts A Bouncy Castle Extensions container object. 340 | * @return A list of maps describing each extensions in the provided 341 | * certificate. 342 | * @throws IOException 343 | */ 344 | private static List> getExtensionList(Extensions exts) 345 | throws IOException 346 | { 347 | List> ret = new ArrayList>(); 348 | 349 | for (ASN1ObjectIdentifier oid : exts.getCriticalExtensionOIDs()) { 350 | ret.add(makeExtensionMap(exts, oid, true)); 351 | } 352 | 353 | for (ASN1ObjectIdentifier oid : exts.getNonCriticalExtensionOIDs()) { 354 | ret.add(makeExtensionMap(exts, oid, false)); 355 | } 356 | 357 | return ret; 358 | } 359 | 360 | /** 361 | * Given an extensions container and an OID, extract the value and 362 | * criticality flag and return the values in a map. If the extension is not 363 | * found then null is returned. 364 | * 365 | * @param exts The Bouncy Castle extensions container. 366 | * @param oid The OID of the extension to find. 367 | * @return A map 368 | * @throws IOException 369 | */ 370 | private static Map makeExtensionMap(Extensions exts, 371 | ASN1ObjectIdentifier oid) 372 | throws IOException 373 | { 374 | boolean critical = Arrays.asList(exts.getCriticalExtensionOIDs()).contains(oid); 375 | return makeExtensionMap(exts, oid, critical); 376 | } 377 | 378 | /** 379 | * Find the X509 Extensions from CSR object. If no extensions 380 | * attribute is found then null is returned. 381 | * 382 | * @param csr The CSR object to extract the Extensions container from. 383 | * @return An extensions container extracted form the CSR. 384 | */ 385 | static Extensions getExtensionsFromCSR(PKCS10CertificationRequest csr) { 386 | Attribute[] attrs = csr.getAttributes(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest); 387 | for (Attribute attr : attrs) { 388 | ASN1Set extsAsn1 = attr.getAttrValues(); 389 | if (extsAsn1 != null) { 390 | ASN1Encodable extObj = extsAsn1.getObjectAt(0); 391 | return Extensions.getInstance(extObj); 392 | } 393 | } 394 | 395 | return null; 396 | } 397 | 398 | /** 399 | * Given a list of maps which represent Extensions, produce a Bouncy Castle 400 | * Extensions object which contains each extension parsed into Bouncy Castle 401 | * Extension objects. 402 | * 403 | * @return The results Extensions container. 404 | * @see #parseExtensionObject(java.util.Map) 405 | */ 406 | static Extensions getExtensionsObjFromMap(List> extMapsList) 407 | throws IOException, OperatorCreationException, CertificateEncodingException { 408 | if ((extMapsList != null) && (extMapsList.size() > 0)) { 409 | List ret = new ArrayList(); 410 | for (Map extObj : extMapsList) { 411 | ret.add(parseExtensionObject(extObj)); 412 | } 413 | 414 | return new Extensions(ret.toArray(new Extension[ret.size()])); 415 | } else { 416 | return null; 417 | } 418 | } 419 | 420 | /** 421 | * Provided a map which describes an X509 extension, parse it into a 422 | * Bouncy Castle Extension object. 423 | * 424 | * @param extMap Map describing an extension. 425 | * @return A parsed Extension object. 426 | * @throws IOException 427 | */ 428 | @SuppressWarnings("unchecked") 429 | static Extension parseExtensionObject(Map extMap) 430 | throws IOException, OperatorCreationException, CertificateEncodingException 431 | { 432 | String oidString = (String)extMap.get("oid"); 433 | ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(oidString); 434 | Boolean isCritical = (Boolean) extMap.get("critical"); 435 | 436 | if (oid.equals((Object) Extension.subjectAlternativeName) || 437 | oid.equals((Object) Extension.issuerAlternativeName)) { 438 | @SuppressWarnings("unchecked") 439 | Map> val = (Map>) extMap.get("value"); 440 | return new Extension(oid, isCritical, new DEROctetString(mapToGeneralNames(val))); 441 | } else if (oid.equals((Object) MiscObjectIdentifiers.netscapeCertComment)) { 442 | DERIA5String ia5Str = new DERIA5String((String) extMap.get("value")); 443 | return new Extension(oid, isCritical, new DEROctetString(ia5Str)); 444 | } else if (oid.equals((Object) Extension.keyUsage)) { 445 | Set val = (Set) extMap.get("value"); 446 | return new Extension(oid, isCritical, new DEROctetString(setToKeyUsage(val))); 447 | } else if (oid.equals((Object) Extension.extendedKeyUsage)) { 448 | List list = (List) extMap.get("value"); 449 | return new Extension(oid, isCritical, new DEROctetString(listToExtendedKeyUsage(list))); 450 | } else if (oid.equals((Object) Extension.basicConstraints)) { 451 | Map val = (Map) extMap.get("value"); 452 | return new Extension(oid, isCritical, new DEROctetString(mapToBasicConstraints(val))); 453 | } else if (oid.equals((Object) Extension.subjectKeyIdentifier)) { 454 | PublicKey pubKey = (PublicKey) extMap.get("value"); 455 | Map options = (Map) extMap.get("options"); 456 | if (options == null) { 457 | return new Extension(oid, isCritical, 458 | new DEROctetString(publicKeyToSubjectKeyIdentifier(pubKey, false))); 459 | } 460 | Boolean truncate = (Boolean) options.get("truncate"); 461 | return new Extension(oid, isCritical, 462 | new DEROctetString(publicKeyToSubjectKeyIdentifier(pubKey, truncate))); 463 | } else if (oid.equals((Object) Extension.authorityKeyIdentifier)) { 464 | Map val = (Map) extMap.get("value"); 465 | Map options = (Map) extMap.get("options"); 466 | if (options == null) { 467 | return new Extension(oid, isCritical, new DEROctetString(mapToAuthorityKeyIdentifier(val, false))); 468 | } 469 | Boolean truncate = (Boolean) options.get("truncate"); 470 | return new Extension(oid, isCritical, new DEROctetString(mapToAuthorityKeyIdentifier(val, truncate))); 471 | } else if (oid.equals((Object) Extension.cRLNumber)) { 472 | BigInteger number = (BigInteger) extMap.get("value"); 473 | return new Extension(oid, false, new DEROctetString( 474 | new CRLNumber(number))); 475 | } else if (oid.equals((Object) Extension.deltaCRLIndicator)) { 476 | BigInteger baseCRLNumber = (BigInteger) extMap.get("value"); 477 | return new Extension(oid, true, new DEROctetString( 478 | new CRLNumber(baseCRLNumber))); 479 | } else { 480 | // If the OID isn't recognized, then just parse the value as a string 481 | String value = (String) extMap.get("value"); 482 | return new Extension(oid, isCritical, new DEROctetString( 483 | new DERUTF8String(value))); 484 | } 485 | } 486 | 487 | /** 488 | * Get a Bouncy Castle Extensions container from a Java X509 certificate 489 | * object. If no extensions are found then null is returned. 490 | * 491 | * @param cert The Java X509 certificate object. 492 | * @return A Bouncy Castle Extensions container object extracted from the 493 | * certificate. 494 | * @throws CertificateEncodingException 495 | * @throws IOException 496 | */ 497 | private static Extensions getExtensionsFromCert(X509Certificate cert) 498 | throws CertificateEncodingException, IOException 499 | { 500 | return new X509CertificateHolder(cert.getEncoded()).getExtensions(); 501 | } 502 | 503 | /** 504 | * Get a Bouncy Castle Extensions container from a Java X509 CRL 505 | * object. If no extensions are found then null is returned. 506 | * 507 | * @param crl The Java X509 CRL object. 508 | * @return A Bouncy Castle Extensions container object extracted from the 509 | * CRL. 510 | * @throws CRLException 511 | * @throws IOException 512 | */ 513 | private static Extensions getExtensionsFromCRL(X509CRL crl) 514 | throws CRLException, IOException 515 | { 516 | return new X509CRLHolder(crl.getEncoded()).getExtensions(); 517 | } 518 | 519 | /** 520 | * Given an Extensions container, an OID, and a critical flag, create a map 521 | * of this extension's data with the following keys: 522 | * 523 | * - "oid" : The OID of the extensions 524 | * - "value" : A String, or list of Strings of this OID's data 525 | * - "critical" : A bool set to true if this extensions is critical, 526 | * false if it isn't. 527 | * 528 | * If the given OID doesn't exist in the extensions container then null is 529 | * returned. 530 | * 531 | * @param exts A Bouncy Castle Extensions container containing the provided OID 532 | * @param oid The OID of the extension to create the map for. 533 | * @param critical True if this extension is critical, false if it isn't. 534 | * @return A map representing the extension with the given OID which exists 535 | * in the provided Extensions container. 536 | * @throws IOException 537 | */ 538 | private static Map makeExtensionMap(Extensions exts, 539 | ASN1ObjectIdentifier oid, 540 | boolean critical) 541 | throws IOException 542 | { 543 | Extension ext = exts.getExtension(oid); 544 | if (ext != null) { 545 | byte[] extensionData = ext.getExtnValue().getOctets(); 546 | ASN1Object asn1Value = binaryToASN1Object(oid, extensionData); 547 | 548 | HashMap ret = new HashMap(); 549 | ret.put("oid", oid.getId()); 550 | ret.put("critical", critical); 551 | ret.put("value", asn1ObjToObj(asn1Value)); 552 | 553 | return ret; 554 | } else { 555 | return null; 556 | } 557 | } 558 | 559 | private static AttributeDescriptor makeAttributeDescriptor(Attribute attr) throws IOException { 560 | AttributeDescriptor result = new AttributeDescriptor(); 561 | result.oid = attr.getAttrType().getId(); 562 | for (ASN1Encodable attributeValue : attr.getAttributeValues()) { 563 | result.values.add(asn1ObjToObj(attributeValue)); 564 | } 565 | return result; 566 | } 567 | 568 | /** 569 | * Convert a chunk of binary data into the Bouncy Castle ASN1 data structure 570 | * which represents the data it contains accord to its OID. I've searched 571 | * all over the BouncyCastle API and I can't seem to find this mapping 572 | * defined anywhere, so I've created it here. 573 | * 574 | * @param oid The extension OID. 575 | * @param data The binary data value of the extension with the given OID. 576 | * @return An ASN1Object which contains the data described by the 577 | * provided OID. 578 | * @throws IOException 579 | */ 580 | private static ASN1Object binaryToASN1Object(ASN1ObjectIdentifier oid, 581 | byte[] data) 582 | throws IOException 583 | { 584 | if (oid.equals((Object) Extension.subjectAlternativeName) || 585 | oid.equals((Object) Extension.issuerAlternativeName)) 586 | { 587 | return GeneralNames.getInstance(data); 588 | } else if (oid.equals((Object) Extension.authorityKeyIdentifier)) { 589 | return AuthorityKeyIdentifier.getInstance(data); 590 | } else if (oid.equals((Object) Extension.subjectKeyIdentifier)) { 591 | return SubjectKeyIdentifier.getInstance(data); 592 | } else if (oid.equals((Object) Extension.basicConstraints)) { 593 | return BasicConstraints.getInstance(data); 594 | } else if (oid.equals((Object) Extension.keyUsage)) { 595 | DERBitString bs = (DERBitString) ASN1Primitive.fromByteArray(data); 596 | return KeyUsage.getInstance(bs); 597 | } else if (oid.equals((Object) Extension.extendedKeyUsage)) { 598 | return ExtendedKeyUsage.getInstance(data); 599 | } else if (oid.equals((Object) MiscObjectIdentifiers.netscapeCertComment)) { 600 | try { 601 | return ASN1Primitive.fromByteArray(data); 602 | } catch (IOException e) { 603 | // Sometimes the comment field is not properly wrapped in an IA5String 604 | return new DERIA5String(new String(data, Charset.forName("US-ASCII"))); 605 | } 606 | } else if (oid.equals((Object) Extension.cRLNumber)) { 607 | return CRLNumber.getInstance(data); 608 | } else { 609 | try { 610 | // If the oid is unknown, use the base primitive conversion 611 | return ASN1Primitive.fromByteArray(data); 612 | } catch (Exception e) { 613 | // This is required to maintain backwards compatibility with 614 | // the erroneous method that Puppet previously used to sign 615 | // trusted facts into the cert. 616 | return new DERUTF8String(new String(data, Charset.forName("US-ASCII"))); 617 | } 618 | } 619 | } 620 | 621 | /** 622 | * Convert a Bouncy Castle ASN1Object into a Java data structure, which 623 | * will generally be in the form of a string, map, list or combination thereof. 624 | * If this method can't determine a method of converting the ASN1 object then 625 | * the raw byte array is returned. 626 | * 627 | * @param asn1Prim The ASN1 object to 628 | * @return A Java data structure which represents the provided ASN1Object. 629 | * @throws IOException 630 | */ 631 | private static Object asn1ObjToObj(ASN1Encodable asn1Prim) 632 | throws IOException 633 | { 634 | if (asn1Prim instanceof GeneralNames) { 635 | return generalNamesToMap((GeneralNames) asn1Prim); 636 | } else if (asn1Prim instanceof ASN1ObjectIdentifier) { 637 | return ((ASN1ObjectIdentifier)asn1Prim).getId(); 638 | } else if (asn1Prim instanceof AuthorityKeyIdentifier) { 639 | return authorityKeyIdToMap((AuthorityKeyIdentifier) asn1Prim); 640 | } else if (asn1Prim instanceof BasicConstraints) { 641 | return basicConstraintsToMap((BasicConstraints) asn1Prim); 642 | } else if (asn1Prim instanceof CRLNumber) { 643 | CRLNumber crlNumber = (CRLNumber) asn1Prim; 644 | return crlNumber.getCRLNumber(); 645 | } else if (asn1Prim instanceof SubjectKeyIdentifier) { 646 | SubjectKeyIdentifier ski = (SubjectKeyIdentifier) asn1Prim; 647 | return ski.getKeyIdentifier(); 648 | } else if (asn1Prim instanceof ExtendedKeyUsage) { 649 | return extKeyUsageToList((ExtendedKeyUsage) asn1Prim); 650 | } else if (asn1Prim instanceof KeyPurposeId) { 651 | KeyPurposeId kpi = (KeyPurposeId) asn1Prim; 652 | return kpi.getId(); 653 | } else if (asn1Prim instanceof KeyUsage) { 654 | KeyUsage ku = (KeyUsage)asn1Prim; 655 | return keyUsageToSet(ku); 656 | } else if (asn1Prim instanceof DERBitString) { 657 | DERBitString bitString = (DERBitString)asn1Prim; 658 | return bitString.getString(); 659 | } else if (asn1Prim instanceof ASN1Sequence) { 660 | return asn1SeqToList((ASN1Sequence) asn1Prim); 661 | } else if (asn1Prim instanceof ASN1String) { 662 | ASN1String str = (ASN1String)asn1Prim; 663 | return str.getString(); 664 | } else if (asn1Prim instanceof ASN1OctetString) { 665 | return ASN1Primitive.fromByteArray(((ASN1OctetString) asn1Prim).getOctets()).toString(); 666 | } else if (asn1Prim instanceof X500Name) { 667 | X500Name name = (X500Name) asn1Prim; 668 | return name.toString(); 669 | } else { 670 | // Return the raw data if there's no clear method of decoding 671 | return asn1Prim.toASN1Primitive().getEncoded(); 672 | } 673 | } 674 | 675 | private static final Map keyUsageFlags = 676 | new HashMap() {{ 677 | put("digital_signature", KeyUsage.digitalSignature); 678 | put("non_repudiation", KeyUsage.nonRepudiation); 679 | put("key_encipherment", KeyUsage.keyEncipherment); 680 | put("data_encipherment", KeyUsage.dataEncipherment); 681 | put("key_agreement", KeyUsage.keyAgreement); 682 | put("key_cert_sign", KeyUsage.keyCertSign); 683 | put("crl_sign", KeyUsage.cRLSign); 684 | put("encipher_only", KeyUsage.encipherOnly); 685 | put("decipher_only", KeyUsage.decipherOnly); 686 | }}; 687 | 688 | private static Set keyUsageToSet(KeyUsage ku) { 689 | Set ret = new HashSet(); 690 | for (String key : keyUsageFlags.keySet()) { 691 | if (ku.hasUsages(keyUsageFlags.get(key))) { 692 | ret.add(key); 693 | } 694 | } 695 | return ret; 696 | } 697 | 698 | private static KeyUsage setToKeyUsage(Set flags) { 699 | int usageBitString = 0; 700 | 701 | for (String key: flags) { 702 | Integer flagBit = keyUsageFlags.get(key); 703 | 704 | if (flagBit == null) { 705 | throw new IllegalArgumentException( 706 | "The provided usage key does not exist: '" + key + "'"); 707 | } 708 | 709 | usageBitString |= flagBit; 710 | } 711 | 712 | return new KeyUsage(usageBitString); 713 | } 714 | 715 | private static ExtendedKeyUsage listToExtendedKeyUsage(List oidList) { 716 | List usages = new ArrayList(); 717 | 718 | for (String oid : oidList) { 719 | usages.add(KeyPurposeId.getInstance(new ASN1ObjectIdentifier(oid))); 720 | } 721 | 722 | return new ExtendedKeyUsage(usages.toArray(new KeyPurposeId[usages.size()])); 723 | } 724 | 725 | private static List extKeyUsageToList(ExtendedKeyUsage eku) 726 | throws IOException 727 | { 728 | List ret = new ArrayList(); 729 | for (KeyPurposeId kpid : eku.getUsages()) { 730 | ret.add(asn1ObjToObj(kpid)); 731 | } 732 | return ret; 733 | } 734 | 735 | private static Map basicConstraintsToMap(BasicConstraints bc) { 736 | Map ret = new HashMap(); 737 | ret.put("is_ca", bc.isCA()); 738 | ret.put("path_len_constraint", bc.getPathLenConstraint()); 739 | return ret; 740 | } 741 | 742 | private static BasicConstraints mapToBasicConstraints(Map bcMap) { 743 | Boolean isCa = (Boolean) bcMap.get("is_ca"); 744 | if (isCa == null) { 745 | throw new IllegalArgumentException( 746 | "The 'is_ca' key must be present in a basic constraint."); 747 | } 748 | 749 | BasicConstraints bc; 750 | Integer pathLenConstraint = (Integer) bcMap.get("path_len_constraint"); 751 | if (pathLenConstraint != null) { 752 | if (!isCa) { 753 | throw new IllegalArgumentException( 754 | "The 'path_len_constraint' key is not supported for " + 755 | "an 'is_ca' value of 'false'"); 756 | } 757 | bc = new BasicConstraints(pathLenConstraint); 758 | } 759 | else { 760 | bc = new BasicConstraints(isCa); 761 | } 762 | 763 | return bc; 764 | } 765 | 766 | private static SubjectKeyIdentifier publicKeyToSubjectKeyIdentifier(PublicKey publicKey, 767 | Boolean truncate) 768 | throws OperatorCreationException { 769 | SubjectPublicKeyInfo pubKeyInfo = 770 | SubjectPublicKeyInfo.getInstance(publicKey.getEncoded()); 771 | 772 | DigestCalculator digCalc = new JcaDigestCalculatorProviderBuilder().build() 773 | .get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)); 774 | 775 | X509ExtensionUtils utils = new JcaX509ExtensionUtils(digCalc); 776 | if (truncate) { 777 | return utils.createTruncatedSubjectKeyIdentifier(pubKeyInfo); 778 | } 779 | return utils.createSubjectKeyIdentifier(pubKeyInfo); 780 | } 781 | 782 | private static JcaX509ExtensionUtils extensionUtils() 783 | throws OperatorCreationException { 784 | DigestCalculator digCalc = 785 | new JcaDigestCalculatorProviderBuilder().build().get( 786 | new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)); 787 | return new JcaX509ExtensionUtils(digCalc); 788 | } 789 | 790 | private static AuthorityKeyIdentifier authKeyIdFromPubKey( 791 | PublicKey pubKey, Boolean truncateKey) 792 | throws OperatorCreationException { 793 | SubjectPublicKeyInfo authPubKeyInfo = 794 | SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()); 795 | 796 | JcaX509ExtensionUtils utils = extensionUtils(); 797 | if (truncateKey) { 798 | byte[] shortKey = utils.createTruncatedSubjectKeyIdentifier( 799 | authPubKeyInfo).getKeyIdentifier(); 800 | return new AuthorityKeyIdentifier(shortKey); 801 | } 802 | else { 803 | return utils.createAuthorityKeyIdentifier(authPubKeyInfo); 804 | } 805 | 806 | } 807 | 808 | private static Boolean ensureValidArgsForAuthKeyIssuer(BigInteger serialNumber, 809 | String issuer, 810 | PublicKey pubKey) 811 | throws IllegalArgumentException { 812 | if (pubKey == null && serialNumber == null) { 813 | /* This is a little funny but since this is called in the conditional 814 | for `cert == null` we know that cert has not been provided and can 815 | say so in the Exception */ 816 | throw new IllegalArgumentException( 817 | "Neither 'public_key', 'serial_number', or 'cert' provided for " + 818 | "auth key identifier. At least one of these must be " + 819 | "provided."); 820 | } 821 | if (issuer == null) { 822 | if (serialNumber != null) { 823 | throw new IllegalArgumentException( 824 | "'issuer' not provided for auth key identifier " + 825 | "but was expected since 'serial_number' was provided"); 826 | } 827 | } 828 | else { 829 | if (serialNumber == null) { 830 | throw new IllegalArgumentException( 831 | "'serial_number' not provided for auth key identifier" + 832 | "but was expected since 'issuer' was provided"); 833 | } 834 | return true; 835 | } 836 | return false; 837 | } 838 | 839 | private static AuthorityKeyIdentifier authKeyIdFromIssuer(String issuer, 840 | AuthorityKeyIdentifier authorityKeyId, 841 | BigInteger serialNumber) 842 | throws OperatorCreationException { 843 | GeneralNames issuerAsGeneralNames = 844 | new GeneralNames(new GeneralName(new X500Name(issuer))); 845 | if (authorityKeyId != null) { 846 | return new AuthorityKeyIdentifier(authorityKeyId.getKeyIdentifier(), 847 | issuerAsGeneralNames, 848 | serialNumber); 849 | } 850 | else { 851 | return new AuthorityKeyIdentifier(issuerAsGeneralNames, 852 | serialNumber); 853 | } 854 | } 855 | 856 | private static AuthorityKeyIdentifier mapToAuthorityKeyIdentifier(Map authKeyIdMap, 857 | Boolean truncate) 858 | throws OperatorCreationException, CertificateEncodingException, IOException { 859 | AuthorityKeyIdentifier authorityKeyId = null; 860 | X509Certificate cert = (X509Certificate) authKeyIdMap.get("cert"); 861 | 862 | if (cert == null) { 863 | PublicKey pubKey = (PublicKey) authKeyIdMap.get ("public_key"); 864 | if (pubKey != null) { 865 | authorityKeyId = authKeyIdFromPubKey(pubKey, truncate); 866 | } 867 | BigInteger serialNumber = (BigInteger) authKeyIdMap.get("serial_number"); 868 | String issuer = (String) authKeyIdMap.get ("issuer_dn"); 869 | if (ensureValidArgsForAuthKeyIssuer(serialNumber, issuer, pubKey) == true) { 870 | authorityKeyId = authKeyIdFromIssuer(issuer, authorityKeyId, serialNumber); 871 | } 872 | } 873 | else { 874 | JcaX509ExtensionUtils utils = extensionUtils(); 875 | // This copies the the field for the SubjectKeyIdentifier from the cert and uses 876 | // that data to generate an AuthorityKeyIdentifier to be added to the signed cert. 877 | authorityKeyId = utils.createAuthorityKeyIdentifier(new X509CertificateHolder(cert.getEncoded())); 878 | } 879 | 880 | return authorityKeyId; 881 | } 882 | 883 | private static Map authorityKeyIdToMap(AuthorityKeyIdentifier akid) 884 | throws IOException 885 | { 886 | Map ret = new HashMap(); 887 | ret.put("issuer", generalNamesToMap(akid.getAuthorityCertIssuer())); 888 | ret.put("serial_number", akid.getAuthorityCertSerialNumber()); 889 | ret.put("key_identifier", akid.getKeyIdentifier()); 890 | return ret; 891 | } 892 | 893 | /** 894 | * Convert an ASN1 Sequence to a Java list. 895 | * 896 | * @param seq The ASN1 sequence to be converted. 897 | * @return A List of parsed ASN1 objects contained in the provided sequence. 898 | * @throws IOException 899 | */ 900 | private static List asn1SeqToList(ASN1Sequence seq) 901 | throws IOException 902 | { 903 | List ret = new ArrayList(); 904 | 905 | for (int i=0; i < seq.size(); i++) { 906 | ret.add(asn1ObjToObj(seq.getObjectAt(i))); 907 | } 908 | 909 | return ret; 910 | } 911 | 912 | /** The key name each tag number represents in a GeneralNames data structure */ 913 | private static final Map generalNameTags = 914 | new HashMap() {{ 915 | put(0, "other_name"); 916 | put(1, "rfc822_name"); 917 | put(2, "dns_name"); 918 | put(3, "x400_address"); 919 | put(4, "directory_name"); 920 | put(5, "edi_party_name"); 921 | put(6, "uri"); 922 | put(7, "ip"); 923 | put(8, "registered_id"); 924 | }}; 925 | 926 | /** 927 | * Given type name, return the general name tag value. 928 | * 929 | * @param name The GeneralName tag name defined in generalNameTags 930 | * @return The tag number of the name, or null if the name doesn't exist. 931 | */ 932 | private static Integer getGnTagFromName(String name) { 933 | for (int i=0; i < generalNameTags.size(); i++) { 934 | if (generalNameTags.get(i).equalsIgnoreCase(name)) { 935 | return i; 936 | } 937 | } 938 | 939 | return null; 940 | } 941 | 942 | /** 943 | * Convert the value of an IP address which is encoded in an 944 | * ASN1OctetString to a string. 945 | * 946 | * @param ip IP address encoded in an octet string. 947 | * @return A string representing the given IP address. 948 | */ 949 | public static String octetStringToIpString(ASN1OctetString ip) 950 | throws UnknownHostException { 951 | return InetAddress.getByAddress(ip.getOctets()).toString().split("/")[1]; 952 | } 953 | 954 | /** 955 | * Convert a Bouncy Castle GeneralNames object into a Java map where the key 956 | * is the type of name defined, and the value is a list of names of that type. 957 | * 958 | * @param names The GeneralNames object to be parsed. 959 | * @return A list of the names contained in each GeneralName in the 960 | * GeneralNames data structure. 961 | * @throws IOException 962 | * @see org.bouncycastle.asn1.x509.GeneralName 963 | */ 964 | private static Map> generalNamesToMap(GeneralNames names) 965 | throws IOException 966 | { 967 | if (names != null) { 968 | Map> ret = new HashMap>(); 969 | for (GeneralName generalName : names.getNames()) { 970 | String type = generalNameTags.get(generalName.getTagNo()); 971 | if (ret.get(type) == null) { 972 | ret.put(type, new ArrayList()); 973 | } 974 | 975 | String name; 976 | switch (generalName.getTagNo()) { 977 | case GeneralName.iPAddress: 978 | name = octetStringToIpString((ASN1OctetString)generalName.getName()); 979 | break; 980 | default: 981 | name = asn1ObjToObj(generalName.getName()).toString(); 982 | break; 983 | } 984 | 985 | ret.get(type).add(name); 986 | } 987 | 988 | return ret; 989 | } else { 990 | return null; 991 | } 992 | } 993 | 994 | /** 995 | * Convert a list of general name maps into a GeneralNames object. 996 | * 997 | * @param gnMap A map containing name types and a list of names. 998 | * @return A Bouncy Castle GeneralNames object. 999 | * @see #generalNamesToMap(org.bouncycastle.asn1.x509.GeneralNames) 1000 | */ 1001 | private static GeneralNames mapToGeneralNames(Map> gnMap) { 1002 | List ret = new ArrayList(); 1003 | for (String type: gnMap.keySet()) { 1004 | Integer tag = getGnTagFromName(type); 1005 | 1006 | if (tag == null) { 1007 | throw new IllegalArgumentException( 1008 | "Could not find a tag number for the type name '" + 1009 | type + '"'); 1010 | } 1011 | 1012 | for (String name: gnMap.get(type)) { 1013 | ret.add(new GeneralName(tag, name)); 1014 | } 1015 | 1016 | } 1017 | return new GeneralNames(ret.toArray(new GeneralName[ret.size()])); 1018 | } 1019 | } 1020 | --------------------------------------------------------------------------------