-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow passing csp_nonce_assign_key into router #40
base: master
Are you sure you want to change the base?
Changes from all commits
6b9e4fb
5dabf27
00d1ea5
b05dc84
ec06fae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,6 +97,26 @@ defmodule MyPhoenixAppWeb.Router do | |
end | ||
``` | ||
|
||
### Content Security Policy | ||
|
||
Content security policy nonces can be passed into the router to allow usage of strict content security policies throughout an application. | ||
|
||
This can be achieved by passing in a `csp_nonce_assign_key` to the `FunWithFlags.UI.Router` forward. Values for the nonces should be set in the conn assigns before reaching this router. | ||
|
||
The value of this can either be a single nonce assign key, or separate assign keys for script and style tags. | ||
|
||
For example: | ||
|
||
``` elixir | ||
forward "/", FunWithFlags.UI.Router, namespace: "feature-flags", csp_nonce_assign_key: :my_csp_nonce | ||
``` | ||
|
||
Or: | ||
|
||
``` elixir | ||
forward "/", FunWithFlags.UI.Router, namespace: "feature-flags", csp_nonce_assign_key: %{style: :my_style_nonce, script: :my_script_nonce} | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two examples are for Phoenix. It would be good here to provide examples for Plug. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, I suggest to provide full examples, that also show how the nonce values can be generated and set in the assigns and response headers. In other words, it's important to show how to use this end-to-end, rather than just mention it without clear instructions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the instructions from Oban are pretty clear, would you be open to basically lifting this into the docs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The way I understand them, the instructions from Oban show how to configure the names of the assign keys for the nonces. They don't show where the nonces are supposed to come from. I suppose they would come from a different plug, but a full example would be helpful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! I already had a nonce stored in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Funny enough, this just popped up in my feed reader. Our solution is different than that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for the delay, but I just wrote 2 examples, 1 simple with a single nonce and another more advanced with nonces specific to style and script tags. |
||
|
||
## Caveats | ||
|
||
While the base `fun_with_flags` library is quite relaxed in terms of valid flag names, group names and actor identifers, this web dashboard extension applies some more restrictive rules. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -198,6 +198,39 @@ defmodule FunWithFlags.UI.RouterTest do | |
end | ||
end | ||
|
||
describe "CSP nonce assign key option" do | ||
test "if csp_nonce_assign_key is set, the CSP nonce is rendered in the script and link tags" do | ||
{:ok, true} = FunWithFlags.enable :coconut | ||
|
||
csp_opts = [csp_nonce_assign_key: :pineapple] | ||
|
||
conn = | ||
conn(:get, "/flags/coconut") | ||
|> Plug.Conn.assign(:pineapple, "mango") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's add a comment to explain what's happening here. Why this can be confusing: manipulating Since this library's "server backend" is self-contained in its Router, I guess that here you expect the nonce That's ok, but let's make it clear with a comment. |
||
|> Router.call(Router.init(csp_opts)) | ||
|
||
assert 200 = conn.status | ||
assert String.contains?(conn.resp_body, ~s{<script nonce="mango"}) | ||
assert String.contains?(conn.resp_body, ~s{<link nonce="mango"}) | ||
end | ||
|
||
test "if csp_nonce_assign_key is set with differing values, the CSP nonce is rendered in the script and link tags" do | ||
{:ok, true} = FunWithFlags.enable :coconut | ||
|
||
csp_opts = [csp_nonce_assign_key: %{script: :lemon, style: :melon}] | ||
|
||
conn = | ||
conn(:get, "/flags/coconut") | ||
|> Plug.Conn.assign(:lemon, "peach") | ||
|> Plug.Conn.assign(:melon, "apricot") | ||
|> Router.call(Router.init(csp_opts)) | ||
|
||
assert 200 = conn.status | ||
assert String.contains?(conn.resp_body, ~s{<script nonce="peach"}) | ||
assert String.contains?(conn.resp_body, ~s{<link nonce="apricot"}) | ||
end | ||
end | ||
|
||
|
||
# For GET and DELETE | ||
# | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to link to some CSP docs here, for reference. For example: