pypsrp 0.8.1__tar.gz → 0.9.0rc1__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.
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/CHANGELOG.md +11 -1
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/PKG-INFO +72 -29
- pypsrp-0.8.1/src/pypsrp.egg-info/PKG-INFO → pypsrp-0.9.0rc1/README.md +40 -39
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/build_helpers/lib.sh +7 -14
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/build_helpers/win-setup.ps1 +97 -75
- pypsrp-0.9.0rc1/pyproject.toml +110 -0
- pypsrp-0.9.0rc1/setup.cfg +4 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/_utils.py +0 -1
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/client.py +0 -1
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/complex_objects.py +3 -3
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/encryption.py +0 -1
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/messages.py +3 -2
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/negotiate.py +3 -6
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/powershell.py +59 -8
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/serializer.py +21 -18
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/shell.py +3 -3
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/wsman.py +78 -34
- pypsrp-0.8.1/README.md → pypsrp-0.9.0rc1/src/pypsrp.egg-info/PKG-INFO +82 -14
- pypsrp-0.9.0rc1/src/pypsrp.egg-info/SOURCES.txt +113 -0
- pypsrp-0.9.0rc1/src/pypsrp.egg-info/requires.txt +25 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/conftest.py +1 -1
- pypsrp-0.9.0rc1/tests/tests_pypsrp/responses/test_psrp_multiple_invocations.yml +21 -0
- pypsrp-0.9.0rc1/tests/tests_pypsrp/responses/test_psrp_no_profile.yml +13 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_noprofile.yml +1 -1
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_client.py +1 -1
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_complex_objects.py +0 -4
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_host.py +9 -10
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_integration.py +2 -2
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_negotiate.py +40 -40
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_powershell.py +60 -9
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_shell.py +2 -2
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_wsman.py +1 -1
- pypsrp-0.8.1/pyproject.toml +0 -76
- pypsrp-0.8.1/requirements-dev.txt +0 -17
- pypsrp-0.8.1/setup.cfg +0 -53
- pypsrp-0.8.1/src/pypsrp.egg-info/SOURCES.txt +0 -114
- pypsrp-0.8.1/src/pypsrp.egg-info/requires.txt +0 -9
- pypsrp-0.8.1/src/pypsrp.egg-info/zip-safe +0 -1
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/LICENSE +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/MANIFEST.in +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/build_helpers/JEARole.psrc +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/build_helpers/JEARoleSettings.pssc +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/build_helpers/check-winrm.py +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/build_helpers/run-ci.sh +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/__init__.py +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/exceptions.py +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/host.py +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/pwsh_scripts/__init__.py +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/pwsh_scripts/copy.ps1 +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/pwsh_scripts/fetch.ps1 +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp/py.typed +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp.egg-info/dependency_links.txt +0 -0
- {pypsrp-0.8.1 → pypsrp-0.9.0rc1}/src/pypsrp.egg-info/top_level.txt +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/__init__.py +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/data/test_sanitise_clixml_with_error.xml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/data/test_sanitise_clixml_with_no_errors.xml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/_template.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_copy_expand_vars.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_copy_file.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_copy_file_empty.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_copy_file_failure.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_copy_file_really_large.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_copy_file_warning.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_execute_cmd.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_execute_cmd_environment.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_execute_ps.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_execute_ps_environment.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_execute_ps_failure.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_fetch_file.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_fetch_file_expand_vars.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_fetch_file_fail_dir.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_fetch_file_fail_missing.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_client_fetch_file_hash_mismatch.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_application_args.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_clear_commands.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_disconnect_runspaces.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_disconnected_commands.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_error_failed.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_get_command_metadata.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_key_exchange_timeout.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_long_running_cmdlet.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_merge_commands.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_multiple_commands.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_nested_command.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_open_runspace.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_pshost_methods.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_pshost_raw_ui_mocked_methods.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_pshost_ui_mocked_methods.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_receive_failure.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_reset_runspace_state.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_reset_runspace_state_fail.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_run_protocol_version_2.1.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_run_protocol_version_2.2.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_run_protocol_version_2.3.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_set_runspaces.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_small_msg_size.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_stream_no_output_invocation.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_stream_output_invocation.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_with_history.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_with_input.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_with_jea_configuration.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_psrp_with_no_history.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_bad_cmd_id.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_environment.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_extra_opts.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_fail_poll_process.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_no_cmd_shell.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_open_already_opened.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_operation_timeout.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_send.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_standard.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_stderr_rc.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_winrs_unicode.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_wsman_update_envelope_size_150.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_wsman_update_envelope_size_4096.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/responses/test_wsman_update_envelope_size_500.yml +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_encryption.py +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_exceptions.py +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_messages.py +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_serializer.py +0 -0
- {pypsrp-0.8.1/tests → pypsrp-0.9.0rc1/tests/tests_pypsrp}/test_utils.py +0 -0
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0 - TBD
|
|
4
|
+
|
|
5
|
+
* Raised minimum Python version to 3.10
|
|
6
|
+
* Added retry handler for WSMan `Receive` operations that can attempt to recover from a network disconnect during a command operation
|
|
7
|
+
* Added `no_profile` option to `RunspacePool` to skip loading the user profile on the remote shell
|
|
8
|
+
* Made an `__enter__` and `__exit__` method for `PowerShell` to allow it to be used with a `with PowerShell(runspace) as ps:` syntax
|
|
9
|
+
* On `__exit__` the pipeline will be closed using the `TERMINATE` signal to clean up any resources on the server end
|
|
10
|
+
* `ps.close()` can also be called manually to clean up any resources and to prep the pipeline to be run again
|
|
11
|
+
* Added `clear_streams()` onto a `PowerShell` object to clear the output and `streams` values so it is ready for a subsequent run
|
|
12
|
+
|
|
3
13
|
## 0.8.1 - 2022-02-22
|
|
4
14
|
|
|
5
|
-
* Bump `requests-credssp`
|
|
15
|
+
* Bump `requests-credssp` minimum to new version to support newer encryption format and simpler dependencies
|
|
6
16
|
|
|
7
17
|
|
|
8
18
|
## 0.8.0 - 2022-02-01
|
|
@@ -1,25 +1,44 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pypsrp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0rc1
|
|
4
4
|
Summary: PowerShell Remoting Protocol and WinRM for Python
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
License: MIT
|
|
5
|
+
Author-email: Jordan Borean <jborean93@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: homepage, https://github.com/jborean93/pypsrp
|
|
9
8
|
Keywords: winrm,psrp,winrs,windows,powershell
|
|
10
|
-
Platform: UNKNOWN
|
|
11
9
|
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
10
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Requires-Python: >=3.10
|
|
19
17
|
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: cryptography>=3.1
|
|
20
|
+
Requires-Dist: pyspnego<1.0.0,>=0.7.0
|
|
21
|
+
Requires-Dist: requests>=2.9.1
|
|
20
22
|
Provides-Extra: credssp
|
|
23
|
+
Requires-Dist: requests-credssp>=2.0.0; extra == "credssp"
|
|
21
24
|
Provides-Extra: kerberos
|
|
22
|
-
|
|
25
|
+
Requires-Dist: pyspnego[kerberos]; extra == "kerberos"
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: black==25.11.0; extra == "dev"
|
|
28
|
+
Requires-Dist: build; extra == "dev"
|
|
29
|
+
Requires-Dist: isort==6.1.0; extra == "dev"
|
|
30
|
+
Requires-Dist: mypy==1.19.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
32
|
+
Requires-Dist: pyspnego[kerberos]; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-mock; extra == "dev"
|
|
36
|
+
Requires-Dist: PyYAML; extra == "dev"
|
|
37
|
+
Requires-Dist: requests-credssp; extra == "dev"
|
|
38
|
+
Requires-Dist: types-requests; extra == "dev"
|
|
39
|
+
Requires-Dist: types-PyYAML; extra == "dev"
|
|
40
|
+
Requires-Dist: xmldiff; extra == "dev"
|
|
41
|
+
Dynamic: license-file
|
|
23
42
|
|
|
24
43
|
# pypsrp - Python PowerShell Remoting Protocol Client library
|
|
25
44
|
|
|
@@ -64,7 +83,7 @@ libraries to be installed.
|
|
|
64
83
|
|
|
65
84
|
See `How to Install` for more details
|
|
66
85
|
|
|
67
|
-
* CPython 3.
|
|
86
|
+
* CPython 3.10+
|
|
68
87
|
* [cryptography](https://github.com/pyca/cryptography)
|
|
69
88
|
* [pyspnego](https://github.com/jborean93/pyspnego)
|
|
70
89
|
* [requests](https://github.com/requests/requests)
|
|
@@ -150,7 +169,19 @@ pip install pypsrp[credssp]
|
|
|
150
169
|
```
|
|
151
170
|
|
|
152
171
|
If that fails you may need to update pip and setuptools to a newer version
|
|
153
|
-
`pip install -U pip setuptools
|
|
172
|
+
`pip install -U pip setuptools`, otherwise the following system package may be
|
|
173
|
+
required;
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# For Debian/Ubuntu
|
|
177
|
+
apt-get install gcc python-dev
|
|
178
|
+
|
|
179
|
+
# For RHEL/Centos
|
|
180
|
+
yum install gcc python-devel
|
|
181
|
+
|
|
182
|
+
# For Fedora
|
|
183
|
+
dnf install gcc python-devel
|
|
184
|
+
```
|
|
154
185
|
|
|
155
186
|
|
|
156
187
|
## How to Use
|
|
@@ -230,7 +261,7 @@ configure a `WinRS` shell;
|
|
|
230
261
|
* `idle_time_out`: THe idle timeout in seconds of the shell
|
|
231
262
|
* `lifetime`: The total lifetime of the shell
|
|
232
263
|
* `name`: The name (description only) of the shell
|
|
233
|
-
* `no_profile`: Whether to create the shell with the user profile loaded or not
|
|
264
|
+
* `no_profile`: Whether to create the shell with the user profile loaded or not. This no longer works on Server 2012/Windows 8 or newer
|
|
234
265
|
* `working_directory`: The default working directory of the created shell
|
|
235
266
|
|
|
236
267
|
`RunspacePool` is a shell used by the PSRP protocol, it is designed to be a
|
|
@@ -247,6 +278,7 @@ Here are the options that can be used to configure a `RunspacePool` shell;
|
|
|
247
278
|
* `min_runspaces`: The minimuum number of runspaces that a pool can hold, default is 1
|
|
248
279
|
* `max_runspaces`: The maximum number of runspaces that a pool can hold. Each PowerShell pipeline is run in a single Runspace, default is 1
|
|
249
280
|
* `session_key_timeout_ms`: The maximum time to wait for a session key transfer from the server
|
|
281
|
+
* `no_profile`: Do not load the user profile on the remote Runspace Pool
|
|
250
282
|
|
|
251
283
|
### Process
|
|
252
284
|
|
|
@@ -352,9 +384,8 @@ from pypsrp.wsman import WSMan
|
|
|
352
384
|
# creates a https connection with explicit kerberos auth and implicit credentials
|
|
353
385
|
wsman = WSMan("server", auth="kerberos", cert_validation=False))
|
|
354
386
|
|
|
355
|
-
with wsman, RunspacePool(wsman) as pool:
|
|
387
|
+
with wsman, RunspacePool(wsman) as pool, PowerShell(pool) as ps:
|
|
356
388
|
# execute 'Get-Process | Select-Object Name'
|
|
357
|
-
ps = PowerShell(pool)
|
|
358
389
|
ps.add_cmdlet("Get-Process").add_cmdlet("Select-Object").add_argument("Name")
|
|
359
390
|
output = ps.invoke()
|
|
360
391
|
|
|
@@ -385,6 +416,19 @@ with wsman, RunspacePool(wsman) as pool:
|
|
|
385
416
|
ps.invoke(["string", 1])
|
|
386
417
|
print(ps.output)
|
|
387
418
|
print(ps.streams.debug)
|
|
419
|
+
|
|
420
|
+
# It is possible to run the PowerShell pipeline again with invoke() but it
|
|
421
|
+
# needs to be explicitly closed first and the commands/streams optionally
|
|
422
|
+
# cleared if desired.
|
|
423
|
+
ps.close()
|
|
424
|
+
|
|
425
|
+
# Clears out ps.output and ps.streams to a blank value. Not required but
|
|
426
|
+
# nice if the output should be separate from a previous run
|
|
427
|
+
ps.clear_streams()
|
|
428
|
+
|
|
429
|
+
# Removes all existing commands. Not required but needed if re-using the
|
|
430
|
+
# same pipeline with a different set of commands
|
|
431
|
+
ps.clear_commands()
|
|
388
432
|
```
|
|
389
433
|
|
|
390
434
|
|
|
@@ -438,17 +482,18 @@ information and should only be used for debugging purposes._
|
|
|
438
482
|
## Testing
|
|
439
483
|
|
|
440
484
|
Any changes are more than welcome in pull request form, you can run the current
|
|
441
|
-
test suite with
|
|
485
|
+
test suite with:
|
|
442
486
|
|
|
443
487
|
```bash
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
488
|
+
pip install -e .[dev]
|
|
489
|
+
|
|
490
|
+
python -m pytest \
|
|
491
|
+
tests/tests_pypsrp \
|
|
492
|
+
--verbose \
|
|
493
|
+
--junitxml junit/test-results.xml \
|
|
494
|
+
--cov pypsrp \
|
|
495
|
+
--cov-report xml \
|
|
496
|
+
--cov-report term-missing
|
|
452
497
|
```
|
|
453
498
|
|
|
454
499
|
A lot of the tests either simulate a remote Windows host but you can also run a
|
|
@@ -518,5 +563,3 @@ tests.
|
|
|
518
563
|
* Add Ansible playbook for better integration tests
|
|
519
564
|
* Improved serialization between Python and .NET objects
|
|
520
565
|
* Live interactive console for PSRP
|
|
521
|
-
|
|
522
|
-
|
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: pypsrp
|
|
3
|
-
Version: 0.8.1
|
|
4
|
-
Summary: PowerShell Remoting Protocol and WinRM for Python
|
|
5
|
-
Home-page: https://github.com/jborean93/pypsrp
|
|
6
|
-
Author: Jordan Borean
|
|
7
|
-
Author-email: jborean93@gmail.com
|
|
8
|
-
License: MIT
|
|
9
|
-
Keywords: winrm,psrp,winrs,windows,powershell
|
|
10
|
-
Platform: UNKNOWN
|
|
11
|
-
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
-
Description-Content-Type: text/markdown
|
|
20
|
-
Provides-Extra: credssp
|
|
21
|
-
Provides-Extra: kerberos
|
|
22
|
-
License-File: LICENSE
|
|
23
|
-
|
|
24
1
|
# pypsrp - Python PowerShell Remoting Protocol Client library
|
|
25
2
|
|
|
26
3
|
[](https://github.com/jborean93/pypsrp/actions/workflows/ci.yml)
|
|
@@ -64,7 +41,7 @@ libraries to be installed.
|
|
|
64
41
|
|
|
65
42
|
See `How to Install` for more details
|
|
66
43
|
|
|
67
|
-
* CPython 3.
|
|
44
|
+
* CPython 3.10+
|
|
68
45
|
* [cryptography](https://github.com/pyca/cryptography)
|
|
69
46
|
* [pyspnego](https://github.com/jborean93/pyspnego)
|
|
70
47
|
* [requests](https://github.com/requests/requests)
|
|
@@ -150,7 +127,19 @@ pip install pypsrp[credssp]
|
|
|
150
127
|
```
|
|
151
128
|
|
|
152
129
|
If that fails you may need to update pip and setuptools to a newer version
|
|
153
|
-
`pip install -U pip setuptools
|
|
130
|
+
`pip install -U pip setuptools`, otherwise the following system package may be
|
|
131
|
+
required;
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# For Debian/Ubuntu
|
|
135
|
+
apt-get install gcc python-dev
|
|
136
|
+
|
|
137
|
+
# For RHEL/Centos
|
|
138
|
+
yum install gcc python-devel
|
|
139
|
+
|
|
140
|
+
# For Fedora
|
|
141
|
+
dnf install gcc python-devel
|
|
142
|
+
```
|
|
154
143
|
|
|
155
144
|
|
|
156
145
|
## How to Use
|
|
@@ -230,7 +219,7 @@ configure a `WinRS` shell;
|
|
|
230
219
|
* `idle_time_out`: THe idle timeout in seconds of the shell
|
|
231
220
|
* `lifetime`: The total lifetime of the shell
|
|
232
221
|
* `name`: The name (description only) of the shell
|
|
233
|
-
* `no_profile`: Whether to create the shell with the user profile loaded or not
|
|
222
|
+
* `no_profile`: Whether to create the shell with the user profile loaded or not. This no longer works on Server 2012/Windows 8 or newer
|
|
234
223
|
* `working_directory`: The default working directory of the created shell
|
|
235
224
|
|
|
236
225
|
`RunspacePool` is a shell used by the PSRP protocol, it is designed to be a
|
|
@@ -247,6 +236,7 @@ Here are the options that can be used to configure a `RunspacePool` shell;
|
|
|
247
236
|
* `min_runspaces`: The minimuum number of runspaces that a pool can hold, default is 1
|
|
248
237
|
* `max_runspaces`: The maximum number of runspaces that a pool can hold. Each PowerShell pipeline is run in a single Runspace, default is 1
|
|
249
238
|
* `session_key_timeout_ms`: The maximum time to wait for a session key transfer from the server
|
|
239
|
+
* `no_profile`: Do not load the user profile on the remote Runspace Pool
|
|
250
240
|
|
|
251
241
|
### Process
|
|
252
242
|
|
|
@@ -352,9 +342,8 @@ from pypsrp.wsman import WSMan
|
|
|
352
342
|
# creates a https connection with explicit kerberos auth and implicit credentials
|
|
353
343
|
wsman = WSMan("server", auth="kerberos", cert_validation=False))
|
|
354
344
|
|
|
355
|
-
with wsman, RunspacePool(wsman) as pool:
|
|
345
|
+
with wsman, RunspacePool(wsman) as pool, PowerShell(pool) as ps:
|
|
356
346
|
# execute 'Get-Process | Select-Object Name'
|
|
357
|
-
ps = PowerShell(pool)
|
|
358
347
|
ps.add_cmdlet("Get-Process").add_cmdlet("Select-Object").add_argument("Name")
|
|
359
348
|
output = ps.invoke()
|
|
360
349
|
|
|
@@ -385,6 +374,19 @@ with wsman, RunspacePool(wsman) as pool:
|
|
|
385
374
|
ps.invoke(["string", 1])
|
|
386
375
|
print(ps.output)
|
|
387
376
|
print(ps.streams.debug)
|
|
377
|
+
|
|
378
|
+
# It is possible to run the PowerShell pipeline again with invoke() but it
|
|
379
|
+
# needs to be explicitly closed first and the commands/streams optionally
|
|
380
|
+
# cleared if desired.
|
|
381
|
+
ps.close()
|
|
382
|
+
|
|
383
|
+
# Clears out ps.output and ps.streams to a blank value. Not required but
|
|
384
|
+
# nice if the output should be separate from a previous run
|
|
385
|
+
ps.clear_streams()
|
|
386
|
+
|
|
387
|
+
# Removes all existing commands. Not required but needed if re-using the
|
|
388
|
+
# same pipeline with a different set of commands
|
|
389
|
+
ps.clear_commands()
|
|
388
390
|
```
|
|
389
391
|
|
|
390
392
|
|
|
@@ -438,17 +440,18 @@ information and should only be used for debugging purposes._
|
|
|
438
440
|
## Testing
|
|
439
441
|
|
|
440
442
|
Any changes are more than welcome in pull request form, you can run the current
|
|
441
|
-
test suite with
|
|
443
|
+
test suite with:
|
|
442
444
|
|
|
443
445
|
```bash
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
446
|
+
pip install -e .[dev]
|
|
447
|
+
|
|
448
|
+
python -m pytest \
|
|
449
|
+
tests/tests_pypsrp \
|
|
450
|
+
--verbose \
|
|
451
|
+
--junitxml junit/test-results.xml \
|
|
452
|
+
--cov pypsrp \
|
|
453
|
+
--cov-report xml \
|
|
454
|
+
--cov-report term-missing
|
|
452
455
|
```
|
|
453
456
|
|
|
454
457
|
A lot of the tests either simulate a remote Windows host but you can also run a
|
|
@@ -518,5 +521,3 @@ tests.
|
|
|
518
521
|
* Add Ansible playbook for better integration tests
|
|
519
522
|
* Improved serialization between Python and .NET objects
|
|
520
523
|
* Live interactive console for PSRP
|
|
521
|
-
|
|
522
|
-
|
|
@@ -62,25 +62,17 @@ lib::setup::python_requirements() {
|
|
|
62
62
|
echo "::group::Installing Python Requirements"
|
|
63
63
|
fi
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
# Getting the version is important so that pip prioritises our local dist
|
|
66
|
+
python -m pip install build
|
|
67
|
+
PSRP_VERSION="$( python -c "import build.util; print(build.util.project_wheel_metadata('.').get('Version'))" )"
|
|
66
68
|
|
|
67
69
|
echo "Installing pypsrp"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
else
|
|
71
|
-
DIST_LINK_PATH="${PWD}/dist"
|
|
72
|
-
fi
|
|
73
|
-
|
|
74
|
-
python -m pip install pypsrp \
|
|
75
|
-
--no-index \
|
|
76
|
-
--find-links "file://${DIST_LINK_PATH}" \
|
|
77
|
-
--no-build-isolation \
|
|
78
|
-
--no-dependencies \
|
|
70
|
+
python -m pip install pypsrp[credssp,kerberos]=="${PSRP_VERSION}" \
|
|
71
|
+
--find-links dist \
|
|
79
72
|
--verbose
|
|
80
|
-
python -m pip install pypsrp[credssp,kerberos]
|
|
81
73
|
|
|
82
74
|
echo "Installing dev dependencies"
|
|
83
|
-
python -m pip install
|
|
75
|
+
python -m pip install .[dev]
|
|
84
76
|
|
|
85
77
|
if [ x"${GITHUB_ACTIONS}" = "xtrue" ]; then
|
|
86
78
|
echo "::endgroup::"
|
|
@@ -114,6 +106,7 @@ lib::tests::run() {
|
|
|
114
106
|
fi
|
|
115
107
|
|
|
116
108
|
python -m pytest \
|
|
109
|
+
tests/tests_pypsrp \
|
|
117
110
|
--verbose \
|
|
118
111
|
--junitxml junit/test-results.xml \
|
|
119
112
|
--cov pypsrp \
|
|
@@ -120,13 +120,13 @@ function New-WinRMFirewallRule {
|
|
|
120
120
|
|
|
121
121
|
foreach ($rule in $rules) {
|
|
122
122
|
$rule_details = @{
|
|
123
|
-
LocalPorts
|
|
124
|
-
RemotePorts
|
|
125
|
-
LocalAddresses
|
|
126
|
-
Enabled
|
|
127
|
-
Direction
|
|
128
|
-
Action
|
|
129
|
-
Grouping
|
|
123
|
+
LocalPorts = $Port
|
|
124
|
+
RemotePorts = "*"
|
|
125
|
+
LocalAddresses = "*"
|
|
126
|
+
Enabled = $true
|
|
127
|
+
Direction = 1
|
|
128
|
+
Action = 1
|
|
129
|
+
Grouping = "Windows Remote Management"
|
|
130
130
|
ApplicationName = "System"
|
|
131
131
|
}
|
|
132
132
|
$rule.Protocol = 6
|
|
@@ -171,33 +171,28 @@ function Reset-WinRMConfig {
|
|
|
171
171
|
Write-Verbose "Removing all existing WinRM listeners"
|
|
172
172
|
Get-ChildItem -LiteralPath WSMan:\localhost\Listener | Remove-Item -Force -Recurse
|
|
173
173
|
|
|
174
|
-
if (-not $CertificateThumbprint) {
|
|
175
|
-
Write-Verbose "Removing all existing certificate in the personal store"
|
|
176
|
-
Remove-Item -Path Cert:\LocalMachine\My\* -Force -Recurse
|
|
177
|
-
}
|
|
178
|
-
|
|
179
174
|
Write-Information -MessageData "Creating HTTP listener"
|
|
180
|
-
$
|
|
175
|
+
$selectorSet = @{
|
|
181
176
|
Transport = "HTTP"
|
|
182
|
-
Address
|
|
177
|
+
Address = "*"
|
|
183
178
|
}
|
|
184
|
-
$
|
|
179
|
+
$valueSet = @{
|
|
185
180
|
Enabled = $true
|
|
186
181
|
}
|
|
187
|
-
New-WSManInstance -ResourceURI winrm/config/listener -SelectorSet $
|
|
182
|
+
New-WSManInstance -ResourceURI winrm/config/listener -SelectorSet $selectorSet -ValueSet $valueSet > $null
|
|
188
183
|
|
|
189
184
|
$certificate = New-LegacySelfSignedCert -Subject $env:COMPUTERNAME -ValidDays 1095
|
|
190
|
-
$
|
|
185
|
+
$selectorSet = @{
|
|
191
186
|
Transport = "HTTPS"
|
|
192
|
-
Address
|
|
187
|
+
Address = "*"
|
|
193
188
|
}
|
|
194
|
-
$
|
|
189
|
+
$valueSet = @{
|
|
195
190
|
CertificateThumbprint = $certificate.Thumbprint
|
|
196
|
-
Enabled
|
|
191
|
+
Enabled = $true
|
|
197
192
|
}
|
|
198
193
|
|
|
199
194
|
Write-Information -MessageData "Creating HTTPS listener"
|
|
200
|
-
New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $
|
|
195
|
+
New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $selectorSet -ValueSet $valueSet > $null
|
|
201
196
|
|
|
202
197
|
Write-Verbose "Enabling PowerShell Remoting"
|
|
203
198
|
Enable-PSRemoting -Force > $null
|
|
@@ -211,8 +206,8 @@ function Reset-WinRMConfig {
|
|
|
211
206
|
Write-Information -MessageData "Enabling CredSSP authentication"
|
|
212
207
|
Enable-WSManCredSSP -Role Server -Force > $null
|
|
213
208
|
|
|
214
|
-
Write-Information -MessageData "Setting AllowUnencrypted to
|
|
215
|
-
Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value $
|
|
209
|
+
Write-Information -MessageData "Setting AllowUnencrypted to True"
|
|
210
|
+
Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value $true
|
|
216
211
|
|
|
217
212
|
Write-Information -MessageData "Configuring WinRM HTTPS firewall rule"
|
|
218
213
|
New-WinRMFirewallRule -Port 5986 -Protocol HTTPS
|
|
@@ -222,11 +217,11 @@ function Reset-WinRMConfig {
|
|
|
222
217
|
|
|
223
218
|
Write-Information -MessageData "Allow local admins over network auth"
|
|
224
219
|
$regInfo = @{
|
|
225
|
-
Path
|
|
226
|
-
Name
|
|
227
|
-
Value
|
|
220
|
+
Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
|
|
221
|
+
Name = "LocalAccountTokenFilterPolicy"
|
|
222
|
+
Value = 1
|
|
228
223
|
PropertyType = "DWord"
|
|
229
|
-
Force
|
|
224
|
+
Force = $true
|
|
230
225
|
}
|
|
231
226
|
New-ItemProperty @regInfo
|
|
232
227
|
|
|
@@ -245,45 +240,61 @@ Function New-CertificateAuthBinding {
|
|
|
245
240
|
|
|
246
241
|
Write-Information -MessageData "Generating self signed certificate for authentication of user $Name"
|
|
247
242
|
$certInfo = @{
|
|
248
|
-
|
|
249
|
-
|
|
243
|
+
Subject = "CN=$Name"
|
|
244
|
+
KeyUsage = "DigitalSignature", "KeyEncipherment"
|
|
245
|
+
KeyAlgorithm = "RSA"
|
|
246
|
+
KeyLength = 2048
|
|
250
247
|
TextExtension = @("2.5.29.37={text}1.3.6.1.5.5.7.3.2", "2.5.29.17={text}upn=$Name@localhost")
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
KeyLength = 2048
|
|
248
|
+
Type = "Custom"
|
|
249
|
+
CertStoreLocation = "Cert:\CurrentUser\My"
|
|
254
250
|
}
|
|
255
251
|
$cert = New-SelfSignedCertificate @certInfo
|
|
256
252
|
|
|
257
|
-
Write-Information -MessageData "Exporting public key of cert"
|
|
258
|
-
$pem_output = @()
|
|
259
|
-
$pem_output += "-----BEGIN CERTIFICATE-----"
|
|
260
|
-
$pem_output += [System.Convert]::ToBase64String($cert.RawData) -replace ".{64}", "$&`n"
|
|
261
|
-
$pem_output += "-----END CERTIFICATE-----"
|
|
262
|
-
[System.IO.File]::WriteAllLines("$CertPath\cert.pem", $pem_output)
|
|
263
|
-
|
|
264
253
|
Write-Information -MessageData "Exporting private key in a PFX file"
|
|
265
254
|
[System.IO.File]::WriteAllBytes("$CertPath\cert.pfx", $cert.Export("Pfx"))
|
|
266
255
|
|
|
267
256
|
Write-Information -MessageData "Converting private key to PEM format with openssl"
|
|
268
|
-
|
|
257
|
+
$out = openssl.exe @(
|
|
258
|
+
"pkcs12",
|
|
259
|
+
"-in", "$CertPath\cert.pfx",
|
|
260
|
+
"-nocerts",
|
|
261
|
+
"-nodes",
|
|
262
|
+
"-out", "$CertPath\cert_key.pem",
|
|
263
|
+
"-passin", "pass:",
|
|
264
|
+
"-passout", "pass:"
|
|
265
|
+
) 2>&1
|
|
266
|
+
if ($LASTEXITCODE) {
|
|
267
|
+
throw "Failed to extract key from PEM:`n$out"
|
|
268
|
+
}
|
|
269
|
+
Remove-Item -Path "$CertPath\cert.pfx" -Force
|
|
270
|
+
|
|
271
|
+
# WinRM seems to be very picky about the type of cert in the trusted root and people store. Make sure this is set
|
|
272
|
+
# to the cert and not cert + key.
|
|
273
|
+
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($cert.RawData)
|
|
274
|
+
|
|
275
|
+
Write-Information -MessageData "Exporting cert and key of user certificate"
|
|
276
|
+
$key_pem = Get-Content -Path "$CertPath\cert_key.pem"
|
|
277
|
+
Remove-Item -Path "$CertPath\cert_key.pem" -Force
|
|
278
|
+
[System.IO.File]::WriteAllLines("$CertPath\cert.pem", @(
|
|
279
|
+
$key_pem
|
|
280
|
+
"-----BEGIN CERTIFICATE-----"
|
|
281
|
+
[System.Convert]::ToBase64String($cert.RawData) -replace ".{64}", "$&`n"
|
|
282
|
+
"-----END CERTIFICATE-----"
|
|
283
|
+
))
|
|
269
284
|
|
|
270
285
|
Write-Information -MessageData "Importing cert into LocalMachine\Root"
|
|
271
|
-
$
|
|
272
|
-
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
|
|
273
|
-
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
|
|
286
|
+
$store = Get-Item -Path Cert:\LocalMachine\Root
|
|
274
287
|
$store.Open("MaxAllowed")
|
|
275
288
|
$store.Add($cert)
|
|
276
289
|
$store.Close()
|
|
277
290
|
|
|
278
291
|
Write-Information -MessageData "Importing cert into LocalMachine\TrustedPeople"
|
|
279
|
-
$
|
|
280
|
-
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
|
|
281
|
-
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
|
|
292
|
+
$store = Get-Item -Path Cert:\LocalMachine\TrustedPeople
|
|
282
293
|
$store.Open("MaxAllowed")
|
|
283
294
|
$store.Add($cert)
|
|
284
295
|
$store.Close()
|
|
285
296
|
|
|
286
|
-
$cert
|
|
297
|
+
$cert
|
|
287
298
|
}
|
|
288
299
|
|
|
289
300
|
Function New-JEAConfiguration {
|
|
@@ -296,31 +307,31 @@ Function New-JEAConfiguration {
|
|
|
296
307
|
$JEAConfigPath
|
|
297
308
|
)
|
|
298
309
|
|
|
299
|
-
$
|
|
300
|
-
Write-Information -MessageData "Setting up JEA PowerShell module path at '$
|
|
301
|
-
if (-not (Test-Path -Path $
|
|
302
|
-
New-Item -Path $
|
|
310
|
+
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\$Name"
|
|
311
|
+
Write-Information -MessageData "Setting up JEA PowerShell module path at '$modulePath'"
|
|
312
|
+
if (-not (Test-Path -Path $modulePath)) {
|
|
313
|
+
New-Item -Path $modulePath -ItemType Directory
|
|
303
314
|
}
|
|
304
315
|
|
|
305
|
-
$
|
|
306
|
-
if (-not (Test-Path -Path $
|
|
307
|
-
New-Item -Path $
|
|
316
|
+
$functionsPath = Join-Path -Path $modulePath -ChildPath "$($Name)Functions.psm1"
|
|
317
|
+
if (-not (Test-Path -Path $functionsPath)) {
|
|
318
|
+
New-Item -Path $functionsPath -ItemType File
|
|
308
319
|
}
|
|
309
320
|
|
|
310
|
-
$
|
|
311
|
-
if (-not (Test-Path -Path $
|
|
312
|
-
New-ModuleManifest -Path $
|
|
321
|
+
$manifestPath = Join-Path -Path $modulePath -ChildPath "$($Name).psd1"
|
|
322
|
+
if (-not (Test-Path -Path $manifestPath)) {
|
|
323
|
+
New-ModuleManifest -Path $manifestPath -RootModule "$($Name)Functions.psm1"
|
|
313
324
|
}
|
|
314
325
|
|
|
315
|
-
$
|
|
316
|
-
if (-not (Test-Path -Path $
|
|
317
|
-
New-Item -Path $
|
|
326
|
+
$rolePath = Join-Path -Path $modulePath -ChildPath "RoleCapabilities"
|
|
327
|
+
if (-not (Test-Path -Path $rolePath)) {
|
|
328
|
+
New-Item -Path $rolePath -ItemType Directory
|
|
318
329
|
}
|
|
319
330
|
|
|
320
|
-
$
|
|
331
|
+
$jeaRoleSrc = Join-Path -Path $JEAConfigPath -ChildPath "$($Name).psrc"
|
|
321
332
|
|
|
322
|
-
Write-Information -MessageData "Copying across JEA role configuration from '$
|
|
323
|
-
Copy-Item -Path $
|
|
333
|
+
Write-Information -MessageData "Copying across JEA role configuration from '$jeaRoleSrc'"
|
|
334
|
+
Copy-Item -Path $jeaRoleSrc -Destination $rolePath
|
|
324
335
|
|
|
325
336
|
if (Get-PSSessionConfiguration | Where-Object { $_.Name -eq $name }) {
|
|
326
337
|
Write-Information -MessageData "JEA role $Name already registered, removing to ensure we start fresh"
|
|
@@ -330,6 +341,7 @@ Function New-JEAConfiguration {
|
|
|
330
341
|
|
|
331
342
|
$secPassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
|
|
332
343
|
$userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:COMPUTERNAME\$UserName, $secPassword
|
|
344
|
+
$userCertCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, $secPassword
|
|
333
345
|
|
|
334
346
|
Enable-PSRemoting -Force
|
|
335
347
|
Start-Service -Name WinRM
|
|
@@ -338,17 +350,19 @@ Reset-WinRMConfig
|
|
|
338
350
|
$localUser = New-LocalUser -Name $UserName -Password $secPassword -AccountNeverExpires -PasswordNeverExpires
|
|
339
351
|
Add-LocalGroupMember -Group Administrators -Member $localUser
|
|
340
352
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
353
|
+
$clientCertificate = New-CertificateAuthBinding -Name $UserName -CertPath $CertPath
|
|
354
|
+
$certChain = [Security.Cryptography.X509Certificates.X509Chain]::new()
|
|
355
|
+
[void]$certChain.Build($clientCertificate)
|
|
356
|
+
|
|
357
|
+
$credBinding = @{
|
|
358
|
+
Path = "WSMan:\localhost\ClientCertificate"
|
|
359
|
+
Subject = "$UserName@localhost"
|
|
360
|
+
URI = "*"
|
|
361
|
+
Issuer = $certChain.ChainElements.Certificate[-1].Thumbprint
|
|
362
|
+
Credential = $userCertCredential
|
|
363
|
+
Force = $true
|
|
364
|
+
}
|
|
365
|
+
New-Item @credBinding
|
|
352
366
|
|
|
353
367
|
New-JEAConfiguration -Name JEARole -JEAConfigPath $PSScriptRoot
|
|
354
368
|
Register-PSSessionConfiguration -Path "$PSScriptRoot\JEARoleSettings.pssc" -Name JEARole -Force
|
|
@@ -356,4 +370,12 @@ Register-PSSessionConfiguration -Path "$PSScriptRoot\JEARoleSettings.pssc" -Name
|
|
|
356
370
|
Restart-Service -Name winrm
|
|
357
371
|
|
|
358
372
|
Write-Information -MessageData "Testing WinRM connection"
|
|
359
|
-
|
|
373
|
+
$invokeParams = @{
|
|
374
|
+
ComputerName = 'localhost'
|
|
375
|
+
ScriptBlock = { whoami.exe }
|
|
376
|
+
SessionOption = (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)
|
|
377
|
+
}
|
|
378
|
+
Invoke-Command @invokeParams -Credential $userCredential
|
|
379
|
+
|
|
380
|
+
# Write-Information -MessageData "Testing WinRM connection with certificates"
|
|
381
|
+
# Invoke-Command @invokeParams -CertificateThumbprint $thumbprint
|