Kyle Isom 7ede54afb2 grpcctl: add auth login and policy commands
- Add auth/login and auth/logout to mciasgrpcctl, calling
  the existing AuthService.Login/Logout RPCs; password is
  always prompted interactively (term.ReadPassword), never
  accepted as a flag, raw bytes zeroed after use
- Add proto/mcias/v1/policy.proto with PolicyService
  (List, Create, Get, Update, Delete policy rules)
- Regenerate gen/mcias/v1/ stubs to include policy
- Implement internal/grpcserver/policyservice.go delegating
  to the same db layer as the REST policy handlers
- Register PolicyService in grpcserver.go
- Add policy list/create/get/update/delete to mciasgrpcctl
- Update mciasgrpcctl man page with new commands

Security: auth login uses the same interactive password
prompt pattern as mciasctl; password never appears in
process args, shell history, or logs; raw bytes zeroed
after string conversion (same as REST CLI and REST server).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 20:51:10 -07:00

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), a gRPC API (TLS), and an HTMX-based web management UI.

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://mcias.metacircular.net: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://mcias.metacircular.net:8443/v1/auth/login \
  -d '{"username":"admin","password":"..."}' | jq -r .token)
export MCIAS_TOKEN=$TOKEN

mciasctl -server https://mcias.metacircular.net:8443 account list
mciasctl account create -username alice          # password prompted interactively
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="--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.


Web Management UI

mciassrv includes a built-in web interface for day-to-day administration. After starting the server, navigate to https://mcias.metacircular.net:8443/login and log in with an admin account.

The UI provides:

  • Dashboard — account summary overview
  • Accounts — list, create, update, delete accounts; manage roles and tags
  • PG Credentials — view, create, and manage Postgres credential access grants
  • Policies — create and manage ABAC policy rules
  • Audit — browse the audit log

Sessions use HttpOnly; Secure; SameSite=Strict cookies with CSRF protection. See ARCHITECTURE.md §8 (Web Management UI) for design details.


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://mcias.metacircular.net: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 §23 for the full security model.

Description
The Metacircular Identity and Access System (MCIAS) provides standard tools for user and access management among metacircular and wntrmute systems.
Readme 521 MiB
Languages
Go 78.7%
Rust 5.9%
HTML 4.8%
Common Lisp 4.6%
Python 4.5%
Other 1.5%