diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93196b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +target +src +*.swp +clamrest +pyenv diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b22eb7c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.3 + +ADD . /go/src/github.com/osterzel/clamrest + +WORKDIR /go/src/github.com/osterzel/clamrest +RUN go get +RUN go install github.com/osterzel/clamrest + +ENTRYPOINT /go/bin/clamrest + +EXPOSE 8080 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1d8ee1e --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +SERVICE=clamrest +VERSION := dev + +run-container: .clamav build-container + -@docker rm -f $(SERVICE) + @docker run -d -p 9000:9000 -e PORT=9000 --name $(SERVICE) --link clamd:clamd $(SERVICE):$(VERSION) + +build-container: + docker build -t $(SERVICE):$(VERSION) . + +run-slug: .clamav build-slug + -@docker rm -f $(SERVICE) + @docker run -d -v target/app:/app -p 9000:9000 -e PORT=9000 --name $(SERVICE) --link clamd:clamd flynn/slugrunner start web + @echo "Clamrest listening on port 9000" + +build-slug: + -@rm -rf target + -@mkdir target + @tar cf - . | docker run --rm -i -a stdin -a stdout -a stderr flynn/slugbuilder -> target/slug.tgz + +test: + + + +.clamav: + @echo "Starting clamav docker image" + -@docker rm -f clamd + @docker run -d -p 3310:3310 --name clamd dinkel/clamavd + @echo "Waiting for clamd to respond" + @sleep 10 + +.restapi: + docker diff --git a/clamrest.go b/clamrest.go index 9e44202..b0ff685 100644 --- a/clamrest.go +++ b/clamrest.go @@ -19,11 +19,11 @@ func init() { } //This is where the action happens. -func uploadHandler(w http.ResponseWriter, r *http.Request) { +func scanHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { //POST takes the uploaded file(s) and saves it to disk. case "POST": - c := clamd.NewClamd(opts["CLAMD_CONNECTION"]) + c := clamd.NewClamd(opts["CLAMD_PORT"]) //get the multipart reader for the request. reader, err := r.MultipartReader() @@ -71,16 +71,16 @@ func main() { opts[pair[0]] = pair[1] } - if opts["CLAMD_CONNECTION"] == "" { - opts["CLAMD_CONNECTION"] = "tcp://localhost:3031" + if opts["CLAMD_PORT"] == "" { + opts["CLAMD_PORT"] = "tcp://localhost:3031" } fmt.Printf("Starting clamav rest bridge\n") - fmt.Printf("Connecting to clamd on %v\n", opts["CLAMD_CONNECTION"]) - clamd_test := clamd.NewClamd(opts["CLAMD_CONNECTION"]) + fmt.Printf("Connecting to clamd on %v\n", opts["CLAMD_PORT"]) + clamd_test := clamd.NewClamd(opts["CLAMD_PORT"]) clamd_test.Ping() version, err := clamd_test.Version() - + if err != nil { fmt.Printf("Error getting clamd version: %v\n", err) os.Exit(1) @@ -88,13 +88,12 @@ func main() { for version_string := range version { fmt.Printf("Clamd version: %v\n", version_string) } - fmt.Printf("Connected to clamd on %v\n", opts["CLAMD_CONNECTION"]) + fmt.Printf("Connected to clamd on %v\n", opts["CLAMD_PORT"]) - http.HandleFunc("/scan", uploadHandler) + http.HandleFunc("/scan", scanHandler) - //static file handler. - http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets")))) - - //Listen on port 8080 - http.ListenAndServe(":3030", nil) + //Listen on port PORT + if opts["PORT"] == "" { opts["PORT"] = "9000" } + fmt.Printf("Listening on port " + opts["PORT"]) + http.ListenAndServe(":" + opts["PORT"], nil) } diff --git a/tests/features/steps/scanning.py b/tests/features/steps/scanning.py new file mode 100644 index 0000000..9339962 --- /dev/null +++ b/tests/features/steps/scanning.py @@ -0,0 +1,18 @@ +from behave import * +from hamcrest import * +import requests + +@given('I have a file with contents "{contents}"') +def step_imp(context, contents): + context.file_contents = contents + +@when('I scan the file for a virus') +def step_impl(context): + files = { 'file': context.file_contents } + url = "http://localhost:9000" + r = requests.post(url + "/scan", files=files) + context.result = r + +@then('I get a http status of "{status}"') +def step_impl(context, status): + assert_that(int(status), equal_to(context.result.status_code)) diff --git a/tests/features/virus-scan.feature b/tests/features/virus-scan.feature new file mode 100644 index 0000000..c5570e6 --- /dev/null +++ b/tests/features/virus-scan.feature @@ -0,0 +1,11 @@ +Feature: testing virus scanning through rest API + + Scenario Outline: scan files for viruses + Given I have a file with contents + When I scan the file for a virus + Then I get a http status of + + Examples: virus_files + | content | status | + | "hello_world" | "200" | + | "X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*" | "500" | diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..b87a86a --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,9 @@ +PyHamcrest==1.8.5 +argparse==1.2.1 +behave==1.2.5 +enum34==1.0.4 +parse==1.6.6 +parse-type==0.3.4 +requests==2.7.0 +six==1.9.0 +wsgiref==0.1.2