// GetServerTLSConfig returns the context server TLS config, initializing it if needed. // If Insecure is true, return a nil config, otherwise load a config based // on the Certs directory. Fails if Insecure=false and Certs="". func (ctx *Context) GetServerTLSConfig() (*tls.Config, error) { // Early out. if ctx.Insecure { return nil, nil } ctx.tlsConfigMu.Lock() defer ctx.tlsConfigMu.Unlock() if ctx.serverTLSConfig != nil { return ctx.serverTLSConfig, nil } if ctx.Certs == "" { return nil, util.Errorf("--insecure=false, but --certs is empty. We need a certs directory") } if log.V(1) { log.Infof("setting up TLS from certificates directory: %s", ctx.Certs) } cfg, err := security.LoadServerTLSConfig(ctx.Certs, ctx.User) if err != nil { return nil, util.Errorf("error setting up server TLS config: %s", err) } ctx.serverTLSConfig = cfg return ctx.serverTLSConfig, nil }
func TestLoadTLSConfig(t *testing.T) { defer leaktest.AfterTest(t) config, err := security.LoadServerTLSConfig(security.EmbeddedCertsDir, "node") if err != nil { t.Fatalf("Failed to load TLS config: %v", err) } if len(config.Certificates) != 1 { t.Fatalf("config.Certificates should have 1 cert; found %d", len(config.Certificates)) } cert := config.Certificates[0] asn1Data := cert.Certificate[0] // TODO Check len() x509Cert, err := x509.ParseCertificate(asn1Data) if err != nil { t.Fatalf("Couldn't parse test cert: %v", err) } if err = verifyX509Cert(x509Cert, "localhost", config.RootCAs); err != nil { t.Errorf("Couldn't verify test cert against server CA: %v", err) } if err = verifyX509Cert(x509Cert, "localhost", config.ClientCAs); err != nil { t.Errorf("Couldn't verify test cert against client CA: %v", err) } if err = verifyX509Cert(x509Cert, "google.com", config.RootCAs); err == nil { t.Errorf("Verified test cert for wrong hostname") } }
// GetServerTLSConfig returns the context server TLS config, initializing it if needed. // If Insecure is true, return a nil config, otherwise load a config based // on the SSLCert file. Fails if Insecure=false and SSLCert="". func (ctx *Context) GetServerTLSConfig() (*tls.Config, error) { // Early out. if ctx.Insecure { return nil, nil } ctx.serverTLSConfig.once.Do(func() { if ctx.SSLCert != "" { ctx.serverTLSConfig.tlsConfig, ctx.serverTLSConfig.err = security.LoadServerTLSConfig( ctx.SSLCA, ctx.SSLCert, ctx.SSLCertKey) if ctx.serverTLSConfig.err != nil { ctx.serverTLSConfig.err = util.Errorf("error setting up client TLS config: %s", ctx.serverTLSConfig.err) } } else { insecureFlag := "insecure" certFlag := "cert" if len(FlagMap) > 0 { insecureFlag = FlagMap[&ctx.Insecure].Name certFlag = FlagMap[&ctx.SSLCert].Name } ctx.serverTLSConfig.err = util.Errorf("--%s=false, but --%s is empty. Certificates must be specified.", insecureFlag, certFlag) } }) return ctx.serverTLSConfig.tlsConfig, ctx.serverTLSConfig.err }
// GetServerTLSConfig returns the context server TLS config, initializing it if needed. // If Insecure is true, return a nil config, otherwise load a config based // on the Certs directory. Fails if Insecure=false and Certs="". func (ctx *Context) GetServerTLSConfig() (*tls.Config, error) { // Early out. if ctx.Insecure { return nil, nil } ctx.serverTLSConfig.once.Do(func() { if ctx.SSLCert != "" { ctx.serverTLSConfig.tlsConfig, ctx.serverTLSConfig.err = security.LoadServerTLSConfig( ctx.SSLCA, ctx.SSLCert, ctx.SSLCertKey) if ctx.serverTLSConfig.err != nil { ctx.serverTLSConfig.err = util.Errorf("error setting up client TLS config: %s", ctx.serverTLSConfig.err) } } else { ctx.serverTLSConfig.err = util.Errorf("--insecure=false, but --cert is empty. Certificates must be specified.") } }) return ctx.serverTLSConfig.tlsConfig, ctx.serverTLSConfig.err }
// This is a fairly high-level test of CA and node certificates. // We construct SSL server and clients and use the generated certs. func TestUseCerts(t *testing.T) { defer leaktest.AfterTest(t)() // Do not mock cert access for this test. security.ResetReadFileFn() defer ResetTest() certsDir := util.CreateTempDir(t, "certs_test") defer util.CleanupDir(certsDir) err := security.RunCreateCACert( filepath.Join(certsDir, security.EmbeddedCACert), filepath.Join(certsDir, security.EmbeddedCAKey), 512) if err != nil { t.Fatalf("Expected success, got %v", err) } err = security.RunCreateNodeCert( filepath.Join(certsDir, security.EmbeddedCACert), filepath.Join(certsDir, security.EmbeddedCAKey), filepath.Join(certsDir, security.EmbeddedNodeCert), filepath.Join(certsDir, security.EmbeddedNodeKey), 512, []string{"127.0.0.1"}) if err != nil { t.Fatalf("Expected success, got %v", err) } err = security.RunCreateClientCert( filepath.Join(certsDir, security.EmbeddedCACert), filepath.Join(certsDir, security.EmbeddedCAKey), filepath.Join(certsDir, security.EmbeddedRootCert), filepath.Join(certsDir, security.EmbeddedRootKey), 512, security.RootUser) if err != nil { t.Fatalf("Expected success, got %v", err) } // Load TLS Configs. This is what TestServer and HTTPClient do internally. _, err = security.LoadServerTLSConfig( filepath.Join(certsDir, security.EmbeddedCACert), filepath.Join(certsDir, security.EmbeddedNodeCert), filepath.Join(certsDir, security.EmbeddedNodeKey)) if err != nil { t.Fatalf("Expected success, got %v", err) } _, err = security.LoadClientTLSConfig( filepath.Join(certsDir, security.EmbeddedCACert), filepath.Join(certsDir, security.EmbeddedNodeCert), filepath.Join(certsDir, security.EmbeddedNodeKey)) if err != nil { t.Fatalf("Expected success, got %v", err) } // Start a test server and override certs. // We use a real context since we want generated certs. params := base.TestServerArgs{ SSLCA: filepath.Join(certsDir, security.EmbeddedCACert), SSLCert: filepath.Join(certsDir, security.EmbeddedNodeCert), SSLCertKey: filepath.Join(certsDir, security.EmbeddedNodeKey), } s, _, _ := serverutils.StartServer(t, params) defer s.Stopper().Stop() // Insecure mode. clientContext := testutils.NewNodeTestBaseContext() clientContext.Insecure = true httpClient, err := clientContext.GetHTTPClient() if err != nil { t.Fatal(err) } req, err := http.NewRequest("GET", s.AdminURL()+"/_admin/v1/health", nil) if err != nil { t.Fatalf("could not create request: %v", err) } resp, err := httpClient.Do(req) if err == nil { resp.Body.Close() t.Fatalf("Expected SSL error, got success") } // Secure mode but no Certs: permissive config. clientContext = testutils.NewNodeTestBaseContext() clientContext.Insecure = false clientContext.SSLCert = "" httpClient, err = clientContext.GetHTTPClient() if err != nil { t.Fatal(err) } // Endpoint that does not enforce client auth (see: server/authentication_test.go) req, err = http.NewRequest("GET", s.AdminURL()+"/_admin/v1/health", nil) if err != nil { t.Fatalf("could not create request: %v", err) } resp, err = httpClient.Do(req) if err != nil { t.Fatalf("Expected success, got %v", err) } resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("Expected OK, got: %d", resp.StatusCode) } // New client. With certs this time. clientContext = testutils.NewNodeTestBaseContext() clientContext.SSLCA = filepath.Join(certsDir, security.EmbeddedCACert) clientContext.SSLCert = filepath.Join(certsDir, security.EmbeddedNodeCert) clientContext.SSLCertKey = filepath.Join(certsDir, security.EmbeddedNodeKey) httpClient, err = clientContext.GetHTTPClient() if err != nil { t.Fatalf("Expected success, got %v", err) } req, err = http.NewRequest("GET", s.AdminURL()+"/_admin/v1/health", nil) if err != nil { t.Fatalf("could not create request: %v", err) } resp, err = httpClient.Do(req) if err != nil { t.Fatalf("Expected success, got %v", err) } resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("Expected OK, got: %d", resp.StatusCode) } }
// This is a fairly high-level test of CA and node certificates. // We construct SSL server and clients and use the generated certs. func TestUseCerts(t *testing.T) { defer leaktest.AfterTest(t) // Do not mock cert access for this test. security.ResetReadFileFn() defer ResetTest() certsDir := util.CreateTempDir(t, "certs_test") defer util.CleanupDir(certsDir) err := security.RunCreateCACert(certsDir, 512) if err != nil { t.Fatalf("Expected success, got %v", err) } err = security.RunCreateNodeCert(certsDir, 512, []string{"127.0.0.1"}) if err != nil { t.Fatalf("Expected success, got %v", err) } err = security.RunCreateClientCert(certsDir, 512, security.RootUser) if err != nil { t.Fatalf("Expected success, got %v", err) } // Load TLS Configs. This is what TestServer and HTTPClient do internally. _, err = security.LoadServerTLSConfig(certsDir, "node") if err != nil { t.Fatalf("Expected success, got %v", err) } _, err = security.LoadClientTLSConfig(certsDir, security.NodeUser) if err != nil { t.Fatalf("Expected success, got %v", err) } // Start a test server and override certs. // We use a real context since we want generated certs. testCtx := server.NewContext() testCtx.Certs = certsDir testCtx.User = security.NodeUser testCtx.Addr = "127.0.0.1:0" testCtx.PGAddr = "127.0.0.1:0" s := &server.TestServer{Ctx: testCtx} if err := s.Start(); err != nil { t.Fatal(err) } defer s.Stop() // Insecure mode. clientContext := testutils.NewNodeTestBaseContext() clientContext.Insecure = true httpClient, err := clientContext.GetHTTPClient() if err != nil { t.Fatal(err) } req, err := http.NewRequest("GET", "https://"+s.ServingAddr()+"/_admin/health", nil) if err != nil { t.Fatalf("could not create request: %v", err) } resp, err := httpClient.Do(req) if err == nil { resp.Body.Close() t.Fatalf("Expected SSL error, got success") } // Secure mode but no Certs directory: permissive config. clientContext = testutils.NewNodeTestBaseContext() clientContext.Certs = "" httpClient, err = clientContext.GetHTTPClient() if err != nil { t.Fatal(err) } // Endpoint that does not enforce client auth (see: server/authentication_test.go) req, err = http.NewRequest("GET", "https://"+s.ServingAddr()+"/_admin/health", nil) if err != nil { t.Fatalf("could not create request: %v", err) } resp, err = httpClient.Do(req) if err != nil { t.Fatalf("Expected success, got %v", err) } resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("Expected OK, got: %d", resp.StatusCode) } // Endpoint that enforces client auth (see: server/authentication_test.go) req, err = http.NewRequest("GET", "https://"+s.ServingAddr()+driver.Endpoint, nil) if err != nil { t.Fatalf("could not create request: %v", err) } resp, err = httpClient.Do(req) if err != nil { t.Fatalf("Expected success, got %v", err) } resp.Body.Close() if resp.StatusCode != http.StatusUnauthorized { t.Fatalf("Expected status code %d, got: %d", http.StatusUnauthorized, resp.StatusCode) } // New client. With certs this time. clientContext = testutils.NewNodeTestBaseContext() clientContext.Certs = certsDir httpClient, err = clientContext.GetHTTPClient() if err != nil { t.Fatalf("Expected success, got %v", err) } req, err = http.NewRequest("GET", "https://"+s.ServingAddr()+"/_admin/health", nil) if err != nil { t.Fatalf("could not create request: %v", err) } resp, err = httpClient.Do(req) if err != nil { t.Fatalf("Expected success, got %v", err) } resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("Expected OK, got: %d", resp.StatusCode) } }