How Akash Implements Certificate Management for Secure Provider-Tenant Communication

Akash implements certificate management through a Cosmos SDK-based x/cert module that stores X.509 certificates on-chain, validates them during a custom TLS handshake, and enforces mutual TLS (mTLS) to ensure only authorized providers and tenants can communicate.

The akash-network/node repository provides a decentralized cloud marketplace where providers offer compute resources and tenants lease them. To secure these interactions without relying on external PKI infrastructure, Akash embeds certificate management for secure provider-tenant communication directly into its Cosmos SDK blockchain state machine. This approach binds cryptographic identity to on-chain accounts, enabling cryptographically verifiable mTLS connections between all network participants.

On-Chain Certificate Lifecycle with Cosmos SDK

Akash’s certificate logic lives in the x/cert module, which implements the full lifecycle of X.509 certificates as Cosmos SDK state transitions. The module treats certificates as first-class blockchain objects with deterministic storage keys and explicit state transitions.

Creating and Storing Certificates

Tenants and providers initiate the lifecycle by submitting a MsgCreateCertificate transaction. The message handler in x/cert/handler/msg_server.go forwards the request to the keeper’s CreateCertificate method, which performs several critical validations via types.ParseAndValidateCertificate:

  • Parses the PEM-encoded certificate and public key
  • Validates the cryptographic signature
  • Confirms the owner address matches the transaction signer

The keeper then stores the certificate in the KV store under a deterministic key combining the owner address and serial number. Valid certificates are written to the CertificateValid prefix, establishing the on-chain identity record required for subsequent mTLS handshakes.

func (m msgServer) CreateCertificate(goCtx context.Context, req *types.MsgCreateCertificate) (*types.MsgCreateCertificateResponse, error) {
    ctx := sdk.UnwrapSDKContext(goCtx)
    owner, err := sdk.AccAddressFromBech32(req.Owner)
    if err != nil { return nil, err }

    // keeper stores the cert
    err = m.keeper.CreateCertificate(ctx, owner, req.Cert, req.Pubkey)
    if err != nil { return nil, err }
    return &types.MsgCreateCertificateResponse{}, nil
}

Revoking Certificates

When a certificate must be invalidated, the owner submits a MsgRevokeCertificate transaction. The RevokeCertificate keeper method in x/cert/keeper/keeper.go locates the existing entry using findCertificate, transitions its state to CertificateRevoked, and moves the storage entry to the revoked prefix. This atomic state change ensures a single source of truth: any query checking for valid certificates will immediately exclude revoked entries, preventing their use in new TLS connections.

Querying Certificate State via gRPC

The module exposes certificate state through a gRPC query service defined in x/cert/keeper/grpc_query.go. This interface allows any network participant to retrieve certificates filtered by owner address, serial number, or validation state. Client applications, including the TLS loader utilities, access this service through ctypes.NewQueryClient as implemented in x/cert/utils/utils.go. This query capability enables real-time verification during connection establishment without requiring full node synchronization.

Runtime TLS Validation and mTLS Enforcement

Akash enforces mutual TLS (mTLS) by integrating on-chain certificate queries directly into the TLS handshake process. Before a provider and tenant can exchange application data, both parties must present certificates that exist on-chain in the valid state.

Loading and Verifying Certificates

The LoadAndQueryCertificateForAccount function in x/cert/utils/utils.go orchestrates three validation layers when preparing a connection:

  1. Local PEM parsing: Converts the local PEM-encoded certificate and private key into a tls.Certificate structure
  2. X.509 validity window: Verifies the current time falls within the certificate's not-before and not-after timestamps
  3. On-chain commitment check: Queries the blockchain to confirm the certificate is committed and in the CertificateValid state

If any check fails, the function returns an error before the TLS handshake completes, effectively blocking unauthorized connections.

func loadTLSCert(ctx context.Context, clientCtx client.Context, pemReader io.Reader) (tls.Certificate, error) {
    // Reads local PEM, validates against blockchain, returns a tls.Certificate usable by grpc.Dial
    return utils.LoadAndQueryCertificateForAccount(ctx, clientCtx, pemReader)
}

KeyPairManager and Local PEM Handling

The KeyPairManager utility in x/cert/utils/key_pair_manager.go handles the local storage and retrieval of PEM-encoded credentials. When a client initiates a gRPC or REST call, this manager reads the local certificate files and provides them to the TLS loader. This separation of concerns allows the cryptographic identity to be stored securely on the filesystem while the blockchain provides the authoritative trust anchor for validation.

Genesis and Upgrade Support

The x/cert module implements InitGenesis and ExportGenesis methods in x/cert/module.go to bootstrap certificate state at chain initialization and preserve it across software upgrades. Additionally, specific upgrade handlers such as those in upgrades/software/v1.0.0/cert.go manage store format migrations, ensuring that certificate data remains accessible and correctly formatted through network upgrades.

Summary

  • On-chain storage: Akash stores X.509 certificates in the application state using the x/cert module, with separate KV store prefixes for valid and revoked certificates.
  • Transaction-based lifecycle: Certificate creation and revocation occur through Cosmos SDK messages (MsgCreateCertificate, MsgRevokeCertificate) processed by handlers in x/cert/handler/msg_server.go and keepers in x/cert/keeper/keeper.go.
  • mTLS enforcement: The LoadAndQueryCertificateForAccount function in x/cert/utils/utils.go validates local PEM files against on-chain state during TLS handshakes, implementing cryptographic mutual authentication.
  • Queryable state: A gRPC query service in x/cert/keeper/grpc_query.go enables real-time certificate status verification without trusting local state alone.
  • Upgrade continuity: Genesis functions and upgrade handlers ensure certificate persistence across chain restarts and protocol upgrades.

Frequently Asked Questions

What is the x/cert module in Akash?

The x/cert module is a Cosmos SDK module within the akash-network/node repository that implements on-chain certificate management. It handles the creation, storage, revocation, and querying of X.509 certificates used for provider-tenant authentication. The module stores certificates in the blockchain's KV store and provides the foundation for mutual TLS enforcement by maintaining an immutable record of valid and revoked credentials.

How does Akash validate certificates during TLS handshakes?

Akash validates certificates through the LoadAndQueryCertificateForAccount function in x/cert/utils/utils.go. This utility performs local X.509 parsing to verify the PEM structure and temporal validity, then queries the on-chain x/cert keeper via gRPC to confirm the certificate exists in the CertificateValid state. Only certificates passing both local cryptographic checks and on-chain state verification are accepted for mTLS connections.

Can a revoked certificate be reused in Akash?

No. Once a certificate is revoked via MsgRevokeCertificate, the keeper in x/cert/keeper/keeper.go moves it from the CertificateValid prefix to the CertificateRevoked prefix in the KV store. Subsequent queries for valid certificates will not return revoked entries, and the LoadAndQueryCertificateForAccount validation will fail, preventing the revoked certificate from being used in new TLS handshakes.

Where are certificates stored in the Akash blockchain?

Certificates are stored in the Cosmos SDK KV store under deterministic keys defined in x/cert/keeper/key.go. Valid certificates use the CertificateValid prefix, while revoked certificates use the CertificateRevoked prefix. The storage key combines the owner address and certificate serial number, enabling efficient lookups by both the keeper logic and gRPC query handlers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →