Shared Services: Gateway, Registry, Packages, API Management, Build Agents¶
A platform often offers shared services next to your spoke. Which ones exist depends on your platform. This page describes what they do and how teams use them. Ask your platform team which are available. The platform team's side (what is deployed and how) is on Shared services: what is deployed and how. Who the platform team is depends on your operating model.
| Service | What it does | MCP product support |
|---|---|---|
| Application Gateway + WAF | Publishes your web app from the internet, with TLS termination and web application firewall | Hub component. Rules are standard changes: Application Gateway |
| Shared Azure Container Registry | Central registry with pull-through cache for public registries | extensions.acr in the spoke JSON (shared service in mcp.json), see Spoke extensions |
| Shared API Management | Publish APIs, products and subscriptions centrally | extensions.apim in the spoke JSON, see Spoke extensions. See also API Management (shared). |
| Service Bus / Event Hub | Shared messaging | extensions.servicebus / extensions.eventhub, see Spoke extensions, Messaging and Known issues |
| Communication Services | Send e-mail (and other communication) from your application | Access through a group that the platform team manages. No spoke extension yet. See Communication Services. |
| Package feeds (Azure DevOps Artifacts) | Private and cached NuGet, npm, Maven, Python packages | Azure DevOps feature. Not part of the platform code. |
| Build agents | Pipeline agents inside the network, to reach private resources | Platform-specific. Not part of the MCP product. See Build agents. Platform team: Container agent pool. |
| Dependency updates (Renovate) | Pull requests for outdated dependencies | Platform-specific |
Spoke extensions: connect to a shared service¶
A spoke extension connects your spoke to a shared service when the spoke is deployed. The deployment gives your groups the right access and configures the shared service for you, so you can use it directly after the delivery of the spoke. You don't wait for a separate change.
Extensions exist for these shared services (if your platform runs them):
Extension (extensions.<name> in the spoke JSON) |
What you get | Your access |
|---|---|---|
apim |
Access to the shared API Management. In the central model on the whole instance, in the decentral model on your own workspace. | Owners and Contributors can change APIs. Readers can read. |
acr |
Access to the shared container registry through two groups and two managed identities of your spoke, one to pull and one to push images. | Your team groups get no registry access from the extension. Use the managed identities in your pipelines and ask the platform team to add other identities. You can't delete images. |
eventhub |
Your own event hub in the shared namespace. | Owners get data and management rights, Contributors can contribute, Readers can read. |
servicebus |
Access to the shared Service Bus namespace. | Owners and Contributors can send and receive. Readers can read the namespace. |
| Communication Services | Currently unavailable. |
The exact roles are in Spoke extensions.
How to get one. Ask your platform team (How to change) to set enabled to true for the extension in your
spoke file (Spoke JSON). It takes effect at the next spoke deployment. Tell the
platform team which service you need, in which environments, and who in your team will use it.
Not every extension is available on every platform
The extensions need the shared service and its settings in the platform configuration. Ask your platform team which ones exist and in which regions. Some extension fields cannot be set yet (Known issues).
How you reach a shared service¶
In the reference design the shared services are secured the same way:
- No public access. Services are reached through a private endpoint in the shared services spoke. Your traffic goes through the hub firewall. If a connection is blocked, request a firewall rule.
- No keys. Local authentication (shared keys, SAS) is switched off on Service Bus and Event Hubs, and the registry has its admin user off. You sign in with Microsoft Entra ID, with a managed identity for applications and pipelines.
- Access through groups. Roles are given to Entra ID groups (and, for the registry, managed identities). To get access, ask for membership of the right group, or use a spoke extension.
- Private DNS. Use the service's normal host name. It must resolve to the private address from your spoke.
These are properties of the reference design. Ask your platform team what applies on your platform.
Publish a web app (Application Gateway)¶
Prerequisites: the security officer approved the exposure, and your application meets your security standards.
Request with:
- application name and environment,
- backend address (IP or FQDN) and service port,
- the external URL (for example
myapp.example.com) and the listener protocol, - the TLS certificate (for HTTPS) or custom-domain needs,
- a health probe (path, protocol, interval),
- a security contact.
Notes:
- HTTPS is the default. An HTTP listener normally redirects to HTTPS.
- Several apps can sit behind one URL with path-based routing.
- Priority of routing rules is unique per gateway. A lower number is evaluated first.
- Your platform may offer self-service: you edit a JSON file for your app in the gateway definitions folder and open a pull request, which the platform team reviews and deploys. Ask whether this applies.
- To investigate blocked requests, see Application Gateway logs.
A legitimate request is blocked by the WAF. The WAF blocks requests that match its managed rules (for example the OWASP rule set), even when your application is fine. Ask for an exception or exclusion, and bring the evidence:
| Give | Where to find it |
|---|---|
| The rule ID and the rule group | The firewall log entry (Application Gateway logs) |
| The URI, and the argument or header that triggers the rule | The same log entry or your own request |
| Why the request is legitimate | Your application team |
| How narrow the exception can be: one header value, one client address, one URI | Your application team |
Security approves the exception. The platform team adds the narrowest possible rule and keeps a list of all exceptions. There are limits on the number and on the kind of values (for example only single IPv4 addresses for an address match), which the platform team checks (WAF exceptions). A disabled rule or a broad exception is normally refused.
Containers: shared Azure Container Registry¶
A shared registry in the hub can cache public registries (Microsoft Container Registry, Docker Hub, Quay), so builds are faster, cheaper and independent of the internet.
| Original image | Through the shared registry |
|---|---|
mcr.microsoft.com/dotnet/aspnet:8.0 |
<registry>.azurecr.io/mcr/dotnet/aspnet:8.0 |
docker.io/library/nginx:latest |
<registry>.azurecr.io/dockerhub/library/nginx:latest |
quay.io/coreos/etcd:latest |
<registry>.azurecr.io/quay/coreos/etcd:latest |
The registry name, the cache rules and the roles are platform-specific, and a registry only offers the cache paths above when the platform team has configured the cache rules. Typical set-up:
-
In the reference design the registry is Premium, reachable only through a private endpoint, with the admin user and anonymous pull switched off, and encrypted with a customer-managed key.
-
With the
acrextension, access runs through groups:AcrPullandAcrPushare assigned once to the main groups of the registry, and your spoke gets a sub-group of each, with a managed identity per sub-group. Members that the platform team adds to the sub-groups are kept. How your own identities (App Service, AKS, Container Apps) getAcrPullis platform-specific. Ask. - The firewall already allows access from all spokes.
- Use managed identities to pull. Don't use admin keys.
Packages: Azure DevOps feeds¶
Use the organisation's feed so that dependencies are cached, scanned and auditable.
- Authenticate in a pipeline with the built-in tasks (
NuGetAuthenticate,npmAuthenticate,PipAuthenticate) and use the feed as source. The pipeline's build service identity authenticates within the same organisation. - Public URLs are blocked by the firewall by default. Use the feed's upstream sources instead of requesting rules.
Build agents in the network¶
Private resources (private endpoints, VMs without public IPs) can only be reached from inside the network. If the platform offers shared agent pools, use them for deployments to your spoke:
| Pool type | Good for | Limit |
|---|---|---|
| VM-based pool | Anything, including root installs (Docker CLI) | Slower to start |
| Container-based pool | Fast builds, one fresh container per job | No root, so no Docker daemon. Use dotnet publish container support, Podman rootless, Kaniko or ko to build images. The example pool stops a job after 30 minutes and has a cold start of a few minutes (Build agents). |
The pool names and how to get access are platform-specific. Permissions come from the service connection your pipeline uses. Ask your platform team for access. How such a pool is typically built, how to use it, and what to do when its OS image changes: Build agents. Recommended Azure DevOps settings: Azure DevOps.
Messaging: Service Bus and Event Hubs¶
For the Integration Platform (queues and topics from JSON files, groups per entity, Event Hubs and API Management design) see Integration Platform, Service Bus and Shared services of the Integration Platform.
If your platform runs shared messaging, you get access to a shared namespace, not your own. In the reference design:
| Service Bus | Event Hubs | |
|---|---|---|
| What is shared | One namespace (Premium SKU, private endpoint, customer-managed key optional). Queues and topics are not created by the shared services code. | One namespace with one or more event hubs |
| Sign-in | Microsoft Entra ID only | Microsoft Entra ID only |
| Access | Through the spoke extension, or through a contributors group on the namespace | Through the spoke extension. Per event hub there is a sender group and a receiver group. |
Use a managed identity in your application, and give it the data roles (sender, receiver) through the groups. Ask your platform team how to get an event hub or queue created, and what the naming and retention settings are. Using these services as part of an integration solution is described in the Integration platform.
Communication Services¶
If your platform runs Communication Services, you can send e-mail from your application through a shared Communication Services and Email Communication Services resource. In the reference design:
- E-mail can be sent from an Azure-managed domain (if the platform team enabled it), or from a customer-managed domain that the platform team adds to the resource. Ask which sender domains exist or request a new one.
- Access is through a contributors group of the platform team. There is no spoke extension for this service yet.
- Delivery logs (send, status, engagement) go to the Log Analytics workspace of the shared services spoke.
Ask your platform team for access and for the sender domain.
API Management (shared)¶
If your platform offers a shared APIM, publish an API by describing it (name, path, backend service_url, OpenAPI
file, products, subscriptions), either through a pull request to the platform's API definitions or by request. Don't
commit subscription keys: reference Key Vault secrets instead. In the reference design the shared instance is private
(an internal network or a private endpoint), its developer portal is off unless the platform team enables it (sign-in is then
required), and telemetry goes to Application Insights, which a Monitoring Reader group can read. Using API Management as part of
an integration solution is described in the Integration platform.
Your own API Management instance in a spoke¶
If you deploy API Management in your own spoke, the network needs care, because spoke traffic goes through the hub firewall and you can't change NSGs and route tables yourself (Limits). Ask for the changes through a change request.
A common secure design is a reference architecture with API Management in internal mode behind an Application Gateway with WAF:
- The Application Gateway has the public IP address and publishes the APIs on a custom domain, in its own subnet.
- API Management (Premium) sits in a separate subnet, in internal mode, and is not reachable directly from the internet.
- Private endpoints connect API Management to back ends that are only exposed to the virtual network.
- Logs and telemetry go to Log Analytics and Application Insights.
DNS. In internal mode you bring your own DNS. Register a custom domain on the API Management instance: it only accepts requests whose host header matches the default gateway domain or a configured custom domain. The same custom domain can be assigned to more than one instance, so you can switch instances by changing a DNS record. Clients must reach the private IP address of API Management through the network, which needs a firewall rule (Firewall rules).
Classic tiers. Because all traffic is forced through the hub firewall, add:
| Item | What |
|---|---|
| User defined route | 0.0.0.0/0 to the firewall (next hop virtual appliance), and the ApiManagement service tag with next hop Internet. Without the second route the management traffic does not map back to its source addresses and the management endpoint becomes unreachable. |
| Service endpoints on the subnet | Azure SQL, Azure Storage, Azure Event Hubs, Azure Key Vault |
| NSG | The rules for internal mode from the Microsoft Learn guide. Inbound management traffic on port 3443 only from the ApiManagement service tag. |
v2 tiers. These have limits compared with the classic tiers: check the feature availability.
| Item | What |
|---|---|
| Subnet | Used by one API Management instance only. At least a /27, a /24 recommended so it can scale. Delegated to Microsoft.Web/serverFarms. The deploying identity needs Microsoft.Network/virtualNetworks/read and Microsoft.Network/virtualNetworks/subnets/join/action. |
| NSG | Required. Minimum: allow outbound Tcp 443 from VirtualNetwork to the Storage service tag (priority 110), plus outbound rules for your back ends. |
| Public access | Can be disabled only after a private endpoint exists. Deploy with public access enabled, then disable it. |