packagetlsimport("crypto/rand""crypto/rsa""crypto/tls""crypto/x509""crypto/x509/pkix""fmt""log/slog""math/big""net""time")const(CertificateValidityDuration=365*24*time.Hour// 1 year)// GetLocalIPAddresses returns all local IP addresses for certificate inclusion.funcGetLocalIPAddresses(listenAddrstring)([]net.IP,error){// Get all local IP addressesipAddresses:=[]net.IP{net.IPv4(127,0,0,1),net.IPv6loopback,}// Add the listen address if it's a specific IPiflistenAddr!=""&&listenAddr!="0.0.0.0"&&listenAddr!="::"{ifip:=net.ParseIP(listenAddr);ip!=nil{ipAddresses=append(ipAddresses,ip)}}// If listening on all interfaces (0.0.0.0), get all local IPsiflistenAddr==""||listenAddr=="0.0.0.0"||listenAddr=="::"{ifaces,err:=net.Interfaces()iferr==nil{for_,iface:=rangeifaces{addrs,err:=iface.Addrs()iferr!=nil{continue}for_,addr:=rangeaddrs{varipnet.IPswitchv:=addr.(type){case*net.IPNet:ip=v.IPcase*net.IPAddr:ip=v.IP}ifip!=nil&&!ip.IsLoopback(){// Check if we already have this IPexists:=falsefor_,existingIP:=rangeipAddresses{ifexistingIP.Equal(ip){exists=truebreak}}if!exists{ipAddresses=append(ipAddresses,ip)}}}}}}returnipAddresses,nil}// CertConfig holds the configuration for the self-signed certificate subject.typeCertConfigstruct{Organizationstring`json:"organization"`Countrystring`json:"country"`Provincestring`json:"province"`Localitystring`json:"locality"`StreetAddressstring`json:"street_address"`PostalCodestring`json:"postal_code"`CommonNamestring`json:"common_name"`}// GenerateSelfSignedCert generates a self-signed TLS certificate// that includes localhost and all local IP addresses.funcGenerateSelfSignedCert(listenAddrstring,configCertConfig,logger*slog.Logger)(*tls.Certificate,error){// Generate private keyprivateKey,err:=rsa.GenerateKey(rand.Reader,2048)iferr!=nil{iflogger!=nil{logger.Error("failed to generate RSA key","error",err)}returnnil,fmt.Errorf("failed to generate RSA key: %w",err)}// Get all local IP addressesipAddresses,err:=GetLocalIPAddresses(listenAddr)iferr!=nil{returnnil,fmt.Errorf("failed to get local IP addresses: %w",err)}// Create certificate template with random serial numberserialNumberLimit:=new(big.Int).Lsh(big.NewInt(1),128)serialNumber,err:=rand.Int(rand.Reader,serialNumberLimit)iferr!=nil{iflogger!=nil{logger.Error("failed to generate serial number","error",err)}returnnil,fmt.Errorf("failed to generate serial number: %w",err)}template:=x509.Certificate{SerialNumber:serialNumber,Subject:pkix.Name{Organization:[]string{config.Organization},Country:[]string{config.Country},Province:[]string{config.Province},Locality:[]string{config.Locality},StreetAddress:[]string{config.StreetAddress},PostalCode:[]string{config.PostalCode},CommonName:config.CommonName,},NotBefore:time.Now(),NotAfter:time.Now().Add(CertificateValidityDuration),KeyUsage:x509.KeyUsageKeyEncipherment|x509.KeyUsageDigitalSignature,ExtKeyUsage:[]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},BasicConstraintsValid:true,IPAddresses:ipAddresses,DNSNames:[]string{"localhost"},}// Create certificatecertDER,err:=x509.CreateCertificate(rand.Reader,&template,&template,&privateKey.PublicKey,privateKey)iferr!=nil{iflogger!=nil{logger.Error("failed to create certificate","error",err)}returnnil,fmt.Errorf("failed to create certificate: %w",err)}// Convert to tls.Certificatecert:=tls.Certificate{Certificate:[][]byte{certDER},PrivateKey:privateKey,}iflogger!=nil{logger.Info("generated self-signed TLS certificate")}return&cert,nil}