-
Notifications
You must be signed in to change notification settings - Fork 92
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
Rewrite coreos-installer in Rust #65
Conversation
It would be useful to turn on travis on this repo, before merging this PR. I don't seem to have the powers to do that myself though. |
Thanks for the review! Updated, and Travis is enabled. Also, as we discussed OOB, I've moved the functionality to an |
An additional wishlist item that came to my mind: it would be great if we could run the installer from a container, just with the bindmounts for the target (rationale: that would allow us to use any linux-host as a provisioner). |
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.
Very nice overall! I like the 1M delayed write trick.
@@ -0,0 +1,91 @@ | |||
-----BEGIN PGP PUBLIC KEY BLOCK----- |
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.
Hmm, why not just pick up the keys from fedora-gpg-keys
/redhat-release-coreos
(i.e. /etc/pki/rpm-gpg
) ?
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.
coreos-installer should run on arbitrary distros, which may not have those files.
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.
OK so the idea here is that we'll publish binaries instead of/in addition to containers? What I'm trying to avoid is adding yet another spot that needs updating during each major release rollover. Can we pull it in as part of the build process at least?
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.
It may make sense to overlay-merge (by filename?) two sets of keys:
- these hardcoded ones (for fallback)
- any on-disk ones (possibly fresher)
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.
OK so the idea here is that we'll publish binaries instead of/in addition to containers?
It was, but if the container works and the UX for running it isn't too bad, I'd favor shipping that instead of a binary.
any on-disk ones (possibly fresher)
Where would we get these? If from /etc/pki/rpm-gpg
, there are no symbolic references for the current key, so we'd have to either import everything we find there (boo) or have a heuristic for importing keys (boo).
If we do ship a bare binary, this would also mean that behavior would differ depending on the host OS, which doesn't seem great.
What I'm trying to avoid is adding yet another spot that needs updating during each major release rollover. Can we pull it in as part of the build process at least?
These are the roots of trust for install images, and IMO it's safer to manage them manually. We can always start that way and add dynamic roots or more automation later on.
In comparison, CL coreos-install
intentionally hardcodes the GPG key and does not provide a command-line mechanism for overriding 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.
So as an example right now we don't have any CI covering the coreos-installer
path. So bumping from f30 to f31 without bumping the keys here would've possibly gone completely unnoticed until it shipped to users. (A gap we should fix of course!)
Where would we get these? If from /etc/pki/rpm-gpg, there are no symbolic references for the current key, so we'd have to either import everything we find there (boo) or have a heuristic for importing keys (boo).
These are the roots of trust for install images, and IMO it's safer to manage them manually. We can always start that way and add dynamic roots or more automation later on.
A big part of this discussion is essentially a direct consequence of coreos/fedora-coreos-tracker#187 (comment). WDYT about:
- ship in a container with
fedora-gpg-keys
- parse the FCOS version to extract the major release, similar to what is proposed for RoboSignatory itself in that ticket
- verify download using only that release's specific key from
/etc/pki/rpm-gpg
?
This is similar to how Fedora verifies RPMs: https://src.fedoraproject.org/rpms/fedora-repos/blob/a12c809ab2dcb730cbeb4a03c50d20e3d25cc048/f/fedora.repo#_10.
For RHEL, the keys don't rotate nearly as much, so we can just bake it in.
Anyway, I'm cool with how things set up for now, and discussing this stuff in more details later on!
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.
So as an example right now we don't have any CI covering the coreos-installer path. So bumping from f30 to f31 without bumping the keys here would've possibly gone completely unnoticed until it shipped to users. (A gap we should fix of course!)
If nothing else, that'll be addressed when we start running kola on Packet, where every machine will bootstrap with coreos-installer.
ship in a container with fedora-gpg-keys
I'd still prefer not to rely on external keys. It'd be great if cargo install coreos-installer
worked properly on e.g. Debian.
parse the FCOS version to extract the major release, similar to what is proposed for RoboSignatory itself in that ticket
verify download using only that release's specific key from /etc/pki/rpm-gpg
I like the idea of binding to a specific key. Will file an issue.
Hmm, maybe stream metadata should list a signing key ID for each artifact?
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, I guess the key ID is already embedded in the signature, so listing it separately in metadata is probably redundant.
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.
src/main.rs
Outdated
extern crate progress_streams; | ||
extern crate reqwest; | ||
extern crate tempdir; | ||
extern crate xz2; |
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 need these with Rust 2018.
|
||
// do the copy | ||
config_dest.push("config.ign"); | ||
let mut config_in = OpenOptions::new() |
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 just std::fs::copy
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.
We get a bit better control this way:
config_out.create_new(true)
ensures that we'll fail if the file already exists for some reason. (Which it shouldn't, of course.)std::fs::copy
also copies permissions, which may not be desired.
// Rewrite the config. Assume that we will only install | ||
// from metal images and that their bootloader configs will | ||
// always set ignition.platform.id. Fail if those | ||
// assumptions change. This is deliberately simplistic. |
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 fine, though should probably no-op return early on if platform
is metal
.
I haven't tried it, but I like the idea. I was originally thinking we'd offer a binary for download, but it does have dynamic library dependencies so that may not work well on other distros:
A container image would sidestep the whole problem. I probably won't pursue it immediately, but filed issue #67. |
Updated! |
We could (in theory) cross-compile to a static binary with musl, but in practice if it works I'd prefer pursuing the container route. |
insecure: bool, | ||
} | ||
|
||
quick_main!(run); |
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.
Is this still needed? main can return a result now.
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.
quick_main
still does better pretty-printing than the default main
.
src/verify.rs
Outdated
|
||
use error_chain::bail; | ||
use std::fs::{metadata, set_permissions, OpenOptions}; | ||
use std::io; |
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 can be combined below:
use std::io{self, Read, Write};
let uname = nix::sys::utsname::uname(); | ||
// Args are listed in --help in the order declared here. Please keep | ||
// the entire help text to 80 columns. | ||
let app_matches = App::new("coreos-installer") |
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 an alternative to using Clap directly, StructOpt is pretty slick.
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! I played with it a bit and don't think it's worth a refactor right now, but I'll keep it in mind for the future.
Features: - Checks that target disk is not in use - Obtains image from local file, remote URL, or stream metadata - Streaming fetch and decompression - Compression format sniffing - Progress reporting - GPG signature verification, mandatory unless --insecure specified - Does not write partition table until signature is verified - Can copy Ignition config to disk - Can override Ignition platform ID - Can write first-boot kernel arguments - Doesn't depend on uniqueness of /boot UUID - Wipes destination partition table on error - Only executable dependencies: gpg, lsblk, udevadm Command-line parameters are not compatible with the original, but the intent is that the coreos.inst.* kargs, to be implemented in a separate wrapper script, will maintain compatibility.
Also relicense coreos-iso-embed-ignition.
Would be pretty cool to have the CI here actually do an install of FCOS. I think Travis CI can give you Ubuntu VMs, though we can also hook it up to CoreOS CI! Now that we've branched, I'm thinking let's just merge this, cut a 0.0.1 release, and iterate on top as we uncover issues? |
Yup, we have a |
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.
LGTM from my side
Features:
--insecure
specified/boot
UUIDgpg
,lsblk
,udevadm
Command-line parameters are not compatible with the original, but the intent is that the
coreos.inst.*
kargs, to be implemented in a separate wrapper script, will maintain compatibility.