Bank API

repository·main·Indexed 21 days ago

https://github.com/erwinkramer/bank-api

A design reference project for building compliant, modern, and secure APIs using a .NET stack. It demonstrates best practices for security (OWASP, JWS), event-driven architecture (CloudEvents, Outbox pattern), and observability. Features include Model Context Protocol (MCP) support, OpenAPI v3.2.0 compliance, and deployment options for Azure Container Apps, Kubernetes via kro, and Podman.

Tokens
3.1K
Snippets
14
Records
17
Agent score
74%

What's inside bank-api

  1. Overview of Bank API

    main

    The Bank API is a design reference project intended to bootstrap the development of modern, compliant APIs. It serves as a blueprint for implementing security, event-driven architecture, and regulatory compliance in a professional API environment.

    Key features include:

    • Compliance: Adheres to OWASP API Security Top 10, OpenAPI v3.2.0, and NLGov REST API Design Rules.
    • Security: Implements JWS (JSON Web Signature) for response signing via the X-JWS-Signature header and provides JWKS (JSON Web Key Set) at /.well-known/jwks.json for validation.
    • Event-Driven Architecture (EDA): Uses the Outbox pattern and CloudEvents (v1.0.2) for event data and HTTP webhook delivery.
    • MCP Support: Includes a Model Context Protocol server.
  2. Verify API response signatures using JWS and JWKS

    main

    The Bank API ensures response integrity by signing responses using JSON Web Signature (JWS) as per RFC 7515.

    To validate these signatures, you can retrieve the public keys from the JSON Web Key Set (JWKS) endpoint provided by the API.

    Header: X-JWS-Signature
    Endpoint: /.well-known/jwks.json
  3. Understand the Bank API architecture

    main

    The project follows a layered design pattern. The core logic resides in BankApi.Core, which contains defaults, downstream clients, and implementations. These are exposed via BankApi.Service.Beta or BankApi.Service.Stable APIs.

    Key architectural components include:

    • BankApi.Core: The foundation containing implementation and downstream client logic.
    • BankApi.Orchestration (Aspire): Handles orchestration and infrastructure generation.
    • BankApi.Mcp: Provides Model Context Protocol capabilities.
    • BankApi.Tests: Contains the testing suite.
    • Generated Layers: Infra.Generated and Specs.Generated are produced by the orchestration and specification processes respectively.
  4. Quick start: Local development setup

    main

    To set up the Bank API for local development, follow these steps using a pwsh shell:

    1. Regenerate API Client (Optional): In the Kiota workspace (.kiota/workspace.json), click Re-generate under clients.
    2. Regenerate HTTPS Certificates (Optional):
      dotnet dev-certs https --clean && dotnet dev-certs https -ep ./.certs/AspNetDev.pfx -p '' --trust
    3. Regenerate Helm Chart Artifacts (Optional):
      rm -r Infra.Generated/* && aspire --version && aspire publish -o Infra.Generated
    4. Generate JWT Token: Create a token for secured endpoints with the bank_api scope and banker role:
      dotnet user-jwts create --scope "bank_api" --role "banker" --valid-for 3650d --project BankApi.Service.Stable
    5. Build and Validate OpenAPI:
      • Set environment to Development:
        setx ASPNETCORE_ENVIRONMENT "Development"
      • Run dotnet build to output the OpenAPI definition.
      • Validate the definition at /Specs.Generated/openapi_v1_spec.json using the Spectral extension.
    dotnet user-jwts create --scope "bank_api" --role "banker" --valid-for 3650d --project BankApi.Service.Stable
  5. Configure Keycloak for Kubernetes Service Account token assertion

    main

    The Bank API uses Kubernetes Service Account tokens for identity. To enable token assertion in a Keycloak realm named bank, follow these steps:

    1. Identity Provider: Create a Keycloak Kubernetes identity provider named local-kubus with issuer https://kubernetes.default.svc.
    2. OIDC Client: Create an OpenID Connect client named sa-bank-api. Enable Client authentication and Service account roles.
    3. Authenticator: In the client's Credentials tab, set the Client Authenticator to Signed JWT - Federated using provider local-kubus and subject system:serviceaccount:infra-services:bank-api.
    4. Sanity Test: Verify the configuration by exchanging a Kubernetes token for a Keycloak token using the api-stable container:
    kubectl -n infra-services exec deploy/bank-api -c api-stable -- sh -c \
    'wget -qO- --header="Content-Type: application/x-www-form-urlencoded" --post-data="grant_type=client_credentials&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=$(cat /var/run/secrets/bank-api/token)" http://keycloak-service.infra-keycloak.svc:8080/realms/bank/protocol/openid-connect/token'
  6. Deploy the Bank API using kro

    main

    To deploy the Bank API with all sidecars in Kubernetes, follow these steps:

    1. Prepare Secrets: Rename bank-api-secret.yaml.sample to bank-api-secret.yaml and replace all REPLACE_ME placeholders with actual values.
    2. Validate Manifests: Run a dry-run to ensure the deployment structure is correct:
      kubectl apply --dry-run=server -f bank-api-rgd.yaml
      kubectl apply --dry-run=server -f bank-api-secret.yaml
      kubectl apply --dry-run=server -f bank-api-instance.yaml
    3. Apply Manifests: Deploy the resources in order:
      kubectl apply -f bank-api-rgd.yaml
      kubectl apply -f bank-api-secret.yaml
      kubectl apply -f bank-api-instance.yaml
    4. Verify: Check the status of the pods in the infra-services namespace:
      kubectl get pods -n infra-services -l app.kubernetes.io/name=bank-api
    kubectl apply -f bank-api-rgd.yaml
    kubectl apply -f bank-api-secret.yaml
    kubectl apply -f bank-api-instance.yaml
  7. Run the Bank API using Podman containers

    main

    You can orchestrate the full stack using podman.

    1. Prepare Environment: Rename .env.sample to .env and update values.
    2. Create Pod:
      podman pod create --name bank-api-pod -p 127.0.0.1:8080:8080 -p 127.0.0.1:5201:10000 -p 127.0.0.1:6070:6070 -p 127.0.0.1:3500:3500
    3. Start Sidecars:
      • Dapr: podman build -t bank-api-daprd:v1 ./Sidecar.Dapr && podman run --pod bank-api-pod --env-file .env bank-api-daprd:v1
      • OpenTelemetry: podman build -t bank-api-otelcol:v1 ./Sidecar.OpenTelemetry && podman run --pod bank-api-pod --env-file .env bank-api-otelcol:v1
      • S3Proxy (Azure Blob as S3): podman build -t bank-api-s3proxy:v1 ./Sidecar.S3Proxy && podman run --pod bank-api-pod --env-file .env bank-api-s3proxy:v1
    4. Start API:
      podman build -t bank-api:v1 .
      podman run --pod bank-api-pod --env-file .env bank-api:v1
    5. Start Proxy (Optional): To use the proxied OpenAPI Spec or Scalar UI:
      podman build -t bank-api-proxy:v1 ./Sidecar.Proxy
      podman run --pod bank-api-pod bank-api-proxy:v1
      • Proxied OpenAPI: http://localhost:5201/v1/openapi/spec.json
      • Scalar UI: http://localhost:5201/v1/docs/
      • Direct API: http://localhost:8080

    Teardown: podman pod rm -f bank-api-pod

    podman pod create --name bank-api-pod -p 127.0.0.1:8080:8080 -p 127.0.0.1:5201:10000 -p 127.0.0.1:6070:6070 -p 127.0.0.1:3500:3500
  8. Run in Aspire minimal mode

    main

    Minimal mode runs only the ASP.NET Core API.

    1. Ensure a container runtime is running.
    2. Start the Aspire Dashboard for visualization:
      podman run --rm -it \
        -p 18888:18888 \
        -p 4317:18889 \
        --name aspire-dashboard \
        mcr.microsoft.com/dotnet/aspire-dashboard:latest
      Use the URL/token provided in the output to log in to the dashboard.
    3. Run the VS Code launch configuration: API - Stable release channel.
    podman run --rm -it \
      -p 18888:18888 \
      -p 4317:18889 \
      --name aspire-dashboard \
      mcr.microsoft.com/dotnet/aspire-dashboard:latest
  9. Install prerequisites for local development

    main

    To develop with the Bank API locally without using a Dev Container, you must install the following:

    1. .NET 11 SDK
    2. Visual Studio Code Extensions: Install all recommended extensions listed in .vscode/extensions.json.
    3. Aspire CLI
    irm https://aspire.dev/install.ps1 | iex
  10. Teardown kro and Bank API deployment

    main

    To remove the deployment, you must delete the resources in this specific order to avoid dependency errors:

    1. Delete the instance.
    2. Delete the RGD (Resource Group Definition).
    3. Delete the bankapis.kro.run Custom Resource Definition (CRD).
    kubectl delete -f bank-api-instance.yaml
    kubectl delete -f bank-api-rgd.yaml
    kubectl delete crd bankapis.kro.run