Skip to content

Commit

Permalink
feat(endomoat): support native modules in policy generation [ci skip]
Browse files Browse the repository at this point in the history
  • Loading branch information
boneskull committed Apr 1, 2024
1 parent 2c283c7 commit dcf0016
Show file tree
Hide file tree
Showing 38 changed files with 827 additions and 10 deletions.
10 changes: 10 additions & 0 deletions packages/endomoat/src/constants.js
Expand Up @@ -65,3 +65,13 @@ export const LMR_TYPE_BUILTIN = 'builtin'
* `js` module type for a `LavamoatModuleRecord`
*/
export const LMR_TYPE_SOURCE = 'js'

/**
* `native` module type for a `LavamoatModuleRecord`
*/
export const LMR_TYPE_NATIVE = 'native'

/**
* Name of Endo's `bytes` parser
*/
export const ENDO_PARSER_BYTES = 'bytes'
3 changes: 3 additions & 0 deletions packages/endomoat/src/index.js
Expand Up @@ -86,6 +86,9 @@ export async function run(entrypointPath, policyOrOpts = {}, opts = {}) {
globals: globalThis,
importHook,
moduleTransforms,
fallbackLanguageForExtension: {
node: 'bytes',
},
})

return namespace
Expand Down
3 changes: 3 additions & 0 deletions packages/endomoat/src/policy-gen/index.js
Expand Up @@ -168,6 +168,9 @@ export async function loadCompartmentMap(
moduleLocation,
importHook,
moduleTransforms,
fallbackLanguageForExtension: {
node: 'bytes',
},
})

