train-juniper 0.5.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: de67907a9faac6a664c8839ed3983998b21f9fca451cd4bfc3f054202cfabc8e
4
+ data.tar.gz: bb3c13bcccbad67ad92175fb35338a6bc63f09684536703b19c891b6fa663101
5
+ SHA512:
6
+ metadata.gz: a4eb54f25f670949ac13c90ac6116711d2c60782f4ff7e0f47cd10ee9bde93eb9c9d8056508286b37b53d74ac59899a1006ed77f252f949f44414fc5919c71d4
7
+ data.tar.gz: 9fa6602f6217e5284ee67209a7ef2fe8e5c105e992ef4a0c62b437d03b2a27bc9a7852096499a3e9de500fc47bbdb1f148dec394821699903047a2626c1587f3
data/.env.example ADDED
@@ -0,0 +1,29 @@
1
+ # Train-Juniper Environment Variables Example
2
+ # Copy this file to .env and fill in your actual values
3
+ # The plugin automatically detects these environment variables
4
+
5
+ # Juniper Device Connection
6
+ JUNIPER_HOST=your.device.hostname.com
7
+ JUNIPER_USER=your_username
8
+ JUNIPER_PASSWORD=your_password
9
+ JUNIPER_PORT=22
10
+ JUNIPER_TIMEOUT=60
11
+
12
+ # Bastion/Jump Host (optional - only if device is behind jump host)
13
+ JUNIPER_BASTION_HOST=your.jumphost.com
14
+ JUNIPER_BASTION_USER=your_jump_username
15
+ JUNIPER_BASTION_PORT=22
16
+ JUNIPER_BASTION_PASSWORD=your_jump_password
17
+
18
+ # Custom Proxy Command (alternative to bastion host)
19
+ # JUNIPER_PROXY_COMMAND=ssh your.jumphost.com -W %h:%p
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
data/CHANGELOG.md ADDED
@@ -0,0 +1,60 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.5.4] - 2025-06-18
9
+
10
+ ### Fixed
11
+
12
+ - Use manual gem push with API key for RubyGems publishing
13
+
14
+ ## [0.5.3] - 2025-06-18
15
+
16
+ ### Fixed
17
+
18
+ - Use API key authentication for RubyGems publishing
19
+
20
+ ## [0.5.2] - 2025-06-18
21
+
22
+ ### Fixed
23
+
24
+ - Update release process to include Gemfile.lock
25
+
26
+ ### Miscellaneous Tasks
27
+
28
+ - Update Gemfile.lock for version 0.5.1
29
+
30
+ ## [0.5.1] - 2025-06-18
31
+
32
+ ### Added
33
+
34
+ - Resolve dependency conflicts and establish bundle development workflow
35
+ - Comprehensive security infrastructure and development workflow improvements
36
+ - Comprehensive CI/CD improvements and code quality enhancements
37
+ - Complete repository separation and documentation restructure
38
+ - Implement Release Please for automated changelog and releases
39
+ - Implement RuboCop-style release process with local changelog generation
40
+
41
+ ### Documentation
42
+
43
+ - Update CHANGELOG.md for v0.5.0 and improve release workflow
44
+
45
+ ### Fixed
46
+
47
+ - Remove large VM images from repository
48
+ - Add x86_64-linux platform to Gemfile.lock for GitHub Actions
49
+ - Resolve CI/CD failures in security workflows
50
+ - Remove redundant security scanning and Brakeman
51
+ - Resolve RuboCop style violations in security scanner
52
+ - Remove TruffleHog from custom security scanner
53
+ - Remove extra blank line in security scanner
54
+ - Address RuboCop violations in release.rake
55
+
56
+ ### Miscellaneous Tasks
57
+
58
+ - Cleanup security infrastructure and fix test suite
59
+
60
+ <!-- generated by git-cliff -->
@@ -0,0 +1,13 @@
1
+ # Code of Conduct
2
+
3
+ This project adopts the [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) as our code of conduct.
4
+
5
+ ## Our Pledge
6
+
7
+ We are committed to making participation in this project a welcoming experience for everyone.
8
+
9
+ ## Enforcement
10
+
11
+ Instances of unacceptable behavior may be reported to the project team at [saf@mitre.org](mailto:saf@mitre.org).
12
+
13
+ For the full text of our code of conduct, please see: https://www.contributor-covenant.org/version/2/1/code_of_conduct/
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,155 @@
1
+ # Contributing to Train-Juniper
2
+
3
+ Thank you for your interest in contributing to the Train-Juniper plugin! We welcome contributions from the community.
4
+
5
+ !!! info "Quick Start for Contributors"
6
+ New to the project? Start with our [development workflow](#development-workflow) below.
7
+
8
+ ## Development Workflow :material-git:
9
+
10
+ We use a standard GitFlow workflow:
11
+
12
+ === "Quick Setup"
13
+ ```bash
14
+ # Fork and clone
15
+ git clone https://github.com/YOUR_USERNAME/train-juniper.git
16
+ cd train-juniper
17
+ bundle install
18
+
19
+ # Run tests
20
+ bundle exec rake test
21
+ ```
22
+
23
+ === "Step by Step"
24
+ 1. **Fork** :material-source-fork: the repository on GitHub
25
+ 2. **Clone** your fork locally
26
+ 3. **Create a feature branch** from `main`:
27
+ ```bash
28
+ git checkout -b feature/your-feature-name
29
+ ```
30
+ 4. **Make your changes** with appropriate tests
31
+ 5. **Run the test suite** to ensure everything passes:
32
+ ```bash
33
+ bundle install
34
+ bundle exec rake test
35
+ ```
36
+ 6. **Commit your changes** with clear, descriptive messages
37
+ 7. **Push** to your fork and **create a Pull Request**
38
+
39
+ ## Code Requirements :material-check-all:
40
+
41
+ !!! warning "Quality Standards"
42
+ All contributions must meet our quality standards before merging.
43
+
44
+ ### Testing :material-test-tube:
45
+ - **All new functionality must include tests**
46
+ - **Tests must pass**: `bundle exec rake test`
47
+ - **Maintain or improve code coverage** (currently 74%+)
48
+
49
+ ### Code Style :material-code-tags:
50
+ - **Follow existing Ruby style conventions**
51
+ - **Run linting**: `bundle exec rubocop`
52
+ - **No RuboCop violations**
53
+
54
+ ### Documentation :material-book-open:
55
+ - **Update README.md** for user-facing changes
56
+ - **Add inline documentation** for new methods
57
+ - **Update relevant documentation** in the [Train Plugin Development Guide](https://github.com/mitre/train-plugin-development-guide)
58
+
59
+ ## Types of Contributions
60
+
61
+ ### Bug Reports :material-bug:
62
+
63
+ !!! bug "Reporting Issues"
64
+ Help us fix problems by providing detailed bug reports.
65
+
66
+ **Requirements:**
67
+ - Use GitHub Issues with the "bug" label
68
+ - Include steps to reproduce
69
+ - Provide InSpec and Ruby version information
70
+ - Include relevant log output with `-l debug`
71
+
72
+ ### Feature Requests :material-lightbulb:
73
+
74
+ !!! tip "Suggesting Features"
75
+ We love new ideas! Please discuss before implementing.
76
+
77
+ **Process:**
78
+ - Open a GitHub Issue with the "enhancement" label
79
+ - Describe the use case and expected behavior
80
+ - Discuss implementation approach before coding
81
+
82
+ ### Code Contributions
83
+ - Bug fixes
84
+ - New features
85
+ - Documentation improvements
86
+ - Test coverage improvements
87
+
88
+ ## Development Setup
89
+
90
+ ```bash
91
+ # Clone your fork
92
+ git clone https://github.com/YOUR-USERNAME/train-juniper.git
93
+ cd train-juniper
94
+
95
+ # Install dependencies
96
+ bundle install
97
+
98
+ # Run tests
99
+ bundle exec rake test
100
+
101
+ # Build and test plugin locally
102
+ gem build train-juniper.gemspec
103
+ inspec plugin install ./train-juniper-0.1.0.gem
104
+ ```
105
+
106
+ ## Testing Guidelines
107
+
108
+ ### Unit Tests
109
+ - Test all public methods
110
+ - Mock external dependencies
111
+ - Fast execution (< 5 seconds total)
112
+
113
+ ### Integration Tests
114
+ - Test real SSH connectivity patterns
115
+ - Use containerized environments when possible
116
+ - Document any manual testing requirements
117
+
118
+ ### Security Testing
119
+ - Run security tests: `bundle exec ruby test/security/security_test.rb`
120
+ - Check for credential exposure
121
+ - Validate input sanitization
122
+
123
+ ## Pull Request Process
124
+
125
+ 1. **Update Documentation**: Ensure README and relevant docs are updated
126
+ 2. **Test Coverage**: Maintain or improve test coverage percentage
127
+ 3. **Security Review**: Run security tests and audit dependencies
128
+ 4. **Code Review**: Address feedback from maintainers
129
+ 5. **Merge**: Maintainers will merge approved PRs
130
+
131
+ ## Release Process
132
+
133
+ Releases are managed by project maintainers:
134
+
135
+ 1. Version bump in `lib/train-juniper/version.rb`
136
+ 2. Update `CHANGELOG.md`
137
+ 3. Create release tag
138
+ 4. Publish to RubyGems.org
139
+ 5. Update GitHub Pages documentation
140
+
141
+ ## Getting Help
142
+
143
+ - **Questions**: Open a GitHub Discussion or Issue
144
+ - **Real-time help**: Email [saf@mitre.org](mailto:saf@mitre.org)
145
+ - **Security issues**: Email [saf-security@mitre.org](mailto:saf-security@mitre.org)
146
+
147
+ ## Community
148
+
149
+ - Follow our [Code of Conduct](CODE_OF_CONDUCT.md)
150
+ - Be respectful and collaborative
151
+ - Help others learn and contribute
152
+
153
+ ## License
154
+
155
+ By contributing, you agree that your contributions will be licensed under the same Apache-2.0 license that covers the project.
data/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+ Licensed under the apache-2.0 license, except as noted below.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ * Redistributions of source code must retain the above copyright/ digital rights legend, this list of conditions and the following Notice.
6
+
7
+ * Redistributions in binary form must reproduce the above copyright copyright/ digital rights legend, this list of conditions and the following Notice in the documentation and/or other materials provided with the distribution.
8
+
9
+ * Neither the name of The MITRE Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
data/NOTICE.md ADDED
@@ -0,0 +1,9 @@
1
+ MITRE hereby grants express written permission to use, reproduce, distribute, modify, and otherwise leverage this software to the extent permitted by the licensed terms provided in the LICENSE.md file included with this project.
2
+
3
+ This software was produced for the U. S. Government under Contract Number HHSM-500-2012-00008I, and is subject to Federal Acquisition Regulation Clause 52.227-14, Rights in Data-General.
4
+
5
+ No other use other than that granted to the U. S. Government, or to those acting on behalf of the U. S. Government under that Clause is authorized without the express written permission of The MITRE Corporation.
6
+
7
+ For further information, please contact The MITRE Corporation, Contracts Management Office, 7515 Colshire Drive, McLean, VA 22102-7539, (703) 983-6000.
8
+
9
+ ©2025 The MITRE Corporation.
data/README.md ADDED
@@ -0,0 +1,399 @@
1
+ # Train Juniper Plugin
2
+
3
+ A production-ready Train plugin that provides SSH connectivity to Juniper Networks devices running JunOS for InSpec compliance testing and infrastructure inspection.
4
+
5
+ !!! info "Quick Start"
6
+ Install the plugin: `inspec plugin install train-juniper` and start testing your Juniper infrastructure immediately.
7
+
8
+ ## Features :material-star:
9
+
10
+ The plugin supports:
11
+
12
+ - :material-ssh: **SSH Authentication** - Secure connections with password or key-based auth
13
+ - :material-router-network: **JunOS Platform Detection** - Automatic version parsing and platform registration
14
+ - :material-console: **Command Execution** - CLI command execution with Juniper-specific prompt handling
15
+ - :material-network: **Proxy/Bastion Support** - Enterprise network connectivity through jump hosts
16
+ - :material-file-document: **Configuration Inspection** - Pseudo-file operations for configuration access
17
+ - :material-test-tube: **Mock Mode** - Complete testing support without requiring real hardware
18
+ - :material-speedometer: **Performance Optimized** - Efficient platform detection with result caching
19
+
20
+ ## Installation :material-download:
21
+
22
+ !!! warning "Prerequisites"
23
+ You will need InSpec v4.0 or later.
24
+
25
+ ### Production Installation (from RubyGems)
26
+
27
+ ```bash
28
+ # Search for train plugins
29
+ $ inspec plugin search train-
30
+
31
+ # Install train-juniper (once published)
32
+ $ inspec plugin install train-juniper
33
+
34
+ # Verify installation
35
+ $ inspec plugin list
36
+ ```
37
+
38
+ ### Development Installation (local testing)
39
+
40
+ ```bash
41
+ # Clone the repository
42
+ $ git clone https://github.com/mitre/train-juniper.git
43
+ $ cd train-juniper
44
+
45
+ # Install dependencies and run tests
46
+ $ bundle install
47
+ $ bundle exec rake test
48
+
49
+ # Build and install local gem
50
+ $ gem build train-juniper.gemspec
51
+ $ inspec plugin install ./train-juniper-0.1.0.gem
52
+
53
+ # Verify plugin is loaded
54
+ $ inspec plugin list
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ### Basic Connection
60
+
61
+ ```bash
62
+ # Detect platform
63
+ $ inspec detect -t juniper://admin@192.168.1.1 --password yourpassword
64
+
65
+ == Platform Details
66
+ Name: juniper
67
+ Families: network
68
+ Release: 21.4R3-S1.6
69
+ Arch: network
70
+
71
+ # Interactive shell
72
+ $ inspec shell -t juniper://admin@192.168.1.1 --password yourpassword
73
+ inspec> command('show version').stdout
74
+ => "Hostname: srx-fw\nModel: SRX340\nJunos: 21.4R3-S1.6\n..."
75
+ ```
76
+
77
+ ### With Bastion Host (Jump Host)
78
+
79
+ ```bash
80
+ # Using Train standard bastion host options
81
+ $ inspec shell -t "juniper://admin@10.1.1.1?bastion_host=jump.example.com&bastion_user=netadmin&bastion_password=jumppass"
82
+
83
+ # With custom port
84
+ $ inspec shell -t "juniper://admin@10.1.1.1?bastion_host=jump.example.com&bastion_user=netadmin&bastion_port=2222&bastion_password=jumppass"
85
+
86
+ # Using environment variables (recommended for automation)
87
+ export JUNIPER_BASTION_HOST=jump.example.com
88
+ export JUNIPER_BASTION_USER=netadmin
89
+ export JUNIPER_BASTION_PASSWORD=jump_password
90
+ export JUNIPER_PASSWORD=device_password
91
+ $ inspec shell -t juniper://admin@10.1.1.1
92
+
93
+ # Same password for both bastion and device (common scenario)
94
+ export JUNIPER_BASTION_HOST=jump.example.com
95
+ export JUNIPER_BASTION_USER=admin
96
+ export JUNIPER_PASSWORD=shared_password # Used for both when bastion_password not set
97
+ $ inspec shell -t juniper://admin@10.1.1.1
98
+ ```
99
+
100
+ ### With Custom Proxy Command
101
+
102
+ ```bash
103
+ # Using SSH ProxyCommand syntax
104
+ $ inspec shell -t "juniper://admin@device.internal?proxy_command=ssh%20jump.host%20-W%20%h:%p"
105
+
106
+ # Complex corporate network scenario
107
+ $ inspec detect -t "juniper://netadmin@core-switch.corp?bastion_host=jump.dmz.corp&bastion_user=svc_inspec"
108
+ ```
109
+
110
+ ### Environment Variables (Auto-Detection)
111
+
112
+ The plugin automatically detects and uses standard environment variables, eliminating the need to pass connection flags:
113
+
114
+ ```bash
115
+ # Basic connection with auto-detection
116
+ export JUNIPER_HOST=192.168.1.1
117
+ export JUNIPER_USER=admin
118
+ export JUNIPER_PASSWORD=yourpassword
119
+ inspec detect -t juniper:// # No flags needed!
120
+
121
+ # With bastion host auto-detection
122
+ export JUNIPER_HOST=internal.device.corp
123
+ export JUNIPER_USER=netadmin
124
+ export JUNIPER_PASSWORD=devicepass
125
+ export JUNIPER_BASTION_HOST=jump.corp.com
126
+ export JUNIPER_BASTION_USER=admin
127
+ export JUNIPER_BASTION_PASSWORD=bastionpass
128
+ inspec detect -t juniper:// # Automatically uses bastion!
129
+
130
+ # Using .env file (recommended for development)
131
+ # Create .env file with your credentials:
132
+ source .env
133
+ inspec detect -t juniper:// # Reads from .env automatically
134
+ ```
135
+
136
+ ## Configuration Options
137
+
138
+ ### Connection Options
139
+
140
+ | Option | Description | Default | Environment Variable |
141
+ |--------|-------------|---------|---------------------|
142
+ | `host` | Juniper device hostname/IP | - | `JUNIPER_HOST` |
143
+ | `user` | SSH username | - | `JUNIPER_USER` |
144
+ | `password` | SSH password | - | `JUNIPER_PASSWORD` |
145
+ | `port` | SSH port | 22 | `JUNIPER_PORT` |
146
+ | `timeout` | Connection timeout (seconds) | 30 | `JUNIPER_TIMEOUT` |
147
+ | `keepalive` | SSH keepalive enabled | true | - |
148
+ | `keepalive_interval` | SSH keepalive interval (seconds) | 60 | - |
149
+
150
+ ### Proxy/Bastion Options
151
+
152
+ | Option | Description | Default | Environment Variable |
153
+ |--------|-------------|---------|---------------------|
154
+ | `bastion_host` | SSH bastion/jump host | - | `JUNIPER_BASTION_HOST` |
155
+ | `bastion_user` | SSH bastion username | root | `JUNIPER_BASTION_USER` |
156
+ | `bastion_port` | SSH bastion port | 22 | `JUNIPER_BASTION_PORT` |
157
+ | `bastion_password` | Password for bastion authentication | - | `JUNIPER_BASTION_PASSWORD` |
158
+ | `proxy_command` | Custom SSH ProxyCommand | - | `JUNIPER_PROXY_COMMAND` |
159
+ | `key_files` | SSH private key files | - | - |
160
+ | `keys_only` | Use only specified keys | false | - |
161
+
162
+ **Notes**:
163
+ - Cannot specify both `bastion_host` and `proxy_command` simultaneously
164
+ - If `bastion_password` not provided, falls back to using `password` for bastion authentication
165
+ - Supports automated password authentication via SSH_ASKPASS mechanism
166
+
167
+ ### InSpec Configuration File
168
+
169
+ Create `~/.inspec/config.json`:
170
+
171
+ ```json
172
+ {
173
+ "credentials": {
174
+ "juniper-lab": {
175
+ "target": "juniper://admin@lab-srx.example.com",
176
+ "password": "yourpassword",
177
+ "insecure": true
178
+ }
179
+ }
180
+ }
181
+ ```
182
+
183
+ Then use: `inspec detect --config=juniper-lab`
184
+
185
+ ## Proxy Connection Patterns
186
+
187
+ The train-juniper plugin supports Train-standard proxy/bastion connections for enterprise environments where Juniper devices are behind jump hosts or in isolated network segments.
188
+
189
+ ### Authentication Patterns
190
+
191
+ **Important**: Train does not have a separate `--bastion-password` option. Here are the standard authentication patterns:
192
+
193
+ #### 🔐 **Same Credentials (Most Common)**
194
+ Use the same `--password` for both bastion host and Juniper device:
195
+
196
+ ```bash
197
+ # Same username/password for jump host and device
198
+ inspec detect -t "juniper://admin@device.internal?bastion_host=jump.corp.com&bastion_user=admin" --password "shared_password"
199
+
200
+ # With environment variables
201
+ export JUNIPER_PASSWORD="shared_password"
202
+ inspec shell -t "juniper://admin@device.internal?bastion_host=jump.corp.com&bastion_user=admin"
203
+ ```
204
+
205
+ #### 🔑 **SSH Key Authentication (Recommended)**
206
+ Use SSH keys for both connections:
207
+
208
+ ```bash
209
+ # SSH keys for both bastion and device
210
+ inspec detect -t "juniper://admin@device.internal?bastion_host=jump.corp.com&bastion_user=admin" -i ~/.ssh/id_rsa
211
+
212
+ # With multiple keys
213
+ inspec shell -t "juniper://admin@device.internal?bastion_host=jump.corp.com" --key-files ~/.ssh/bastion_key ~/.ssh/device_key
214
+ ```
215
+
216
+ #### 🔗 **Different Credentials (Advanced)**
217
+ Use SSH ProxyCommand when bastion and device require different authentication:
218
+
219
+ ```bash
220
+ # Bastion uses one password, device uses another (embed bastion auth in proxy command)
221
+ inspec detect -t "juniper://deviceuser@device.internal?proxy_command=sshpass%20-p%20bastionpass%20ssh%20bastionuser@jump.corp.com%20-W%20%h:%p" --password "device_password"
222
+
223
+ # Bastion uses SSH key, device uses password
224
+ inspec shell -t "juniper://admin@device.internal?proxy_command=ssh%20-i%20~/.ssh/bastion_key%20admin@jump.corp.com%20-W%20%h:%p" --password "device_password"
225
+ ```
226
+
227
+ ### Bastion Host Scenarios
228
+
229
+ ```bash
230
+ # Corporate network with dedicated jump host
231
+ inspec exec profile -t "juniper://admin@core-switch.internal?bastion_host=jump.corp.com&bastion_user=netadmin" --password "shared_password"
232
+
233
+ # Cloud environment with bastion instance
234
+ inspec exec profile -t "juniper://ubuntu@10.0.1.100?bastion_host=bastion.aws.company.com&bastion_port=2222" --key-files ~/.ssh/aws_key
235
+
236
+ # DMZ access pattern
237
+ inspec detect -t "juniper://operator@firewall.dmz?bastion_host=jump.dmz.corp&bastion_user=svc_account" --password "corporate_password"
238
+ ```
239
+
240
+ ### Custom Proxy Commands
241
+
242
+ ```bash
243
+ # SSH ProxyCommand for complex routing
244
+ inspec shell -t "juniper://admin@device?proxy_command=ssh%20-o%20StrictHostKeyChecking=no%20jump%20nc%20%h%20%p"
245
+
246
+ # Multi-hop proxy (SSH chain)
247
+ inspec exec profile -t "juniper://admin@target?proxy_command=ssh%20-J%20first-jump,second-jump%20-W%20%h:%p"
248
+ ```
249
+
250
+ ### SSH Key Authentication with Proxy
251
+
252
+ ```ruby
253
+ # In Ruby code or configuration
254
+ Train.create('juniper', {
255
+ host: 'secure.device.corp',
256
+ user: 'admin',
257
+ bastion_host: 'jump.corp.com',
258
+ bastion_user: 'automation',
259
+ key_files: ['/path/to/private/key'],
260
+ keys_only: true
261
+ })
262
+ ```
263
+
264
+ ### Common Authentication Issues
265
+
266
+ #### ❌ **Error**: "No bastion password specified"
267
+ **Solution**: Train doesn't have `--bastion-password`. Use one of these patterns:
268
+ ```bash
269
+ # Same password for both (most common)
270
+ inspec detect -t "juniper://user@device?bastion_host=jump" --password "shared_pass"
271
+
272
+ # SSH keys (recommended)
273
+ inspec detect -t "juniper://user@device?bastion_host=jump" --key-files ~/.ssh/id_rsa
274
+
275
+ # Different passwords (use proxy command)
276
+ inspec detect -t "juniper://user@device?proxy_command=sshpass%20-p%20jumppass%20ssh%20jumpuser@jump%20-W%20%h:%p" --password "device_pass"
277
+ ```
278
+
279
+ #### ❌ **Error**: "Authentication failed"
280
+ **Solutions**:
281
+ ```bash
282
+ # Verify bastion connection first
283
+ ssh jumpuser@jump.corp.com
284
+
285
+ # Test direct device connection (if accessible)
286
+ ssh deviceuser@device.internal
287
+
288
+ # Use verbose SSH for debugging
289
+ inspec detect -t "juniper://user@device?bastion_host=jump&proxy_command=ssh%20-v%20jump%20-W%20%h:%p" --password "pass"
290
+
291
+ # Use InSpec debug mode for detailed logging
292
+ inspec detect -t "juniper://user@device?bastion_host=jump" --password "pass" -l debug
293
+ ```
294
+
295
+ #### ❌ **Error**: "Connection timeout"
296
+ **Solutions**:
297
+ ```bash
298
+ # Increase timeouts
299
+ inspec detect -t "juniper://user@device?bastion_host=jump&connection_timeout=60" --password "pass"
300
+
301
+ # Check network connectivity
302
+ ping device.internal # From bastion host
303
+ telnet device.internal 22 # Test SSH port
304
+ ```
305
+
306
+ ## Development
307
+
308
+ ### Requirements
309
+
310
+ - Ruby 3.1+
311
+ - Bundler
312
+ - InSpec 4.0+ (for testing)
313
+
314
+ ### Setup
315
+
316
+ ```bash
317
+ git clone https://github.com/mitre/train-juniper.git
318
+ cd train-juniper
319
+ bundle install
320
+ ```
321
+
322
+ ### Testing
323
+
324
+ ```bash
325
+ # Run all tests
326
+ bundle exec rake test
327
+
328
+ # Run individual test suites
329
+ bundle exec ruby test/unit/connection_test.rb
330
+ bundle exec ruby test/functional/juniper_test.rb
331
+
332
+ # Lint code
333
+ bundle exec rubocop
334
+ ```
335
+
336
+ ### Architecture
337
+
338
+ This plugin implements the Train Plugin V1 API with:
339
+
340
+ - **Transport** (`lib/train-juniper/transport.rb`) - Plugin registration and factory
341
+ - **Connection** (`lib/train-juniper/connection.rb`) - SSH connectivity and command execution
342
+ - **Platform** (`lib/train-juniper/platform.rb`) - JunOS platform detection
343
+ - **Version** (`lib/train-juniper/version.rb`) - Plugin version management
344
+
345
+ ### Documentation
346
+
347
+ - **[Installation Guide](installation.md)** - Complete installation instructions
348
+ - **[Basic Usage](basic-usage.md)** - Getting started with the plugin
349
+ - **[Release Process](RELEASE_PROCESS.md)** - How to cut releases and publish gems
350
+ - **[Project Roadmap](ROADMAP.md)** - Future development plans and contribution opportunities
351
+
352
+ ### Plugin Development Resources
353
+
354
+ - **[Train Plugin Development Guide](https://github.com/mitre/train-plugin-development-guide)** - Comprehensive tutorial for Train plugin development
355
+ - **How This Plugin Was Built** - See modules 20-22 in the development guide for our research methodology, implementation approach, and containerlab testing environment
356
+
357
+ ## Contributing
358
+
359
+ 1. Fork the repository
360
+ 2. Create a feature branch
361
+ 3. Make your changes with tests
362
+ 4. Run `bundle exec rake test`
363
+ 5. Submit a pull request
364
+
365
+ ## Support and Contact
366
+
367
+ For questions, feature requests, or general support:
368
+ - Email: [saf@mitre.org](mailto:saf@mitre.org)
369
+ - GitHub Issues: [https://github.com/mitre/train-juniper/issues](https://github.com/mitre/train-juniper/issues)
370
+
371
+ For security issues or vulnerabilities:
372
+ - Email: [saf-security@mitre.org](mailto:saf-security@mitre.org)
373
+ - GitHub Security: [https://github.com/mitre/train-juniper/security](https://github.com/mitre/train-juniper/security)
374
+
375
+ ## Acknowledgments
376
+
377
+ This project was inspired by and references several excellent community Train plugins:
378
+
379
+ - **[train-rest](https://github.com/prospectra/train-rest)** by Thomas Heinen (Prospectra) - REST API transport patterns
380
+ - **[train-awsssm](https://github.com/prospectra/train-awsssm)** by Thomas Heinen (Prospectra) - AWS Systems Manager transport
381
+ - **[train-pwsh](https://github.com/mitre/train-pwsh)** by MITRE SAF Team - PowerShell/Windows automation transport
382
+ - **[train-k8s-container](https://github.com/inspec/train-k8s-container)** by InSpec Team - Kubernetes container platform detection
383
+ - **[train-local-rot13](https://github.com/inspec/train/tree/master/examples/plugins/train-local-rot13)** by InSpec Team - Official plugin development example
384
+
385
+ Special thanks to the Train and InSpec communities for their excellent documentation and plugin examples.
386
+
387
+ ## License
388
+
389
+ Licensed under the Apache-2.0 license, except as noted below.
390
+
391
+ See [LICENSE](LICENSE.md) for full details.
392
+
393
+ ### Notice
394
+
395
+ This software was produced for the U.S. Government under contract and is subject to Federal Acquisition Regulation Clause 52.227-14.
396
+
397
+ See [NOTICE](NOTICE.md) for full details.
398
+
399
+ © 2025 The MITRE Corporation.