GHOSTby AlphaBravo
CatalogWhy GhostContactAccount
Ghost Container Registry — Secure, signed, FIPS-ready images·Built by AlphaBravo
Catalog/azure-service-operator/Guides

azure service operator

FIPS 140-3Developer tools

Azure Service Operator allows you to create Azure resources using kubectl.

OverviewGuidesTags

Quick Start

Pull the latest version of this image from the Ghost registry. Pulling requires authentication — generate a token and run docker login first (see Authentication below).

Authentication

The Ghost catalog is public to browse, but pulling images requires an account. Generate a pull token below (or from your Account → Tokens page) — you'll get a ready-to-paste docker login command, then docker pull works.

The username is generated automatically (it looks like robot$<project>+<auto-id>, not the name you typed) and is included in the docker login command above. The secret is shown only once when you create the token.

Verify Signature

All Ghost images are signed with cosign. Verifying the signature before deployment ensures the image has not been tampered with.

Install cosign via brew install cosign or download from the Sigstore releases page.

Using This Image

Reference this image in your Dockerfile as a base layer:

FIPS 140-3 Compliance

This is a vendor-built FIPS-enabled image: its cryptography runs on FIPS 140-3 validated modules configured by the upstream vendor. You can inspect the image metadata:

StandardFIPS 140-3
Crypto moduleVendor-configured validated modules
CryptographyValidated modules only
Use caseGovernment, regulated industries, compliance workloads

Additional Notes

How to use this image

All examples in this guide use the public image. If you’ve mirrored the repository for your own use (for example, to your Docker Hub namespace), update your commands to reference the mirrored image instead of the public one.

For example:

  • Public image: registry.ghost-prod.alphabravo.io/ghost-base/<repository>:<tag>
  • Mirrored image: <your-namespace>/dhi-<repository>:<tag>

For the examples, you must first use docker login registry.ghost-prod.alphabravo.io to authenticate to the registry to pull the images.

Install Azure Service Operator using Helm

The recommended way to install Azure Service Operator is using the official Helm chart. Replace <tag> with the image variant you want to run.

# Add the Azure Service Operator Helm repository
helm repo add aso2 https://raw.githubusercontent.com/Azure/azure-service-operator/main/v2/charts
helm repo update

# Install with basic configuration
helm install aso2 aso2/azure-service-operator \
  --create-namespace \
  --namespace azureserviceoperator-system \
  --set image.repository=registry.ghost-prod.alphabravo.io/ghost-base/azure-service-operator:<tag> \
  --set azureTenantID="your-tenant-id" \
  --set azureSubscriptionID="your-subscription-id" \
  --set azureClientID="your-client-id" \
  --set azureClientSecret="your-client-secret"

Run Azure Service Operator directly

On this page

Quick StartAuthenticationVerify SignatureUsing This ImageFIPS ComplianceAdditional Notes

For testing or development purposes, you can run the operator directly:

# Run with required environment variables
docker run --rm -e AZURE_TENANT_ID="your-tenant-id" \
  -e AZURE_SUBSCRIPTION_ID="your-subscription-id" \
  -e AZURE_CLIENT_ID="your-client-id" \
  -e AZURE_CLIENT_SECRET="your-client-secret" \
  registry.ghost-prod.alphabravo.io/ghost-base/azure-service-operator:<tag>

[!NOTE] This direct approach is for testing only. Production deployments should use the Helm chart for proper RBAC, webhooks, and CRD management.

Authentication methods

Azure Service Operator supports multiple authentication methods to connect to Azure:

Service Principal (Client Secret)

The most common authentication method using a service principal:

# values.yaml for Helm installation
azureTenantID: "your-tenant-id"
azureSubscriptionID: "your-subscription-id"
azureClientID: "your-service-principal-client-id"
azureClientSecret: "your-service-principal-secret"

Workload Identity (Recommended for AKS)

For AKS clusters, use Azure Workload Identity for enhanced security:

# values.yaml for Helm installation
azureTenantID: "your-tenant-id"
azureSubscriptionID: "your-subscription-id"
azureClientID: "your-managed-identity-client-id"
useWorkloadIdentityAuth: true

# Pod identity configuration
podLabels:
  azure.workload.identity/use: "true"

Client Certificate

Authenticate using a client certificate:

# values.yaml for Helm installation
azureTenantID: "your-tenant-id"
azureSubscriptionID: "your-subscription-id"
azureClientID: "your-service-principal-client-id"
azureClientCertificate: |
  -----BEGIN CERTIFICATE-----
  [certificate content]
  -----END CERTIFICATE-----
azureClientCertificatePassword: "certificate-password" # Optional

Common use cases

Azure Service Operator enables you to manage Azure resources directly from Kubernetes manifests.

Provision an Azure Storage Account

apiVersion: storage.azure.com/v1api20210401
kind: StorageAccount
metadata:
  name: mystorageaccount
  namespace: default
spec:
  location: eastus
  resourceGroupRef:
    name: myresourcegroup
  kind: StorageV2
  sku:
    name: Standard_LRS

Create an Azure Database for PostgreSQL

apiVersion: dbforpostgresql.azure.com/v1api20210601
kind: FlexibleServer
metadata:
  name: mypostgresql
  namespace: default
spec:
  location: eastus
  resourceGroupRef:
    name: myresourcegroup
  administratorLogin: myadmin
  administratorLoginPassword:
    name: postgresql-secret
    key: password
  storage:
    storageSizeGB: 32
  sku:
    name: Standard_B1ms
    tier: Burstable
  version: "13"

Multi-tenant configuration

For managing resources across multiple tenants:

# values.yaml for Helm installation
azureTenantID: "primary-tenant-id"
azureAdditionalTenants: "tenant-id-1,tenant-id-2,tenant-id-3"
multitenant:
  enable: true

Configuration options

Namespace targeting

Control which namespaces the operator monitors:

# values.yaml - Monitor specific namespaces only
azureTargetNamespaces: ["production", "staging"]

# Or monitor all namespaces (default)
azureTargetNamespaces: []

Sync period configuration

# values.yaml - Set how often resources are re-synced with Azure
azureSyncPeriod: "1h"  # Options: "1h", "30m", "never"

CRD management

# values.yaml - Control which CRDs to install
installCRDs: true
crdPattern: "resources.azure.com/*;compute.azure.com/*;storage.azure.com/*"

Metrics and monitoring

# values.yaml - Enable metrics endpoint
metrics:
  enable: true
  secure: true  # Serve over HTTPS
  port: 8443

Image variants

Ghost hardened images come in different variants depending on their intended use.

  • Runtime variants are designed to run your application in production. These images are intended to be used either directly or as the FROM image in the final stage of a multi-stage build. These images typically:

    • Run as the nonroot user
    • Do not include a shell or a package manager
    • Contain only the minimal set of libraries needed to run the app
  • Build-time variants typically include dev in the variant name and are intended for use in the first stage of a multi-stage Dockerfile. These images typically:

    • Run as the root user
    • Include a shell and package manager
    • Are used to build or compile applications

Migrate to a Ghost hardened image

To migrate your Azure Service Operator deployment to a Ghost hardened image, you must update your Helm values or Kubernetes manifests. At minimum, you must update the container image reference to use a Ghost hardened image. This and a few other common changes are listed in the following table of migration notes.

