train-juniper 0.7.1 → 0.7.4
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.
- checksums.yaml +4 -4
- data/.env.example +13 -26
- data/CHANGELOG.md +56 -0
- data/README.md +44 -10
- data/lib/train-juniper/connection/bastion_proxy.rb +51 -35
- data/lib/train-juniper/connection/ssh_askpass.rb +69 -0
- data/lib/train-juniper/connection/windows_proxy.rb +48 -0
- data/lib/train-juniper/version.rb +1 -1
- data/train-juniper.gemspec +2 -2
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6da9bb07db2daaa3ca21d2fef18b0a200ff15597495dece758e0e509d10c13ad
|
4
|
+
data.tar.gz: 86e802113118c172748e2187e09db4c95c080f393dc083932a65386d19c82f3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0137dee8f2547f0973d2e513491574e624f55a605993ca8e6211e1c84c77341fe840d45704903e25eaeacb6e043b1846556f2f124ee08863c591357e34c37ecb
|
7
|
+
data.tar.gz: ddd016a7cf4cc47d68e9e0f89283d874ea563abab20cc6f2e822d67658694bac3782d3cef0ef4f2a1976bfbf4b2a8652050ff87c9b9d13c18864a5c26a169482
|
data/.env.example
CHANGED
@@ -1,29 +1,16 @@
|
|
1
|
-
#
|
2
|
-
# Copy this
|
3
|
-
# The plugin automatically detects these environment variables
|
1
|
+
# Example .env file for Windows testing
|
2
|
+
# Copy this to .env and fill in your actual values
|
4
3
|
|
5
|
-
# Juniper
|
6
|
-
JUNIPER_HOST=
|
7
|
-
JUNIPER_USER=
|
8
|
-
JUNIPER_PASSWORD=
|
9
|
-
JUNIPER_PORT=22
|
10
|
-
JUNIPER_TIMEOUT=60
|
4
|
+
# Target Juniper device (behind bastion)
|
5
|
+
JUNIPER_HOST=192.168.1.100
|
6
|
+
JUNIPER_USER=admin
|
7
|
+
JUNIPER_PASSWORD=device_password
|
11
8
|
|
12
|
-
# Bastion/Jump
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
JUNIPER_BASTION_PASSWORD=your_jump_password
|
9
|
+
# Bastion/Jump host
|
10
|
+
BASTION_HOST=bastion.example.com
|
11
|
+
BASTION_USER=jumpuser
|
12
|
+
BASTION_PASSWORD=bastion_password
|
17
13
|
|
18
|
-
# Custom
|
19
|
-
#
|
20
|
-
|
21
|
-
# Usage Examples:
|
22
|
-
# 1. Basic connection (auto-detects above variables):
|
23
|
-
# inspec detect -t juniper://
|
24
|
-
#
|
25
|
-
# 2. Override specific values:
|
26
|
-
# inspec detect -t juniper://different_user@different_host --password override_pass
|
27
|
-
#
|
28
|
-
# 3. Test connection:
|
29
|
-
# source .env && inspec detect -t juniper:// -l debug
|
14
|
+
# Optional: Custom ports
|
15
|
+
# JUNIPER_PORT=22
|
16
|
+
# BASTION_PORT=22
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,59 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.7.4] - 2025-06-24
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
- Add Windows plink.exe support for bastion authentication
|
13
|
+
|
14
|
+
### Documentation
|
15
|
+
|
16
|
+
- Add Windows bastion setup guide and improve navigation
|
17
|
+
- Fix MkDocs link warnings
|
18
|
+
- Add host key acceptance instructions and InSpec testing examples
|
19
|
+
- Improve Windows documentation and standardize on inspec shell
|
20
|
+
|
21
|
+
### Miscellaneous Tasks
|
22
|
+
|
23
|
+
- Fix linting issues in Windows test script
|
24
|
+
|
25
|
+
### Testing
|
26
|
+
|
27
|
+
- Add Windows testing scripts and guide
|
28
|
+
- Add .env file support to Windows test scripts
|
29
|
+
|
30
|
+
## [0.7.3] - 2025-06-23
|
31
|
+
|
32
|
+
### Documentation
|
33
|
+
|
34
|
+
- Improve README structure for better MkDocs rendering
|
35
|
+
- Add platform support section to README
|
36
|
+
|
37
|
+
### Fixed
|
38
|
+
|
39
|
+
- Follow standard RubyGems conventions for gem packaging
|
40
|
+
- Remove .md extensions from internal MkDocs links
|
41
|
+
- **docs**: Improve Support section formatting with subsections
|
42
|
+
- **windows**: Use PowerShell for SSH_ASKPASS on Windows and add cross-platform CI/CD
|
43
|
+
- **ci**: Add comprehensive platform support for cross-platform compatibility
|
44
|
+
- Update ffi dependency to support Ruby 3.3 on Windows
|
45
|
+
- Handle Windows PowerShell script paths in bastion proxy tests
|
46
|
+
- Use direct gem push instead of rubygems/release-gem action
|
47
|
+
- Complete release workflow implementation
|
48
|
+
|
49
|
+
### Miscellaneous Tasks
|
50
|
+
|
51
|
+
- Add session.md to .gitignore
|
52
|
+
|
53
|
+
### Styling
|
54
|
+
|
55
|
+
- Fix trailing whitespace in bastion proxy files
|
56
|
+
|
57
|
+
### Testing
|
58
|
+
|
59
|
+
- Add nocov markers for Windows-specific PowerShell code
|
60
|
+
|
8
61
|
## [0.7.1] - 2025-06-23
|
9
62
|
|
10
63
|
### Added
|
@@ -26,6 +79,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
26
79
|
- Add v0.7.0 to mkdocs and automate nav updates
|
27
80
|
- **coverage**: Properly handle SimpleCov :nocov: markers in analysis
|
28
81
|
- **docs**: Move Security Policy to About section in navigation
|
82
|
+
- Resolve RuboCop violations for CI/CD compliance
|
83
|
+
- Update release task to handle GitHub Actions gem publishing
|
84
|
+
- Resolve final RuboCop issues in release task
|
29
85
|
|
30
86
|
### Miscellaneous Tasks
|
31
87
|
|
data/README.md
CHANGED
@@ -175,11 +175,11 @@ This allows maximum flexibility while providing sensible defaults for common sce
|
|
175
175
|
| `key_files` | SSH private key files | - | - |
|
176
176
|
| `keys_only` | Use only specified keys | false | - |
|
177
177
|
|
178
|
-
|
179
|
-
- Cannot specify both `bastion_host` and `proxy_command` simultaneously
|
180
|
-
- If `bastion_user` not provided, falls back to using main `user` for bastion authentication
|
181
|
-
- If `bastion_password` not provided, falls back to using main `password` for bastion authentication
|
182
|
-
- Supports automated password authentication via SSH_ASKPASS mechanism
|
178
|
+
!!! note "Important Configuration Notes"
|
179
|
+
- Cannot specify both `bastion_host` and `proxy_command` simultaneously
|
180
|
+
- If `bastion_user` not provided, falls back to using main `user` for bastion authentication
|
181
|
+
- If `bastion_password` not provided, falls back to using main `password` for bastion authentication
|
182
|
+
- Supports automated password authentication via SSH_ASKPASS mechanism
|
183
183
|
|
184
184
|
### InSpec Configuration File
|
185
185
|
|
@@ -280,7 +280,8 @@ Train.create('juniper', {
|
|
280
280
|
|
281
281
|
### Common Authentication Issues
|
282
282
|
|
283
|
-
#### ❌
|
283
|
+
#### ❌ Error: "No bastion password specified"
|
284
|
+
|
284
285
|
**Solution**: Train doesn't have `--bastion-password`. Use one of these patterns:
|
285
286
|
```bash
|
286
287
|
# Same password for both (most common)
|
@@ -293,7 +294,8 @@ inspec detect -t "juniper://user@device?bastion_host=jump" --key-files ~/.ssh/id
|
|
293
294
|
inspec detect -t "juniper://user@device?proxy_command=sshpass%20-p%20jumppass%20ssh%20jumpuser@jump%20-W%20%h:%p" --password "device_pass"
|
294
295
|
```
|
295
296
|
|
296
|
-
#### ❌
|
297
|
+
#### ❌ Error: "Authentication failed"
|
298
|
+
|
297
299
|
**Solutions**:
|
298
300
|
```bash
|
299
301
|
# Verify bastion connection first
|
@@ -309,7 +311,8 @@ inspec detect -t "juniper://user@device?bastion_host=jump&proxy_command=ssh%20-v
|
|
309
311
|
inspec detect -t "juniper://user@device?bastion_host=jump" --password "pass" -l debug
|
310
312
|
```
|
311
313
|
|
312
|
-
#### ❌
|
314
|
+
#### ❌ Error: "Connection timeout"
|
315
|
+
|
313
316
|
**Solutions**:
|
314
317
|
```bash
|
315
318
|
# Increase timeouts
|
@@ -349,6 +352,7 @@ result = connection.run_command('show version')
|
|
349
352
|
```
|
350
353
|
|
351
354
|
Mock mode provides:
|
355
|
+
|
352
356
|
- ✅ Realistic JunOS command outputs
|
353
357
|
- ✅ Platform detection (JunOS 12.1X47-D15.4)
|
354
358
|
- ✅ Error simulation for negative testing
|
@@ -393,10 +397,30 @@ This plugin implements the Train Plugin V1 API with:
|
|
393
397
|
- **Platform** (`lib/train-juniper/platform.rb`) - JunOS platform detection
|
394
398
|
- **Version** (`lib/train-juniper/version.rb`) - Plugin version management
|
395
399
|
|
400
|
+
### Platform Support
|
401
|
+
|
402
|
+
This gem supports a wide range of platforms to ensure maximum compatibility:
|
403
|
+
|
404
|
+
| Platform | Description | Use Case |
|
405
|
+
|----------|-------------|----------|
|
406
|
+
| `ruby` | Platform-independent | Pure Ruby installations |
|
407
|
+
| `x86_64-linux` | Standard Linux | Most Linux servers and CI/CD |
|
408
|
+
| `aarch64-linux` | ARM64 Linux | AWS Graviton, Raspberry Pi |
|
409
|
+
| `x86_64-linux-musl` | Alpine Linux | Docker containers |
|
410
|
+
| `x86_64-darwin` | Intel macOS | Older Mac workstations |
|
411
|
+
| `arm64-darwin-*` | Apple Silicon macOS | Modern Mac workstations |
|
412
|
+
| `x64-mingw-ucrt` | Windows (UCRT) | Windows 10/11 with modern Ruby ([bastion setup](windows-bastion-setup.md)) |
|
413
|
+
| `x86_64-freebsd` | FreeBSD | Network appliances (JunOS heritage) |
|
414
|
+
| `x86_64-solaris` | Solaris/illumos | Enterprise environments |
|
415
|
+
|
416
|
+
!!! note "Platform Compatibility"
|
417
|
+
This comprehensive platform support ensures the plugin works wherever InSpec runs, from developer workstations to CI/CD pipelines to production jump hosts. The FreeBSD support is particularly relevant given that JunOS is based on FreeBSD.
|
418
|
+
|
396
419
|
### Documentation
|
397
420
|
|
398
421
|
- **[Installation Guide](installation.md)** - Complete installation instructions
|
399
422
|
- **[Basic Usage](basic-usage.md)** - Getting started with the plugin
|
423
|
+
- **[Windows Bastion Setup](windows-bastion-setup.md)** - Windows bastion/jump host authentication guide
|
400
424
|
- **[Release Process](RELEASE_PROCESS.md)** - How to cut releases and publish gems
|
401
425
|
- **[Project Roadmap](ROADMAP.md)** - Future development plans and contribution opportunities
|
402
426
|
|
@@ -407,19 +431,29 @@ This plugin implements the Train Plugin V1 API with:
|
|
407
431
|
|
408
432
|
## Contributing
|
409
433
|
|
434
|
+
We welcome contributions! Here's how to get started:
|
435
|
+
|
410
436
|
1. Fork the repository
|
411
|
-
2. Create a feature branch
|
437
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
412
438
|
3. Make your changes with tests
|
413
|
-
4. Run `bundle exec rake test`
|
439
|
+
4. Run `bundle exec rake test` to ensure tests pass
|
414
440
|
5. Submit a pull request
|
415
441
|
|
442
|
+
Please see our [Contributing Guide](CONTRIBUTING.md) for more details.
|
443
|
+
|
416
444
|
## Support and Contact
|
417
445
|
|
446
|
+
### General Support
|
447
|
+
|
418
448
|
For questions, feature requests, or general support:
|
449
|
+
|
419
450
|
- Email: [saf@mitre.org](mailto:saf@mitre.org)
|
420
451
|
- GitHub Issues: [https://github.com/mitre/train-juniper/issues](https://github.com/mitre/train-juniper/issues)
|
421
452
|
|
453
|
+
### Security Issues
|
454
|
+
|
422
455
|
For security issues or vulnerabilities:
|
456
|
+
|
423
457
|
- Email: [saf-security@mitre.org](mailto:saf-security@mitre.org)
|
424
458
|
- GitHub Security: [https://github.com/mitre/train-juniper/security](https://github.com/mitre/train-juniper/security)
|
425
459
|
|
@@ -1,26 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'train-juniper/constants'
|
4
|
+
require 'train-juniper/connection/windows_proxy'
|
5
|
+
require 'train-juniper/connection/ssh_askpass'
|
4
6
|
|
5
7
|
module TrainPlugins
|
6
8
|
module Juniper
|
7
9
|
# Handles bastion host proxy configuration and authentication
|
8
10
|
module BastionProxy
|
11
|
+
include WindowsProxy
|
12
|
+
include SshAskpass
|
13
|
+
|
9
14
|
# Configure bastion proxy for SSH connection
|
10
15
|
# @param ssh_options [Hash] SSH options to modify
|
11
16
|
def configure_bastion_proxy(ssh_options)
|
12
|
-
require 'net/ssh/proxy/jump' unless defined?(Net::SSH::Proxy::Jump)
|
13
|
-
|
14
|
-
# Build proxy jump string from bastion options
|
15
17
|
bastion_user = @options[:bastion_user] || @options[:user]
|
16
18
|
bastion_port = @options[:bastion_port]
|
19
|
+
bastion_password = @options[:bastion_password] || @options[:password]
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
# On Windows with password auth, use plink.exe if available
|
22
|
+
if Gem.win_platform? && bastion_password && plink_available?
|
23
|
+
configure_plink_proxy(ssh_options, bastion_user, bastion_port, bastion_password)
|
24
|
+
else
|
25
|
+
configure_standard_proxy(ssh_options, bastion_user, bastion_port)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Configure standard SSH proxy using Net::SSH::Proxy::Jump
|
32
|
+
# @param ssh_options [Hash] SSH options to modify
|
33
|
+
# @param bastion_user [String] Username for bastion
|
34
|
+
# @param bastion_port [Integer] Port for bastion
|
35
|
+
def configure_standard_proxy(ssh_options, bastion_user, bastion_port)
|
36
|
+
require 'net/ssh/proxy/jump' unless defined?(Net::SSH::Proxy::Jump)
|
23
37
|
|
38
|
+
proxy_jump = build_proxy_jump_string(bastion_user, bastion_port)
|
24
39
|
@logger.debug("Using bastion host: #{proxy_jump}")
|
25
40
|
|
26
41
|
# Set up automated password authentication via SSH_ASKPASS
|
@@ -29,30 +44,35 @@ module TrainPlugins
|
|
29
44
|
ssh_options[:proxy] = Net::SSH::Proxy::Jump.new(proxy_jump)
|
30
45
|
end
|
31
46
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
47
|
+
# Configure plink.exe proxy for Windows password authentication
|
48
|
+
# @param ssh_options [Hash] SSH options to modify
|
49
|
+
# @param bastion_user [String] Username for bastion
|
50
|
+
# @param bastion_port [Integer] Port for bastion
|
51
|
+
# @param bastion_password [String] Password for bastion
|
52
|
+
def configure_plink_proxy(ssh_options, bastion_user, bastion_port, bastion_password)
|
53
|
+
require 'net/ssh/proxy/command' unless defined?(Net::SSH::Proxy::Command)
|
54
|
+
|
55
|
+
proxy_cmd = build_plink_proxy_command(
|
56
|
+
@options[:bastion_host],
|
57
|
+
bastion_user,
|
58
|
+
bastion_port,
|
59
|
+
bastion_password
|
60
|
+
)
|
61
|
+
|
62
|
+
@logger.debug('Using plink.exe for bastion proxy')
|
63
|
+
ssh_options[:proxy] = Net::SSH::Proxy::Command.new(proxy_cmd)
|
41
64
|
end
|
42
65
|
|
43
|
-
#
|
44
|
-
# @param
|
45
|
-
# @
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@logger.debug("Created SSH_ASKPASS script at #{script.path}")
|
55
|
-
script.path
|
66
|
+
# Build proxy jump string from bastion options
|
67
|
+
# @param bastion_user [String] Username for bastion
|
68
|
+
# @param bastion_port [Integer] Port for bastion
|
69
|
+
# @return [String] Proxy jump string
|
70
|
+
def build_proxy_jump_string(bastion_user, bastion_port)
|
71
|
+
if bastion_port == Constants::DEFAULT_SSH_PORT
|
72
|
+
"#{bastion_user}@#{@options[:bastion_host]}"
|
73
|
+
else
|
74
|
+
"#{bastion_user}@#{@options[:bastion_host]}:#{bastion_port}"
|
75
|
+
end
|
56
76
|
end
|
57
77
|
|
58
78
|
# Generate SSH proxy command for bastion host using ProxyJump (-J)
|
@@ -68,11 +88,7 @@ module TrainPlugins
|
|
68
88
|
end
|
69
89
|
|
70
90
|
# Use ProxyJump (-J) which handles password authentication properly
|
71
|
-
jump_host =
|
72
|
-
"#{bastion_user}@#{@options[:bastion_host]}"
|
73
|
-
else
|
74
|
-
"#{bastion_user}@#{@options[:bastion_host]}:#{bastion_port}"
|
75
|
-
end
|
91
|
+
jump_host = build_proxy_jump_string(bastion_user, bastion_port)
|
76
92
|
args += ['-J', jump_host]
|
77
93
|
|
78
94
|
# Add SSH keys if specified
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
module TrainPlugins
|
6
|
+
module Juniper
|
7
|
+
# SSH_ASKPASS script management for automated password authentication
|
8
|
+
module SshAskpass
|
9
|
+
# Set up SSH_ASKPASS for bastion password authentication
|
10
|
+
def setup_bastion_password_auth
|
11
|
+
bastion_password = @options[:bastion_password] || @options[:password]
|
12
|
+
return unless bastion_password
|
13
|
+
|
14
|
+
@ssh_askpass_script = create_ssh_askpass_script(bastion_password)
|
15
|
+
ENV['SSH_ASKPASS'] = @ssh_askpass_script
|
16
|
+
ENV['SSH_ASKPASS_REQUIRE'] = 'force'
|
17
|
+
@logger.debug('Configured SSH_ASKPASS for automated bastion authentication')
|
18
|
+
end
|
19
|
+
|
20
|
+
# Create temporary SSH_ASKPASS script for automated password authentication
|
21
|
+
# @param password [String] The password to use
|
22
|
+
# @return [String] Path to the created script
|
23
|
+
def create_ssh_askpass_script(password)
|
24
|
+
if Gem.win_platform?
|
25
|
+
create_windows_askpass_script(password)
|
26
|
+
else
|
27
|
+
create_unix_askpass_script(password)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# Create Windows PowerShell script for SSH_ASKPASS
|
34
|
+
# @param password [String] The password to use
|
35
|
+
# @return [String] Path to the wrapper batch file
|
36
|
+
def create_windows_askpass_script(password)
|
37
|
+
# :nocov:
|
38
|
+
# Create Windows PowerShell script
|
39
|
+
script = Tempfile.new(['ssh_askpass', '.ps1'])
|
40
|
+
# PowerShell handles escaping better, just escape quotes
|
41
|
+
escaped_password = password.gsub("'", "''")
|
42
|
+
script.write("Write-Output '#{escaped_password}'\r\n")
|
43
|
+
script.close
|
44
|
+
|
45
|
+
# Create a wrapper batch file to execute PowerShell with bypass policy
|
46
|
+
wrapper = Tempfile.new(['ssh_askpass_wrapper', '.bat'])
|
47
|
+
wrapper.write("@echo off\r\npowershell.exe -ExecutionPolicy Bypass -File \"#{script.path}\"\r\n")
|
48
|
+
wrapper.close
|
49
|
+
|
50
|
+
@logger.debug("Created SSH_ASKPASS PowerShell script at #{script.path} with wrapper at #{wrapper.path}")
|
51
|
+
wrapper.path
|
52
|
+
# :nocov:
|
53
|
+
end
|
54
|
+
|
55
|
+
# Create Unix shell script for SSH_ASKPASS
|
56
|
+
# @param password [String] The password to use
|
57
|
+
# @return [String] Path to the created script
|
58
|
+
def create_unix_askpass_script(password)
|
59
|
+
script = Tempfile.new(['ssh_askpass', '.sh'])
|
60
|
+
script.write("#!/bin/bash\necho '#{password}'\n")
|
61
|
+
script.close
|
62
|
+
File.chmod(0o755, script.path)
|
63
|
+
|
64
|
+
@logger.debug("Created SSH_ASKPASS script at #{script.path}")
|
65
|
+
script.path
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'shellwords'
|
4
|
+
|
5
|
+
module TrainPlugins
|
6
|
+
module Juniper
|
7
|
+
# Windows-specific proxy handling using plink.exe
|
8
|
+
# This pattern is used by various Ruby projects for Windows SSH support,
|
9
|
+
# including hglib.rb (Mercurial) and follows Net::SSH::Proxy::Command patterns
|
10
|
+
module WindowsProxy
|
11
|
+
# Check if plink.exe is available on Windows
|
12
|
+
# @return [Boolean] true if plink.exe is found in PATH
|
13
|
+
def plink_available?
|
14
|
+
return false unless Gem.win_platform?
|
15
|
+
|
16
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).any? do |path|
|
17
|
+
File.exist?(File.join(path, 'plink.exe'))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Build plink.exe proxy command for Windows bastion authentication
|
22
|
+
# @param bastion_host [String] Bastion hostname
|
23
|
+
# @param user [String] Username for bastion
|
24
|
+
# @param port [Integer] Port for bastion
|
25
|
+
# @param password [String] Password for bastion
|
26
|
+
# @return [String] Complete plink command string
|
27
|
+
def build_plink_proxy_command(bastion_host, user, port, password)
|
28
|
+
parts = []
|
29
|
+
parts << 'plink.exe'
|
30
|
+
parts << '-batch' # Non-interactive mode
|
31
|
+
parts << '-ssh' # Force SSH protocol (not telnet)
|
32
|
+
parts << '-pw'
|
33
|
+
parts << (password.include?(' ') ? "\"#{password}\"" : password)
|
34
|
+
|
35
|
+
if port && port != 22
|
36
|
+
parts << '-P'
|
37
|
+
parts << port.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
parts << "#{user}@#{bastion_host}"
|
41
|
+
parts << '-nc'
|
42
|
+
parts << '%h:%p' # Netcat mode for proxying
|
43
|
+
|
44
|
+
parts.join(' ')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/train-juniper.gemspec
CHANGED
@@ -68,8 +68,8 @@ Gem::Specification.new do |spec|
|
|
68
68
|
spec.add_dependency 'net-ssh', '>= 2.9', '< 8.0'
|
69
69
|
|
70
70
|
# FFI dependency - required by train-core
|
71
|
-
#
|
72
|
-
spec.add_dependency 'ffi', '>= 1.15.5', '< 1.
|
71
|
+
# Updated to support Ruby 3.3 on Windows (ffi 1.17.x required)
|
72
|
+
spec.add_dependency 'ffi', '>= 1.15.5', '< 1.18.0'
|
73
73
|
|
74
74
|
# Development dependencies
|
75
75
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: train-juniper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MITRE Corporation
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-06-
|
11
|
+
date: 2025-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train-core
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
version: 1.15.5
|
54
54
|
- - "<"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 1.
|
56
|
+
version: 1.18.0
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -63,7 +63,7 @@ dependencies:
|
|
63
63
|
version: 1.15.5
|
64
64
|
- - "<"
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: 1.
|
66
|
+
version: 1.18.0
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: bundler
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -227,8 +227,10 @@ files:
|
|
227
227
|
- lib/train-juniper/connection/bastion_proxy.rb
|
228
228
|
- lib/train-juniper/connection/command_executor.rb
|
229
229
|
- lib/train-juniper/connection/error_handling.rb
|
230
|
+
- lib/train-juniper/connection/ssh_askpass.rb
|
230
231
|
- lib/train-juniper/connection/ssh_session.rb
|
231
232
|
- lib/train-juniper/connection/validation.rb
|
233
|
+
- lib/train-juniper/connection/windows_proxy.rb
|
232
234
|
- lib/train-juniper/constants.rb
|
233
235
|
- lib/train-juniper/file_abstraction/juniper_file.rb
|
234
236
|
- lib/train-juniper/helpers/environment.rb
|