Security at CSP Continuity

Your cost data never leaves your tenant. We built the entire product around that sentence — and this page exists so your security team can verify it.

CSP Continuity is an Azure Managed Application published by Savoy Systems. It deploys from the Azure Marketplace into a resource group in your subscription, reads your cost and reservation data with read-only permissions, and stores every byte in resources you own. There is no Savoy-hosted service, no SaaS backend, no data pipeline to us. This page covers the architecture, the controls, the trade-offs we made deliberately, and the questions enterprise reviewers ask most.

Download the Security Posture Report

PDF, October 2026. Publisher-conducted assessment — not a third-party penetration test, and the report says so plainly.

At a glance

Deployment model Azure Managed Application — runs entirely in your tenant, in your subscription
Data location Your Azure SQL database, your storage account, your Application Insights — all in a resource group you can see
Data egress None of your cost data. The only recurring outbound business event is a marketplace billing meter carrying a subscription-count tier — no cost figures, no resource names
Permissions Read-only: Cost Management Reader + Reservations Reader. The app cannot modify, move, or delete anything in your environment
Authentication Your Microsoft Entra ID, enforced by App Service Authentication; fail-closed from the moment of deployment
Authorization Access restricted to users you explicitly assign in Entra ("Users and groups")
Encryption TLS 1.2 minimum everywhere in transit; platform encryption + SQL TDE at rest
Publisher access Savoy has no standing access to your data. The managed-resource-group deny assignment is enforced by Azure, not by us
Update integrity Every artifact is SHA-256 pinned in an unbroken chain from the marketplace template to the running code

Architecture: where it runs and what it touches

One deployment creates, inside a managed resource group in your subscription: a Linux Function App (Python), an Azure SQL database, a storage account, a Log Analytics workspace with Application Insights, and an Azure Monitor Workbook (the dashboard). A system-assigned managed identity is the application's only identity — there are no deployment-specific service accounts in our tenant, and nothing phones home.

The collection pipeline runs on a timer inside your tenant: it reads cost and reservation data from Microsoft's Cost Management APIs for the subscriptions you grant, computes amortization and discounts locally, writes results to your SQL database and storage account, and emits dashboard metrics to your own Application Insights resource. The dashboard is an Azure Monitor Workbook querying that Application Insights data — rendered by the Azure portal itself.

Every outbound connection, and what it carries

The application's network egress is limited to Microsoft first-party endpoints. In full:

Destination Purpose What is sent
management.azure.com Reading your cost/reservation data; daily self-check of the app's own deployment state Authenticated read requests. Data flows in, not out
graph.microsoft.com Displaying who has access to the app (its own assignment list) Read request for the app's own role assignments
Azure Monitor ingestion (*.monitor.azure.com / *.applicationinsights.azure.com) Dashboard metrics to your own Application Insights resource Aggregated daily totals and subscription health — transits Microsoft's ingestion front door, lands in your tenant
marketplaceapi.microsoft.com Marketplace metered billing A tier dimension and a quantity of 1, once per month. No cost figures, no subscription names, no resource data
*.blob.core.windows.net Downloading your own Microsoft-issued cost report files; reading the application package from your own storage account Your data, from Microsoft or your own tenant, inbound

That marketplace billing event is the single recurring fact that leaves your tenant, and it exists only so Azure can bill you on the plan you chose. The in-product pages load zero external resources — fonts are self-hosted, there are no CDN scripts, no trackers, no beacons.

Identity and access control

Sign-in is your Entra ID. Every dashboard, management page, and API requires authentication through your own Microsoft Entra tenant via App Service Authentication. The app registration is single-tenant: accounts outside your directory cannot sign in at all.

Fail-closed from minute zero. The deployment template ships with authentication configured to reject every request (HTTP 401) before onboarding ever runs. There is no window between deployment and configuration in which data is reachable anonymously. The only endpoints exempt from sign-in are a health probe, the onboarding status/instructions pages (which contain no data), and the Azure lifecycle webhook — each deliberately minimal.

Access is assignment-based. Authentication alone is not authorization: onboarding enables Entra's "assignment required" enforcement, so only users or groups you explicitly assign (Entra ID → Enterprise applications → CSP Continuity → Users and groups) can sign in — not every account in your directory. The administrator who runs onboarding is assigned automatically so there is no lockout; everyone else is added by your admins, on your terms. Unassigned users are rejected by Microsoft's sign-in page before ever reaching the application. Two facts your reviewers will want stated plainly: per Microsoft's documented behavior, Global Administrators bypass the assignment requirement, and removing a user takes effect at their next token issuance rather than instantly terminating a live session.

Defense in depth in code. Independently of platform authentication, application code re-verifies the authenticated principal on every endpoint, so data stays protected even if platform authentication were ever misconfigured out-of-band.

Read-only resource permissions. The managed identity holds exactly two Azure roles against your environment — Cost Management Reader and Reservations Reader — plus the platform-granted ability to read its own managed-app resource. You choose the scope at onboarding, as an explicit choice between management-group-wide or per-subscription. The identity cannot write to, modify, or delete anything in your environment. Its one write-capable permission is scoped to itself: it can update its own application's configuration, which powers zero-touch update self-healing (details under Updates).

What Savoy can and cannot do. Azure's managed-application deny assignment governs the managed resource group: it is enforced by the Azure platform, not by us, and it restricts the publisher's authorization to the narrow operations declared in the marketplace offer. Savoy has no standing credentials to your deployment, no remote access channel into it, and no copy of your data — there is nowhere for a copy to exist, because no pipeline to us exists. You retain full read visibility into every resource the app creates, including its audit logs.

Encryption

  • In transit: HTTPS-only on the application; TLS 1.2 minimum on the app, SCM endpoint, SQL server, and storage account; SQL connections use Encrypt=yes with certificate validation (TrustServerCertificate=no). These settings were verified on a live marketplace deployment, not just in the template.
  • At rest: Transparent Data Encryption on the SQL database; Azure Storage service-side encryption; configuration values stored as platform-encrypted application settings.
  • Storage is private: public blob access disabled on the account and on every container.

Secrets management

  • No secrets ship in the package. Every credential a deployment uses is generated inside your tenant at deploy or onboarding time: the database password you choose at install (never defaulted, never derived, never logged), platform-generated storage keys, and a randomly generated read-only reporting credential. No two installations share any secret.
  • Sign-in is secretless. App Service Authentication uses a managed-identity federated credential instead of a client secret — there is no authentication secret to store, rotate, or leak, and nothing that expires.
  • Secrets live as platform-encrypted application settings inside the managed resource group, protected by the deny assignment. We deliberately do not use Key Vault here: inside a marketplace managed application, the platform deny assignment blocks the role-based data-plane access Key Vault requires. Rather than punch holes in the deny assignment — the control that protects you from unauthorized changes, including by us — we rely on the platform's application-setting encryption and keep the deny assignment intact. (More in Design decisions, below.)
  • The reporting credential is read-only and per-deployment, scoped to the reporting views only, and is displayed only to authenticated administrators, with caching disabled on the response.

Network posture

  • Nothing listens on insecure channels. FTP/FTPS publishing disabled; basic-auth deployment credentials disabled on both publishing endpoints; the Kudu/SCM surface is dead to password auth.
  • The database is reachable for your BI tools — deliberately, and narrowly. Direct Power BI connectivity to your own cost database is a product feature, so the SQL endpoint accepts TLS-encrypted connections gated by server firewall rules. The in-app firewall helper lets an assigned administrator open individual /32 addresses only — single IPs, never ranges, never rules it didn't create. Database authentication events and queries are audited to storage in your tenant with 90-day retention.
  • The application has no CORS surface — no cross-origin access is configured anywhere, which closes the common web attack-amplification path for cookie-authenticated apps.

Supply-chain and update integrity

Every artifact you run is covered by an unbroken SHA-256 chain, anchored in the marketplace template that Microsoft certified:

  1. The deployment template carries the SHA-256 of the onboarding script, and scripts are published only at versioned URLs — a published script can never silently change out from under its hash. Every surface that shows you the download command also shows the one-line Get-FileHash verification against the template-pinned value.
  2. The onboarding script carries the SHA-256 of the application package and refuses to install a package that does not match — verification is fail-closed, not advisory.
  3. The running application re-verifies the same pin before it will relocate or update its own package.

Updates are yours to apply. Publisher updates arrive through the Azure Marketplace as versioned offers — we cannot push code into your tenant. When you apply an update, the application's self-healing re-establishes its configuration and re-verifies the package pin without manual steps. The application package is hosted in your own storage account, so day-to-day operation never depends on publisher infrastructure: if cspcontinuity.com vanished tomorrow, your deployment would keep running and keep collecting.

Dependencies are pinned and bundled into the deployment package — no install-time fetches at runtime — and are security-audited against known-vulnerability databases as part of the release process. The in-tenant package carries no secrets and no customer data.

Application security

  • Parameterized database access throughout. No SQL is built from user input; dynamic identifiers come only from fixed allowlists. This claim has been adversarially verified — by static analysis and by manual review of every query path.
  • Strict input allowlisting on every configuration write: the API cannot be used to modify deployment state, billing state, or credentials, because those keys are simply not writable through it.
  • Output encoding on every page; database-sourced values (resource names, tags) are treated as untrusted and escaped in all display contexts.
  • Generic errors by design. Error responses carry a correlation ID and a generic message; stack traces, driver errors, and connection details never reach a client. Diagnostic detail stays in your tenant's logs — and those logs are themselves kept free of secrets (no connection strings, tokens, or passwords are ever logged).
  • Outbound destination allowlisting: application credentials are only ever presented to Microsoft endpoints; export destinations are validated against Azure Storage domains (public, Government, and China clouds) before any connection is attempted.

Logging, monitoring, and audit

  • Structured logging with correlation IDs across the entire collection pipeline — every pipeline run is traceable end-to-end in your own Application Insights (90-day retention, in your resource group).
  • SQL auditing enabled to your storage account, 90-day retention: authentication events and queries.
  • The managed application's activity is visible in your Azure Activity Log like any other resource; you can route any of it to your SIEM — it's your workspace.
  • A coarse health/billing status endpoint lets your operations team verify the deployment is collecting and reporting correctly; failures surface loudly in the app and workbook rather than silently.

Lifecycle: suspend, cancel, uninstall

  • Suspend/cancel: collection stops when the managed application is suspended or cancelled; already-collected data remains in your tenant under your control, and read access to it stays available.
  • Uninstall: deleting the managed application deletes the managed resource group — database, storage, telemetry, and every byte of collected data are destroyed with it. Nothing persists on our side because nothing ever existed on our side. Export anything you want to keep before deleting — the Power BI connection or a storage export makes this a five-minute task.
  • Complete offboarding: onboarding created two artifacts outside the managed resource group — the Entra app registration used for sign-in, and the read-only role assignments. The uninstall documentation walks through removing both; an automated offboarding script is first on our published hardening backlog.

Design decisions we want you to see

Enterprise reviewers find these faster than any scanner — so here they are, with the reasoning. Each is a deliberate trade-off inside the managed-application model, documented rather than discovered.

  1. Key-based auth is used inside your tenant where the deny assignment blocks role-based auth. The marketplace deny assignment — the control that prevents anyone, including us, from tampering with the deployment — also blocks Azure RBAC data-plane access within the managed resource group. The app therefore uses platform-generated keys (storage, telemetry ingestion) within your tenant boundary, stored as platform-encrypted application settings. We chose an intact deny assignment plus key-based auth over a weakened deny assignment plus RBAC. The keys never leave your tenant.
  2. No Key Vault, for the same reason (deny assignment blocks its data plane). Application settings are platform-encrypted at rest and readable only by identities that can already administer the app.
  3. The SQL endpoint is network-reachable so your analysts can connect Power BI Desktop directly to your own data — access is gated by TLS 1.2, a customer-chosen strong password, firewall rules, and full auditing. A private-endpoint-only design would remove the product's self-service BI value; we chose auditability and narrow firewall self-service instead.
  4. A long-lived read-only access signature keeps the application package mounted from your own storage across Azure's routine platform maintenance, so your deployment never depends on publisher uptime. It is read-only, scoped to the package blob, and the package contains only the already-published application code.
  5. The dashboard's telemetry ingestion accepts key-based writes (again: deny assignment). The key only permits writing metrics into your own Application Insights resource — worst case is dashboard graffiti in your own tenant, with no read or confidentiality impact.

