scy

package module
v0.9.3 Latest Latest
Warning

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

Go to latest
Published: May 4, 2024 License: Apache-2.0 Imports: 16 Imported by: 12

README

scy - secure store api for golang

GoReportCard GoDoc

This library is compatible with Go 1.16+

Please refer to CHANGELOG.md if you encounter breaking changes.

Motivation

The goal of this project is provide API for integrating secret.

Usage

scy CLI client
  #To secure raw secrets 
  scy -m=secure  -d=gcp://secretmanager/projects/viant-e2e/secrets/my_raw_secret1  -k=blowfish://default -t=raw
  #To reveal raw secrets 
  scy -m=reveal -s=gcp://secretmanager/projects/viant-e2e/secrets/aw1test  -k=blowfish://default -t=raw
  
  #create JWT claim
  echo '{"user_id":123,"email":"dev@viantinc.com"}' > claims.json 
  scy -m=signJwt -s=claims.json -r=private.scy -k=blowfish://default  

check CLI for mode details

In application

package mypkg

import (
	"context"
	"database/sql"
	"fmt"
	"github.com/viant/scy"
	"github.com/viant/scy/cred"
	"github.com/viant/scy/kms/gcp"
	_ "github.com/viant/scy/kms/blowfish"
	_ "github.com/viant/afsc/tree/master/gcp/secretmanager"
	"log"
)

func ExampleService_Load() {

	{ //loading generic credentials from google secret manager
		resource := scy.NewResource("", "gcp://secretmanager/projects/gcp-e2e/secrets/mycred", "")
		secrets := scy.New()
		secret, err := secrets.Load(context.Background(), resource)
		if err != nil {
			log.Fatalln(err)
		}
		fmt.Printf("%v ->  %s\n", secret.Target, secret.String())
		dsn := "${Username}:${Password}}@/dbname"
		db, err := sql.Open("mysql", secret.Expand(dsn))
		fmt.Printf("%v %v\n", db, err)
	}

	{ //loading secret from google cloud secret manager
		resource := scy.NewResource("secret", 
			"gcp://secretmanager/projects/gcp-e2e/secrets/mysecret", "")
		secrets := scy.New()
		secret, err := secrets.Load(context.Background(), resource)
		if err != nil {
			log.Fatalln(err)
		}
		fmt.Printf("%v %v\n", secret.String())
	}

	{ //loading secret from cloud storage encrypted with GCP KMS

		cipher, err := gcp.New(context.Background())
		if err != nil {
			log.Fatalln(err)
		}
		kms.Register(gcp.Scheme, cipher)
		
		resource := scy.NewResource("secret", 
			"gs://mybucket/asset.enc", 
			"gcp://kms/projects/my-project/locations/us-central1/keyRings/my-ring/cryptoKeys/my-key")
		secrets := scy.New()
		secret, err := secrets.Load(context.Background(), resource)
		if err != nil {
			log.Fatalln(err)
		}
		fmt.Printf("%v %v\n", secret.String())
	}


	{ //loading local secret
		//Assume that : /tmp/secret.json {"Username":"Bob","EncryptedPassword":"AAAAAAAAAAAtM4MTWOJOJ4SyE44PjH66"}
		//make sure _ "github.com/viant/scy/kms/blowfish" is imported
		resource := scy.NewResource(cred.Basic{}, 
		    "/tmp/secret.json", 
		    "blowfish://default")
		secrets := scy.New()
		secret, err := secrets.Load(context.Background(), resource)
		if err != nil {
			log.Fatalln(err)
		}
		basicCred := secret.Target.(*cred.Basic)
		fmt.Printf("user: %v, password: %v\n", basicCred.Username, basicCred.Password)
		dsn := "${cred.Username}:${cred.Password}}@/dbname"
		db, err := sql.Open("mysql", secret.Expand(dsn))
		fmt.Printf("%v %v\n", db, err)
	}

	{ //loading encrypted file
		resource := scy.NewResource("password", "/tmp/password.enc", "blowfish://default")
		secrets := scy.New()
		secret, err := secrets.Load(context.Background(), resource)
		if err != nil {
			log.Fatalln(err)
		}

		dsn := "myuser:${password}}@/dbname"
		db, err := sql.Open("mysql", secret.Expand(dsn))
		if err != nil {
			log.Fatalln(err)
		}
		fmt.Printf("%v %v\n", db, err)
	}

	{ //loading structured encrypted file
		resource := scy.NewResource("cred", "/tmp/cred.enc", "blowfish://default")
		secrets := scy.New()
		secret, err := secrets.Load(context.Background(), resource)
		if err != nil {
			log.Fatalln(err)
		}
		dsn := "${cred.Username}:${cred.Password}}@/dbname"
		db, err := sql.Open("mysql", secret.Expand(dsn))
		if err != nil {
			log.Fatalln(err)
		}
		fmt.Printf("%v %v\n", db, err)
	}

	
}


Secret store file system

You can use diractly the following Secret stores

  • GCP Google Secret Manager
  • AWS - Secret Manager
  • AWS - System Manager - Parameter

Keys

  • gcp://kms/projects/my-project/locations/us-central1/keyRings/my-ring/cryptoKeys/my-key
  • blowfish://default
  • blowfish://env/mykey
  • blowfish://localhost/localpath
  • blowfish://mac (Mac address based hashed key)

Invoking secured cloud function


import (
	"context"
	"fmt"
	"github.com/viant/scy/auth/gcp"
	"github.com/viant/scy/auth/gcp/client"
	"io/ioutil"
	"log"
)


func ExampleService_IDClient() {
	srv := gcp.New(client.NewGCloud())
	ctx := context.Background()
	audience := "https://us-central1-myProject.cloudfunctions.net/MyCloudFunction"
	httpClient, err := srv.IDClient(ctx, audience)
	//Call secured cloud function
	resp, err := httpClient.Get(audience)
	if err != nil {
		log.Fatal(err)
	}
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("CF response: %s\n", data)
}

