authz

package module
v0.0.0-...-f8a288c Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2023 License: Apache-2.0 Imports: 9 Imported by: 1

README

gRPC Authorization

This package provides the ability to add authorization to a gRPC server. It is made to be coupled with github.com/grpc-ecosystem/go-grpc-middleware/auth.

Background

Under the hood it is using https://github.com/cristalhq/jwt for all JWT functionality. The main reason this library was chosen was because jwt.io reports it as supporting all algorithms and validations.

Currently, in this repo, the following algorithms are supported.

  • HS256, HS384, HS512
  • RS256, RS384, RS512

Usage

This example will validate that the JWT was signed by the given key and not expired.

package main

import (
    "net"
    "os"

    jwt "github.com/cristalhq/jwt/v3"
    grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
    "github.com/packethost/pkg/grpc/authz"
    "google.golang.org/grpc"
)

var (
    hsKey = []byte("supersecret")
)

func main() {
    // create a Config
    // at a minimum an algorithm, scope mapping (only the methods defined here will protected), and key are needed
    config := authz.NewConfig(
        jwt.HS256,
        map[string][]string{
            "/github.com.tinkerbell.pbnj.api.v1.Machine/Power": {},
        },
        authz.WithHSKey(hsKey),
        
    )

    // the AuthFunc method can then be used with as middleware with a gRPC server
    grpcServer := grpc.NewServer(
        grpc_middleware.WithUnaryServerChain(
            grpc_auth.UnaryServerInterceptor(config.AuthFunc),
        ),
    )

    listen, err := net.Listen("tcp", ":50051")
    if err != nil {
        panic(err)
    }

    if err := grpcServer.Serve(listen); err != nil {
        os.Exit(1)
    }
}

This example will validate that the JWT was signed by the given key, not expired, and custom scopes match the called method.

package main

import (
    "encoding/json"
    "net"
    "os"

    jwt "github.com/cristalhq/jwt/v3"
    grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
    "github.com/packethost/pkg/grpc/authz"
    "google.golang.org/grpc"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"
)

var (
    hsKey = []byte("supersecret")
)

func main() {
    // create a func for validating Scopes
    scopeFunc := func(tokenClaims []byte, scopes []string) error {
        type CustomClaims struct {
            jwt.StandardClaims
            Scopes []string `json:"scopes"`
        }
        var newClaims CustomClaims
        err := json.Unmarshal(tokenClaims, &newClaims)
        if err != nil {
            return status.Errorf(codes.Unauthenticated, "access token is invalid: %s", err.Error())
        }

        if !contains(newClaims.Scopes, "write") {
            return status.Errorf(codes.PermissionDenied, "no permission to access this RPC: no matching scope found")
        }

        return nil
    }
    // create a Config
    // at a minimum an algorithm, scope mapping (only the methods defined here will protected), and a key are needed. we set the scope validation
    // and audience on this one.
    config := authz.NewConfig(
        jwt.HS256,
        map[string][]string{
            "/github.com.tinkerbell.pbnj.api.v1.Machine/Power": {"write"},
        },
        authz.WithHSKey(hsKey),
        authz.WithValidateScopeFunc(scopeFunc),
        authz.WithAudience("admin"),
    )

    // the AuthFunc method can then be used with as middleware with a gRPC server
    grpcServer := grpc.NewServer(
        grpc_middleware.WithUnaryServerChain(
            grpc_auth.UnaryServerInterceptor(config.AuthFunc),
        ),
    )

    listen, err := net.Listen("tcp", ":50051")
    if err != nil {
        panic(err)
    }

    if err := grpcServer.Serve(listen); err != nil {
        os.Exit(1)
    }
}

func contains(s []string, str string) bool {
    for _, v := range s {
        if v == str {
            return true
        }
    }
    return false
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	Algorithm jwt.Algorithm

	// ScopeMapping should hold full rpc methods, given by
	// grpc.UnaryServerInfo.FullMethod, mapped to a slice of
	// allowed scopes. Only the methods here will be protected
	// by auth.
	ScopeMapping map[string][]string
	// ValidateScopeFunc is a user defined func for validating a token
	// has the correct scopes. This will take in the decoded token json and
	// unmarshal into any struct the user wants. See the test files for examples.
	ValidateScopeFunc         func(tokenClaims []byte, scopes []string) error
	Audience                  string
	DisableAudienceValidation bool
	// HSKey for use with HS algorithms
	HSKey []byte
	// RSAPublicKey for use with RS algorithms
	RSAPublicKey *rsa.PublicKey
	// contains filtered or unexported fields
}

Config auth details

func NewConfig

func NewConfig(algo jwt.Algorithm, scopeMapping map[string][]string, opts ...ConfigOption) *Config

NewConfig returns a new config with options

func (*Config) AuthFunc

func (c *Config) AuthFunc(ctx context.Context) (context.Context, error)

AuthFunc authorization function

type ConfigOption

type ConfigOption func(*Config)

ConfigOption for setting optional values

func WithAudience

func WithAudience(aud string) ConfigOption

WithAudience sets the audience

func WithDisableAudienceValidation

func WithDisableAudienceValidation(disable bool) ConfigOption

WithDisableAudienceValidation sets the WithDisableAudienceValidation option

func WithHSKey

func WithHSKey(hKey []byte) ConfigOption

WithHSKey sets the HS key

func WithRSAPubKey

func WithRSAPubKey(rsaPubKey *rsa.PublicKey) ConfigOption

WithRSAPubKey sets the RSA public key

func WithValidateScopeFunc

func WithValidateScopeFunc(scopeFunc func(tokenClaims []byte, scopes []string) error) ConfigOption

WithValidateScopeFunc sets the ValidateScopeFunc option

Jump to

Keyboard shortcuts

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