-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Automatically download and run migrations if needed #2939
Conversation
"strings" | ||
) | ||
|
||
var DistPath = "https://ipfs.io/ipns/dist.ipfs.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.
let's make this overridable -- will also make it much much easier to test-drive this
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, as we can then deploy to just fs:/ipfs/.
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.
preference on an env var name?
Why not just build the migration functionality into IPFS and run it on start if needed? Downloading and running arbitrary code like this makes auditing IPFS impossible and is generally considered a big no-no from a security perspective. |
Certifying the migration code the same way we certify go-ipfs code is enough. Meaning:
It's not "arbitrary code", it's "code from the developers", which if you don't trust, then you probably shouldn't be running go-ipfs anyway. If we really wanted to, we could version lock (with a hash) directly from There are many reasons NOT to embed that code in go-ipfs:
|
No, it's whatever happens to be at https://ipfs.io/ipns/dist.ipfs.io when the migrations run. I generally trust the IPFS developers to not be actively malicious but I don't expect them to be perfect and never lose control of a code signing key. Also, as implemented here, all an attacker needs a cert for ipfs.io and the ability to MITM the client (no developer involvement whatsoever).
This is absolutely necessary. While a unfortunate (it kills disconnected upgrades), it's still (mostly) fixes the security issue. Would these migrations really be that big? Usually, they're pretty tiny (on the order of kilobytes).
Until someone steels your keys. Basically, this all comes down to (1) ensuring that everyone gets the same code and (2) minimizing the attack surface.
|
The |
A lot of that is the go runtime and shared dependencies. For example, if I remove the latest migration (3-4), it's 9.9MiB. However, some of the other migrations appear to be bigger (on the order of a megabyte) so I agree that building this into IPFS may not be the best way to do this (basically, IPFS would never be able to drop any dependencies needed to read old datastore formats). |
@Stebalien it prompts you before doing anything. If you want to download and verify everything yourself you still can. This just makes it easier on the 99% of users who are okay with auto updates |
} | ||
|
||
return RunMigration(tovers) | ||
} |
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.
Sorry for creeping up on you with this feedback one day before the planned release :( :)
This should be part of the daemon command. With previous migrations, the daemon would abort with a non-zero exit code, now it'll just hang waiting for input. It'll be useful to have a -migrate=true|false
option which assumes yes/no and omits the prompt. (Actually it's really important for server environments.)
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.
Agreed! 👍
I agree that version locking with a hash is good. Any hijacking of the ipfs.io CNAME DNS record will make the update vulnerable. This doesn't even require SSL MitM since we're not talking about A/AAAA records. |
Good point. That with code signing is probably good enough for most cases. Unfortunately, it doesn't cover the unattended upgrade use case (e.g., running IPFS as a daemon on a NAS/server) but distros could probably include a subset of the migrations in their packages and run them in a post-upgrade script. As a matter of fact, they'll probably do this regardless. However, I don't really see a reason to not just hash the migration code and embed the hash in IPFS -- checking a hash is much easier than code signing. Yes this means you can't fix bugs in the migration code after the fact without also releasing a new version of IPFS. However, this would only be an issue if you expected the migration code to be significantly buggier than IPFS itself. |
Thats the reason i'm not as comfortable hard coding a hash. If that ends up happening (even though i'm fairly confident it wont) then the only reasonable response (from my end) is to re-release the same version with a new hard-coded migrations hash. Otherwise we end up with a 'bad' version that users would still be able to download and fail with in the future. |
Nevermind, this is actually only an issue if you use a local IPFS daemon. |
At the end of the day, this is solving a different concern. Think of it this way: By default, X would be bundled with Y as it is logically a part of Y. However, X is being extracted into a separate binary to be downloaded on-demand because... Case 1: ...it would make Y significantly larger and isn't needed for normal operation. Only case 3 motivates using code signing over including a hash but only case 1 is applicable here. Now, you could argue that, because we're doing this anyways, why not tackle two birds with one stone. However, I feel that a bug in the migration code is actually significantly less likely than a bug in the rest of IPFS so the chances of there being a reason to release a new migration tool and there existing no reason to release a new version of IPFS is vanishingly small. Basically, doing this would be sacrificing some security and simplicity (again, code signing is non-trivial) for negligible gain. |
@Stebalien want to try running the migrations to help test it for me? If i have more people tell me it works well then i'll be more inclined to hard code a hash in |
I have. I'm running ad5730d. |
okay cool, everything went smoothly i take it? |
I haven't noticed any problems so far. I just tried extracting an Arch Linux ISO (large file) I put into IPFS before the migration and got the correct result (md5 was correct) so it appears to be working. |
650a0eb
to
88a72d8
Compare
@@ -16,6 +16,12 @@ import ( | |||
|
|||
var DistPath = "https://ipfs.io/ipns/dist.ipfs.io" | |||
|
|||
func init() { | |||
if dist := os.Getenv("IPFS_DIST_PATH"); dist != "" { |
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 this should be a variable, not an env var. env vars are really pernicious as is. but added here that this control the distribution updates, rough!
the issue with env vars and why they're really bad for security is that it can turn secure scripts and commands into something unexpected by running before. meaning, in something like this:
> ./something
...
> /secure/bin/ipfs daemon --yes-run-migrations
something
may not have been secured to not download anything, doesnt have permissions to change binaries or anything, but it can change an env var. it adds attach surface area in ways an option does not.
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.
though i think this is irrelevant if the hashes are hard coded.
Thanks everyone for this awesome discussion. Very happy with the careful thought expressed here! Couple of points, some already mentioned above:
|
@whyrusleeping give me a set of commands to try |
@jbenet just install this version and make sure your repo is an older v3 version. Then run |
88a72d8
to
5a66520
Compare
I have a commit to add to this: bc6d71f It detects whether the running go-ipfs binary is linked against musl libc, and sets the OS to |
Okay, rebased this branch on top of a recent-ish master, added my OS detection commit, amended to not spawn a shell. |
BTW, here's how I've been testing this, with |
4f82eb7
to
fd732d2
Compare
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
License: MIT Signed-off-by: Lars Gierth <larsg@systemli.org>
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
@@ -15,7 +15,7 @@ import ( | |||
"strings" | |||
) | |||
|
|||
var DistPath = "https://ipfs.io/ipns/dist.ipfs.io" | |||
var DistPath = "https://ipfs.io/ipfs/QmUnvqDuRyfe7HJuiMMHv77AMUFnjGyAU28LFPeTYwGmFF" |
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.
👍
7914ee9
to
fcc4f00
Compare
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
Feedback from @jbenet about the prompt and userspace: would be good to prompt only when there's a TTY, and otherwise assume --migrate=false. Otherwise SGTHim |
Where does it verify the hash or is that not happening (yet)? |
Gonna test this with ipfs-ctl too tomorrow |
|
Chooo Chooo! |
"strings" | ||
) | ||
|
||
var DistPath = "https://ipfs.io/ipfs/QmUnvqDuRyfe7HJuiMMHv77AMUFnjGyAU28LFPeTYwGmFF" |
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.
doesn't this need a migration usable by 0.4.3(-*)?
? i dont think this has the last migration needed
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 has fs-repo-migrations-1.1.0 which includes the 3-to-4 migration: https://github.com/ipfs/fs-repo-migrations/tree/v1.1.0
This will prompt the user when a migration is needed to let ipfs try to automatically download and run the migrations.
If a version of the migrations tool is installed that is high enough, ipfs will use it instead of downloading its own.
Currently, the download its own function will fail as there is not a build of fs-repo-migrations with ipfs-3-to-4 up on the distributions page yet.
Resolves: #2907
License: MIT
Signed-off-by: Jeromy why@ipfs.io