cased

package module
v0.0.0 Latest Latest
Warning

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

Go to latest
Published: Jan 9, 2021 License: MIT Imports: 13 Imported by: 4

README

cased-go

A Cased client for Go applications in your organization to control and monitor the access of information within your organization.

Build Status go.dev

Overview

Installation

To make cased-go available for use in your package, run:

$ go get github.com/cased/cased-go

After installing the cased-go package and configuring cased-go, the first thing you'll want to do is start publishing audit events:

package main

import "github.com/cased/cased-go"

func main() {
	p := cased.NewPublisher(
		cased.WithPublishKey("publish_test_1mY8qb355NWIa3uY00H2fk7elpT"),
	)
	cased.SetPublisher(p)

	ae := cased.AuditEvent{
		"action":          "user.login",
		"actor":           cased.NewSensitiveValue("John Doe", "username"),
		"actor_id":        "User;1",
		"organization":    "cased",
		"organization_id": "Organization;1",
	}
	cased.Publish(ae)

	fmt.Printf("%+v\n", ae)
}

cased-go publishes audit events asynchronously by default. To ensure no audit events are dropped at the end of your process, you'll want to make sure cased.Flush is called at some point in your shutdown process.

package main

import "github.com/cased/cased-go"

func main() {
	p := cased.NewPublisher(
		cased.WithPublishKey("publish_test_1mY8qb355NWIa3uY00H2fk7elpT"),
	)
	cased.SetPublisher(p)

	// The process will wait 30 seconds to publish all events to Cased before
	// exiting the process.
	defer cased.Flush(30 * time.Second)

	ae := cased.AuditEvent{
		"action":          "user.login",
		"actor":           cased.NewSensitiveValue("John Doe", "username"),
		"actor_id":        "User;1",
		"organization":    "cased",
		"organization_id": "Organization;1",
	}
	cased.Publish(ae)

	fmt.Printf("%+v\n", ae)
}

You've now installed cased-go properly and have published your first event. For more details on publishing audit events and protecting sensitive values, keep reading on.

Configuration

All configuration options available in cased-go are available to be configured by an environment variable or manually.

package main

import (
	"net/http"
	"time"

	"github.com/cased/cased-go"
)

func main() {
	p := cased.NewPublisher(
		// CASED_PUBLISH_URL=https://publish.cased.com
		cased.WithPublishURL("https://publish.cased.com"),

		// CASED_PUBLISH_KEY=publish_live_1mY8qb355NWIa3uY00H2fk7elpT
		cased.WithPublishKey("publish_live_1mY8qb355NWIa3uY00H2fk7elpT"),

		// CASED_DEBUG=1
		cased.WithDebug(true),

		// CASED_SILENCE=1
		cased.WithSilence(true),

		// You can configure your own client or re-use an existing HTTP client from
		// your application.
		cased.WithHTTPClient(&http.Client{}),

		// You can configure your own transport or re-use an existing HTTP transport
		// from your application.
		cased.WithHTTPTransport(&http.Transport{}),

		// CASED_HTTP_TIMEOUT=10s
		cased.WithHTTPTimeout(10*time.Second),
		cased.WithTransport(cased.NewNoopHTTPTransport()),
	)
	cased.SetPublisher(p)

	// ...
}

Usage

Publishing events to Cased

There are two ways to publish your first Cased event.

Manually

package user

import "github.com/cased/cased-go"

type Organization struct {
	ID   string
	Name string
}

type User struct {
	ID           string
	Username     string
	Organization Organization
}

func (u *User) login(password, passwordConfirmation string) error {
	ae := cased.AuditEvent{
		"action":          "user.login",
		"actor":           cased.NewSensitiveValue(u.Username, "username"),
		"actor_id":        u.ID,
		"organization":    u.Organization.Name,
		"organization_id": u.Organization.ID,
	}
	defer cased.Publish(ae)

	if password != passwordConfirmation {
		ae["action"] = "user.failed_login"
		return errors.New("invalid password")
	}

	return nil
}
Masking & filtering sensitive information

If you are handling sensitive information on behalf of your users you should consider masking or filtering any sensitive information.

package user

import "github.com/cased/cased-go"

type Address struct {
	Street  string
	City    string
	State   string
	ZipCode string
}

type User struct {
	ID       string
	Username string
	Address  *Address
}

func (a *Address) Create() error {
	cased.Publish(cased.AuditEvent{
		"action":   "address.create",
		"actor":    cased.NewSensitiveValue(u.Username, "username"),
		"actor_id": u.ID,
		"location": map[string]interface{}{
			"street":   cased.NewSensitiveValue(u.Address.Street, "street"),
			"city":     cased.NewSensitiveValue(u.Address.City, "city"),
			"state":    cased.NewSensitiveValue(u.Address.State, "state"),
			"zip_code": cased.NewSensitiveValue(u.Address.ZipCode, "zip-code"),
		},
	})

	return nil
}
Disable publishing events

Although rare, there may be times where you wish to disable publishing events to Cased. You can configure it using an environment variable or in the client.

package main

import (
	"net/http"
	"time"

	"github.com/cased/cased-go"
)

func main() {
	p := cased.NewPublisher(
		// CASED_SILENCE=1
		cased.WithSilence(true),
	)
	cased.SetPublisher(p)
	defer cased.Flush(10 * time.Second)

	// This audit event will not get published to Cased.
	cased.Publish(cased.AuditEvent{
		"action":             "user.login",
		"actor":              "dewski",
		"actor_id":           "user_1dsGbftbx1c47iU8c7BzUcKJRcD",
		"organization":       "Cased",
		"organization_id":    "org_1dsGTnNZLzgwb1alwS2szN0KUo5",
		"request_id":         "27d62d1869e5f9826acc6cfd80edca90",
		"request_url":        "https://app.cased.com/saml/consume",
		"request_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
	})
}

Or you can configure the entire process to disable publishing events.

CASED_SILENCE=1 go run main.go

