Skip to content
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 resolve Docker images to immutable digests #1104

Merged
merged 4 commits into from
Sep 12, 2017
Merged

Conversation

ejholmes
Copy link
Contributor

@ejholmes ejholmes commented Sep 2, 2017

Closes #247

With this change, when you deploy an image using a mutable tag (e.g. emp deploy remind101/acme-inc:latest), Empire will resolve the image reference to an immutable reference (e.g. remind101/acme-inc@sha256:c6f77d2098bc0e32aef3102e71b51831a9083dd9356a0ccadca860596a1e9007) before saving the slug. This has a number of benefits, both for security and for stability.

This was always the intention, but couldn't be done until ECS supported digests (which it now does).

In this PR, the first commit is a small refactor to change the ProcfileExtractor interface to an ImageRegistry interface. And then the second commit is a small change that implements digest resolution.

@@ -207,72 +204,6 @@ func TestEmpire_Deploy_ImageNotFound(t *testing.T) {
s.AssertExpectations(t)
}

func TestEmpire_Deploy_Concurrent(t *testing.T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm removing this test, mainly because it's been buggy and fails randomly (pretty sure it's the test itself, and not what it's actually testing). I'll try to follow up in the future with a better version of this test.

}

if len(i.RepoDigests) <= 0 {
return img, &DigestError{Image: img.String()}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out RepoDigests is only populated from a docker pull in Docker 1.12+. This thread moby/moby#15508 explains the details of that.

We've been locked to 1.11.x for some time now, just for stability, but should probably consider upgrading to a later version.

Instead of returning an error here, this could just fallback to the existing behavior instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just wondering about this - yeah, seems like falling back to existing behavior - or possibly having it be able to configure that you require digests - would be good.

Copy link
Contributor

@phobologic phobologic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small comment, but looks good.

}

if len(i.RepoDigests) <= 0 {
return img, &DigestError{Image: img.String()}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just wondering about this - yeah, seems like falling back to existing behavior - or possibly having it be able to configure that you require digests - would be good.

@phobologic
Copy link
Contributor

Also could use some docs/etc.

The name type is responsible for interacting with images, like
extracting Procfiles and resolving them to immutable identifiers.
This automatically resolves Docker images to an immutable identifier
before saving the slug. This has numerous benefits:

1. For security, it prevents docker registry attack vectors (MiTM,
credential exposure).
2. For reliability, it prevents issues from someone accidentally
overwriting a tag.
@ejholmes
Copy link
Contributor Author

ejholmes commented Sep 7, 2017

Ok, pretty happy with this now. It now falls back to the older behavior if no digests are available, and prints info in the deployment stream. If the underlying Docker Daemon supports digests, you'll see:

$ emp deploy remind101/acme-inc:master
...
Status: Image is up to date for remind101/acme-inc:master
Status: Resolved remind101/acme-inc:master to remind101/acme-inc@sha256:c6f77d2098bc0e32aef3102e71b51831a9083dd9356a0ccadca860596a1e9007

If there are no digests:

$ emp deploy remind101/acme-inc:master
...
Status: Image is up to date for remind101/acme-inc:master
Status: Image has no repository digests. Using remind101/acme-inc:master as image identifier

Also updated the relevant docs, and made procfile extraction use the resolved identifier.

@phobologic
Copy link
Contributor

Should there be a way to configure Empire so it only accepts images with a digest? Not sure what the implications are in the fall back mode, or if it exposes us to any potential security vulnerabilities.

@ejholmes
Copy link
Contributor Author

ejholmes commented Sep 7, 2017

Should there be a way to configure Empire so it only accepts images with a digest

That'd probably be good. I agree the fallback mode is a little fishy, since it could potentially be used as an attack vector.

For the fallback, I think either a flag to enforce digests, or change the logic to use the Docker API version (or a combination of the both).

Previously, if a digest was provided, it wouldn't be passed down to
PullImage, which would end up pulling all images (the behavior of the
Docker daemon).
This adds a new --docker.digests flag (DOCKER_DIGESTS env var) that
allows the behavior of image resolution to be controlled. The default is
to use a digest if available, but can be changed to enforce digests
(error out if the image has no immutable digest), or disabled to get the
same behavior as before (no digest resolution).
@ejholmes
Copy link
Contributor Author

ejholmes commented Sep 8, 2017

Alrighty, updated this with a --docker.digests flag (DOCKER_DIGESTS env var) to control the behavior. Default is to "prefer" digests if the image has one, but can be changed to a more secure "enforce", or disabled entirely with "disable".

I'll run this in our staging env for a couple days and merge if no issues come up.

@ejholmes
Copy link
Contributor Author

This is working well in staging. Gonna merge.

@ejholmes ejholmes merged commit 7867007 into master Sep 12, 2017
@ejholmes ejholmes deleted the digests branch September 12, 2017 03:01
@ejholmes ejholmes mentioned this pull request Sep 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Move to immutable identifiers
2 participants