devedge-sdk

module
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 19, 2026 License: Apache-2.0

README ΒΆ

devedge-sdk

CI Docs Go Reference

A clean, pluggable Go framework for building Infoblox services. Declare authorization and secrets once in your proto β€” the framework enforces them everywhere, refuses to boot if any served method is undeclared, and never lets a secret field leak.

It is the runtime companion to devedge: devedge is the dev- and deploy-time edge; devedge-sdk is the runtime library that production services import.

Status: early. APIs will change. Pin a version and read the changelog/releases before upgrading.

πŸ“š Documentation

Full docs live at infobloxopen.github.io/devedge-sdk. Start here:

Section What's there
πŸš€ Getting Started Install the SDK and stand up a service in five minutes (Quickstart).
πŸ’‘ Concepts The architecture, the annotation contract, and the tenant-isolation model.
πŸ“– Guides Task how-tos: define a service, model a resource, pick a storage shape, handle secrets, run seccheck, set up Vault.
πŸ“‘ Reference Per-package API reference and codegen-plugin docs.
πŸŽ“ Tutorial Build the API Key Manager service end to end.

Why devedge-sdk

  • Declare authz once, enforced everywhere. Annotate an RPC with (infoblox.authz.v1.rule). The framework builds the per-method rule table, enforces it fail-closed, and refuses to boot if any served method is undeclared.
  • Secret fields encrypted at rest. Mark a field secret in proto; generated code hashes it for lookup and encrypts the ciphertext β€” AES-256-GCM in dev, HashiCorp Vault Transit in prod. Plaintext is never persisted and never returned.
  • Cross-account tenant isolation. Every query is scoped by account-id at the storage layer (GORM and ent). One principal can never see another's resources β€” and seccheck proves it in CI.
  • Batteries-included gRPC server. server.New assembles the interceptor chain β€” request-ID, error mapping, tenant-ID, fail-closed authz, field-mask validation, ETag/412 preconditions β€” plus an optional HTTP/JSON gateway.
  • Codegen from your proto. protoc-gen-svc scaffolds the service, protoc-gen-storage emits a GORM repository, protoc-gen-ent emits an ent schema. The proto is the single source of truth.
  • Pluggable, dependency-light core. Core packages depend only on the standard library β€” no ORM, no policy-engine dependency. Every seam ships a dev default and swaps for a production backend without touching service code.

Install

go get github.com/infobloxopen/devedge-sdk@latest

Install the codegen plugins onto your PATH so buf generate can invoke them:

go install github.com/infobloxopen/devedge-sdk/cmd/protoc-gen-svc@latest
go install github.com/infobloxopen/devedge-sdk/cmd/protoc-gen-storage@latest
go install github.com/infobloxopen/devedge-sdk/cmd/protoc-gen-ent@latest
go install github.com/infobloxopen/devedge-sdk/cmd/protoc-gen-devedge-authz@latest

Requires Go 1.25+ and buf. Postgres and Vault are only needed for the production storage and secret backends β€” the in-memory store and dev encryptor run in-process. Full prerequisites: Installation.

Quickstart

1. Declare each RPC's authz requirement in proto β€” verb + resource is all a method needs:

service WidgetService {
  rpc GetWidget(GetWidgetRequest) returns (Widget) {
    option (infoblox.authz.v1.rule) = {verb: "get", resource: "widget:{id}"};
  }
  rpc CreateWidget(CreateWidgetRequest) returns (Widget) {
    option (infoblox.authz.v1.rule) = {verb: "create", resource: "widget"};
  }
}

2. Generate (buf generate) β€” protoc-gen-devedge-authz emits a WidgetServiceAuthzRules table next to the .pb.go.

3. Wire the server. The Authorizer defaults to default-deny, so every call is denied until you grant something β€” fail-closed by construction:

srv, err := server.New(server.Config{
    GRPCAddr: ":9090",
    HTTPAddr: ":8080", // optional HTTP/JSON gateway; omit to run gRPC-only
    Rules:    widgetv1.WidgetServiceAuthzRules, // generated in step 2

    // Dev decision point β€” grant group:admin everything. Swap for an
    // OPA/Cedar/remote Authorizer in production; nothing else changes.
    Authorizer: authz.NewDevAuthorizer(authz.Grant{
        Tenant: "t1", Subjects: []string{"group:admin"},
        Verbs: []authz.Verb{"*"}, Resource: "*",
    }),
    // Derive the principal from request metadata (account-id β†’ tenant, groups β†’
    // group:<name>). Use a verified-token func in production.
    PrincipalFunc: grpcauthz.DevPrincipalFunc(),
})
if err != nil {
    log.Fatal(err)
}

widgetv1.RegisterWidgetServiceServer(srv.GRPCServer(), &widgetServer{})
log.Fatal(srv.Serve(ctx)) // blocks until ctx is cancelled

The chain server.New builds, outermost first:

RequestID β†’ ErrorMapper β†’ TenantID β†’ grpcauthz (fail-closed) β†’ FieldMask β†’ ETag/412 β†’ ReadMask β†’ ValidateOnly β†’ Deduplicate

β†’ Full walkthrough with tests: Quickstart.

Packages

Package What it provides
authz Engine-neutral model: Principal, Resource, Verb, AccessRequest, Decision, the pluggable Authorizer, and DevAuthorizer (in-process, default-deny).
authz/grpcauthz Fail-closed gRPC interceptor + boot gate. Rough-compatible with atlas-authz-middleware/grpc_opa (COMPAT.md).
authz/catalog Builds the permission catalog (per resource: verbs, endpoints, View/Manage groups) from declared rules.
authz/authzpb Reflection-based rule extractor β€” reads (infoblox.authz.v1.rule) off linked descriptors, no generated file.
server Server lifecycle: gRPC + optional HTTP/JSON gateway, interceptor chain auto-wired.
middleware The interceptors: RequestID, TenantID, FieldMask, ErrorMapper, ValidateOnly, Dedup, and etag.
secret Secret-at-rest Encryptor: AES-256-GCM + HMAC for dev, HashiCorp Vault Transit for prod.
persistence ORM-free Repository[T,K] seam, in-memory dev store, DSN hotload, filtering. Storage shape is per-service (SHAPES.md).
lro AIP-151/152 long-running operations: Store, Manager, Operation, cancellation.
seccheck Static + dynamic security assertions you run in CI (see Security model).

Full API reference for every package: Reference docs β†—.

Codegen plugins

The proto is the single source of truth; make generate (or buf generate) drives these:

Plugin (cmd/…) Output
protoc-gen-svc service scaffold (*.svc.go)
protoc-gen-storage GORM-backed Repository (*.storage.go)
protoc-gen-ent ent schema (ent/schema/*.go)
protoc-gen-devedge-authz the <Service>AuthzRules []MethodRule table (*.authz.go)

Security model

Authorization is fail-closed: an undeclared or ungranted method is denied with no code required. The seccheck package turns the model's invariants into assertions you run in CI (make security-check):

Invariant Asserted by
Every RPC has (infoblox.authz.v1.rule) or public: true AssertRulesComplete
No secret-annotated field value in a read/list response AssertNoSecretFieldsLeaked
Unknown principal β†’ PermissionDenied on all RPCs AssertUnknownPrincipalDenied
Account A cannot read Account B's resources AssertCrossAccountIsolation
Errors never leak SQL, stack traces, or hostnames AssertErrorMessagesClean

β†’ Security Check guide.

Swapping the decision point

WithAuthorizer / Config.Authorizer takes any authz.Authorizer. To target a production engine, implement the one-method interface β€” an OPA-backed authorizer calling a sidecar, a Cedar/OpenFGA client, a remote PDP β€” and pass it in. Nothing else in the service changes. The SDK core stays engine-neutral: no OPA, no ORM, no policy-model types β€” those belong in adapters built on the SDK.

Building from source

make build            # go build ./...
make test             # unit tests (root module)
make vet              # go vet ./...
make lint             # golangci-lint if installed, else go vet
make generate         # rebuild plugins + regenerate after any .proto change
make security-check   # run the seccheck assertions

testdata/toy, testdata/apikey, and testdata/fleet are separate modules with their own integration tests β€” run them with cd testdata/<name> && go test ./.... See AGENTS.md for the full contributor guide.

License

Apache-2.0. See LICENSE.

Directories ΒΆ

Path Synopsis
authn
oidc module
Package authz defines a clean, transport-neutral, pluggable authorization model for Infoblox services.
Package authz defines a clean, transport-neutral, pluggable authorization model for Infoblox services.
authzpb
Package authzpb extracts declared authorization rules from compiled protobuf descriptors.
Package authzpb extracts declared authorization rules from compiled protobuf descriptors.
catalog
Package catalog turns declared method rules into the permission catalog β€” the code-backed source of truth that the API enforces, that a portal can render as a role-creation UI, and that a downstream engine/policy generator can consume.
Package catalog turns declared method rules into the permission catalog β€” the code-backed source of truth that the API enforces, that a portal can render as a role-creation UI, and that a downstream engine/policy generator can consume.
grpcauthz
Package grpcauthz wires the SDK's pluggable authz.Authorizer into gRPC as a fail-closed server interceptor.
Package grpcauthz wires the SDK's pluggable authz.Authorizer into gRPC as a fail-closed server interceptor.
cmd module
devedge-sdk command
Command devedge-sdk is the devedge-sdk developer CLI.
Command devedge-sdk is the devedge-sdk developer CLI.
devedge-sdk/internal/scaffold
Package scaffold renders and assembles an apx-native devedge-sdk service project from a service name + one resource.
Package scaffold renders and assembles an apx-native devedge-sdk service project from a service name + one resource.
internal/storagegen
Package storagegen holds engine-neutral helpers shared by the storage code generators (protoc-gen-ent and, per F027, protoc-gen-storage).
Package storagegen holds engine-neutral helpers shared by the storage code generators (protoc-gen-ent and, per F027, protoc-gen-storage).
protoc-gen-devedge-authz command
Command protoc-gen-devedge-authz is a protoc/buf plugin that emits, for every service method carrying the (infoblox.authz.v1.rule) annotation, a compile-time []authz.MethodRule table β€” the codegen variant of the authz/authzpb reflection extractor.
Command protoc-gen-devedge-authz is a protoc/buf plugin that emits, for every service method carrying the (infoblox.authz.v1.rule) annotation, a compile-time []authz.MethodRule table β€” the codegen variant of the authz/authzpb reflection extractor.
protoc-gen-ent command
Command protoc-gen-ent is a protoc/buf plugin that emits, for every proto resource message, an ent schema definition (ent/schema/<snake_resource>.go) plus an ent/generate.go that drives entc code generation:
Command protoc-gen-ent is a protoc/buf plugin that emits, for every proto resource message, an ent schema definition (ent/schema/<snake_resource>.go) plus an ent/generate.go that drives entc code generation:
protoc-gen-storage command
Command protoc-gen-storage is a protoc/buf plugin that emits, for every proto message, a GORM-backed repository (.storage.go) implementing persistence.Repository[*pb.<Message>, string]:
Command protoc-gen-storage is a protoc/buf plugin that emits, for every proto message, a GORM-backed repository (.storage.go) implementing persistence.Repository[*pb.<Message>, string]:
protoc-gen-svc command
Command protoc-gen-svc is a protoc/buf plugin that emits, for every proto service, an application-layer handler interface (.svc.go) with:
Command protoc-gen-svc is a protoc/buf plugin that emits, for every proto service, an application-layer handler interface (.svc.go) with:
security-check command
Command security-check performs a static cross-reference between a compiled proto FileDescriptorSet and an authz rules JSON file.
Command security-check performs a static cross-reference between a compiled proto FileDescriptorSet and an authz rules JSON file.
config
koanf module
events
kafkabus module
internal
Package lro implements the AIP-151 Long-Running Operation pattern.
Package lro implements the AIP-151 Long-Running Operation pattern.
etag
Package etag provides gRPC middleware for HTTP ETag / conditional-request semantics: it reads the If-Match precondition from incoming metadata and writes the ETag for the response to the outgoing trailer.
Package etag provides gRPC middleware for HTTP ETag / conditional-request semantics: it reads the If-Match precondition from incoming metadata and writes the ETag for the response to the outgoing trailer.
redact
Package redact provides proto-reflection-based helpers that replace (infoblox.field.v1.opts).secret = true field values with "[REDACTED]" before logging.
Package redact provides proto-reflection-based helpers that replace (infoblox.field.v1.opts).secret = true field values with "[REDACTED]" before logging.
observability
otel module
Package persistence provides connection and storage helpers for Infoblox services.
Package persistence provides connection and storage helpers for Infoblox services.
filter
Package filter implements an AIP-160 subset parser for list filter expressions and an AIP-132 parser for order_by strings.
Package filter implements an AIP-160 subset parser for list filter expressions and an AIP-132 parser for order_by strings.
resourcename
Package resourcename provides AIP-122 resource name formatting and parsing.
Package resourcename provides AIP-122 resource name formatting and parsing.
gormtx module
migrate module
proto
Package server provides a batteries-included gRPC server builder for Infoblox services.
Package server provides a batteries-included gRPC server builder for Infoblox services.
Package types provides reusable, ORM-agnostic field types for Infoblox resources.
Package types provides reusable, ORM-agnostic field types for Infoblox resources.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL