-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add OpenSSL::SSL::Server and HTTP::Server#bind_ssl #5960
Add OpenSSL::SSL::Server and HTTP::Server#bind_ssl #5960
Conversation
Doesn't this make requiring socket require openssl now? That's certainly something I don't like. |
Yes. But we can remove |
If we already have Which avoids the whole require issue entirely. |
spec/std/http/server/server_spec.cr
Outdated
@@ -1,5 +1,8 @@ | |||
require "spec" | |||
require "http/server" | |||
{% unless flag?(:without_openssl) %} | |||
require "../../../support/ssl" | |||
{% end %} |
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.
Perhaps specs should always expect SSL?
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.
Maybe... I don't care.
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.
Well, I don't understand why specs should sometimes test something but sometimes shouldn't.
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.
True. I don't know if there is any specific use case for speccing without openssl.
If removed, it should be removed from http client specs as well.
3f367f9
to
7f0045e
Compare
In Ruby this is
|
|
I agree with @ysbaddaden that having On the other hand, there is a small conceptual difference, as It probably doesn't make much sense to to SSL over Unix sockets, but it should be flexible enough to be able to do that (or possibly any other Socket implementation). But I could add some initializer overloads to match those of |
7f0045e
to
f88c43b
Compare
This is simply because we have no abstraction for a "IO producer". If we did have one,
Yes it does - client certificates can be useful for a system daemon. It's not common though. I'm fine with adding constructors to shorten This needs a rebase. |
f88c43b
to
a2c868b
Compare
Rebased |
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.
The socket library is a real mess, honestly.
src/http/server.cr
Outdated
@@ -260,7 +260,9 @@ class HTTP::Server | |||
end | |||
|
|||
private def handle_client(io : IO) | |||
io.sync = false | |||
if io.is_a?(IO::Buffered) |
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.
This highlights some pretty bad design:
sync
should always be false by default, it's currently not for socketssync
should always be a property onIO
, it should be ignored if theIO
isn't buffered.- the previous means wrapper
IO
s can correctly pass throughsync
to their wrapped IOs.
src/openssl/ssl/server.cr
Outdated
end | ||
end | ||
|
||
def accept? : OpenSSL::SSL::Socket::Server? |
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.
We need to provide def accept
too. In TCPServer
this comes from Socket
(which we don't inherit).
::Socket::Server
also needs to gain the correct abstract def
s.
src/openssl/ssl/server.cr
Outdated
@wrapped.close if @sync_close | ||
end | ||
|
||
delegate local_address, remote_address, to: @wrapped |
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.
If you're going to add these delegations you might as well just make wrapped
a TCPSocket | UNIXSocket
instead of a Socket::Server
.
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.
Actually, remote_address
is incorrect, a server doesn't have one. Only sockets do.
But every server should have a local_address
(see my proposal in #5778). So I think @wrapped
's type should stay Socket::Server
. And this way you can wrap SSL socket servers ;)
a2c868b
to
0527633
Compare
0527633
to
259c64e
Compare
Can this get a review? |
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.
This is a breaking change though, so should be merged for 0.26.0
.
I still think we should have a OpenSSL::SSL::Server.tcp
constructor.
spec/support/ssl.cr
Outdated
|
||
def ssl_context_pair | ||
server_context = OpenSSL::SSL::Context::Server.new | ||
server_context.certificate_chain = File.join("spec", "std", "openssl", "ssl", "openssl.crt") |
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.
use datapath?
begin | ||
yield server | ||
ensure | ||
server.close |
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.
Maybe we should bubble exceptions in general. There might be a specific kind of exception that make sense to not bubble, but usually that is not the case. Other than that LGTM.
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.
This does bubble exceptions, it's ensure
not rescue
?
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.
Yup, I miss read it.
259c64e
to
b3d8a98
Compare
src/http/server.cr
Outdated
# context.private_key = "openssl.key" | ||
# server.bind_ssl "127.0.0.1", 8080, context | ||
# ``` | ||
def bind_ssl(host : String, port : Int32, context : OpenSSL::SSL::Context::Server = OpenSSL::SSL::Context::Server.new, reuse_port : Bool = false) : Socket::IPAddress |
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.
Shouldn't bind_ssl
methods be wrapped between {% unless flag?(:without_openssl) %}
?
Otherwise there is a reference to a type that is not declared.
f042096
to
5afb75b
Compare
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.
@straight-shoota I had two minor questions regarding docs and a request for a rebase of the PR so the CI can be happy before merging.
src/http/server.cr
Outdated
# context.private_key = "openssl.key" | ||
# server.bind_ssl "127.0.0.1", 8080, context | ||
# ``` | ||
def bind_ssl(host : String, port : Int32, context : OpenSSL::SSL::Context::Server = OpenSSL::SSL::Context::Server.new, reuse_port : Bool = false) : Socket::IPAddress |
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.
Can the context be accessed and changed after bind_ssl
is called?
Or does the default OpenSSL::SSL::Context::Server.new
load some system information?
Otherwise I don't see why a default OpenSSL::SSL::Context::Server
is defined.
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.
Yeah, it probably doesn't make much sense. The context can't be accessed afterwards.
src/openssl/ssl/server.cr
Outdated
@@ -0,0 +1,46 @@ | |||
require "socket" | |||
|
|||
class OpenSSL::SSL::Server |
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.
There is doc missing in the OpenSSL::SSL::Server
, #initialize
and .open
. Or there is a :nodoc:
missing.
5afb75b
to
0fddf42
Compare
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.
Thanks!
@straight-shoota I would rather merge this without squashing, but since there are fixup! commits, should I ask you to rebase? I don't think that when commit-merging from GitHub directly the fixup will be applied when intended. |
Rebased and squashed 👍 |
0fddf42
to
a9e78f2
Compare
This adds a reusable
SSLServer
class which wraps anotherSocket::Server
in an SSL layer.With
HTTP::Server#bind_ssl
SSL context can be configured for every server socket individually instead of using the instance variabletls
for all sockets.Followup on #5776