10 KiB
10 KiB
Kiwy-Signage Self-Signed Certificate Support - Code Patches
This file contains exact code patches ready to apply to enable self-signed certificate support.
PATCH 1: Create ssl_config.py
File: Kiwy-Signage/src/ssl_config.py (NEW FILE)
"""
SSL Configuration Module for Kiwy-Signage
Handles certificate verification for self-signed and custom CA certificates
"""
import os
import logging
logger = logging.getLogger(__name__)
class SSLConfig:
"""Manage SSL certificate verification settings"""
# Default to True (use system CA certificates)
_custom_ca_path = None
_verify_ssl = True
@classmethod
def get_ca_bundle(cls):
"""Get path to CA certificate bundle for verification
Priority order:
1. Custom CA bundle path specified via set_ca_bundle()
2. CA bundle path from REQUESTS_CA_BUNDLE environment variable
3. CA bundle in config/ca_bundle.crt
4. System default CA bundle (True = use system certs)
Returns:
str or bool: Path to CA bundle file or True for system default
"""
# Check if custom CA was explicitly set
if cls._custom_ca_path:
if os.path.exists(cls._custom_ca_path):
logger.info(f"Using custom CA bundle: {cls._custom_ca_path}")
return cls._custom_ca_path
else:
logger.warning(f"Custom CA bundle not found: {cls._custom_ca_path}, falling back to system")
# Check environment variable
env_ca = os.environ.get('REQUESTS_CA_BUNDLE')
if env_ca and os.path.exists(env_ca):
logger.info(f"Using CA bundle from REQUESTS_CA_BUNDLE: {env_ca}")
return env_ca
# Check config directory
config_ca = 'config/ca_bundle.crt'
if os.path.exists(config_ca):
logger.info(f"Using CA bundle from config: {config_ca}")
return config_ca
# Use system default
logger.debug("Using system default CA certificates")
return True
@classmethod
def get_verify_setting(cls):
"""Get the 'verify' parameter for requests calls
Returns:
bool or str: Value to pass as 'verify=' parameter to requests
"""
if not cls._verify_ssl:
logger.warning("SSL verification is DISABLED - this is insecure!")
return False
return cls.get_ca_bundle()
@classmethod
def set_ca_bundle(cls, ca_path):
"""Manually set custom CA bundle path
Args:
ca_path (str): Path to CA certificate file
"""
if os.path.exists(ca_path):
cls._custom_ca_path = ca_path
logger.info(f"CA bundle set to: {ca_path}")
else:
logger.error(f"CA bundle file not found: {ca_path}")
@classmethod
def disable_verification(cls):
"""DANGER: Disable SSL certificate verification
⚠️ WARNING: Only use for development/testing!
This makes the application vulnerable to MITM attacks.
"""
cls._verify_ssl = False
logger.critical("⚠️ SSL VERIFICATION DISABLED - This is insecure!")
@classmethod
def enable_verification(cls):
"""Enable SSL certificate verification (default)"""
cls._verify_ssl = True
logger.info("SSL verification enabled")
@classmethod
def is_verification_enabled(cls):
"""Check if SSL verification is enabled
Returns:
bool: True if verification is enabled, False if disabled
"""
return cls._verify_ssl
PATCH 2: Modify src/player_auth.py
Location: Kiwy-Signage/src/player_auth.py
Change 2a: Add import at top of file
# AFTER line 10 (after existing imports), ADD:
from ssl_config import SSLConfig
Change 2b: Modify init method (lines 20-30)
BEFORE:
def __init__(self, config_file: str = 'player_auth.json'):
"""Initialize player authentication.
Args:
config_file: Path to authentication config file
"""
self.config_file = config_file
self.auth_data = self._load_auth_data()
AFTER:
def __init__(self, config_file: str = 'player_auth.json'):
"""Initialize player authentication.
Args:
config_file: Path to authentication config file
"""
self.config_file = config_file
self.auth_data = self._load_auth_data()
self.verify_ssl = SSLConfig.get_verify_setting()
Change 2c: Modify authenticate() method (line 95)
BEFORE:
response = requests.post(auth_url, json=payload, timeout=timeout)
AFTER:
response = requests.post(auth_url, json=payload, timeout=timeout, verify=self.verify_ssl)
Change 2d: Modify verify_auth() method (line 157)
BEFORE:
response = requests.post(verify_url, json=payload, timeout=timeout)
AFTER:
response = requests.post(verify_url, json=payload, timeout=timeout, verify=self.verify_ssl)
Change 2e: Modify get_playlist() method (line 178)
BEFORE:
response = requests.get(playlist_url, headers=headers, timeout=timeout)
AFTER:
response = requests.get(playlist_url, headers=headers, timeout=timeout, verify=self.verify_ssl)
Change 2f: Modify send_heartbeat() method (line 227-228)
BEFORE:
response = requests.post(heartbeat_url, headers=headers,
json=payload, timeout=timeout)
AFTER:
response = requests.post(heartbeat_url, headers=headers,
json=payload, timeout=timeout, verify=self.verify_ssl)
Change 2g: Modify send_feedback() method (line 254-255)
BEFORE:
response = requests.post(feedback_url, headers=headers,
json=payload, timeout=timeout)
AFTER:
response = requests.post(feedback_url, headers=headers,
json=payload, timeout=timeout, verify=self.verify_ssl)
PATCH 3: Modify src/get_playlists_v2.py
Location: Kiwy-Signage/src/get_playlists_v2.py
Change 3a: Add import (after line 6)
# AFTER line 6 (after "from player_auth import PlayerAuth"), ADD:
from ssl_config import SSLConfig
Change 3b: Modify download_media_files() function (line 159)
BEFORE:
response = requests.get(file_url, timeout=30)
AFTER:
verify_ssl = SSLConfig.get_verify_setting()
response = requests.get(file_url, timeout=30, verify=verify_ssl)
PATCH 4: Extract Server Certificate
Steps to follow on the DigiServer:
#!/bin/bash
# Run this on the DigiServer with self-signed certificate
# Export the certificate
openssl s_client -connect localhost:443 -showcerts < /dev/null | \
openssl x509 -outform PEM > /tmp/server_cert.crt
# Copy to player configuration directory
# (transfer via SSH, USB, or other secure method)
cp /tmp/server_cert.crt /path/to/Kiwy-Signage/config/ca_bundle.crt
# Verify it was copied correctly
ls -la /path/to/Kiwy-Signage/config/ca_bundle.crt
PATCH 5: Alternative - Use Environment Variable
Instead of placing cert in config directory, you can use environment variable:
#!/bin/bash
# Before running the player:
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/custom-ca.crt
cd /path/to/Kiwy-Signage
./start.sh
Testing After Patches
Test 1: Verify patches applied correctly
cd /tmp/Kiwy-Signage/src
# Check imports added
grep "from ssl_config import SSLConfig" player_auth.py
grep "from ssl_config import SSLConfig" get_playlists_v2.py
# Check verify parameter added
grep "verify=self.verify_ssl" player_auth.py | wc -l
# Should output: 5
# Check new file exists
test -f ssl_config.py && echo "ssl_config.py exists" || echo "MISSING"
Test 2: Test with self-signed server
cd /tmp/Kiwy-Signage
# 1. Export server cert (run on server)
openssl s_client -connect server.local:443 -showcerts < /dev/null | \
openssl x509 -outform PEM > config/ca_bundle.crt
# 2. Test player connection
python3 -c "
import sys
sys.path.insert(0, 'src')
from player_auth import PlayerAuth
from ssl_config import SSLConfig
# Check what certificate will be used
cert_path = SSLConfig.get_ca_bundle()
print(f'Using certificate: {cert_path}')
# Try authentication
auth = PlayerAuth()
success, error = auth.authenticate(
server_url='https://server.local:443',
hostname='test-player',
quickconnect_code='TEST123'
)
print(f'Connection result: {\"SUCCESS\" if success else \"FAILED\"}')
if error:
print(f'Error: {error}')
"
Test 3: Verify backward compatibility
cd /tmp/Kiwy-Signage
# Test connection to production server (valid CA cert)
python3 -c "
import sys
sys.path.insert(0, 'src')
from player_auth import PlayerAuth
auth = PlayerAuth()
success, error = auth.authenticate(
server_url='https://digi-signage.moto-adv.com',
hostname='test-player',
quickconnect_code='TEST123'
)
print(f'Production server: {\"OK\" if success else \"FAILED\"}')
"
Summary of Changes
| File | Type | Changes | Complexity |
|---|---|---|---|
src/ssl_config.py |
NEW | Full file (~60 lines) | Low |
src/player_auth.py |
MODIFY | 7 small changes | Low |
src/get_playlists_v2.py |
MODIFY | 2 small changes | Low |
config/ca_bundle.crt |
NEW | Certificate file | N/A |
Total lines of code modified: ~8 lines
New code added: ~60 lines
Breaking changes: None
Backward compatible: Yes
Rollback Instructions
If you need to revert the changes:
cd /tmp/Kiwy-Signage
# Restore original files from git
git checkout src/player_auth.py
git checkout src/get_playlists_v2.py
# Remove new file
rm src/ssl_config.py
# Remove certificate file (optional)
rm config/ca_bundle.crt
Implementation Checklist
- Read the full analysis (KIWY_PLAYER_HTTPS_ANALYSIS.md)
- Review this patch file
- Create
src/ssl_config.py(PATCH 1) - Apply changes to
src/player_auth.py(PATCH 2) - Apply changes to
src/get_playlists_v2.py(PATCH 3) - Export server certificate (PATCH 4)
- Place certificate in
config/ca_bundle.crt - Run Test 1: Verify patches applied
- Run Test 2: Test with self-signed server
- Run Test 3: Test with production server
- Update player documentation
- Deploy to test player
- Monitor player logs for SSL errors