Skip to content
This repository was archived by the owner on Feb 16, 2023. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ require (
github.com/alecthomas/kingpin v1.3.8-0.20200323085623-b6657d9477a6
github.com/atotto/clipboard v0.1.2
github.com/aws/aws-sdk-go v1.25.49
github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5
github.com/docker/go-units v0.3.3
github.com/fatih/color v1.7.0
github.com/john-pierce/procspy v0.0.0-20191229154840-1689d734233b
github.com/masterzen/winrm v0.0.0-20190308153735-1d17eaf15943
github.com/mattn/go-colorable v0.1.1
github.com/mattn/go-isatty v0.0.7
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/go-ps v1.0.0
github.com/mitchellh/mapstructure v1.1.2
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/secrethub/demo-app v0.1.0
Expand Down
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5Vpd
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alvaroloes/enumer v1.1.2 h1:5khqHB33TZy1GWCO/lZwcroBFh7u+0j40T83VUbfAMY=
github.com/alvaroloes/enumer v1.1.2/go.mod h1:FxrjvuXoDAx9isTJrv4c+T410zFi0DtXIT0m65DJ+Wo=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/atotto/clipboard v0.1.2 h1:YZCtFu5Ie8qX2VmVTBnrqLSiU9XOWwqNRmdT3gIQzbY=
Expand All @@ -20,6 +22,8 @@ github.com/aws/aws-sdk-go v1.19.38 h1:WKjobgPO4Ua1ww2NJJl2/zQNreUZxvqmEzwMlRjjm9
github.com/aws/aws-sdk-go v1.19.38/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.25.49 h1:j5R2Ey+g8qaiy2NJ9iH+KWzDWS4SjXRCjhc22EeQVE4=
github.com/aws/aws-sdk-go v1.25.49/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 h1:BjkPE3785EwPhhyuFkbINB+2a1xATwk8SNDWnJiD41g=
github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5/go.mod h1:jtAfVaU/2cu1+wdSRPWE2c1N2qeAA3K4RH9pYgqwets=
github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU=
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
Expand All @@ -42,6 +46,8 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/john-pierce/procspy v0.0.0-20191229154840-1689d734233b h1:7aPSSKrDkCDih93KBe2CYX6jYOg+DGwR9RT+KPFOMzo=
github.com/john-pierce/procspy v0.0.0-20191229154840-1689d734233b/go.mod h1:KYfx4NvMycLeRE8w0OmgF+QNX/gSPTE9m/e5PcUXchw=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand All @@ -62,10 +68,14 @@ github.com/mattn/go-shellwords v1.0.6 h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3Zk
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1 h1:/I3lTljEEDNYLho3/FUB7iD/oc2cEFgVmbHzV+O0PtU=
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1/go.mod h1:eD5JxqMiuNYyFNmyY9rkJ/slN8y59oEu4Ei7F8OoKWQ=
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/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
Expand All @@ -84,6 +94,8 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/weaveworks/procspy v0.0.0-20150706124340-cb970aa190c3 h1:UC4iN/yCDCObTBhKzo34/R2U6qptTPmqbzG6UiQVMUQ=
github.com/weaveworks/procspy v0.0.0-20150706124340-cb970aa190c3/go.mod h1:cJTfuBcxkdbj8Mabk4PPdaf0AXv9TYEJmkFxKcWxYY4=
github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 h1:U5I57s4ISLpeeLYl8b3MsainSSh9F+mRXauln37b50I=
github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07/go.mod h1:XlXBIfkGawHNVOHlenOaBW7zlfCh8LovwjOgjamYnkQ=
golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
Expand All @@ -92,14 +104,18 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exq
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190524210228-3d17549cdc6b h1:iEAPfYPbYbxG/2lNN4cMOHkmgKNsCuUwkxlDCK46UlU=
golang.org/x/tools v0.0.0-20190524210228-3d17549cdc6b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
20 changes: 20 additions & 0 deletions internals/integrations/tfstate/backend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package tfstate

import (
"fmt"
"io"
)

type Backend interface {
Serve() error
}

type prefixWriter struct {
io.Writer
prefix string
}

func (l prefixWriter) Write(p []byte) (int, error) {
_, err := fmt.Fprintf(l.Writer, "%s%s", l.prefix, p)
return len(p), err
}
189 changes: 189 additions & 0 deletions internals/integrations/tfstate/backend_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// +build !windows !386

package tfstate

import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"

"github.com/secrethub/secrethub-go/internals/api"
"github.com/secrethub/secrethub-go/pkg/secrethub"
"github.com/secrethub/secrethub-go/pkg/secretpath"
)

type backend struct {
client secrethub.ClientInterface
port uint16
logger io.Writer
}

func New(client secrethub.ClientInterface, port uint16, logger io.Writer) Backend {
return &backend{
client: client,
port: port,
logger: prefixWriter{
Writer: logger,
prefix: "[SecretHub]: ",
},
}
}

func (b *backend) Serve() error {
server := &http.Server{
Addr: fmt.Sprintf("127.0.0.1:%d", b.port),
Handler: http.HandlerFunc(b.Handle),
}
err := server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
return err
}

return nil
}

func (b *backend) Handle(w http.ResponseWriter, r *http.Request) {
resp, err := b.handle(r)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(b.logger, "Encountered an unexpected error: %s\n", err)
return
}
w.WriteHeader(resp.code)
fmt.Fprintf(w, resp.body)
}

type statusResponse struct {
code int
body string
}

func (b *backend) respondError(statusCode int, format string, a ...interface{}) *statusResponse {
msg := fmt.Sprintf(format, a...)
fmt.Fprintf(b.logger, "%s\n", msg)
return &statusResponse{
code: statusCode,
body: msg,
}
}

func (b *backend) handle(r *http.Request) (*statusResponse, error) {
isChild, err := connectionFromChildProcess(os.Getpid(), r)
if err != nil {
return nil, err
}
if !isChild {
return b.respondError(http.StatusForbidden, "can only be reached from a process spawned with secrethub run"), nil
}

body, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, fmt.Errorf("reading request body: %s", err)
}

path, password, ok := r.BasicAuth()
if !ok {
return b.respondError(http.StatusBadRequest, "`username` field must be set to the SecretHub directory where the Terraform state should be stored (for example `<org>/<repo>/terraform-state`)"), nil
}

if secretpath.Count(path) < 2 {
return b.respondError(http.StatusBadRequest, "`username` field must be set to the SecretHub directory where the Terraform state should be stored (for example `<org>/<repo>/terraform-state`), got: %s", path), nil
}

statePath := secretpath.Join(path, "state")
lockPath := secretpath.Join(path, "lock")
passwordPath := secretpath.Join(path, "password")

if _, err := b.client.Dirs().GetTree(path, 0, false); api.IsErrNotFound(err) {
return b.respondError(http.StatusBadRequest, "`%s` is not a directory on SecretHub", path), nil
}

secret, err := b.client.Secrets().ReadString(passwordPath)
if err != nil && !api.IsErrNotFound(err) {
return nil, err
} else if err == nil {
if password == "" {
return b.respondError(http.StatusUnauthorized, "password stored at %s should be set as auth password", passwordPath), nil
}
if password != secret {
return b.respondError(http.StatusForbidden, "provided password does not match password stored at %s", passwordPath), nil
}
}

switch r.Method {
case http.MethodGet:
secret, err := b.client.Secrets().Read(statePath)
if api.IsErrNotFound(err) {
return &statusResponse{code: http.StatusNotFound}, nil
} else if err != nil {
return nil, err
}

return &statusResponse{
code: http.StatusOK,
body: string(secret.Data),
}, nil
case http.MethodPost:
_, err = b.client.Secrets().Write(statePath, body)
if api.IsErrNotFound(err) {
return b.respondError(http.StatusNotFound, err.Error()), nil
} else if err != nil {
return nil, err
}
return &statusResponse{
code: http.StatusOK,
}, nil
case "LOCK":
currentLock, err := b.client.Secrets().Versions().GetWithData(lockPath + ":1")
if err == nil {
return &statusResponse{
code: http.StatusLocked,
body: string(currentLock.Data),
}, nil
} else if !api.IsErrNotFound(err) {
return nil, err
}

res, err := b.client.Secrets().Write(lockPath, body)
if api.IsErrNotFound(err) {
return b.respondError(http.StatusNotFound, err.Error()), nil
} else if err != nil {
return nil, err
}
if res.Version != 1 {
return &statusResponse{
code: http.StatusLocked,
}, nil
}
return &statusResponse{
code: http.StatusOK,
}, nil

case "UNLOCK":
secret, err := b.client.Secrets().Read(lockPath)
if api.IsErrNotFound(err) {
return &statusResponse{
code: http.StatusOK,
body: "not locked",
}, nil
}

if len(body) > 0 && !bytes.Equal(body, secret.Data) {
return b.respondError(http.StatusBadRequest, "incorrect lock"), nil
}

err = b.client.Secrets().Delete(lockPath)
if err != nil {
return nil, err
}
return &statusResponse{
code: http.StatusOK,
}, nil
default:
return nil, errors.New("received an unexpected request")
}
}
21 changes: 21 additions & 0 deletions internals/integrations/tfstate/backend_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// +build windows,386

package tfstate

import (
"errors"
"io"

"github.com/secrethub/secrethub-go/pkg/secrethub"
)

type notSupportedBackend struct {
}

func New(client secrethub.ClientInterface, port uint16, logger io.Writer) Backend {
return &notSupportedBackend{}
}

func (b *notSupportedBackend) Serve() error {
return errors.New("tfstate backend currently not supported on Windows i386")
}
50 changes: 50 additions & 0 deletions internals/integrations/tfstate/pid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// +build !windows !386

package tfstate

import (
"net"
"net/http"
"strconv"
"strings"

"github.com/mitchellh/go-ps"
)

func connectionFromChildProcess(pid int, r *http.Request) (bool, error) {
split := strings.Split(r.RemoteAddr, ":")
host := net.ParseIP(split[0])
port64, err := strconv.ParseUint(split[1], 10, 16)
if err != nil {
return false, err
}
port := uint16(port64)

socks, err := tcpSocks()
if err != nil {
return false, err
}
for _, c := range socks {
if c.LocalAddress.Equal(host) && c.LocalPort == port {
nextProcess := c.Process.PID
for {
if nextProcess == pid {
return true, nil
}
if nextProcess == 1 {
break
}
parent, err := ps.FindProcess(nextProcess)
if err != nil {
return false, err
}
if parent == nil {
break
}

nextProcess = parent.PPid()
}
}
}
return false, nil
}
18 changes: 18 additions & 0 deletions internals/integrations/tfstate/socks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package tfstate

import (
"net"
)

type Connection struct {
LocalAddress net.IP
LocalPort uint16
RemoteAddress net.IP
RemotePort uint16
Process
}

type Process struct {
PID int
Name string
}
Loading