8000 stage0/{run,prepare}: remove ondisk verification by euank · Pull Request #3623 · rkt/rkt · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Feb 24, 2020. It is now read-only.

stage0/{run,prepare}: remove ondisk verification #3623

Merged
merged 4 commits into from
Apr 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Documentation/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ In addition to the flags used by individual `rkt` commands, `rkt` has a set of g
| `--cpuprofile (hidden flag)` | '' | A file path | Write CPU profile to the file |
| `--debug` | `false` | `true` or `false` | Prints out more debug information to `stderr` |
| `--dir` | `/var/lib/rkt` | A directory path | Path to the `rkt` data directory |
| `--insecure-options` | none | **none**, **http**, **image**, **tls**, **ondisk**, **pubkey**, **capabilities**, **paths**, **seccomp**, **all-fetch**, **all-run**, **all** <br/> More information below. | Comma-separated list of security features to disable |
| `--insecure-options` | none | **none**, **http**, **image**, **tls**, **pubkey**, **capabilities**, **paths**, **seccomp**, **all-fetch**, **all-run**, **all** <br/> More information below. | Comma-separated list of security features to disable |
| `--local-config` | `/etc/rkt` | A directory path | Path to the local configuration directory |
| `--memprofile (hidden flag)` | '' | A file path | Write memory profile to the file |
| `--system-config` | `/usr/lib/rkt` | A directory path | Path to the system configuration directory |
Expand All @@ -83,13 +83,12 @@ In addition to the flags used by individual `rkt` commands, `rkt` has a set of g
- **http**: Allow HTTP connections. Be warned that this will send any credentials as clear text, allowing anybody with access to your network to obtain them. It will also perform no validation of the remote server, making it possible for an attacker to impersonate the remote server. This applies specifically to fetching images, signatures, and gpg pubkeys.
- **image**: Disables verifying image signatures. If someone is able to replace the image on the server with a modified one or is in a position to impersonate the server, they will be able to force you to run arbitrary code.
- **tls**: Accept any certificate from the server and any host name in that certificate. This will make it possible for attackers to spoof the remote server and provide malicious images.
- **ondisk**: Disables verifying the integrity of the on-disk, rendered image before running. This significantly speeds up start time. If an attacker is able to modify the contents of your local filesystem, this will allow them to cause you to run arbitrary malicious code.
- **pubkey**: Allow fetching pubkeys via insecure connections (via HTTP connections or from servers with unverified certificates). This slightly extends the meaning of the `--trust-keys-from-https` flag. This will make it possible for an attacker to spoof the remote server, potentially providing fake keys and allowing them to provide container images that have been tampered with.
- **capabilities**: Gives all [capabilities][capabilities] to apps. This allows an attacker that is able to execute code in the container to trivially escalate to root privileges on the host.
- **paths**: Disables inaccessible and read-only paths. This makes it easier for an attacker who can gain control over a single container to execute code in the host system, potentially allowing them to escape from the container. This also leaks additional information.
- **seccomp**: Disables [seccomp][seccomp]. This increases the attack surface available to an attacker who can gain control over a single container, potentially making it easier for them to escape from the container.
- **all-fetch**: Disables the following security checks: image, tls, http
- **all-run**: Disables the following security checks: ondisk, capabilities, paths, seccomp
- **all-run**: Disables the following security checks: capabilities, paths, seccomp
- **all**: Disables all security checks

