Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/teleterm/grpccredentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func createClientTLSConfig(clientKeyPair tls.Certificate, serverCertPath string)
}, nil
}

func generateAndSaveCert(targetPath string) (tls.Certificate, error) {
func generateAndSaveCert(targetPath string, eku ...x509.ExtKeyUsage) (tls.Certificate, error) {
// The cert is first saved under a temp path and then renamed to targetPath. This prevents other
// processes from reading a half-written file.
tempFile, err := os.CreateTemp(filepath.Dir(targetPath), filepath.Base(targetPath))
Expand All @@ -108,7 +108,7 @@ func generateAndSaveCert(targetPath string) (tls.Certificate, error) {
}
defer os.Remove(tempFile.Name())

cert, err := cert.GenerateSelfSignedCert([]string{"localhost"}, nil)
cert, err := cert.GenerateSelfSignedCert([]string{"localhost"}, nil, eku...)
if err != nil {
return tls.Certificate{}, trace.Wrap(err, "failed to generate the certificate")
}
Expand Down
3 changes: 2 additions & 1 deletion lib/teleterm/teleterm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package teleterm
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net"
Expand Down Expand Up @@ -209,7 +210,7 @@ func createValidClientTLSConfig(t *testing.T, certsDir string) *tls.Config {
// reach the tsh gRPC server, so we need to use the renderer cert as the client cert.
clientCertPath := filepath.Join(certsDir, rendererCertFileName)
serverCertPath := filepath.Join(certsDir, tshdCertFileName)
clientCert, err := generateAndSaveCert(clientCertPath)
clientCert, err := generateAndSaveCert(clientCertPath, x509.ExtKeyUsageClientAuth)
require.NoError(t, err)

tlsConfig, err := createClientTLSConfig(clientCert, serverCertPath)
Expand Down
15 changes: 12 additions & 3 deletions lib/utils/cert/selfsigned.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (
// verifier and not in Go.
const macMaxTLSCertValidityPeriod = 825 * 24 * time.Hour

// Credentials keeps the typical 3 components of a proper HTTPS configuration
// Credentials keeps the typical 3 components of a proper TLS configuration
type Credentials struct {
// PublicKey in PEM format
PublicKey []byte
Expand All @@ -49,8 +49,16 @@ type Credentials struct {
}

// GenerateSelfSignedCert generates a self-signed certificate that
// is valid for given domain names and ips, returns PEM-encoded bytes with key and cert
func GenerateSelfSignedCert(hostNames []string, ipAddresses []string) (*Credentials, error) {
// is valid for given domain names and IPs. If extended key usage
// is not specified, the cert will be generated for server auth.
func GenerateSelfSignedCert(hostNames []string, ipAddresses []string, eku ...x509.ExtKeyUsage) (*Credentials, error) {
if len(eku) == 0 {
// if not specified, assume this cert is for server auth,
// which is required for validation on macOS:
// https://support.apple.com/en-in/HT210176
eku = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}
}

priv, err := native.GenerateRSAPrivateKey()
if err != nil {
return nil, trace.Wrap(err)
Expand All @@ -77,6 +85,7 @@ func GenerateSelfSignedCert(hostNames []string, ipAddresses []string) (*Credenti
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: eku,
BasicConstraintsValid: true,
IsCA: true,
}
Expand Down