Skip to content
This repository has been archived by the owner on Jun 11, 2019. It is now read-only.

Commit

Permalink
removed support for deployment time encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandernilsson committed Dec 14, 2015
1 parent 293ad0e commit 66d463b
Show file tree
Hide file tree
Showing 12 changed files with 53 additions and 153 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
secretary*
target
coverage.txt
.vscode
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ clean:
rm -f ./secretary

docker:
docker build -t mikljohansson/secretary:latest .
docker build -t meltwater/secretary:latest .

.PHONY: get fmt build test clean
28 changes: 5 additions & 23 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,22 @@ func newKeyCrypto(publicKey *[32]byte, privateKey *[32]byte) *KeyCrypto {
// Decrypts using the secretary daemon
type RemoteCrypto struct {
DaemonUrl, AppId, AppVersion, TaskId string
ConfigKey, MasterKey, DeployKey, ServiceKey *[32]byte
MasterKey, DeployKey, ServiceKey *[32]byte
}

func newRemoteCrypto(
daemonUrl string, appId string, appVersion string, taskId string,
configKey *[32]byte, masterKey *[32]byte, deployKey *[32]byte, serviceKey *[32]byte) *RemoteCrypto {
masterKey *[32]byte, deployKey *[32]byte, serviceKey *[32]byte) *RemoteCrypto {
return &RemoteCrypto{
DaemonUrl: daemonUrl, AppId: appId, AppVersion: appVersion, TaskId: taskId,
ConfigKey: configKey, MasterKey: masterKey, DeployKey: deployKey, ServiceKey: serviceKey}
MasterKey: masterKey, DeployKey: deployKey, ServiceKey: serviceKey}
}

func (self *RemoteCrypto) Decrypt(envelope string) ([]byte, error) {
// Authenticate with config key and decrypt with deploy key
requestedSecret, deployNonce, err := decryptEnvelopeNonce(self.ConfigKey, self.DeployKey, envelope)
if err != nil {
return nil, errors.New(fmt.Sprintf("Failed to decrypt secret parameter using config key and deploy key (%s)", err))
}

var serviceNonce string
if self.ServiceKey != nil {
// Authenticate with config key and decrypt with optional service key
serviceEnvelope, nonce, err := decryptEnvelopeNonce(self.ConfigKey, self.ServiceKey, string(requestedSecret))
if err != nil {
return nil, errors.New(fmt.Sprintf("Failed to decrypt secret parameter using config key and service key (%s)", err))
}

requestedSecret = serviceEnvelope
serviceNonce = encode(nonce[:])
}

message := DaemonRequest{
AppId: self.AppId, AppVersion: self.AppVersion, TaskId: self.TaskId,
RequestedSecret: string(requestedSecret),
DeployNonce: encode(deployNonce[:]), ServiceNonce: serviceNonce}
RequestedSecret: envelope,
}
encoded, err := json.Marshal(message)
if err != nil {
return nil, err
Expand Down
74 changes: 13 additions & 61 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ func TestRemoteCrypto(t *testing.T) {
// Start secretary daemon
handler := decryptEndpointHandler(marathon.URL,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/config-private-key.pem"),
pemRead("./resources/test/keys/master-private-key.pem"))

daemon := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -70,26 +69,25 @@ func TestRemoteCrypto(t *testing.T) {
http.Error(w, fmt.Sprintf("Bad URL %s", r.URL.Path), http.StatusNotFound)
}
}))

defer daemon.Close()

deployPrivateKey, err := pemDecode("8Cw5ysGd14dRObahAX/MtPrkmc7tOVj6OX5lM8HxerI=")
assert.Nil(t, err)

appId, appVersion, taskId := "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"
badAppVersion, badTaskId := "2015-11-04T12:25:08.426Z", "demo_webapp.0f844265-9a82-11e5-94c7-6a515f434e2d"
deployServiceKeySecret := "ENC[NACL,9eXE3SFcX28qlijqHLUm47HbrMtIL6xJtcTLrc5Ucr3yvgRBNesFmSVFYqWqsKRlaPZUE5s124dpNOwUsMFuJpUFuPle9mi037UMReKrdXs/vSbOcRoJUWkGUxyXRywj4LS4dBlea2y9eVIYYHYHQDC4DFGaVd/2wftoGseph1pC1+026CCuzXgVphS0d5u+3gsgi5WMnLOTDVp8TQpsptW64sn/RrulWsp4Ci2O9c0Nqt+PFNlB70GZQlz7aWSQjCkBTbdCDwlwPA==]"
deployKeySecret := "ENC[NACL,5Jje+wI4faU6ilAjwkJmehY1THiRi6Lj+IcrgWuom7dn0HDM10aQdt2C4PQJLyjhZr8md0m5KVfAGi23aRFB5vKw30QCNBx4pIBHhgm0vP/W1/2DOf2KQr3Z+zPo0smoC0m54ugauBTuFpWf/QTKUuW1]"
encryptedSecret := "ENC[NACL,jpDAHM6WZe/1C93FLHd2M916U9AQwjT3VdvzQ7JHTHc57dLXsGE+oI8wDE2Fiw==]"

// Test decryption with both deploy and service keys
{
crypto := newRemoteCrypto(daemon.URL,
appId, appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey,
pemRead("./resources/test/keys/myservice-private-key.pem"))

plaintext, err := crypto.Decrypt(deployServiceKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.Nil(t, err)
assert.Equal(t, "secret", string(plaintext))
}
Expand All @@ -98,11 +96,10 @@ func TestRemoteCrypto(t *testing.T) {
{
crypto := newRemoteCrypto(daemon.URL,
"/demo/webapp2", appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey, nil)

plaintext, err := crypto.Decrypt(deployKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.Nil(t, err)
assert.Equal(t, "secret", string(plaintext))
}
Expand All @@ -111,7 +108,6 @@ func TestRemoteCrypto(t *testing.T) {
{
crypto := newRemoteCrypto(daemon.URL,
"/demo/webapp2", appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey, nil)

Expand All @@ -125,70 +121,52 @@ func TestRemoteCrypto(t *testing.T) {
{
crypto := newRemoteCrypto(daemon.URL,
appId, appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
pemRead("./resources/test/keys/bad-private-key.pem"),
pemRead("./resources/test/keys/myservice-private-key.pem"))

plaintext, err := crypto.Decrypt(deployServiceKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt secret parameter using config key and deploy key (Failed to decrypt (incorrect keys?))", err.Error())
assert.Equal(t, "Failed to decrypt using daemon (HTTP 400 Error: Failed to authenticate/decrypt request using deploy and master key (incorrect master key or hacking attempt? (Failed to decrypt (incorrect keys?))))", err.Error())
}

// Test decryption with bad service key
{
crypto := newRemoteCrypto(daemon.URL,
appId, appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey,
pemRead("./resources/test/keys/bad-private-key.pem"))

plaintext, err := crypto.Decrypt(deployServiceKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt secret parameter using config key and service key (Failed to decrypt (incorrect keys?))", err.Error())
assert.Equal(t, "Failed to decrypt using daemon (HTTP 400 Error: Failed to authenticate/decrypt request using service and master key (incorrect master key or hacking attempt? (Failed to decrypt (incorrect keys?))))", err.Error())
}

// Test with a bad master key
{
crypto := newRemoteCrypto(daemon.URL,
"/demo/webapp", appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/bad-public-key.pem"),
deployPrivateKey, nil)

plaintext, err := crypto.Decrypt(deployKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt using daemon (HTTP 400 Error: Failed to authenticate/decrypt request using deploy and master key (incorrect master key or hacking attempt? (Failed to decrypt (incorrect keys?))))", err.Error())
}

// Test with a bad config key
{
crypto := newRemoteCrypto(daemon.URL,
"/demo/webapp", appVersion, taskId,
pemRead("./resources/test/keys/bad-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey, nil)

plaintext, err := crypto.Decrypt(deployKeySecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt secret parameter using config key and deploy key (Failed to decrypt (incorrect keys?))", err.Error())
}

// Test with a bad service key
{
crypto := newRemoteCrypto(daemon.URL,
appId, badAppVersion, badTaskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey,
pemRead("./resources/test/keys/myservice-private-key.pem"))

plaintext, err := crypto.Decrypt(deployServiceKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt using daemon (HTTP 400 Error: Failed to authenticate/decrypt request using service and master key (incorrect master key or hacking attempt? (Failed to decrypt (incorrect keys?))))", err.Error())
Expand All @@ -198,12 +176,11 @@ func TestRemoteCrypto(t *testing.T) {
{
crypto := newRemoteCrypto(daemon.URL,
appId, appVersion, badTaskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey,
pemRead("./resources/test/keys/myservice-private-key.pem"))

plaintext, err := crypto.Decrypt(deployServiceKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt using daemon (HTTP 500 Error: Given taskId is not running (bug or hacking attempt?))", err.Error())
Expand All @@ -212,58 +189,33 @@ func TestRemoteCrypto(t *testing.T) {
// Test with a bad config public key
handler = decryptEndpointHandler(marathon.URL,
pemRead("./resources/test/keys/bad-public-key.pem"),
pemRead("./resources/test/keys/config-private-key.pem"),
pemRead("./resources/test/keys/master-private-key.pem"))

{
crypto := newRemoteCrypto(daemon.URL,
appId, appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey,
pemRead("./resources/test/keys/myservice-private-key.pem"))

plaintext, err := crypto.Decrypt(deployServiceKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt using daemon (HTTP 400 Error: Failed to decrypt plaintext secret, incorrect config or master key? (Failed to decrypt (incorrect keys?)))", err.Error())
}

// Test with a bad config private key
handler = decryptEndpointHandler(marathon.URL,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/bad-private-key.pem"),
pemRead("./resources/test/keys/master-private-key.pem"))

{
crypto := newRemoteCrypto(daemon.URL,
appId, appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey,
pemRead("./resources/test/keys/myservice-private-key.pem"))

plaintext, err := crypto.Decrypt(deployServiceKeySecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt using daemon (HTTP 401 Error: Given secret isn't part of app config (bug or hacking attempt?))", err.Error())
}

// Test with a bad master private key
handler = decryptEndpointHandler(marathon.URL,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/config-private-key.pem"),
pemRead("./resources/test/keys/bad-private-key.pem"))

{
crypto := newRemoteCrypto(daemon.URL,
appId, appVersion, taskId,
pemRead("./resources/test/keys/config-public-key.pem"),
pemRead("./resources/test/keys/master-public-key.pem"),
deployPrivateKey,
pemRead("./resources/test/keys/myservice-private-key.pem"))

plaintext, err := crypto.Decrypt(deployServiceKeySecret)
plaintext, err := crypto.Decrypt(encryptedSecret)
assert.NotNil(t, err)
assert.Nil(t, plaintext)
assert.Equal(t, "Failed to decrypt using daemon (HTTP 400 Error: Failed to authenticate/decrypt request using deploy and master key (incorrect master key or hacking attempt? (Failed to decrypt (incorrect keys?))))", err.Error())
Expand Down
39 changes: 6 additions & 33 deletions daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ type DaemonRequest struct {

// Secret encrypted with master key
RequestedSecret string

// Nonces that was used when encrypting the config secret
DeployNonce, ServiceNonce string
}

type DaemonResponse struct {
Expand Down Expand Up @@ -57,34 +54,10 @@ func decryptRequest(app *MarathonApp, masterKey *[32]byte, serviceEnvelope strin
return &request, nil
}

func verifyAuthorization(app *MarathonApp, request *DaemonRequest, configPrivateKey *[32]byte) (bool, error) {
// Recreate encrypted secret as expected in the repo
secret := request.RequestedSecret
if app.ServiceKey != nil {
nonce, err := decodeNonce(request.ServiceNonce)
if err != nil {
return false, err
}

secret, err = encryptEnvelopeNonce(app.ServiceKey, configPrivateKey, []byte(secret), nonce)
if err != nil {
return false, err
}
}

nonce, err := decodeNonce(request.DeployNonce)
if err != nil {
return false, err
}

encrypted, err := encryptEnvelopeNonce(app.DeployKey, configPrivateKey, []byte(secret), nonce)
if err != nil {
return false, err
}

func verifyAuthorization(app *MarathonApp, request *DaemonRequest) (bool, error) {
// Verify that encrypted string is present in app config
for _, value := range app.Env {
if value == string(encrypted) {
if value == request.RequestedSecret {
return true, nil
}
}
Expand Down Expand Up @@ -117,7 +90,7 @@ func encryptResponse(app *MarathonApp, masterKey *[32]byte, plaintext []byte) ([
return []byte(encrypted), nil
}

func decryptEndpointHandler(marathonUrl string, configPublicKey *[32]byte, configPrivateKey *[32]byte, masterKey *[32]byte) func(http.ResponseWriter, *http.Request) {
func decryptEndpointHandler(marathonUrl string, configPublicKey *[32]byte, masterKey *[32]byte) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
errorResponse(w, r, "Expected POST method", http.StatusMethodNotAllowed)
Expand Down Expand Up @@ -156,7 +129,7 @@ func decryptEndpointHandler(marathonUrl string, configPublicKey *[32]byte, confi
}

// Verify that the secret is actually part of the service's config
ok, err := verifyAuthorization(app, request, configPrivateKey)
ok, err := verifyAuthorization(app, request)
if !ok || err != nil {
errorResponse(w, r, err, http.StatusUnauthorized)
return
Expand All @@ -179,8 +152,8 @@ func decryptEndpointHandler(marathonUrl string, configPublicKey *[32]byte, confi
}
}

func daemonCommand(listenAddress string, marathonUrl string, configPublicKey *[32]byte, configPrivateKey *[32]byte, masterKey *[32]byte) {
http.HandleFunc("/v1/decrypt", decryptEndpointHandler(marathonUrl, configPublicKey, configPrivateKey, masterKey))
func daemonCommand(listenAddress string, marathonUrl string, configPublicKey *[32]byte, masterKey *[32]byte) {
http.HandleFunc("/v1/decrypt", decryptEndpointHandler(marathonUrl, configPublicKey, masterKey))
log.Printf("Daemon listening on %s", listenAddress)
log.Fatal(http.ListenAndServe(listenAddress, nil))
}
Loading

0 comments on commit 66d463b

Please sign in to comment.