Contributing

  1. Fork it ( https://github.com/cased/cased-go/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Documentation

Index

Constants

View Source
const (
	// DotCasedKey is the key name for the property that encodes information about
	// an AuditEvent.
	DotCasedKey = ".cased"

	// DefaultSensitiveLabel is the default value used if a particular PII
	// does not contain a label.
	DefaultSensitiveLabel = "sensitive-value"
)

Variables

View Source
var ContextKey = contextKey(0)

ContextKey ...

View Source
var Logger = log.New(ioutil.Discard, "[Cased] ", log.LstdFlags)

Logger ...

Processors contains all processors available to transform an audit event before it's published to Cased.

Functions

func Flush

func Flush(timeout time.Duration) bool

Flush waits for audit events to be published.

func Publish

func Publish(event AuditEvent) error

Publish publishes an audit event to Cased.

func PublishWithContext

func PublishWithContext(ctx context.Context, event AuditEvent) error

PublishWithContext enriches the provided audit event with the context set in the request. If the same key is present in both the context and provided audit event, the audit event value will be preserved.

func SetPublisher

func SetPublisher(publisher Publisher)

SetPublisher ...

Types

type AuditEvent

type AuditEvent map[string]interface{}

AuditEvent ...

func GetContextFromContext

func GetContextFromContext(ctx context.Context) AuditEvent

GetContextFromContext ...

func (AuditEvent) MarshalJSON

func (ae AuditEvent) MarshalJSON() ([]byte, error)

MarshalJSON ...

type AuditEventPayload

type AuditEventPayload struct {
	DotCased   DotCased `json:".cased"`
	AuditEvent AuditEvent
}

AuditEventPayload is the wrapper struct hosting the nestable JSON AuditEvent with the internal `.cased` property with a rich struct.

func NewAuditEventPayload

func NewAuditEventPayload(event AuditEvent) *AuditEventPayload

NewAuditEventPayload ...

func PublishedAtProcessor

func PublishedAtProcessor(aep *AuditEventPayload) *AuditEventPayload

PublishedAtProcessor sets the current time the audit event was published at.

func SensitiveDataProcessor

func SensitiveDataProcessor(aep *AuditEventPayload) *AuditEventPayload

SensitiveDataProcessor adds sensitive data positions based on values.

func (*AuditEventPayload) MarshalJSON

func (aep *AuditEventPayload) MarshalJSON() ([]byte, error)

MarshalJSON ...

func (*AuditEventPayload) UnmarshalJSON

func (aep *AuditEventPayload) UnmarshalJSON(data []byte) error

UnmarshalJSON ...

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the underlying processor that is used by the main API and Hub instances. It must be created with NewClient.

func (*Client) Flush

func (c *Client) Flush(timeout time.Duration) bool

Flush ...

func (Client) Options

func (c Client) Options() PublisherOptions

Options return PublisherOptions for the current Client.

func (Client) Publish

func (c Client) Publish(event AuditEvent) error

Publish ...

type DotCased

type DotCased struct {
	PII                map[string][]*SensitiveRange `json:"pii,omitempty"`
	ID                 string                       `json:"id,omitempty"`
	Event              AuditEvent                   `json:"event,omitempty"`
	PublisherUserAgent string                       `json:"publisher_user_agent,omitempty"`
	ProcessedAt        *time.Time                   `json:"processed_at,omitempty"`
	ReceivedAt         *time.Time                   `json:"received_at,omitempty"`
	PublishedAt        time.Time                    `json:"published_at"`
}

DotCased is a reserved property in an audit event containing the original event, any modifications to the event post-processing, timestamps, and more.

type HTTPSyncTransport

type HTTPSyncTransport struct {
	// contains filtered or unexported fields
}

HTTPSyncTransport provides a transport that publishes audit events synchronously as they are received.

func NewHTTPSyncTransport

func NewHTTPSyncTransport() *HTTPSyncTransport

NewHTTPSyncTransport returns a transport that publishes audit events synchronously as they are received.

func (*HTTPSyncTransport) Configure

func (t *HTTPSyncTransport) Configure(options PublisherOptions)

Configure prepares the synchronous audit event publisher with provided client options.

func (*HTTPSyncTransport) Flush

func (t *HTTPSyncTransport) Flush(_ time.Duration) bool

Flush is unused.

func (*HTTPSyncTransport) Publish

func (t *HTTPSyncTransport) Publish(event *AuditEventPayload) error

Publish publishes the provided audit event to Cased.

type HTTPTransport

type HTTPTransport struct {
	BufferSize int
	// contains filtered or unexported fields
}

HTTPTransport ...

func NewHTTPTransport

func NewHTTPTransport() *HTTPTransport

NewHTTPTransport ...

func (*HTTPTransport) Configure

func (t *HTTPTransport) Configure(options PublisherOptions)

Configure prepares the asynchronous audit event publisher with provided client options.

func (*HTTPTransport) Flush

func (t *HTTPTransport) Flush(timeout time.Duration) bool

Flush waits for all audit events to be published that are in the buffer.

func (*HTTPTransport) Publish

func (t *HTTPTransport) Publish(event *AuditEventPayload) error

Publish queues the audit event to be published in the asynchronously.

To ensure queued audit events are published at end of process see Flush.

type MockPublisher

type MockPublisher struct {
	Events []AuditEvent
	// contains filtered or unexported fields
}

func NewMockPublisher

func NewMockPublisher() (*MockPublisher, func())

func NewSilencedMockPublisher

func NewSilencedMockPublisher() (*MockPublisher, func())

func (MockPublisher) Flush

func (mp MockPublisher) Flush(_ time.Duration) bool

func (MockPublisher) Options

func (mp MockPublisher) Options() PublisherOptions

func (*MockPublisher) Publish

func (mp *MockPublisher) Publish(event AuditEvent) error

type NoopHTTPTransport

type NoopHTTPTransport struct{}

NoopHTTPTransport does not publish audit events to Cased.

func NewNoopHTTPTransport

func NewNoopHTTPTransport() *NoopHTTPTransport

NewNoopHTTPTransport returns a client that does not publish audit events to Cased.

func (*NoopHTTPTransport) Configure

func (t *NoopHTTPTransport) Configure(options PublisherOptions)

Configure is a noop operation.

func (*NoopHTTPTransport) Flush

func (t *NoopHTTPTransport) Flush(_ time.Duration) bool

Flush is a noop operation.

func (*NoopHTTPTransport) Publish

func (t *NoopHTTPTransport) Publish(event *AuditEventPayload) error

Publish is a noop operation.

type Processor

type Processor func(*AuditEventPayload) *AuditEventPayload

Processor is the interface necessary for processor functions to implement. It takes the audit event payload that is about to be published and mutates it as necessary.

Each processor should be idempotent and not depend on another processor to be called beforehand.

type Publisher

type Publisher interface {
	Publish(event AuditEvent) error
	Options() PublisherOptions
	Flush(timeout time.Duration) bool
}

Publisher describes the interface for structs that want to publish audit events to Cased.

func CurrentPublisher

func CurrentPublisher() Publisher

CurrentPublisher ...

func NewPublisher

func NewPublisher(opts ...PublisherOption) Publisher

NewPublisher ...

type PublisherOption

type PublisherOption func(opts *PublisherOptions)

PublisherOption ...

func WithDebug

func WithDebug(debug bool) PublisherOption

WithDebug ...

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) PublisherOption

