Skip to content

Commit

Permalink
feat: GCP provider (#143)
Browse files Browse the repository at this point in the history
* feat: add gcp secret manager provider

Signed-off-by: Bence Csati <[email protected]>

* docs: add gcp, update other docs

Signed-off-by: Bence Csati <[email protected]>

* chore: update nix

Signed-off-by: Bence Csati <[email protected]>

* fix(gcp): Remarks

Signed-off-by: Bence Csati <[email protected]>

* fix(test): get env path for args test

Signed-off-by: Bence Csati <[email protected]>

* fix(README): Add AWS SSM to supported providers

Signed-off-by: Bence Csati <[email protected]>

---------

Signed-off-by: Bence Csati <[email protected]>
  • Loading branch information
csatib02 authored May 23, 2024
1 parent 6960099 commit 9d3ccc9
Show file tree
Hide file tree
Showing 18 changed files with 585 additions and 139 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
- **Async loading** - Secrets are loaded asynchronously to improve speed.
- **Renew secrets** - Use daemon mode to renew secrets in the background.

| **Supported Providers** | **Status** |
|--------------------------------------------------------------|----------------|
| Local provider | ✅ Implemented |
| [HashiCorp Vault](https://www.vaultproject.io) | ✅ Implemented |
| [OpenBao](https://github.com/openbao/openbao) | ✅ Implemented |
| [AWS Secrets Manager](https://aws.amazon.com/secrets-manager)| ✅ Implemented |
| **Supported Providers** | **Stability** |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------|
| Local provider | ✅ Production Ready |
| [HashiCorp Vault](https://www.vaultproject.io) | ✅ Production Ready |
| [OpenBao](https://github.com/openbao/openbao) | 🟡 Beta |
| [AWS Secrets Manager](https://aws.amazon.com/secrets-manager) / [AWS Systems Manager Parameter Store](https://aws.amazon.com/systems-manager/features/#Parameter_Store) | ✅ Production Ready |
| [Google Cloud Secret Manager](https://cloud.google.com/secret-manager) | ✅ Production Ready |

## Getting started

Expand Down
11 changes: 9 additions & 2 deletions args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@ package main

import (
"fmt"
"os/exec"
"testing"

"github.com/stretchr/testify/assert"
)

func TestExtractEntrypoint(t *testing.T) {
// Find the path of the env binary
envPath, err := exec.LookPath("env")
if err != nil {
t.Fatalf("failed to find path of env binary: %v", err)
}

tests := []struct {
name string
args []string
Expand All @@ -32,13 +39,13 @@ func TestExtractEntrypoint(t *testing.T) {
{
name: "Valid case with one argument",
args: []string{"secret-init", "env"},
expectedBinaryPath: "/usr/bin/env",
expectedBinaryPath: envPath,
expectedBinaryArgs: []string{},
},
{
name: "Valid case with more than two arguments",
args: []string{"secret-init", "env", "|", "grep", "secrets"},
expectedBinaryPath: "/usr/bin/env",
expectedBinaryPath: envPath,
expectedBinaryArgs: []string{"|", "grep", "secrets"},
},
{
Expand Down
31 changes: 25 additions & 6 deletions env_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/bank-vaults/secret-init/pkg/provider/aws"
"github.com/bank-vaults/secret-init/pkg/provider/bao"
"github.com/bank-vaults/secret-init/pkg/provider/file"
"github.com/bank-vaults/secret-init/pkg/provider/gcp"
"github.com/bank-vaults/secret-init/pkg/provider/vault"
)

Expand All @@ -35,6 +36,7 @@ var supportedProviders = []string{
vault.ProviderName,
bao.ProviderName,
aws.ProviderName,
gcp.ProviderName,
}

// EnvStore is a helper for managing interactions between environment variables and providers,
Expand Down Expand Up @@ -78,6 +80,9 @@ func (s *EnvStore) GetSecretReferences() map[string][]string {

case aws.ProviderName:
secretReferences[aws.ProviderName] = append(secretReferences[aws.ProviderName], envSecretReference)

case gcp.ProviderName:
secretReferences[gcp.ProviderName] = append(secretReferences[gcp.ProviderName], envSecretReference)
}
}

Expand All @@ -97,7 +102,7 @@ func (s *EnvStore) LoadProviderSecrets(ctx context.Context, providerPaths map[st
vaultPaths, ok := providerPaths[vault.ProviderName]
if ok {
var err error
providerSecrets, err = s.workaroundForBao(vaultPaths)
providerSecrets, err = s.workaroundForBao(ctx, vaultPaths)
if err != nil {
return nil, fmt.Errorf("failed to workaround for bao: %w", err)
}
Expand All @@ -115,7 +120,7 @@ func (s *EnvStore) LoadProviderSecrets(ctx context.Context, providerPaths map[st
go func(providerName string, paths []string, errCh chan<- error) {
defer wg.Done()

provider, err := newProvider(providerName, s.appConfig)
provider, err := newProvider(ctx, providerName, s.appConfig)
if err != nil {
errCh <- fmt.Errorf("failed to create provider %s: %w", providerName, err)
return
Expand Down Expand Up @@ -152,15 +157,15 @@ func (s *EnvStore) LoadProviderSecrets(ctx context.Context, providerPaths map[st
}

// Workaround for openBao, essentially loading secretes from Vault first.
func (s *EnvStore) workaroundForBao(vaultPaths []string) ([]provider.Secret, error) {
func (s *EnvStore) workaroundForBao(ctx context.Context, vaultPaths []string) ([]provider.Secret, error) {
var secrets []provider.Secret

provider, err := newProvider(vault.ProviderName, s.appConfig)
provider, err := newProvider(ctx, vault.ProviderName, s.appConfig)
if err != nil {
return nil, fmt.Errorf("failed to create provider %s: %w", vault.ProviderName, err)
}

secrets, err = provider.LoadSecrets(context.Background(), vaultPaths)
secrets, err = provider.LoadSecrets(ctx, vaultPaths)
if err != nil {
return nil, fmt.Errorf("failed to load secrets for provider %s: %w", vault.ProviderName, err)
}
Expand Down Expand Up @@ -204,10 +209,17 @@ func getProviderPath(path string) (string, string) {
return aws.ProviderName, path
}

// Example GCP prefixes:
// gcp:secretmanager:projects/{PROJECT_ID}/secrets/{SECRET_NAME}
// gcp:secretmanager:projects/{PROJECT_ID}/secrets/{SECRET_NAME}/versions/{VERSION|latest}
if strings.HasPrefix(path, "gcp:secretmanager:") {
return gcp.ProviderName, path
}

return "", path
}

func newProvider(providerName string, appConfig *common.Config) (provider.Provider, error) {
func newProvider(ctx context.Context, providerName string, appConfig *common.Config) (provider.Provider, error) {
switch providerName {
case file.ProviderName:
config := file.LoadConfig()
Expand Down Expand Up @@ -250,6 +262,13 @@ func newProvider(providerName string, appConfig *common.Config) (provider.Provid
provider := aws.NewProvider(config)
return provider, nil

case gcp.ProviderName:
provider, err := gcp.NewProvider(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create gcp provider: %w", err)
}
return provider, nil

default:
return nil, fmt.Errorf("provider %s is not supported", providerName)
}
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Discover a range of examples that highlight the functionalities of **secret-init
- [Vault provider](vault-provider.md)
- [Bao provider](bao-provider.md)
- [AWS provider](aws-provider.md)
- [GCP provider](gcp-provider.md)

## Multi provider use-case

Expand Down
13 changes: 5 additions & 8 deletions examples/aws-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Overview

The AWS Provider in Secret-init can load secrets from AWS Secrets Manager and AWS Systems Manager (SSM) Parameter Store as well.
The AWS Provider in Secret-init can load secrets from AWS Secrets Manager and AWS Systems Manager (SSM) Parameter Store as well. This provider interfaces with AWS's API, to fetch and load secrets.

## Prerequisites

Expand All @@ -13,7 +13,7 @@ The AWS Provider in Secret-init can load secrets from AWS Secrets Manager and AW
## Environment setup

```bash
# Secret-ini requires atleast these environment variables to be set properly
# Secret-init requires atleast these environment variables to be set properly
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
export AWS_REGION
Expand All @@ -23,8 +23,8 @@ export AWS_REGION

```bash
# Export environment variables
export MYSQL_PASSWORD=arn:aws:secretsmanager:eu-north-1:123456789:secret:secret/test/mysql-ASD123
export SM_JSON=arn:aws:secretsmanager:eu-north-1:123456789:secret:test/secret/JSON-ASD123
export MYSQL_PASSWORD=arn:aws:secretsmanager:eu-north-1:123456789:secret:bank-vaults/test/mysql-ASD123
export SM_JSON=arn:aws:secretsmanager:eu-north-1:123456789:secret:bank-vaults/test/JSON-ASD123
export SSM_SECRET=arn:aws:ssm:eu-north-1:123456789:parameter/bank-vaults/test

# NOTE: Secret-init is designed to identify any secret-reference that starts with "arn:aws:secretsmanager:" or "arn:aws:ssm:"
Expand All @@ -34,10 +34,7 @@ export SSM_SECRET=arn:aws:ssm:eu-north-1:123456789:parameter/bank-vaults/test

```bash
# Build the secret-init binary
go build

# Use in daemon mode
SECRET_INIT_DAEMON="true"
make build

# Run secret-init with a command e.g.
./secret-init env | grep 'MYSQL_PASSWORD\|SM_JSON\|SSM_SECRET'
Expand Down
6 changes: 5 additions & 1 deletion examples/bao-provider.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Bao-provider

## Overview

The Bao provider in Secret-Init can load secrets from Open-Bao. This provider interfaces with Vault's API via Bank-Vaults's Vault-SDK, to fetch and load secrets.

## Prerequisites

- Golang `>= 1.21`
Expand Down Expand Up @@ -47,7 +51,7 @@ export RABBITMQ_PASSWORD="bao:secret/data/test/rabbitmq#RABBITMQ_PASSWORD"

```bash
# Build the secret-init binary
go build
make build

# Use in daemon mode
export SECRET_INIT_DAEMON="true"
Expand Down
6 changes: 5 additions & 1 deletion examples/file-provider.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# File-provider

## Overview

The File provider in Secret-Init can load secrets from local files.

## Prerequisites

- Golang `>= 1.21`
Expand Down Expand Up @@ -34,7 +38,7 @@ export FILE_SECRET_2=file:$PWD/example/super-secret-value

```bash
# Build the secret-init binary
go build
make build

# Run secret-init with a command e.g.
./secret-init env | grep 'FILE_SECRET_1\|FILE_SECRET_2'
Expand Down
50 changes: 50 additions & 0 deletions examples/gcp-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Google Cloud Provider

## Overview

The Google Cloud Provider in Secret-Init can load secrets from Google Cloud Secret Manager. This provider interfaces with Google Cloud Secret Manager's API, to fetch and load secrets.

## Prerequisites

- Golang `>= 1.21`
- Makefile
- Access to GCP services

## Environment setup

```bash
# Secret-init requires atleast this environment variable to be set properly
export GOOGLE_APPLICATION_CREDENTIALS
```

## Define secrets to inject

```bash
# Export environment variables
export MYSQL_PASSWORD=gcp:secretmanager:projects/123456789123/secrets/bank-vaults_secret-init_test_mysql_password/versions/2
export UNVERSIONED_SECRET=gcp:secretmanager:projects/123456789123/secrets/bank-vaults_secret-init_test
# NOTE: If version is not supplied then latest will be used.

# NOTE: Secret-init is designed to identify any secret-reference that starts with "gcp:secretmanager"
```

## Run secret-init

```bash
# Build the secret-init binary
make build

# Run secret-init with a command e.g.
./secret-init env | grep 'MYSQL_PASSWORD\|UNVERSIONED_SECRET'
```

## Cleanup

```bash
# Remove binary
rm -rf secret-init

# Unset the environment variables
unset MYSQL_PASSWORD
unset UNVERSIONED_SECRET
```
2 changes: 1 addition & 1 deletion examples/multi-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export AWS_ACCESS_KEY_ID=vault:secret/data/test/aws#AWS_ACCESS_KEY_ID

```bash
# Build the secret-init binary
go build
make build

# Use in daemon mode
export SECRET_INIT_DAEMON="true"
Expand Down
6 changes: 5 additions & 1 deletion examples/vault-provider.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Vault-provider

## Overview

The Vault provider in Secret-Init can load secrets from HashiCorp Vault. This provider interfaces with Vault's API via Bank-Vaults's Vault-SDK, to fetch and load secrets.

## Prerequisites

- Golang `>= 1.21`
Expand Down Expand Up @@ -47,7 +51,7 @@ export AWS_ACCESS_KEY_ID=vault:secret/data/test/aws#AWS_ACCESS_KEY_ID

```bash
# Build the secret-init binary
go build
make build

# Use in daemon mode
export SECRET_INIT_DAEMON="true"
Expand Down
Loading

0 comments on commit 9d3ccc9

Please sign in to comment.