Skip to content

Commit

Permalink
start mod
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Paoletti committed Feb 19, 2024
0 parents commit d0d6187
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.vscode/
.idea/
localhost.crt
localhost.key
localCA.crt
.golangci.yaml
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Esempio di utilizzo:

```go
func main() {
// crea il tuo mux
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("hello server"))
})
// crea il Trust con i tuoi certificati self signed
t, err := https.NewTrust("localhost.crt", "localhost.key", "localCA.crt", tls.RequireAndVerifyClientCert)
if err != nil {
log.Fatal(err)
}
// avvia il server HTTPS
if e := t.StartServer(mux, 8080); e != nil {
log.Fatal(e)
}
}
```

La cartella `sample` contiene un esempio di esecuzione. È necessario avere i certificati self signed creati
con lo script `certs.sh`; utilizzando [Task](https://taskfile.dev/) viene fatto tutto in automatico come riportato
nell'esempio di output qui di seguito

```bash
$> task sample

task: [sample] go run main.go
2024/02/19 14:52:42 server started at port 8080
2024/02/19 14:52:43 ***** Trusted client:
2024/02/19 14:52:43 > hello server
2024/02/19 14:52:43 ***** Bad client error:
2024/02/19 14:52:43 http: TLS handshake error from [::1]:59274: remote error: tls: bad certificate
2024/02/19 14:52:43 Get "https://localhost:8080": tls: failed to verify certificate: x509: certificate signed by unknown authority
2024/02/19 14:52:43 Server closed, BYE :)
```
26 changes: 26 additions & 0 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: "3"

tasks:
lint:
cmds:
- golangci-lint cache clean && golangci-lint run ./...
cert:
dir: ./sample
cmds:
- chmod +x certs.sh
- ./certs.sh
clean:
dir: ./sample
cmds:
- rm localCA.crt localhost.crt localhost.key
test:
cmds:
- task: lint
- task: cert
- go test -race -count=1 ./... -v -cover
- task: clean
sample:
dir: ./sample
cmds:
- task: cert
- go run main.go
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module ssc

go 1.22.0
13 changes: 13 additions & 0 deletions sample/certs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

# CA cert
openssl req -new -newkey rsa:2048 -days 3650 -extensions v3_ca -nodes -x509 -sha256 -set_serial 0 \
-keyout localCA.key -out localCA.crt -subj "/CN=RootCA/"
# Certificate Signing Request
openssl req -new -newkey rsa:2048 -nodes -keyout localhost.key -out localhost.csr \
-config request.cnf -extensions v3_req
# Self-Signing
openssl x509 -req -sha256 -CAcreateserial -in localhost.csr -days 3650 -CA localCA.crt \
-CAkey localCA.key -out localhost.crt -extfile <(printf "subjectAltName=DNS:localhost")

rm localhost.csr localCA.key localCA.srl
45 changes: 45 additions & 0 deletions sample/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package main

import (
"crypto/tls"
"io"
"log"
"net/http"
"time"

"ssc"
)

func main() {
t, err := ssc.NewTrust("localhost.crt", "localhost.key", "localCA.crt", tls.RequireAndVerifyClientCert)
if err != nil {
log.Fatal(err)
}
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("hello server"))
})
go func() {
log.Println("server started at port 8080")
if e := t.StartServer(mux, 8080); e != nil {
log.Fatal(e)
}
}()
time.Sleep(1 * time.Second)
client := t.Client(10 * time.Second)
resp, err := client.Get("https://localhost:8080")
if err != nil {
log.Println(err)
}
body := resp.Body
b, _ := io.ReadAll(body)
resp.Body.Close()
log.Println("***** Trusted client:")
log.Printf("> %s\n", string(b))
log.Println("***** Bad client error:")
_, err = http.Get("https://localhost:8080")
if err != nil {
log.Println(err)
}
log.Println("Server closed, BYE :)")
}
21 changes: 21 additions & 0 deletions sample/request.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = req_ext
prompt = no
[req_distinguished_name]
C = IT
ST = Italia
L = Florence
O = development
OU = development
CN = localhost
[v3_req]
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[req_ext]
subjectAltName = @alt_names
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = localhost
80 changes: 80 additions & 0 deletions trust.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package ssc

import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
"time"
)

// Trust raccoglie gli elementi di certificazione della connessione
type Trust struct {
Cert tls.Certificate
Pool *x509.CertPool
cert string
key string
ClientAuth tls.ClientAuthType
}

// NewTrust crea un nuovo trust a partire dai certificati passati come argomento
func NewTrust(certificate, key, ca string, auth tls.ClientAuthType) (*Trust, error) {
root, err := os.ReadFile(ca)
if err != nil {
return nil, err
}
pool, err := x509.SystemCertPool()
if err != nil {
return nil, err
}
pool.AppendCertsFromPEM(root)
c, err := tls.LoadX509KeyPair(certificate, key)
if err != nil {
return nil, err
}
return &Trust{
Pool: pool,
Cert: c,
ClientAuth: auth,
cert: certificate,
key: key,
}, nil
}

// Client crea client HTTP con certificati trusted
func (t *Trust) Client(timeout time.Duration) *http.Client {
return &http.Client{
Transport: t.transport(),
Timeout: timeout,
}
}

// StartServer avvia un server HTTPS configurato per gestire le richieste definite dal Trust
func (t *Trust) StartServer(mux *http.ServeMux, port int) error {
server := &http.Server{
Addr: fmt.Sprintf(":%d", port),
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 30 * time.Second,
Handler: mux,
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
ClientCAs: t.Pool,
ClientAuth: t.ClientAuth,
},
}
return server.ListenAndServeTLS(t.cert, t.key)
}

// transport crea un Transport certificato
func (t *Trust) transport() *http.Transport {
return &http.Transport{
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{t.Cert},
RootCAs: t.Pool,
},
DisableKeepAlives: false,
}
}

0 comments on commit d0d6187

Please sign in to comment.