Skip to content

Commit

Permalink
feat: crypto/tlsutil: add HTTPSVersionCheckResponse{}
Browse files Browse the repository at this point in the history
  • Loading branch information
grokify committed Jan 18, 2025
1 parent 025d6ec commit 0477d6a
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 62 deletions.
36 changes: 6 additions & 30 deletions crypto/tlsutil/cmd/httpsversioncheck/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,19 @@
package main

import (
"context"
"crypto/tls"
"fmt"
"net/http"
"os"

"github.com/grokify/mogo/crypto/tlsutil"
"github.com/grokify/mogo/log/logutil"
"github.com/grokify/mogo/fmt/fmtutil"
)

func main() {
url := "https://pkg.go.dev/"

if len(os.Args) > 1 {
url = os.Args[1]
if len(os.Args) <= 1 {
fmt.Println("usage: httpsversioncheck <url1> <url2> <url3>")
os.Exit(1)
}

fmt.Printf("Checking URL: [%s]\n", url)

resp, err := http.Get(url)
logutil.FatalErr(err)
tlsv, err := tlsutil.HTTPResponseTLSVersion(resp)
logutil.FatalErr(err)
fmt.Printf("TLS_CONNECT_DEFAULT: [%s]\n", tlsv.String())

// Test each TLS version
tlsVersions := []tlsutil.TLSVersion{
tls.VersionTLS10,
tls.VersionTLS11,
tls.VersionTLS12,
tls.VersionTLS13}

for _, tlsVersion := range tlsVersions {
if err := tlsutil.SupportsTLSVersion(context.Background(), tlsVersion, url); err != nil {
fmt.Printf("%s: Not Supported: (%s)\n", tlsVersion.String(), err.Error())
} else {
fmt.Printf("%s: Supported\n", tlsVersion.String())
}
}
res := tlsutil.CheckURLs(os.Args[1:])
fmtutil.PrintJSON(res)
}
32 changes: 0 additions & 32 deletions crypto/tlsutil/tlsutil.go → crypto/tlsutil/config.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package tlsutil

import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net/http"
"os"
"strings"

"github.com/grokify/mogo/errors/errorsutil"
"golang.org/x/net/context/ctxhttp"
)

type TLSConfig struct {
Expand Down Expand Up @@ -99,31 +95,3 @@ func (tc *TLSConfig) LoadRootCACert(caCertFilepath string) error {
return nil
}
}

// SupportsTLSVersion returns an error if a connection cannot be made and a nil
// if the connection is successful.
func SupportsTLSVersion(ctx context.Context, tlsVersion TLSVersion, url string) error {
client := &http.Client{Transport: &http.Transport{
TLSClientConfig: &tls.Config{
MinVersion: uint16(tlsVersion),
MaxVersion: uint16(tlsVersion),
},
}}

if resp, err := ctxhttp.Get(ctx, client, url); err != nil {
return errorsutil.Wrapf(err, "tls version not supported (%s)", tlsVersion.String())
} else {
defer resp.Body.Close()
return nil
}
}

func HTTPResponseTLSVersion(r *http.Response) (TLSVersion, error) {
if r == nil {
return 0, errors.New("http.Response cannot be nil")
} else if r.TLS == nil {
return 0, errors.New("http.Response.TLS cannot be nil")
} else {
return TLSVersion(r.TLS.Version), nil
}
}
89 changes: 89 additions & 0 deletions crypto/tlsutil/version_check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package tlsutil

import (
"context"
"crypto/tls"
"errors"
"net/http"

"github.com/grokify/mogo/errors/errorsutil"
"golang.org/x/net/context/ctxhttp"
)

// SupportsTLSVersion returns an error if a connection cannot be made and a nil
// if the connection is successful.
func SupportsTLSVersion(ctx context.Context, tlsVersion TLSVersion, url string) (*int, error) {
client := &http.Client{Transport: &http.Transport{
TLSClientConfig: &tls.Config{
MinVersion: uint16(tlsVersion),
MaxVersion: uint16(tlsVersion),
},
}}

if resp, err := ctxhttp.Get(ctx, client, url); err != nil {
return nil, errorsutil.Wrapf(err, "tls version not supported (%s)", tlsVersion.String())
} else {
defer resp.Body.Close()
return &resp.StatusCode, nil
}
}

func HTTPResponseTLSVersion(r *http.Response) (TLSVersion, error) {
if r == nil {
return 0, errors.New("http.Response cannot be nil")
} else if r.TLS == nil {
return 0, errors.New("http.Response.TLS cannot be nil")
} else {
return TLSVersion(r.TLS.Version), nil
}
}

func CheckURLs(urls []string) HTTPSVersionCheckResponse {
res := NewHTTPSVersionCheckResponse()
for _, url := range urls {
res.Results = append(res.Results, CheckURL(url))
}
return res
}

func CheckURL(url string) URLResults {
res := URLResults{
URL: url,
TLSVersionChecks: []TLSVersionCheck{}}
tlsVersions := TLSVersions()
for _, tlsVersion := range tlsVersions {
tlsVersionCheck := TLSVersionCheck{
TLSVersion: tlsVersion.String(),
}
if statusCode, err := SupportsTLSVersion(context.Background(), tlsVersion, url); err != nil {
tlsVersionCheck.Message = err.Error()
} else {
tlsVersionCheck.Supported = true
tlsVersionCheck.HTTPStatusCode = statusCode
}
res.TLSVersionChecks = append(res.TLSVersionChecks, tlsVersionCheck)
}
return res
}

type HTTPSVersionCheckResponse struct {
Results []URLResults `json:"results"`
}

func NewHTTPSVersionCheckResponse() HTTPSVersionCheckResponse {
return HTTPSVersionCheckResponse{
Results: []URLResults{},
}
}

type URLResults struct {
URL string `json:"url"`
TLSVersionChecks []TLSVersionCheck `json:"tlsVersionChecks"`
}

type TLSVersionCheck struct {
TLSVersion string `json:"tlsVersion"`
HTTPStatusCode *int `json:"httpStatusCode"`
Supported bool `json:"supported"`
Message string `json:"message"`
}

0 comments on commit 0477d6a

Please sign in to comment.