sidecred

package module
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2022 License: MIT Imports: 9 Imported by: 0

README

sidecred

go.dev reference latest release build status go report

Sidecred handles the lifecycle of your credentials "on the side". It supports multiple credential providers and secret stores, and handles the lifecycle from creation, to rotations and eventual deletion.

Why?

Security and convenience. E.g. our CI/CD requires AWS credentials in order to deploy terraform templates, and instead of using static credentials tied to one or more IAM users, we can use Sidecred to create and rotate a temporary set of credentials that are tied to an IAM role and written to a secret store where it can be accessed by our CI/CD. Likewise we can use Sidecred to provision and rotate temporary access tokens tied to a Github App instead of using machine users to create personal access tokens (PAC) that are not automatically rotated.

Installation

You can install sidecred by downloading it from the releases, or you can easily deploy to AWS using the following terraform template: https://github.com/telia-oss/terraform-aws-sidecred.

Usage

See sidecred --help for supported flags. Flags can also be set via the environment after prefixing the flag name with SIDECRED_. E.g. --sts-provider-enabled can be set with SIDECRED_STS_PROVIDER_ENABLED=true.

Configuration

---
version: 1

namespace: cloudops

stores:
  - type: secretsmanager
  - type: github
    config:
      repository: telia-oss/sidecred
      secret_template: "{{ .Namespace }}_{{ .Name }}"
  - type: github:dependabot
    config:
      repository: telia-oss/sidecred
      secret_template: "{{ .Namespace }}_{{ .Name }}"

requests:
  - store: github
    creds:
      - type: aws:sts
        name: open-source-dev-read-only
        config:
          role_arn: arn:aws:iam::role/role-name
          duration: 15m
  - store: github:dependabot
    creds:
      - type: aws:sts
        name: open-source-dev-read-only
        config:
          role_arn: arn:aws:iam::role/role-name
          duration: 15m          
  - store: secretsmanager
    creds:
      - type: github:access-token
        list:
          - name: itsdalmo-access-token
            config: { owner: itsdalmo }
          - name: telia-oss-access-token
            config: { owner: telia-oss }

As shown above, Sidecred expects a YAML configuration that contains the following elements:

  • namespace: A namespace (e.g. the name of a team, project or similar) to use when processing the credential requests. Replaces {{ .Namespace }} in secret templates and resource names.
  • stores: One or more secret stores to use for writing the requested credentials. You can name: stores for readability, or to de-dupe store types.
  • requests: A list of credential requests that map creds: to a store:. Each credential request under creds: should specify a credential type: and unique name: for the credentials, and optionally a config: which is passed to the credential provider.

See below for a list of supported secret stores and credential providers.

Supported secret stores

Secret stores are used to store credentials generated by providers. The following credential stores are supported:

Supported providers

Providers are used to generate/provide credentials (see the provider documentation for details):

Supported backends

Sidecred keeps an internal state to track credential expiration and to perform cleanup for external resources when they are no longer needed. Backends are used to store this internal state, and Sidecred currently supports the following backends:

  • File
  • AWS S3

Development

Local
# Enable the STS provider
export AWS_REGION=eu-west-1
export SIDECRED_STS_PROVIDER_ENABLED=true
export SIDECRED_STS_PROVIDER_SESSION_DURATION=20m

# Enable the Github provider
export SIDECRED_GITHUB_PROVIDER_ENABLED=true
export SIDECRED_GITHUB_PROVIDER_KEY_ROTATION_INTERVAL=20m
export SIDECRED_GITHUB_PROVIDER_INTEGRATION_ID="<value>"
export SIDECRED_GITHUB_PROVIDER_PRIVATE_KEY="<value>"

# Chose a secret store and configure it
export SIDECRED_SSM_STORE_ENABLED=true
export SIDECRED_SSM_STORE_PATH_TEMPLATE="/sidecred/{{ .Namespace }}/{{ .Name }}"

# Chose a state backend and configure it
export SIDECRED_STATE_BACKEND=file

# Enable debug logging
export SIDECRED_DEBUG=true

After setting the above you can execute sidecred as follows:

# The Github App credentials (integration ID and private key) and AWS STS credentials
# should be populated using e.g. vaulted or aws-vault:
go run ./cmd/sidecred --config ./cmd/sidecred/testdata/config.yml

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildSecretTemplate added in v0.7.0

func BuildSecretTemplate(secretTemplate, namespace, name string) (string, error)

BuildSecretTemplate is a convenience function for building secret templates.

func UnmarshalConfig added in v0.7.0

func UnmarshalConfig(config json.RawMessage, target interface{}) error

UnmarshalConfig is a convenience method for performing a strict unmarshalling of a JSON config into a provided structure. If config is empty, no operation is performed by this function.

Types

type Config added in v0.7.0

type Config interface {
	Validatable

	// Namespace (e.g. the name of a team, project or similar) to use when processing the credential requests.
	Namespace() string

	// Stores that can be targeted when mapping credentials.
	Stores() []*StoreConfig

	// Requests to map credentials to a secret store.
	Requests() []*CredentialsMap
}

