<commit_before>package utils

import (
	"crypto/tls"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/assert"
)

const (
	ServerCert = "../fixtures/notary-server.crt"
	ServerKey  = "../fixtures/notary-server.key"
	RootCA     = "../fixtures/root-ca.crt"
)

// copies the provided certificate into a temporary directory
func makeTempCertDir(t *testing.T) string {
	tempDir, err := ioutil.TempDir("/tmp", "cert-test")
	assert.NoError(t, err, "couldn't open temp directory")

	in, err := os.Open(RootCA)
	assert.NoError(t, err, "cannot open %s", RootCA)
	defer in.Close()
	copiedCert := filepath.Join(tempDir, filepath.Base(RootCA))
	out, err := os.Create(copiedCert)
	assert.NoError(t, err, "cannot open %s", copiedCert)
	defer out.Close()
	_, err = io.Copy(out, in)
	assert.NoError(t, err, "cannot copy %s to %s", RootCA, copiedCert)

	return tempDir
}

// If the cert files and directory are provided but are invalid, an error is
// returned.
func TestConfigServerTLSFailsIfUnableToLoadCerts(t *testing.T) {
	tempDir := makeTempCertDir(t)

	for i := 0; i < 3; i++ {
		files := []string{ServerCert, ServerKey, tempDir}
		files[i] = "not-real-file"

		result, err := ConfigureServerTLS(files[0], files[1], true, files[2])
		assert.Nil(t, result)
		assert.Error(t, err)
	}
}

// If server cert and key are provided, and client auth is disabled, then
// a valid tls.Config is returned with ClientAuth set to NoClientCert
func TestConfigServerTLSServerCertsOnly(t *testing.T) {
	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
	assert.NoError(t, err)

	tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, false, "")
	assert.NoError(t, err)
	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
	assert.True(t, tlsConfig.PreferServerCipherSuites)
	assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
	assert.Nil(t, tlsConfig.ClientCAs)
}

// If server cert and key are provided, and client cert directory is provided,
// a valid tls.Config is returned with the clientCAs set to the certs in that
// directory.
func TestConfigServerTLSWithCACerts(t *testing.T) {
	tempDir := makeTempCertDir(t)
	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
	assert.NoError(t, err)

	tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, false, tempDir)
	assert.NoError(t, err)
	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
	assert.True(t, tlsConfig.PreferServerCipherSuites)
	assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
	assert.Len(t, tlsConfig.ClientCAs.Subjects(), 1)
}

// If server cert and key are provided, and client auth is disabled, then
// a valid tls.Config is returned with ClientAuth set to
// RequireAndVerifyClientCert<commit_msg>Add test for if the client CA dir is empty<commit_after>package utils

import (
	"crypto/tls"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/assert"
)

const (
	ServerCert = "../fixtures/notary-server.crt"
	ServerKey  = "../fixtures/notary-server.key"
	RootCA     = "../fixtures/root-ca.crt"
)

// copies the provided certificate into a temporary directory
func makeTempCertDir(t *testing.T) string {
	tempDir, err := ioutil.TempDir("/tmp", "cert-test")
	assert.NoError(t, err, "couldn't open temp directory")

	in, err := os.Open(RootCA)
	assert.NoError(t, err, "cannot open %s", RootCA)
	defer in.Close()
	copiedCert := filepath.Join(tempDir, filepath.Base(RootCA))
	out, err := os.Create(copiedCert)
	assert.NoError(t, err, "cannot open %s", copiedCert)
	defer out.Close()
	_, err = io.Copy(out, in)
	assert.NoError(t, err, "cannot copy %s to %s", RootCA, copiedCert)

	return tempDir
}

// If the cert files and directory are provided but are invalid, an error is
// returned.
func TestConfigServerTLSFailsIfUnableToLoadCerts(t *testing.T) {
	tempDir := makeTempCertDir(t)

	for i := 0; i < 3; i++ {
		files := []string{ServerCert, ServerKey, tempDir}
		files[i] = "not-real-file"

		result, err := ConfigureServerTLS(files[0], files[1], true, files[2])
		assert.Nil(t, result)
		assert.Error(t, err)
	}
}

// If server cert and key are provided, and client auth is disabled, then
// a valid tls.Config is returned with ClientAuth set to NoClientCert
func TestConfigServerTLSServerCertsOnly(t *testing.T) {
	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
	assert.NoError(t, err)

	tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, false, "")
	assert.NoError(t, err)
	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
	assert.True(t, tlsConfig.PreferServerCipherSuites)
	assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
	assert.Nil(t, tlsConfig.ClientCAs)
}

// If a valid client cert directory is provided, but it contains no client
// certs, an error is returned.
func TestConfigServerTLSWithEmptyCACertDir(t *testing.T) {
	tempDir, err := ioutil.TempDir("/tmp", "cert-test")
	assert.NoError(t, err, "couldn't open temp directory")

	tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, false, tempDir)
	assert.Nil(t, tlsConfig)
	assert.Error(t, err)
}

// If server cert and key are provided, and client cert directory is provided,
// a valid tls.Config is returned with the clientCAs set to the certs in that
// directory.
func TestConfigServerTLSWithCACerts(t *testing.T) {
	tempDir := makeTempCertDir(t)
	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
	assert.NoError(t, err)

	tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, false, tempDir)
	assert.NoError(t, err)
	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
	assert.True(t, tlsConfig.PreferServerCipherSuites)
	assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
	assert.Len(t, tlsConfig.ClientCAs.Subjects(), 1)
}

// If server cert and key are provided, and client auth is disabled, then
// a valid tls.Config is returned with ClientAuth set to
// RequireAndVerifyClientCert
{'fraction_non_alphanumeric': 0.12919547984483049, 'fraction_numerical': 0.004047900151796255, 'mean_word_length': 4.871287128712871, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '482959', 'n_tokens_mistral': 2132, 'n_tokens_neox': 2080, 'n_words': 555}