This commit includes: - SSL Manager implementation for certificate operations - Configuration file with UniFi device parameters - Test files for various components - Documentation for UniFi verification - Project guidelines
266 lines
8.5 KiB
Markdown
266 lines
8.5 KiB
Markdown
# SSL Management Project Guidelines
|
|
|
|
This document provides guidelines for developing and maintaining the SSL Management project, which is a Python-based tool for managing SSL certificates for UniFi devices such as UDM-SE. The tool helps automate the process of obtaining, validating, and deploying SSL certificates to UniFi devices.
|
|
|
|
## Build/Configuration Instructions
|
|
|
|
### Prerequisites
|
|
|
|
1. **Python 3.6+**: The project is written in Python and requires Python 3.6 or higher.
|
|
2. **OpenSSL**: Required for certificate operations. Must be installed and available in your PATH.
|
|
3. **Virtual Environment**: The project uses a virtual environment for dependency isolation.
|
|
4. **Linux Environment**: The script is designed to run on Linux systems such as Ubuntu 24.04. While development can occur on any platform, deployment is expected on a Linux server.
|
|
|
|
### Setup
|
|
|
|
1. Clone the repository:
|
|
```bash
|
|
git clone <repository-url>
|
|
cd ssl-managment
|
|
```
|
|
|
|
2. Create and activate a virtual environment:
|
|
```bash
|
|
python -m venv .venv
|
|
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
```
|
|
|
|
3. No external Python packages are required as the project uses standard library modules.
|
|
|
|
### Configuration
|
|
|
|
The SSL Manager uses a configuration file (`config.json`) to store default settings. The configuration file should be placed in the project root directory. Here's an example of the configuration file:
|
|
|
|
```json
|
|
{
|
|
"cert_dir": "~/.ssl-certs",
|
|
"default_port": 443,
|
|
"connection_timeout": 3.0,
|
|
"default_validity_days": 365,
|
|
"key_size": 2048,
|
|
"unifi": {
|
|
"host": "unifi.example.com",
|
|
"username": "admin",
|
|
"password": "password",
|
|
"site": "default",
|
|
"ssh_port": 22,
|
|
"ssh_username": "root",
|
|
"ssh_password": "",
|
|
"ssh_key_path": "~/.ssh/id_rsa"
|
|
}
|
|
}
|
|
```
|
|
|
|
Configuration options:
|
|
- `cert_dir`: Directory where certificates and keys will be stored
|
|
- `default_port`: Default port to use when checking certificate expiration
|
|
- `connection_timeout`: Timeout in seconds for SSL connections
|
|
- `default_validity_days`: Default validity period in days for generated certificates
|
|
- `key_size`: Key size in bits for generated certificates
|
|
- `unifi`: UniFi device connection parameters
|
|
- `host`: Hostname or IP address of the UniFi device
|
|
- `username`: Username for authenticating with the UniFi device
|
|
- `password`: Password for authenticating with the UniFi device
|
|
- `site`: Site name for the UniFi device (default: 'default')
|
|
- `ssh_port`: SSH port for the UniFi device (default: 22)
|
|
- `ssh_username`: Username for SSH authentication with the UniFi device
|
|
- `ssh_password`: Password for SSH authentication (leave empty to use SSH key)
|
|
- `ssh_key_path`: Path to the SSH private key file for authentication
|
|
|
|
### Usage
|
|
|
|
The SSL Manager provides three main commands. All commands support the following global options:
|
|
|
|
- `--config`: Path to the config file (default: config.json)
|
|
- `--cert-dir`: Directory to store certificates (overrides config)
|
|
|
|
1. **Check Certificate Expiration**:
|
|
```bash
|
|
python src/ssl_manager.py check example.com [--port PORT]
|
|
```
|
|
The `--port` option overrides the `default_port` from the config file.
|
|
|
|
2. **Generate Self-Signed Certificate**:
|
|
```bash
|
|
python src/ssl_manager.py generate example.com [--days DAYS]
|
|
```
|
|
The `--days` option overrides the `default_validity_days` from the config file.
|
|
|
|
3. **Validate Certificate Chain**:
|
|
```bash
|
|
python src/ssl_manager.py validate path/to/certificate.crt [--ca-path path/to/ca.crt]
|
|
```
|
|
|
|
## Testing Information
|
|
|
|
### Running Tests
|
|
|
|
Tests are written using the Python `unittest` framework. To run all tests:
|
|
|
|
```bash
|
|
cd ssl-managment # Ensure you're in the project root
|
|
python -m unittest discover tests
|
|
```
|
|
|
|
To run a specific test file:
|
|
|
|
```bash
|
|
python -m tests.test_ssl_manager
|
|
```
|
|
|
|
### Adding New Tests
|
|
|
|
1. Create a new test file in the `tests` directory, following the naming convention `test_*.py`.
|
|
2. Import the necessary modules and the `SSLManager` class:
|
|
```python
|
|
import os
|
|
import sys
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
# Add the src directory to the Python path
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../src')))
|
|
|
|
from ssl_manager import SSLManager
|
|
```
|
|
|
|
3. Create a test class that inherits from `unittest.TestCase`:
|
|
```python
|
|
class TestYourFeature(unittest.TestCase):
|
|
def setUp(self):
|
|
# Set up test fixtures
|
|
self.ssl_manager = SSLManager()
|
|
|
|
def test_your_feature(self):
|
|
# Test your feature
|
|
result = self.ssl_manager.your_method()
|
|
self.assertEqual(result, expected_value)
|
|
```
|
|
|
|
4. Use mocking to avoid actual network or system calls:
|
|
```python
|
|
@patch('ssl_manager.subprocess.run')
|
|
def test_with_mock(self, mock_run):
|
|
mock_run.return_value = MagicMock(returncode=0)
|
|
# Test with mock
|
|
```
|
|
|
|
### Test Example
|
|
|
|
Here's a simple test that verifies the SSLManager initializes correctly:
|
|
|
|
```python
|
|
def test_init_creates_cert_dir(self):
|
|
"""Test that the constructor creates the certificate directory."""
|
|
test_path = os.path.expanduser("~/test-ssl-certs")
|
|
|
|
# Remove the directory if it exists
|
|
if os.path.exists(test_path):
|
|
os.rmdir(test_path)
|
|
|
|
# Create a new SSLManager with the test path
|
|
ssl_manager = SSLManager(cert_dir=test_path)
|
|
|
|
# Verify the directory was created
|
|
self.assertTrue(os.path.exists(test_path))
|
|
self.assertTrue(os.path.isdir(test_path))
|
|
|
|
# Clean up
|
|
os.rmdir(test_path)
|
|
```
|
|
|
|
## Development Guidelines
|
|
|
|
### Code Style
|
|
|
|
1. **PEP 8**: Follow the [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guide for Python code.
|
|
2. **Docstrings**: Use docstrings for all modules, classes, and functions. Follow the [Google style](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) for docstrings.
|
|
3. **Type Hints**: Use type hints for function parameters and return values.
|
|
|
|
### Project Structure
|
|
|
|
- `src/`: Contains the source code
|
|
- `ssl_manager.py`: Main module with the SSLManager class
|
|
- `tests/`: Contains test files
|
|
- `test_ssl_manager.py`: Tests for the SSLManager class
|
|
|
|
### Best Practices
|
|
|
|
1. **Error Handling**: Use try-except blocks to handle exceptions gracefully.
|
|
2. **Logging**: Use the Python logging module for logging instead of print statements.
|
|
3. **Testing**: Write tests for all new features and bug fixes.
|
|
4. **Documentation**: Update documentation when making changes to the code.
|
|
|
|
## Deployment and Automation
|
|
|
|
### Cross-Machine Deployment
|
|
|
|
The SSL Management tool can be developed on one machine and deployed to another server for production use. When deploying across machines:
|
|
|
|
1. Ensure the target server meets all the prerequisites (Python 3.6+, OpenSSL, etc.)
|
|
2. Transfer the entire project directory to the target server
|
|
3. Set up the virtual environment on the target server
|
|
4. Configure the `config.json` file with the appropriate settings for the target environment
|
|
5. Test the deployment by running a simple command like `python src/ssl_manager.py check <hostname>`
|
|
|
|
### Automated Certificate Updates
|
|
|
|
To automate certificate updates using cron:
|
|
|
|
1. Create a shell script wrapper for the SSL Manager:
|
|
```bash
|
|
#!/bin/bash
|
|
# File: update_certificates.sh
|
|
|
|
# Change to the project directory
|
|
cd /path/to/ssl-managment
|
|
|
|
# Activate the virtual environment
|
|
source .venv/bin/activate
|
|
|
|
# Run the SSL Manager to update certificates
|
|
python src/ssl_manager.py generate your-unifi-device.example.com --days 90
|
|
|
|
# Additional commands to deploy the certificate to the UniFi device can be added here
|
|
```
|
|
|
|
2. Make the script executable:
|
|
```bash
|
|
chmod +x update_certificates.sh
|
|
```
|
|
|
|
3. Add a cron job to run the script periodically (e.g., every 60 days):
|
|
```bash
|
|
# Edit the crontab
|
|
crontab -e
|
|
|
|
# Add a line like this to run at 2:30 AM on the 1st of every other month
|
|
30 2 1 */2 * /path/to/update_certificates.sh >> /var/log/certificate-updates.log 2>&1
|
|
```
|
|
|
|
4. Verify the cron job is set up correctly:
|
|
```bash
|
|
crontab -l
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **OpenSSL Command Not Found**
|
|
|
|
Ensure OpenSSL is installed and in your PATH.
|
|
|
|
2. **Permission Denied When Creating Certificates**
|
|
|
|
Check that you have write permissions to the certificate directory.
|
|
|
|
3. **Import Errors in Tests**
|
|
|
|
Make sure you're running tests from the project root directory.
|
|
|
|
### Debugging
|
|
|
|
- Set the `SSL_DEBUG=1` environment variable for verbose output
|
|
- Check the OpenSSL version with `openssl version`
|
|
- Verify certificate paths are correct and accessible |