Config represents the user-defined configuration that should be passed when processing credentials using sidecred.

type Credential

type Credential struct {
	// Name is the identifier for the credential.
	Name string `json:"name,omitempty"`

	// Value is the credential value (typically a secret).
	Value string `json:"-"`

	// Description returns a short description of the credential.
	Description string `json:"-"`

	// Expiration is the time at which the credential will have expired.
	Expiration time.Time `json:"expiration"`
}

Credential is a key/value pair returned by a sidecred.Provider.

type CredentialRequest added in v0.7.0

type CredentialRequest struct {
	// Type identifies the type of credential (and provider) for a request.
	Type CredentialType `json:"type"`

	// Name is an identifier that can be used for naming resources and
	// credentials created by a sidecred.Provider. The exact usage for
	// name is up to the individual provider.
	Name string `json:"name"`

	// Rotation is an override for the default rotation window
	// measured in seconds.
	// This will aid in cases where we want to be more granular
	// for possibly longer running authentications or processes.
	RotationWindow *Duration `json:"rotation_window"`

	// Config holds the provider configuration for the requested credential.
	Config json.RawMessage `json:"config"`
}

CredentialRequest is the structure used to request credentials in Sidecred.

func (*CredentialRequest) UnmarshalConfig added in v0.7.0

func (r *CredentialRequest) UnmarshalConfig(target interface{}) error

UnmarshalConfig performs a strict JSON unmarshal of the config to the desired struct.

type CredentialType

type CredentialType string

CredentialType ...

const (
	Randomized             CredentialType = "random"
	AWSSTS                 CredentialType = "aws:sts"
	GithubDeployKey        CredentialType = "github:deploy-key"
	GithubAccessToken      CredentialType = "github:access-token"
	ArtifactoryAccessToken CredentialType = "artifactory:access-token"
)

Enumeration of known credential types.

func (CredentialType) Provider

func (c CredentialType) Provider() ProviderType

Provider returns the sidecred.ProviderType for the credential.

type CredentialsMap added in v0.11.0

type CredentialsMap struct {
	// Store identifies the name or alias of the target secret store.
	Store string

	// Credentials that will be provisioned and written to the secret store.
	Credentials []*CredentialRequest
}

CredentialsMap represents a mapping between one or more credential request and a target secret store.

type Duration added in v0.10.0

type Duration struct {
	time.Duration
}

Duration implements JSON (un)marshal for time.Duration.

func (Duration) MarshalJSON added in v0.10.0

func (d Duration) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*Duration) UnmarshalJSON added in v0.10.0

func (d *Duration) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type Metadata

type Metadata map[string]string

Metadata allows providers to pass additional information to be stored in the sidecred.ResourceState after successfully creating credentials.

type Provider

type Provider interface {
	// Type returns the provider type.
	Type() ProviderType

	// Create the requested credentials. Any sidecred.Resource
	// returned will be stored in state and used to determine
	// when credentials need to be rotated.
	Create(request *CredentialRequest) ([]*Credential, *Metadata, error)

	// Destroy the specified resource. This is scheduled if
	// a resource in the state has expired. For providers that
	// are not stateful this should be a no-op.
	Destroy(resource *Resource) error
}

Provider is the interface that has to be satisfied by credential providers.

type ProviderType

type ProviderType string

ProviderType ...

const (
	Random      ProviderType = "random"
	AWS         ProviderType = "aws"
	Github      ProviderType = "github"
	Artifactory ProviderType = "artifactory"
)

Enumeration of known provider types.

type Resource

type Resource struct {
	Type       CredentialType  `json:"type"`
	ID         string          `json:"id"`
	Store      string          `json:"store"`
	Expiration time.Time       `json:"expiration"`
	Deposed    bool            `json:"deposed"`
	Config     json.RawMessage `json:"config,omitempty"`
	Metadata   *Metadata       `json:"metadata,omitempty"`
	InUse      bool            `json:"-"`
}

Resource represents a resource provisioned by a sidecred.Provider as part of creating the requested credentials.

type Secret

type Secret struct {
	ResourceID string    `json:"resource_id"`
	Path       string    `json:"path"`
	Expiration time.Time `json:"expiration"`
}

Secret is used to hold state about secrets stored in a secret backend.

type SecretStore

type SecretStore interface {
	// Type returns the store type.
	Type() StoreType

	// Write a sidecred.Credential to the secret store.
	Write(namespace string, secret *Credential, config json.RawMessage) (string, error)

	// Read the specified secret by reference.
	Read(path string, config json.RawMessage) (string, bool, error)

	// Delete the specified secret. Should not return an error
	// if the secret does not exist or has already been deleted.
	Delete(path string, config json.RawMessage) error
}

SecretStore is implemented by store backends for secrets.

type Sidecred

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

Sidecred is the underlying structure for the service.

func New

func New(providers []Provider, stores []SecretStore, rotationWindow time.Duration, logger *zap.Logger) (*Sidecred, error)

New returns a new instance of sidecred.Sidecred with the desired configuration.

func (*Sidecred) Process

func (s *Sidecred) Process(config Config, state *State) error

