Skip to content

Commit

Permalink
Merge pull request #31 from ag5/feature/aws-parameterstore
Browse files Browse the repository at this point in the history
Feature/aws parameterstore
  • Loading branch information
amohabir authored May 18, 2022
2 parents 6f223c7 + 2a6ed83 commit 7bcd5a6
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 19 deletions.
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changes

### v1.10.0

- add AWS Parameter Store backend

### v1.9.0

- add Google Secret Manager backend

### v1.8.1

- fallback to list command if argument is not a known command.
Expand Down
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

<img align="right" src="kea.jpg">

Kiya is a tool to access secrets stored in Google Secret Manager(GSM) or a Google Bucket and encrypted by Google Key Management Service (KMS).
Kiya is a tool to manage secrets stored in any of:
- Google Secret Manager(GSM)
- Google Bucket and encrypted by Google Key Management Service (KMS)
- Amazon Web Services Parameter Store (SSM)

### Introduction

Expand All @@ -12,8 +15,7 @@ Examples are passwords, service accounts, TLS certificates, API tokens and Encry
managed with great care. This means secrets must be stored encrypted on reliable shared storage and its access must
controlled by AAA (authentication, authorisation and auditing).

**Kiya** is a simple tool that eases the access to the secrets stored in GSM or KMS. It requires an authenticated Google account and permissions for that account to read secrets and perform
encryption and decryption.
**Kiya** is a simple tool that eases the access to the secrets stored in GSM,KMS or SSM. It requires an authenticated account and permissions for that account to read secrets and perform encryption and decryption.

#### Labeled secrets

Expand All @@ -23,11 +25,16 @@ one parent key (lowercase with or without dots). The value must be a string whic

### Prerequisites

Kiya uses your authenticated Google account to access the Secret Manager / Storage Bucket, KMS and Audit Logging. The bucket stores the
encrypted secret value using the label as the storage key.
#### GCP
Kiya uses your authenticated Google account to access the Secret Manager / Storage Bucket, KMS and Audit Logging.
The bucket stores the encrypted secret value using the label as the storage key.

gcloud auth application-default login

#### AWS
Kiya uses your AWS credentials to access the AWS Parameter Store (part of Systems Management).
All values are stored using the specified encryption key ID or the default key set for your AWS Account.

## Install

go install github.com/kramphub/kiya/cmd/kiya@latest
Expand All @@ -39,8 +46,9 @@ Read `setup.md` for detailed instructions how to setup the basic prerequisites.
### Configuration

Create a file name `.kiya` in your home directory with the content for a shareable secrets profile. You can have
multiple profiles for different usages. Each profile should either mention `kms` or `gsm` to be used as the `backend`.
If no value is defined for a profile's `backend`, `kms` will be used as a default.
multiple profiles for different usages. Each profile should either mention `kms`, `gsm` or `ssm` to be used as the `backend`.
If no value is defined for a profile's `backend`, `kms` will be used as a default available for GCP.
Use the backend `ssm` if you are storing keys in AWS Parameter Store as part of the System Management services.

```json
{
Expand All @@ -55,14 +63,21 @@ If no value is defined for a profile's `backend`, `kms` will be used as a defaul
"teamF2-on-gsm": {
"backend": "gsm",
"projectID": "another-gcp-project"
}
},
"ag5": {
"backend": "ssm",
"location": "eu-central-1"
}
}

```

#### GCP
You should define `location`, `keyring`, `cryptoKey` and `bucket` for KMS based profiles.
For Google Secret Manager based profiles a `projectID` is sufficient.

For Google Secret Manager based profiles a `projectID` is only enough.
#### AWS
You should define `location` for SSM (AWS Systems Management) based profiles ; its value is an AWS region.
The `cryptoKey` is optional and must be set if you do not want to use the default key setup for your AWS Account.

### Store a password, _put_

Expand Down
123 changes: 123 additions & 0 deletions backend/aws-parameterstore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package backend

import (
"context"
"fmt"
"os"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
)

