Skip to content

Commit

Permalink
Merge pull request #19 from cipherstash/identity
Browse files Browse the repository at this point in the history
init: lock context interface
  • Loading branch information
calvinbrewer authored Dec 25, 2024
2 parents e35c1d9 + 9e16175 commit af747d6
Show file tree
Hide file tree
Showing 22 changed files with 2,732 additions and 4,064 deletions.
5 changes: 5 additions & 0 deletions .changeset/big-taxis-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/jseql": minor
---

Released support for LockContext initializer.
5 changes: 5 additions & 0 deletions .changeset/real-trains-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/jseql": minor
---

Refactored init function to not require envrionment variables as arguments.
5 changes: 5 additions & 0 deletions .changeset/witty-ligers-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/jseql": minor
---

Replaces jset with vitest for better typescript support.
8 changes: 8 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ jobs:
- name: Install Dependencies
run: npm install

- name: Create .env file in ./packages/jseql/
run: |
touch ./packages/jseql/.env
echo "CS_WORKSPACE_ID=${{ secrets.CS_WORKSPACE_ID }}" >> ./packages/jseql/.env
echo "CS_CLIENT_ID=${{ secrets.CS_CLIENT_ID }}" >> ./packages/jseql/.env
echo "CS_CLIENT_KEY=${{ secrets.CS_CLIENT_KEY }}" >> ./packages/jseql/.env
echo "CS_CLIENT_ACCESS_KEY=${{ secrets.CS_CLIENT_ACCESS_KEY }}" >> ./packages/jseql/.env
# Run TurboRepo tests
- name: Run tests
run: npm run test
56 changes: 31 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
`jseql` leverages [Encrypt Query Language (EQL)](https://github.com/cipherstash/encrypt-query-language) and [CipherStash](https://cipherstash.com) to encrypt data in a PostgreSQL database.

**Features:**
- **Data encryption**: Easily encrypt data with the `encrypt` function.
- **Data encryption**: Easily encrypt data with the `encrypt` function. CipherStash uses a unique encryption key for every record in the database. This is also know as **field level encryption.**
- **Data decryption**: Extract plaintext data from encrypted data using the `decrypt` function.
- **TypeScript support**: Strongly typed with TypeScript interfaces and types.
- **Logging**: Integrated logging using [logtape](https://github.com/logtape/logtape) for debugging and monitoring.
Expand Down Expand Up @@ -93,13 +93,7 @@ Import the `eql` function from the `@cipherstash/jseql` package and initialize t

```typescript
const { eql } = require('@cipherstash/jseql')

const eqlClient = await eql({
workspaceId: process.env.CS_WORKSPACE_ID,
clientId: process.env.CS_CLIENT_ID,
clientKey: process.env.CS_CLIENT_KEY,
accessToken: process.env.CS_CLIENT_ACCESS_KEY,
})
const eqlClient = await eql()
```

.. or using ES6?
Expand All @@ -109,12 +103,7 @@ import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const { eql } = require('@cipherstash/jseql')

const eqlClient = await eql({
workspaceId: process.env.CS_WORKSPACE_ID,
clientId: process.env.CS_CLIENT_ID,
clientKey: process.env.CS_CLIENT_KEY,
accessToken: process.env.CS_CLIENT_ACCESS_KEY,
})
const eqlClient = await eql()
```

We are working on a solution to support the `import` statement in the future.
Expand All @@ -130,7 +119,7 @@ const ciphertext = await eqlClient.encrypt('plaintext', {
})
```

The `encrypt` function returns an object with a `c` property, which is the encrypted data.
The `encrypt` function returns an object with a `c` key, and the value is the encrypted data.

```typescript
{
Expand All @@ -155,28 +144,45 @@ The `decrypt` function returns a string with the plaintext data.
### Lock context

`jseql` supports lock contexts to ensure that only the intended users can access sensitive data.
To use a lock context, initialize a `LockContext` object with the identity claims and workspace ID.

To use a lock context, you will need to provide an array of identity claims.
```typescript
import { LockContext } from '@cipherstash/jseql'

// eqlClient from the previous steps
const lc = new LockContext(eqlClient, {
identityClaim: ['sub'],
})
```

The lock context needs to be tied to a specific user.
To identify the user, call the `identify` method on the lock context object.

```typescript
const plaintext = await eqlClient.encrypt(plaintext, {
const lockContext = await lc.identify('jwt_token_from_identiti_provider')
```

The `jwt_token_from_identiti_provider` is the JWT token from your identity provider, and can be retrieved from the user's session.

### Encrypting data with a lock context

To encrypt data with a lock context, pass the lock context object as a parameter to the `encrypt` function.

```typescript
const ciphertext = await eqlClient.encrypt('plaintext', {
table: 'users',
column: 'email',
lockContext: {
identityClaim: ['sub'],
},
lockContext,
})
```

The `identityClaim` property is an array of identity claims that must be present in the JWT token to decrypt the data.
### Decrypting data with a lock context

To decrypt data, use the `decrypt` function by passing in the lock context:
To decrypt data with a lock context, pass the lock context object as a parameter to the `decrypt` function.

```typescript
const plaintext = await eqlClient.decrypt(ciphertext, {
lockContext: {
identityClaim: ['sub'],
},
lockContext,
})
```

Expand Down
10 changes: 1 addition & 9 deletions apps/basic/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,7 @@ import 'dotenv/config'
import { eql } from '../../packages/jseql/dist/index.cjs'

async function main() {
if (!process.env.CS_CLIENT_ID || !process.env.CS_CLIENT_KEY) {
throw new Error('CS_CLIENT_ID and CS_CLIENT_KEY must be set')
}

const eqlClient = await eql({
workspaceId: process.env.CS_WORKSPACE_ID,
clientId: process.env.CS_CLIENT_ID,
clientKey: process.env.CS_CLIENT_KEY,
})
const eqlClient = await eql()

const ciphertext = await eqlClient.encrypt('plaintext', {
column: 'column_name',
Expand Down
1 change: 0 additions & 1 deletion apps/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"license": "ISC",
"description": "",
"dependencies": {
"@cipherstash/jseql": "*",
"dotenv": "^16.4.7"
}
}
12 changes: 6 additions & 6 deletions apps/basic/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */

/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
Expand All @@ -25,7 +25,7 @@
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */

/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"module": "commonjs" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
Expand Down Expand Up @@ -77,12 +77,12 @@
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,

/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
Expand All @@ -105,6 +105,6 @@

/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
1 change: 1 addition & 0 deletions apps/drizzle/environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ declare namespace NodeJS {
CS_CLIENT_ID: string
CS_CLIENT_KEY: string
CS_WORKSPACE_ID: string
CS_CLIENT_ACCESS_KEY: string
}
}
3 changes: 1 addition & 2 deletions apps/drizzle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"devDependencies": {
"@types/node": "^22.10.2",
"@types/pg": "^8.11.10",
"dotenv": "^16.4.7",
"drizzle-kit": "^0.24.2",
"tsx": "^4.19.2"
},
Expand All @@ -20,8 +21,6 @@
"typescript": "^5.0.0"
},
"dependencies": {
"@cipherstash/jseql": "^3.0.0",
"dotenv": "^16.4.7",
"drizzle-orm": "^0.33.0",
"pg": "^8.13.1",
"postgres": "^3.4.4"
Expand Down
13 changes: 4 additions & 9 deletions apps/drizzle/src/eql.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import 'dotenv/config'

// NPM isn't working with Turborepo so hardcoded to cjs build for now
// import { eql } from '@cipherstash/jseql'
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const { eql } = require('@cipherstash/jseql')
import { eql } from '../../../packages/jseql/dist/index.cjs'

export const eqlClient = await eql({
workspaceId: process.env.CS_WORKSPACE_ID,
clientId: process.env.CS_CLIENT_ID,
clientKey: process.env.CS_CLIENT_KEY,
accessToken: process.env.CS_CLIENT_ACCESS_KEY,
})
export const eqlClient = await eql()
Loading

0 comments on commit af747d6

Please sign in to comment.