nitlsconfig 1.0.0a1__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,20 @@
1
+ Copyright (c) 2022, National Instruments Corp.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included
12
+ in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.3
2
+ Name: nitlsconfig
3
+ Version: 1.0.0a1
4
+ Summary: Python API for reading nitlsconfig configurations and creating gRPC client channels from them
5
+ License: MIT
6
+ Keywords: nitlsconfig,tls,mtls,grpc,configuration
7
+ Author: NI
8
+ Author-email: opensource@ni.com
9
+ Maintainer: Philip Thong
10
+ Maintainer-email: philip.thong@emerson.com
11
+ Requires-Python: >=3.9
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Provides-Extra: grpc
25
+ Requires-Dist: grpcio (>=1.49.0,<2.0) ; extra == "grpc"
26
+ Project-URL: Repository, https://github.com/ni/nitlsconfig-python
27
+ Description-Content-Type: text/markdown
28
+
29
+ # nitlsconfig
30
+
31
+ Python API that reads nitlsconfig configurations through the `nitlsconfig` command line,
32
+ and builds gRPC client channels from them.
33
+
34
+ Installed and imported as `nitlsconfig`; developed at
35
+ [ni/nitlsconfig-python](https://github.com/ni/nitlsconfig-python).
36
+
37
+ ## Runtime dependencies
38
+
39
+ - nitlsconfig executable, discoverable, or explicit path to NITLSCONFIG_CLI
40
+
41
+ ## Install
42
+
43
+ Reading NI-TLS configuration is pure Python and has no third-party dependencies:
44
+
45
+ - `pip install nitlsconfig`
46
+
47
+ The gRPC channel factory additionally needs grpcio, which is an optional extra:
48
+
49
+ - `pip install nitlsconfig[grpc]`
50
+
51
+ ## Creating a gRPC channel
52
+
53
+ `create_grpc_client_channel` reads the local NI-TLS client configuration and returns a
54
+ `grpc.Channel` secured accordingly. The `server_address` hostname or address is used to
55
+ select matching target-specific NI-TLS settings. Pass the channel straight to any NI
56
+ gRPC Python API:
57
+
58
+ ```python
59
+ import nidcpower
60
+ import nitlsconfig
61
+
62
+ with nitlsconfig.create_grpc_client_channel("localhost", 31763) as channel:
63
+ options = nidcpower.GrpcSessionOptions(channel, "")
64
+ with nidcpower.Session("Dev1", grpc_options=options) as session:
65
+ ...
66
+ ```
67
+
68
+ The channel is mutually authenticated, one-way TLS, or insecure depending on how
69
+ the machine is configured; no code change is needed to move between them. The
70
+ channel is owned by the caller - NI driver APIs never close it.
71
+
72
+ Retries are opt-in:
73
+
74
+ ```python
75
+ channel = nitlsconfig.create_grpc_client_channel(
76
+ "localhost", 31763, retry_policy=nitlsconfig.RetryPolicy()
77
+ )
78
+ ```
79
+
80
+ `TlsConfigurationError` is raised when TLS is enabled but the configuration is
81
+ unusable. Accessing any of these names without the `grpc` extra installed raises
82
+ `ImportError` telling you which extra to install.
83
+
84
+ ## Reading configurations
85
+ ```python
86
+ import nitlsconfig
87
+
88
+ # List configured services
89
+ clients = nitlsconfig.ClientConfig.list_services()
90
+ servers = nitlsconfig.ServerConfig.list_services()
91
+
92
+ if clients:
93
+ # Read one client configuration
94
+ client_info = nitlsconfig.ClientConfig(clients[0])
95
+ print(client_info.service_name)
96
+ print(client_info.certificate_mode)
97
+ print(client_info.certificate_chain_location.scheme)
98
+ print(client_info.certificate_chain_location.path)
99
+ print(client_info.certificate_chain_contents)
100
+
101
+ # Inspect target-specific configurations
102
+ for known_server in client_info.known_servers:
103
+ print(known_server.server_name)
104
+ print(known_server.server_mode)
105
+ print(known_server.trusted_certificates_location)
106
+
107
+ if servers:
108
+ # Read one server configuration
109
+ server_info = nitlsconfig.ServerConfig(servers[0])
110
+ print(server_info.service_name)
111
+ print(server_info.certificate_mode)
112
+ print(server_info.client_mode)
113
+ print(server_info.certificate_chain_location.scheme)
114
+ print(server_info.certificate_key_location.scheme)
115
+ print(server_info.trusted_certificates_location.scheme)
116
+ print(server_info.trusted_certificates_contents)
117
+ print(server_info.certificate_key_contents)
118
+
119
+ # Enumerate trusted certificates
120
+ for cert in server_info.trusted_certificates:
121
+ print(cert.display_name)
122
+ print(cert.trusted_certificate_location.path)
123
+ print(cert.trusted_certificate_contents)
124
+ ```
125
+
126
+
127
+
@@ -0,0 +1,98 @@
1
+ # nitlsconfig
2
+
3
+ Python API that reads nitlsconfig configurations through the `nitlsconfig` command line,
4
+ and builds gRPC client channels from them.
5
+
6
+ Installed and imported as `nitlsconfig`; developed at
7
+ [ni/nitlsconfig-python](https://github.com/ni/nitlsconfig-python).
8
+
9
+ ## Runtime dependencies
10
+
11
+ - nitlsconfig executable, discoverable, or explicit path to NITLSCONFIG_CLI
12
+
13
+ ## Install
14
+
15
+ Reading NI-TLS configuration is pure Python and has no third-party dependencies:
16
+
17
+ - `pip install nitlsconfig`
18
+
19
+ The gRPC channel factory additionally needs grpcio, which is an optional extra:
20
+
21
+ - `pip install nitlsconfig[grpc]`
22
+
23
+ ## Creating a gRPC channel
24
+
25
+ `create_grpc_client_channel` reads the local NI-TLS client configuration and returns a
26
+ `grpc.Channel` secured accordingly. The `server_address` hostname or address is used to
27
+ select matching target-specific NI-TLS settings. Pass the channel straight to any NI
28
+ gRPC Python API:
29
+
30
+ ```python
31
+ import nidcpower
32
+ import nitlsconfig
33
+
34
+ with nitlsconfig.create_grpc_client_channel("localhost", 31763) as channel:
35
+ options = nidcpower.GrpcSessionOptions(channel, "")
36
+ with nidcpower.Session("Dev1", grpc_options=options) as session:
37
+ ...
38
+ ```
39
+
40
+ The channel is mutually authenticated, one-way TLS, or insecure depending on how
41
+ the machine is configured; no code change is needed to move between them. The
42
+ channel is owned by the caller - NI driver APIs never close it.
43
+
44
+ Retries are opt-in:
45
+
46
+ ```python
47
+ channel = nitlsconfig.create_grpc_client_channel(
48
+ "localhost", 31763, retry_policy=nitlsconfig.RetryPolicy()
49
+ )
50
+ ```
51
+
52
+ `TlsConfigurationError` is raised when TLS is enabled but the configuration is
53
+ unusable. Accessing any of these names without the `grpc` extra installed raises
54
+ `ImportError` telling you which extra to install.
55
+
56
+ ## Reading configurations
57
+ ```python
58
+ import nitlsconfig
59
+
60
+ # List configured services
61
+ clients = nitlsconfig.ClientConfig.list_services()
62
+ servers = nitlsconfig.ServerConfig.list_services()
63
+
64
+ if clients:
65
+ # Read one client configuration
66
+ client_info = nitlsconfig.ClientConfig(clients[0])
67
+ print(client_info.service_name)
68
+ print(client_info.certificate_mode)
69
+ print(client_info.certificate_chain_location.scheme)
70
+ print(client_info.certificate_chain_location.path)
71
+ print(client_info.certificate_chain_contents)
72
+
73
+ # Inspect target-specific configurations
74
+ for known_server in client_info.known_servers:
75
+ print(known_server.server_name)
76
+ print(known_server.server_mode)
77
+ print(known_server.trusted_certificates_location)
78
+
79
+ if servers:
80
+ # Read one server configuration
81
+ server_info = nitlsconfig.ServerConfig(servers[0])
82
+ print(server_info.service_name)
83
+ print(server_info.certificate_mode)
84
+ print(server_info.client_mode)
85
+ print(server_info.certificate_chain_location.scheme)
86
+ print(server_info.certificate_key_location.scheme)
87
+ print(server_info.trusted_certificates_location.scheme)
88
+ print(server_info.trusted_certificates_contents)
89
+ print(server_info.certificate_key_contents)
90
+
91
+ # Enumerate trusted certificates
92
+ for cert in server_info.trusted_certificates:
93
+ print(cert.display_name)
94
+ print(cert.trusted_certificate_location.path)
95
+ print(cert.trusted_certificate_contents)
96
+ ```
97
+
98
+
@@ -0,0 +1,110 @@
1
+ [project]
2
+ name = "nitlsconfig"
3
+ version = "1.0.0a1"
4
+ license = "MIT"
5
+ description = "Python API for reading nitlsconfig configurations and creating gRPC client channels from them"
6
+ authors = [{name = "NI", email = "opensource@ni.com"}]
7
+ maintainers = [
8
+ {name = "Philip Thong", email = "philip.thong@emerson.com"},
9
+ ]
10
+ readme = "README.md"
11
+ keywords = ["nitlsconfig", "tls", "mtls", "grpc", "configuration"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Operating System :: Microsoft :: Windows",
17
+ "Operating System :: POSIX",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.9",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ ]
26
+ requires-python = ">=3.9"
27
+ dynamic = ["dependencies"]
28
+
29
+ # Reading NI-TLS configuration is pure Python. Only nitlsconfig.grpc_channel
30
+ # needs grpcio, so the binary wheel is opt-in.
31
+ [project.optional-dependencies]
32
+ grpc = ["grpcio>=1.49.0,<2.0"]
33
+
34
+ [project.urls]
35
+ repository = "https://github.com/ni/nitlsconfig-python"
36
+
37
+ [build-system]
38
+ requires = ["poetry-core>=1.9.0"]
39
+ build-backend = "poetry.core.masonry.api"
40
+
41
+ [tool.poetry]
42
+ packages = [{ include = "nitlsconfig", from = "src" }]
43
+ requires-poetry = '>=2.1,<3.0'
44
+
45
+ [tool.poetry.dependencies]
46
+ python = ">=3.9,<4.0"
47
+
48
+
49
+ [tool.poetry.group.lint.dependencies]
50
+ bandit = { version = ">=1.7", extras = ["toml"] }
51
+ ni-python-styleguide = ">=0.4.1"
52
+ mypy = ">=1.0"
53
+ pyright = { version = ">=1.1.400", extras = ["nodejs"] }
54
+
55
+ [tool.poetry.group.test.dependencies]
56
+ pytest = ">=7.2"
57
+ pytest-cov = ">=4.0"
58
+ pytest-mock = ">=3.0"
59
+ pytest-env = ">=1.0,<2.0"
60
+ cryptography = ">=41.0"
61
+
62
+ [tool.poetry.group.docs]
63
+ optional = true
64
+
65
+ [tool.poetry.group.docs.dependencies]
66
+ # The latest Sphinx requires a recent Python version.
67
+ Sphinx = [
68
+ { version = ">=8.1", python = ">=3.10,<3.11" },
69
+ { version = ">=8.2", python = "^3.11" },
70
+ ]
71
+ sphinx-rtd-theme = ">=1.0.0"
72
+ sphinx-autoapi = ">=1.8.4"
73
+ m2r2 = ">=0.3.2"
74
+ toml = ">=0.10.2"
75
+
76
+ [tool.poetry.scripts]
77
+ nitlsconfig-read = "nitlsconfig.cli:nitlsconfig_main"
78
+
79
+ [tool.pytest_env]
80
+ env_files = [".env"]
81
+
82
+ [tool.ni-python-styleguide]
83
+ extend_exclude = ".tox,docs"
84
+ application-import-names = "nitlsconfig,tests"
85
+
86
+ [tool.black]
87
+ extend-exclude = '\.tox/|docs/'
88
+ line-length = 100
89
+
90
+ [tool.mypy]
91
+ files = "src/nitlsconfig/,tests/"
92
+ namespace_packages = true
93
+ strict = true
94
+
95
+ [[tool.mypy.overrides]]
96
+ # grpcio does not ship a py.typed marker.
97
+ module = "grpc.*"
98
+ ignore_missing_imports = true
99
+
100
+ [tool.bandit]
101
+ skips = [
102
+ "B101", # assert_used
103
+ ]
104
+
105
+ [tool.pytest.ini_options]
106
+ addopts = "--doctest-modules --strict-markers"
107
+ testpaths = ["src/nitlsconfig", "tests"]
108
+
109
+ [tool.pyright]
110
+ include = ["src/", "tests/"]
@@ -0,0 +1,97 @@
1
+ """Python package to read settings from nitlsconfig and build connections from them.
2
+
3
+ Reading configuration is pure Python and has no third-party dependencies. The
4
+ gRPC channel factory needs grpcio, which is an optional extra::
5
+
6
+ pip install nitlsconfig[grpc]
7
+
8
+ The gRPC names below are therefore resolved lazily: importing this package never
9
+ imports grpcio, so a caller that only reads NI-TLS configuration does not pay
10
+ for a binary dependency it will not use. Additional transports can be added the
11
+ same way without changing what a bare install requires.
12
+ """
13
+
14
+ from importlib.metadata import version
15
+ from importlib.util import find_spec
16
+ from typing import TYPE_CHECKING, Any
17
+
18
+ from nitlsconfig.cli import (
19
+ CertificateLocation,
20
+ ClientCertMode,
21
+ ClientConfig,
22
+ ClientServerMode,
23
+ CommandFailedError,
24
+ ExecutableNotFoundError,
25
+ InvalidOutputError,
26
+ LocationScheme,
27
+ NitlsconfigCliError,
28
+ ServerCertMode,
29
+ ServerClientMode,
30
+ ServerConfig,
31
+ TrustedCertificateData,
32
+ KnownServerData,
33
+ )
34
+
35
+ if TYPE_CHECKING:
36
+ # Imported eagerly for type checkers and editors, which do not run __getattr__.
37
+ from nitlsconfig.grpc_channel import (
38
+ DEFAULT_SERVICE_NAME,
39
+ RetryPolicy,
40
+ TlsConfigurationError,
41
+ create_grpc_client_channel,
42
+ )
43
+
44
+ __version__ = version("nitlsconfig")
45
+
46
+ # Names re-exported from nitlsconfig.grpc_channel, which requires grpcio.
47
+ # A plain list literal, because pyright only tracks __all__ through a small set
48
+ # of literal forms; anything computed makes it give up on the export list.
49
+ _GRPC_EXPORTS = [
50
+ "DEFAULT_SERVICE_NAME",
51
+ "RetryPolicy",
52
+ "TlsConfigurationError",
53
+ "create_grpc_client_channel",
54
+ ]
55
+
56
+ __all__ = [
57
+ "__version__",
58
+ "CertificateLocation",
59
+ "ClientCertMode",
60
+ "ClientConfig",
61
+ "ClientServerMode",
62
+ "LocationScheme",
63
+ "ServerCertMode",
64
+ "ServerClientMode",
65
+ "ServerConfig",
66
+ "NitlsconfigCliError",
67
+ "ExecutableNotFoundError",
68
+ "CommandFailedError",
69
+ "InvalidOutputError",
70
+ "TrustedCertificateData",
71
+ "KnownServerData",
72
+ ]
73
+
74
+ # The gRPC names are public API, but only on an install that can supply them.
75
+ # Listing them unconditionally would make `from nitlsconfig import *` raise
76
+ # ImportError without the grpc extra, since star-import resolves every name in
77
+ # __all__. find_spec only locates grpcio; it does not import it, so the lazy
78
+ # __getattr__ below still decides when grpcio is actually loaded.
79
+ if find_spec("grpc") is not None:
80
+ # pyright only tracks __all__ through inline literals, so it cannot follow
81
+ # this and warns that the export list may be incomplete. The TYPE_CHECKING
82
+ # block above already declares these names for static consumers.
83
+ __all__ += _GRPC_EXPORTS # pyright: ignore[reportUnsupportedDunderAll]
84
+
85
+
86
+ def __getattr__(name: str) -> Any:
87
+ """Resolve gRPC exports on first use, so importing this package does not need grpcio."""
88
+ if name in _GRPC_EXPORTS:
89
+ try:
90
+ from nitlsconfig import grpc_channel
91
+ except ImportError as exc: # pragma: no cover - requires an install without the extra
92
+ raise ImportError(
93
+ f"nitlsconfig.{name} requires grpcio, which is not installed. "
94
+ "Install it with: pip install nitlsconfig[grpc]"
95
+ ) from exc
96
+ return getattr(grpc_channel, name)
97
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")