Simple test to show TLS over UDS
To run:
go test -v -timeout 1s
The third test hangs (ClientUsesTLS) at the moment. The output does look like the client has encrypted the data as it got sent to the listner.
| module gist | |
| go 1.21.9 | |
| require github.com/stretchr/testify v1.9.0 | |
| require ( | |
| github.com/davecgh/go-spew v1.1.1 // indirect | |
| github.com/pmezard/go-difflib v1.0.0 // indirect | |
| gopkg.in/yaml.v3 v3.0.1 // indirect | |
| ) |
| package main | |
| import ( | |
| "crypto/tls" | |
| "crypto/x509" | |
| "net" | |
| ) | |
| func main() { | |
| // Code | |
| } | |
| func getUDS(socketPath string) (net.Listener, error) { | |
| return net.Listen("unix", socketPath) | |
| } | |
| func getUDSClient(socketPath string) (net.Conn, error) { | |
| return net.Dial("unix", socketPath) | |
| } | |
| func getUDSWithTLS(socketPath string) (net.Listener, error) { | |
| cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey) | |
| if err != nil { | |
| return nil, err | |
| } | |
| config := tls.Config{Certificates: []tls.Certificate{cert}} | |
| // return tls.Listen("unix", socketPath, &config) | |
| l, err := getUDS(socketPath) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return tls.NewListener(l, &config), nil | |
| } | |
| func getUDSWithTLSClient(socketPath string) (net.Conn, error) { | |
| cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey) | |
| if err != nil { | |
| return nil, err | |
| } | |
| rootCA, err := x509.ParseCertificate(cert.Certificate[0]) | |
| if err != nil { | |
| return nil, err | |
| } | |
| certpool := x509.NewCertPool() | |
| certpool.AddCert(rootCA) | |
| config := tls.Config{RootCAs: certpool, InsecureSkipVerify: true} | |
| con, err := getUDSClient(socketPath) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return tls.Client(con, &config), nil | |
| } |
| package main | |
| import ( | |
| "net" | |
| "path/filepath" | |
| "sync" | |
| "testing" | |
| "github.com/stretchr/testify/require" | |
| ) | |
| func TestUDSCLientsAndServer(t *testing.T) { | |
| tests := []struct { | |
| name string | |
| getClient func(socketPath string) (net.Conn, error) | |
| getListener func(socketPath string) (net.Listener, error) | |
| }{ | |
| { | |
| name: "UDSwithTLS", | |
| getClient: getUDSWithTLSClient, | |
| getListener: getUDSWithTLS, | |
| }, | |
| { | |
| name: "UDS", | |
| getClient: getUDSClient, | |
| getListener: getUDS, | |
| }, | |
| { | |
| name: "ClientUsesTLS", | |
| getClient: getUDSWithTLSClient, | |
| getListener: getUDS, | |
| }, | |
| } | |
| for _, tt := range tests { | |
| t.Run(tt.name, func(t *testing.T) { | |
| tmpSocket := filepath.Join(t.TempDir(), "test.sock") | |
| t.Log("socket:", tmpSocket) | |
| l, err := tt.getListener(tmpSocket) | |
| require.NoError(t, err) | |
| result := make(chan string) | |
| go func() { | |
| conn, err := l.Accept() | |
| require.NoError(t, err) | |
| defer conn.Close() | |
| buf := make([]byte, 512) | |
| nr, err := conn.Read(buf) | |
| require.NoError(t, err) | |
| out := string(buf[0:nr]) | |
| t.Log("out was:", out) | |
| result <- string(out) | |
| }() | |
| c, err := tt.getClient(tmpSocket) | |
| require.NoError(t, err) | |
| defer c.Close() | |
| var wg sync.WaitGroup | |
| wg.Add(1) | |
| go func() { | |
| _, err := c.Write([]byte("hi\n")) | |
| require.NoError(t, err) | |
| wg.Done() | |
| }() | |
| wg.Wait() | |
| actual := <-result | |
| require.Equal(t, "hi\n", actual) | |
| }) | |
| } | |
| } |
| package main | |
| import "strings" | |
| // LocalhostCert is a PEM-encoded TLS cert with SAN IPs | |
| // "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT. | |
| // generated from src/crypto/tls: | |
| // go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h | |
| var LocalhostCert = []byte(`-----BEGIN CERTIFICATE----- | |
| MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS | |
| MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw | |
| MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A | |
| MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r | |
| bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U | |
| aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P | |
| YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk | |
| POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu | |
| h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE | |
| AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud | |
| DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv | |
| bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI | |
| 5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv | |
| cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2 | |
| +tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B | |
| grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK | |
| 5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/ | |
| WkBKOclmOV2xlTVuPw== | |
| -----END CERTIFICATE-----`) | |
| // LocalhostKey is the private key for LocalhostCert. | |
| var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY----- | |
| MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDoZtrm0dXV0Aqi | |
| 4Bpc7f95sNRTiu/AJSD8I1onY9PnEsPg3VVxvytsVJbYdcqr4w99V3AgpH/UNzMS | |
| gAZ/8lZBNbsSDOVesJ3euVqMRfYPvd9pYl6QPRRpSDPm+2tNdn3QFAvta9EgJ3sW | |
| URnoU85w+W6aLI2bNSq3AaE771p3VbkGolpEjo9h+i42TBHo1rhPNKPkGupR8/QX | |
| AOLMpInRdeaHyDwb2a3DE5I3dG7VAVzrVfJ6W6Q84YoFX+rpEE2SVM17SAjy6xQy | |
| VjKgLvK2mk0xbtfa+h0B6VK7bmODHZqeP18NVm6HsBcXn7iclLgAC3SfWU1jucZK | |
| x1lqzw9tAgMBAAECggEABWzxS1Y2wckblnXY57Z+sl6YdmLV+gxj2r8Qib7g4ZIk | |
| lIlWR1OJNfw7kU4eryib4fc6nOh6O4AWZyYqAK6tqNQSS/eVG0LQTLTTEldHyVJL | |
| dvBe+MsUQOj4nTndZW+QvFzbcm2D8lY5n2nBSxU5ypVoKZ1EqQzytFcLZpTN7d89 | |
| EPj0qDyrV4NZlWAwL1AygCwnlwhMQjXEalVF1ylXwU3QzyZ/6MgvF6d3SSUlh+sq | |
| XefuyigXw484cQQgbzopv6niMOmGP3of+yV4JQqUSb3IDmmT68XjGd2Dkxl4iPki | |
| 6ZwXf3CCi+c+i/zVEcufgZ3SLf8D99kUGE7v7fZ6AQKBgQD1ZX3RAla9hIhxCf+O | |
| 3D+I1j2LMrdjAh0ZKKqwMR4JnHX3mjQI6LwqIctPWTU8wYFECSh9klEclSdCa64s | |
| uI/GNpcqPXejd0cAAdqHEEeG5sHMDt0oFSurL4lyud0GtZvwlzLuwEweuDtvT9cJ | |
| Wfvl86uyO36IW8JdvUprYDctrQKBgQDycZ697qutBieZlGkHpnYWUAeImVA878sJ | |
| w44NuXHvMxBPz+lbJGAg8Cn8fcxNAPqHIraK+kx3po8cZGQywKHUWsxi23ozHoxo | |
| +bGqeQb9U661TnfdDspIXia+xilZt3mm5BPzOUuRqlh4Y9SOBpSWRmEhyw76w4ZP | |
| OPxjWYAgwQKBgA/FehSYxeJgRjSdo+MWnK66tjHgDJE8bYpUZsP0JC4R9DL5oiaA | |
| brd2fI6Y+SbyeNBallObt8LSgzdtnEAbjIH8uDJqyOmknNePRvAvR6mP4xyuR+Bv | |
| m+Lgp0DMWTw5J9CKpydZDItc49T/mJ5tPhdFVd+am0NAQnmr1MCZ6nHxAoGABS3Y | |
| LkaC9FdFUUqSU8+Chkd/YbOkuyiENdkvl6t2e52jo5DVc1T7mLiIrRQi4SI8N9bN | |
| /3oJWCT+uaSLX2ouCtNFunblzWHBrhxnZzTeqVq4SLc8aESAnbslKL4i8/+vYZlN | |
| s8xtiNcSvL+lMsOBORSXzpj/4Ot8WwTkn1qyGgECgYBKNTypzAHeLE6yVadFp3nQ | |
| Ckq9yzvP/ib05rvgbvrne00YeOxqJ9gtTrzgh7koqJyX1L4NwdkEza4ilDWpucn0 | |
| xiUZS4SoaJq6ZvcBYS62Yr1t8n09iG47YL8ibgtmH3L+svaotvpVxVK+d7BLevA/ | |
| ZboOWVe3icTy64BT3OQhmg== | |
| -----END RSA TESTING KEY-----`)) | |
| func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } |