gosh

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2022 License: MIT

README

Gosh

Gosh is a secure shell and scripting language. It features a fined-grain permission system and enforces a strong isolation of dependencies.
Gosh is not production ready yet : if you find a bug or want to suggest a feature create an issue please ! Expect breaking changes :).

Have a look at the features section and the wiki !

Installation

You can use the gosh executable to execute scripts and launch the shell:

go install github.com/gosh-project/gosh/cmd/gosh@0.1.0
Editor support

If you use VSCode you can install the extension of ID gosh.gosh.

Shell

Launch the REPL with the shell subcommand:

gosh shell

Before starting the REPL gosh will execute $HOME/startup.gosh and grant the required permissions by the script to the shell.
No additional permissions will be granted. You can copy the file named startup.gosh in this repository and modify it.

Execute commands
ex echo "hello"   # 'ex echo hello' will not work
ex go help

NOTE: Almost no commands are allowed by default, edit your startup.gosh file to allow more commands (and subcommands).

Read, Create, Update, Delete, Provide resources

From now on we will references files, HTTP servers and endpoints as "resources".

You can easily manipulate resources using read | create | update | delete followed by the resource's name.

Read

Read the entries of a folder: read ./dir/

Read a file: read ./file.txt

Read an HTTP resource with: read https://jsonplaceholder.typicode.com/posts/1

Create

Create a dir: create ./dir/

Create a file: create ./file.txt [optional string content]

Update

Append to a file: update ./file.txt append <string>

Patch an HTTP resource: update <url> <string | object>

Delete

Use delete <resource> for deletion. The deletion is recursive for folders.

Scripting

# hello.gosh

require {
    use: {
        globals: "*"
    }
}

log "hello world !"

Execute the script with the run subcommand:

gos run hello.gosh -p=required

Language features

The most important features are described in this section. If you want to learn Gosh or want to know more details about specific features you can go on the wiki.

integer = 1 
float = 1.0

if true {
    log 1 2
} else {
    log(3,4)
}

slice1 = ["a", "b", 3, $integer]
slice2 = [
    "a" 
    "b"
    3
    $integer
]

object = {name: "Foo"}
Permissions

Required permissions are specified at the top of each module (file).

require {
    read: {
        # access to all HTTPS hosts (GET, HEAD, QUERY)
        : https://*

        # access to all paths prefixed with /home/project
        : /home/project/...
    }
    use: {
        globals: "*"
    }
    create: {
        globals: ["myvar"]
        : https://* # POST to all HTTPS hosts
    }
}

Gosh also provides limitations to prevent a script to take all resources. In the example below writing to the filesystem is limited to 100 kB/s.

require {
    
    [...]

    limits: {
        "fs/write": 100kB/s
    }
}

Permissions can also be dropped.

drop-perms {
   read: {
       : https://*
   }
}
Special literals & expressions
# Path literals
/home/user/
./file.json

# Path expressions
/home/user/$dirpath$

# Path patterns support basic globbing (*, [set], ?) and prefixing (not both at the same time).
./data/*.json
/app/logs/...
/app/*/...     		# invalid (this might be allowed in the future though)

# HTTP host literals
https://example.com
https://example.com:443

# HTTP host pattern literals
https://*               # any HTTPS host
https://*.com           # any domain with .com as TLD, will not match against subdomains
https://*.example.com   # any subdomain of example.com

# URL literals
https://example.com/
https://example.com/index.html
https://localhost/

# URL expressions
https://example.com/users/$id$
@loc/index.html       	# @loc is a host alias : the expression resolves to https://localhost/index.html if @loc = https://localhost


# URL pattern literals (only prefix patterns supported)
https://example.com/users/...
Quantity literals
10s		# time.Duration
10ms    # time.Duration
10%		# 0.10

sleep 100ms
Imports

Syntax:

import <varname> <url> <file-content-sha256>  { <global variables> } allow { <permission> }

Importing a module is like executing a script with the passed globals and granted permissions.

# content of https://example.com/return_1.gosh
return 1

Script:

import modresult https://example.com/return_1.gosh "SG2a/7YNuwBjsD2OI6bM9jZM4gPcOp9W8g51DrQeyt4=" {MY_GLOBVAR: "a"} allow {}
Routines

Routines are mainly used for concurrent work and isolation. Each routine has its own goroutine and state.

Embedded module:

routine = sr {http: $$http} {
    return http.get(https://example.com/)!
} allow { 
    use: {globals: ["http"]} 
}

Call syntax (all permissions are inherited).

routine = sr nil f()

Routines can optionally be part of a "routine group" that allows easier control of multiple routines. The group variable is defined (and updated) when the spawn expression is evaluated.

for (1 .. 10) {
    sr req_group nil read(https://jsonplaceholder.typicode.com/posts)!
}

results = $req_group.WaitAllResults()!

For more details about the different features you can read the repository's wiki.

Implementation

  • Why use a tree walk interpreter instead of a bytecode interpreter ?
    -> Tree walk interpreters are slower but simpler : that means less bugs and vulnerabilities. An implementation of Gosh that uses a bytecode interpreter might be developed in the future though.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL