- proto/mcias/v1/: AdminService, AuthService, TokenService, AccountService, CredentialService; generated Go stubs in gen/ - internal/grpcserver: full handler implementations sharing all business logic (auth, token, db, crypto) with REST server; interceptor chain: logging -> auth (JWT alg-first + revocation) -> rate-limit (token bucket, 10 req/s, burst 10, per-IP) - internal/config: optional grpc_addr field in [server] section - cmd/mciassrv: dual-stack startup; gRPC/TLS listener on grpc_addr when configured; graceful shutdown of both servers in 15s window - cmd/mciasgrpcctl: companion gRPC CLI mirroring mciasctl commands (health, pubkey, account, role, token, pgcreds) using TLS with optional custom CA cert - internal/grpcserver/grpcserver_test.go: 20 tests via bufconn covering public RPCs, auth interceptor (no token, invalid, revoked -> 401), non-admin -> 403, Login/Logout/RenewToken/ValidateToken flows, AccountService CRUD, SetPGCreds/GetPGCreds AES-GCM round-trip, credential fields absent from all responses Security: JWT validation path identical to REST: alg header checked before signature, alg:none rejected, revocation table checked after sig. Authorization metadata value never logged by any interceptor. Credential fields (PasswordHash, TOTPSecret*, PGPassword) absent from all proto response messages — enforced by proto design and confirmed by test TestCredentialFieldsAbsentFromAccountResponse. Login dummy-Argon2 timing guard preserves timing uniformity for unknown users (same as REST handleLogin). TLS required at listener level; cmd/mciassrv uses credentials.NewServerTLSFromFile; no h2c offered. 137 tests pass, zero race conditions (go test -race ./...)
46 lines
1.4 KiB
Protocol Buffer
46 lines
1.4 KiB
Protocol Buffer
// Common message types shared across MCIAS gRPC services.
|
|
syntax = "proto3";
|
|
|
|
package mcias.v1;
|
|
|
|
option go_package = "git.wntrmute.dev/kyle/mcias/gen/mcias/v1;mciasv1";
|
|
|
|
import "google/protobuf/timestamp.proto";
|
|
|
|
// Account represents a user or service identity. Credential fields
|
|
// (password_hash, totp_secret) are never included in any response.
|
|
message Account {
|
|
string id = 1; // UUID
|
|
string username = 2;
|
|
string account_type = 3; // "human" or "system"
|
|
string status = 4; // "active", "inactive", or "deleted"
|
|
bool totp_enabled = 5;
|
|
google.protobuf.Timestamp created_at = 6;
|
|
google.protobuf.Timestamp updated_at = 7;
|
|
}
|
|
|
|
// TokenInfo describes an issued token by its JTI (never the raw value).
|
|
message TokenInfo {
|
|
string jti = 1;
|
|
google.protobuf.Timestamp issued_at = 2;
|
|
google.protobuf.Timestamp expires_at = 3;
|
|
google.protobuf.Timestamp revoked_at = 4; // zero if not revoked
|
|
}
|
|
|
|
// PGCreds holds Postgres connection details. Password is decrypted and
|
|
// present only when explicitly requested via GetPGCreds; it is never
|
|
// included in list responses.
|
|
message PGCreds {
|
|
string host = 1;
|
|
string database = 2;
|
|
string username = 3;
|
|
string password = 4; // security: only populated on explicit get
|
|
int32 port = 5;
|
|
}
|
|
|
|
// Error is the canonical error detail embedded in gRPC status details.
|
|
message Error {
|
|
string message = 1;
|
|
string code = 2;
|
|
}
|