Skip to content

Latest commit

 

History

History
131 lines (91 loc) · 4.88 KB

README.md

File metadata and controls

131 lines (91 loc) · 4.88 KB

spamhouse

CircleCI

Spamhouse is a graphql server that adds ips to a local storage and detemines whether the IPs are in spamhous block list.

Spam

Usage

Run the server for the first time

make dev

Access the GraphQL browser UI at http://localhost:8080. The UI uses basic authentication, and as such the credentials are bootstrapped at application startup. The default credentials are: secureworks/supersecret. To modify default credentials, specify them as environment variables: DEFAULT_USER and DEFAULT_USER_PASSWORD in docker-compose.yml

The application port default is 8080, to modify the port the application is running on, modify the PORT number in the Makefile

Example mutation

To create a new entry, used the mutation below in the GraphQL UI.

mutation{
  enqueue(input: ["1.2.3.4"]){
    status
    errors
  }
}

Example query

To retrieve an existing entry, specify the query as follows:

query{
  getIPDetails(input: "1.2.3.4"){
    node{
      ip_address
      response_code
      uuid
      created_at
      updated_at
     
    }
  }
}

Start server from scratch

make run stops/starts the server without building the appplication

Stop the server

make stop

Shell into the database

make db-shell

Creates a shell into sqlite3. See instructions for sqlite3 here

Test server

make test

Runs go tests locally. Makes uses of golang build tags to only trigger local tests with !integration

Test integration

make test-integration

Runs integration tests. Makes uses of build tags to only trigger integration tests.

Development

  • To extend database access, modify repo.go
  • To modify the graphql resolvers, modify gqlgen.yml, after the changes are saved, run make regenerate
  • To update auth (e.g. add database user validation) update auth.go

Requirements

  • Your API must be protected with basic authentication

    • Username: secureworks
    • Password: supersecret
  • You should have a GraphQL API that is available via a /graphql endpoint

    • We suggest using https://gqlgen.com/
      • Mutations
        • enqueue(ip: [“ip1”, “ip2”])

          • This should kick off a background job to do the DNS lookup and store it in the database for each IP passed in for future lookups
          • If the lookup has already happened, this should queue it up again and update the response and updated_at fields
        • Queries

          • getIPDetails(ip: “ip address here”)
            • It should look up the IP in the database

            • If it’s not there, it should respond with the appropriate response code

            • This should have:

              • uuid ID
              • created_at time
              • updated_at time
              • response_code string
              • ip_address string
  • You should use SQLite as your database to make this portable

  • Dependencies should be handled using go mod

  • Tests should be written for the key components of the system

  • A README is required and should explain how to develop and run the project as if it were a new team member working on it

  • The application should be packaged as a Dockerfile, and should accept a PORT environment variable to know which port to run on

  • You can use any external libraries you want, but you must document and explain why you’re using them

External dependencies

  • gorm - golang orm, used it for migration simplicity mainly.
  • logrus - structured logger utility, better than printf :)
  • testify - testify, utility for test assertion
  • backoff - backoff utility, used for ensuring db is up before staring up the application
  • envconfig - utility library for environment variable configuration
  • chi - Added chi for injecting auth middleware
  • gqlgen - graphql, per the requirements suggestion
  • uuid - generate UUID, used for generating uuid before inserting ip entry into database. See BeforeCreate hook in model

Additional comments

  • Initially I had implemented the queuing process to return the ips added upon enqueueing. See commit, however, I recognized that ultimately this was not the best approach since it would dpeend on each ip returning after it had been refreshed.