Skip to content

Commit 1a02c6c

Browse files
chore(ci): add ci
1 parent 1a2d03d commit 1a02c6c

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,6 @@ jobs:
7171
SOFTHSM2_CONF: ${{ github.workspace }}/softhsm2.conf
7272
HSM_MODULE: ${{ steps.softhsm.outputs.SOFTHSM2_LIB }}
7373
SIGNING_SERVER_BIN: ${{ github.workspace }}/signing-server
74-
HSM_PUBLIC_KEY: ${{ github.workspace }}/public_key.pem
74+
HSM_PUBLIC_KEY_FILE: ${{ github.workspace }}/public_key.pem
7575
run: |
7676
go test -v ./...

cmd/signing-server/main_test.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/pem"
7+
"fmt"
8+
"io"
9+
"log"
10+
"net/http"
11+
"os"
12+
"os/exec"
13+
"strings"
14+
"sync"
15+
"testing"
16+
"time"
17+
18+
"go.uber.org/zap"
19+
)
20+
21+
func TestSoftHSMConcurrentSignRequests(t *testing.T) {
22+
hsmModule, err := exec.Command("softhsm2-util", "--show-config", "default-pkcs11-lib").CombinedOutput()
23+
if err != nil {
24+
hsmModule = []byte("/usr/lib/softhsm/libsofthsm2.so")
25+
}
26+
tokenLabel := os.Getenv("TOKEN_LABEL")
27+
if tokenLabel == "" {
28+
t.Skip("TOKEN_LABEL environment variable is not set")
29+
}
30+
keyLabel := os.Getenv("KEY_LABEL")
31+
if keyLabel == "" {
32+
t.Skip("KEY_LABEL environment variable is not set")
33+
}
34+
hsmPin := os.Getenv("HSM_PIN")
35+
if hsmPin == "" {
36+
t.Skip("HSM_PIN environment variable is not set")
37+
}
38+
39+
const (
40+
base = "http://localhost:8080"
41+
healthURL = base + "/healthz"
42+
url = base + "/sign/rsassa-pss?hashAlgorithm=sha256"
43+
bodyHex = "aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f"
44+
)
45+
46+
var (
47+
headers = map[string]string{
48+
"Content-Type": "text/plain",
49+
"Content-Encoding": "hex",
50+
"Accept": "application/x-pem-file",
51+
}
52+
)
53+
54+
l, err := zap.NewDevelopment()
55+
if err != nil {
56+
t.Fatalf("Failed to create logger: %v", err)
57+
}
58+
59+
ctx, cancel := context.WithCancel(t.Context())
60+
t.Cleanup(func() {
61+
cancel()
62+
})
63+
64+
go func() {
65+
if err := run(&Config{
66+
HSMModule: strings.TrimSpace(string(hsmModule)),
67+
HSMTokenLabel: tokenLabel,
68+
HSMSlot: -1,
69+
HSMKeyLabel: keyLabel,
70+
HSMPass: hsmPin,
71+
Port: "8080",
72+
DisableHTTPS: true,
73+
DisableAuth: true,
74+
MaxBodySizeBytes: 2048,
75+
Logger: l,
76+
RunServer: true,
77+
}); err != nil {
78+
cancel()
79+
t.Fatalf("Failed to start signing server: %v", err)
80+
}
81+
}()
82+
83+
var wg sync.WaitGroup
84+
client := &http.Client{Timeout: 10 * time.Second}
85+
86+
outer:
87+
for {
88+
select {
89+
case <-ctx.Done():
90+
t.Fatal("Test context was cancelled before health check passed")
91+
default:
92+
log.Println("Waiting for signing server to be ready...")
93+
healthReq, err := http.NewRequest(http.MethodGet, healthURL, nil)
94+
if err != nil {
95+
t.Fatalf("Health request creation failed: %v", err)
96+
}
97+
healthResp, _ := client.Do(healthReq)
98+
if healthResp != nil && healthResp.StatusCode == http.StatusOK {
99+
log.Println("Health check passed")
100+
break outer
101+
}
102+
}
103+
}
104+
105+
for i := 0; i < 10; i++ {
106+
wg.Add(1)
107+
108+
go func(index int) {
109+
defer wg.Done()
110+
111+
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBufferString(bodyHex))
112+
if err != nil {
113+
t.Errorf("Request %d creation failed: %v", index, err)
114+
return
115+
}
116+
117+
for k, v := range headers {
118+
req.Header.Set(k, v)
119+
}
120+
121+
resp, err := client.Do(req)
122+
if err != nil {
123+
t.Errorf("Request %d failed: %v", index, err)
124+
return
125+
}
126+
defer resp.Body.Close()
127+
128+
body, err := io.ReadAll(resp.Body)
129+
if err != nil {
130+
t.Errorf("Request %d read body failed: %v", index, err)
131+
return
132+
}
133+
if resp.StatusCode != http.StatusOK {
134+
t.Errorf("Request %d failed with status %d: %s", index, resp.StatusCode, body)
135+
return
136+
}
137+
138+
block, _ := pem.Decode(body)
139+
if block == nil || block.Type != "SIGNATURE" {
140+
log.Fatal("Failed to parse PEM block")
141+
}
142+
fmt.Printf("Decoded signature: %x\n", block.Bytes)
143+
144+
log.Printf("Response %d: %d - %.100q\n", index, resp.StatusCode, body)
145+
}(i)
146+
}
147+
148+
wg.Wait()
149+
}

0 commit comments

Comments
 (0)