Skip to content

Conversation

@i110
Copy link
Contributor

@i110 i110 commented Aug 5, 2016

This adds a feature which makes it easy to write access control handler, as below

mruby.handler |
  acl {
    allow { addr.start_with?("192.168.") }
    deny { ! addr.match?(/^110\.110\./) && user_agent.match(/curl/i) }
    redirect("https://example.com", 301) { path == "/redirect" }
    response(403, {}, ["you are evil!"]) { user_agent.match(/evil/i) }
  }
file.dir: examples/doc_root
  • H2O::ACL module will be automatically included, which has only one method acl.
  • Also add a setup to test mruby handlers. If you want to run ruby handler tests, do make mruby-test and execute t/00unit.mruby.t
  • To avoid miss-configuration, add some checks of return value from configuration. The details are as follows.

When you use acl in a handler code, acl must be called only once, and the return value of the code is exactly acl 's return value (i.e. you must wrap whole handler's code by acl block)

See the following example:

This setting is danger because acl setting is absolutely ignored (so check it and abort if so)

mruby.hanlder |
  acl {
    deny { addr.start_with?("110.110.") } # meaningless
  }
  Htpasswd.new("/path/to/.htpasswd", "realm")

You can correct it as the below.

mruby.hanlder |
  acl {
    deny { addr.start_with?("110.110.") }
    Htpasswd.new("/path/to/.htpasswd", "realm")
  }

or separate it into multple handlers.

mruby.hanlder |
  acl {
    deny { addr.start_with?("110.110.") }
  }
mruby.hanlder |
  Htpasswd.new("/path/to/.htpasswd", "realm")

end

def satisfy?(env)
return @cond.nil? || MatchingBlock.new(env).instance_eval(&@cond)
Copy link
Member

@kazuho kazuho Aug 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is my understanding that satisfy? is called for every request? If so, please move the call to instance_eval to somewhere during the initialization phase.

To generalize, I think we should refrain from calling slow functions (e.g. instance_eval) while processing each request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed, we have to call satisfy? method for every requests because whether the request match conditions or not cannot be decided without each request information.
I guess that not so many acl conditions will appear, so it won't be performance issue.

@kazuho
Copy link
Member

kazuho commented Aug 8, 2016

Thank you for the PR.

I like it very much, since the DSL looks very attractive (and easy to use). Please take a look at my in-line comments.

fprintf(stderr, "%s: no memory\n", H2O_MRUBY_MODULE_NAME);
abort();
}
int ok = !mrb_nil_p(h2o_mruby_compile_code(mrb, config, errbuf));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここマクロの中で2回コンパイル走ってた罠

@i110
Copy link
Contributor Author

i110 commented Aug 8, 2016

@kazuho all issues are fixed.

.gitmodules Outdated
url = https://github.com/h2o/cache-digest.js.git
[submodule "misc/mruby-mtest"]
path = misc/mruby-mtest
url = https://github.com/iij/mruby-mtest.git
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use misc/dump-github-repository.pl to dump mruby-mtest into misc/mruby-mtest. Run the perl script without arguments to find out how to use the program.

The reason we should do so is because tarballs created by GitHub will not include submodules; files required for building and testing H2O should never be a git-submodule.

@kazuho
Copy link
Member

kazuho commented Aug 12, 2016

Thank you for the updates. I've left two comments in-line, PTAL.

@i110
Copy link
Contributor Author

i110 commented Aug 15, 2016

@kazuho fixed the points you said.

it is unclear to me why we'd want to return values from each directive

Before this fix, acl can use plain callable returned value like the following:

acl {
  deny { path.match/../ }
  allow { addr.start_with?("192.") }
  proc {|env| [200, {}, []] } # this proc will be called when other directives don't match their conditions
}

The covering test cases were: 3346d3c#diff-1f0e213b76131d8d4093df0099c9d190R95

But as you said, it is a bit unclear behavior for the users and makes impl complicated, so I removed this behavior.
Now we can use use directive in such case:

acl {
  deny { path.match/../ }
  allow { addr.start_with?("192.") }
  use proc {|env| [200, {}, []] }
}

I think this is more intuitive.

/* require and include built-in libraries */
h2o_mruby_eval_expr(mrb, "require \"h2o.rb\"\n"
"require \"acl.rb\"\n"
"include H2O::ACL\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one more thing...

How about doing all of the following?

  1. renaming h2o.rb to bootstrap.rb
  2. require and include the acl code from bootstrap.rb

@kazuho
Copy link
Member

kazuho commented Aug 16, 2016

Maybe merge the contents of h2o.rb to bootstrap.rb?

@i110
Copy link
Contributor Author

i110 commented Aug 16, 2016

@kazuho I created new bootstrap.rb file and require h2o.rb in it instead of renaming, because I feel this is more clear about the initialization process.


/* require core modules and include built-in libraries */
h2o_mruby_eval_expr(mrb, "require \"preloads.rb\"");
h2o_mruby_assert(mrb);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we expect adequate information emitted to the log in case either requiring preloads.rb or doing the requires in preloads.rb fails?

If the answer is yes, I think we can merge this PR right away.

@kazuho
Copy link
Member

kazuho commented Aug 17, 2016

LGTM. Thank you for all your efforts.

Will merge once you finish applying clang-format.

@i110
Copy link
Contributor Author

i110 commented Aug 17, 2016

@kazuho Thank YOU for all your kind comments.
I applied clang-format for c files, and it didn't change anything wihout annoying header ordering.
So, pleaes go on.

@kazuho kazuho merged commit 219ccfa into h2o:master Aug 17, 2016
@i110 i110 mentioned this pull request Aug 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants