nitlsconfig 1.0.0__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.
- nitlsconfig-1.0.0/LICENSE +20 -0
- nitlsconfig-1.0.0/PKG-INFO +146 -0
- nitlsconfig-1.0.0/README.md +115 -0
- nitlsconfig-1.0.0/pyproject.toml +116 -0
- nitlsconfig-1.0.0/src/nitlsconfig/__init__.py +99 -0
- nitlsconfig-1.0.0/src/nitlsconfig/_service.py +12 -0
- nitlsconfig-1.0.0/src/nitlsconfig/audit.py +279 -0
- nitlsconfig-1.0.0/src/nitlsconfig/channel_tag.py +39 -0
- nitlsconfig-1.0.0/src/nitlsconfig/cli.py +617 -0
- nitlsconfig-1.0.0/src/nitlsconfig/errors.py +81 -0
- nitlsconfig-1.0.0/src/nitlsconfig/grpc_channel.py +339 -0
- nitlsconfig-1.0.0/src/nitlsconfig/py.typed +0 -0
|
@@ -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,146 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: nitlsconfig
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python API for reading nitlsconfig configurations and creating NI gRPC Device 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 :: 5 - Production/Stable
|
|
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
|
+
Requires-Dist: pywin32 (>=306) ; (sys_platform == "win32") and (extra == "grpc")
|
|
27
|
+
Project-URL: Documentation, https://nitlsconfig-python.readthedocs.io
|
|
28
|
+
Project-URL: Repository, https://github.com/ni/nitlsconfig-python
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# nitlsconfig
|
|
32
|
+
|
|
33
|
+
Python API that reads nitlsconfig configurations through the `nitlsconfig` command line,
|
|
34
|
+
and builds NI gRPC Device client channels from them.
|
|
35
|
+
|
|
36
|
+
Installed and imported as `nitlsconfig`; developed at
|
|
37
|
+
[ni/nitlsconfig-python](https://github.com/ni/nitlsconfig-python).
|
|
38
|
+
|
|
39
|
+
## Runtime dependencies
|
|
40
|
+
|
|
41
|
+
- nitlsconfig executable, discoverable.
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
Reading NI TLS configuration is pure Python and has no third-party dependencies:
|
|
46
|
+
|
|
47
|
+
- `pip install nitlsconfig`
|
|
48
|
+
|
|
49
|
+
The gRPC channel factory additionally needs grpcio, which is an optional extra:
|
|
50
|
+
|
|
51
|
+
- `pip install nitlsconfig[grpc]`
|
|
52
|
+
|
|
53
|
+
Neither install provides the `nitlsconfig` runtime itself. This package reads
|
|
54
|
+
configuration by invoking the `nitlsconfig` command line interface, which ships with NI
|
|
55
|
+
driver software products that support NI TLS. Install a driver that provides it before using
|
|
56
|
+
this package; without it, calls raise `ExecutableNotFoundError`.
|
|
57
|
+
|
|
58
|
+
## Creating a gRPC channel
|
|
59
|
+
|
|
60
|
+
`create_grpc_device_channel` reads the local NI TLS client configuration for the NI
|
|
61
|
+
gRPC Device Server and returns a `grpc.Channel` secured accordingly. The
|
|
62
|
+
`server_address` hostname or address is used to select matching target-specific NI TLS
|
|
63
|
+
settings. Pass the channel straight to any NI gRPC Python API:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
import nidcpower
|
|
67
|
+
import nitlsconfig
|
|
68
|
+
|
|
69
|
+
with nitlsconfig.create_grpc_device_channel("localhost", 31763) as channel:
|
|
70
|
+
options = nidcpower.GrpcSessionOptions(channel, "")
|
|
71
|
+
with nidcpower.Session("Dev1", grpc_options=options) as session:
|
|
72
|
+
...
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
NI driver software provides the NI TLS configuration. Using `create_grpc_device_channel`
|
|
76
|
+
opts into mTLS.
|
|
77
|
+
|
|
78
|
+
Before `create_grpc_device_channel` can succeed, use NI Hardware Manager to perform a
|
|
79
|
+
certificate exchange with the remote system. See
|
|
80
|
+
[Managing mTLS](https://www.ni.com/docs/en-US/bundle/hardwaremanager/page/mtls-manage.html)
|
|
81
|
+
for details.
|
|
82
|
+
|
|
83
|
+
Weakening the security posture to one-way TLS or to an insecure connection
|
|
84
|
+
requires explicitly changing that configuration in NI Hardware Manager. Either way, no
|
|
85
|
+
code change is needed.
|
|
86
|
+
|
|
87
|
+
The channel is owned by the caller - NI driver APIs never close it.
|
|
88
|
+
|
|
89
|
+
Retries are opt-in:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
channel = nitlsconfig.create_grpc_device_channel(
|
|
93
|
+
"localhost", 31763, retry_policy=nitlsconfig.RetryPolicy()
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`TlsConfigurationError` is raised when TLS is enabled but the configuration is
|
|
98
|
+
unusable. It is always importable, since handling it does not require grpcio.
|
|
99
|
+
|
|
100
|
+
`create_grpc_device_channel` and `RetryPolicy` do require grpcio; accessing them
|
|
101
|
+
without the `grpc` extra installed raises `ImportError` telling you which extra
|
|
102
|
+
to install.
|
|
103
|
+
|
|
104
|
+
## Reading configurations
|
|
105
|
+
```python
|
|
106
|
+
import nitlsconfig
|
|
107
|
+
|
|
108
|
+
# List configured services
|
|
109
|
+
clients = nitlsconfig.ClientConfig.list_services()
|
|
110
|
+
servers = nitlsconfig.ServerConfig.list_services()
|
|
111
|
+
|
|
112
|
+
if clients:
|
|
113
|
+
# Read one client configuration
|
|
114
|
+
client_info = nitlsconfig.ClientConfig(clients[0])
|
|
115
|
+
print(client_info.service_name)
|
|
116
|
+
print(client_info.certificate_mode)
|
|
117
|
+
print(client_info.certificate_chain_location.scheme)
|
|
118
|
+
print(client_info.certificate_chain_location.path)
|
|
119
|
+
print(client_info.certificate_chain_contents)
|
|
120
|
+
|
|
121
|
+
# Inspect target-specific configurations
|
|
122
|
+
for known_server in client_info.known_servers:
|
|
123
|
+
print(known_server.server_name)
|
|
124
|
+
print(known_server.server_mode)
|
|
125
|
+
print(known_server.trusted_certificates_location)
|
|
126
|
+
|
|
127
|
+
if servers:
|
|
128
|
+
# Read one server configuration
|
|
129
|
+
server_info = nitlsconfig.ServerConfig(servers[0])
|
|
130
|
+
print(server_info.service_name)
|
|
131
|
+
print(server_info.certificate_mode)
|
|
132
|
+
print(server_info.client_mode)
|
|
133
|
+
print(server_info.certificate_chain_location.scheme)
|
|
134
|
+
print(server_info.certificate_key_location.scheme)
|
|
135
|
+
print(server_info.trusted_certificates_location.scheme)
|
|
136
|
+
print(server_info.trusted_certificates_contents)
|
|
137
|
+
|
|
138
|
+
# Enumerate trusted certificates
|
|
139
|
+
for cert in server_info.trusted_certificates:
|
|
140
|
+
print(cert.display_name)
|
|
141
|
+
print(cert.trusted_certificate_location.path)
|
|
142
|
+
print(cert.trusted_certificate_contents)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# nitlsconfig
|
|
2
|
+
|
|
3
|
+
Python API that reads nitlsconfig configurations through the `nitlsconfig` command line,
|
|
4
|
+
and builds NI gRPC Device 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.
|
|
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
|
+
Neither install provides the `nitlsconfig` runtime itself. This package reads
|
|
24
|
+
configuration by invoking the `nitlsconfig` command line interface, which ships with NI
|
|
25
|
+
driver software products that support NI TLS. Install a driver that provides it before using
|
|
26
|
+
this package; without it, calls raise `ExecutableNotFoundError`.
|
|
27
|
+
|
|
28
|
+
## Creating a gRPC channel
|
|
29
|
+
|
|
30
|
+
`create_grpc_device_channel` reads the local NI TLS client configuration for the NI
|
|
31
|
+
gRPC Device Server and returns a `grpc.Channel` secured accordingly. The
|
|
32
|
+
`server_address` hostname or address is used to select matching target-specific NI TLS
|
|
33
|
+
settings. Pass the channel straight to any NI gRPC Python API:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import nidcpower
|
|
37
|
+
import nitlsconfig
|
|
38
|
+
|
|
39
|
+
with nitlsconfig.create_grpc_device_channel("localhost", 31763) as channel:
|
|
40
|
+
options = nidcpower.GrpcSessionOptions(channel, "")
|
|
41
|
+
with nidcpower.Session("Dev1", grpc_options=options) as session:
|
|
42
|
+
...
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
NI driver software provides the NI TLS configuration. Using `create_grpc_device_channel`
|
|
46
|
+
opts into mTLS.
|
|
47
|
+
|
|
48
|
+
Before `create_grpc_device_channel` can succeed, use NI Hardware Manager to perform a
|
|
49
|
+
certificate exchange with the remote system. See
|
|
50
|
+
[Managing mTLS](https://www.ni.com/docs/en-US/bundle/hardwaremanager/page/mtls-manage.html)
|
|
51
|
+
for details.
|
|
52
|
+
|
|
53
|
+
Weakening the security posture to one-way TLS or to an insecure connection
|
|
54
|
+
requires explicitly changing that configuration in NI Hardware Manager. Either way, no
|
|
55
|
+
code change is needed.
|
|
56
|
+
|
|
57
|
+
The channel is owned by the caller - NI driver APIs never close it.
|
|
58
|
+
|
|
59
|
+
Retries are opt-in:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
channel = nitlsconfig.create_grpc_device_channel(
|
|
63
|
+
"localhost", 31763, retry_policy=nitlsconfig.RetryPolicy()
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`TlsConfigurationError` is raised when TLS is enabled but the configuration is
|
|
68
|
+
unusable. It is always importable, since handling it does not require grpcio.
|
|
69
|
+
|
|
70
|
+
`create_grpc_device_channel` and `RetryPolicy` do require grpcio; accessing them
|
|
71
|
+
without the `grpc` extra installed raises `ImportError` telling you which extra
|
|
72
|
+
to install.
|
|
73
|
+
|
|
74
|
+
## Reading configurations
|
|
75
|
+
```python
|
|
76
|
+
import nitlsconfig
|
|
77
|
+
|
|
78
|
+
# List configured services
|
|
79
|
+
clients = nitlsconfig.ClientConfig.list_services()
|
|
80
|
+
servers = nitlsconfig.ServerConfig.list_services()
|
|
81
|
+
|
|
82
|
+
if clients:
|
|
83
|
+
# Read one client configuration
|
|
84
|
+
client_info = nitlsconfig.ClientConfig(clients[0])
|
|
85
|
+
print(client_info.service_name)
|
|
86
|
+
print(client_info.certificate_mode)
|
|
87
|
+
print(client_info.certificate_chain_location.scheme)
|
|
88
|
+
print(client_info.certificate_chain_location.path)
|
|
89
|
+
print(client_info.certificate_chain_contents)
|
|
90
|
+
|
|
91
|
+
# Inspect target-specific configurations
|
|
92
|
+
for known_server in client_info.known_servers:
|
|
93
|
+
print(known_server.server_name)
|
|
94
|
+
print(known_server.server_mode)
|
|
95
|
+
print(known_server.trusted_certificates_location)
|
|
96
|
+
|
|
97
|
+
if servers:
|
|
98
|
+
# Read one server configuration
|
|
99
|
+
server_info = nitlsconfig.ServerConfig(servers[0])
|
|
100
|
+
print(server_info.service_name)
|
|
101
|
+
print(server_info.certificate_mode)
|
|
102
|
+
print(server_info.client_mode)
|
|
103
|
+
print(server_info.certificate_chain_location.scheme)
|
|
104
|
+
print(server_info.certificate_key_location.scheme)
|
|
105
|
+
print(server_info.trusted_certificates_location.scheme)
|
|
106
|
+
print(server_info.trusted_certificates_contents)
|
|
107
|
+
|
|
108
|
+
# Enumerate trusted certificates
|
|
109
|
+
for cert in server_info.trusted_certificates:
|
|
110
|
+
print(cert.display_name)
|
|
111
|
+
print(cert.trusted_certificate_location.path)
|
|
112
|
+
print(cert.trusted_certificate_contents)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "nitlsconfig"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
license = "MIT"
|
|
5
|
+
description = "Python API for reading nitlsconfig configurations and creating NI gRPC Device 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 :: 5 - Production/Stable",
|
|
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. pywin32 rides along with it
|
|
31
|
+
# because audit records are only produced when a channel is created, and the
|
|
32
|
+
# Windows Event Log logging handler cannot be written to without it.
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
grpc = ["grpcio>=1.49.0,<2.0", "pywin32>=306; sys_platform == 'win32'"]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
repository = "https://github.com/ni/nitlsconfig-python"
|
|
38
|
+
documentation = "https://nitlsconfig-python.readthedocs.io"
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
nitlsconfig-read = "nitlsconfig.cli:nitlsconfig_main"
|
|
42
|
+
|
|
43
|
+
[build-system]
|
|
44
|
+
requires = ["poetry-core>=1.9.0"]
|
|
45
|
+
build-backend = "poetry.core.masonry.api"
|
|
46
|
+
|
|
47
|
+
[tool.poetry]
|
|
48
|
+
packages = [{ include = "nitlsconfig", from = "src" }]
|
|
49
|
+
requires-poetry = '>=2.1,<3.0'
|
|
50
|
+
|
|
51
|
+
[tool.poetry.dependencies]
|
|
52
|
+
python = ">=3.9,<4.0"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
[tool.poetry.group.lint.dependencies]
|
|
56
|
+
bandit = { version = ">=1.7", extras = ["toml"] }
|
|
57
|
+
ni-python-styleguide = ">=0.4.1"
|
|
58
|
+
mypy = ">=1.0"
|
|
59
|
+
pyright = { version = ">=1.1.400", extras = ["nodejs"] }
|
|
60
|
+
|
|
61
|
+
[tool.poetry.group.test.dependencies]
|
|
62
|
+
pytest = [
|
|
63
|
+
{ version = ">=7.2", python = "<3.10" },
|
|
64
|
+
{ version = ">=9.1.1", python = ">=3.10" },
|
|
65
|
+
]
|
|
66
|
+
pytest-cov = ">=4.0"
|
|
67
|
+
pytest-mock = ">=3.0"
|
|
68
|
+
pytest-env = ">=1.0,<2.0"
|
|
69
|
+
cryptography = ">=41.0"
|
|
70
|
+
|
|
71
|
+
[tool.poetry.group.docs]
|
|
72
|
+
optional = true
|
|
73
|
+
|
|
74
|
+
[tool.poetry.group.docs.dependencies]
|
|
75
|
+
# The latest Sphinx requires a recent Python version.
|
|
76
|
+
Sphinx = [
|
|
77
|
+
{ version = ">=8.1", python = ">=3.10,<3.11" },
|
|
78
|
+
{ version = ">=8.2", python = "^3.11" },
|
|
79
|
+
]
|
|
80
|
+
sphinx-rtd-theme = ">=1.0.0"
|
|
81
|
+
sphinx-autoapi = ">=1.8.4"
|
|
82
|
+
m2r2 = ">=0.3.2"
|
|
83
|
+
toml = ">=0.10.2"
|
|
84
|
+
|
|
85
|
+
[tool.pytest_env]
|
|
86
|
+
env_files = [".env"]
|
|
87
|
+
|
|
88
|
+
[tool.ni-python-styleguide]
|
|
89
|
+
extend_exclude = ".tox,docs"
|
|
90
|
+
application-import-names = "nitlsconfig,tests"
|
|
91
|
+
|
|
92
|
+
[tool.black]
|
|
93
|
+
extend-exclude = '\.tox/|docs/'
|
|
94
|
+
line-length = 100
|
|
95
|
+
|
|
96
|
+
[tool.mypy]
|
|
97
|
+
files = "src/nitlsconfig/,tests/"
|
|
98
|
+
namespace_packages = true
|
|
99
|
+
strict = true
|
|
100
|
+
|
|
101
|
+
[[tool.mypy.overrides]]
|
|
102
|
+
# grpcio does not ship a py.typed marker.
|
|
103
|
+
module = "grpc.*"
|
|
104
|
+
ignore_missing_imports = true
|
|
105
|
+
|
|
106
|
+
[tool.bandit]
|
|
107
|
+
skips = [
|
|
108
|
+
"B101", # assert_used
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
[tool.pytest.ini_options]
|
|
112
|
+
addopts = "--doctest-modules --strict-markers"
|
|
113
|
+
testpaths = ["src/nitlsconfig", "tests"]
|
|
114
|
+
|
|
115
|
+
[tool.pyright]
|
|
116
|
+
include = ["src/", "tests/"]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Python package to read settings from nitlsconfig and build NI gRPC Device channels from them.
|
|
2
|
+
|
|
3
|
+
The gRPC names below are resolved lazily: importing this package never imports
|
|
4
|
+
grpcio, so a caller that only reads NI TLS configuration does not pay for a
|
|
5
|
+
binary dependency it will not use. See the project README for install options.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from importlib.metadata import version
|
|
9
|
+
from importlib.util import find_spec
|
|
10
|
+
from typing import TYPE_CHECKING, Any
|
|
11
|
+
|
|
12
|
+
from nitlsconfig.audit import audit_session_connect
|
|
13
|
+
from nitlsconfig.cli import (
|
|
14
|
+
CertificateLocation,
|
|
15
|
+
ClientCertMode,
|
|
16
|
+
ClientConfig,
|
|
17
|
+
ClientServerMode,
|
|
18
|
+
LocationScheme,
|
|
19
|
+
ServerCertMode,
|
|
20
|
+
ServerClientMode,
|
|
21
|
+
ServerConfig,
|
|
22
|
+
TrustedCertificateData,
|
|
23
|
+
KnownServerData,
|
|
24
|
+
)
|
|
25
|
+
from nitlsconfig.errors import (
|
|
26
|
+
CommandFailedError,
|
|
27
|
+
CommandTimeoutError,
|
|
28
|
+
ExecutableNotFoundError,
|
|
29
|
+
InvalidOutputError,
|
|
30
|
+
NitlsconfigCliError,
|
|
31
|
+
NitlsconfigError,
|
|
32
|
+
TlsConfigurationError,
|
|
33
|
+
get_tls_connection_error_elaboration,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
# Imported eagerly for type checkers and editors, which do not run __getattr__.
|
|
38
|
+
from nitlsconfig.grpc_channel import (
|
|
39
|
+
RetryPolicy,
|
|
40
|
+
create_grpc_device_channel,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__version__ = version("nitlsconfig")
|
|
44
|
+
|
|
45
|
+
# Names re-exported from nitlsconfig.grpc_channel, which requires grpcio.
|
|
46
|
+
# A plain list literal, because pyright only tracks __all__ through a small set
|
|
47
|
+
# of literal forms; anything computed makes it give up on the export list.
|
|
48
|
+
_GRPC_EXPORTS = [
|
|
49
|
+
"RetryPolicy",
|
|
50
|
+
"create_grpc_device_channel",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"__version__",
|
|
55
|
+
"audit_session_connect",
|
|
56
|
+
"CertificateLocation",
|
|
57
|
+
"ClientCertMode",
|
|
58
|
+
"ClientConfig",
|
|
59
|
+
"ClientServerMode",
|
|
60
|
+
"LocationScheme",
|
|
61
|
+
"ServerCertMode",
|
|
62
|
+
"ServerClientMode",
|
|
63
|
+
"ServerConfig",
|
|
64
|
+
"NitlsconfigError",
|
|
65
|
+
"NitlsconfigCliError",
|
|
66
|
+
"ExecutableNotFoundError",
|
|
67
|
+
"CommandFailedError",
|
|
68
|
+
"CommandTimeoutError",
|
|
69
|
+
"InvalidOutputError",
|
|
70
|
+
"TlsConfigurationError",
|
|
71
|
+
"TrustedCertificateData",
|
|
72
|
+
"KnownServerData",
|
|
73
|
+
"get_tls_connection_error_elaboration",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
# The gRPC names are public API, but only on an install that can supply them.
|
|
77
|
+
# Listing them unconditionally would make `from nitlsconfig import *` raise
|
|
78
|
+
# ImportError without the grpc extra, since star-import resolves every name in
|
|
79
|
+
# __all__. find_spec only locates grpcio; it does not import it, so the lazy
|
|
80
|
+
# __getattr__ below still decides when grpcio is actually loaded.
|
|
81
|
+
if find_spec("grpc") is not None:
|
|
82
|
+
# pyright only tracks __all__ through inline literals, so it cannot follow
|
|
83
|
+
# this and warns that the export list may be incomplete. The TYPE_CHECKING
|
|
84
|
+
# block above already declares these names for static consumers.
|
|
85
|
+
__all__ += _GRPC_EXPORTS # pyright: ignore[reportUnsupportedDunderAll]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def __getattr__(name: str) -> Any:
|
|
89
|
+
"""Resolve gRPC exports on first use, so importing this package does not need grpcio."""
|
|
90
|
+
if name in _GRPC_EXPORTS:
|
|
91
|
+
try:
|
|
92
|
+
from nitlsconfig import grpc_channel
|
|
93
|
+
except ImportError as exc: # pragma: no cover - requires an install without the extra
|
|
94
|
+
raise ImportError(
|
|
95
|
+
f"nitlsconfig.{name} requires grpcio, which is not installed. "
|
|
96
|
+
"Install it with: pip install nitlsconfig[grpc]"
|
|
97
|
+
) from exc
|
|
98
|
+
return getattr(grpc_channel, name)
|
|
99
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""The NI TLS services this package builds transports for.
|
|
2
|
+
|
|
3
|
+
Only the NI gRPC Device Server is supported today. Anything else can still be
|
|
4
|
+
read through :class:`~nitlsconfig.cli.ClientConfig`, but has no channel factory.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
# The NI TLS registered service name for the NI gRPC Device Server: the file stem of
|
|
10
|
+
# ni-grpc-device.client.caps.yml, the Event Log source, and the record tag are all this
|
|
11
|
+
# one name, so records can be tied back to the configuration they describe.
|
|
12
|
+
SERVICE_NAME = "ni-grpc-device"
|