Skip to content

Commit 92e8b0a

Browse files
committed
feat: Implement GPG-encrypted PEM key workflow for Chrome CRX signing
- Add blog-link-analyzer.pem.gpg (encrypted private key) to repository - Update CI/CD workflow to decrypt GPG-encrypted PEM file using GitHub Secret - Install GPG in pipeline for key decryption - Add secure cleanup of decrypted key file after use - Update deployment script to use CRX files instead of ZIP for Chrome Web Store - Integrate Chrome Web Store API v2 with proper OAuth2 flow This enables secure Chrome extension signing with encrypted key storage while maintaining compliance with Chrome Web Store Verified CRX Uploads. Security improvements: - Encrypted PEM file stored in repository - Decryption key stored separately in GitHub Secrets - Secure cleanup of temporary decrypted key - Defense-in-depth security model
1 parent 7414471 commit 92e8b0a

File tree

3 files changed

+235
-74
lines changed

3 files changed

+235
-74
lines changed

.github/workflows/ci-cd.yml

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -175,21 +175,23 @@ jobs:
175175
run: |
176176
echo "🔍 Chrome Configuration Validation"
177177
echo "Extension ID configured: ${{ secrets.CHROME_EXTENSION_ID != '' }}"
178+
echo "Publisher ID configured: ${{ secrets.CHROME_PUBLISHER_ID != '' }}"
178179
echo "Client ID configured: ${{ secrets.CHROME_CLIENT_ID != '' }}"
179180
echo "Client Secret configured: ${{ secrets.CHROME_CLIENT_SECRET != '' }}"
180181
echo "Refresh Token configured: ${{ secrets.CHROME_REFRESH_TOKEN != '' }}"
181182
echo ""
182183
183184
# Validate all required secrets are configured
184185
if [[ -n "${{ secrets.CHROME_EXTENSION_ID }}" && \
186+
-n "${{ secrets.CHROME_PUBLISHER_ID }}" && \
185187
-n "${{ secrets.CHROME_CLIENT_ID }}" && \
186188
-n "${{ secrets.CHROME_CLIENT_SECRET }}" && \
187189
-n "${{ secrets.CHROME_REFRESH_TOKEN }}" ]]; then
188190
echo "✅ All Chrome secrets are configured"
189191
echo "🚀 Proceeding with Chrome Web Store deployment"
190192
else
191193
echo "❌ Missing Chrome secrets configuration"
192-
echo "Please check: CHROME_EXTENSION_ID, CHROME_CLIENT_ID, CHROME_CLIENT_SECRET, CHROME_REFRESH_TOKEN"
194+
echo "Please check: CHROME_EXTENSION_ID, CHROME_PUBLISHER_ID, CHROME_CLIENT_ID, CHROME_CLIENT_SECRET, CHROME_REFRESH_TOKEN"
193195
echo "Chrome deployment will be skipped"
194196
fi
195197
@@ -201,41 +203,61 @@ jobs:
201203
rm -f blog-link-analyzer-firefox-*.xpi
202204
echo "✅ Artifacts cleaned"
203205
206+
- name: Install GPG for Key Decryption
207+
run: |
208+
sudo apt-get update
209+
sudo apt-get install -y gnupg
210+
211+
- name: Decrypt CRX Private Key
212+
run: |
213+
echo "🔐 Decrypting CRX private key..."
214+
gpg --batch --yes --decrypt --quiet \
215+
--passphrase "${{ secrets.CHROME_CRX_GPG_PASSPHRASE }}" \
216+
--output blog-link-analyzer.pem blog-link-analyzer.pem.gpg
217+
218+
if [ -f "blog-link-analyzer.pem" ]; then
219+
echo "✅ CRX private key decrypted successfully"
220+
echo "CHROME_CRX_PRIVATE_KEY_PATH=blog-link-analyzer.pem" >> $GITHUB_ENV
221+
else
222+
echo "❌ Failed to decrypt CRX private key"
223+
exit 1
224+
fi
225+
204226
- name: Build Version-Specific Artifacts
205227
run: |
206228
VERSION=$(node -p 'require("./package.json").version')
207229
echo "VERSION=${VERSION}" >> $GITHUB_ENV
208230
209-
# Create ZIP package for Chrome Web Store deployment
210-
echo "🔧 Creating ZIP package for Chrome Web Store..."
211-
npm run build:zip
231+
# Create packages for Chrome Web Store deployment
232+
echo "🔧 Creating packages for Chrome Web Store..."
233+
npm run package:all-formats
212234
213235
# Copy existing artifacts with version numbers
214236
cp blog-link-analyzer.zip "blog-link-analyzer-${VERSION}.zip"
215237
cp blog-link-analyzer-firefox.xpi "blog-link-analyzer-firefox-${VERSION}.xpi"
216238
217-
# Verify ZIP file exists with version number
218-
if [ -f "blog-link-analyzer-${VERSION}.zip" ]; then
219-
echo "✅ ZIP file created and versioned"
220-
ls -la blog-link-analyzer-${VERSION}.zip
239+
# Verify CRX file exists with version number
240+
if [ -f "blog-link-analyzer-${VERSION}.crx" ]; then
241+
echo "✅ CRX file created and versioned"
242+
ls -la blog-link-analyzer-${VERSION}.crx
221243
else
222-
echo "❌ ZIP file not found - Chrome Web Store deployment will fail"
223-
echo "Available ZIP files:"
224-
find . -name "*.zip" -type f -exec ls -la {} \;
244+
echo "❌ CRX file not found - Chrome Web Store deployment will fail"
245+
echo "Available CRX files:"
246+
find . -name "*.crx" -type f -exec ls -la {} \;
225247
exit 1
226248
fi
227249
228250
echo "✅ Artifacts built with version ${VERSION}"
229251
echo "📋 Available artifacts:"
230-
ls -la blog-link-analyzer-${VERSION}.zip blog-link-analyzer-firefox-${VERSION}.xpi 2>/dev/null || echo "Some artifacts may be missing"
252+
ls -la blog-link-analyzer-${VERSION}.zip blog-link-analyzer-${VERSION}.crx blog-link-analyzer-firefox-${VERSION}.xpi 2>/dev/null || echo "Some artifacts may be missing"
231253
232-
# Ensure ZIP file exists for Chrome deployment
233-
if [ ! -f "blog-link-analyzer-${VERSION}.zip" ]; then
234-
echo "❌ Chrome ZIP file not found - deployment cannot continue"
254+
# Ensure CRX file exists for Chrome deployment
255+
if [ ! -f "blog-link-analyzer-${VERSION}.crx" ]; then
256+
echo "❌ Chrome CRX file not found - deployment cannot continue"
235257
exit 1
236258
fi
237259
238-
echo "✅ Chrome ZIP file ready for deployment"
260+
echo "✅ Chrome CRX file ready for deployment"
239261
240262
- name: Verify Deployment Files
241263
run: |
@@ -264,9 +286,11 @@ jobs:
264286
run: |
265287
VERSION=$(node -p 'require("./package.json").version')
266288
echo "CHROME_ZIP_PATH=blog-link-analyzer-${VERSION}.zip" >> $GITHUB_ENV
289+
echo "CHROME_CRX_PATH=blog-link-analyzer-${VERSION}.crx" >> $GITHUB_ENV
267290
echo "FIREFOX_XPI_PATH=blog-link-analyzer-firefox-${VERSION}.xpi" >> $GITHUB_ENV
268291
echo "Deployment paths set:"
269292
echo "Chrome ZIP: $CHROME_ZIP_PATH"
293+
echo "Chrome CRX: $CHROME_CRX_PATH"
270294
echo "Firefox: $FIREFOX_XPI_PATH"
271295
272296
- name: Authenticate to Google Cloud (Workload Identity Federation)
@@ -278,9 +302,10 @@ jobs:
278302
- name: Deploy to Chrome Web Store (OAuth2 - Primary)
279303
id: chrome-deploy
280304
run: |
281-
echo "🚀 Deploying to Chrome Web Store using OAuth2 (Primary Method)"
305+
echo "🚀 Deploying to Chrome Web Store using OAuth2 with CRX upload (Primary Method)"
282306
echo "📦 Extension ID: $CHROME_EXTENSION_ID"
283307
echo "📁 ZIP Path: $CHROME_ZIP_PATH"
308+
echo "📦 CRX will be generated from ZIP for upload"
284309
285310
# Install chrome-webstore-upload-cli for V2 API compatibility
286311
echo "📦 Installing chrome-webstore-upload-cli..."
@@ -304,6 +329,7 @@ jobs:
304329
fi
305330
env:
306331
CHROME_EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
332+
CHROME_PUBLISHER_ID: ${{ secrets.CHROME_PUBLISHER_ID }}
307333
CHROME_ZIP_PATH: ${{ env.CHROME_ZIP_PATH }}
308334
CHROME_CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }}
309335
CHROME_CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
@@ -344,14 +370,26 @@ jobs:
344370
jwt-secret: ${{ secrets.FIREFOX_JWT_SECRET }}
345371
continue-on-error: true
346372

373+
- name: Secure Cleanup of Decrypted Key
374+
if: always()
375+
run: |
376+
echo "🧹 Securely cleaning up decrypted CRX private key..."
377+
if [ -f "blog-link-analyzer.pem" ]; then
378+
# Securely shred the decrypted key file
379+
shred -u blog-link-analyzer.pem
380+
echo "✅ Decrypted key file securely removed"
381+
else
382+
echo "ℹ️ No decrypted key file found for cleanup"
383+
fi
384+
347385
- name: Notify deployment success
348386
if: success()
349387
run: |
350388
echo "🚀 Store Deployment Successful"
351389
if [ "${{ steps.chrome-deploy.outputs.CHROME_DEPLOY_SUCCESS }}" == "true" ]; then
352-
echo "✅ Chrome Web Store: ZIP file uploaded via OAuth2 (Primary)"
390+
echo "✅ Chrome Web Store: CRX file uploaded via OAuth2 (Primary)"
353391
elif [ "${{ steps.chrome-deploy-fallback.outcome }}" == "success" ]; then
354-
echo "✅ Chrome Web Store: ZIP file uploaded via Service Account (Fallback)"
392+
echo "✅ Chrome Web Store: CRX file uploaded via Service Account (Fallback)"
355393
else
356394
echo "⚠️ Chrome Web Store: Deployment may have failed - check logs"
357395
fi

blog-link-analyzer.pem.gpg

1.37 KB
Binary file not shown.

0 commit comments

Comments
 (0)