## Logging
Expand Down
11 changes: 11 additions & 0 deletions Documentation/subcommands/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ rkt: successfully removed aci for image: "sha512-91e98d7f167905b69cce91b163963cc
rkt: 2 image(s) successfully removed
```

## rkt image verify

Given one or more image IDs or image names, verify will verify that their
ondisk checksum matches the value previously calculated on render.

```
# rkt image verify quay.io/coreos/etcd:v3.1.0 sha512-887890e697d9
successfully verified checksum for image: "quay.io/coreos/etcd:v3.1.0" ("sha512-e70ec975ce5327ea52c4a30cc4a951ecea55217a290e866e70888517964ba700")
successfully verified checksum for image: "sha512-887890e697d9" ("sha512-887890e697d9a0229eff22436def3c436cb4b18f72ac274c8c05427b39539307")
```

## Global options

See the table with [global options in general commands documentation][global-options].
Expand Down
15 changes: 7 additions & 8 deletions rkt/app_sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,13 @@ func runAppSandbox(cmd *cobra.Command, args []string) int {
useOverlay := !flagNoOverlay && ovlOk

pcfg := stage0.PrepareConfig{
CommonConfig: &cfg,
UseOverlay: useOverlay,
PrivateUsers: user.NewBlankUidRange(),
SkipTreeStoreCheck: globalFlags.InsecureFlags.SkipOnDiskCheck(),
Apps: &rktApps,
Ports: []types.ExposedPort(flagAppPorts),
UserAnnotations: parseAnnotations(&flagAnnotations),
UserLabels: parseLabels(&flagLabels),
CommonConfig: &cfg,
UseOverlay: useOverlay,
PrivateUsers: user.NewBlankUidRange(),
Apps: &rktApps,
Ports: []types.ExposedPort(flagAppPorts),
UserAnnotations: parseAnnotations(&flagAnnotations),
UserLabels: parseLabels(&flagLabels),
}

if globalFlags.Debug {
Expand Down
10 changes: 4 additions & 6 deletions rkt/flag/secflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ const (
insecureNone = 0
insecureImage = 1 << (iota - 1)
insecureTLS
insecureOnDisk
insecureOnDisk // ignored, left for backwards compatibility
insecureHTTP
insecurePubKey
insecureCapabilities
insecurePaths
insecureSeccomp

insecureAllFetch = (insecureImage | insecureTLS | insecureHTTP | insecurePubKey)
insecureAllRun = (insecureOnDisk | insecureCapabilities | insecurePaths | insecureSeccomp)
insecureAllRun = (insecureCapabilities | insecurePaths | insecureSeccomp)
insecureAll = (insecureAllFetch | insecureAllRun)
)

Expand Down Expand Up @@ -85,6 +85,8 @@ func NewSecFlags(defOpts string) (*SecFlags, error) {
if err != nil {
return nil, err
}
// Ignore ondisk
bf.Flags = bf.Flags &^ insecureOnDisk

sf := &SecFlags{
BitFlags: bf,
Expand All @@ -100,10 +102,6 @@ func (sf *SecFlags) SkipTLSCheck() bool {
return sf.HasFlag(insecureTLS)
}

func (sf *SecFlags) SkipOnDiskCheck() bool {
return sf.HasFlag(insecureOnDisk)
}

func (sf *SecFlags) AllowHTTP() bool {
return sf.HasFlag(insecureHTTP)
}
Expand Down
84 changes: 35 additions & 49 deletions rkt/flag/secflags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,66 +18,56 @@ import "testing"

func TestSecFlags(t *testing.T) {
tests := []struct {
opts string
image bool
tls bool
onDisk bool
http bool
err bool
opts string
image bool
tls bool
http bool
err bool
}{
{
opts: "none",
image: false,
tls: false,
onDisk: false,
http: false,
opts: "none",
image: false,
tls: false,
http: false,
},
{
opts: "image",
image: true,
tls: false,
onDisk: false,
http: false,
opts: "image",
image: true,
tls: false,
http: false,
},
{
opts: "tls",
image: false,
tls: true,
onDisk: false,
http: false,
opts: "tls",
image: false,
tls: true,
http: false,
},
{
opts: "onDisk",
image: false,
tls: false,
onDisk: true,
http: false,
opts: "http",
image: false,
tls: false,
http: true,
},
{
opts: "http",
image: false,
tls: false,
onDisk: false,
http: true,
opts: "all",
image: true,
tls: true,
http: true,
},
{
opts: "all",
image: true,
tls: true,
onDisk: true,
http: true,
},
{
opts: "image,tls",
image: true,
tls: true,
onDisk: false,
http: false,
opts: "image,tls",
image: true,
tls: true,
http: false,
},
{
opts: "i-am-sure-we-will-not-get-this-insecure-flag",
err: true,
},
{
opts: "ondisk",
err: false,
},
}

for i, tt := range tests {
Expand All @@ -99,20 +89,16 @@ func TestSecFlags(t *testing.T) {
t.Errorf("test %d: expected tls skip to be %v, got %v", i, tt.tls, got)
}

if got := sf.SkipOnDiskCheck(); tt.onDisk != got {
t.Errorf("test %d: expected on disk skip to be %v, got %v", i, tt.onDisk, got)
}

if got := sf.AllowHTTP(); tt.http != got {
t.Errorf("test %d: expected http allowed to be %v, got %v", i, tt.http, got)
}

all := tt.http && tt.onDisk && tt.tls && tt.image
all := tt.http && tt.tls && tt.image
if got := sf.SkipAllSecurityChecks(); all != got {
t.Errorf("test %d: expected all skip to be %v, got %v", i, all, got)
}

any := tt.http || tt.onDisk || tt.tls || tt.image
any := tt.http || tt.tls || tt.image
if got := sf.SkipAnySecurityChecks(); any != got {
t.Errorf("test %d: expected all skip to be %v, got %v", i, any, got)
}
Expand Down
101 changes: 101 additions & 0 deletions rkt/image_verify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright 2017 The rkt Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"os"

"github.com/hashicorp/errwrap"
"github.com/rkt/rkt/store/imagestore"
"github.com/rkt/rkt/store/treestore"
"github.com/spf13/cobra"
)

var (
cmdImageVerify = &cobra.Command{
Use: "verify IMAGE...",
Short: "Verify one or more rendered images in the local store",
Long: `Verify is able to check that, based on the stored hash value, a rendered image on disk has not changed.

This command may be used if the user suspects disk corruption might have damaged the rkt store.`,
Run: runWrapper(runVerifyImage),
}
)

func init() {
cmdImage.AddCommand(cmdImageVerify)
}

func runVerifyImage(cmd *cobra.Command, args []string) int {
if len(args) < 1 {
stderr.Print("must provide at least one image ID")
return 254
}

s, err := imagestore.NewStore(storeDir())
if err != nil {
stderr.PrintE("cannot open store", err)
return 254
}

ts, err := treestore.NewStore(treeStoreDir(), s)
if err != nil {
stderr.PrintE("cannot open treestore", err)
return 254
}

for _, img := range args {
key, err := getStoreKeyFromAppOrHash(s, img)
if err != nil {
stderr.Printf("unable to resolve store key for image %s: %v", img, err)
return 254
}
id, err := ts.GetID(key)
if err != nil {
stderr.Printf("unable to get treestoreID for image %s: %v", img, err)
return 254
}
_, err = ts.Check(id)
if isNotRenderedErr(err) {
stdout.Printf("image %q not rendered; no verification needed", img)
continue
}
if err != nil {
stdout.Printf("tree cache verification failed for image %s: %v; rebuilding...", img, err)
_, _, err = ts.Render(key, true)
if err != nil {
stderr.Printf("unable to repair cache for image %s: %v", img, err)
return 254
}
} else {
stdout.Printf("successfully verified checksum for image: %q (%q)", img, key)
}
}
return 0
}

func isNotRenderedErr(err error) bool {
containsIsNotExist := false
containsReadHashErr := false
errwrap.Walk(err, func(e error) {
if os.IsNotExist(e) {
containsIsNotExist = true
}
if e == treestore.ErrReadHashfile {
containsReadHashErr = true
}
})
return containsIsNotExist && containsReadHashErr
}
7 changes: 3 additions & 4 deletions rkt/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,9 @@ func runPrepare(cmd *cobra.Command, args []string) (exit int) {
}

pcfg := stage0.PrepareConfig{
CommonConfig: &cfg,
UseOverlay: !flagNoOverlay && ovlOk,
PrivateUsers: privateUsers,
SkipTreeStoreCheck: globalFlags.InsecureFlags.SkipOnDiskCheck(),
CommonConfig: &cfg,
UseOverlay: !flagNoOverlay && ovlOk,
PrivateUsers: privateUsers,
}

if len(flagPodManifest) > 0 {
Expand Down
7 changes: 3 additions & 4 deletions rkt/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,9 @@ func runRun(cmd *cobra.Command, args []string) (exit int) {
useOverlay := !flagNoOverlay && ovlOk

pcfg := stage0.PrepareConfig{
CommonConfig: &cfg,
UseOverlay: useOverlay,
PrivateUsers: privateUsers,
SkipTreeStoreCheck: globalFlags.InsecureFlags.SkipOnDiskCheck(),
CommonConfig: &cfg,
UseOverlay: useOverlay,
PrivateUsers: privateUsers,
}

if len(flagPodManifest) > 0 {
Expand Down
Loading
0