Skip to content

Commit

Permalink
add e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
devang-gaur committed May 17, 2021
1 parent caff66f commit af88e60
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 66 deletions.
1 change: 0 additions & 1 deletion pkg/http-server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,3 @@ type APIServer struct {
func NewAPIServer() *APIServer {
return &APIServer{}
}

32 changes: 16 additions & 16 deletions pkg/http-server/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,35 @@ import (
func TestValidateFiles(t *testing.T) {
server := APIServer{}
table := []struct {
name string
name string
privateKeyFile string
certFile string
wantOutput interface{}
wantErr error
certFile string
wantOutput interface{}
wantErr error
}{
{
name : "normal file names",
name: "normal file names",
privateKeyFile: "key",
certFile: "cert",
wantErr: nil,
certFile: "cert",
wantErr: nil,
},
{
name : "error in both privatekey and certfile filenames",
name: "error in both privatekey and certfile filenames",
privateKeyFile: "",
certFile: "server.crt",
wantErr: fmt.Errorf("certificate file provided but private key file missing"),
certFile: "server.crt",
wantErr: fmt.Errorf("certificate file provided but private key file missing"),
},
{
name: "error in privatekey filename",
name: "error in privatekey filename",
privateKeyFile: "",
certFile: "",
wantErr: nil,
certFile: "",
wantErr: nil,
},
{
name: "error in certfile filename",
name: "error in certfile filename",
privateKeyFile: "keyfile",
certFile: "",
wantErr: fmt.Errorf("private key file provided but certficate file missing"),
certFile: "",
wantErr: fmt.Errorf("private key file provided but certficate file missing"),
},
}

Expand Down
202 changes: 202 additions & 0 deletions test/e2e/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,21 @@
package server_test

import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"io"
"math/big"
"net"
"net/http"
"os"
"path/filepath"
"strings"
"time"

"github.com/accurics/terrascan/pkg/utils"
serverUtils "github.com/accurics/terrascan/test/e2e/server"
Expand All @@ -46,6 +55,8 @@ var (
iacRootRelPath = filepath.Join("..", "test_data", "iac")
awsIacRelPath = filepath.Join(iacRootRelPath, "aws")
policyRootRelPath = filepath.Join("..", "test_data", "policies")
tlsServerKeyPath = filepath.Join("..", "test_data", "certs", "server.key")
tlsServerCertPath = filepath.Join("..", "test_data", "certs", "server.crt")
goldenFilesRelPath = filepath.Join("..", "scan", "golden")
tfGoldenFilesRelPath = filepath.Join(goldenFilesRelPath, "terraform_scans", "aws")
awsAmiGoldenRelPath = filepath.Join(tfGoldenFilesRelPath, "aws_ami_violations")
Expand Down Expand Up @@ -194,6 +205,88 @@ var _ = Describe("Server", func() {
})
})
})
Context("server is started with --key-path and --cert-path flag values", func() {
//setUpTLSFiles()

JustBeforeEach(func() {
os.Setenv(terrascanServerPort, "")
})

Context("--key-path server.key --cert-path server.crt", func() {
session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, []string{serverUtils.ServerCommand, "--key-path", tlsServerKeyPath, "--cert-path", tlsServerCertPath}...)
It("should start the https server session", func() {
// logs are written in StdErr
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route GET - /health"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route POST - /v1/{iac}/{iacVersion}/{cloud}/local/file/scan"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route POST - /v1/{iac}/{iacVersion}/{cloud}/remote/dir/scan"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("https server listening at port 9010"))
})

if utils.IsWindowsPlatform() {
session.Kill()
Eventually(session).Should(gexec.Exit(helper.ExitCodeOne))
} else {
session.Interrupt()
Eventually(session).Should(gexec.Exit(helper.ExitCodeZero))
}
})

Context("--key-path does-not-exist.key --cert-path non-existent.crt", func() {
session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, []string{serverUtils.ServerCommand, "--key-path", "does-not-exist.key", "--cert-path", "non-existent.crt"}...)
It("should start the https server session", func() {
// logs are written in StdErr
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route GET - /health"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route POST - /v1/{iac}/{iacVersion}/{cloud}/local/file/scan"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route POST - /v1/{iac}/{iacVersion}/{cloud}/remote/dir/scan"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("https server listening at port 9010"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("open non-existent.crt: no such file or directory"))
})

serverUtils.ValidateExitCode(session, helper.ExitCodeOne)
})

Context("--key-path does-not-exist.key --cert-path server.crt", func() {
session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, []string{serverUtils.ServerCommand, "--key-path", "does-not-exist.key", "--cert-path", tlsServerCertPath}...)
It("should start the https server session", func() {
// logs are written in StdErr
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route GET - /health"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route POST - /v1/{iac}/{iacVersion}/{cloud}/local/file/scan"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("Route POST - /v1/{iac}/{iacVersion}/{cloud}/remote/dir/scan"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("https server listening at port 9010"))
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("open does-not-exist.key: no such file or directory"))
})

serverUtils.ValidateExitCode(session, helper.ExitCodeOne)
})

Context("--key-path --cert-path server.crt", func() {
session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, []string{serverUtils.ServerCommand, "--key-path", "--cert-path", tlsServerCertPath}...)
It("should exit with code 1", func() {
// logs are written in StdErr
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("error with --key-path flag value: file name inappropriate: --cert-path"))
serverUtils.ValidateExitCode(session, helper.ExitCodeOne)
})
})
Context("--key-path server.key --cert-path -l debug", func() {
session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, []string{serverUtils.ServerCommand, "--key-path", tlsServerKeyPath, "--cert-path", "-l debug"}...)
It("should exit with code 1", func() {
// logs are written in StdErr
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("error with --cert-path flag value: file name inappropriate: -l"))
serverUtils.ValidateExitCode(session, helper.ExitCodeOne)
})
})
Context("server --key-path server.key --cert-path --log-level debug", func() {
session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, []string{serverUtils.ServerCommand, "--key-path", tlsServerKeyPath, "--cert-path", "--log-level", "debug"}...)
It("should exit with code 1", func() {
// logs are written in StdErr
Eventually(session.Err, serverUtils.ServerCommandTimeout).Should(gbytes.Say("error with --cert-path flag value: file name inappropriate: --log-level"))
serverUtils.ValidateExitCode(session, helper.ExitCodeOne)
})
})

//deleteTLSFiles()
})

})
})

Expand Down Expand Up @@ -224,3 +317,112 @@ rego_subdir = "%s"`, policyAbsPath, policyAbsPath)
}
os.Setenv(terrascanConfigEnvName, configFileName)
}

func setUpTLSFiles() (err error) {
// set up our CA certificate
ca := &x509.Certificate{
SerialNumber: big.NewInt(2019),
Subject: pkix.Name{
Organization: []string{"Company, INC."},
Country: []string{"US"},
Province: []string{""},
Locality: []string{"San Francisco"},
StreetAddress: []string{"Golden Gate Bridge"},
PostalCode: []string{"94016"},
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(0, 0, 1),
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}

// create our private and public key
caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return err
}

// create the CA
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
if err != nil {
return err
}

// pem encode
caPEM := new(bytes.Buffer)
pem.Encode(caPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: caBytes,
})

caPrivKeyPEM := new(bytes.Buffer)
pem.Encode(caPrivKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey),
})

// set up our server certificate
cert := &x509.Certificate{
SerialNumber: big.NewInt(2019),
Subject: pkix.Name{
Organization: []string{"Company, INC."},
Country: []string{"US"},
Province: []string{""},
Locality: []string{"San Francisco"},
StreetAddress: []string{"The Street"},
PostalCode: []string{"94016"},
},
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(0, 0, 1),
SubjectKeyId: []byte{1, 2, 3, 4, 6},
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}

certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return err
}

certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, &certPrivKey.PublicKey, caPrivKey)
if err != nil {
return err
}

certPEM := new(bytes.Buffer)
pem.Encode(certPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
})

certPrivKeyPEM := new(bytes.Buffer)
pem.Encode(certPrivKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
})

keyPath, err := os.Create(tlsServerKeyPath)
defer keyPath.Close()
certPrivKeyPEM.WriteTo(keyPath)

certPath, err := os.Create(tlsServerCertPath)
defer certPath.Close()
certPEM.WriteTo(certPath)

return
}

func deleteTLSFiles() error {
err := os.RemoveAll(tlsServerKeyPath)
if err != nil {
return err
}
err = os.RemoveAll(tlsServerCertPath)
if err != nil {
return err
}
return nil
}
7 changes: 6 additions & 1 deletion test/e2e/server/server_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,19 @@ const (
ServerCommand string = "server"
)

// ValidateExitCodeAndOutput validates the exit code and output of the command
// ValidateExitCodeAndOutput validates the exit code
func ValidateExitCodeAndOutput(session *gexec.Session, exitCode int, relFilePath string, isStdOut bool) {
gomega.Eventually(session).Should(gexec.Exit(exitCode))
goldenFileAbsPath, err := filepath.Abs(relFilePath)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
helper.CompareActualWithGolden(session, goldenFileAbsPath, isStdOut)
}

// ValidateExitCode validates the exit code
func ValidateExitCode(session *gexec.Session, exitCode int) {
gomega.Eventually(session).Should(gexec.Exit(exitCode))
}

// MakeHTTPRequest calls health handler of the api server
func MakeHTTPRequest(method, URL string) (*http.Response, error) {
r, err := http.NewRequest(method, URL, nil)
Expand Down
17 changes: 17 additions & 0 deletions test/e2e/test_data/certs/domain.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn
[dn]
C = IN
ST = Maharashtra
L = Pune
O = Acme
emailAddress = [email protected]
CN = terrascan.terrascan.svc
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = terrascan.terrascan.svc.cluster.local
43 changes: 21 additions & 22 deletions test/e2e/test_data/certs/server.crt
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID9TCCAt2gAwIBAgIJANcasjhanWjaMA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD
VQQGEwJJTjEUMBIGA1UECAwLTWFoYXJhc2h0cmExDTALBgNVBAcMBFB1bmUxETAP
BgNVBAoMCEFjY3VyaWNzMScwJQYJKoZIhvcNAQkBFhhkZXZhbmcuZ2F1ckBhY2N1
cmljcy5jb20xLjAsBgNVBAMMJXRlcnJhc2Nhbi50ZXJyYXNjYW4uc3ZjLmNsdXN0
ZXIubG9jYWwwHhcNMjEwNTEwMjIzMTM0WhcNMjEwNjA5MjIzMTM0WjCBnjELMAkG
A1UEBhMCSU4xFDASBgNVBAgMC01haGFyYXNodHJhMQ0wCwYDVQQHDARQdW5lMREw
DwYDVQQKDAhBY2N1cmljczEnMCUGCSqGSIb3DQEJARYYZGV2YW5nLmdhdXJAYWNj
dXJpY3MuY29tMS4wLAYDVQQDDCV0ZXJyYXNjYW4udGVycmFzY2FuLnN2Yy5jbHVz
dGVyLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnph3od0J
zp3RI8eQx488YVWIlBbqGZChDxoS8aadmBc+clM2ZPnEDfgsOvCe8UL0uG//waC1
UzNoXe5ThhsqD8avrlfqxYQk+PGcaf/iOOEMN9+G+rUmqm1zKkVPRkHjtMXvGUHb
lwULA0qMlvW24noWPXS+D+6cv90pFxP+2Xkh4FnDE63pXrQ+2Gf2hNVDMNaeiTP9
zPnyBE+6Pd5uLAMHrBpwkC9M39yhnLx1vlKO/XnOQGXANpItVHO8HsbKT+o6fbPI
/RshvNi7rq1mPBcbq/gwTs68RpafdXDKIWMOZDpMVOto5+B2DRMHIvZ/BW4y5Ip0
+wI2kXw8UlrHkQIDAQABozQwMjAwBgNVHREEKTAngiV0ZXJyYXNjYW4udGVycmFz
Y2FuLnN2Yy5jbHVzdGVyLmxvY2FsMA0GCSqGSIb3DQEBCwUAA4IBAQAGHoZvgZwd
dLbaZaVT6jfZLqZxz2g004/sK9z4U6bcXTeXx5nJUsE4RkCVt+wAsH1eNF8Xdr7c
rMTH5mcHYcpcRH1CBktYkMF5nZwLzjRoR5abju0BZWrsEZi7cDJOeboW6EQqFBn8
LFsG2437Lx8to8XYheo91HG3QFdFo2kofaelUAqIxz0WdPnjChPH7RpjUEubXn1+
VKKrFhB6zKulU+YJaEJ0LO38CejrwKRT+pr1v3HaWnJSitZaJDDwxvkvSjdf8Rk2
4HsU1Rp2v3ts1zfzUthWrnc3G8darZx5ZdQWjRK2C17zrtzJO7M33D8BjiQaTQXL
kCfVMzBQKmOp
MIIDwzCCAqugAwIBAgIJAO7Z/NNvw4OiMA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD
VQQGEwJJTjEUMBIGA1UECAwLTWFoYXJhc2h0cmExDTALBgNVBAcMBFB1bmUxDTAL
BgNVBAoMBEFjbWUxIDAeBgkqhkiG9w0BCQEWEWpvaG4uZG9lQGFjbWUuY29tMSAw
HgYDVQQDDBd0ZXJyYXNjYW4udGVycmFzY2FuLnN2YzAeFw0yMTA1MTUwNzI5MjNa
Fw0yMTA2MTQwNzI5MjNaMIGFMQswCQYDVQQGEwJJTjEUMBIGA1UECAwLTWFoYXJh
c2h0cmExDTALBgNVBAcMBFB1bmUxDTALBgNVBAoMBEFjbWUxIDAeBgkqhkiG9w0B
CQEWEWpvaG4uZG9lQGFjbWUuY29tMSAwHgYDVQQDDBd0ZXJyYXNjYW4udGVycmFz
Y2FuLnN2YzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALo0QgEtWsxx
S4xhcIdwu/cPGLnpsGPa9GNQwj9Nm8YHIQCFo3J2Q5wEA524dBZpZ+pWJkeynCdU
fXz8UiLTSqaMNOkQRLYX5l3wg4Wgy0Q1/qXFwaUiIjt+Hkd/rREPHlD02dGckUGk
0LVmFbSLu9XllIzec4CVq7YyfLRlFB/UoD2DQp11QEKv26GR5UJMQPUU5GsnO9eX
Zj55uC3xrxbLtll5u6YELcHQiLPHIMGBSOlKPYo1OKqkRRis9cDrg7a1EhmZ0h5z
jf1fA8jYndmWlIyzX7b2Sk2jN3YhY3s+BFbT+lWri84sWwmaFm28Hw5gKwyUtUnu
wKlmmxMgXHkCAwEAAaM0MDIwMAYDVR0RBCkwJ4IldGVycmFzY2FuLnRlcnJhc2Nh
bi5zdmMuY2x1c3Rlci5sb2NhbDANBgkqhkiG9w0BAQsFAAOCAQEAgvaoNX7uebBJ
/id4nRGQmnioqj9JalhVEEU1lXXazGlSevmbghGzd26r/g/CPaHDCcfBtXxdNhQA
1OSI4IU6aZcJh5y/Y/KOOnqcMJ+ttKJoTKJ0rDQR3HtPBodE9Hmly3q2IBDcRnaP
qNOcXMa01l3ySSwGycCsxFDVcjGNpJbgFn5rEL6SQcviH3vTU9UObpTU14aazotJ
M+Y5T9ao7IJUG4CQ0xNICJadWEIlbmCgVQQFV5x2IovAVtvB2Lg78/ppBPEJLklc
D45vXtA05ieqLSWYNK6Hr/gzbZ87cruXx18qKu1j6APj3ic9X0wbwfy07avPkV/I
A0EB636k6Q==
-----END CERTIFICATE-----
Loading

0 comments on commit af88e60

Please sign in to comment.