-
Notifications
You must be signed in to change notification settings - Fork 347
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
T5661: Add show show ssh dynamic-protection attacker and show log ssh… #2369
Conversation
Confusingly, show-ssh-fingerprints.py shows up in this PR - because I made it executable I guess.
|
Permission changes are also recorded in Git, that's why the file pops up. Please remove this change from this PR. |
show-ssh-dynamic-protection is not good name for new op-mode module I’d request for review from @jestabro and @dmbaturin before merging I want to see more clear and short names, especially if we want to use it for graphql there are examples of “good names” https://github.com/vyos/vyos-1x/blob/current/data/op-mode-standardized.json |
So it sounds like the "right way" would be to combine the functions of show-ssh-dynamic-protection and show-ssh-fingerprints into a single ssh.py? |
That would be the best way indeed. |
Seeing as it's so fresh in my memory, I can combine the two into a single ssh.py. I should have something ready sometime tomorrow. |
This has been modified to include both the show ssh dynamic-protection and show ssh fingerprints commands in ssh.py, while using the new op mode style. Supports human readable and --raw output for all your API needs. |
src/op_mode/ssh.py
Outdated
pass | ||
if attackers: | ||
if raw: | ||
return {"response": attackers} |
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.
As I understand we don’t need extra “response” here
@jestabro what do you think?
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 have removed the "response" from the raw sections (except the errors)
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 idea but the implementation needs work.
|
||
def show_fingerprints(raw: bool, ascii: bool): | ||
config = ConfigTreeQuery() | ||
if not config.exists("service 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.
There's a dedicated exception for this case.
src/op_mode/ssh.py
Outdated
else: | ||
response = "SSH server public key fingerprints:\n" | ||
for key in keys: | ||
response = response + key + "\n" |
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.
Why not use "\n".join()
?
|
||
def show_dynamic_protection(raw: bool): | ||
config = ConfigTreeQuery() | ||
if not config.exists("service ssh dynamic-protection"): |
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.
See above, we have an exception specially for this case.
src/op_mode/ssh.py
Outdated
else: | ||
response = "Blocked attackers:\n" | ||
for attacker in attackers: | ||
response = response + attacker + "\n" |
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.
Same, I see no reason not to use "\n".join()
.
src/op_mode/ssh.py
Outdated
return response | ||
else: | ||
if raw: | ||
return {"response": "No blocked attackers."} |
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.
Imagine how the client will handle it. Logically, this call returns a list of blocked addresses. The client will want to pass that list to a template or similar. With your approach, the client will have to handle two cases: when it's a list as expected, and when it's a custom response with an error message.
Having no blocked attackers is not even an error state — there can be none because no one is attacking.
The API should just return an empty list in this case.
src/op_mode/ssh.py
Outdated
for keyfile in publickeys: | ||
if ascii: | ||
try: | ||
keys.append(cmd("ssh-keygen -l -v -E sha256 -f " + keyfile)) |
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.
While ssh-keygen
doesn't support any machine-readable output (sadly), I believe we can and should make an attempt to return useful ouput in the raw
case.
For example, suppose we have this:
256 SHA256:SCthwOukM2sh24XSgVbz8J+9i1DtEIV4czP7ECVHjtA no comment (ECDSA)
+---[ECDSA 256]---+
| .. ..ooo+ |
| .= . +oE= |
| ...B o.o.=. |
|..+. = ooo |
|.= o. +oS.o |
|*.+ ...oo. . |
|.B.. . .. |
|o.. . .. |
|. . .. |
+----[SHA256]-----+
For a user calling this from a script, something like this would be so much easier to work with:
{
"key_size: 256,
"type": "ECDSA",
"comment": "no comment",
"fingerprint": "SCthwOukM2sh24XSgVbz8J+9i1DtEIV4czP7ECVHjtA",
"ascii_art": ...
}
(Since ssh-keygen
says "no comment" when comment is not set and doesn't signal the absense of a comment, I think we should just always include what it says than try to infer if it's not a key with comment explicitly set to "no comment" somehow).
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've made the requested changes. In the process I also "tabulated" the output.
SSH server public key fingerprints:
Type Key Size Fingerprint Comment
------- ---------- -------------------------------------------------- -----------
RSA 3072 SHA256:QUsk927nC0ds8AF/CvxTUtBvNDcyEJjoHGQOE+yFZ8U root@debian
DSA 1024 SHA256:fWZsMLLdPOJ8RoO+Qo8ThizDUlIoDWkhhTaBK28Nlcs root@vyos
ED25519 256 SHA256:NGYZ85iN4dbzQVWPrzzxpvxlQLo5sndUsjLOYGYISHU root@debian
ECDSA 256 SHA256:TsFZT0f4TvlJjKjiIcCRTKPOf459v3oXA0IZiPe76jI root@debian
show_fingerprints --raw:
[
{
"type": "RSA",
"key_size": "3072",
"fingerprint": "SHA256:QUsk927nC0ds8AF/CvxTUtBvNDcyEJjoHGQOE+yFZ8U",
"comment": "root@debian"
},
{
"type": "DSA",
"key_size": "1024",
"fingerprint": "SHA256:fWZsMLLdPOJ8RoO+Qo8ThizDUlIoDWkhhTaBK28Nlcs",
"comment": "root@vyos"
},
{
"type": "ED25519",
"key_size": "256",
"fingerprint": "SHA256:NGYZ85iN4dbzQVWPrzzxpvxlQLo5sndUsjLOYGYISHU",
"comment": "root@debian"
},
{
"type": "ECDSA",
"key_size": "256",
"fingerprint": "SHA256:TsFZT0f4TvlJjKjiIcCRTKPOf459v3oXA0IZiPe76jI",
"comment": "root@debian"
}
]
SSH server public key fingerprints:
Type Key Size Fingerprint Comment ASCII Art
------- ---------- -------------------------------------------------- ----------- -------------------
RSA 3072 SHA256:QUsk927nC0ds8AF/CvxTUtBvNDcyEJjoHGQOE+yFZ8U root@debian +---[RSA 3072]----+
| .+=+O.+o+o. |
| o=@ E o +.oo|
| . *.+ = + =o+|
| . o o * * o|
| S o X . |
| . = . |
| . o |
| o . |
| . |
+----[SHA256]-----+
DSA 1024 SHA256:fWZsMLLdPOJ8RoO+Qo8ThizDUlIoDWkhhTaBK28Nlcs root@vyos +---[DSA 1024]----+
|+O+. . |
|*+o + |
|oo.+ . . o |
|o o E = B |
|.. * . .S = % |
| + = o ++ B o |
| . . o o ++ o |
| + .+ |
| o. |
+----[SHA256]-----+
...
show_fingerprints --ascii --raw
[
{
"type": "RSA",
"key_size": "3072",
"fingerprint": "SHA256:QUsk927nC0ds8AF/CvxTUtBvNDcyEJjoHGQOE+yFZ8U",
"comment": "root@debian",
"ascii_art": "+---[RSA 3072]----+\n| .+=+O.+o+o. |\n| o=@ E o +.oo|\n| . *.+ = + =o+|\n| . o o * * o|\n| S o X . |\n|
. = . |\n| . o |\n| o . |\n| . |\n+----[SHA256]-----+"
},
{
"type": "DSA",
"key_size": "1024",
"fingerprint": "SHA256:fWZsMLLdPOJ8RoO+Qo8ThizDUlIoDWkhhTaBK28Nlcs",
"comment": "root@vyos",
"ascii_art": "+---[DSA 1024]----+\n|+O+. . |\n|*+o + |\n|oo.+ . . o |\n|o o E = B |\n|.. * . .S = % |\n|
+ = o ++ B o |\n| . . o o ++ o |\n| + .+ |\n| o. |\n+----[SHA256]-----+"
},
{
"type": "ED25519",
"key_size": "256",
"fingerprint": "SHA256:NGYZ85iN4dbzQVWPrzzxpvxlQLo5sndUsjLOYGYISHU",
"comment": "root@debian",
"ascii_art": "+--[ED25519 256]--+\n| .. E .....|\n| . o % . ..|\n| . . % = . o .|\n| . .= . o +...|\n| .S. o o+.|\n|
. = o+o= |\n| +.++++ =|\n| o+o.=.|\n| .. .o..|\n+----[SHA256]-----+"
},
{
"type": "ECDSA",
"key_size": "256",
"fingerprint": "SHA256:TsFZT0f4TvlJjKjiIcCRTKPOf459v3oXA0IZiPe76jI",
"comment": "root@debian",
"ascii_art": "+---[ECDSA 256]---+\n| ooo ..o . .oo |\n| .=.o + o o.. |\n| .. o o + o.o. |\n|o o o o . .+o |\n| o . S o o...|\n|
. . * . o ...|\n| . .o = o |\n| E= + . . |\n| .+=o.+oo |\n+----[SHA256]-----+"
}
]
… dynamic-protection
When this gets approved, I believe it should be an easy backport to 1.4. A pre-requisite backport would be #2363 however, as it contains the op command definitions for the 'show ssh fingerprints' command which was improved in this one. |
… dynamic-protection
Change Summary
Adds the following:
show log ssh dynamic-protection
show ssh dynamic-protection
Types of changes
Related Task(s)
Related PR(s)
Component(s) name
show log ssh dynamic-protection
show ssh dynamic-protection
Proposed changes
show log ssh dynamic-protection
show ssh dynamic-protection
How to test
Smoketest result
Checklist: