Skip to content

About

SDK reference implementation for Go

Resources

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

Kessel SDK for Go

OpenSSF Scorecard

The official Go SDK for the Kessel inventory and authorization services. This SDK provides a type-safe gRPC client for managing resources, checking permissions, and interacting with RBAC workspaces.

Features

  • gRPC client support -- High-performance gRPC communication via the unified KesselInventoryService
  • Type-safe API -- Generated from protobuf definitions at buf.build/project-kessel/inventory-api
  • Fluent ClientBuilder -- Construct clients with a chainable builder pattern supporting insecure, TLS, and OAuth2 modes
  • RBAC utilities -- REST workspace client and helper functions for RBAC resource/subject references
  • OIDC discovery -- Built-in OAuth2 client credentials flow with automatic token caching

Installation

go get github.com/project-kessel/kessel-sdk-go

Quick Start

Insecure (local development)

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/project-kessel/kessel-sdk-go/kessel/inventory/v1beta2"
)

func main() {
	ctx := context.Background()

	inventoryClient, conn, err := v1beta2.NewClientBuilder("localhost:9000").
		Insecure().
		Build()
	if err != nil {
		log.Fatal("Failed to create gRPC client:", err)
	}
	defer conn.Close()

	response, err := inventoryClient.Check(ctx, &v1beta2.CheckRequest{
		Object: &v1beta2.ResourceReference{
			ResourceType: "host",
			ResourceId:   "server-123",
			Reporter:     &v1beta2.ReporterReference{Type: "HBI"},
		},
		Relation: "member",
		Subject: &v1beta2.SubjectReference{
			Resource: &v1beta2.ResourceReference{
				ResourceType: "user",
				ResourceId:   "alice",
			},
		},
	})
	if err != nil {
		log.Fatal("Check failed:", err)
	}

	fmt.Printf("Check result: %v\n", response.Allowed)
}

With OAuth2 authentication

inventoryClient, conn, err := v1beta2.NewClientBuilder(endpoint).
	OAuth2ClientAuthenticated(&oauthCredentials, nil).
	Build()

Or bring your own PerRPCCredentials:

inventoryClient, conn, err := v1beta2.NewClientBuilder(endpoint).
	Authenticated(kesselgrpc.OAuth2CallCredentials(&oauthCredentials), nil).
	Build()

See the examples section for complete working code.

ClientBuilder modes

Method Transport Auth Use case
.Insecure() Plaintext None Local development
.Unauthenticated(tlsCreds) TLS None TLS without auth
.Authenticated(perRPC, tlsCreds) TLS Custom PerRPCCredentials Bring-your-own auth
.OAuth2ClientAuthenticated(creds, tlsCreds) TLS Built-in OAuth2 Client credentials flow

Pass nil for tlsCreds to use the default TLS configuration.

gRPC keepalive

Every client built with ClientBuilder.Build() uses a 45-second keepalive interval, a 10-second acknowledgment timeout, and permits keepalive pings when no RPC is active. No keepalive call is needed for these defaults. The v1beta2 builder exposes typed functional options for overrides; each option changes only its specified value, so omitted values retain their current setting and an explicit false is honored:

inventoryClient, conn, err := v1beta2.NewClientBuilder(endpoint).
	Keepalive(
		v1beta2.WithKeepaliveInterval(60*time.Second),
		v1beta2.WithKeepaliveTimeout(15*time.Second),
		v1beta2.WithKeepalivePermitWithoutCalls(false),
	).
	Insecure().
	Build()

Keepalive durations must be positive; Build() returns an error for zero or negative values. grpc-go clamps configured intervals below 10 seconds to 10 seconds. Keepalive is transport-level ping behavior, not an application health check, retry mechanism, or guarantee against server or load-balancer idle timeouts. Servers and gateways must permit the configured ping cadence, including pings while idle, or may close the connection with a GOAWAY carrying too_many_pings. See the configuration-only keepalive example; it builds clients with both defaults and overrides without making an RPC.

