# IT setup guide — Marcus-Law OutlookAddin Audience: IT admin. Walks you through deploying the ClickOnce installer, distributing the code-signing certificate via GPO, provisioning per-user EspoCRM API keys, and operating the add-in for the 10 attorneys at Marcus-Law. ## Prerequisites - Windows AD domain (`marcus-law.local`) with GPO push to all attorney machines. - EspoCRM admin access on `https://crm.prod.marcus-law.co.il`. - SSH access to `platform.dev.marcus-law.co.il` for serving the ClickOnce artifacts. - Mattermost webhook for release notifications (`#git-verelasim`). - Infisical project `outlook-addin` for storing secrets. ## 1. Build infrastructure ### Windows CI runner (one-time) A Windows 11 Pro VM on Coolify hosts the Gitea Actions runner. It needs: - **Visual Studio Build Tools 2022** with workloads: - `Microsoft.VisualStudio.Workload.Office` (for the VSTO MSBuild targets) - `Microsoft.VisualStudio.Workload.ManagedDesktop` (for WPF) - **Windows SDK 10.0.22621** (for `signtool.exe`). - **.NET Framework 4.8 Developer Pack** (`mage.exe`). - **WSL Ubuntu** (for the `rsync` step of the publish job). - **Gitea act_runner** registered as a Windows service with label `windows`. ### Code-signing certificate The runner needs a code-signing certificate in `Cert:\CurrentUser\My`. Generate a self-signed cert once: ```powershell $cert = New-SelfSignedCertificate ` -Subject "CN=Marcus-Law OutlookAddin" ` -Type CodeSigningCert ` -CertStoreLocation Cert:\CurrentUser\My ` -NotAfter (Get-Date).AddYears(3) ` -KeyAlgorithm RSA ` -KeyLength 2048 $thumbprint = $cert.Thumbprint $pfxPassword = ConvertTo-SecureString -String "" -Force -AsPlainText Export-PfxCertificate -Cert $cert -FilePath C:\codesign.pfx -Password $pfxPassword Export-Certificate -Cert $cert -FilePath C:\codesign.cer # public part — for GPO push ``` Store these in Infisical `/outlook-addin/`: | Key | Value | |---|---| | `CODESIGN_THUMBPRINT` | The cert thumbprint (40 hex chars) | | `CODESIGN_PFX_BASE64` | `[Convert]::ToBase64String([IO.File]::ReadAllBytes("C:\codesign.pfx"))` | | `CODESIGN_PASSWORD` | The PFX password | | `PLATFORM_DEV_SSH_KEY` | Base64 of the rsync target's ed25519 private key | | `MATTERMOST_WEBHOOK_RELEASES` | Incoming webhook URL for `#git-verelasim` | In Gitea (`Settings → Actions → Secrets`), add four secrets that reference Infisical: - `CODESIGN_THUMBPRINT` - `PLATFORM_DEV_SSH_KEY` - `MATTERMOST_WEBHOOK_RELEASES` (The PFX itself is imported once on the runner; the workflow only uses the thumbprint.) ## 2. Deploy the certificate via GPO The ClickOnce installer refuses to launch unless the publishing certificate is in **Trusted Publishers** on each attorney's machine. Use GPO to push it. 1. Copy `codesign.cer` to `\\marcus-law.local\SYSVOL\marcus-law.local\Scripts\certs\codesign.cer`. 2. Open **Group Policy Management Console** → edit a GPO scoped to the attorney OU. 3. Navigate to: `Computer Configuration → Policies → Windows Settings → Security Settings → Public Key Policies` 4. Right-click **Trusted Publishers → Import…** and pick `codesign.cer`. 5. Repeat under **Trusted Root Certification Authorities** (self-signed cert). 6. Force update everywhere: ```powershell Invoke-Command -ComputerName (Get-ADComputer -Filter * -SearchBase "OU=Attorneys,DC=marcus-law,DC=local").Name -ScriptBlock { gpupdate /force } ``` 7. Verify on one attorney machine: ```powershell certutil -store -user TrustedPublisher | findstr /C:"Marcus-Law OutlookAddin" ``` ## 3. nginx — serve the ClickOnce artifacts On `platform.dev.marcus-law.co.il`, add `/etc/nginx/sites-available/outlook-addin.conf`: ```nginx server { listen 443 ssl http2; server_name platform.dev.marcus-law.co.il; ssl_certificate /etc/letsencrypt/live/platform.dev.marcus-law.co.il/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/platform.dev.marcus-law.co.il/privkey.pem; location /outlook-addin/ { alias /var/www/outlook-addin/; autoindex off; types { application/x-ms-application application; application/x-ms-manifest manifest; application/octet-stream vsto; application/octet-stream deploy; } add_header Cache-Control "no-cache, must-revalidate"; } } ``` ```bash sudo mkdir -p /var/www/outlook-addin sudo chown -R www-data:www-data /var/www/outlook-addin sudo ln -s /etc/nginx/sites-available/outlook-addin.conf /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx ``` The CI runner pushes new versions here on every `v*` tag via the publish job. ## 4. EspoCRM API key provisioning Per attorney: 1. EspoCRM admin → **Administration → Users → Create**. 2. **User Type:** API User (or a Regular User with the "API" role). 3. **Username:** mail prefix (e.g. `chaim` for `chaim@marcus-law.co.il`). 4. **Role:** at least: read Contact / Case / Account / Lead / Email; create Email; read EmailAddress. 5. Save, then **Generate API Key**. Copy it. 6. Store under Infisical `/outlook-addin/users/` (or send via a 1-time link service). Send the attorney a personal email matching the ONBOARDING.md template, with their per-user key. ## 5. Release procedure (each new version) 1. Tag the commit on `main`: ```bash git tag v1.0.0 git push origin v1.0.0 ``` 2. Gitea Actions builds Release, signs, generates the ClickOnce artifacts, rsyncs to platform.dev, and posts to `#git-verelasim`. 3. Smoke-test from a clean attorney machine (or a Windows 11 sandbox): - Browse to `https://platform.dev.marcus-law.co.il/outlook-addin/OutlookAddin.vsto`. - The ClickOnce installer should run with **no security warning**. If you see "Unknown Publisher", the GPO cert hasn't propagated to that machine. - First-run Settings → enter creds → Test Connection green. - Send a test email to a known contact, hit "תייק ל-EspoCRM", confirm it appears in the EspoCRM activity stream. 4. If a release goes badly, push a new tag with a fix; ClickOnce will roll all users forward automatically on their next Outlook start. ## 6. URL protocol handler (optional) To make EspoCRM "Compose email" links open Outlook with the case pre-filled: 1. After the ClickOnce install, run as the user: ```powershell & "$env:LOCALAPPDATA\Apps\OutlookAddinProtocolHandler\install-protocol.ps1" ``` 2. Verify: `start outlookaddin://compose?caseId=` should open a new Outlook composer with the case pre-populated. (Outlook must be already running so the named pipe is up.) 3. To uninstall the registration: `uninstall-protocol.ps1`. ## 7. Monitoring - **CI status** — Mattermost `#git-verelasim`, plus Gitea Actions UI. - **Server-side filing** — EspoCRM internal logs (`data/logs/espo-*.log`) for `/api/v1/MailRouter/file` calls. - **Client-side errors** — when an attorney reports an issue, ask them to send `%LOCALAPPDATA%\MarcusLaw\OutlookAddin\logs\addin-.log`. Logs roll daily, retained 14 days. ## 8. Off-boarding (attorney leaves) 1. In EspoCRM admin, delete or disable the API User. 2. Their `creds.dat` on the laptop is DPAPI-encrypted with their Windows user profile — wiping the profile (or the laptop) is enough. 3. No central state to remove beyond EspoCRM. ## 9. Troubleshooting playbook | Symptom | Likely cause | Fix | |---|---|---| | Install dialog says "Unknown Publisher" | GPO cert hasn't reached the machine | `gpupdate /force`, then `certutil -store -user TrustedPublisher` to confirm | | Add-in installs but ribbon group is missing | `Microsoft.VSTORuntime.4.0` missing | ClickOnce normally pulls it; if Office < 2019, install [VSTO 4 Runtime](https://www.microsoft.com/download/details.aspx?id=48217) manually | | Mass 401s after a renewal | API keys were rotated | Send new keys, ask users to re-open Settings and paste them | | Retry queue is growing | EspoCRM unreachable, or 5xx errors | Check EspoCRM health; once it's back, the processor drains the queue on its 30-second loop | | User says "categories disappeared" | They are local to that PC. If they reinstall Outlook on a new machine, categories don't sync (MAPI limitation) | Re-file is harmless — server-side dedups on `messageId` (409 returned, counted as success) |