Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5ef6cef
Initial commit
vu-hoang-phan-form3 Aug 1, 2022
55ec5ff
add config
vu-hoang-phan-form3 Aug 2, 2022
97cce8b
add flag overrides
vu-hoang-phan-form3 Aug 3, 2022
1d9b1e9
add flag override
vu-hoang-phan-form3 Aug 3, 2022
e4d579b
setup log
vu-hoang-phan-form3 Aug 3, 2022
1632e66
update proxy
vu-hoang-phan-form3 Aug 4, 2022
0ba3b33
change config according to doc
vu-hoang-phan-form3 Aug 4, 2022
9bd26d9
chore: Docker build and GithubAction
njasm-f3 Aug 9, 2022
d9da6d8
implement signer
vu-hoang-phan-form3 Aug 4, 2022
2ac2e24
fix test and go mod
vu-hoang-phan-form3 Aug 11, 2022
8710b01
add metrics
vu-hoang-phan-form3 Aug 11, 2022
e99e817
fix GHA
vu-hoang-phan-form3 Aug 12, 2022
ce6e8c5
remove unused test
vu-hoang-phan-form3 Aug 12, 2022
51a7157
apply comment suggestions part 1
vu-hoang-phan-form3 Aug 17, 2022
6597297
change metrics name as suggested
vu-hoang-phan-form3 Aug 17, 2022
6a803a6
check for empty body
vu-hoang-phan-form3 Aug 17, 2022
4f2bea9
minor rename
vu-hoang-phan-form3 Aug 17, 2022
61b3a7a
address pr comments
vu-hoang-phan-form3 Aug 18, 2022
fbadc0e
add example dir
vu-hoang-phan-form3 Aug 18, 2022
96bb5cc
update dependencies
vu-hoang-phan-form3 Aug 19, 2022
1104b31
fix: CI pipeline and add .goreleaser.yaml configuration
njasm-f3 Aug 19, 2022
47b2642
add e2e tests
vu-hoang-phan-form3 Aug 22, 2022
84c350c
cleanup handler_test.go
vu-hoang-phan-form3 Aug 22, 2022
2d78a60
cleanup handler_test.go
vu-hoang-phan-form3 Aug 22, 2022
dc99047
doc in example
vu-hoang-phan-form3 Aug 24, 2022
9d8a60a
update dependencies
vu-hoang-phan-form3 Aug 25, 2022
7ea882f
minor fix
vu-hoang-phan-form3 Aug 25, 2022
89faa2d
change request duration bucket
vu-hoang-phan-form3 Aug 25, 2022
97451ab
fix: use localhost for test and add docstrings to errors
samphillips-f3 Aug 26, 2022
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
11 changes: 11 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: gomod
directory: "/"
schedule:
interval: daily
time: "08:00"
timezone: Europe/London
open-pull-requests-limit: 10
pull-request-branch-name:
separator: "-"
67 changes: 67 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: CI
on:
push:
branches:
- master
pull_request: {}

jobs:
test:
name: Linter and Tests
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Setup Golang
uses: actions/setup-go@b22fbbc2921299758641fab08929b4ac52b32923 # v3.2.0
with:
go-version-file: go.mod
- name: Run Linter
run: make lint
- name: Run Tests
run: make test
- name: Calculate the next SemVer tag
id: tag
run: |
TAG="$(make calculate-next-semver)"
echo "::set-output name=tag::$TAG"
tag:
name: SemVer Tag
needs: test
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
with:
fetch-depth: 0
- name: Push SemVer Tag
uses: mathieudutour/github-tag-action@d745f2e74aaf1ee82e747b181f7a0967978abee0 # v6.0
with:
custom_tag: ${{ needs.test.outputs.tag }}
github_token: ${{ secrets.GITHUB_TOKEN }}

