Skip to content

Commit 6670ca9

Browse files
feat: auth test service for testing sdk auth
1 parent 48026fe commit 6670ca9

File tree

9 files changed

+246
-0
lines changed

9 files changed

+246
-0
lines changed

.github/workflows/build-docker.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Create and publish a Docker image
2+
3+
on:
4+
push:
5+
tags:
6+
- "*"
7+
8+
env:
9+
REGISTRY: ghcr.io
10+
IMAGE_NAME: ${{ github.repository }}
11+
12+
jobs:
13+
build-and-push-image:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: read
17+
packages: write
18+
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@v3
22+
23+
- name: Log in to the Container registry
24+
uses: docker/[email protected]
25+
with:
26+
registry: ${{ env.REGISTRY }}
27+
username: ${{ github.actor }}
28+
password: ${{ secrets.GITHUB_TOKEN }}
29+
30+
- name: Extract metadata (tags, labels) for Docker
31+
id: meta
32+
uses: docker/[email protected]
33+
with:
34+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
35+
36+
- name: Build and push Docker image
37+
uses: docker/[email protected]
38+
with:
39+
context: .
40+
push: true
41+
tags: ${{ steps.meta.outputs.tags }}
42+
labels: ${{ steps.meta.outputs.labels }}

.vscode/launch.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Launch Package",
9+
"type": "go",
10+
"request": "launch",
11+
"mode": "auto",
12+
"program": "${workspaceFolder}/cmd/server/main.go"
13+
}
14+
]
15+
}

Dockerfile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
## Build
2+
FROM golang as builder
3+
4+
WORKDIR /app
5+
6+
COPY go.mod ./
7+
COPY go.sum ./
8+
9+
RUN go mod download
10+
11+
COPY internal/ ./internal/
12+
COPY cmd/ ./cmd/
13+
COPY pkg/ ./pkg/
14+
15+
RUN go build -o /server cmd/server/main.go
16+
17+
## Deploy
18+
FROM gcr.io/distroless/base-debian11
19+
20+
WORKDIR /
21+
22+
COPY --from=builder /server /server
23+
24+
EXPOSE 8080
25+
26+
ENTRYPOINT ["/server"]

cmd/server/main.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"net/http"
6+
7+
"github.com/gorilla/mux"
8+
"github.com/speakeasy-api/speakeasy-auth-test-service/internal/auth"
9+
)
10+
11+
func main() {
12+
r := mux.NewRouter()
13+
r.HandleFunc("/auth", auth.HandleAuth).Methods(http.MethodPost)
14+
15+
log.Println("Listening on :8080")
16+
if err := http.ListenAndServe(":8080", r); err != nil {
17+
log.Fatal(err)
18+
}
19+
}

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/speakeasy-api/speakeasy-auth-test-service
2+
3+
go 1.19
4+
5+
require github.com/gorilla/mux v1.8.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
2+
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=

internal/auth/auth.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package auth
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/speakeasy-api/speakeasy-auth-test-service/pkg/models"
9+
)
10+
11+
var authError = errors.New("invalid auth")
12+
13+
func checkAuth(req models.AuthRequest, r *http.Request) error {
14+
if req.BasicAuth != nil {
15+
if err := checkBasicAuth(*req.BasicAuth, r); err != nil {
16+
return err
17+
}
18+
}
19+
20+
for _, headerAuth := range req.HeaderAuth {
21+
if err := checkHeaderAuth(headerAuth, r); err != nil {
22+
return err
23+
}
24+
}
25+
26+
return nil
27+
}
28+
29+
func checkBasicAuth(basicAuth models.BasicAuth, r *http.Request) error {
30+
basicAuthHeader := r.Header.Get("Authorization")
31+
if basicAuthHeader == "" {
32+
return fmt.Errorf("missing Authorization header for Basic Auth: %w", authError)
33+
}
34+
35+
username, password, ok := r.BasicAuth()
36+
if !ok {
37+
return fmt.Errorf("invalid Authorization header for Basic Auth: %w", authError)
38+
}
39+
40+
if username != basicAuth.Username {
41+
return fmt.Errorf("invalid username for Basic Auth: %w", authError)
42+
}
43+
44+
if password != basicAuth.Password {
45+
return fmt.Errorf("invalid password for Basic Auth: %w", authError)
46+
}
47+
48+
return nil
49+
}
50+
51+
func checkHeaderAuth(headerAuth models.HeaderAuth, r *http.Request) error {
52+
headerValue := r.Header.Get(headerAuth.HeaderName)
53+
if headerValue == "" {
54+
return fmt.Errorf("missing %s header: %w", headerAuth.HeaderName, authError)
55+
}
56+
57+
if headerValue != headerAuth.ExpectedValue {
58+
return fmt.Errorf("invalid %s header: %w", headerAuth.HeaderName, authError)
59+
}
60+
61+
return nil
62+
}

internal/auth/service.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package auth
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"io"
7+
"log"
8+
"net/http"
9+
10+
"github.com/speakeasy-api/speakeasy-auth-test-service/pkg/models"
11+
)
12+
13+
func HandleAuth(w http.ResponseWriter, r *http.Request) {
14+
body, err := io.ReadAll(r.Body)
15+
if err != nil {
16+
handleError(w, err)
17+
return
18+
}
19+
20+
var req models.AuthRequest
21+
if err := json.Unmarshal(body, &req); err != nil {
22+
handleError(w, err)
23+
return
24+
}
25+
26+
if err := checkAuth(req, r); err != nil {
27+
handleError(w, err)
28+
return
29+
}
30+
}
31+
32+
func handleError(w http.ResponseWriter, err error) {
33+
log.Println(err)
34+
35+
data, marshalErr := json.Marshal(models.ErrorResponse{
36+
Error: models.ErrorMessage{
37+
Message: err.Error(),
38+
},
39+
})
40+
if marshalErr != nil {
41+
w.WriteHeader(http.StatusInternalServerError)
42+
return
43+
}
44+
45+
if errors.Is(err, authError) {
46+
w.WriteHeader(http.StatusUnauthorized)
47+
} else {
48+
w.WriteHeader(http.StatusInternalServerError)
49+
}
50+
_, _ = w.Write(data)
51+
}

pkg/models/models.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package models
2+
3+
type ErrorMessage struct {
4+
Message string `json:"message"`
5+
}
6+
7+
type ErrorResponse struct {
8+
Error ErrorMessage `json:"error"`
9+
}
10+
11+
type HeaderAuth struct {
12+
HeaderName string `json:"headerName"`
13+
ExpectedValue string `json:"expectedValue"`
14+
}
15+
16+
type BasicAuth struct {
17+
Username string `json:"username"`
18+
Password string `json:"password"`
19+
}
20+
21+
type AuthRequest struct {
22+
HeaderAuth []HeaderAuth `json:"headerAuth,omitempty"`
23+
BasicAuth *BasicAuth `json:"basicAuth,omitempty"`
24+
}

0 commit comments

Comments
 (0)