// AWSParameterStore implements Backend for AWS Parameter Store service.
type AWSParameterStore struct {
client *ssm.SSM
kmsKeyID string
}

// NewAWSParameterStore returns a new AWSParameterStore with an initialized AWS SSM client.
func NewAWSParameterStore(ctx context.Context, p *Profile) (*AWSParameterStore, error) {
sess := session.New(&aws.Config{
Region: aws.String(p.Location),
MaxRetries: aws.Int(2),
})
return &AWSParameterStore{client: ssm.New(sess), kmsKeyID: p.CryptoKey}, nil
}

// Get returns the decrypted value for a parameter by key.
func (s *AWSParameterStore) Get(ctx context.Context, p *Profile, key string) ([]byte, error) {
input := &ssm.GetParameterInput{
Name: aws.String(key),
WithDecryption: aws.Bool(true),
}
output, err := s.client.GetParameter(input)
if err != nil {
return []byte{}, err
}
return []byte(*output.Parameter.Value), nil
}

// List returns all keys available.
func (s *AWSParameterStore) List(ctx context.Context, p *Profile) (list []Key, err error) {
input := &ssm.GetParametersByPathInput{
Path: aws.String("/"),
MaxResults: aws.Int64(10), // is the maximum
}
for {
output, err := s.client.GetParametersByPath(input)
if err != nil {
return []Key{}, err
}
for _, each := range output.Parameters {
list = append(list, Key{
Name: *each.Name,
CreatedAt: *each.LastModifiedDate,
Info: fmt.Sprintf("type: %v datatype: %v version: %v", *each.Type, *each.DataType, *each.Version),
Owner: "<Unknown>",
})
}
if output.NextToken != nil {
input.NextToken = output.NextToken
} else {
break
}
}
return
}

// CheckExists returns true if there exists a value for a given key.
func (s *AWSParameterStore) CheckExists(ctx context.Context, p *Profile, key string) (bool, error) {
input := &ssm.GetParameterInput{
Name: aws.String(key),
WithDecryption: aws.Bool(false), // No decryption is needed
}
_, err := s.client.GetParameter(input)
if _, ok := err.(*ssm.ParameterNotFound); ok {
return false, nil
}
// other error?
if err != nil {
return false, err
}
return true, nil

}

// Put write the parameter and its value using encryption ;either the default key or the one specified in the profile.
func (s *AWSParameterStore) Put(ctx context.Context, p *Profile, key, value string) error {
input := &ssm.PutParameterInput{
Name: aws.String(key),
Value: aws.String(value),
Overwrite: aws.Bool(false),
DataType: aws.String("text"),
Description: aws.String(fmt.Sprintf("created by %s using kiya", os.Getenv("USER"))),
Tags: []*ssm.Tag{{Key: aws.String("creator"), Value: aws.String(os.Getenv("USER"))}},
Type: aws.String("SecureString"),
}
// only if CryptoKey is set in the Profile then we set the KeyId
// which overrides the default key associated with the AWS account
if p.CryptoKey != "" {
input.KeyId = aws.String(s.kmsKeyID)
}
_, err := s.client.PutParameter(input)
if err != nil {
return err
}
return nil
}

// Delete removes the parameter by its key
func (s *AWSParameterStore) Delete(ctx context.Context, p *Profile, key string) error {
input := &ssm.DeleteParameterInput{
Name: aws.String(key),
}
_, err := s.client.DeleteParameter(input)
return err
}

// Close is not effictive for this backend
func (s *AWSParameterStore) Close() error {
// noop
return nil
}
1 change: 1 addition & 0 deletions backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Key struct {
Name string
CreatedAt time.Time
Owner string
Info string
}

// Profile describes a single profile in a .kiya configuration
Expand Down
3 changes: 2 additions & 1 deletion backend/gsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ func (b *GSM) List(ctx context.Context, p *Profile) ([]Key, error) {
keys = append(keys, Key{
Name: b.fullNameToName(secret.Name),
CreatedAt: secret.CreateTime.AsTime(),
Owner: "<Unknown>", // no owner
Info: "creator: <Unknown>", // no owner
Owner: "<Unknown>",
})
}

Expand Down
1 change: 1 addition & 0 deletions backend/kms.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ func (b *KMS) List(ctx context.Context, p *Profile) ([]Key, error) {
keys = append(keys, Key{
Name: next.Name,
CreatedAt: next.Created,
Info: fmt.Sprintf("creator: %s", next.Owner),
Owner: next.Owner,
})
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/kiya/cmd_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func commandList(ctx context.Context, b backend.Backend, target *backend.Profile
continue
}
}
data = append(data, []string{fmt.Sprintf("kiya %s copy %s", target.Label, k.Name), k.CreatedAt.Format(time.RFC822), k.Owner})
data = append(data, []string{fmt.Sprintf("kiya %s copy %s", target.Label, k.Name), k.CreatedAt.Format(time.RFC822), k.Info})
}

if len(filter) > 0 {
Expand All @@ -38,7 +38,7 @@ func commandList(ctx context.Context, b backend.Backend, target *backend.Profile

table := tablewriter.NewWriter(os.Stdout)
table.SetAutoWrapText(false)
table.SetHeader([]string{"Copy to clipboard command", "Created", "Creator"})
table.SetHeader([]string{"Copy to clipboard command", "Created", "Info"})
table.AppendBulk(data)
table.Render() // writes to stdout
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/kiya/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ func main() {

func getBackend(ctx context.Context, p *backend.Profile) (backend.Backend, error) {
switch p.Backend {
case "ssm":
return backend.NewAWSParameterStore(ctx, p)
case "gsm":
// Create GSM client
gsmClient, err := secretmanager.NewClient(ctx)
Expand Down
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ require (
cloud.google.com/go/secretmanager v0.1.0
cloud.google.com/go/storage v1.10.0
github.com/atotto/clipboard v0.0.0-20160219034421-bb272b845f11
github.com/aws/aws-sdk-go v1.43.31
github.com/emicklei/tre v0.0.0-20170203105728-6532a4213209
github.com/olekukonko/tablewriter v0.0.0-20170925234030-a7a4c189eb47
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a
google.golang.org/api v0.54.0
google.golang.org/genproto v0.0.0-20210820002220-43fce44e7af1
Expand All @@ -21,10 +22,11 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/mattn/go-runewidth v0.0.2 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect
)
22 changes: 19 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/atotto/clipboard v0.0.0-20160219034421-bb272b845f11 h1:Gmm0NreNeu4FgEzX1Ht6ceAf5/wOBG+Gi625BEy9d40=
github.com/atotto/clipboard v0.0.0-20160219034421-bb272b845f11/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aws/aws-sdk-go v1.43.31 h1:yJZIr8nMV1hXjAvvOLUFqZRJcHV7udPQBfhJqawDzI0=
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
Expand All @@ -61,6 +63,7 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/tre v0.0.0-20170203105728-6532a4213209 h1:uVKDszIb7eKEiD5Rxa1xuDLJDmV8OI1rJ16+6mjRoJY=
github.com/emicklei/tre v0.0.0-20170203105728-6532a4213209/go.mod h1:QITyLYm0EScbfskFNk1wgRL1dVWz0M6f7ArRoU3OLTU=
Expand Down Expand Up @@ -154,6 +157,10 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
Expand All @@ -164,6 +171,8 @@ github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/olekukonko/tablewriter v0.0.0-20170925234030-a7a4c189eb47 h1:9LtI8V19RbIDkx5gAhcP1TV1ByyIdavLGgWgefpoEPM=
github.com/olekukonko/tablewriter v0.0.0-20170925234030-a7a4c189eb47/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
Expand Down Expand Up @@ -261,8 +270,9 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 h1:a8jGStKg0XqKDlKqjLrXn0ioF5MH36pT7Z0BRTqLhbk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -329,20 +339,24 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down Expand Up @@ -535,6 +549,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down

0 comments on commit 7bcd5a6

Please sign in to comment.