Process a single sidecred.Request.

type State

type State struct {
	Providers []*providerState `json:"providers,omitempty"`
	Stores    []*storeState    `json:"stores,omitempty"`
}

State is responsible for keeping track of when credentials need to be rotated because they are expired, the configuration has changed, or they have been deposed and need to clean up resources and secrets.

func NewState

func NewState() *State

NewState returns a new sidecred.State.

func (*State) AddResource

func (s *State) AddResource(resource *Resource)

AddResource stores a resource state for the given provider. The provider will be added to state if it does not already exist. Any existing resources with the same ID will be marked as deposed.

func (*State) AddSecret

func (s *State) AddSecret(c *StoreConfig, secret *Secret)

AddSecret adds state for the specified sidecred.SecretStore alias. The store will be added to state if it does not already exist, and any existing state for the same secret path will be overwritten.

func (*State) GetResourcesByID

func (s *State) GetResourcesByID(t CredentialType, id, store string) []*Resource

GetResourcesByID returns all resources with the given ID from state, and also marks the resources as being in use.

func (*State) ListOrphanedSecrets added in v0.2.0

func (s *State) ListOrphanedSecrets(c *StoreConfig) []*Secret

ListOrphanedSecrets lists all secrets tied to missing resource IDs that should be considered orphaned.

func (*State) RemoveResource

func (s *State) RemoveResource(resource *Resource)

RemoveResource from the state.

func (*State) RemoveSecret

func (s *State) RemoveSecret(c *StoreConfig, secret *Secret)

RemoveSecret from the state.

type StateBackend

type StateBackend interface {
	// Load state from the backend. If no state exists it should be created.
	Load(path string) (*State, error)

	// Save a state to the backend.
	Save(path string, state *State) error
}

StateBackend is implemented by things that know how to store sidecred.State.

type StoreConfig added in v0.7.0

type StoreConfig struct {
	Type   StoreType       `json:"type"`
	Name   string          `json:"name"`
	Config json.RawMessage `json:"config,omitempty"`
}

StoreConfig is used to define the secret stores in the configuration for Sidecred.

func (*StoreConfig) Alias added in v0.11.0

func (c *StoreConfig) Alias() string

Alias returns a name that can be used to identify configured store. defaults to the StoreType.

type StoreType

type StoreType string

StoreType ...

const (
	Inprocess               StoreType = "inprocess"
	SecretsManager          StoreType = "secretsmanager"
	SSM                     StoreType = "ssm"
	GithubSecrets           StoreType = "github"
	GithubDependabotSecrets StoreType = "github:dependabot"
)

Enumeration of known backends.

type Validatable added in v0.11.0

type Validatable interface {
	Validate() error
}

Validatable allows sidecred to ensure the validity of the opaque config values used for processing a request.

Directories

Path Synopsis
backend
file
Package file implements a sidecred.StateBackend that writes to a file.
Package file implements a sidecred.StateBackend that writes to a file.
s3
Package s3 implements a sidecred.StateBackend using AWS S3.
Package s3 implements a sidecred.StateBackend using AWS S3.
s3/s3fakes
Code generated by counterfeiter.
Code generated by counterfeiter.
cmd
internal
cli
provider
artifactory
Package artifactory implements a sidecred.Provider for Artifactory access token credentials.
Package artifactory implements a sidecred.Provider for Artifactory access token credentials.
artifactory/artifactoryfakes
Code generated by counterfeiter.
Code generated by counterfeiter.
github
Package github implements a sidecred.Provider for Github access tokens and deploy keys.
Package github implements a sidecred.Provider for Github access tokens and deploy keys.
github/githubfakes
Code generated by counterfeiter.
Code generated by counterfeiter.
random
Package random implements a sidecred.Provider for random strings, and can be used for tests.
Package random implements a sidecred.Provider for random strings, and can be used for tests.
sts
Package sts implements a sidecred.Provider for AWS STS Credentials.
Package sts implements a sidecred.Provider for AWS STS Credentials.
sts/stsfakes
Code generated by counterfeiter.
Code generated by counterfeiter.
store
github
Package github implements a sidecred.SecretStore on top of Github secrets.
Package github implements a sidecred.SecretStore on top of Github secrets.
github/githubfakes
Code generated by counterfeiter.
Code generated by counterfeiter.
inprocess
Package inprocess implements a sidecred.SecretStore in memory, and can be used for tests.
Package inprocess implements a sidecred.SecretStore in memory, and can be used for tests.
secretsmanager
Package secretsmanager implements sidecred.SecretStore on top of AWS Secrets Manager.
Package secretsmanager implements sidecred.SecretStore on top of AWS Secrets Manager.
secretsmanager/secretsmanagerfakes
Code generated by counterfeiter.
Code generated by counterfeiter.
ssm
Package ssm implements sidecred.SecretStore on top of AWS Parameter store.
Package ssm implements sidecred.SecretStore on top of AWS Parameter store.
ssm/ssmfakes
Code generated by counterfeiter.
Code generated by counterfeiter.

Jump to

Keyboard shortcuts

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