Skip to content

Key Management SDK — Prerequisites

SDK Version: 3.4.0
Audience: A product or pipeline that manages the keys of one AnkaSecure tenant without a person at the keyboard

The Key Management SDK signs in as an administrative workload of a tenant. Before the first call, three things must exist: a reachable deployment, the workload with its public key registered, and the scopes the workload needs. The SDK creates none of them: people prepare the workload once, in the Admin Console.

The SDK itself must be on the classpath first. Coordinates, JAR and checksums are on the Downloads page.


1. A reachable deployment

The SDK dials one origin over https and reaches both the Auth API (the workload token) and the Admin API (key management) through it. It first reads the deployment's authorization server metadata (/api/v3/auth/.well-known/oauth-authorization-server) and refuses to send any credential unless that document names the platform issuer, lists ES256 DPoP proofs and publishes a token endpoint.

The published token endpoint must be on the origin the SDK dials; otherwise the SDK refuses to sign in. Every DPoP proof and the assertion audience name that origin. Configure the deployment's address that serves the authorization server metadata and the workload token endpoint.


2. The administrative workload

An administrative workload is an identity of the tenant: a UUID that proves itself with a key pair your product holds, or with a token an issuer the platform trusts minted for it. It is not a user and has no client secret. Two people prepare it once, in this order:

Step Who Does Hands over
1 Integration developer Generates the workload's key pair and keeps the private key The public JWK, to the tenant administrator
2 Tenant administrator Creates the workload, registers the public JWK, assigns the scopes The workload id, to the integration developer
3 Integration developer Configures the SDK with the deployment's address, the workload id and the private key file —

After step 3 nobody signs in again for the product's automation.

2.1 Step 1 — the integration developer generates the key pair

The private key never leaves the product, and the platform never sees it. Any tool that produces an EC P-256, P-384 or P-521 key, or an RSA key of 2048 to 4096 bits, will do, as long as you end with:

  • the private key as an unencrypted PKCS#8 PEM file (it begins -----BEGIN PRIVATE KEY-----) or as a private JWK. A SEC1 PEM (-----BEGIN EC PRIVATE KEY-----) and an encrypted PEM are not read;
  • the public key as a JWK: kty, crv, x, y for EC; kty, n, e for RSA. kid, alg, use (sig) and key_ops (with verify) are accepted and nothing else; the platform ignores a kid you set and names the key by its RFC 7638 thumbprint.

The JDK alone does it, with nothing to install:

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;

/** Generates an EC P-256 key pair for an administrative workload. */
public class GenerateWorkloadKey {

    public static void main(String[] args) throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
        generator.initialize(new ECGenParameterSpec("secp256r1"));
        KeyPair pair = generator.generateKeyPair();

        // The private key, as an unencrypted PKCS#8 PEM file: it stays with the integration.
        String pem = "-----BEGIN PRIVATE KEY-----\n"
                + Base64.getMimeEncoder(64, new byte[] {'\n'}).encodeToString(pair.getPrivate().getEncoded())
                + "\n-----END PRIVATE KEY-----\n";
        Files.writeString(Path.of("workload-key.pem"), pem, StandardCharsets.US_ASCII);

        // The public JWK: the only part the tenant administrator registers.
        ECPublicKey publicKey = (ECPublicKey) pair.getPublic();
        Base64.Encoder base64url = Base64.getUrlEncoder().withoutPadding();
        System.out.println("{\"kty\":\"EC\",\"crv\":\"P-256\",\"x\":\""
                + base64url.encodeToString(coordinate(publicKey.getW().getAffineX()))
                + "\",\"y\":\""
                + base64url.encodeToString(coordinate(publicKey.getW().getAffineY())) + "\"}");
    }

    /** A P-256 coordinate as exactly 32 unsigned big-endian bytes (RFC 7518, section 6.2.1.2). */
    private static byte[] coordinate(BigInteger value) {
        byte[] raw = value.toByteArray();
        byte[] fixed = new byte[32];
        int start = Math.max(0, raw.length - 32);
        System.arraycopy(raw, start, fixed, 32 - (raw.length - start), raw.length - start);
        return fixed;
    }
}
java GenerateWorkloadKey.java > workload-public.jwk   # prints the public JWK, writes workload-key.pem
chmod 600 workload-key.pem                            # owner-only: the SDK refuses a group- or world-readable key

Send workload-public.jwk to the tenant administrator; it holds nothing secret. Keep workload-key.pem where the product runs, readable only by the product's account. On Windows, restrict the file's access list to that account: the SDK warns when another principal can read it.

