podman

Форк
0
220 строк · 7.6 Кб
1
package buildah
2

3
import (
4
	"context"
5
	"fmt"
6
	"io"
7
	"time"
8

9
	"github.com/containers/buildah/define"
10
	"github.com/containers/buildah/internal/mkcw"
11
	"github.com/containers/image/v5/docker/reference"
12
	"github.com/containers/image/v5/types"
13
	encconfig "github.com/containers/ocicrypt/config"
14
	"github.com/containers/storage"
15
	"github.com/containers/storage/pkg/archive"
16
	"github.com/opencontainers/go-digest"
17
	"github.com/sirupsen/logrus"
18
)
19

20
// CWConvertImageOptions provides both required and optional bits of
21
// configuration for CWConvertImage().
22
type CWConvertImageOptions struct {
23
	// Required parameters.
24
	InputImage string
25

26
	// If supplied, we'll tag the resulting image with the specified name.
27
	Tag         string
28
	OutputImage types.ImageReference
29

30
	// If supplied, we'll register the workload with this server.
31
	// Practically necessary if DiskEncryptionPassphrase is not set, in
32
	// which case we'll generate one and throw it away after.
33
	AttestationURL string
34

35
	// Used to measure the environment.  If left unset (0), defaults will be applied.
36
	CPUs   int
37
	Memory int
38

39
	// Can be manually set.  If left unset ("", false, nil), reasonable values will be used.
40
	TeeType                  define.TeeType
41
	IgnoreAttestationErrors  bool
42
	WorkloadID               string
43
	DiskEncryptionPassphrase string
44
	Slop                     string
45
	FirmwareLibrary          string
46
	BaseImage                string
47
	Logger                   *logrus.Logger
48
	ExtraImageContent        map[string]string
49

50
	// Passed through to BuilderOptions. Most settings won't make
51
	// sense to be made available here because we don't launch a process.
52
	ContainerSuffix     string
53
	PullPolicy          PullPolicy
54
	BlobDirectory       string
55
	SignaturePolicyPath string
56
	ReportWriter        io.Writer
57
	IDMappingOptions    *IDMappingOptions
58
	Format              string
59
	MaxPullRetries      int
60
	PullRetryDelay      time.Duration
61
	OciDecryptConfig    *encconfig.DecryptConfig
62
	MountLabel          string
63
}
64

65
// CWConvertImage takes the rootfs and configuration from one image, generates a
66
// LUKS-encrypted disk image that more or less includes them both, and puts the
67
// result into a new container image.
68
// Returns the new image's ID and digest on success, along with a canonical
69
// reference for it if a repository name was specified.
70
func CWConvertImage(ctx context.Context, systemContext *types.SystemContext, store storage.Store, options CWConvertImageOptions) (string, reference.Canonical, digest.Digest, error) {
71
	// Apply our defaults if some options aren't set.
72
	logger := options.Logger
73
	if logger == nil {
74
		logger = logrus.StandardLogger()
75
	}
76

77
	// Now create the target working container, pulling the base image if
78
	// there is one and it isn't present.
79
	builderOptions := BuilderOptions{
80
		FromImage:     options.BaseImage,
81
		SystemContext: systemContext,
82
		Logger:        logger,
83

84
		ContainerSuffix:     options.ContainerSuffix,
85
		PullPolicy:          options.PullPolicy,
86
		BlobDirectory:       options.BlobDirectory,
87
		SignaturePolicyPath: options.SignaturePolicyPath,
88
		ReportWriter:        options.ReportWriter,
89
		IDMappingOptions:    options.IDMappingOptions,
90
		Format:              options.Format,
91
		MaxPullRetries:      options.MaxPullRetries,
92
		PullRetryDelay:      options.PullRetryDelay,
93
		OciDecryptConfig:    options.OciDecryptConfig,
94
		MountLabel:          options.MountLabel,
95
	}
96
	target, err := NewBuilder(ctx, store, builderOptions)
97
	if err != nil {
98
		return "", nil, "", fmt.Errorf("creating container from target image: %w", err)
99
	}
100
	defer func() {
101
		if err := target.Delete(); err != nil {
102
			logrus.Warnf("deleting target container: %v", err)
103
		}
104
	}()
105
	targetDir, err := target.Mount("")
106
	if err != nil {
107
		return "", nil, "", fmt.Errorf("mounting target container: %w", err)
108
	}
109
	defer func() {
110
		if err := target.Unmount(); err != nil {
111
			logrus.Warnf("unmounting target container: %v", err)
112
		}
113
	}()
114

115
	// Mount the source image, pulling it first if necessary.
116
	builderOptions = BuilderOptions{
117
		FromImage:     options.InputImage,
118
		SystemContext: systemContext,
119
		Logger:        logger,
120

121
		ContainerSuffix:     options.ContainerSuffix,
122
		PullPolicy:          options.PullPolicy,
123
		BlobDirectory:       options.BlobDirectory,
124
		SignaturePolicyPath: options.SignaturePolicyPath,
125
		ReportWriter:        options.ReportWriter,
126
		IDMappingOptions:    options.IDMappingOptions,
127
		Format:              options.Format,
128
		MaxPullRetries:      options.MaxPullRetries,
129
		PullRetryDelay:      options.PullRetryDelay,
130
		OciDecryptConfig:    options.OciDecryptConfig,
131
		MountLabel:          options.MountLabel,
132
	}
133
	source, err := NewBuilder(ctx, store, builderOptions)
134
	if err != nil {
135
		return "", nil, "", fmt.Errorf("creating container from source image: %w", err)
136
	}
137
	defer func() {
138
		if err := source.Delete(); err != nil {
139
			logrus.Warnf("deleting source container: %v", err)
140
		}
141
	}()
142
	sourceInfo := GetBuildInfo(source)
143
	if err != nil {
144
		return "", nil, "", fmt.Errorf("retrieving info about source image: %w", err)
145
	}
146
	sourceImageID := sourceInfo.FromImageID
147
	sourceSize, err := store.ImageSize(sourceImageID)
148
	if err != nil {
149
		return "", nil, "", fmt.Errorf("computing size of source image: %w", err)
150
	}
151
	sourceDir, err := source.Mount("")
152
	if err != nil {
153
		return "", nil, "", fmt.Errorf("mounting source container: %w", err)
154
	}
155
	defer func() {
156
		if err := source.Unmount(); err != nil {
157
			logrus.Warnf("unmounting source container: %v", err)
158
		}
159
	}()
160

161
	// Generate the image contents.
162
	archiveOptions := mkcw.ArchiveOptions{
163
		AttestationURL:           options.AttestationURL,
164
		CPUs:                     options.CPUs,
165
		Memory:                   options.Memory,
166
		TempDir:                  targetDir,
167
		TeeType:                  options.TeeType,
168
		IgnoreAttestationErrors:  options.IgnoreAttestationErrors,
169
		ImageSize:                sourceSize,
170
		WorkloadID:               options.WorkloadID,
171
		DiskEncryptionPassphrase: options.DiskEncryptionPassphrase,
172
		Slop:                     options.Slop,
173
		FirmwareLibrary:          options.FirmwareLibrary,
174
		Logger:                   logger,
175
		GraphOptions:             store.GraphOptions(),
176
		ExtraImageContent:        options.ExtraImageContent,
177
	}
178
	rc, workloadConfig, err := mkcw.Archive(sourceDir, &source.OCIv1, archiveOptions)
179
	if err != nil {
180
		return "", nil, "", fmt.Errorf("generating encrypted image content: %w", err)
181
	}
182
	if err = archive.Untar(rc, targetDir, &archive.TarOptions{}); err != nil {
183
		if err = rc.Close(); err != nil {
184
			logger.Warnf("cleaning up: %v", err)
185
		}
186
		return "", nil, "", fmt.Errorf("saving encrypted image content: %w", err)
187
	}
188
	if err = rc.Close(); err != nil {
189
		return "", nil, "", fmt.Errorf("cleaning up: %w", err)
190
	}
191

192
	// Commit the image.  Clear out most of the configuration (if there is any — we default
193
	// to scratch as a base) so that an engine that doesn't or can't set up a TEE will just
194
	// run the static entrypoint.  The rest of the configuration which the runtime consults
195
	// is in the .krun_config.json file in the encrypted filesystem.
196
	logger.Log(logrus.DebugLevel, "committing disk image")
197
	target.ClearAnnotations()
198
	target.ClearEnv()
199
	target.ClearLabels()
200
	target.ClearOnBuild()
201
	target.ClearPorts()
202
	target.ClearVolumes()
203
	target.SetCmd(nil)
204
	target.SetCreatedBy(fmt.Sprintf(": convert %q for use with %q", sourceImageID, workloadConfig.Type))
205
	target.SetDomainname("")
206
	target.SetEntrypoint([]string{"/entrypoint"})
207
	target.SetHealthcheck(nil)
208
	target.SetHostname("")
209
	target.SetMaintainer("")
210
	target.SetShell(nil)
211
	target.SetUser("")
212
	target.SetWorkDir("")
213
	commitOptions := CommitOptions{
214
		SystemContext: systemContext,
215
	}
216
	if options.Tag != "" {
217
		commitOptions.AdditionalTags = append(commitOptions.AdditionalTags, options.Tag)
218
	}
219
	return target.Commit(ctx, options.OutputImage, commitOptions)
220
}
221

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.