-
Notifications
You must be signed in to change notification settings - Fork 71
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
Refactoring of library to simplify the kex/cipher handling #134
Refactoring of library to simplify the kex/cipher handling #134
Conversation
@chris-rock @atomic111 what do you think about the direction? I guess we should place this to the 2.0.0 because of the chef version. What do you think? |
0cff3c9
to
c047c60
Compare
b4bef9a
to
18579f6
Compare
18579f6
to
afb7f33
Compare
@chris-rock @arlimus @atomic111 its ready. Can you please review? Please do not merge, we need the 1.3.0 first (#135). Followups of this PR will be addressed by issues #136 and #137 |
@chris-rock @arlimus @atomic111 any remarks? I would really appreciate the review of this one |
afb7f33
to
5493a4c
Compare
@chris-rock @arlimus @atomic111 anybody? :-( |
@artem-sidorenko Great work. Let me have a look at this later today. |
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.
@artem-sidorenko Thank you for the improvement. I apologize for the late review. I like your clean-up and and the improved version detection. I am not sure about the meta programing. Could you explain why we need it?
|
||
type, call = parse_method(method) | ||
|
||
Chef::Log.debug("Called #{method}") |
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.
Do we need the whitespace between the lines?
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.
fixed
@@ -0,0 +1,220 @@ | |||
# encoding: utf-8 |
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.
any reason why you prefix the file with devsec
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.
Module/class name is DevSec::SSH
, as there is no similar path in place, I called the file devsec_ssh
to allow a similar matching between file name and class/module name
|
||
ssh_version = send("get_ssh_#{type}_version", node) | ||
|
||
Chef::Log.debug("Detected ssh version #{ssh_version}") |
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.
I like the additional logging
private | ||
|
||
def method_missing(method, node, enable_weak = false) | ||
super unless respond_to_missing?(method) |
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.
Instead of using method missing, I would prefer to use get_client_macs
directly and use the abstracting then. I suggest, we use method_missing
only if required.
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.
Do you mean something like this?
def get_data(type, args)
end
def get_client_macs(args)
get_data('client_macs', args)
end
def get_server_macs(args)
get_data('server_macs', args)
end
My basic idea was to avoid the same code 5 times...
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.
@artem-sidorenko Yes, I think that would make it easier to read and understand the code. We would also be more explicit. I also believe, its easier for Ruby beginners to add contributions if we try to avoid Ruby meta programming
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.
A good read from my perspective: https://www.codeschool.com/blog/2015/04/24/7-deadly-sins-of-ruby-metaprogramming/
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.
@chris-rock I agree with you on the disadvantages (esp. the point about ruby beginners and contributions), I also thought about define_method like suggested by you in some other comment, in this case the usage of method_missing was the most elegant way from my perspective.
I'll have a look how to rewrite it, maybe a combination of abstraction and simple loop with define_method will be a good tradeoff and understandable for Ruby beginners too
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.
I really like your abstractions and we should keep those, even it it means we define 3 method and they all call the same internal method. Personally I am not sure if we should even do define_method
. Maybe we try to be explicit and grow from there?
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.
@chris-rock I was thinking about something like
[:macs, :ciphers, :kexs].each do |crypto_type|
define_method("get_client_#{crypto_type}") do |node, enable_weak = false|
get_crypto_data(crypto_type, :client, node, enable_weak)
end
define_method("get_server_#{crypto_type}") do |node, enable_weak = false|
get_crypto_data(crypto_type, :server, node, enable_weak)
end
end
What do you think?
What do you mean with grow from there
?
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.
'grow' - to see if we need further abstractions. I am not 100% sure if we should use define_method
. I would like to get a perspective from @arlimus or @atomic111
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.
@chris-rock I pushed the ef4e38a without method_missing and define_method
class << self | ||
KLASS ||= ::DevSec::Ssh | ||
|
||
def method_missing(method, *args) |
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.
I would try to avoid method_missing
here. I am not sure why we need that.
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 can also get rid of this proxy connector and integrate the entire thing as Chef::Recipe::DevSec::SSH
?
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 particular method_missing
is a transparent proxy, if you want to extend / change ::DevSec::Ssh
- you do not have to change something here
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.
I removed this proxy completely and we use DevSec::Ssh
now
end | ||
|
||
def get_ssh_version(node, package) | ||
version = node['packages'][package]['version'] |
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.
👍 I like the version detection based on the real package
mac: SshMac.get_macs(node, node['ssh']['client']['weak_hmac']), | ||
kex: SshKex.get_kexs(node, node['ssh']['client']['weak_kex']), | ||
cipher: SshCipher.get_ciphers(node, node['ssh']['client']['cbc_required']), | ||
mac: DevSec.get_client_macs(node, node['ssh']['client']['weak_hmac']), |
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.
Should we use DevSec::SSH
as namespace? In order to avoid name conflicts with other cookbooks?
My first iteration was without it, I ended up with almost a same code for all functions |
The node object should not be passed anymore as parameter from recipe. Please do not merge this PR after you think the review is done, I'll squash the fixup commits prior to the merge to master |
@chris-rock I already removed the metaprogramming implementation, so there is no open discussion point anymore. Please let us proceed here, this PR is already open for 1 month and it blocks me on further progress in this cookbook. Do you see any other points? Otherwise please tell me "LGTM" and I will squash&merge it and start to work on other tasks. |
There's advice available on preferred choices of key exchange, message authentication and ciphers from a number of sources [1][2][3], all of which don't _entirely_ agree with each other, and then there's the hardcoded selection of Kex, MAC and ciphers encoded in this cookbook. At the time of committing, there is a refactor going on to simplify kex and cipher handling: dev-sec#134 Even in that refactor, hmac-ripemd160 MACs, which have been removed in OpenSSH 6.7 (and hence flagged by ssh-audit[1] and are absent from Mozilla's recommendations[2] for modern sshd, yet are still recommended by secure secure shell[3]) are included in the default MAC list. Likewise hmac-sha2-256 and hmac-sha2-512 are flagged by ssh-audit[1] as they are encrypt-and-MAC, which has a number of issues, discussed in secure secure shell[3]. There is likely to be more complexity and balancing of features/security to consider plus the future changes of refactors in this cookbook, so initially, I'd just like a way of overriding the generated defaults. [1] https://github.com/arthepsy/ssh-audit [2] https://wiki.mozilla.org/Security/Guidelines/OpenSSH [3] https://stribika.github.io/2015/01/04/secure-secure-shell.html
There's advice available on preferred choices of key exchange, message authentication and ciphers from a number of sources [1][2][3], all of which don't _entirely_ agree with each other, and then there's the hardcoded selection of Kex, MAC and ciphers encoded in this cookbook. At the time of committing, there is a refactor going on to simplify kex and cipher handling: dev-sec#134 Even in that refactor, hmac-ripemd160 MACs, which have been removed in OpenSSH 6.7 (and hence flagged by ssh-audit[1] and are absent from Mozilla's recommendations[2] for modern sshd, yet are still recommended by secure secure shell[3]) are included in the default MAC list. Likewise hmac-sha2-256 and hmac-sha2-512 are flagged by ssh-audit[1] as they are encrypt-and-MAC, which has a number of issues, discussed in secure secure shell[3]. There is likely to be more complexity and balancing of features/security to consider plus the future changes of refactors in this cookbook, so initially, I'd just like a way of overriding the generated defaults. [1] https://github.com/arthepsy/ssh-audit [2] https://wiki.mozilla.org/Security/Guidelines/OpenSSH [3] https://stribika.github.io/2015/01/04/secure-secure-shell.html
@artem-sidorenko great job!!! i will discuss this with @chris-rock. it looks pretty complete |
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 looks good to me @artem-sidorenko Once you remove the WIP from the title we should merge it
end | ||
|
||
def get_client_macs(enable_weak = false) | ||
get_crypto_data(:macs, :client, enable_weak) |
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.
👍 cool abstraction. much easier to read!
Module `DevSec::Ssh` delivers the crypto parameters. There is autodetection of ssh version with fallback to 5.9
d50ba56
to
33caca8
Compare
@chris-rock @atomic111 thank you! I bumped the master to 2.0.0 |
Closes #87, #136, #137
TODOs
DevSec::SshHardening
, extendChef::Recipe
only with functions used in the recipeDevSec::SshHardening
module