Skip to content

Commit

Permalink
Merge pull request #82 from OperationSpark/feat/sign-snap-mail-requests
Browse files Browse the repository at this point in the history
Sign SNAP mail requests
  • Loading branch information
harveysanders authored Nov 7, 2023
2 parents 47b98d5 + e8f389a commit 94c7ffc
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 8 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ jobs:
OS_RENDERING_SERVICE_URL=${{secrets.OS_RENDERING_SERVICE_URL}},
SNAP_MAIL_URL=${{secrets.SNAP_MAIL_URL}},
MONGO_URI=${{secrets.MONGO_URI}},
SIGNING_SECRET=${{secrets.SIGNING_SECRET}},
APP_ENV=staging
- id: "trigger-url"
run: 'echo "${{ steps.deploy.outputs.url }}"'
1 change: 1 addition & 0 deletions .github/workflows/deploy-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jobs:
OS_RENDERING_SERVICE_URL=${{secrets.OS_RENDERING_SERVICE_URL}},
SNAP_MAIL_URL=${{secrets.SNAP_MAIL_URL}},
MONGO_URI=${{secrets.MONGO_URI}},
SIGNING_SECRET=${{secrets.SIGNING_SECRET}},
APP_ENV=testing
- id: "trigger-url"
run: 'echo "${{ steps.deploy.outputs.url }}"'
3 changes: 2 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ jobs:
OS_MESSAGING_SERVICE_URL=${{secrets.OS_MESSAGING_SERVICE_URL}},
OS_RENDERING_SERVICE_URL=${{secrets.OS_RENDERING_SERVICE_URL}},
SNAP_MAIL_URL=${{secrets.SNAP_MAIL_URL}},
MONGO_URI=${{secrets.MONGO_URI}}
MONGO_URI=${{secrets.MONGO_URI}},
SIGNING_SECRET=${{secrets.SIGNING_SECRET}}
- id: "trigger-url"
run: 'echo "${{ steps.deploy.outputs.url }}"'
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Session Sign Up Service

![Coverage](https://img.shields.io/badge/Coverage-55.5%25-yellow)
![Coverage](https://img.shields.io/badge/Coverage-56.1%25-yellow)

When someone signs up for an Info Session on [operationspark.org](https://operationspark.org),
this service runs a series of tasks:
Expand Down
20 changes: 20 additions & 0 deletions reqsign.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package signup

import (
"crypto"
"crypto/hmac"
"fmt"
)

// CreateSignature take a request body and a secret and returns a signature. The signature is hex encoded and prefixed with "sha256=".
func createSignature(body []byte, secret []byte) ([]byte, error) {
mac := hmac.New(crypto.SHA256.New, secret)
_, err := mac.Write(body)
if err != nil {
return nil, fmt.Errorf("mac.Write: %w", err)

}
calculatedMAC := mac.Sum(nil)
signature := []byte(fmt.Sprintf("sha256=%x", calculatedMAC))
return signature, nil
}
19 changes: 19 additions & 0 deletions reqsign_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package signup

import (
"testing"

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

func TestCreateSignature(t *testing.T) {
t.Run("returns a signature", func(t *testing.T) {
secret := []byte("It's a Secret to Everybody")
payload := []byte("Hello, World!")
want := []byte("sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17")

got, err := createSignature(payload, secret)
require.NoError(t, err)
require.Equal(t, want, got)
})
}
8 changes: 7 additions & 1 deletion signup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -754,12 +754,18 @@ func TestSnapMail(t *testing.T) {
mockSnapServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assertEqual(t, r.URL.Path, "/events")

signature := r.Header.Get("X-Signature-256")
assertEqual(t, signature, "sha256=d0c60e4c56076f1128f496fe7e6d4f696c5e8684ff407a3f25c95371e4bd9fbc")

gotJSON, err := io.ReadAll(r.Body)
assertNilError(t, err)
assertEqual(t, string(gotJSON), wantJSON)
}))

err := NewSnapMail(mockSnapServer.URL).run(context.Background(), su)
signingKey := "testkey"

err := NewSnapMail(mockSnapServer.URL, WithSigningSecret(signingKey)).run(context.Background(), su)

assertNilError(t, err)

})
Expand Down
24 changes: 19 additions & 5 deletions snapmail.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import (
)

type SnapMail struct {
url string // Service HTTP endpoint
client *http.Client
url string // Service HTTP endpoint
client *http.Client
signingSecret []byte // Secret used to sign the request body
}

type Payload struct {
Expand Down Expand Up @@ -75,14 +76,21 @@ func (sm *SnapMail) run(ctx context.Context, signup Signup) error {
return err
}

signature, err := createSignature(payload, sm.signingSecret)
if err != nil {
return fmt.Errorf("createSignature: %w", err)
}

req, err := http.NewRequestWithContext(ctx, http.MethodPost, sm.url, bytes.NewReader(payload))
if err != nil {
return err
return fmt.Errorf("http.NewRequestWithContext: %w", err)
}
req.Header.Add("Content-Type", "application/json")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Signature-256", string(signature))

resp, err := sm.client.Do(req)
if err != nil {
return err
return fmt.Errorf("client.Do: %w", err)
}
defer resp.Body.Close()

Expand All @@ -97,3 +105,9 @@ func WithClient(client *http.Client) snapMailOption {
sm.client = client
}
}

func WithSigningSecret(secret string) snapMailOption {
return func(sm *SnapMail) {
sm.signingSecret = []byte(secret)
}
}

0 comments on commit 94c7ffc

Please sign in to comment.