Skip to content

Commit

Permalink
✨ Implement vault logic
Browse files Browse the repository at this point in the history
  • Loading branch information
dev-drprasad committed May 8, 2020
1 parent 3000aa1 commit 6ec63de
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/bin
.DS_Store
.test/
12 changes: 11 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ var rootCmd = &cobra.Command{
}

func init() {
// si, err := os.Stdin.Stat()
// if err != nil {
// fmt.Println("could not get stdin info")
// os.Exit(1)
// }
// if si.Mode()&os.ModeCharDevice == os.ModeCharDevice {
// fmt.Println("This binary is a Porter plugin. It is not meant to be executed directly.")
// os.Exit(126)
// }
p = pkg.New()
rootCmd.AddCommand(versionCmd)
rootCmd.SetErr(p.Err)
rootCmd.AddCommand(versionCmd, runCmd)
}

func Execute() error {
Expand Down
17 changes: 17 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cmd

import (
"github.com/dev-drprasad/porter-hashicorp-plugins/pkg"
"github.com/spf13/cobra"
)

var runCmd = &cobra.Command{
Use: "run [implementation]",
Short: "Run the plugin and listen for client connections.",
Args: cobra.ExactValidArgs(1),
ValidArgs: []string{pkg.VaultPluginInterface},
SilenceUsage: true, // Lets not send usage text to caller when error happens
Run: func(cmd *cobra.Command, args []string) {
p.Run(args)
},
}
1 change: 1 addition & 0 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var versionFormat string
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the plugin version",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
opts := version.Options{}
opts.RawFormat = versionFormat
Expand Down
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ module github.com/dev-drprasad/porter-hashicorp-plugins
go 1.13

require (
get.porter.sh/plugin/azure v0.2.0-beta.1
get.porter.sh/porter v0.26.2-beta.1
github.com/Azure/azure-sdk-for-go v19.1.1+incompatible
github.com/cnabio/cnab-go v0.11.0-beta1
github.com/hashicorp/go-hclog v0.9.2
github.com/hashicorp/go-plugin v1.0.1
github.com/hashicorp/vault/api v1.0.4
github.com/pkg/errors v0.8.1
github.com/spf13/cobra v1.0.0
)

Expand Down
52 changes: 52 additions & 0 deletions go.sum

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package main

import "github.com/dev-drprasad/porter-hashicorp-plugins/cmd"
import (
"os"

"github.com/dev-drprasad/porter-hashicorp-plugins/cmd"
)

func main() {
cmd.Execute()
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
}
34 changes: 34 additions & 0 deletions pkg/plugin.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package pkg

import (
"encoding/json"
"fmt"
"strings"

"github.com/dev-drprasad/porter-hashicorp-plugins/pkg/config"
"github.com/dev-drprasad/porter-hashicorp-plugins/pkg/vault"
"github.com/pkg/errors"

"get.porter.sh/porter/pkg/context"
"get.porter.sh/porter/pkg/pkgmgmt"
"get.porter.sh/porter/pkg/plugins"
"get.porter.sh/porter/pkg/porter/version"
"get.porter.sh/porter/pkg/secrets"
plugin "github.com/hashicorp/go-plugin"
)

// These are build-time values, set during an official release
Expand All @@ -14,6 +23,8 @@ var (
Version string
)

const VaultPluginInterface = secrets.PluginInterface + ".hashicorp.vault"

type PluginBox struct {
*context.Context
config.Config
Expand All @@ -25,6 +36,29 @@ func New() *PluginBox {
}
}

func (p *PluginBox) Run(args []string) {
if err := json.NewDecoder(p.In).Decode(&p.Config); err != nil {
fmt.Fprint(p.Err, errors.Wrapf(err, "could not unmarshal config from input"))
}

key := args[0]
parts := strings.Split(key, ".")
// HANDLE index out of range
selectedInterface := parts[0]
var plugin plugin.Plugin
switch key {
case VaultPluginInterface:
plugin = vault.NewPlugin(p.Config)
}

if plugin == nil {
fmt.Fprintf(p.Err, "invalid plugin key specified: %q", key)
}

plugins.Serve(selectedInterface, plugin)

}

func (p *PluginBox) PrintVersion(opts version.Options) error {
metadata := pkgmgmt.Metadata{
Name: "hashicorp",
Expand Down
23 changes: 23 additions & 0 deletions pkg/vault/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package vault

import (
"get.porter.sh/porter/pkg/secrets"
cnabsecrets "github.com/cnabio/cnab-go/secrets"
"github.com/dev-drprasad/porter-hashicorp-plugins/pkg/config"
plugin "github.com/hashicorp/go-plugin"
)

var _ cnabsecrets.Store = &Plugin{}

// Plugin is the plugin wrapper for accessing secrets from Vault.
type Plugin struct {
cnabsecrets.Store
}

func NewPlugin(cfg config.Config) plugin.Plugin {
return &secrets.Plugin{
Impl: &Plugin{
Store: NewStore(cfg),
},
}
}
74 changes: 74 additions & 0 deletions pkg/vault/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package vault

import (
"encoding/json"
"strings"

"get.porter.sh/porter/pkg/secrets"
cnabsecrets "github.com/cnabio/cnab-go/secrets"
"github.com/dev-drprasad/porter-hashicorp-plugins/pkg/config"
"github.com/hashicorp/vault/api"
vaultapi "github.com/hashicorp/vault/api"
"github.com/pkg/errors"
)

var _ cnabsecrets.Store = &Store{}

const (
SecretKeyName = "secret"
)

// Store implements the backing store for secrets in azure key vault.
type Store struct {
config config.Config
client *vaultapi.Client
}

func NewStore(cfg config.Config) cnabsecrets.Store {
s := &Store{
config: cfg,
}

return secrets.NewSecretStore(s)
}

func (s *Store) Connect() error {
if s.client != nil {
return nil
}

config := &vaultapi.Config{
Address: s.config.VaultAddr,
}
client, err := api.NewClient(config)
if err != nil {
return errors.Wrapf(err, "could not connect to vault server with address %s", s.config.VaultAddr)
}
s.client = client
s.client.SetToken("s.BRGSWg7rIGxfq4ZsBQiCZ8Ki")

return nil
}

func (s *Store) Resolve(keyName string, keyValue string) (string, error) {
if strings.ToLower(keyName) != SecretKeyName {
return "", errors.Errorf("cannot resolve unsupported keyName '%s'. Vault plugin only supports '%s' right now", keyName, SecretKeyName)
}

vaultSecret, err := s.client.Logical().Read(s.config.PathPrefix + "/data/" + keyValue)
if err != nil || vaultSecret == nil {
panic(err)
}

data, ok := vaultSecret.Data["data"]
if !ok {
return "", errors.New("property 'data' does not exist in secret")
}

secretB, err := json.Marshal(data)
if err != nil {
return "", errors.Wrap(err, "could not marshal secret data")
}

return string(secretB), nil
}

0 comments on commit 6ec63de

Please sign in to comment.