A Go microservice with OPA (Open Policy Agent) integration implementing NGAC-style authorization policies. The Go app acts as a Policy Enforcement Point (PEP), OPA serves as the Policy Decision Point (PDP), and simple Policy Information Point (PIP) stubs fetch attributes.
- Go App (PEP): Runs on port 8080, enforces authorization decisions
- OPA (PDP): Runs on port 8181, evaluates NGAC-style policies
- Policies: Deny-overrides, condition predicates, and obligations
- Hot Reload: OPA watches for policy changes and reloads automatically
- NGAC-style Policies: Deny-overrides with condition predicates
- Obligations: Masking, logging, and alerting obligations
- Fast Developer Loop: Hot-reload Rego policies,
opa test
,make dev
- Docker Compose: Complete development environment
- Comprehensive Testing: Go tests + OPA policy tests
- Docker and Docker Compose
- Go 1.23+ (for local development)
-
Start the complete stack:
make dev
-
Test authorization endpoints:
make test-auth
-
Run OPA policy tests:
make opa-test
Test the masking obligation with different user roles:
# Regular user (sensitive fields masked)
curl -H "X-User-ID: user1" \
-H "X-User-Role: user" \
-H "X-Resource-Owner: user1" \
-H "X-Resource-Type: normal" \
http://localhost:8080/api/v1/users/user123/data
# Admin user (no masking)
curl -H "X-User-ID: admin1" \
-H "X-User-Role: admin" \
-H "X-Resource-Owner: admin1" \
-H "X-Resource-Type: normal" \
http://localhost:8080/api/v1/users/user123/data
# Sensitive resource (access denied)
curl -H "X-User-ID: user1" \
-H "X-User-Role: user" \
-H "X-Resource-Owner: user1" \
-H "X-Resource-Type: sensitive" \
http://localhost:8080/api/v1/users/user123/data
make dev
- Start development environment with Docker Composemake build
- Build the Go applicationmake test
- Run Go testsmake opa-test
- Run OPA policy testsmake lint
- Run lintermake clean
- Clean build artifacts and stop containersmake deps
- Install dependenciesmake run-local
- Run application locally (without Docker)make test-auth
- Test authorization endpoints with curlmake help
- Show all available targets
├── cmd/ # Application entrypoints
├── internal/
│ ├── authz/ # OPA integration middleware
│ │ ├── client.go # OPA HTTP client
│ │ └── middleware.go # Gin authorization middleware
│ └── ... # Other internal packages
├── pkg/
│ └── server/ # HTTP server with authz integration
├── opa/
│ ├── config.yaml # OPA configuration
│ └── policies/
│ ├── authz.rego # NGAC-style authorization policies
│ └── authz_test.rego # Policy tests
├── docker-compose.yml # Development environment
└── Makefile # Development commands
The authorization system implements Next Generation Access Control (NGAC) principles:
- Deny-overrides: Prohibitions take precedence over permissions
- Condition Predicates: Named conditions evaluated by reference
- Obligations: Actions returned with authorization decisions
# Main decision with deny-overrides
decision := "deny" if has_prohibition else "allow" if has_permission else "deny"
# Obligations from matching rules
obligations := [obligation | ...]
# Condition evaluation
conditions_met := {name: condition_result | ...}
- Masking:
{"type": "mask", "fields": ["ssn", "credit_card"]}
- Logging:
{"type": "log", "message": "access granted"}
- Alerting:
{"type": "alert", "message": "sensitive data access"}
OPA_URL
: OPA server URL (default:http://localhost:8181
)
The OPA server is configured via opa/config.yaml
:
- Decision logs enabled to console
- Policies loaded from mounted volume
- Watch mode for hot reload
- Edit policies in
opa/policies/authz.rego
- Test policies with
make opa-test
- Start environment with
make dev
- Test endpoints with
make test-auth
- Iterate - OPA hot-reloads policy changes automatically
GET /healthz
- Health checkGET /readyz
- Readiness checkGET /metrics
- Prometheus metrics
GET /api/v1/users/:resource_id/data
- User data with masking obligations
X-User-ID
: User identifierX-User-Role
: User role (admin, user, etc.)X-Resource-Owner
: Resource owner IDX-Resource-Type
: Resource type (normal, sensitive, etc.)