// `compartmentRenames` is a mapping of filepath to compartment name;
Expand Down
30 changes: 21 additions & 9 deletions packages/endomoat/src/policy-gen/policy-generator-context.js
Expand Up @@ -8,8 +8,10 @@ import { isBuiltin as nodeIsBuiltin } from 'node:module'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import {
ENDO_PARSER_BYTES,
LAVAMOAT_PKG_POLICY_ROOT,
LMR_TYPE_BUILTIN,
LMR_TYPE_NATIVE,
LMR_TYPE_SOURCE,
} from '../constants.js'
import { defaultReadPowers } from '../power.js'
Expand Down Expand Up @@ -289,7 +291,10 @@ export class PolicyGeneratorContext {
* @returns {Promise<import('lavamoat-core').LavamoatModuleRecord[]>}
* @internal
*/
async buildModuleRecordsForSource(specifier, { record, sourceLocation }) {
async buildModuleRecordsForSource(
specifier,
{ parser, record, sourceLocation }
) {
if (!sourceLocation) {
// XXX: why would we not have a sourceLocation?
throw new TypeError(
Expand Down Expand Up @@ -317,17 +322,24 @@ export class PolicyGeneratorContext {
* The `ModuleSource.content` prop is already pre-processed by Endo, and we
* do not want that, since it befouls our AST crawling.
*
* This will not be run if the `parser` is `bytes`.
*
* @remarks
* Doing this first since it may be more likely to fail than the other
* operations below
* @type {NonNullable<
* import('lavamoat-core').LavamoatModuleRecord['content']
* >}
* operations below.
* @type {string | undefined}
* @todo Modify Endo to surface the original source
*
* @todo Add more exceptions to the parsers?
*/
const content = await this.#readPowers
.read(sourceLocation)
.then((buffer) => PolicyGeneratorContext.#decoder.decode(buffer))
let content

await Promise.resolve()
if (parser !== ENDO_PARSER_BYTES) {
content = await this.#readPowers
.read(sourceLocation)
.then((buffer) => PolicyGeneratorContext.#decoder.decode(buffer))
}

/**
* The {@link LavamoatModuleRecord.file} prop
Expand Down Expand Up @@ -356,7 +368,7 @@ export class PolicyGeneratorContext {
packageName: this.packageName,
importMap,
content,
type: LMR_TYPE_SOURCE,
type: parser === ENDO_PARSER_BYTES ? LMR_TYPE_NATIVE : LMR_TYPE_SOURCE,
}),
]

Expand Down
5 changes: 5 additions & 0 deletions packages/endomoat/test/fixture/dynamic/README.md
@@ -0,0 +1,5 @@
This fixture is not used directly; it's only here in order to create a snapshot:

```bash
npm run start
```
2 changes: 2 additions & 0 deletions packages/endomoat/test/fixture/dynamic/index.js
@@ -0,0 +1,2 @@
import { hello as otherHello } from 'dynamic-require'
export const hello = 'hello ' + otherHello

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions packages/endomoat/test/fixture/dynamic/package.json
@@ -0,0 +1,14 @@
{
"name": "hello",
"version": "0.0.0",
"type": "module",
"description": "this code actually runs",
"private": true,
"main": "index.js",
"scripts": {
"start": "npx snapshot-fs . ../json/dynamic.json"
},
"dependencies": {
"dynamic-require": "0.0.0"
}
}
10 changes: 10 additions & 0 deletions packages/endomoat/test/fixture/json/dynamic.json
@@ -0,0 +1,10 @@
{
"/package.json": "{\n \"name\": \"hello\",\n \"version\": \"0.0.0\",\n \"type\": \"module\",\n \"description\": \"this code actually runs\",\n \"private\": true,\n \"main\": \"index.js\",\n \"scripts\": {\n \"start\": \"npx snapshot-fs . ../json/dynamic.json\"\n },\n \"dependencies\": {\n \"dynamic-require\": \"0.0.0\"\n }\n}\n",
"/index.js": "import { hello as otherHello } from 'dynamic-require'\nexport const hello = 'hello ' + otherHello\n",
"/README.md": "This fixture is not used directly; it's only here in order to create a snapshot:\n\n```bash\nnpm run start\n```\n",
"/node_modules/dynamic-require/world.js": "module.exports = 'world'\n",
"/node_modules/dynamic-require/package.json": "{\n \"name\": \"dynamic-require\",\n \"version\": \"1.0.0\",\n \"license\": \"ISC\",\n \"private\": true,\n \"main\": \"index.js\",\n \"dependencies\": {\n \"dummy\": \"0.0.0\"\n }\n}\n",
"/node_modules/dynamic-require/index.js": "function dynamic (value) {\n return require(value)\n}\n\nexports.hello = dynamic('dummy')\n",
"/node_modules/dummy/package.json": "{\n \"name\": \"dummy\",\n \"version\": \"0.0.0\"\n}\n",
"/node_modules/dummy/index.js": "module.exports = \"world\"\n"
}
139 changes: 139 additions & 0 deletions packages/endomoat/test/fixture/json/native.json

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions packages/endomoat/test/fixture/json/phony-native.json
@@ -0,0 +1,8 @@
{
"/package.json": "{\n \"name\": \"native\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"license\": \"ISC\",\n \"private\": true,\n \"main\": \"app.js\",\n \"dependencies\": {\n \"hello\": \"^1.0.0\"\n }\n}\n",
"/index.js": "import addon from 'hello'\nexport const hello = addon.hello()\n",
"/node_modules/hello/package.json": "{\n \"name\": \"hello\",\n \"version\": \"0.0.0\",\n \"description\": \"this code does not run\",\n \"private\": true,\n \"main\": \"index.js\"\n}\n",
"/node_modules/hello/index.js": "var addon = require('./hello')\n\nconsole.log(addon.hello()) // 'world'\n\nmodule.exports = addon\n",
"/node_modules/hello/hello.node": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000",
"/node_modules/hello/README.md": "This fixture is an example of a package shipping a native module (`hello.node`). `hello.node` is not _actually_ a native module, but it has the right extension and is full of null bytes. Good enough.\n"
}
5 changes: 5 additions & 0 deletions packages/endomoat/test/fixture/native/README.md
@@ -0,0 +1,5 @@
This fixture is not used directly; it's only here in order to create a snapshot:

```bash
npm run start
```
2 changes: 2 additions & 0 deletions packages/endomoat/test/fixture/native/index.js
@@ -0,0 +1,2 @@
import addon from 'hello_world'
export const hello = addon.hello()
Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Binary file not shown.
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit dcf0016

Please sign in to comment.