2.2 Step 2 — the tenant administrator prepares the workload

  1. Create the workload on the console's Administrative Workloads screen, with a name the audit trail will show for everything the product does (for example acme-key-rotation). A new workload is ACTIVE but can do nothing yet.
  2. Register the public key on the workload's Keys tab: paste the JWK the developer sent. Valid until is optional; left empty, the key is accepted for twelve months, and never for more than twenty-four.
  3. Assign the scopes on the Scopes tab: exactly the ones the product calls, and no more (§3).
  4. Send the developer the workload's id, the UUID shown under its name when you open it. It is not secret.

On a SaaS deployment the tenant's own administrator prepares it. On a private cloud or on-premises deployment a platform administrator may as well. A workload of the tenant can never prepare another one for that tenant.

2.3 Step 3 — the integration developer configures the SDK

Three values reach the SDK, and none of them is a secret held by the platform:

  • the deployment's address (kmsdk.scheme, kmsdk.host, kmsdk.port);
  • the workload id from the tenant administrator;
  • the path of the private key file, or the source of the federated token.

The same id and key file also sign the Key Management CLI in:

ankasecure-km init --url https://api.example.com --workload-id <workload id> --private-key-file /etc/acme/workload-key.pem

3. Scopes

A workload's token carries exactly the scopes assigned to it, and the SDK never requests scopes explicitly. A call without its scope is refused with 403 and the SDK raises a KeyManagementSdkException.

Group Operation Scope
Keys list, get, export, lifecycle-cause verdicts admin.keys.read
Keys create admin.keys.orchestrate
Keys update metadata admin.keys.patch
Keys import a key migration.importKey
Keys import or analyse a keystore migration.importKeystore
Keys supported algorithms admin.tenant.algorithms.read
Keys suspend, reactivate, revoke, archive admin.keys.suspend, admin.keys.reactivate, admin.keys.revoke, admin.keys.archive
Key versions list, get admin.tenant.keys.materials.read
Key versions revoke admin.tenant.keys.materials.revoke
Rotation rotate admin.keys.rotate
Rotation admissibility admin.keys.read
Rotation schedule, executions admin.keys.rotation-schedule.read
Rotation replace schedule admin.keys.rotation-schedule.write
Destruction request / cancel for a key admin.keys.mark-for-destruction / admin.keys.cancel-destruction
Destruction request / cancel for a version admin.tenant.keys.materials.mark-for-destruction / admin.tenant.keys.materials.cancel-destruction
Destruction orders admin.keys.read
Own quorum requests list, get / cancel admin.tenant.quorum.read / admin.tenant.quorum.cancel
Exchange contexts read / create, update, delete, suspend, resume, close admin.tenant.exchange-context.list, .read / .create, .update, .delete, .suspend, .resume, .close
Exchanges list, get admin.tenant.exchange.read
Exchanges create, clone admin.tenant.exchange.create
Exchanges update, validate admin.tenant.exchange.update
Exchanges preview activation, activate, resume admin.tenant.exchange.activate
Exchanges suspend / revoke / discard a draft admin.tenant.exchange.suspend / .revoke / .delete
Capability grants list, get / create, preview / delete admin.tenant.capability-grant.list, .read / .create / .revoke
Constraint policies list, get / create / update / delete admin.tenant.constraint-policy.list, .read / .create / .update / .delete
Internal cryptographic use cases list, get / create / suspend / resume / delete admin.tenant.internal-use-case.read / .create / .suspend / .resume / .revoke
Directory applications / actors / counterparty types admin.tenant.application.list, .read / admin.tenant.actor.list, .read / admin.tenant.counterparty-type.list, .read

A workload is never admitted to the scopes of tenant general policies, key backends, BYOK, key custody or the tenant override switch: those stay with people in the Admin Console. The version-level destruction request that would leave the key with no version outside a destruction is the key's own destruction request and needs admin.keys.mark-for-destruction as well (Key Destruction).


4. Configuration

The SDK reads its endpoint from a Properties object. The credential is a method argument, not configuration. kmsdk.scheme and kmsdk.host are required: the constructor refuses a configuration that lacks either with a KeyManagementSdkException naming each missing key (kmsdk.host is required), and never assumes an address. A port or timeout that is not a number, or is out of range, is refused the same way, naming the key.

Property Default Purpose
kmsdk.scheme None — required Protocol: https, or http for development
kmsdk.host None — required The host the SDK dials
kmsdk.port The scheme's own port: 443 for https, 80 for http The port the SDK dials, from 1 to 65535
kmsdk.connectTimeoutMs 10000 Connection timeout (milliseconds)
kmsdk.readTimeoutMs 30000 Read timeout (milliseconds)
kmsdk.writeTimeoutMs 30000 Write timeout (milliseconds)
kmsdk.tls.insecure false Trust-all TLS toggle — development only; emits a WARN when enabled
kmsdk.auth.issuer https://auth.ankatech.co The platform issuer the authorization server metadata must name before a workload authenticates

5. Next steps


Version: 3.4.0
Last updated: 2026-10-26