466 líneas
11 KiB
Markdown
466 líneas
11 KiB
Markdown
# Guía de Firma de Extensiones
|
|
|
|
Esta guía explica cómo firmar las extensiones de Classic Add-ons Archive para Firefox y Chrome.
|
|
|
|
## 🔐 ¿Por qué firmar?
|
|
|
|
- **Firefox**: Las extensiones firmadas pueden distribuirse fuera de AMO
|
|
- **Chrome**: La firma genera un ID consistente y permite actualizaciones
|
|
- **Seguridad**: Los usuarios pueden verificar la autenticidad
|
|
- **Profesional**: Distribución en stores oficiales
|
|
|
|
## 📋 Requisitos Previos
|
|
|
|
### Software necesario
|
|
|
|
```bash
|
|
# Instalar Node.js y npm (si no lo tienes)
|
|
sudo apt install nodejs npm # Debian/Ubuntu
|
|
# o
|
|
brew install node # macOS
|
|
|
|
# Instalar dependencias del proyecto (incluye web-ext)
|
|
npm install
|
|
|
|
# Para Chrome: openssl (generalmente ya instalado)
|
|
openssl version
|
|
```
|
|
|
|
**Nota**: web-ext se instala automáticamente como dependencia local, no necesitas instalarlo globalmente.
|
|
|
|
### Permisos de ejecución
|
|
|
|
```bash
|
|
chmod +x scripts/generate-keys.sh
|
|
chmod +x build.sh
|
|
```
|
|
|
|
## 🔑 Paso 1: Generar Claves
|
|
|
|
### Generación automática
|
|
|
|
```bash
|
|
cd /home/ale/projects/firefox/ca-archive
|
|
./scripts/generate-keys.sh
|
|
```
|
|
|
|
Este script genera:
|
|
- **Chrome**: Clave privada RSA 2048-bit (`private-keys/chrome-extension.pem`)
|
|
- **Chrome**: Extension ID calculado
|
|
- **Firefox**: Plantilla de credenciales AMO
|
|
|
|
### Generación manual (alternativa)
|
|
|
|
**Para Chrome:**
|
|
```bash
|
|
mkdir -p private-keys
|
|
openssl genrsa -out private-keys/chrome-extension.pem 2048
|
|
```
|
|
|
|
**Para Firefox:**
|
|
Crea `private-keys/firefox-amo-credentials.json`:
|
|
```json
|
|
{
|
|
"web-ext": {
|
|
"sign": {
|
|
"apiKey": "user:12345678:123",
|
|
"apiSecret": "tu-secret-aqui",
|
|
"id": "ca-archive@Off.JustOff",
|
|
"channel": "unlisted"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🦊 Paso 2: Configurar Credenciales de Firefox (AMO)
|
|
|
|
### Obtener credenciales AMO
|
|
|
|
1. **Inicia sesión** en https://addons.mozilla.org
|
|
|
|
2. **Ve a API Keys**: https://addons.mozilla.org/developers/addon/api/key/
|
|
|
|
3. **Genera credenciales**:
|
|
- Click en "Generate new credentials"
|
|
- Copia el **JWT issuer** (API Key)
|
|
- Copia el **JWT secret** (API Secret)
|
|
|
|
4. **Edita el archivo de credenciales**:
|
|
```bash
|
|
nano private-keys/firefox-amo-credentials.json
|
|
```
|
|
|
|
5. **Agrega tus credenciales**:
|
|
```json
|
|
{
|
|
"web-ext": {
|
|
"sign": {
|
|
"apiKey": "user:12345678:456",
|
|
"apiSecret": "1a2b3c4d5e6f7g8h9i0j...",
|
|
"channel": "unlisted"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Nota importante**: El ID de la extensión (`ca-archive@Off.JustOff`) se lee automáticamente de `manifest.json`, no es necesario incluirlo en las credenciales.
|
|
|
|
### Tipos de canal (channel)
|
|
|
|
- **`unlisted`**: No aparece en búsquedas de AMO, distribución externa
|
|
- **`listed`**: Aparece en AMO, revisión más estricta
|
|
|
|
**Recomendado**: Usar `unlisted` para desarrollo y `listed` para producción.
|
|
|
|
## 🏗️ Paso 3: Construir y Firmar
|
|
|
|
### Firmar ambas versiones
|
|
|
|
```bash
|
|
./build.sh --sign
|
|
```
|
|
|
|
Esto:
|
|
1. Construye paquetes ZIP sin firmar
|
|
2. Firma el paquete de Firefox con AMO
|
|
3. Firma el paquete de Chrome con tu clave privada
|
|
4. Genera archivos `.xpi` (Firefox) y `.crx` (Chrome)
|
|
|
|
### Firmar solo Firefox
|
|
|
|
```bash
|
|
./build.sh --sign-firefox
|
|
```
|
|
|
|
### Firmar solo Chrome
|
|
|
|
```bash
|
|
./build.sh --sign-chrome
|
|
```
|
|
|
|
### Usando npm scripts
|
|
|
|
```bash
|
|
# Generar claves
|
|
npm run keys:generate
|
|
|
|
# Construir sin firmar
|
|
npm run build
|
|
|
|
# Construir y firmar todo
|
|
npm run build:sign
|
|
|
|
# Firmar solo Firefox
|
|
npm run build:sign-firefox
|
|
|
|
# Firmar solo Chrome
|
|
npm run build:sign-chrome
|
|
```
|
|
|
|
## 📦 Archivos Generados
|
|
|
|
Después de la firma encontrarás en `dist/`:
|
|
|
|
### Firefox
|
|
- `ca-archive-3.0.0.xpi` - Paquete sin firmar
|
|
- `ca-archive-3.0.0-an+fx.xpi` - Paquete firmado por AMO
|
|
- `firefox-sign.log` - Log del proceso de firma
|
|
|
|
### Chrome
|
|
- `ca-archive-3.0.0-chrome.zip` - Paquete ZIP sin firmar
|
|
- `ca-archive-3.0.0-chrome.crx` - Paquete firmado
|
|
- `chrome-extension-id.txt` - ID de la extensión
|
|
- `ca-archive-3.0.0-chrome.crx.sha256` - Hash de verificación
|
|
|
|
## 🔍 Verificar Firma
|
|
|
|
### Firefox
|
|
|
|
```bash
|
|
# Verificar que es un ZIP válido
|
|
unzip -t dist/ca-archive-*.xpi
|
|
|
|
# Ver metadatos (requiere web-ext)
|
|
web-ext lint --source-dir=. --self-hosted
|
|
```
|
|
|
|
### Chrome
|
|
|
|
```bash
|
|
# Verificar hash SHA256
|
|
sha256sum -c dist/ca-archive-*-chrome.crx.sha256
|
|
|
|
# Ver Extension ID
|
|
cat dist/chrome-extension-id.txt
|
|
```
|
|
|
|
## 🚀 Distribución
|
|
|
|
### Firefox
|
|
|
|
**Opción 1: AMO (Recomendado para usuarios finales)**
|
|
|
|
1. Ve a: https://addons.mozilla.org/developers/
|
|
2. Click en "Submit a New Add-on"
|
|
3. Sube el archivo `.xpi` firmado
|
|
4. Completa información y submit para revisión
|
|
|
|
**Opción 2: Self-hosted (para desarrollo)**
|
|
|
|
1. Sube el `.xpi` firmado a tu servidor
|
|
2. Usuarios pueden instalarlo desde: `https://tu-servidor.com/ca-archive.xpi`
|
|
3. Firefox verificará la firma automáticamente
|
|
|
|
### Chrome
|
|
|
|
**Opción 1: Chrome Web Store (Recomendado)**
|
|
|
|
1. Ve a: https://chrome.google.com/webstore/devconsole
|
|
2. Click en "New Item"
|
|
3. Sube el archivo **`.zip`** (NO el .crx)
|
|
4. Completa información y publica
|
|
|
|
**Nota**: Chrome Web Store firma automáticamente, no subas el .crx.
|
|
|
|
**Opción 2: Enterprise distribution (.crx)**
|
|
|
|
1. Distribuye el archivo `.crx` firmado
|
|
2. Los usuarios deben agregarlo manualmente
|
|
3. Requiere políticas empresariales habilitadas
|
|
|
|
## 🔐 Seguridad de las Claves
|
|
|
|
### ⚠️ IMPORTANTE: Protege tus claves
|
|
|
|
```bash
|
|
# Permisos seguros
|
|
chmod 600 private-keys/chrome-extension.pem
|
|
chmod 600 private-keys/firefox-amo-credentials.json
|
|
chmod 700 private-keys/
|
|
|
|
# Verificar que están en .gitignore
|
|
git status private-keys/ # Debe decir "ignored"
|
|
```
|
|
|
|
### Backup de claves
|
|
|
|
```bash
|
|
# Hacer backup cifrado
|
|
tar czf ca-archive-keys-backup.tar.gz private-keys/
|
|
gpg -c ca-archive-keys-backup.tar.gz
|
|
rm ca-archive-keys-backup.tar.gz
|
|
|
|
# Guarda ca-archive-keys-backup.tar.gz.gpg en lugar seguro
|
|
```
|
|
|
|
### Restaurar backup
|
|
|
|
```bash
|
|
gpg -d ca-archive-keys-backup.tar.gz.gpg > ca-archive-keys-backup.tar.gz
|
|
tar xzf ca-archive-keys-backup.tar.gz
|
|
```
|
|
|
|
### ¿Qué hacer si pierdes las claves?
|
|
|
|
**Chrome:**
|
|
- El Extension ID cambiará
|
|
- Los usuarios verán una extensión "nueva"
|
|
- Perderás valoraciones/estadísticas
|
|
|
|
**Firefox:**
|
|
- Puedes generar nuevas credenciales AMO
|
|
- El ID de la extensión se mantiene (está en manifest.json)
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### Error: "Cannot set custom ID ... because manifest.json declares ID"
|
|
|
|
**Causa**: El archivo de credenciales incluye un campo `"id"` que ya está en manifest.json
|
|
|
|
**Solución**:
|
|
Edita `private-keys/firefox-amo-credentials.json` y elimina la línea con `"id"`:
|
|
```json
|
|
{
|
|
"web-ext": {
|
|
"sign": {
|
|
"apiKey": "user:12345678:123",
|
|
"apiSecret": "tu-secret-aqui",
|
|
"channel": "unlisted"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
El ID se lee automáticamente de `manifest.json`.
|
|
|
|
### Error: "Unknown JWT iss (issuer)" - Status 401
|
|
|
|
**Error completo:**
|
|
```
|
|
WebExtError: Received bad response from the server while requesting
|
|
https://addons.mozilla.org/api/v4/addons/...
|
|
status: 401
|
|
response: {"detail":"Unknown JWT iss (issuer)."}
|
|
```
|
|
|
|
**Causa**: Las credenciales AMO son inválidas o son credenciales de ejemplo/prueba.
|
|
|
|
**Soluciones**:
|
|
|
|
1. **Verificar que tienes credenciales reales de AMO:**
|
|
```bash
|
|
cat private-keys/firefox-amo-credentials.json
|
|
```
|
|
|
|
Si ves valores como:
|
|
- `"apiKey": "user:12345678:123"` ← ❌ Ejemplo, no funciona
|
|
- `"apiSecret": "1234567890abcdef..."` ← ❌ Ejemplo, no funciona
|
|
|
|
**Debes obtener credenciales reales:**
|
|
|
|
2. **Obtener credenciales reales de AMO:**
|
|
- Ve a: https://addons.mozilla.org/developers/addon/api/key/
|
|
- Inicia sesión con tu cuenta de Firefox
|
|
- Click en "Generate new credentials"
|
|
- Dale un nombre descriptivo (ej: "ca-archive signing")
|
|
- **Copia el JWT issuer** → Este es tu `apiKey`
|
|
- **Copia el JWT secret** → Este es tu `apiSecret`
|
|
|
|
3. **Actualizar archivo de credenciales:**
|
|
```json
|
|
{
|
|
"web-ext": {
|
|
"sign": {
|
|
"apiKey": "user:TU_USER_ID_REAL:TU_KEY_ID_REAL",
|
|
"apiSecret": "tu_secret_real_de_64_caracteres_hexadecimales_aqui",
|
|
"channel": "unlisted"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
4. **Volver a intentar:**
|
|
```bash
|
|
./build.sh --sign
|
|
```
|
|
|
|
**⚠️ Nota importante:**
|
|
- El archivo de ejemplo tiene credenciales de prueba que NO funcionan
|
|
- DEBES generar tus propias credenciales en AMO
|
|
- Las credenciales son secretas, no las compartas ni las subas a Git
|
|
- El archivo `private-keys/` está excluido de Git por seguridad
|
|
|
|
### Error: "API Key invalid"
|
|
|
|
**Causa**: Credenciales de AMO incorrectas o mal formateadas
|
|
|
|
**Solución**:
|
|
1. Verifica que copiaste correctamente API Key y Secret (sin espacios extra)
|
|
2. Verifica formato JSON válido: `python3 -m json.tool private-keys/firefox-amo-credentials.json`
|
|
3. Regenera credenciales en AMO si lleva mucho tiempo creadas
|
|
4. Verifica que tu cuenta AMO tenga permisos de API habilitados
|
|
|
|
### Error: "Private key not found"
|
|
|
|
**Causa**: No se generaron las claves
|
|
|
|
**Solución**:
|
|
```bash
|
|
./scripts/generate-keys.sh
|
|
```
|
|
|
|
### Error: "web-ext: command not found"
|
|
|
|
**Solución**:
|
|
```bash
|
|
# Instalar dependencias locales
|
|
npm install
|
|
|
|
# El script usará automáticamente web-ext desde node_modules
|
|
./build.sh --sign
|
|
```
|
|
|
|
**Alternativa (instalación global)**:
|
|
```bash
|
|
npm install -g web-ext
|
|
```
|
|
|
|
### Chrome: "Package is invalid: CRX_HEADER_INVALID"
|
|
|
|
**Causa**: Archivo .crx mal formado
|
|
|
|
**Solución**:
|
|
- Usa la versión .zip para Chrome Web Store
|
|
- Regenera el .crx con: `./build.sh --sign-chrome`
|
|
|
|
### Firefox: Validación falla
|
|
|
|
**Solución**:
|
|
```bash
|
|
# Validar primero sin firmar
|
|
npm run lint
|
|
|
|
# Corregir errores y luego firmar
|
|
./build.sh --sign-firefox
|
|
```
|
|
|
|
## 📊 Automatización (CI/CD)
|
|
|
|
### GitHub Actions (ejemplo)
|
|
|
|
```yaml
|
|
name: Build and Sign
|
|
on: [push]
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v2
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v2
|
|
with:
|
|
node-version: '16'
|
|
|
|
- name: Install dependencies
|
|
run: npm install -g web-ext
|
|
|
|
- name: Setup keys
|
|
run: |
|
|
mkdir -p private-keys
|
|
echo "${{ secrets.CHROME_KEY }}" > private-keys/chrome-extension.pem
|
|
echo "${{ secrets.FIREFOX_CREDS }}" > private-keys/firefox-amo-credentials.json
|
|
|
|
- name: Build and sign
|
|
run: ./build.sh --sign
|
|
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v2
|
|
with:
|
|
name: signed-packages
|
|
path: dist/
|
|
```
|
|
|
|
**Configura secrets en**: Repository Settings > Secrets and variables > Actions
|
|
|
|
## 📚 Recursos Adicionales
|
|
|
|
- [Firefox Extension Workshop](https://extensionworkshop.com/)
|
|
- [Chrome Extension Publishing](https://developer.chrome.com/docs/webstore/publish/)
|
|
- [web-ext Documentation](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/)
|
|
- [AMO Signing API](https://addons-server.readthedocs.io/en/latest/topics/api/signing.html)
|
|
|
|
## 🆘 Soporte
|
|
|
|
¿Problemas con la firma?
|
|
|
|
1. Revisa los logs en `dist/*-sign.log`
|
|
2. Verifica permisos: `ls -la private-keys/`
|
|
3. Prueba con: `npm run lint`
|
|
4. Abre un issue en GitHub
|
|
|
|
---
|
|
|
|
**Recuerda**: NUNCA compartas tus claves privadas ni las subas a repositorios públicos.
|