lemur-ca-import 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+
2
+ The MIT License (MIT)
3
+
4
+ Copyright (c) 2026 Philippe Desmarais
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.4
2
+ Name: lemur-ca-import
3
+ Version: 0.0.1
4
+ Summary: A plugin for Lemur that allows users to import existing CA certificates into the system.
5
+ Author-email: Philippe Desmarais <philippe.desmarais4@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/desmaraisp/lemur-ca-import
8
+ Project-URL: Issues, https://github.com/desmaraisp/lemur-ca-import/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE.md
14
+ Requires-Dist: lemur>=1.7.0
15
+ Requires-Dist: flask>=2.3.0
16
+ Provides-Extra: tests
17
+ Requires-Dist: pytest; extra == "tests"
18
+ Requires-Dist: setuptools; extra == "tests"
19
+ Dynamic: license-file
20
+
21
+ # lemur-ca-import
22
+
23
+ A [Lemur](https://github.com/netflix/lemur) plugin that allows users to import existing CA certificates into the system, which can then be used to issue certificates without interacting with remote systems.
24
+
25
+ ## Installation
26
+
27
+ Install from PyPI:
28
+
29
+ ```bash
30
+ pip install lemur-ca-importer
31
+ ```
32
+
33
+ Or from source in development mode:
34
+
35
+ ```bash
36
+ pip install -e .
37
+ ```
38
+
39
+ With test dependencies:
40
+
41
+ ```bash
42
+ pip install -e '.[tests]'
43
+ ```
44
+
45
+ ## Testing
46
+
47
+ Run the test suite:
48
+
49
+ ```bash
50
+ python -m pytest
51
+ ```
52
+
53
+ ## Building
54
+
55
+ Build distributions locally:
56
+
57
+ ```bash
58
+ python -m build
59
+ ```
60
+
61
+ This generates both sdist and wheel in `dist/`.
62
+
63
+ To control the package version, set the `CA_IMPORTER_VERSION` environment variable:
64
+
65
+ ```bash
66
+ CA_IMPORTER_VERSION=1.2.3 python -m build
67
+ ```
68
+
69
+ ## Publishing
70
+
71
+ The package uses GitHub Actions for automated CI/CD:
72
+
73
+ - **PR builds** (`.github/workflows/pr-build.yml`): Tests and builds on each PR targeting `main`. Artifacts are uploaded and linked in the PR.
74
+ - **Release publishing** (`.github/workflows/release.yml`): Tests, builds, and publishes to PyPI on each GitHub release. Uses OIDC trusted publishing (no long-lived tokens).
75
+
76
+ ## Usage
77
+
78
+ The `CAImporterPlugin` is registered as a Lemur issuer plugin via entry point `ca_importer`. Configure it in Lemur by providing:
79
+
80
+ - **public_certificate**: External CA certificate in PEM format
81
+ - **private_key**: External CA private key in PEM format
82
+
83
+ The plugin creates an authority bound to the imported CA certificate and generates admin/operator roles.
84
+
@@ -0,0 +1,64 @@
1
+ # lemur-ca-import
2
+
3
+ A [Lemur](https://github.com/netflix/lemur) plugin that allows users to import existing CA certificates into the system, which can then be used to issue certificates without interacting with remote systems.
4
+
5
+ ## Installation
6
+
7
+ Install from PyPI:
8
+
9
+ ```bash
10
+ pip install lemur-ca-importer
11
+ ```
12
+
13
+ Or from source in development mode:
14
+
15
+ ```bash
16
+ pip install -e .
17
+ ```
18
+
19
+ With test dependencies:
20
+
21
+ ```bash
22
+ pip install -e '.[tests]'
23
+ ```
24
+
25
+ ## Testing
26
+
27
+ Run the test suite:
28
+
29
+ ```bash
30
+ python -m pytest
31
+ ```
32
+
33
+ ## Building
34
+
35
+ Build distributions locally:
36
+
37
+ ```bash
38
+ python -m build
39
+ ```
40
+
41
+ This generates both sdist and wheel in `dist/`.
42
+
43
+ To control the package version, set the `CA_IMPORTER_VERSION` environment variable:
44
+
45
+ ```bash
46
+ CA_IMPORTER_VERSION=1.2.3 python -m build
47
+ ```
48
+
49
+ ## Publishing
50
+
51
+ The package uses GitHub Actions for automated CI/CD:
52
+
53
+ - **PR builds** (`.github/workflows/pr-build.yml`): Tests and builds on each PR targeting `main`. Artifacts are uploaded and linked in the PR.
54
+ - **Release publishing** (`.github/workflows/release.yml`): Tests, builds, and publishes to PyPI on each GitHub release. Uses OIDC trusted publishing (no long-lived tokens).
55
+
56
+ ## Usage
57
+
58
+ The `CAImporterPlugin` is registered as a Lemur issuer plugin via entry point `ca_importer`. Configure it in Lemur by providing:
59
+
60
+ - **public_certificate**: External CA certificate in PEM format
61
+ - **private_key**: External CA private key in PEM format
62
+
63
+ The plugin creates an authority bound to the imported CA certificate and generates admin/operator roles.
64
+
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools >= 70", "build>=1.5.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "lemur-ca-import"
7
+ dynamic = ["version"]
8
+ authors = [
9
+ { name = "Philippe Desmarais", email = "philippe.desmarais4@gmail.com" },
10
+ ]
11
+ dependencies = ["lemur>=1.7.0", "flask>=2.3.0"]
12
+ description = "A plugin for Lemur that allows users to import existing CA certificates into the system."
13
+ readme = "README.md"
14
+ requires-python = ">=3.9"
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ ]
19
+ license = "MIT"
20
+ license-files = ["LICEN[CS]E*"]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/desmaraisp/lemur-ca-import"
24
+ Issues = "https://github.com/desmaraisp/lemur-ca-import/issues"
25
+
26
+
27
+ [project.entry-points."lemur.plugins"]
28
+ ca_importer = "lemur_ca_importer.plugin:CAImporterPlugin"
29
+
30
+
31
+ [project.optional-dependencies]
32
+ tests = [
33
+ "pytest","setuptools"
34
+ ]
35
+
36
+ [tool.pytest.ini_options]
37
+ filterwarnings = [
38
+ "ignore::DeprecationWarning::", # ignore deprecations from all modules
39
+ "default::DeprecationWarning:mymodule.*:", # except from our own code
40
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ import os
2
+ from setuptools import setup
3
+
4
+ package_version = os.environ.get("CA_IMPORTER_VERSION")
5
+
6
+ setup(
7
+ version=package_version if package_version else "0.0.1"
8
+ )
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.4
2
+ Name: lemur-ca-import
3
+ Version: 0.0.1
4
+ Summary: A plugin for Lemur that allows users to import existing CA certificates into the system.
5
+ Author-email: Philippe Desmarais <philippe.desmarais4@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/desmaraisp/lemur-ca-import
8
+ Project-URL: Issues, https://github.com/desmaraisp/lemur-ca-import/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE.md
14
+ Requires-Dist: lemur>=1.7.0
15
+ Requires-Dist: flask>=2.3.0
16
+ Provides-Extra: tests
17
+ Requires-Dist: pytest; extra == "tests"
18
+ Requires-Dist: setuptools; extra == "tests"
19
+ Dynamic: license-file
20
+
21
+ # lemur-ca-import
22
+
23
+ A [Lemur](https://github.com/netflix/lemur) plugin that allows users to import existing CA certificates into the system, which can then be used to issue certificates without interacting with remote systems.
24
+
25
+ ## Installation
26
+
27
+ Install from PyPI:
28
+
29
+ ```bash
30
+ pip install lemur-ca-importer
31
+ ```
32
+
33
+ Or from source in development mode:
34
+
35
+ ```bash
36
+ pip install -e .
37
+ ```
38
+
39
+ With test dependencies:
40
+
41
+ ```bash
42
+ pip install -e '.[tests]'
43
+ ```
44
+
45
+ ## Testing
46
+
47
+ Run the test suite:
48
+
49
+ ```bash
50
+ python -m pytest
51
+ ```
52
+
53
+ ## Building
54
+
55
+ Build distributions locally:
56
+
57
+ ```bash
58
+ python -m build
59
+ ```
60
+
61
+ This generates both sdist and wheel in `dist/`.
62
+
63
+ To control the package version, set the `CA_IMPORTER_VERSION` environment variable:
64
+
65
+ ```bash
66
+ CA_IMPORTER_VERSION=1.2.3 python -m build
67
+ ```
68
+
69
+ ## Publishing
70
+
71
+ The package uses GitHub Actions for automated CI/CD:
72
+
73
+ - **PR builds** (`.github/workflows/pr-build.yml`): Tests and builds on each PR targeting `main`. Artifacts are uploaded and linked in the PR.
74
+ - **Release publishing** (`.github/workflows/release.yml`): Tests, builds, and publishes to PyPI on each GitHub release. Uses OIDC trusted publishing (no long-lived tokens).
75
+
76
+ ## Usage
77
+
78
+ The `CAImporterPlugin` is registered as a Lemur issuer plugin via entry point `ca_importer`. Configure it in Lemur by providing:
79
+
80
+ - **public_certificate**: External CA certificate in PEM format
81
+ - **private_key**: External CA private key in PEM format
82
+
83
+ The plugin creates an authority bound to the imported CA certificate and generates admin/operator roles.
84
+
@@ -0,0 +1,13 @@
1
+ LICENSE.md
2
+ README.md
3
+ pyproject.toml
4
+ setup.py
5
+ src/lemur_ca_import.egg-info/PKG-INFO
6
+ src/lemur_ca_import.egg-info/SOURCES.txt
7
+ src/lemur_ca_import.egg-info/dependency_links.txt
8
+ src/lemur_ca_import.egg-info/entry_points.txt
9
+ src/lemur_ca_import.egg-info/requires.txt
10
+ src/lemur_ca_import.egg-info/top_level.txt
11
+ src/lemur_ca_importer/__init__.py
12
+ src/lemur_ca_importer/plugin.py
13
+ tests/test_ca_importer.py
@@ -0,0 +1,2 @@
1
+ [lemur.plugins]
2
+ ca_importer = lemur_ca_importer.plugin:CAImporterPlugin
@@ -0,0 +1,6 @@
1
+ lemur>=1.7.0
2
+ flask>=2.3.0
3
+
4
+ [tests]
5
+ pytest
6
+ setuptools
@@ -0,0 +1 @@
1
+ lemur_ca_importer
@@ -0,0 +1,8 @@
1
+ try:
2
+ VERSION = __import__('pkg_resources').get_distribution(__name__).version
3
+ AUTHOR = __import__('pkg_resources').get_distribution(__name__).get_metadata('PKG-INFO').split('Author: ')[1].splitlines()[0]
4
+ URL = __import__('pkg_resources').get_distribution(__name__).get_metadata('PKG-INFO').split('Home-page: ')[1].splitlines()[0]
5
+ except Exception as e:
6
+ VERSION = 'unknown'
7
+ AUTHOR = ''
8
+ URL = ''
@@ -0,0 +1,77 @@
1
+ from typing import Tuple
2
+
3
+ from flask import current_app
4
+
5
+ from lemur.common.utils import check_validation
6
+ from lemur.exceptions import InvalidConfiguration
7
+ from lemur.plugins.lemur_cryptography import plugin as lemur_cryptography
8
+ import lemur_ca_importer
9
+
10
+
11
+ class CAImporterPlugin(lemur_cryptography.CryptographyIssuerPlugin):
12
+ title = "CA Importer"
13
+ slug = "ca-importer"
14
+ description = "Enables the import of existing CA certificates into Lemur."
15
+ version = lemur_ca_importer.VERSION
16
+
17
+ options = [
18
+ {
19
+ "name": "public_certificate",
20
+ "type": "textarea",
21
+ "default": "",
22
+ "required": True,
23
+ "validation": check_validation("^-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----$"),
24
+ "helpMessage": "External CA public certificate in PEM format. This is used to build the certificate chain and is required when creating an authority.",
25
+ },
26
+ {
27
+ "name": "private_key",
28
+ "type": "textarea",
29
+ "default": "",
30
+ "required": True,
31
+ "validation": check_validation("^-----BEGIN PRIVATE KEY-----.*-----END PRIVATE KEY-----$"),
32
+ "helpMessage": "External CA private key in PEM format. With this, Lemur can sign certificates using the imported CA. This is required when creating an authority.",
33
+ }
34
+ ]
35
+
36
+ author = lemur_ca_importer.AUTHOR
37
+ author_url = lemur_ca_importer.URL
38
+
39
+ @staticmethod
40
+ def create_authority(options) -> Tuple[str, str, None, list]:
41
+ """
42
+ The authority created here is bound to a single user-provided CA certificate.
43
+
44
+ :param options:
45
+ :return:
46
+ """
47
+ current_app.logger.debug(
48
+ f"Issuing new imported authority with options: {options}"
49
+ )
50
+
51
+ plugin_options = get_plugin_options(options)
52
+ cert_pem = get_option(plugin_options, "public_certificate")
53
+ private_key = get_option(plugin_options, "private_key")
54
+
55
+ roles = [
56
+ {"username": "", "password": "", "name": options["name"] + "_admin"},
57
+ {"username": "", "password": "", "name": options["name"] + "_operator"},
58
+ ]
59
+ return cert_pem, private_key, None, roles
60
+
61
+ def get_plugin_options(options):
62
+ plugin_options = options.get("plugin", {}).get("plugin_options")
63
+ if not plugin_options:
64
+ error = f"Invalid options for ca importer plugin: {options}"
65
+ current_app.logger.error(error)
66
+ raise InvalidConfiguration(error)
67
+ return plugin_options
68
+
69
+ def get_option(plugin_options, option_name) -> str:
70
+ for option in plugin_options:
71
+ if option.get("name") == option_name:
72
+ return option.get("value")
73
+
74
+ error = f"Invalid options for ca importer plugin: {option_name}"
75
+ current_app.logger.error(error)
76
+ raise InvalidConfiguration(error)
77
+
@@ -0,0 +1,54 @@
1
+ import pytest
2
+ from flask import Flask
3
+ from lemur_ca_importer import plugin
4
+
5
+ def test_create_authority_returns_expected_roles():
6
+ app = Flask('test')
7
+ with app.app_context():
8
+ options = {
9
+ "name": "test",
10
+ "plugin": {
11
+ "plugin_options": [
12
+ {"name": "public_certificate", "value": "-----BEGIN CERTIFICATE-----FAKE"},
13
+ {"name": "private_key", "value": "FAKE"}
14
+ ]
15
+ }
16
+ }
17
+ pub, key, chain, roles = plugin.CAImporterPlugin().create_authority(options)
18
+
19
+ assert pub is not None
20
+ assert pub.startswith("-----BEGIN CERTIFICATE-----")
21
+ assert chain is None
22
+ assert key is not None
23
+ assert key is "FAKE"
24
+ assert roles[0]["name"] == "test_admin"
25
+ assert roles[1]["name"] == "test_operator"
26
+
27
+ def test_get_plugin_options_valid():
28
+ options = {"plugin": {"plugin_options": [1, 2, 3]}}
29
+ result = plugin.get_plugin_options(options)
30
+ assert result == [1, 2, 3]
31
+
32
+ def test_get_plugin_options_invalid():
33
+ options = {"plugin": {}}
34
+ app = Flask('test')
35
+ with app.app_context():
36
+ with pytest.raises(plugin.InvalidConfiguration):
37
+ plugin.get_plugin_options(options)
38
+
39
+ def test_get_option_pub_cert():
40
+ opts = [
41
+ {"name": "public_certificate", "value": "CERTDATA"},
42
+ {"name": "other", "value": "X"}
43
+ ]
44
+ result = plugin.get_option(opts, "public_certificate")
45
+ assert result == "CERTDATA"
46
+
47
+
48
+ def test_get_option_pub_cert_throws():
49
+ opts = []
50
+ app = Flask('test')
51
+
52
+ with app.app_context():
53
+ with pytest.raises(plugin.InvalidConfiguration):
54
+ plugin.get_option(opts, "public_certificate")