Rash in Jupyter (with iracket)
First of all, congratulations for this beautiful piece of code.
Recently, I have been using it in my daily work with Emacs + Org-mode to create "literate scripts". I would also like to propose my colleagues to use it but they feel Emacs as a real obstacle. They are more receptive to Jupyter, though.
So, trying to connect the dots, I found a Racket kernel for Jupyter (iRacket). However, I have not been able to create Jupyter cells that make use of the Rash reader on it. Would it be possible?
On Sun, Jun 26, 2022 at 12:21:34PM -0700, ixemad wrote:
First of all, congratulations for this beautiful piece of code.
Thanks! I'm glad you like it.
Recently, I have been using it in my daily work with Emacs + Org-mode to create "literate scripts".
Do you have any example of this you can share? I'd be interested to see what you are doing.
I would also like to propose my colleagues to use it but they feel Emacs as a real obstacle. They are more receptive to Jupyter, though.
So, trying to connect the dots, I found a Racket kernel for Jupyter (iRacket). However, I have not been able to create Jupyter cells that make use of the Rash reader on it. Would it be possible?
I haven't used it, but it looks like it should be. The iRacket documentation has a section about using it with other languages and readers. Note that there is an optional #:reader argument. Rash's reader is called Linea. My documentation on Linea isn't, uh, superb. But you should be able to get it working if you use #:reader linea/reader (or maybe just #:reader linea, but without looking closer I'm pretty sure it's the former).
I hope that helps, despite being delayed and shallow help. Good luck, Rash with Jupyter sounds awesome!
Yeah, I tried to use linea both ways but it did not work. I get the following error in the Jupyter's backend if I set the reader to linea/reader:
open-input-file: cannot open module file
module path: linea/reader
path: /home/user/.local/share/racket/8.5/pkgs/linea/reader.rkt
system error: no such file or directory; rkt_err=3
context...:
/home/user/.local/share/racket/8.5/pkgs/iracket/lang.rkt:65:2: config:get-read-syntax
/home/user/.local/share/racket/8.5/pkgs/iracket/private/kernel.rkt:124:13
Oh the other hand, there is no iRacket complaint if I just set linea as the reader. However, it fails to execute any Rash cell.

Of course, I tested that iRacket was correctly installed in my machine.

With respect to the (amazing) Org-mode example, the next one is likely not the clearest one but it will allow me to expose how flexible (and powerful) is the combination of Org-mode + Rash (+ Qi):
#+name: vulnerable_lambda/lambda-arn
#+header: :var assumed-role=vulnerable_lambda/assumed-role
#+header: :var regions=ALL-REGIONS
#+begin_src racket :lang rash
(require racket/function
racket/string
racket/stream
json
qi )
(define (/ entry-name)
(☯ (~> (hash-ref entry-name) (if list? sep _))))
(define (@ entry-name op entry-value)
(☯ (pass (esc (λ (key) (op (hash-ref key entry-name) entry-value))))) )
(void (putenv "AWS_ACCESS_KEY_ID" #{ echo $assumed-role | jq -r ".Credentials.AccessKeyId" }))
(void (putenv "AWS_SECRET_ACCESS_KEY" #{ echo $assumed-role | jq -r ".Credentials.SecretAccessKey" }))
(void (putenv "AWS_SESSION_TOKEN" #{ echo $assumed-role | jq -r ".Credentials.SessionToken" }))
(let ([lambdas
(for*/stream ([region (string-split regions)]
[result (in-list
(with-handlers ([exn:fail? (const '())])
#{ aws lambda list-functions \
--region $region \
|>> string->jsexpr \
|> (☯ (~> (/ 'Functions)
(>< (/ 'FunctionArn))
▽)) } ) ) ] )
result) ])
(if (stream-empty? lambdas)
"no lambdas in any region"
(~> (lambdas) stream-first display) ) )
#+end_src
#+RESULTS[087d42e5287904de8dadb0f07a8eae4e90888f72]: vulnerable_lambda/lambda-arn
: arn:aws:lambda:us-east-1:7245XXXX8614:function:vulnerable_lambda_cgidb34c8zbk3d-policy_applier_lambda1
So, the Org-mode block vulnerable_lambda/lambda-arn is using as input parameters (assumed-role, regions) the output of other two previous blocks (vulnerable_lambda/assumed-role and ALL-REGIONS). This block combines Racket, Rash, Qi and jq to get as a cached result arn:aws:lambda:us-east-1:7245XXXX8614:function:vulnerable_lambda_cgidb34c8zbk3d-policy_applier_lambda1 which can be reused by another block. Beautiful, isn't it? :smile:
I saw but didn't notice that iRacket code runs in a sandbox. A far as I can see, the sandbox refuses to run the following example code:
(require shell/pipeline)
(run-subprocess-pipeline '(echo))
subprocess: `execute' access denied for /usr/bin/echo
context...:
body of top-level
/home/user/.local/share/racket/8.5/pkgs/shell-pipeline/private/subprocess-pipeline.rkt:663:0: run-pipeline-members
/home/user/.local/share/racket/8.5/pkgs/shell-pipeline/private/subprocess-pipeline.rkt:510:0: run-pipeline/spec
/home/user/.local/share/racket/8.5/pkgs/shell-pipeline/private/subprocess-pipeline.rkt:441:0: run-subprocess-pipeline
/usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:555:3
So, my colleagues will have to love Emacs :smile:
Alright, with respect to my previous comment, iRacket can be hacked to allow the execute permission in the sandbox (specifically, by modifying the sandbox-path-permissions parameter). Of course, this is a sensitive decision that must be weighed.