fix: updated certs and added shell int. test
This commit is contained in:
parent
6796f16813
commit
4b6bfc8974
3
examples/shell/curl.sh
Executable file
3
examples/shell/curl.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
curl "${TERM_TAP_CURL_URL:-https://ipinfo.io:443/json}"
|
||||
@ -21,6 +21,7 @@ var stdoutWriter io.Writer = stdioRef{isErr: false}
|
||||
var stderrWriter io.Writer = stdioRef{isErr: true}
|
||||
var startSessionFn = app.StartSession
|
||||
var runTUIFn = tui.Run
|
||||
var currentGOOS = runtime.GOOS
|
||||
|
||||
type stdioRef struct {
|
||||
isErr bool
|
||||
@ -131,7 +132,6 @@ func runCert() {
|
||||
}
|
||||
|
||||
certPath := ca.CertPath()
|
||||
quotedCertPath := strconv.Quote(certPath)
|
||||
fmt.Fprintf(stdoutWriter, "Certificate path: %s\n", certPath)
|
||||
if ca.WasCreated() {
|
||||
fmt.Fprintln(stdoutWriter, "Created a new local HTTPS interception CA.")
|
||||
@ -148,12 +148,20 @@ func runCert() {
|
||||
fmt.Fprintln(stdoutWriter, "System trust store: not trusted")
|
||||
}
|
||||
|
||||
if runtime.GOOS != "linux" {
|
||||
fmt.Fprintln(stdoutWriter, "Install this certificate into your OS or client trust store to inspect HTTPS traffic.")
|
||||
return
|
||||
}
|
||||
printTrustInstructions(certPath)
|
||||
}
|
||||
|
||||
fmt.Fprintln(stdoutWriter)
|
||||
func printTrustInstructions(certPath string) {
|
||||
quotedCertPath := strconv.Quote(certPath)
|
||||
|
||||
switch currentGOOS {
|
||||
case "windows":
|
||||
fmt.Fprintln(stdoutWriter, "Install this certificate into Windows Trusted Root Certification Authorities.")
|
||||
fmt.Fprintln(stdoutWriter, "If curl reports Schannel revocation errors, try: curl --ssl-no-revoke --cacert "+quotedCertPath+" https://example.com")
|
||||
case "darwin":
|
||||
fmt.Fprintln(stdoutWriter, "Import this certificate into Keychain Access and set it to always trust.")
|
||||
fmt.Fprintf(stdoutWriter, "Quick curl test: curl --proxy http://%s --cacert %s https://example.com\n", proxyAddrForPort(defaultProxyPort), quotedCertPath)
|
||||
case "linux":
|
||||
fmt.Fprintln(stdoutWriter, "Trust instructions (Linux):")
|
||||
fmt.Fprintln(stdoutWriter, "Debian/Ubuntu:")
|
||||
fmt.Fprintf(stdoutWriter, " sudo cp %s /usr/local/share/ca-certificates/termtap.crt\n", quotedCertPath)
|
||||
@ -166,4 +174,7 @@ func runCert() {
|
||||
fmt.Fprintln(stdoutWriter)
|
||||
fmt.Fprintln(stdoutWriter, "Quick curl test:")
|
||||
fmt.Fprintf(stdoutWriter, " curl --proxy http://%s --cacert %s https://example.com\n", proxyAddrForPort(defaultProxyPort), quotedCertPath)
|
||||
default:
|
||||
fmt.Fprintln(stdoutWriter, "Install this certificate into your OS or client trust store to inspect HTTPS traffic.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,6 +206,8 @@ func TestRunCert_EnsureCAFailureCallsFatalExit(t *testing.T) {
|
||||
func TestRunCertOutputContract(t *testing.T) {
|
||||
configRoot := t.TempDir()
|
||||
t.Setenv("XDG_CONFIG_HOME", configRoot)
|
||||
origGOOS := currentGOOS
|
||||
t.Cleanup(func() { currentGOOS = origGOOS })
|
||||
|
||||
stdout, _ := captureOutput(t, func() {
|
||||
runCert()
|
||||
@ -228,6 +230,41 @@ func TestRunCertOutputContract(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCert_WindowsHint(t *testing.T) {
|
||||
configRoot := t.TempDir()
|
||||
t.Setenv("XDG_CONFIG_HOME", configRoot)
|
||||
origGOOS := currentGOOS
|
||||
t.Cleanup(func() { currentGOOS = origGOOS })
|
||||
currentGOOS = "windows"
|
||||
|
||||
stdout, _ := captureOutput(t, func() {
|
||||
runCert()
|
||||
})
|
||||
|
||||
if !strings.Contains(stdout, "Windows Trusted Root Certification Authorities") {
|
||||
t.Fatalf("stdout missing windows trust hint: %q", stdout)
|
||||
}
|
||||
if !strings.Contains(stdout, "--ssl-no-revoke") {
|
||||
t.Fatalf("stdout missing windows curl hint: %q", stdout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCert_DarwinHint(t *testing.T) {
|
||||
configRoot := t.TempDir()
|
||||
t.Setenv("XDG_CONFIG_HOME", configRoot)
|
||||
origGOOS := currentGOOS
|
||||
t.Cleanup(func() { currentGOOS = origGOOS })
|
||||
currentGOOS = "darwin"
|
||||
|
||||
stdout, _ := captureOutput(t, func() {
|
||||
runCert()
|
||||
})
|
||||
|
||||
if !strings.Contains(stdout, "Keychain Access") {
|
||||
t.Fatalf("stdout missing macOS trust hint: %q", stdout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCert_CreatedThenExistingMessage(t *testing.T) {
|
||||
configRoot := t.TempDir()
|
||||
t.Setenv("XDG_CONFIG_HOME", configRoot)
|
||||
|
||||
@ -130,8 +130,7 @@ func (ca *CertificateAuthority) create() error {
|
||||
},
|
||||
NotBefore: now.Add(-1 * time.Hour),
|
||||
NotAfter: now.Add(caValidFor),
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
MaxPathLen: 1,
|
||||
|
||||
88
internal/tui/shell_integration_test.go
Normal file
88
internal/tui/shell_integration_test.go
Normal file
@ -0,0 +1,88 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"termtap.dev/internal/app"
|
||||
"termtap.dev/internal/model"
|
||||
)
|
||||
|
||||
func TestShellExampleProducesRequestData(t *testing.T) {
|
||||
scriptPath := shellExamplePath(t)
|
||||
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = fmt.Fprint(w, "shell-example-ok")
|
||||
}))
|
||||
t.Cleanup(upstream.Close)
|
||||
|
||||
t.Setenv("TERM_TAP_CURL_URL", upstream.URL+"/demo")
|
||||
|
||||
addr := freeTCPAddr(t)
|
||||
s, err := app.StartSession(model.Command{Name: "sh", Args: []string{scriptPath}}, addr)
|
||||
if err != nil {
|
||||
t.Fatalf("StartSession() error = %v", err)
|
||||
}
|
||||
t.Cleanup(s.Stop)
|
||||
|
||||
m := NewModel(s.Events, Controls{})
|
||||
if next, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40}); next != nil {
|
||||
m = next.(Model)
|
||||
}
|
||||
|
||||
deadline := time.After(6 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case ev := <-s.Events:
|
||||
next, _ := m.Update(EventMsg{value: ev})
|
||||
m = next.(Model)
|
||||
if len(m.requests) > 0 && !m.requests[0].Pending && m.requests[0].Status == http.StatusOK && string(m.requests[0].ResponseData) == "shell-example-ok" {
|
||||
if got := string(m.requests[0].ResponseData); got != "shell-example-ok" {
|
||||
t.Fatalf("response data = %q, want %q", got, "shell-example-ok")
|
||||
}
|
||||
s.Stop()
|
||||
return
|
||||
}
|
||||
case <-deadline:
|
||||
t.Fatalf("timed out waiting for request data; requests=%#v", m.requests)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func freeTCPAddr(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.Listen() error = %v", err)
|
||||
}
|
||||
addr := ln.Addr().String()
|
||||
if err := ln.Close(); err != nil {
|
||||
t.Fatalf("listener close error = %v", err)
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
func shellExamplePath(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
_, file, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
t.Fatal("runtime.Caller failed")
|
||||
}
|
||||
|
||||
path := filepath.Join(filepath.Dir(file), "..", "..", "examples", "shell", "curl.sh")
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
t.Fatalf("stat shell example: %v", err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user