Contribution

scy is an open source project and contributors are welcome!

See TODO list

License

The source code is made available under the terms of the Apache License, Version 2, as stated in the file LICENSE.

Individual files may be made available under their own specific license, all compatible with Apache License, Version 2. Please see individual files for details.

Credits and Acknowledgements

Authors:

  • Adrian Witas

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Registry added in v0.3.0

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

func Resources added in v0.3.0

func Resources() *Registry

Resources returns resources registry

func (*Registry) Lookup added in v0.3.0

func (r *Registry) Lookup(name string) *Resource

func (*Registry) Register added in v0.3.0

func (r *Registry) Register(name string, resource *Resource)

func (*Registry) Remove added in v0.3.0

func (r *Registry) Remove(name string)

type Resource

type Resource struct {
	Name      string `json:",omitempty"`
	URL       string `json:",omitempty"`
	Key       string `json:",omitempty"` //encryption key
	MaxRetry  int    `json:",omitempty"`
	TimeoutMs int    `json:",omitempty"`
	Fallback  *Resource
	Options   []storage.Option
	Data      []byte
	// contains filtered or unexported fields
}

Resource represents a secret config

func NewResource

func NewResource(target interface{}, URL, Key string) *Resource

NewResource creates a resource

func (*Resource) Init added in v0.1.1

func (r *Resource) Init()

func (*Resource) SetTarget

func (r *Resource) SetTarget(t reflect.Type)

SetTarget sets target type

func (*Resource) Timeout added in v0.1.1

func (r *Resource) Timeout() time.Duration

func (*Resource) Validate

func (r *Resource) Validate() error

Validate checks if resource if valid

type Secret

type Secret struct {
	*Resource
	Target interface{}

	IsPlain bool
	// contains filtered or unexported fields
}

Secret represent secret

func NewSecret

func NewSecret(target interface{}, resource *Resource) *Secret

NewSecret creates a secret

func (*Secret) Decode

func (s *Secret) Decode(target interface{}) error

Decode secret into target

func (*Secret) Expand

func (s *Secret) Expand(text string) string

Expand expend text with secret data

func (*Secret) String

func (s *Secret) String() string

String returns secret literal

func (*Secret) Validate

func (s *Secret) Validate() error

Validate checks if secrt is valid

type Service

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

Service represents secret service

func New

func New() *Service

New creates a new secret service

func (*Service) Load

func (s *Service) Load(ctx context.Context, resource *Resource) (*Secret, error)

Load loads secret

Example
{ //loading generic credentials from google secret manager

	resource := NewResource("", "gcp://secretmanager/projects/gcp-e2e/secrets/mycred", "")
	secrets := New()
	secret, err := secrets.Load(context.Background(), resource)
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("%T ->  %s\n", secret.Target, secret.String())
	dsn := "${Username}:${Password}@/dbname"
	db, err := sql.Open("mysql", secret.Expand(dsn))
	fmt.Printf("%v %v\n", db, err)
}

{ //loading secret from google cloud secret manager

	resource := NewResource("secret", "gcp://secretmanager/projects/gcp-e2e/secrets/test2sec", "")
	secrets := New()
	secret, err := secrets.Load(context.Background(), resource)
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("%v\n", secret.String())
}

{ //loading secret from cloud storage encrypted with GCP KMS
	cipher, err := gcp.New(context.Background())
	if err != nil {
		log.Fatalln(err)
	}
	kms.Register(gcp.Scheme, cipher)

	resource := NewResource("secret", "gs://mybucket/asset.enc", "gcp://kms/projects/my-project/locations/us-central1/keyRings/my-ring/cryptoKeys/my-key")
	secrets := New()
	secret, err := secrets.Load(context.Background(), resource)
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("%v \n", secret.String())
}

{ //loading local secret
	//Assume that : /tmp/secret.json {"Username":"Bob","EncryptedSecret":"AAAAAAAAAAAtM4MTWOJOJ4SyE44PjH66"}
	//make sure _ "github.com/viant/scy/kms/blowfish" is imported
	resource := NewResource(cred.Basic{}, "/tmp/secret.json", "blowfish://default")
	secrets := New()
	secret, err := secrets.Load(context.Background(), resource)
	if err != nil {
		log.Fatalln(err)
	}
	basicCred := secret.Target.(*cred.Basic)
	fmt.Printf("user: %v, password: %v\n", basicCred.Username, basicCred.Password)
	dsn := "${cred.Username}:${cred.Password}}@/dbname"
	db, err := sql.Open("mysql", secret.Expand(dsn))
	fmt.Printf("%v %v\n", db, err)
}

{ //loading encrypted file
	resource := NewResource("password", "/tmp/password.enc", "blowfish://default")
	secrets := New()
	secret, err := secrets.Load(context.Background(), resource)
	if err != nil {
		log.Fatalln(err)
	}

	dsn := "myuser:${password}}@/dbname"
	db, err := sql.Open("mysql", secret.Expand(dsn))
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("%v %v\n", db, err)
}

{ //loading structured encrypted file
	resource := NewResource("password", "/tmp/cred.enc", "blowfish://default")
	secrets := New()
	secret, err := secrets.Load(context.Background(), resource)
	if err != nil {
		log.Fatalln(err)
	}
	dsn := "${cred.Username}:${cred.Password}}@/dbname"
	db, err := sql.Open("mysql", secret.Expand(dsn))
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("%v %v\n", db, err)
}
Output:

func (*Service) Store

func (s *Service) Store(ctx context.Context, secret *Secret) error

Store stores secret

Jump to

Keyboard shortcuts

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