-
Notifications
You must be signed in to change notification settings - Fork 0
Complete Documentation
- Overview
- Features
- Requirements
- Installation
- Configuration
- Usage
- API Mapping
- User Management
- Advanced Configuration
- Troubleshooting
- Best Practices
- Examples
- Contributing
- FAQ
- Credits
rudder2snipe is a Python-based tool that synchronizes asset inventory between Rudder.io (configuration management platform) and Snipe-IT (asset management system). It automatically creates, updates, and manages hardware assets in Snipe-IT based on node information from Rudder.
- Automated Sync: Eliminates manual data entry between systems
- Bidirectional Updates: Keeps both systems in sync
- Flexible Mapping: Customizable field mapping between Rudder and Snipe-IT
- Asset Lifecycle: Handles creation, updates, and user assignments
- Error Recovery: Built-in retry mechanisms and error handling
- ✅ Asset Discovery: Automatically finds Rudder nodes and creates corresponding Snipe-IT assets
- ✅ Model Management: Creates hardware models in Snipe-IT based on Rudder machine types
- ✅ Field Mapping: Maps Rudder node properties to Snipe-IT asset fields
- ✅ User Assignment: Associates assets with users based on configurable mapping
- ✅ Asset Tag Sync: Synchronizes asset tags between systems (Snipe-IT as authority)
- ✅ Timestamp Checking: Only updates when source data is newer than destination
- ✅ Dry Run Mode: Test configuration without making changes
- ✅ Connection Testing: Verify API connectivity before operations
- ✅ Rate Limiting: Respects API rate limits (120 requests/minute)
- ✅ SSL Configuration: Supports custom SSL verification settings
- ✅ Force Updates: Override timestamp checking when needed
- ✅ Auto-incrementing: Support for auto-incrementing asset tags
- ✅ Detailed Logging: Comprehensive logging with multiple verbosity levels
- ✅ Error Handling: Graceful handling of API errors and network issues
- Python: 3.7 or higher
- Operating System: Linux, macOS, or Windows
- Network: Access to both Rudder and Snipe-IT instances
pip install requests configparser argparseOr use the provided requirements file:
pip install -r requirements.txt- Rudder API Token: Read permissions for nodes endpoint
- Snipe-IT API Key: Create/edit permissions for assets, models, and users
- Network Connectivity: HTTPS access to both API endpoints
# Download the latest release
wget https://github.com/norbertoaquino/rudder2snipe/archive/main.zip
unzip main.zip
cd rudder2snipe-maingit clone https://github.com/norbertoaquino/rudder2snipe.git
cd rudder2snipe# Install to /opt (recommended for production)
sudo mkdir -p /opt/rudder2snipe
sudo cp -r * /opt/rudder2snipe/
sudo chown -R rudder:rudder /opt/rudder2snipe# Create virtual environment
python3 -m venv ~/.virtualenv/rudder2snipe
source ~/.virtualenv/rudder2snipe/bin/activate
# Install dependencies
pip install -r requirements.txt- Copy Example Configuration:
cp settings-rudder.conf.example settings.conf- Edit Configuration File:
vim settings.conf # or your preferred editorrudder2snipe searches for settings.conf in the following order:
/opt/rudder2snipe/settings.conf/etc/rudder2snipe/settings.conf-
./settings.conf(current directory)
[rudder]
url = https://your-rudder-server.domain.com
api_token = YOUR-RUDDER-API-TOKEN-HERERequired Fields:
-
url: Full URL to your Rudder server (without trailing slash) -
api_token: Rudder API token with read permissions
[snipe-it]
url = https://your-snipe-instance.domain.com
apikey = YOUR-SNIPE-API-KEY-HERE
manufacturer_id = 2
defaultStatus = 2
computer_model_category_id = 2Required Fields:
-
url: Full URL to your Snipe-IT instance (without trailing slash) -
apikey: Snipe-IT API key with create/edit permissions -
manufacturer_id: Default manufacturer ID for new assets -
defaultStatus: Default status ID for new assets -
computer_model_category_id: Category ID for computer models
Optional Fields:
-
computer_custom_fieldset_id: Custom fieldset for computer models -
asset_tag: Custom asset tag field (defaults to rudderid-{id})
- Go to Snipe-IT Admin → Manufacturers
- Enable the ID column (click column selector)
- Note the ID of your default manufacturer (usually "Apple" or "Dell")
- Go to Snipe-IT Admin → Status Labels
- Enable the ID column
- Note the ID for "Ready to Deploy" or similar status
- Go to Snipe-IT Admin → Categories
- Enable the ID column
- Note the ID for your computer category
python3 rudder2snipe [OPTIONS]-
-h, --help: Show help message -
-v, --verbose: Enable INFO level logging -
-d, --debug: Enable DEBUG level logging -
--version: Show version and exit
-
--dryrun: Test run without making changes -
--connection_test: Test API connectivity only -
-f, --force: Force update regardless of timestamps -
--auto_incrementing: Use Snipe-IT auto-incrementing asset tags
-
--do_not_verify_ssl: Skip SSL certificate verification -
-r, --ratelimited: Enable rate limiting (120 requests/minute) -
--do_not_update_rudder: Don't sync asset tags back to Rudder
-
-u, --users: Check out assets to users if not deployed -
-ui, --users_inverse: Check out assets to users if already deployed -
-uf, --users_force: Force check out assets to users -
-uns, --users_no_search: Don't search for users if fields don't match
python3 rudder2snipe --connection_testpython3 rudder2snipe --dryrun --verbosepython3 rudder2snipe --verbosepython3 rudder2snipe --force --verbosepython3 rudder2snipe --ratelimited --verboseAPI mapping defines how Rudder node properties map to Snipe-IT asset fields.
[api-mapping]
# Snipe Field = Rudder Property Path
name = hostname
_snipeit_mac_address_1 = properties ipHostNumber
_snipeit_os_2 = properties osName
_snipeit_os_version_3 = properties osVersion
_snipeit_machine_type_4 = properties machineType
_snipeit_manufacturer_5 = properties manufacturer
_snipeit_memory_6 = properties memorySize| Snipe-IT Field | Description | Example Mapping |
|---|---|---|
name |
Asset name | hostname |
serial |
Serial number | properties serialNumber |
model_id |
Model (auto-managed) | properties machineType |
asset_tag |
Asset tag | properties serialNumber |
Custom fields in Snipe-IT use the format _snipeit_fieldname_id:
-
Get Custom Field DB Name:
- Go to Snipe-IT Admin → Custom Fields
- Enable "DB Field" column
- Copy the DB field name
-
Add to Mapping:
[api-mapping]
_snipeit_ip_address_1 = properties ipHostNumber
_snipeit_cpu_model_2 = properties processorModel
_snipeit_ram_size_3 = properties memorySizeCommon Rudder node properties you can map:
| Property Path | Description | Example Value |
|---|---|---|
hostname |
Node hostname | server01.example.com |
properties osName |
Operating system | Ubuntu |
properties osVersion |
OS version | 20.04 |
properties osKernelVersion |
Kernel version | 5.4.0-42-generic |
properties machineType |
Hardware model | PowerEdge R640 |
properties manufacturer |
Hardware manufacturer | Dell Inc. |
properties serialNumber |
Serial number | 1234567890 |
properties memorySize |
RAM size | 32768 |
properties ipHostNumber |
IP address | 192.168.1.100 |
properties timezone |
System timezone | UTC |
properties agentName |
Rudder agent version | cfengine-community |
[api-mapping]
_snipeit_os_name_1 = properties osName
_snipeit_os_version_2 = properties osVersion
_snipeit_os_kernel_3 = properties osKernelVersion
_snipeit_os_full_4 = properties osFullName[api-mapping]
_snipeit_cpu_model_5 = properties processorModel
_snipeit_cpu_cores_6 = properties processorCount
_snipeit_ram_size_7 = properties memorySize
_snipeit_disk_size_8 = properties diskSize[api-mapping]
_snipeit_ip_address_9 = properties ipHostNumber
_snipeit_mac_address_10 = properties macAddress
_snipeit_hostname_11 = hostname
_snipeit_fqdn_12 = properties fqdnrudder2snipe can automatically assign assets to users based on Rudder node information.
[user-mapping]
rudder_api_field = properties username- Assigns assets to users only if they're not already deployed
- Good for initial setup
python3 rudder2snipe --users --verbose- Assigns assets to users only if they're already deployed
- Good for reassignments
python3 rudder2snipe --users_inverse --verbose- Always assigns assets to users regardless of current status
- Overwrites existing assignments
python3 rudder2snipe --users_force --verbose- Doesn't search Snipe-IT if username doesn't match exactly
- Faster but less flexible
python3 rudder2snipe --users --users_no_search --verbose[user-mapping]
rudder_api_field = properties username[user-mapping]
rudder_api_field = properties primaryUser[user-mapping]
rudder_api_field = properties assetOwnerBy default, rudder2snipe uses rudderid-{node_id} for asset tags. You can customize this:
[snipe-it]
asset_tag = properties serialNumberIf Snipe-IT has auto-incrementing asset tags enabled:
python3 rudder2snipe --auto_incrementingpython3 rudder2snipe --do_not_verify_sslexport REQUESTS_CA_BUNDLE=/path/to/ca-certificates.crt
python3 rudder2snipeFor large environments or shared Snipe-IT instances:
python3 rudder2snipe --ratelimitedThis adds a 0.5-second delay between API calls to stay under 120 requests/minute.
- WARNING (default): Only errors and warnings
-
INFO (
--verbose): Basic operation information -
DEBUG (
--debug): Detailed debugging information
python3 rudder2snipe --verbose 2>&1 | tee rudder2snipe.logProblem: 401 Unauthorized or 403 Forbidden
Solutions:
- Verify API tokens are correct
- Check token permissions
- Ensure tokens haven't expired
# Test Rudder API
curl -H "X-API-TOKEN: YOUR-TOKEN" https://rudder.example.com/rudder/api/latest/nodes
# Test Snipe-IT API
curl -H "Authorization: Bearer YOUR-TOKEN" https://snipe.example.com/api/v1/hardwareProblem: Connection timeout or SSL errors
Solutions:
- Check network connectivity
- Verify URLs are correct (no trailing slashes)
- Test SSL configuration
# Test connectivity
python3 rudder2snipe --connection_test
# Skip SSL verification (temporary)
python3 rudder2snipe --do_not_verify_ssl --connection_testProblem: 429 Too Many Requests
Solutions:
- Enable rate limiting
- Reduce concurrent operations
python3 rudder2snipe --ratelimitedProblem: Cannot create assets or models
Solutions:
- Check Snipe-IT user permissions
- Verify API key scope
- Test with web interface
Problem: Fields not updating or incorrect values
Solutions:
- Verify field names in api-mapping
- Check custom field DB names
- Test with debug logging
python3 rudder2snipe --debug --dryrunpython3 rudder2snipe --debug --dryrun --verbose- Note asset serial number from logs
- Check in both Rudder and Snipe-IT
- Compare field values
# Test with curl to see raw API responses
curl -H "Authorization: Bearer TOKEN" https://snipe.example.com/api/v1/hardware/byserial/SERIAL# Add to crontab for hourly sync
0 * * * * /opt/rudder2snipe/.venv/bin/python /opt/rudder2snipe/rudder2snipe --ratelimited >> /var/log/rudder2snipe.log 2>&1- Create dedicated service accounts in both systems
- Use least-privilege permissions
- Rotate API keys regularly
# Monitor log files
tail -f /var/log/rudder2snipe.log
# Check for errors
grep -i error /var/log/rudder2snipe.log- Store configuration in version control
- Use templates with variables
- Document all custom mappings
# Different configs for different environments
/opt/rudder2snipe/
├── settings-prod.conf
├── settings-staging.conf
└── settings-dev.conf- Backup Snipe-IT database before major changes
- Test in staging environment first
- Keep configuration backups
- Use rate limiting (
--ratelimited) - Run during off-peak hours
- Monitor API response times
- Filter nodes in Rudder if possible
- Use groups or smart groups
- Implement custom filtering logic
- Cache API responses when possible
- Implement local model lookup cache
- Use conditional requests
Scenario: Small office with 50 computers
Configuration:
[rudder]
url = https://rudder.company.com
api_token = abc123...
[snipe-it]
url = https://assets.company.com
apikey = xyz789...
manufacturer_id = 1
defaultStatus = 2
computer_model_category_id = 1
[api-mapping]
name = hostname
_snipeit_ip_1 = properties ipHostNumber
_snipeit_os_2 = properties osNameExecution:
# Test first
python3 rudder2snipe --connection_test
python3 rudder2snipe --dryrun --verbose
# Live sync
python3 rudder2snipe --verboseScenario: Large organization with 1000+ assets
Configuration:
[rudder]
url = https://rudder.enterprise.com
api_token = enterprise_token...
[snipe-it]
url = https://snipe.enterprise.com
apikey = enterprise_key...
manufacturer_id = 2
defaultStatus = 4
computer_model_category_id = 3
[api-mapping]
name = hostname
_snipeit_ip_address_1 = properties ipHostNumber
_snipeit_os_name_2 = properties osName
_snipeit_os_version_3 = properties osVersion
_snipeit_cpu_model_4 = properties processorModel
_snipeit_ram_size_5 = properties memorySize
_snipeit_serial_6 = properties serialNumber
[user-mapping]
rudder_api_field = properties primaryUserExecution:
# Rate-limited sync with user assignment
python3 rudder2snipe --ratelimited --users --verboseCron Job:
# /etc/cron.d/rudder2snipe
0 2 * * * rudder /opt/rudder2snipe/.venv/bin/python /opt/rudder2snipe/rudder2snipe --ratelimited --users >> /var/log/rudder2snipe.log 2>&1Scenario: MSP managing multiple client environments
Directory Structure:
/opt/rudder2snipe/
├── clients/
│ ├── client1/
│ │ └── settings.conf
│ ├── client2/
│ │ └── settings.conf
│ └── client3/
│ └── settings.conf
└── scripts/
└── sync-all-clients.sh
Sync Script:
#!/bin/bash
# sync-all-clients.sh
for client in /opt/rudder2snipe/clients/*/; do
echo "Syncing $(basename $client)..."
cd "$client"
/opt/rudder2snipe/.venv/bin/python /opt/rudder2snipe/rudder2snipe --ratelimited --verbose
doneScenario: Development/testing setup
Configuration:
[rudder]
url = https://rudder-dev.lab.local
api_token = dev_token...
[snipe-it]
url = https://snipe-dev.lab.local
apikey = dev_key...
manufacturer_id = 1
defaultStatus = 1
computer_model_category_id = 1
[api-mapping]
name = hostname
_snipeit_environment_1 = properties environmentUsage:
# Always use dry run in development
python3 rudder2snipe --dryrun --debug
# Test specific features
python3 rudder2snipe --dryrun --users_force --debugWe welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
git clone https://github.com/YOUR-USERNAME/rudder2snipe.git
cd rudder2snipe
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt# Syntax check
python3 -m py_compile rudder2snipe
# Lint check
flake8 rudder2snipe
# Test run
python3 rudder2snipe --helpQ: How often should I run rudder2snipe?
A: Depends on your needs. Most organizations run it hourly or daily. Use --ratelimited for frequent runs.
Q: Can I run multiple instances simultaneously? A: Not recommended. API rate limits and database conflicts may occur.
Q: Does rudder2snipe delete assets? A: No, it only creates and updates assets. Manual cleanup may be needed for decommissioned nodes.
Q: What happens if Rudder and Snipe-IT have conflicting data?
A: rudder2snipe compares timestamps and updates the asset only if Rudder has newer data. Use --force to override.
Q: Can I map one Rudder field to multiple Snipe-IT fields? A: Not directly. You would need custom logic or multiple mapping entries.
Q: How do I handle custom asset tags?
A: Set asset_tag in the [snipe-it] section to map to a Rudder property, or use --auto_incrementing.
Q: Why aren't my custom fields updating? A: Check the DB field name in Snipe-IT Admin → Custom Fields. Ensure it matches your mapping exactly.
Q: I'm getting SSL errors, what should I do?
A: Try --do_not_verify_ssl temporarily, but properly configure SSL certificates for production.
Q: Assets are being created but not updated. Why?
A: Check timestamps. Use --force to override timestamp checking, or ensure Rudder inventory is up to date.
This project is based on the excellent jamf2snipe project by Brian Monroe and contributors.
- Brian Monroe and the jamf2snipe contributors for the original foundation
- Rudder.io team for the excellent configuration management platform
- Snipe-IT team for the robust asset management system
- Python community for the libraries that make this possible
MIT License - see LICENSE file for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Project Wiki
- Check this documentation first
- Search existing issues
- Create a detailed issue with:
- Environment details
- Configuration (sanitized)
- Error messages
- Steps to reproduce
Last updated: December 2024