-
Notifications
You must be signed in to change notification settings - Fork 66
Rebuild and allow user SSH #2977
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
Conversation
Per @lachmanfrantisek claim, @nforro wants to be the early adopter! :-) |
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.
vcs-diff-lint found more than 10 potential problems in the proposed changes. Check the Files changed tab for more details.
d8bf463
to
f964c9b
Compare
There is still work to be done but can you please do a preliminary review @praiskup? I don't want to sink time in fine-tuning the details without knowing, that the general idea looks good. What remains to be done:
|
@@ -862,6 +865,8 @@ def add(cls, user, pkgs, copr, source_type=None, source_json=None, | |||
copr_dir=copr_dir, | |||
bootstrap=bootstrap, | |||
isolation=isolation, | |||
allow_user_ssh=allow_user_ssh, | |||
ssh_public_key=ssh_public_key, |
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.
Would it be possible to have this in YAML/JSON format or something...? We
could have things like:
:
---
type: FAS
fas_user: xyzuser
---
type: plaintext
pub_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDj5HauAOur/6+...
---
type: online
url: https://github.com/praiskup.keys
We don't have to implement all the options in the web-UI right now, nor in cli.
But we can be "prepared".
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 sounds reasonable, not done yet.
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 thought about this and it is probably not needed now. We IMHO still want one big textarea for user input and then parse the different (types of) keys somewhere in our code. Personally, I would do the parsing on backend (we have workers there) or even on builder. Because we can fetch the keys from FAS or URL right after that.
Right now only plaintext and one key is supported, so the value could only be
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDj5HauAOur/6+.
Seeing some other comments in the PR, we will probably implement support for multiple keys in this PR, so newline would be separator, e.g.
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDj5HauAOur/6+.
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDj5HauAOur/6+.
Once we start to support other methods, the input could be
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDj5HauAOur/6+.
FAS:xyzuser
https://github.com/praiskup.keys
GitHub:frostyx
We can always save the blob to the database as is and parse it when needed. That would be consistent with how e.g. copr://
external repositories work.
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.
Right now only plaintext and one key is supported
Huh, I've successfully tested before with multiple keys :-)
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 IMHO still want one big textarea for user input and then parse the different (types of) keys somewhere in our code.
I'd prefer to have a separate text area in the future, rather than changing the field and start "guessing" the type of input.
My thought was to start doing it right away in the background -- aka giving the user a simple textarea for multi-line key-only input, converting it to the yaml thing in the background, and store into DB. This way we would have open doors for later enhancements without touching the old entries. But I agree that this is rather a nice to have thing, there are many such things.
This is a very exciting change. Thank you for the progress! |
Can we have the per/user (maybe per arch) limit? I dont remember whether we decided to not implement it.. |
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.
Thank you very much for the review. I updated almost everything but the PR is still WIP.
@@ -862,6 +865,8 @@ def add(cls, user, pkgs, copr, source_type=None, source_json=None, | |||
copr_dir=copr_dir, | |||
bootstrap=bootstrap, | |||
isolation=isolation, | |||
allow_user_ssh=allow_user_ssh, | |||
ssh_public_key=ssh_public_key, |
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 sounds reasonable, not done yet.
7a4cd5d
to
7f0b348
Compare
87e8c7e
to
9fa616e
Compare
Thank you very much for the review @praiskup,
I spent a couple of hours on this before Christmas and wasn't able to set up MOTD on the builders. And then @xsuchy suggested it might be a good idea not having MOTD because of cases like |
But MOTD shouldn't affect stdout:
|
jakub to ping pavel and take a look at motd problems.. |
@@ -307,6 +318,9 @@ def _parse_results(self): | |||
""" | |||
Parse `results.json` and update the `self.job` object. | |||
""" | |||
if self.job.ssh_public_keys: |
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 implication here deserves an inline comment :-)
@@ -683,6 +704,9 @@ def _collect_built_packages(self, job): | |||
""" | |||
self.log.info("Listing built binary packages in %s", job.results_dir) | |||
|
|||
if self.job.ssh_public_keys: | |||
return "Public SSH access was enabled, no results were stored" |
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.
Isn't it safer to return empty dict here?
"{}/".format(dest), | ||
"&>", log_filepath, | ||
]) | ||
command = " ".join(command) |
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.
Nice!
backend/copr_backend/rpm_builds.py
Outdated
if not x._task.get("ssh_public_keys"): | ||
return None | ||
return x.owner | ||
super().__init__(predicate, limit, name="userssh") |
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.
s/predicate/hasher/?
backend/copr_backend/rpm_builds.py
Outdated
""" | ||
Limit the number of builders that allow user SSH | ||
""" | ||
def __init__(self, _hasher, limit): |
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.
You can drop the unused hasher argument I think.
<input type="hidden" name="allow_user_ssh" value="{{ allow_user_ssh }}"> | ||
{{ render_field(form.ssh_public_keys, label='Public SSH keys', | ||
placeholder='Newline separated public SSH keys, e.g. ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDR+QU9...', | ||
rows=8, cols=50) }} |
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 seems damn awesome! :-) Can't wait for testing it.
1bf44bb
to
153d521
Compare
I'm a bit uncertain about the windows-like EOLs, in vim I see:
|
I tried to drop |
@@ -51,6 +58,9 @@ | |||
|
|||
COMMANDS = { | |||
"rpm_q_builder": "rpm -q copr-rpmbuild --qf \"%{VERSION}\n\"", | |||
"echo_authorized_keys": "echo {0} >> /root/.ssh/authorized_keys", | |||
"set_expiration": "echo -n {0} > " + USER_SSH_EXPIRATION_PATH, | |||
"cat_expiration": "cat {0}".format(USER_SSH_EXPIRATION_PATH), |
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 think we should document here that we must be especially careful about error handling; users may replace the echo
or cat
commands, and (in theory) cause damage to the backend machine. This deserves documenting IMO (here ore in a later PR).
if self.job.ssh_public_keys: | ||
self.log.info("Builder allowed user SSH, not downloading the " | ||
"results for safety reasons.") | ||
filter_ = ["+ success", "+ *.spec", "- *"] |
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'm thinking ... what if user replaces the remote side (server) rsync
binary. Can that trick the backend to download some unwanted stuff?
Ideas?
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 quite dangerous. Should we maybe verify some checksum of the binary, or something like that? Same for the cat
commands mentioned above? But maybe that leads to the same issue (i.e. we can't be sure that the checksum tool wasn't tampered with)?
Just a few comments above, otherwise it seems OK to squash and merge. The motd and other things can be done later. |
Do you want the instructions in the "SSH access to the builder" section to be indented to the right?
Hmm, I haven't encountered this. Where do you see the ^M characters? |
""" | ||
Find the user preference for the builder expiration. | ||
""" | ||
rc, out, _err = self.root_ssh.run_expensive(COMMANDS["cat_expiration"]) |
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.
Don't use run_expensive
and check output length and/or timeout.
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 couldn't use run
because it doesn't return the output. So I kept run_expensive
and added a timeout for it.
7d1741a
to
c5d0ca5
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.
Thank you!
Implementation of fedora-copr/debate#6
Fixes: #2364