-
Notifications
You must be signed in to change notification settings - Fork 4
Initial HTTP server implementation #1
Changes from all commits
1f15f4d
6e5148d
064737b
2068a19
64ac420
e50dd28
2762e04
35a8042
42305ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module github.com/keylockerbv/secrethub-clientd | ||
|
||
require ( | ||
github.com/gorilla/mux v1.7.0 | ||
github.com/keylockerbv/secrethub-go v0.0.0-20190225132925-244d98858e9d | ||
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b // indirect | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
bitbucket.org/zombiezen/cardcpx v0.0.0-20150417151802-902f68ff43ef h1:Y5Zf3CYdrdGE7GOuK/MNN98GS1V8mOfeiJlISrKUcEo= | ||
bitbucket.org/zombiezen/cardcpx v0.0.0-20150417151802-902f68ff43ef/go.mod h1:ZJR5FpaQx7Bt2bzIV3gBaCInI1+kG949WhNYYlRr8eA= | ||
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/certifi/gocertifi v0.0.0-20190105021004-abcd57078448 h1:8tNk6SPXzLDnATTrWoI5Bgw9s/x4uf0kmBpk21NZgI4= | ||
github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= | ||
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= | ||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= | ||
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= | ||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= | ||
github.com/go-chi/chi v4.0.1+incompatible h1:RSRC5qmFPtO90t7pTL0DBMNpZFsb/sHF3RXVlDgFisA= | ||
github.com/go-chi/chi v4.0.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= | ||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= | ||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= | ||
github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= | ||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= | ||
github.com/keylockerbv/secrethub-go v0.0.0-20190225132925-244d98858e9d h1:NxCFGfkmBF9RaloxF5c/J5knS3FE/g+uWOZ9ENucc1M= | ||
github.com/keylockerbv/secrethub-go v0.0.0-20190225132925-244d98858e9d/go.mod h1:U086plZMagUfy92G4DgCsRAns20Q5j+Rf8bYDXiDxMw= | ||
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= | ||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | ||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= | ||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= | ||
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/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | ||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= | ||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= | ||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= | ||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M= | ||
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||
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= |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"net/http" | ||
"os" | ||
|
||
"github.com/gorilla/mux" | ||
"github.com/keylockerbv/secrethub-go/pkg/api" | ||
"github.com/keylockerbv/secrethub-go/pkg/errio" | ||
"github.com/keylockerbv/secrethub-go/pkg/secrethub" | ||
) | ||
|
||
var ( | ||
credential string | ||
credentialPassphrase string | ||
port int | ||
client secrethub.Client | ||
) | ||
|
||
func init() { | ||
flag.StringVar(&credential, "C", "", "(Required) SecretHub credential") | ||
flag.StringVar(&credentialPassphrase, "P", "", "Passphrase to unlock SecretHub credential") | ||
flag.IntVar(&port, "p", 8080, "HTTP port to listen on") | ||
flag.Parse() | ||
|
||
if credential == "" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to see these flags either sourced from:
It's not entirely necessary for the MVP, but it would be very nice to make it consistent with current CLI behavior. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice if the same DRY function could be used there. What do you think @SimonBarendse? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that would be the preferred end-state. However, I think for now it’s better to duplicate it in an internal package, so that the cli open-source release doesnt become a blocker for the terrraform open-source release. If we use the same signature, we can replace it (deduplicate) with the cli package when that is open-source. |
||
flag.Usage() | ||
exit(fmt.Errorf("credential is required")) | ||
} | ||
|
||
cred, err := secrethub.NewCredential(credential, credentialPassphrase) | ||
if err != nil { | ||
exit(err) | ||
} | ||
|
||
client = secrethub.NewClient(cred, nil) | ||
} | ||
|
||
func main() { | ||
err := startHTTPServer() | ||
if err != nil { | ||
exit(err) | ||
} | ||
} | ||
|
||
func startHTTPServer() error { | ||
mux := mux.NewRouter() | ||
v1 := mux.PathPrefix("/v1/").Subrouter() | ||
|
||
v1.PathPrefix("/secrets/").Handler( | ||
http.StripPrefix("/v1/secrets/", http.HandlerFunc(handleSecret)), | ||
) | ||
|
||
fmt.Println("SecretHub Clientd started, press ^C to exit") | ||
return http.ListenAndServe(fmt.Sprintf(":%v", port), mux) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
} | ||
|
||
func handleSecret(w http.ResponseWriter, r *http.Request) { | ||
path := r.URL.Path | ||
err := api.ValidateSecretPath(path) | ||
if err != nil { | ||
w.WriteHeader(http.StatusBadRequest) | ||
io.WriteString(w, err.Error()) | ||
return | ||
} | ||
|
||
switch r.Method { | ||
case "GET": | ||
secret, err := client.Secrets().Versions().GetWithData(path) | ||
if err != nil { | ||
var errCode int | ||
|
||
if err, ok := err.(errio.PublicStatusError); ok { | ||
errCode = err.StatusCode | ||
} | ||
|
||
if errCode == 0 { | ||
errCode = http.StatusInternalServerError | ||
} | ||
|
||
w.WriteHeader(errCode) | ||
io.WriteString(w, err.Error()) | ||
return | ||
} | ||
|
||
w.WriteHeader(http.StatusOK) | ||
w.Write(secret.Data) | ||
case "POST": | ||
secret, err := ioutil.ReadAll(r.Body) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
io.WriteString(w, err.Error()) | ||
return | ||
} | ||
|
||
_, err = client.Secrets().Write(path, secret) | ||
mackenbach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
var errCode int | ||
|
||
if err, ok := err.(errio.PublicStatusError); ok { | ||
errCode = err.StatusCode | ||
} | ||
|
||
switch err { | ||
case secrethub.ErrCannotWriteToVersion, | ||
SimonBarendse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
secrethub.ErrEmptySecret, | ||
secrethub.ErrSecretTooBig: | ||
errCode = http.StatusBadRequest | ||
} | ||
|
||
if errCode == 0 { | ||
errCode = http.StatusInternalServerError | ||
} | ||
|
||
w.WriteHeader(errCode) | ||
io.WriteString(w, err.Error()) | ||
return | ||
} | ||
|
||
w.WriteHeader(http.StatusCreated) | ||
default: | ||
w.Header().Add("Allow", "GET, POST") | ||
w.WriteHeader(http.StatusMethodNotAllowed) | ||
} | ||
} | ||
|
||
func exit(err error) { | ||
florisvdg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fmt.Printf("secrethub-clientd: error: %v\n", err) | ||
os.Exit(1) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SecretHub CLI has a
--credential-passphrase
flag with a shortcut-p
. Not sure what we want to do here