Skip to content

About

Web Application that connects to ibm-hyper-protect/contract-ui

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

IBM Confidential Computing Contract Manager

A persona-governed, cryptographically auditable contract lifecycle system for IBM Confidential Computing Container Runtime (CCRT) deployments.


Prerequisites

Requirement Minimum version
Docker Engine 20.10+
Docker Compose plugin v2.0+
Git any
RAM 2 GB
Disk 5 GB

No Go toolchain is required on the host — the image is built inside a multi-stage Docker build.


Self-Hosting (Fresh VM)

1. Clone the repository

git clone <repository-url>
cd contract-manager

2. Create your environment file

All configuration lives in compose/.env. Copy the example and fill in the required values:

cp compose/.env.example compose/.env

Open compose/.env and set at minimum the four required fields (the compose file will refuse to start without them):

# Required — pick strong unique values
POSTGRES_PASSWORD=<strong-password>
ADMIN_NAME=System Admin
[email protected]
ADMIN_PASSWORD=<strong-password>

All other values have working defaults. See compose/.env.example for the full reference.

3. Build the backend image

The contract-manager:local image does not exist in any registry — it must be built from source:

docker build -t contract-manager:local .

This runs a two-stage build: compiles the Go binary and the migrate tool inside the builder stage, then copies them into a minimal Alpine runtime image. Expect 2–5 minutes on first run (module download + compile); subsequent builds use the layer cache.

4. Start all services

docker compose -f compose/docker-compose.yaml --project-directory compose up -d

This starts five containers in dependency order:

  1. hpcr-postgres — PostgreSQL 16 database
  2. hpcr-migrate — runs all schema migrations then exits
  3. hpcr-backend — Go API server (waits for migrate to complete)
  4. hpcr-reverse-proxy — nginx reverse proxy (waits for backend healthy)
  5. hpcr-pgadmin — pgAdmin 4 web UI

5. Verify the stack

# All four long-running containers should show "healthy"
docker compose -f compose/docker-compose.yaml --project-directory compose ps

# Backend health endpoint
curl http://localhost:8080/health
# Expected: {"status":"ok"}

Default Access

Interface URL Default credentials
API / App http://localhost:8080 ADMIN_EMAIL / ADMIN_PASSWORD from .env
pgAdmin http://localhost:5050 PGADMIN_DEFAULT_EMAIL / PGADMIN_DEFAULT_PASSWORD from .env
Swagger UI http://localhost:8080/swagger —

First login: Every new account (including the seeded admin) must complete a mandatory setup flow before accessing any functionality: change the initial password, generate an RSA-4096 key pair, and register the public key.

Each client may register its own identity key: at most five active RSA-4096 keys per user, each valid for 90 days. Later registrations require password confirmation and, while an active key exists, a request signed with that key. Owners and admins can revoke individual keys; admins can also revoke all active keys. See the API reference and multi-key testing guide.

Existing clients remain compatible for normal use with one active key. Clients must update their registration flow before renewing keys or adding devices, and select the local key's fingerprint for signed requests instead of using the newest key returned by login.


Day-to-Day Operations

Rebuild after code changes

docker build -t contract-manager:local . \
  && docker compose -f compose/docker-compose.yaml --project-directory compose up -d --no-deps backend

View logs

# All services
docker compose -f compose/docker-compose.yaml --project-directory compose logs -f

# Single service
docker compose -f compose/docker-compose.yaml --project-directory compose logs -f backend

Stop the stack

docker compose -f compose/docker-compose.yaml --project-directory compose down

Full reset (destroys all data)

docker compose -f compose/docker-compose.yaml --project-directory compose down -v
sudo rm -rf compose/data/postgres

Access the database directly

docker compose -f compose/docker-compose.yaml --project-directory compose \
  exec postgres psql -U hpcr hpcr_builder

Project Layout

.
├── cmd/server/             # Main entrypoint — wires services, builds router
├── internal/
│   ├── config/             # Environment variable config
│   ├── contract/           # Engine interface + contract-go v3 implementation
│   ├── handler/            # HTTP handlers (writeJSON / writeError)
│   ├── keymgmt/            # KeyProvider interface; db implementation
│   ├── middleware/         # Auth, RBAC, signature, rate-limit, setup guard
│   ├── model/              # Domain types + AppError constructors
│   ├── repository/         # SQLC-generated DB layer (do not edit *.sql.go)
│   ├── repository/queries/ # SQL source files — edit these, then run ./scripts/generate-repository.sh
│   └── service/            # Business logic
├── migrations/             # golang-migrate SQL files (020 migrations)
├── compose/
│   ├── docker-compose.yaml # Stack definition
│   ├── .env.example        # Config template — copy to .env
│   └── config/nginx/       # nginx default.conf and tls.conf
├── Dockerfile              # Multi-stage build: Go builder → Alpine runtime
└── .dockerignore           # Excludes compose/data/, .bob/, .git/