Development practices

  • Changes ship with a test suite of 1,100+ automated tests; releases follow a one-change-per-release discipline with post-deploy verification.
  • Secret scanning is enforced on the repository; dependency and template security scanning run as release gates.
  • A full security assessment (architecture, permissions, complete code review, secrets/dependency/static/infrastructure scanning, plus a live-deployment audit) was completed in October 2026 using an enterprise security team's methodology; the three High findings and highest-impact Mediums were remediated and released before publication. It states plainly that it is publisher-conducted, not a third-party engagement.
  • Development is a single-maintainer model — stated rather than disguised. The compensating controls are the ones above: the test gate, secret scanning, the artifact hash chain, and marketplace-mediated releases that customers apply on their own schedule.
Download the Technical Security Assessment (PDF)

Enterprise security FAQ

Does any of our cost data leave our tenant?
No. All collection, processing, storage, and dashboarding happens in resources inside your subscription. The only recurring outbound business event is the Azure Marketplace billing meter: a tier dimension and a quantity, once per month, so Azure can bill your chosen plan. It contains no cost figures, no subscription names, and no resource information. This is verifiable in your tenant: network egress from the app goes only to the Microsoft endpoints listed above.
Can Savoy Systems access our data or our environment?
No standing access exists. There is no Savoy backend connected to your deployment, no support tunnel, and no credential in our possession for your tenant. The managed-application deny assignment (enforced by Azure) restricts even the publisher authorization to the operations declared in the certified offer. If you ever grant us support access, it is through your own Entra controls, on your terms, revocable by you.
What permissions does it need, and why?
Two read-only roles: Cost Management Reader (to read cost data) and Reservations Reader (to read reservation inventory for amortization). You choose the scope during onboarding. The app's identity cannot create, modify, or delete resources in your environment. The one write permission it holds is on itself — its own app configuration — to support zero-touch updates.
Who in our company can see the cost data?
Only users or groups your administrators assign to the application in Entra ID (Enterprise applications → Users and groups). Sign-in is your Entra ID with your conditional-access and MFA policies applied; unassigned users are rejected at Microsoft's sign-in page. Note Microsoft's documented behavior: Global Administrators bypass assignment restrictions.
Does it support SSO and MFA?
It is SSO: sign-in goes through your Entra ID, so your MFA, conditional access, device compliance, and sign-in risk policies all apply automatically. There are no local accounts.
Where are credentials stored? Why not Key Vault?
All credentials are generated in your tenant at deploy/onboarding time and stored as platform-encrypted application settings inside the deny-assignment-protected resource group. Key Vault's data plane is blocked by that same deny assignment; we kept the deny assignment intact rather than weaken it. Sign-in itself is secretless (managed-identity federated credential) — there is no auth secret to rotate.
How do we know the software we're running is what you published?
Chain of pinned SHA-256 hashes: the Microsoft-certified template pins the onboarding script's hash; the script pins the application package's hash and refuses a mismatch; the running app re-verifies the same pin on every self-update. Scripts live at versioned URLs so a hash can never drift from its file. The verification command appears alongside every download instruction.
How are updates delivered? Can the publisher push code to us?
No. Updates ship as new versions of the marketplace offer; you (or your update policy) apply them. On update, the app self-heals its configuration and re-verifies the package hash. Day-to-day operation runs from a package in your own storage account and does not depend on publisher infrastructure being reachable.
What happens when we uninstall?
Deleting the managed application deletes the managed resource group and all data in it — there is no publisher-side copy to chase. Export what you want to keep first. Two onboarding artifacts live outside that group (the Entra sign-in app registration and the read-only role assignments); the uninstall documentation walks through removing both, and an automated offboarding script is first on our published hardening backlog.
What data retention applies while it's running?
Cost data: retained in your SQL database under a retention setting you control from the admin page; up to 13 months of history is collected on first run. Telemetry: 90 days in your Application Insights. SQL audit logs: 90 days in your storage. All of it is yours to extend, export, or delete.
Is the database exposed to the internet?
The SQL endpoint accepts TLS-only connections, gated by firewall rules, because direct Power BI connectivity to your own data is a product feature. Access requires the customer-chosen admin password or the per-deployment read-only reporting credential; every authentication event and query is audited to your tenant. The in-app firewall helper only opens single /32 addresses and can't touch rules it didn't create. If your policy requires it, you can tighten the firewall rules in your own tenant — they're your resources.
Will this trip Microsoft Defender for Cloud recommendations in our tenant?
Possibly a handful, and we'd rather tell you which ones than have you find them: SQL "enable Entra-only authentication" and "private endpoint" recommendations (see the database answer above), and storage shared-key recommendations (see Design decisions #1). Each is a documented trade-off of the managed-application deny-assignment model, not an oversight. Defender for SQL / threat-detection plans are a licensing choice we leave to you — they work normally on the deployed resources if you enable them.
Who is Savoy Systems? Why should we trust a small vendor?
CSP Continuity is built and operated by a one-person company, and we think the right response to that fact is architecture and transparency rather than paperwork. The product keeps every byte of your data in your tenant; it runs with no dependency on our infrastructure; updates ship only through the Azure Marketplace, applied when you choose; and we publish our own security testing so your review starts from evidence. We don't have a security operations center or a compliance team, and we won't invent answers that imply we do.
Do you have SOC 2 / ISO 27001?
No, and we don't claim otherwise. Two things stand in for it: the architecture removes most of the vendor-risk surface a SOC 2 report exists to cover (we never hold, process, or transmit your data — there is no vendor side), and our control posture is published transparently on this page and in the downloadable Technical Security Assessment rather than summarized in a questionnaire.
Has it been penetration tested?
Not by a third-party firm yet. What exists — and is published in full summary as the Technical Security Assessment — is a publisher-conducted assessment using an enterprise security team's methodology: complete source review, secrets scanning across the entire repository history with live credential verification, dependency and static analysis, infrastructure-as-code scanning, and a read-only audit of a production marketplace installation. It found 0 critical / 3 high findings; the Highs and the highest-impact Mediums were fixed and released before the report was published, and the remaining backlog is listed in the report itself. We say plainly in the document that this is not a third-party penetration test; we'd rather show you real testing than imply an engagement that didn't happen.
What is your incident response process? How would we be notified of a security issue affecting the product?
Honestly: there is no formal enterprise IR program — there is one person who wrote every line of the code and reads every security report. The architecture bounds what an incident can mean: we hold no customer data and have no access to your deployment, so a publisher-side incident cannot touch your tenant. A product vulnerability means "a fixed version needs to ship" — it would be released through the marketplace with an advisory on this page and to customer contacts. Security reports: email support@savoysystems.ai.
What about business continuity — what if Savoy disappears?
The architecture is the answer: your deployment runs from your tenant, from a package in your storage, with no runtime dependency on Savoy. Collection, dashboards, and your data continue working indefinitely; what stops arriving is updates. There is no formal escrow arrangement today; the honest mitigation is that the product already behaves the way escrow outcomes are supposed to — it keeps running without us.
Does the product use AI / send data to AI services?
No. There are no AI components and no data flows to any AI service.
Which clouds are supported?
Azure public cloud (the marketplace offer's target). The export-destination validation additionally recognizes Azure Government and Azure China storage domains, but those clouds are not currently supported deployment targets for the offer itself.

Last reviewed: October 2026, against a full security review of the shipping architecture and a live marketplace deployment.