WithHTTPClient ...

func WithHTTPTimeout

func WithHTTPTimeout(httpTimeout time.Duration) PublisherOption

WithHTTPTimeout ...

func WithHTTPTransport

func WithHTTPTransport(httpTransport *http.Transport) PublisherOption

WithHTTPTransport ...

func WithPublishKey

func WithPublishKey(publishKey string) PublisherOption

WithPublishKey configures the publish key used to publish audit events to Cased. You can obtain the publish key from the audit trail settings page within the Cased dashboard.

func WithPublishURL

func WithPublishURL(publishURL string) PublisherOption

WithPublishURL ...

func WithSilence

func WithSilence(silence bool) PublisherOption

WithSilence ...

func WithTransport

func WithTransport(transport Transporter) PublisherOption

WithTransport ...

type PublisherOptions

type PublisherOptions struct {
	// PublishURL contains the URL to published Cased events to.
	PublishURL string `envconfig:"CASED_PUBLISH_URL" default:"https://publish.cased.com"`

	// PublishKey is the publish API key used to publish to an audit trail.
	//
	// A publish key is associated with a single audit trail and is required if
	// you intend to publish events to Cased in your application.
	PublishKey string `envconfig:"CASED_PUBLISH_KEY"`

	Debug bool `envconfig:"CASED_DEBUG" default:"false"`

	// Silence to determine if new events are published to Cased.
	Silence bool `envconfig:"CASED_SILENCE" default:"false"`

	HTTPClient    *http.Client
	HTTPTransport *http.Transport
	HTTPTimeout   time.Duration `envconfig:"CASED_HTTP_TIMEOUT" default:"5s"`

	Transport Transporter
}

PublisherOptions ...

type SensitiveRange

type SensitiveRange struct {
	Begin int    `json:"begin"`
	End   int    `json:"end"`
	Label string `json:"label"`
}

SensitiveRange is a range that informs Cased about any sensitive information stored in an AuditEvent.

type SensitiveValue

type SensitiveValue struct {
	Value  string
	Ranges []SensitiveRange
}

SensitiveValue contains the sensitive value and all the sensitive ranges within the provided value.

func NewSensitiveValue

func NewSensitiveValue(value, label string) SensitiveValue

NewSensitiveValue marks an entire string as sensitive.

The marked sensitive value will be encoded upon publishing to Cased.

func (SensitiveValue) MarshalJSON

func (sv SensitiveValue) MarshalJSON() ([]byte, error)

MarshalJSON encodes the provided sensitive value for JSON representation.

type Transporter

type Transporter interface {
	Configure(options PublisherOptions)
	Publish(event *AuditEventPayload) error
	Flush(timeout time.Duration) bool
}

Transporter ...

Directories

Path Synopsis
example
basic command
configuration command
http command
sensitive-data command

Jump to

Keyboard shortcuts

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