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 +7 -0
- data/.env.example +29 -0
- data/CHANGELOG.md +60 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/CONTRIBUTING.md +155 -0
- data/LICENSE.md +9 -0
- data/NOTICE.md +9 -0
- data/README.md +399 -0
- data/Rakefile +94 -0
- data/SECURITY.md +79 -0
- data/lib/train-juniper/connection.rb +408 -0
- data/lib/train-juniper/platform.rb +191 -0
- data/lib/train-juniper/transport.rb +55 -0
- data/lib/train-juniper/version.rb +12 -0
- data/lib/train-juniper.rb +23 -0
- data/train-juniper.gemspec +72 -0
- metadata +115 -0
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 -->
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -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.
|