Services and Ports

Container Image Exposed port Purpose
hpcr-reverse-proxy nginx:1.27-alpine 8080 → 80 Reverse proxy, rate limiting, TLS termination
hpcr-backend contract-manager:local internal 8080 Go API server
hpcr-postgres postgres:16-alpine internal 5432 PostgreSQL database
hpcr-migrate contract-manager:local — Schema migration runner (exits on completion)
hpcr-pgadmin dpage/pgadmin4:9 5050 → 80 Database management UI

Configuration Reference

All variables are set in compose/.env. The table below lists those that must be changed from the example defaults before first run:

Variable Required Description
POSTGRES_PASSWORD ✅ PostgreSQL password for the hpcr user
ADMIN_NAME ✅ Display name for the seeded admin account
ADMIN_EMAIL ✅ Email for the seeded admin account
ADMIN_PASSWORD ✅ Initial password for the seeded admin account
DATABASE_URL ✅ Full postgres DSN — must match POSTGRES_* values
MIGRATE_DATABASE_URL ✅ Same DSN used by the migration runner
PGADMIN_DEFAULT_PASSWORD recommended pgAdmin login password

DATABASE_URL and MIGRATE_DATABASE_URL in .env.example use ${POSTGRES_*} variable interpolation — if your shell or Docker Compose version does not expand these, set them explicitly as literal strings.

Optional: SSO (IBM w3id)

SSO login is disabled unless all four variables below are set. Users must already exist (matched by email); SSO never creates accounts, and password login keeps working.

Variable Description
APPID_CLIENT_ID OIDC client ID registered for the application
APPID_CLIENT_SECRET OIDC client secret
APPID_OAUTH_SERVER_URL Base URL of the OIDC endpoint (without /authorize)
APPID_REDIRECT_URI Redirect URI registered with the provider; must match exactly

Development

Run tests

go test ./cmd/... ./internal/...

Lint / vet

go vet ./cmd/... ./internal/...
gofmt -w .

Regenerate SQLC repository layer

After editing any .sql file under internal/repository/queries/:

./scripts/generate-repository.sh

Never edit internal/repository/*.sql.go directly — they are overwritten by ./scripts/generate-repository.sh. The script runs SQLC and copies license headers from the SQL source files into the generated query files.


Troubleshooting

pull access denied for contract-manager The image must be built locally first. Run step 3 above (docker build -t contract-manager:local .).

POSTGRES_PASSWORD must be set / ADMIN_PASSWORD must be set The compose file enforces these with :?. Copy .env.example to .env and fill in the required fields.

hpcr-migrate exits with non-zero / backend won't start

docker compose -f compose/docker-compose.yaml --project-directory compose logs migrate

A migration failure (e.g. dirty state from a previous partial run) will block the backend. To reset:

docker compose -f compose/docker-compose.yaml --project-directory compose down -v
sudo rm -rf compose/data/postgres
docker compose -f compose/docker-compose.yaml --project-directory compose up -d

/health returns 429 This should not happen — the /health endpoint is registered outside the rate-limited middleware group. If you see it, ensure you are running the image built from the current source.

compose/data/postgres permission errors The postgres data directory is written by the postgres container running as its internal UID. If you see permission errors after a sudo rm -rf, recreate the directory:

mkdir -p compose/data/postgres

Docker will repopulate it on next start.

Contract validation and runtime encryption

Workload and environment inputs are validated against the embedded CCRT schema before encryption, separately or as a complete plaintext contract. Builds use one runtime encryption certificate for workload, environment and attestation. See contract input validation and encryption for accepted formats, verification and compatibility limits.

Runtime certificate selection

Authenticated clients can discover platform-specific versions using GET /v2/encryption-certificates/versions and fetch an exact embedded PEM using GET /v2/encryption-certificates/certificate?platform=ccrt&version=26.7.2. The legacy flat versions field remains compatible. Catalog data comes from pinned contract-go v3.5.0; only CCRT is supported by the current contract workflow. See certificate API and rollout details. Deploy this additive API before the companion desktop selector; its custom certificate upload remains available.

Deploy this backend before releasing the paired UI validation change: the UI requires POST /v2/contract-validate. Existing unpinned builds cannot retrospectively verify the encryption recipient of older sections. No database migration is added by this change.

About

Web Application that connects to ibm-hyper-protect/contract-ui

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages