Where we are right now

User writes this

SELECT * FROM profile WHERE email='{{context.arguments.email}}'
{
  arguments: {
    email: "john@example.com"
  }
}

Template

Context

SELECT * FROM profile WHERE email='john@example.com'

Database

Result

SELECT * FROM profile WHERE email='{{context.arguments.email}}'
{
  arguments: {
    email: "john@example.com"
  }
}

Template

Context

SELECT * FROM profile WHERE email='john@example.com'

Database

Result

Not easy to write

Insecure

a; DROP TABLE profile

Hard to check if query was correct or if there were errors

Can only write one statement

How can we make it better ?

Potential Options

  1. Keep the current approach but mitigate injection issues.
  2. Allow users to write some declarative meta language
  3. Allow users to write a small amount of custom code

 

Option 1 and 3 both involve using a library called Knex

1. Fix injection problems with Current Approach

SELECT * FROM profile WHERE email=?
[$context.arguments.email]

Query

Args

SELECT * FROM profile WHERE email='john@example.com'

Database

Result

Context

Approach 1 (continued)

  • User defines the raw query + arguments to be passed
  • Knex builds a safe SQL statement

Drawbacks

  • SQL is hard to write
  • User can still only write one statement per resolver

2. Allow users to write some declarative meta language

{
  "profile": {
    "where": {
      "email": "$context.arguments.email"
    }
  }
}

Context

SELECT * FROM profile WHERE email='john@example.com'

???

  • No existing solution we can leverage
  • Building one would be really hard and is not in our interest

Approach 3 - Allow Users to Write Code

Approach 3 (Continued)

return db.select().from('meme').orderBy('id', 'desc')

JavaScript

{
  db: Knex,
  resolve: {
    args: { ... },
    // more graphql stuff
  }
}

Sandbox

VM

Result

Approach 3

  • User writes some javascript code with help of Knex.
  • User code is run inside a sandboxed environment
    • Cannot require()
    • Cannot process.exit()
    • etc.
  • User can do multiple queries and write some small pieces of business logic.

Multiple Queries

Custom Business Logic

Drawbacks

  • It's 5x slower than the original
  • It can be modified so it's only a small bit slower.
    • This opens up one case where the user code can crash the server
    • while(true) {}

Impact

  • We can only do this if we agree that a user 100% owns their server
  • If they cause problems, they have to deal with it.
  • We will not be able to support running code from different users in the same server - It's too dangerous
  • If we want to do multi tenancy, we will need to solve it at another level

Summary

Three approaches:

  • Keep existing approach but mitigate injection issues with knex
    • Can't do multiple queries
    • Do people want to write SQL?
  • Meta Language approach
    • Might be nice but too much effort
  • Users write some sandboxed code
    • Flexible, multiple queries, business logic
    • Multi-Tenancy Concerns
    • Do people want to write JavaScript? :)
Made with Slides.com