ItemMigration note
Base imageReplace your container image references in your Helm values or Kubernetes manifests with a Ghost hardened image.
Package managementNon-dev images, intended for runtime, don't contain package managers. Use package managers only in images with a dev tag.
Nonroot userBy default, non-dev images, intended for runtime, run as the nonroot user. Ensure that necessary files and directories are accessible to the nonroot user.
Multi-stage buildUtilize images with a dev tag for build stages and non-dev images for runtime. For binary executables, use a static image for runtime.
TLS certificatesGhost hardened images contain standard TLS certificates by default. There is no need to install TLS certificates.
PortsNon-dev hardened images run as a nonroot user by default. As a result, applications in these images can't bind to privileged ports (below 1024) when running in Kubernetes or in Docker Engine versions older than 20.10. To avoid issues, configure your application to listen on port 1025 or higher inside the container.
Entry pointGhost hardened images may have different entry points than images such as Docker Official Images. Inspect entry points for Ghost hardened images and update your Dockerfile if necessary.
No shellBy default, non-dev images, intended for runtime, don't contain a shell. Use dev images in build stages to run shell commands and then copy artifacts to the runtime stage.

The following steps outline the general migration process.

  1. Update your Helm values or Kubernetes manifests

    Replace the existing image reference in your Helm values file:

    # Before
    image:
      repository: mcr.microsoft.com/k8s/azureserviceoperator:v2.15.0
    
    # After
    image:
      repository: registry.ghost-prod.alphabravo.io/ghost-base/azure-service-operator:<tag>
    
  2. Verify authentication configuration

    Ensure your authentication method is properly configured and the operator can connect to Azure.

  3. Test with a subset of resources

    Start by deploying the operator in a test namespace and verify it can manage a simple Azure resource like a Resource Group.

  4. Monitor webhook and CRD functionality

    Verify that webhooks are working correctly and CRDs are installed as expected.

Troubleshooting migration

The following are common issues that you may encounter during migration.

General debugging

The hardened images intended for runtime don't contain a shell nor any tools for debugging. The recommended method for debugging applications built with Ghost hardened images is to use Docker Debug to attach to these containers. Docker Debug provides a shell, common debugging tools, and lets you install other tools in an ephemeral, writable layer that only exists during the debugging session.

Authentication failures

If the operator fails to authenticate with Azure:

  1. Verify credentials: Ensure all required authentication parameters are correctly configured
  2. Check service principal permissions: Verify the service principal has appropriate RBAC roles in your Azure subscription
  3. Validate tenant and subscription IDs: Confirm the tenant and subscription IDs are correct
  4. Test workload identity setup: For workload identity, verify the federated identity credential is properly configured

CRD installation issues

If CRDs are not installing correctly:

  1. Check CRD patterns: Verify your crdPattern setting matches the resources you want to manage
  2. Verify cluster permissions: Ensure the operator has cluster-admin permissions to install CRDs
  3. Review operator logs: Check the operator logs for specific CRD installation errors

Resource reconciliation problems

If Azure resources are not being created or updated:

  1. Check resource status: Use kubectl describe to check the status conditions of your Custom Resources
  2. Review Azure permissions: Verify the authenticated identity has permissions to create the specific Azure resources
  3. Validate resource group references: Ensure referenced resource groups exist and are accessible
  4. Monitor sync periods: Check if resources are being reconciled according to your azureSyncPeriod setting

Webhook configuration issues

If validation webhooks are not working:

  1. Verify webhook certificates: Ensure webhook certificates are properly configured and not expired
  2. Check network policies: If using network policies, ensure webhook traffic is allowed
  3. Validate webhook service: Confirm the webhook service is accessible from the Kubernetes API server

Performance and scaling

For performance optimization:

  1. Adjust concurrent reconciles: Use MAX_CONCURRENT_RECONCILES environment variable to control parallelism
  2. Configure rate limiting: Set appropriate RATE_LIMIT_QPS and RATE_LIMIT_BUCKET_SIZE values
  3. Optimize sync periods: Use longer sync periods for stable environments to reduce Azure API calls
  4. Scale replicas: Increase replica count for high-availability deployments

No shell

By default, image variants intended for runtime don't contain a shell. Use dev images in build stages to run shell commands and then copy any necessary artifacts into the runtime stage. In addition, use Docker Debug to debug containers with no shell.

Entry point

Ghost hardened images may have different entry points than upstream images. The Azure Service Operator DHI uses /aso-controller as the entry point. If you're customizing the container command or args, ensure they're compatible with this entry point.