Error Handling

The SDK uses standard gRPC status codes:

response, err := inventoryClient.Check(ctx, checkRequest)
if err != nil {
	if st, ok := status.FromError(err); ok {
		switch st.Code() {
		case codes.Unavailable:
			log.Fatal("Service unavailable:", err)
		case codes.PermissionDenied:
			log.Fatal("Permission denied:", err)
		default:
			log.Fatal("gRPC error:", err)
		}
	} else {
		log.Fatal("Unknown error:", err)
	}
}

Listing Workspaces

The ListWorkspaces helper automatically paginates through all workspaces a subject can access. Continuation tokens are handled internally.

import (
    v1beta2 "github.com/project-kessel/kessel-sdk-go/kessel/inventory/v1beta2"
    v2 "github.com/project-kessel/kessel-sdk-go/kessel/rbac/v2"
)

// Lazy iteration (constant memory)
for resp, err := range v2.ListWorkspaces(ctx, client, subject, "viewer", "") {
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(resp.Object.GetResourceId())
}

// Materialise into a slice
var all []*v1beta2.StreamedListObjectsResponse
for resp, err := range v2.ListWorkspaces(ctx, client, subject, "viewer", "") {
    if err != nil {
        log.Fatal(err)
    }
    all = append(all, resp)
}

See examples/rbac/list_workspaces.go for a complete working example.

Project Structure

kessel/
  auth/                    # OAuth2 client credentials, OIDC discovery, AuthRequest interface
  config/                  # CompatibilityConfig with functional options (legacy)
  grpc/                    # OAuth2 PerRPCCredentials wrapper for gRPC
  inventory/
    internal/builder/      # Generic ClientBuilder[C] (Go generics)
    v1/                    # Generated: health service only (stable)
    v1beta1/               # Generated: legacy per-resource-type services
    v1beta2/               # Generated: unified API + hand-written client_builder.go
  rbac/v2/                 # Hand-written: REST workspace client + v1beta2 utility constructors
examples/
  grpc/                    # gRPC client examples
  rbac/                    # RBAC workspace examples
  console/                 # Console identity examples
.github/workflows/         # CI: lint, build-test, buf-generate

Generated vs. hand-written code: All *.pb.go and *_grpc.pb.go files under kessel/inventory/ are generated by buf generate and must not be edited. Hand-written logic lives in kessel/auth/, kessel/config/, kessel/grpc/, kessel/inventory/internal/builder/, kessel/inventory/v1beta2/client_builder.go, kessel/rbac/v2/, and examples/.

API Version

Always use v1beta2 for new code. It provides the unified KesselInventoryService with Check, CheckBulk, ReportResource, DeleteResource, and more. The v1beta1 package is legacy and v1 contains only health endpoints.

Development

Prerequisites

  • Go 1.25 or later
  • Docker or Podman (for linting)
  • buf (for protobuf code generation)

Build, Test, and Lint

# Install dependencies
go mod download

# Run tests
make test

# Run tests with coverage report
make test-coverage

# Run linting (via Docker/Podman)
make lint

# Build all example binaries
make build

# Format code
make fmt

# Tidy modules
make mod-tidy

# Regenerate protobuf files from buf.build
make generate

Available Make Targets

Target Description
make test Run all tests (go test -v ./kessel/...)
make test-coverage Run tests and generate coverage.html
make lint Run golangci-lint via Docker/Podman
make build Compile example binaries into bin/
make generate Regenerate protobuf files with buf generate
make fmt Format Go code
make mod-tidy Run go mod tidy
make clean Remove build artifacts
make help Display all available targets

Examples

All examples are standalone package main binaries. Copy the .env.sample file to .env and fill in your values before running.

Inventory (gRPC)

Example File Description
Insecure client examples/grpc/insecure.go Connect without TLS for local development and perform a Check
Authenticated client examples/grpc/authenticated.go Connect with OIDC discovery and custom PerRPCCredentials via .Authenticated()
OAuth2 client examples/grpc/oauth2client_authenticated.go Connect with built-in OAuth2 flow via .OAuth2ClientAuthenticated()
Report resource examples/grpc/report_resource.go Report a resource with metadata, common, and reporter representations
Delete resource examples/grpc/delete_resource.go Delete a resource by reference
Bulk check examples/grpc/check_bulk.go Check multiple permission tuples in a single CheckBulk call
Keepalive examples/grpc/keepalive.go Build clients with default and overridden gRPC keepalive settings; no RPC is sent

RBAC (REST + gRPC)

Example File Description
Fetch workspace examples/rbac/fetch_workspace.go Fetch default and root workspaces via the REST API
List workspaces examples/rbac/list_workspaces.go List workspaces using gRPC with range-over-func iteration

Running examples

# Build all examples
make build

# Run an example
./bin/insecure-example
./bin/authenticated-example
./bin/oauth2client-authenticated-example
./bin/report-resource-example
./bin/delete-resource-example
./bin/check_bulk_example
./bin/keepalive-example
./bin/fetch_workspace
./bin/list_workspaces

Further Documentation

Document Description
AGENTS.md Onboarding guide for AI agents -- architecture, conventions, and pitfalls
kessel/auth/GUIDELINES.md OAuth2 client credentials, token caching, OIDC discovery
kessel/rbac/v2/GUIDELINES.md REST workspace client, gRPC iterator, utility constructors
kessel/inventory/internal/builder/GUIDELINES.md Generic ClientBuilder, auth modes, three-value return
examples/GUIDELINES.md Example binary conventions, env config, error handling

Release Instructions

This section provides step-by-step instructions for maintainers to release a new version of the Kessel SDK for Go.

Version Management

This project follows Semantic Versioning 2.0.0. Version numbers use the format MAJOR.MINOR.PATCH:

  • MAJOR: Increment for incompatible API changes
  • MINOR: Increment for backward-compatible functionality additions
  • PATCH: Increment for backward-compatible bug fixes

Note: SDK versions across different languages (Ruby, Python, Go, etc.) do not need to be synchronized. Each language SDK can evolve independently based on its specific requirements and release schedule.

Prerequisites for Release

  • Write access to the GitHub repository
  • Ensure quality checks are passing
  • Go 1.25 or higher
  • buf for protobuf/gRPC code generation:
    # On macOS
    brew install bufbuild/buf/buf
    
    # On Linux
    curl -sSL "https://github.com/bufbuild/buf/releases/latest/download/buf-$(uname -s)-$(uname -m)" -o "/usr/local/bin/buf" && chmod +x "/usr/local/bin/buf"

Release Process

  1. Determine the version

Check existing tags (e.g. on GitHub or locally after git fetch --tags), choose the next version using semantic versioning (see Version Management above), then set VERSION for the steps below:

export VERSION=X.Y.Z
echo "Releasing version: v${VERSION}"
  1. Update Dependencies (if needed)
# Regenerate gRPC code if there are updates to the Kessel Inventory API
make generate
  1. Run Quality Checks
# Run linting
make lint

# Run tests
make test

# Build examples
make build
  1. Commit and push (if needed)

If make generate or other changes produced diffs, commit and push them before tagging:

git add .
git commit -m "chore: regenerate protobuf code"
git push origin main
  1. Tag the Release
git tag -a v${VERSION} -m "Release version ${VERSION}"
git push origin v${VERSION}
  1. Create GitHub Release
gh release create v${VERSION} --title "v${VERSION}" --generate-notes

Or manually:

  • Go to the GitHub Releases page
  • Click "Create a new release"
  • Select the tag you just created
  • Publish the release

After the tag is published, users can install that version with:

go get github.com/project-kessel/kessel-sdk-go@v${VERSION}

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

About

SDK reference implementation for Go

Resources

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages