Files
mcias/README.md
Kyle Isom 0c441f5c4f Implement Phase 9: client libraries (Go, Rust, Lisp, Python)
- clients/README.md: canonical API surface and error type reference
- clients/testdata/: shared JSON response fixtures
- clients/go/: mciasgoclient package; net/http + TLS 1.2+; sync.RWMutex
  token state; DisallowUnknownFields on all decoders; 25 tests pass
- clients/rust/: async mcias-client crate; reqwest+rustls (no OpenSSL);
  thiserror MciasError enum; Arc<RwLock> token state; 22+1 tests pass;
  cargo clippy -D warnings clean
- clients/lisp/: ASDF mcias-client; dexador HTTP, yason JSON; mcias-error
  condition hierarchy; Hunchentoot mock-dispatcher; 37 fiveam checks pass
  on SBCL 2.6.1; yason boolean normalisation in validate-token
- clients/python/: mcias_client package (Python 3.11+); httpx sync;
  py.typed; dataclasses; 32 pytest tests; mypy --strict + ruff clean
- test/mock/mockserver.go: in-memory mock server for Go client tests
- ARCHITECTURE.md §19: updated per-language notes to match implementation
- PROGRESS.md: Phase 9 marked complete
- .gitignore: exclude clients/rust/target/, python .venv, .pytest_cache,
  .fasl files
Security: token never logged or exposed in error messages in any library;
TLS enforced in all four languages; token stored under lock/mutex/RwLock
2026-03-11 16:38:32 -07:00

6.5 KiB
Raw Blame History

MCIAS — Metacircular Identity and Access System

MCIAS is a self-hosted SSO and IAM service for personal projects. It provides authentication (JWT/Ed25519), account management, TOTP, and Postgres credential storage over a REST API (HTTPS) and a gRPC API (TLS).

See ARCHITECTURE.md for the technical design and PROJECT_PLAN.md for the implementation roadmap.


Quick Start

Option A: Install from source

Prerequisites: Go 1.26+, a C compiler (required by modernc.org/sqlite).

git clone https://git.wntrmute.dev/kyle/mcias
cd mcias
make build        # produces bin/mciassrv, other binaries
sudo make install

Option B: Docker

docker build -t mcias:latest .
# or
make docker       # tags mcias:<git-describe>

See Deploying with Docker below.


First-Run Setup

1. Generate a TLS certificate

Option A: Using the cert tool

Install the cert tool:

go install github.com/kisom/cert@latest

Create a certificate request configuration file:

cat > /tmp/request.yaml << EOF
subject:
  common_name: auth.example.com
hosts:
  - auth.example.com
  - localhost
key:
  algo: ecdsa
  size: 521
ca:
  expiry: 87600h  # 10 years
EOF

Generate the certificate:

cert genkey -a ec -s 521 > /etc/mcias/server.key
cert selfsign -p /etc/mcias/server.key -f /tmp/request.yaml > /etc/mcias/server.crt
chmod 0640 /etc/mcias/server.key
chown root:mcias /etc/mcias/server.key
rm /tmp/request.yaml

Option B: Using openssl

openssl req -x509 -newkey ed25519 -days 3650 \
  -keyout /etc/mcias/server.key \
  -out    /etc/mcias/server.crt \
  -subj   "/CN=auth.example.com" \
  -nodes
chmod 0640 /etc/mcias/server.key
chown root:mcias /etc/mcias/server.key

2. Configure the server

cp dist/mcias.conf.example /etc/mcias/mcias.conf
$EDITOR /etc/mcias/mcias.conf
chmod 0640 /etc/mcias/mcias.conf
chown root:mcias /etc/mcias/mcias.conf

Minimum required fields:

[server]
listen_addr = "0.0.0.0:8443"
tls_cert    = "/etc/mcias/server.crt"
tls_key     = "/etc/mcias/server.key"

[database]
path = "/var/lib/mcias/mcias.db"

[tokens]
issuer = "https://auth.example.com"

[master_key]
passphrase_env = "MCIAS_MASTER_PASSPHRASE"

See dist/mcias.conf.example for the fully-commented reference configuration. For local development, use dist/mcias-dev.conf.example.

3. Set the master key passphrase

cp dist/mcias.env.example /etc/mcias/env
$EDITOR /etc/mcias/env      # replace the placeholder passphrase
chmod 0640 /etc/mcias/env
chown root:mcias /etc/mcias/env

Important: Back up the passphrase to a secure offline location. Losing it means losing access to all encrypted data in the database.

4. Create the first admin account

export MCIAS_MASTER_PASSPHRASE=your-passphrase

mciasdb --config /etc/mcias/mcias.conf account create \
  --username admin --type human
mciasdb --config /etc/mcias/mcias.conf account set-password --id <UUID>
mciasdb --config /etc/mcias/mcias.conf role grant --id <UUID> --role admin

5. Start the server

# systemd
systemctl enable --now mcias

# manual
MCIAS_MASTER_PASSPHRASE=your-passphrase mciassrv -config /etc/mcias/mcias.conf

6. Verify

curl -k https://localhost:8443/v1/health
# {"status":"ok"}

Building

make build      # compile all binaries to bin/
make test       # go test -race ./...
make lint       # golangci-lint run ./...
make generate   # regenerate protobuf stubs (requires protoc)
make man        # build compressed man pages
make clean      # remove bin/ and generated artifacts
make dist       # cross-compiled tarballs for linux/amd64 and linux/arm64
make docker     # build Docker image mcias:<version>

Admin CLI (mciasctl)

TOKEN=$(curl -sk https://localhost:8443/v1/auth/login \
  -d '{"username":"admin","password":"..."}' | jq -r .token)
export MCIAS_TOKEN=$token

mciasctl -server https://localhost:8443 account list
mciasctl account create -username alice -password s3cr3t
mciasctl role set -id $UUID -roles admin
mciasctl token issue -id $SYSTEM_UUID
mciasctl pgcreds set -id $UUID -host db.example.com -port 5432 \
  -db mydb -user myuser -password mypassword

See man mciasctl for the full reference.


Database Maintenance Tool (mciasdb)

export MCIAS_MASTER_PASSPHRASE=your-passphrase
CONF<<3C>--config /etc/mcias/mcias.conf

mciasdb $CONF schema verify
mciasdb $CONF account list
mciasdb $CONF account set-password --id $UUID
mciasdb $CONF role grant --id $UUID --role admin
mciasdb $CONF prune tokens
mciasdb $CONF audit tail --n 50
mciasdb $CONF audit query --account $UUID --json

See man mciasdb for the full reference, including the trust model and safety warnings.


gRPC Interface

Enable the gRPC listener in config:

[server]
listen_addr = "0.0.0.0:8443"
grpc_addr   = "0.0.0.0:9443"
tls_cert    = "/etc/mcias/server.crt"
tls_key     = "/etc/mcias/server.key"

Using mciasgrpcctl:

export MCIAS_TOKEN=$ADMIN_JWT
mciasgrpcctl -server auth.example.com:9443 -cacert /etc/mcias/server.crt health
mciasgrpcctl account list

Using grpcurl:

grpcurl -cacert /etc/mcias/server.crt \
  -H "authorization: Bearer $ADMIN_JWT" \
  auth.example.com:9443 \
  mcias.v1.AdminService/Health

See man mciasgrpcctl and ARCHITECTURE.md §17.


Deploying with Docker

make docker

mkdir -p /srv/mcias/config
cp dist/mcias.conf.docker.example /srv/mcias/config/mcias.conf
$EDITOR /srv/mcias/config/mcias.conf

docker run -d \
  --name mcias \
  -v /srv/mcias/config:/etc/mcias:ro \
  -v mcias-data:/data \
  -e MCIAS_MASTER_PASSPHRASE=your-passphrase \
  -p 8443:8443 \
  -p 9443:9443 \
  mcias:latest

curl -k https://localhost:8443/v1/health

The container runs as uid 10001 (mcias) with no capabilities. TLS termination happens inside the container. See dist/mcias.conf.docker.example for the config template.


Man Pages

man mciassrv      # server reference
man mciasctl      # admin CLI (REST)
man mciasdb       # database maintenance tool
man mciasgrpcctl  # gRPC admin CLI

Security Notes

  • JWTs signed with Ed25519 (EdDSA); alg header validated before processing to defeat algorithm confusion attacks.
  • Passwords hashed with Argon2id at OWASP 2023 minimum parameters.
  • All secret material encrypted at rest with AES-256-GCM using the master key.
  • Credential fields never appear in any API response.
  • TLS 1.2 minimum protocol version.

See ARCHITECTURE.md §2-³3 for the full security model.