goreleaser:
name: Create GH Release
needs: tag
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
with:
fetch-depth: 0
- name: Fetch all tags
run: git fetch --force --tags
- name: Setup Go
uses: actions/setup-go@b22fbbc2921299758641fab08929b4ac52b32923 # v3.2.0
with:
go-version-file: go.mod
- name: Run goreleaser release
uses: goreleaser/goreleaser-action@b953231f81b8dfd023c58e0854a721e35037f28b # v2.9.1
with:
distribution: goreleaser
version: v1.10.3
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

# Test binary, built with `go test -c`
*.test
tools/

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
vendor/
vendor/

.idea/
.idea/
.vscode/
55 changes: 55 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
builds:
-
# GOOS list to build for.
# For more info refer to: https://golang.org/doc/install/source#environment
# Defaults are darwin and linux.
goos:
- darwin
- linux
- windows

# GOARCH to build for.
# For more info refer to: https://golang.org/doc/install/source#environment
# Defaults are 386, amd64 and arm64.
goarch:
- amd64
- arm64

changelog:
skip: false
use: git
sort: asc

groups:
- title: Breaking Changes
regexp: "^.*BREAKING CHANGE[(\\w)]*:+.*$"
order: 0
- title: Features
regexp: "^.*feat[(\\w)]*:+.*$"
order: 1
- title: 'Bug fixes'
regexp: "^.*fix[(\\w)]*:+.*$"
order: 2
- title: 'Enhancements'
regexp: "^.*(chore|build|style|refactor|perf|test)[(\\w)]*:+.*$"
order: 3
- title: Others
order: 999

filters:
exclude:
- '^docs'
- '^ci'
- typo

archives:
# Additional files/template/globs you want to add to the archive.
- files:
- LICENSE
- README.md
- example/cert.crt
- example/config_example.yaml
- example/docker-compose.yaml
- example/private.key
- example/rsa_private_key.pem
- example/rsa_public_key.pub
22 changes: 22 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM golang:1.19.0-alpine3.16 AS build-env

WORKDIR /app

COPY ./go.mod ./
COPY ./go.sum ./

RUN go mod download

COPY . ./

RUN go build -o /go/bin/proxy

FROM alpine:3.16

RUN apk add --no-cache ca-certificates && update-ca-certificates

COPY --from=build-env /go/bin/proxy /

ENV GIN_MODE=release

ENTRYPOINT ["./proxy"]
40 changes: 40 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
GOLANGCI_VERSION ?= 1.46.2
GOIMPORTS_VERSION ?= v0.1.12

.PHONY: default
default: lint test

.PHONY: test
test:
@echo "==> Executing tests..."
@go test -test.v ./... -race -covermode=atomic -coverprofile=cover.out && \
go tool cover -func=cover.out && rm cover.out

.PHONY: lint
lint: tools/golangci-lint
@echo "==> Running golangci-lint..."
@tools/golangci-lint run

.PHONY: goimports
goimports: tools/goimports
@echo "==> Running goimports..."
@tools/goimports -w $(GOFMT_FILES)

.PHONY: calculate-next-semver
calculate-next-semver:
@bash -e -o pipefail -c '(source ./scripts/calculate-next-version.sh && echo $${FULL_TAG}) | tail -n 1'

###########################
# Tools targets
###########################

.PHONY: tools/golangci-lint
tools/golangci-lint:
@echo "==> Installing golangci-lint..."
@./scripts/install-golangci-lint.sh $(GOLANGCI_VERSION)

.PHONY: tools/goimports
tools/goimports:
@echo "==> Installing goimports..."
@GOBIN=$$(pwd)/tools/ go install golang.org/x/tools/cmd/goimports@$(GOIMPORTS_VERSION)

65 changes: 65 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package cmd

import (
"fmt"

"github.com/form3tech-oss/http-message-signing-proxy/config"
"github.com/form3tech-oss/http-message-signing-proxy/logger"
"github.com/form3tech-oss/http-message-signing-proxy/metric"
"github.com/form3tech-oss/http-message-signing-proxy/proxy"
"github.com/form3tech-oss/http-message-signing-proxy/signer"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

func Execute() {
rootCmd := NewRootCmd()
err := rootCmd.Execute()
if err != nil {
logrus.WithError(err).Fatal("failed to start server")
}
}

func NewRootCmd() *cobra.Command {
var (
cfgFile string
overrides []string
)

rootCmd := &cobra.Command{
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.LoadConfig(cfgFile, overrides)
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}

err = logger.Configure(cfg.Log)
if err != nil {
return fmt.Errorf("failed to configure logger: %w", err)
}

reqSigner, err := signer.NewRequestSigner(cfg.Proxy.Signer)
if err != nil {
return fmt.Errorf("failed to initialise request signer: %w", err)
}

signingProxy, err := proxy.NewReverseProxy(cfg.Proxy.UpstreamTarget)
if err != nil {
return fmt.Errorf("failed to create signing proxy: %w", err)
}

metricPublisher := metric.NewMetricPublisher(cfg.Proxy.UpstreamTarget)
handler := proxy.NewHandler(signingProxy, reqSigner, metricPublisher)
server := proxy.NewServer(cfg.Server, handler, metricPublisher)
server.Start()

return nil
},
}

f := rootCmd.Flags()
f.StringVar(&cfgFile, "config", "", "path to config file")
f.StringArrayVar(&overrides, "set", nil, "set value for certain config fields to override config file, can be set multiple times")

return rootCmd
}
42 changes: 42 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package config

type Config struct {
Proxy ProxyConfig `mapstructure:"proxy"`
Server ServerConfig `mapstructure:"server"`
Log LogConfig `mapstructure:"log"`
}

type ServerConfig struct {
Port int `mapstructure:"port"`
SSL SSLConfig `mapstructure:"ssl"`
}

type ProxyConfig struct {
UpstreamTarget string `mapstructure:"upstreamTarget"`
Signer SignerConfig `mapstructure:"signer"`
}

type SSLConfig struct {
Enable bool `mapstructure:"enable"`
CertFilePath string `mapstructure:"certFilePath"`
KeyFilePath string `mapstructure:"keyFilePath"`
}

type SignerConfig struct {
KeyId string `mapstructure:"keyId"`
KeyFilePath string `mapstructure:"keyFilePath"`
BodyDigestAlgo string `mapstructure:"bodyDigestAlgo"`
SignatureHashAlgo string `mapstructure:"signatureHashAlgo"`
Headers HeadersConfig `mapstructure:"headers"`
}

type HeadersConfig struct {
IncludeDigest bool `mapstructure:"includeDigest"`
IncludeRequestTarget bool `mapstructure:"includeRequestTarget"`
SignatureHeaders []string `mapstructure:"signatureHeaders"`
}

type LogConfig struct {
Level string `mapstructure:"level"`
Format string `mapstructure:"format"`
}
25 changes: 25 additions & 0 deletions config/config_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
server:
port: 8080
ssl:
enable: false
certFilePath: "/etc/ssl/certs/cert.crt"
keyFilePath: "/etc/ssl/private/private.key"

proxy:
upstreamTarget: "https://api.form3.tech/v1"
signer:
keyId: "6f33b219-137c-467e-9a61-f61040a03363"
keyFilePath: "/etc/form3/private/private.key"
bodyDigestAlgo: "SHA-256"
signatureHashAlgo: "SHA-256"
headers:
includeDigest: true
includeRequestTarget: true
signatureHeaders:
- host
- date
- content-length

log:
level: info
format: json
16 changes: 16 additions & 0 deletions config/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package config

// ValidationError describes an error validating the provided config.
type ValidationError struct {
message string
}

func NewValidationError(message string) error {
return &ValidationError{
message: message,
}
}

func (e *ValidationError) Error() string {
return e.message
}
Loading